[Rpm-ecosystem] [PATCH v6 08/11] Add file signature support to package signing

Lubos Kardos lkardos at redhat.com
Thu Jul 16 14:47:17 UTC 2015


I can't build rpm after applying this patch without applying also following
patches:
rpmgensig.c:24:30: fatal error: lib/rpmsignfiles.h: No such file or directory
 #include "lib/rpmsignfiles.h"
                              

----- Original Message -----
> From: "Mimi Zohar" <zohar at linux.vnet.ibm.com>
> To: rpm-ecosystem at lists.rpm.org
> Cc: fin at linux.vnet.ibm.com, "Fionnuala Gunter" <fionnuala.gunter at gmail.com>
> Sent: Monday, July 6, 2015 8:52:22 PM
> Subject: [Rpm-ecosystem] [PATCH v6 08/11] Add file signature support to	package signing
> 
> From: "fin at linux.vnet.ibm.com" <fin at linux.vnet.ibm.com>
> 
> This patch modifies rpmSign to include file signatures in the header.
> Since the header is altered, the package digest and package+archive
> digest need to be recalculated and updated in the signature header.
> Defer resigning the header digests to replaceSignature().
> 
> Changelog:
> - removed extraneous semicolon - Mimi
> - Update signature header digests only if necessary - Mimi
> ---
>  sign/rpmgensig.c | 174
>  ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 171 insertions(+), 3 deletions(-)
> 
> diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
> index b660c60..97e245b 100644
> --- a/sign/rpmgensig.c
> +++ b/sign/rpmgensig.c
> @@ -17,9 +17,11 @@
>  #include <rpm/rpmfileutil.h>	/* rpmMkTemp() */
>  #include <rpm/rpmlog.h>
>  #include <rpm/rpmstring.h>
> +#include <rpmio/rpmio_internal.h>
>  
>  #include "lib/rpmlead.h"
>  #include "lib/signature.h"
> +#include "lib/rpmsignfiles.h"
>  
>  #include "debug.h"
>  
> @@ -503,13 +505,175 @@ static void unloadImmutableRegion(Header *hdrp,
> rpmTagVal tag, rpmtd utd)
>      }
>  }
>  
> +static rpmRC replaceSigDigests(FD_t fd, const char *rpm, Header *sigp,
> +			       off_t sigStart, off_t headerSize,
> +			       char *SHA1, uint8_t *MD5)
> +{
> +    off_t archiveSize;
> +    rpmRC rc = RPMRC_OK;
> +
> +    if (Fseek(fd, sigStart, SEEK_SET) < 0) {
> +	rc = RPMRC_FAIL;
> +	rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
> +		rpm, Fstrerror(fd));
> +	goto exit;
> +    }
> +
> +    /* Get payload size from signature tag */
> +    archiveSize = headerGetNumber(*sigp, RPMSIGTAG_PAYLOADSIZE);
> +    if (!archiveSize) {
> +	archiveSize = headerGetNumber(*sigp, RPMSIGTAG_LONGARCHIVESIZE);
> +    }
> +
> +    /* Replace old digests in sigh */
> +    rc = rpmGenerateSignature(SHA1, MD5, headerSize, archiveSize, fd);
The third argument is size of header + size of compressed payload and
not only size of header.

> +    if (rc != RPMRC_OK) {
> +	rpmlog(RPMLOG_ERR, _("generateSignature failed\n"));
> +	goto exit;
> +    }
> +
> +    if (Fseek(fd, sigStart, SEEK_SET) < 0) {
> +	rc = RPMRC_FAIL;
> +	rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
> +		rpm, Fstrerror(fd));
> +	goto exit;
> +    }
> +
> +    rc = rpmReadSignature(fd, sigp, RPMSIGTYPE_HEADERSIG, NULL);
Value which sigp points to is overridden without deallocation.

> +    if (rc != RPMRC_OK) {
> +	rpmlog(RPMLOG_ERR, _("rpmReadSignature failed\n"));
> +	goto exit;
> +    }
> +
> +exit:
> +    return rc;
> +}
> +
> +static rpmRC includeFileSignatures(FD_t fd, const char *rpm,
> +				   Header *sigp, Header *hdrp,
> +				   off_t sigStart, off_t headerStart)
> +{
> +    FD_t ofd = NULL;
> +    struct rpmtd_s td;
> +    char *trpm = NULL;
> +    const char *key;
> +    char *SHA1 = NULL;
> +    uint8_t *MD5 = NULL;
> +    unsigned char buf[32*BUFSIZ];
> +    size_t sha1len;
> +    size_t md5len;
> +    off_t headerSize;
> +    rpmRC rc = RPMRC_OK;
> +    struct rpmtd_s osigtd;
> +    char *o_sha1 = NULL;
> +    uint8_t o_md5[16];
> +
> +    unloadImmutableRegion(hdrp, RPMTAG_HEADERIMMUTABLE, &td);
> +
> +    key = rpmExpand("%{?_file_signing_key}", NULL);
> +
> +    rc = rpmSignFiles(*hdrp, key);
> +    if (rc != RPMRC_OK) {
> +	goto exit;
> +    }
> +
> +    *hdrp = headerReload(*hdrp, RPMTAG_HEADERIMMUTABLE);
> +    if (*hdrp == NULL) {
> +	rc = RPMRC_FAIL;
> +	rpmlog(RPMLOG_ERR, _("headerReload failed\n"));
> +	goto exit;
> +    }
> +
> +    ofd = rpmMkTempFile(NULL, &trpm);
> +    if (ofd == NULL || Ferror(ofd)) {
> +	rc = RPMRC_FAIL;
> +	rpmlog(RPMLOG_ERR, _("rpmMkTemp failed\n"));
> +	goto exit;
> +    }
> +
> +    /* Copy archive to temp file */
> +    if (copyFile(&fd, rpm, &ofd, trpm)) {
> +	rc = RPMRC_FAIL;
> +	rpmlog(RPMLOG_ERR, _("copyFile failed\n"));
> +	goto exit;
> +    }
> +
> +    if (Fseek(fd, headerStart, SEEK_SET) < 0) {
> +	rc = RPMRC_FAIL;
> +	rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
> +		rpm, Fstrerror(fd));
> +	goto exit;
> +    }
> +
> +    /* Write header to rpm and recalculate SHA1 */
> +    fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
> +    rc = headerWrite(fd, *hdrp, HEADER_MAGIC_YES);
> +    if (rc != RPMRC_OK) {
> +	rpmlog(RPMLOG_ERR, _("headerWrite failed\n"));
> +	goto exit;
> +    }
> +    fdFiniDigest(fd, PGPHASHALGO_SHA1, (void **)&SHA1, &sha1len, 1);
> +    headerSize = Ftell(fd) - headerStart;
> +
> +    /* Copy archive from temp file */
> +    if (Fseek(ofd, 0, SEEK_SET) < 0) {
> +	rc = RPMRC_FAIL;
> +	rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
> +		rpm, Fstrerror(fd));
> +	goto exit;
> +    }
> +    if (copyFile(&ofd, trpm, &fd, rpm)) {
> +	rc = RPMRC_FAIL;
> +	rpmlog(RPMLOG_ERR, _("copyFile failed\n"));
> +	goto exit;
> +    }
> +    unlink(trpm);
> +
> +    /* Recalculate MD5 digest of header+archive */
> +    if (Fseek(fd, headerStart, SEEK_SET) < 0) {
> +	rc = RPMRC_FAIL;
> +	rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"),
> +		rpm, Fstrerror(fd));
> +	goto exit;
> +    }
> +    fdInitDigest(fd, PGPHASHALGO_MD5, 0);
> +
> +    while (Fread(buf, sizeof(buf[0]), sizeof(buf), fd) > 0)
> +	;
> +    if (Ferror(fd)) {
> +	rc = RPMRC_FAIL;
> +	rpmlog(RPMLOG_ERR, _("Fread failed in file %s: %s\n"),
> +		rpm, Fstrerror(fd));
> +	goto exit;
> +    }
> +    fdFiniDigest(fd, PGPHASHALGO_MD5, (void **)&MD5, &md5len, 0);
> +
> +    if (headerGet(*sigp, RPMSIGTAG_MD5, &osigtd, HEADERGET_DEFAULT))
> +	memcpy(o_md5, osigtd.data, 16);
> +
> +    if (headerGet(*sigp, RPMSIGTAG_SHA1, &osigtd, HEADERGET_DEFAULT))
> +	o_sha1 = xstrdup(osigtd.data);
> +
> +    if (memcmp(MD5, o_md5, md5len) == 0 && strcmp(SHA1, o_sha1) == 0)
> +	rpmlog(RPMLOG_WARNING,
> +	       _("%s already contains identical file signatures\n"),
> +	       rpm);
> +    else
> +	replaceSigDigests(fd, rpm, sigp, sigStart, headerSize, SHA1, MD5);
> +
> +exit:
> +if (ofd)    (void) closeFile(&ofd);
> +    return rc;
> +}
> +
>  /** \ingroup rpmcli
>   * Create/modify elements in signature header.
>   * @param rpm		path to package
>   * @param deleting	adding or deleting signature?
> + * @param signfiles	sign files if non-zero
>   * @return		0 on success, -1 on error
>   */
> -static int rpmSign(const char *rpm, int deleting)
> +static int rpmSign(const char *rpm, int deleting, int signfiles)
>  {
>      FD_t fd = NULL;
>      FD_t ofd = NULL;
> @@ -560,6 +724,10 @@ static int rpmSign(const char *rpm, int deleting)
>  	goto exit;
>      }
>  
> +    if (signfiles) {
> +	includeFileSignatures(fd, rpm, &sigh, &h, sigStart, headerStart);
> +    }
> +
>      unloadImmutableRegion(&sigh, RPMTAG_HEADERSIGNATURES, &utd);
>      origSigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
>  
> @@ -709,7 +877,7 @@ int rpmPkgSign(const char *path, const struct rpmSignArgs
> * args)
>  	}
>      }
>  
> -    rc = rpmSign(path, 0);
> +    rc = rpmSign(path, 0, args->signfiles);
>  
>      if (args) {
>  	if (args->hashalgo) {
> @@ -725,5 +893,5 @@ int rpmPkgSign(const char *path, const struct rpmSignArgs
> * args)
>  
>  int rpmPkgDelSign(const char *path)
>  {
> -    return rpmSign(path, 1);
> +    return rpmSign(path, 1, 0);
>  }
> --
> 2.1.0
> 
> _______________________________________________
> Rpm-ecosystem mailing list
> Rpm-ecosystem at lists.rpm.org
> http://lists.rpm.org/mailman/listinfo/rpm-ecosystem
> 

Lubos


More information about the Rpm-ecosystem mailing list