From d343c335fbf451ff1eebe3b347954c401c22ebf1 Mon Sep 17 00:00:00 2001 From: Panu Matilainen 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