malmond / rpms / rpm

Forked from rpms/rpm 5 years ago
Clone
Blob Blame History Raw
From d343c335fbf451ff1eebe3b347954c401c22ebf1 Mon Sep 17 00:00:00 2001
From: Panu Matilainen <pmatilai@redhat.com>
Date: Tue, 10 Oct 2017 11:44:10 +0300
Subject: [PATCH 05/33] Place file signatures into the signature header where
 they belong

The original file signing puts the file signatures into the main header
immutable region, invalidating all previous signatures and digests so
the package no longer appears to be what it was when it came out of the
assembly line. Which is bad. Doing that also requires recalculating
everything again which is just added complexity, and since it adds
stuff to different place from the rest of the signing, it requires yet
complexity to deal with that. Moving the file signatures into the
signature header solves all that and allows removing a big pile of
now unnecessary code.

Because this means retrofitting tags bass-ackwards into the signature
header, the tag definitions are backwards to everything else. Other
options would certainly be possible, but this makes things look more
normal on the signature header side. "Users" only ever see the
unchanged file signature tags as they have always been.

This also means the signature header can be MUCH bigger than ever before,
so bump up the limit (to 64MB, arbitrary something for now), and
permit string array types to be migrated from the signature header
on package read.

Caveats:
This loses the check for identical existing signatures to keep the
complexity down, it's hardly a critical thing and can be added back later.
While file signing could now be done separately to other signing, that
is not handled here.
---
 lib/header.c        |   2 +-
 lib/package.c       |   4 +-
 lib/rpmtag.h        |   4 ++
 sign/rpmgensig.c    | 161 +++-------------------------------------------------
 sign/rpmsignfiles.c |  14 ++---
 sign/rpmsignfiles.h |   5 +-
 6 files changed, 26 insertions(+), 164 deletions(-)

diff --git a/lib/header.c b/lib/header.c
index b05fda196..ab96da309 100644
--- a/lib/header.c
+++ b/lib/header.c
@@ -1910,7 +1910,7 @@ rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrbl
 
     if (regionTag == RPMTAG_HEADERSIGNATURES) {
 	il_max = 32;
-	dl_max = 8192;
+	dl_max = 64 * 1024;
     }
 
     memset(block, 0, sizeof(block));
diff --git a/lib/package.c b/lib/package.c
index d3fc37324..8ee0e9e7c 100644
--- a/lib/package.c
+++ b/lib/package.c
@@ -69,6 +69,8 @@ void headerMergeLegacySigs(Header h, Header sigh)
 	case RPMSIGTAG_SHA256:
 	case RPMSIGTAG_DSA:
 	case RPMSIGTAG_RSA:
+	case RPMSIGTAG_FILESIGNATURELENGTH:
+	case RPMSIGTAG_FILESIGNATURES:
 	default:
 	    if (!(td.tag >= HEADER_SIGBASE && td.tag < HEADER_TAGBASE))
 		continue;
@@ -88,11 +90,11 @@ void headerMergeLegacySigs(Header h, Header sigh)
 		    continue;
 		break;
 	    case RPM_STRING_TYPE:
+	    case RPM_STRING_ARRAY_TYPE:
 	    case RPM_BIN_TYPE:
 		if (td.count >= 16*1024)
 		    continue;
 		break;
-	    case RPM_STRING_ARRAY_TYPE:
 	    case RPM_I18NSTRING_TYPE:
 		continue;
 		break;
diff --git a/lib/rpmtag.h b/lib/rpmtag.h
index 8bdf34405..7a9092a6e 100644
--- a/lib/rpmtag.h
+++ b/lib/rpmtag.h
@@ -65,6 +65,8 @@ typedef enum rpmTag_e {
     RPMTAG_LONGARCHIVESIZE	= RPMTAG_SIG_BASE+15,	/* l */
     /* RPMTAG_SIG_BASE+16 reserved */
     RPMTAG_SHA256HEADER		= RPMTAG_SIG_BASE+17,	/* s */
+    /* RPMTAG_SIG_BASE+18 reserved for RPMSIGTAG_FILESIGNATURELENGTH */
+    /* RPMTAG_SIG_BASE+19 reserved for RPMSIGTAG_FILESIGNATURES */
 
     RPMTAG_NAME  		= 1000,	/* s */
 #define	RPMTAG_N	RPMTAG_NAME	/* s */
@@ -426,6 +428,8 @@ typedef enum rpmSigTag_e {
     RPMSIGTAG_LONGSIZE	= RPMTAG_LONGSIGSIZE,	/*!< internal Header+Payload size (64bit) in bytes. */
     RPMSIGTAG_LONGARCHIVESIZE = RPMTAG_LONGARCHIVESIZE, /*!< internal uncompressed payload size (64bit) in bytes. */
     RPMSIGTAG_SHA256	= RPMTAG_SHA256HEADER,
+    RPMSIGTAG_FILESIGNATURELENGTH	= RPMTAG_SIG_BASE + 18,
+    RPMSIGTAG_FILESIGNATURES		= RPMTAG_SIG_BASE + 19,
 } rpmSigTag;
 
 
diff --git a/sign/rpmgensig.c b/sign/rpmgensig.c
index e20cbdb12..875b96078 100644
--- a/sign/rpmgensig.c
+++ b/sign/rpmgensig.c
@@ -410,74 +410,12 @@ static void unloadImmutableRegion(Header *hdrp, rpmTagVal tag)
     }
 }
 
-#ifdef WITH_IMAEVM
-static rpmRC replaceSigDigests(FD_t fd, const char *rpm, Header *sigp,
-			       off_t sigStart, off_t sigTargetSize,
-			       char *SHA256, 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);
-    }
-
-    /* Set reserved space to 0 */
-    rpmPushMacro(NULL, "__gpg_reserved_space", NULL, 0, RMIL_GLOBAL);
-
-    /* Replace old digests in sigh */
-    rc = rpmGenerateSignature(SHA256, SHA1, MD5, sigTargetSize, archiveSize, fd);
-    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;
-    }
-
-    headerFree(*sigp);
-    rc = rpmReadSignature(fd, sigp, NULL);
-    if (rc != RPMRC_OK) {
-	rpmlog(RPMLOG_ERR, _("rpmReadSignature failed\n"));
-	goto exit;
-    }
-
-exit:
-    return rc;
-}
-#endif
-
-static rpmRC includeFileSignatures(FD_t fd, const char *rpm,
-				   Header *sigp, Header *hdrp,
-				   off_t sigStart, off_t headerStart)
+static rpmRC includeFileSignatures(Header *sigp, Header *hdrp)
 {
 #ifdef WITH_IMAEVM
-    FD_t ofd = NULL;
-    char *trpm = NULL;
+    rpmRC rc;
     char *key;
     char *keypass;
-    char *SHA1 = NULL;
-    char *SHA256 = NULL;
-    uint8_t *MD5 = NULL;
-    off_t sigTargetSize;
-    rpmRC rc = RPMRC_OK;
-    struct rpmtd_s osigtd;
-    char *o_sha1 = NULL;
-
-    unloadImmutableRegion(hdrp, RPMTAG_HEADERIMMUTABLE);
 
     key = rpmExpand("%{?_file_signing_key}", NULL);
 
@@ -487,94 +425,10 @@ static rpmRC includeFileSignatures(FD_t fd, const char *rpm,
 	keypass = NULL;
     }
 
-    rc = rpmSignFiles(*hdrp, key, keypass);
-    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;
-    }
+    rc = rpmSignFiles(*sigp, *hdrp, key, keypass);
 
-    /* Start MD5 calculation */
-    fdInitDigestID(fd, PGPHASHALGO_MD5, RPMSIGTAG_MD5, 0);
-
-    /* Write header to rpm and recalculate digests */
-    fdInitDigestID(fd, PGPHASHALGO_SHA1, RPMSIGTAG_SHA1, 0);
-    fdInitDigestID(fd, PGPHASHALGO_SHA256, RPMSIGTAG_SHA256, 0);
-    rc = headerWrite(fd, *hdrp, HEADER_MAGIC_YES);
-    if (rc != RPMRC_OK) {
-	rpmlog(RPMLOG_ERR, _("headerWrite failed\n"));
-	goto exit;
-    }
-    fdFiniDigest(fd, RPMSIGTAG_SHA1, (void **)&SHA1, NULL, 1);
-    /* Only add SHA256 if it was there to begin with */
-    if (headerIsEntry(*sigp, RPMSIGTAG_SHA256))
-	fdFiniDigest(fd, RPMSIGTAG_SHA256, (void **)&SHA256, NULL, 1);
-
-    /* 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);
-
-    sigTargetSize = Ftell(fd) - headerStart;
-    fdFiniDigest(fd, RPMSIGTAG_MD5, (void **)&MD5, NULL, 0);
-
-    if (headerGet(*sigp, RPMSIGTAG_SHA1, &osigtd, HEADERGET_DEFAULT)) {
-	o_sha1 = xstrdup(osigtd.data);
-	rpmtdFreeData(&osigtd);
-    }
-
-    if (strcmp(SHA1, o_sha1) == 0)
-	rpmlog(RPMLOG_WARNING,
-	       _("%s already contains identical file signatures\n"),
-	       rpm);
-    else
-	replaceSigDigests(fd, rpm, sigp, sigStart, sigTargetSize, SHA256, SHA1, MD5);
-
-exit:
-    free(trpm);
-    free(MD5);
-    free(SHA1);
-    free(SHA256);
-    free(o_sha1);
     free(keypass);
     free(key);
-    if (ofd)
-	(void) closeFile(&ofd);
     return rc;
 #else
     rpmlog(RPMLOG_ERR, _("file signing support not built in\n"));
@@ -667,13 +521,14 @@ static int rpmSign(const char *rpm, int deleting, int signfiles)
 	goto exit;
     }
 
-    if (signfiles) {
-	includeFileSignatures(fd, rpm, &sigh, &h, sigStart, headerStart);
-    }
-
     unloadImmutableRegion(&sigh, RPMTAG_HEADERSIGNATURES);
     origSigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
 
+    if (signfiles) {
+	if (includeFileSignatures(&sigh, &h))
+	    goto exit;
+    }
+
     if (deleting) {	/* Nuke all the signature tags. */
 	deleteSigs(sigh);
     } else {
diff --git a/sign/rpmsignfiles.c b/sign/rpmsignfiles.c
index 1fc127cb1..2dcc50400 100644
--- a/sign/rpmsignfiles.c
+++ b/sign/rpmsignfiles.c
@@ -80,7 +80,7 @@ char *keypass)
     return siglen + 1;
 }
 
-rpmRC rpmSignFiles(Header h, const char *key, char *keypass)
+rpmRC rpmSignFiles(Header sigh, Header h, const char *key, char *keypass)
 {
     struct rpmtd_s digests, td;
     int algo;
@@ -107,19 +107,19 @@ rpmRC rpmSignFiles(Header h, const char *key, char *keypass)
 	return RPMRC_FAIL;
     }
 
-    headerDel(h, RPMTAG_FILESIGNATURELENGTH);
-    headerDel(h, RPMTAG_FILESIGNATURES);
+    headerDel(sigh, RPMTAG_FILESIGNATURELENGTH);
+    headerDel(sigh, RPMTAG_FILESIGNATURES);
     siglen = signatureLength(algoname, diglen, key, keypass);
 
     rpmtdReset(&td);
-    td.tag = RPMTAG_FILESIGNATURELENGTH;
+    td.tag = RPMSIGTAG_FILESIGNATURELENGTH;
     td.type = RPM_INT32_TYPE;
     td.data = &siglen;
     td.count = 1;
-    headerPut(h, &td, HEADERPUT_DEFAULT);
+    headerPut(sigh, &td, HEADERPUT_DEFAULT);
 
     rpmtdReset(&td);
-    td.tag = RPMTAG_FILESIGNATURES;
+    td.tag = RPMSIGTAG_FILESIGNATURES;
     td.type = RPM_STRING_ARRAY_TYPE;
     td.data = NULL; /* set in the loop below */
     td.count = 1;
@@ -133,7 +133,7 @@ rpmRC rpmSignFiles(Header h, const char *key, char *keypass)
 	    goto exit;
 	}
 	td.data = &signature;
-	if (!headerPut(h, &td, HEADERPUT_APPEND)) {
+	if (!headerPut(sigh, &td, HEADERPUT_APPEND)) {
 	    free(signature);
 	    rpmlog(RPMLOG_ERR, _("headerPutString failed\n"));
 	    rc = RPMRC_FAIL;
diff --git a/sign/rpmsignfiles.h b/sign/rpmsignfiles.h
index 4163fafde..2ff623cdf 100644
--- a/sign/rpmsignfiles.h
+++ b/sign/rpmsignfiles.h
@@ -9,14 +9,15 @@ extern "C" {
 #endif
 
 /**
- * Sign file digests in header and store the signatures in header
+ * Sign file digests in header into signature header
+ * @param sigh		package signature header
  * @param h		package header
  * @param key		signing key
  * @param keypass	signing key password
  * @return		RPMRC_OK on success
  */
 RPM_GNUC_INTERNAL
-rpmRC rpmSignFiles(Header h, const char *key, char *keypass);
+rpmRC rpmSignFiles(Header sigh, Header h, const char *key, char *keypass);
 
 #ifdef _cplusplus
 }
-- 
2.13.5