From f354c5a4265ddad758ad41abfb2f5fe174a54c69 Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Tue, 10 Oct 2017 11:44:10 +0300 Subject: [PATCH 04/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/rpmtag.h | 4 ++ sign/rpmgensig.c | 161 +++----------------------------------------- sign/rpmsignfiles.c | 14 ++-- sign/rpmsignfiles.h | 5 +- 4 files changed, 22 insertions(+), 162 deletions(-) diff --git a/lib/rpmtag.h b/lib/rpmtag.h index 002492d20..46719ec75 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 */ @@ -425,6 +427,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 8f77ad9c1..5fddb56ea 100644 --- a/sign/rpmgensig.c +++ b/sign/rpmgensig.c @@ -417,74 +417,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); @@ -494,94 +432,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")); @@ -674,13 +528,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.27.0