diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/package.c | 151 | ||||
-rw-r--r-- | lib/query.c | 2 | ||||
-rw-r--r-- | lib/rpmchecksig.c | 44 | ||||
-rw-r--r-- | lib/rpmlib.h | 13 | ||||
-rw-r--r-- | lib/signature.c | 328 | ||||
-rw-r--r-- | lib/verify.c | 2 |
6 files changed, 392 insertions, 148 deletions
diff --git a/lib/package.c b/lib/package.c index 712289b0c..3d79c2b9a 100644 --- a/lib/package.c +++ b/lib/package.c @@ -39,6 +39,7 @@ void headerMergeLegacySigs(Header h, const Header sig) ptr = hfd(ptr, type)) { switch (tag) { + /* XXX Translate legacy signature tag values. */ case RPMSIGTAG_SIZE: tag = RPMTAG_SIGSIZE; /*@switchbreak@*/ break; @@ -60,6 +61,11 @@ void headerMergeLegacySigs(Header h, const Header sig) case RPMSIGTAG_PGP5: tag = RPMTAG_SIGPGP5; /*@switchbreak@*/ break; + case RPMSIGTAG_PAYLOADSIZE: + tag = RPMTAG_ARCHIVESIZE; + /*@switchbreak@*/ break; + case RPMSIGTAG_SHA1: + case RPMSIGTAG_DSA: default: if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE)) continue; @@ -88,6 +94,7 @@ Header headerRegenSigHeader(const Header h) ptr = hfd(ptr, type)) { switch (tag) { + /* XXX Translate legacy signature tag values. */ case RPMTAG_SIGSIZE: stag = RPMSIGTAG_SIZE; /*@switchbreak@*/ break; @@ -109,6 +116,11 @@ Header headerRegenSigHeader(const Header h) case RPMTAG_SIGPGP5: stag = RPMSIGTAG_PGP5; /*@switchbreak@*/ break; + case RPMTAG_ARCHIVESIZE: + stag = RPMSIGTAG_PAYLOADSIZE; + /*@switchbreak@*/ break; + case RPMTAG_SHA1HEADER: + case RPMTAG_DSAHEADER: default: if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE)) continue; @@ -249,6 +261,7 @@ int rpmReadPackageFile(rpmTransactionSet ts, FD_t fd, /*@notreached@*/ break; } + /* Read the signature header. */ rc = rpmReadSignature(fd, &sig, l->signature_type); if (!(rc == RPMRC_OK || rc == RPMRC_BADSIZE)) { rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed\n"), fn); @@ -260,24 +273,26 @@ int rpmReadPackageFile(rpmTransactionSet ts, FD_t fd, goto exit; } - if (!ts->verify_legacy) /* leave fd ready to install payload */ - ts->sigtag = 0; - else if (headerIsEntry(sig, RPMSIGTAG_GPG)) + /* Figger the most effective available signature. */ + if (headerIsEntry(sig, RPMSIGTAG_DSA)) + ts->sigtag = RPMSIGTAG_DSA; + else if (!ts->verify_legacy) /* leave fd ready to install payload */ + ts->sigtag = (headerIsEntry(sig, RPMSIGTAG_SHA1)) ? RPMSIGTAG_SHA1 : 0; + else if (headerIsEntry(sig, RPMSIGTAG_GPG)) { ts->sigtag = RPMSIGTAG_GPG; - else if (headerIsEntry(sig, RPMSIGTAG_PGP)) + fdInitDigest(fd, PGPHASHALGO_SHA1, 0); + } else if (headerIsEntry(sig, RPMSIGTAG_PGP)) { ts->sigtag = RPMSIGTAG_PGP; - else if (headerIsEntry(sig, RPMSIGTAG_MD5)) + fdInitDigest(fd, PGPHASHALGO_MD5, 0); + } else if (headerIsEntry(sig, RPMSIGTAG_SHA1)) { + ts->sigtag = RPMSIGTAG_SHA1; /* XXX never happens */ + } else if (headerIsEntry(sig, RPMSIGTAG_MD5)) { ts->sigtag = RPMSIGTAG_MD5; - else - ts->sigtag = 0; - - /*@-type@*/ /* FIX: cast? */ - if (ts->sigtag == RPMSIGTAG_GPG) - fdInitDigest(fd, PGPHASHALGO_SHA1, 0); - else if (ts->sigtag == RPMSIGTAG_PGP || ts->sigtag == RPMSIGTAG_MD5) fdInitDigest(fd, PGPHASHALGO_MD5, 0); - /*@=type@*/ + } else + ts->sigtag = 0; /* XXX never happens */ + /* Read the metadata, computing digest(s) on the fly. */ hmagic = ((l->major >= 3) ? HEADER_MAGIC_YES : HEADER_MAGIC_NO); h = headerRead(fd, hmagic); if (h == NULL) { @@ -293,56 +308,94 @@ int rpmReadPackageFile(rpmTransactionSet ts, FD_t fd, } ts->dig = pgpNewDig(); - ts->dig->nbytes = headerSizeof(h, hmagic); - - /* Read the compressed payload. */ - while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0) - ts->dig->nbytes += count; - - if (count < 0) { - rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"), fn, Fstrerror(fd)); - rc = RPMRC_FAIL; + if (ts->dig == NULL) { + rc = RPMRC_OK; /* XXX WRONG */ goto exit; } - ts->dig->nbytes += count; + ts->dig->nbytes = 0; + /* Retrieve the tag parameters from the signature header. */ + ts->sig = NULL; xx = headerGetEntry(sig, ts->sigtag, &ts->sigtype, (void **) &ts->sig, &ts->siglen); + if (ts->sig == NULL) { + rc = RPMRC_OK; /* XXX WRONG */ + goto exit; + } - xx = pgpPrtPkts(ts->sig, ts->siglen, ts->dig, rpmIsDebug()); - - /*@-type@*/ /* FIX: cast? */ - for (i = fd->ndigests - 1; i >= 0; i--) { - FDDIGEST_t fddig = fd->digests + i; - if (fddig->hashctx == NULL) - continue; - if (fddig->hashalgo == PGPHASHALGO_MD5) { - /*@-branchstate@*/ - if (ts->dig->md5ctx != NULL) - (void) rpmDigestFinal(ts->dig->md5ctx, NULL, NULL, 0); - /*@=branchstate@*/ - ts->dig->md5ctx = fddig->hashctx; - fddig->hashctx = NULL; - continue; + switch (ts->sigtag) { + case RPMSIGTAG_DSA: + /* Parse the parameters from the OpenPGP packets that will be needed. */ + xx = pgpPrtPkts(ts->sig, ts->siglen, ts->dig, rpmIsDebug()); + /*@fallthrough@*/ + case RPMSIGTAG_SHA1: + { void * uh = NULL; + int_32 uht; + int_32 uhc; + + /*@-branchstate@*/ + if (headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)) { + ts->dig->sha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE); + (void) rpmDigestUpdate(ts->dig->sha1ctx, uh, uhc); + ts->dig->nbytes += uhc; + uh = headerFreeData(uh, uht); } - if (fddig->hashalgo == PGPHASHALGO_SHA1) { - /*@-branchstate@*/ - if (ts->dig->sha1ctx != NULL) - (void) rpmDigestFinal(ts->dig->sha1ctx, NULL, NULL, 0); - /*@=branchstate@*/ - ts->dig->sha1ctx = fddig->hashctx; - fddig->hashctx = NULL; - continue; + /*@=branchstate@*/ + } break; + case RPMSIGTAG_GPG: + case RPMSIGTAG_PGP5: /* XXX legacy */ + case RPMSIGTAG_PGP: + /* Parse the parameters from the OpenPGP packets that will be needed. */ + xx = pgpPrtPkts(ts->sig, ts->siglen, ts->dig, rpmIsDebug()); + /*@fallthrough@*/ + case RPMSIGTAG_MD5: + /* Legacy signatures need the compressed payload in the digest too. */ + ts->dig->nbytes += headerSizeof(h, hmagic); + while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0) + ts->dig->nbytes += count; + if (count < 0) { + rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"), + fn, Fstrerror(fd)); + rc = RPMRC_FAIL; + goto exit; + } + ts->dig->nbytes += count; + + /* XXX Steal the digest-in-progress from the file handle. */ + /*@-type@*/ /* FIX: cast? */ + for (i = fd->ndigests - 1; i >= 0; i--) { + FDDIGEST_t fddig = fd->digests + i; + if (fddig->hashctx == NULL) + continue; + if (fddig->hashalgo == PGPHASHALGO_MD5) { + /*@-branchstate@*/ + if (ts->dig->md5ctx != NULL) + (void) rpmDigestFinal(ts->dig->md5ctx, NULL, NULL, 0); + /*@=branchstate@*/ + ts->dig->md5ctx = fddig->hashctx; + fddig->hashctx = NULL; + continue; + } + if (fddig->hashalgo == PGPHASHALGO_SHA1) { + /*@-branchstate@*/ + if (ts->dig->sha1ctx != NULL) + (void) rpmDigestFinal(ts->dig->sha1ctx, NULL, NULL, 0); + /*@=branchstate@*/ + ts->dig->sha1ctx = fddig->hashctx; + fddig->hashctx = NULL; + continue; + } } + /*@=type@*/ + break; } - /*@=type@*/ /** @todo Implement disable/enable/warn/error/anal policy. */ buf[0] = '\0'; switch (rpmVerifySignature(ts, buf)) { case RPMSIG_OK: /* Signature is OK. */ - rpmMessage(RPMMESS_VERBOSE, "%s: %s", fn, buf); + rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf); rc = RPMRC_OK; break; case RPMSIG_UNKNOWN: /* Signature is unknown. */ @@ -363,7 +416,7 @@ exit: /* Convert legacy headers on the fly ... */ legacyRetrofit(h, l); - /* Append (and remap) signature tags. */ + /* Append (and remap) signature tags to the metadata. */ headerMergeLegacySigs(h, sig); /* Bump reference count for return. */ diff --git a/lib/query.c b/lib/query.c index d08b02ad5..09f0875e9 100644 --- a/lib/query.c +++ b/lib/query.c @@ -974,7 +974,9 @@ int rpmcliQuery(rpmTransactionSet ts, QVA_t qva, const char ** argv) qva->qva_showPackage = showQueryPackage; switch (qva->qva_source) { +#ifdef DYING case RPMQV_RPM: +#endif case RPMQV_SPECFILE: break; default: diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c index 671b3a49a..6bc10328d 100644 --- a/lib/rpmchecksig.c +++ b/lib/rpmchecksig.c @@ -21,6 +21,8 @@ /*@access FD_t @*/ /*@access pgpDig @*/ +/** + */ static int manageFile(FD_t *fdp, const char **fnp, int flags, /*@unused@*/ int rc) /*@globals rpmGlobalMacroContext, @@ -78,6 +80,7 @@ static int manageFile(FD_t *fdp, const char **fnp, int flags, } /** + * Copy header+payload, calculating digest(s) on the fly. */ static int copyFile(FD_t *sfdp, const char **sfnp, FD_t *tfdp, const char **tfnp) @@ -158,11 +161,11 @@ static int rpmReSign(/*@unused@*/ rpmTransactionSet ts, } switch (l->major) { case 1: - rpmError(RPMERR_BADSIGTYPE, _("%s: Can't sign v1.0 RPM\n"), rpm); + rpmError(RPMERR_BADSIGTYPE, _("%s: Can't sign v1 packaging\n"), rpm); goto exit; /*@notreached@*/ /*@switchbreak@*/ break; case 2: - rpmError(RPMERR_BADSIGTYPE, _("%s: Can't re-sign v2.0 RPM\n"), rpm); + rpmError(RPMERR_BADSIGTYPE, _("%s: Can't re-sign v2 packaging\n"), rpm); goto exit; /*@notreached@*/ /*@switchbreak@*/ break; default: @@ -202,18 +205,25 @@ static int rpmReSign(/*@unused@*/ rpmTransactionSet ts, } (void) headerRemoveEntry(sig, RPMSIGTAG_SIZE); - (void) headerRemoveEntry(sig, RPMSIGTAG_MD5); + (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_SIZE, qva->passPhrase); (void) headerRemoveEntry(sig, RPMSIGTAG_LEMD5_1); (void) headerRemoveEntry(sig, RPMSIGTAG_LEMD5_2); + (void) headerRemoveEntry(sig, RPMSIGTAG_MD5); + (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_MD5, qva->passPhrase); +#ifdef NOTNOW + (void) headerRemoveEntry(sig, RPMSIGTAG_SHA1); + (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_SHA1, qva->passPhrase); + (void) headerRemoveEntry(sig, RPMSIGTAG_PGP5); (void) headerRemoveEntry(sig, RPMSIGTAG_PGP); (void) headerRemoveEntry(sig, RPMSIGTAG_GPG); - (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_SIZE, qva->passPhrase); - (void) rpmAddSignature(sig, sigtarget, RPMSIGTAG_MD5, qva->passPhrase); +#endif } - if ((sigtype = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0) + if ((sigtype = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0) { + (void) headerRemoveEntry(sig, sigtype); (void) rpmAddSignature(sig, sigtarget, sigtype, qva->passPhrase); + } /* Write the lead/signature of the output rpm */ strcpy(tmprpm, rpm); @@ -466,7 +476,6 @@ static int readFile(FD_t fd, int_32 sigtag, const char * fn, pgpDig dig) rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"), fn, Fstrerror(fd)); goto exit; } - dig->nbytes += count; /*@-type@*/ /* FIX: cast? */ for (i = fd->ndigests - 1; i >= 0; i--) { @@ -546,14 +555,20 @@ int rpmVerifySignatures(QVA_t qva, rpmTransactionSet ts, FD_t fd, } /* Grab a hint of what needs doing to avoid duplication. */ - if (headerIsEntry(sig, RPMSIGTAG_GPG)) + if (headerIsEntry(sig, RPMSIGTAG_DSA)) + sigtag = RPMSIGTAG_DSA; + else if (headerIsEntry(sig, RPMSIGTAG_GPG)) sigtag = RPMSIGTAG_GPG; else if (headerIsEntry(sig, RPMSIGTAG_PGP)) sigtag = RPMSIGTAG_PGP; else if (headerIsEntry(sig, RPMSIGTAG_MD5)) sigtag = RPMSIGTAG_MD5; +#ifdef NOTYET + else if (headerIsEntry(sig, RPMSIGTAG_SHA1)) + sigtag = RPMSIGTAG_SHA1; /* XXX never happens */ +#endif else - sigtag = 0; /* XXX never happens */ + sigtag = 0; /* XXX never happens */ ts->dig = pgpNewDig(); @@ -589,6 +604,7 @@ if (rpmIsDebug()) fprintf(stderr, "========================= Package RSA Signature\n"); xx = pgpPrtPkts(ts->sig, ts->siglen, ts->dig, rpmIsDebug()); /*@switchbreak@*/ break; + case RPMSIGTAG_DSA: case RPMSIGTAG_GPG: if (!(qva->qva_flags & VERIFY_SIGNATURE)) continue; @@ -603,11 +619,17 @@ fprintf(stderr, "========================= Package DSA Signature\n"); continue; /* * Don't bother with md5 if pgp, as RSA/MD5 is more reliable - * than the legacy -- now unsupported -- legacy md5 breakage. + * than the -- now unsupported -- legacy md5 breakage. */ if (sigtag == RPMSIGTAG_PGP) continue; /*@switchbreak@*/ break; + case RPMSIGTAG_SHA1: +#ifdef NOTYET + if (!(qva->qva_flags & VERIFY_DIGEST)) + continue; + /*@switchbreak@*/ break; +#endif default: continue; /*@notreached@*/ /*@switchbreak@*/ break; @@ -662,6 +684,7 @@ fprintf(stderr, "========================= Package DSA Signature\n"); /*@innerbreak@*/ break; } /*@switchbreak@*/ break; + case RPMSIGTAG_DSA: case RPMSIGTAG_GPG: /* Do not consider this a failure */ switch (res3) { @@ -703,6 +726,7 @@ fprintf(stderr, "========================= Package DSA Signature\n"); case RPMSIGTAG_PGP: b = stpcpy(b, "pgp "); /*@switchbreak@*/ break; + case RPMSIGTAG_DSA: case RPMSIGTAG_GPG: b = stpcpy(b, "gpg "); /*@switchbreak@*/ break; diff --git a/lib/rpmlib.h b/lib/rpmlib.h index 4b34fbbe7..1f7310969 100644 --- a/lib/rpmlib.h +++ b/lib/rpmlib.h @@ -228,6 +228,7 @@ typedef enum rpmTag_e { /*@=enummemuse@*/ RPMTAG_SHA1HEADER = RPMTAG_SIG_BASE+9, RPMTAG_PUBKEYS = RPMTAG_SIG_BASE+10, + RPMTAG_DSAHEADER = RPMTAG_SIG_BASE+11, RPMTAG_NAME = 1000, RPMTAG_VERSION = 1001, @@ -773,9 +774,9 @@ typedef /*@abstract@*/ struct _rpmdbMatchIterator * rpmdbMatchIterator; /*@modifies mi, fileSystem @*/; /** \ingroup rpmdb - * Return join key for current position of rpm database iterator. + * Return header join key for current position of rpm database iterator. * @param mi rpm database iterator - * @return current join key + * @return current header join key */ unsigned int rpmdbGetIteratorOffset(/*@null@*/ rpmdbMatchIterator mi) /*@*/; @@ -1780,12 +1781,16 @@ typedef enum rpmEraseInterfaceFlags_e { enum rpmtagSignature { RPMSIGTAG_SIZE = 1000, /*!< Header+Payload size in bytes. */ /* the md5 sum was broken *twice* on big endian machines */ - RPMSIGTAG_LEMD5_1 = 1001, /*!< Broken MD5, take 1 */ + RPMSIGTAG_LEMD5_1 = 1001, /*!< Broken MD5, take 1 @deprecated legacy. */ RPMSIGTAG_PGP = 1002, /*!< PGP 2.6.3 signature. */ - RPMSIGTAG_LEMD5_2 = 1003, /*!< Broken MD5, take 2 */ + RPMSIGTAG_LEMD5_2 = 1003, /*!< Broken MD5, take 2 @deprecated legacy. */ RPMSIGTAG_MD5 = 1004, /*!< MD5 signature. */ RPMSIGTAG_GPG = 1005, /*!< GnuPG signature. */ RPMSIGTAG_PGP5 = 1006, /*!< PGP5 signature @deprecated legacy. */ + RPMSIGTAG_PAYLOADSIZE = 1007, + /*!< uncompressed payload size in bytes. */ + RPMSIGTAG_SHA1 = RPMTAG_SHA1HEADER, /*!< sha1 header digest. */ + RPMSIGTAG_DSA = RPMTAG_DSAHEADER, /*!< DSA header signature. */ }; /** diff --git a/lib/signature.c b/lib/signature.c index 40ed66cc1..f9a81b2e0 100644 --- a/lib/signature.c +++ b/lib/signature.c @@ -7,6 +7,7 @@ #include "rpmio_internal.h" #include <rpmlib.h> #include <rpmmacro.h> /* XXX for rpmGetPath() */ +#include "rpmdb.h" #include "depends.h" #include "misc.h" /* XXX for dosetenv() and makeTempFile() */ @@ -483,6 +484,10 @@ int rpmAddSignature(Header h, const char * file, int_32 sigTag, if (ret == 0) (void) headerAddEntry(h, sigTag, RPM_BIN_TYPE, sig, size); break; + case RPMSIGTAG_DSA: /* XXX UNIMPLEMENTED */ + break; + case RPMSIGTAG_SHA1: /* XXX UNIMPLEMENTED */ + break; } return ret; @@ -523,6 +528,7 @@ static int checkPassPhrase(const char * passPhrase, const int sigTag) (void) dup2(passPhrasePipe[0], 3); switch (sigTag) { + case RPMSIGTAG_DSA: case RPMSIGTAG_GPG: { const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL); @@ -597,6 +603,7 @@ char * rpmGetPassPhrase(const char * prompt, const int sigTag) int aok; switch (sigTag) { + case RPMSIGTAG_DSA: case RPMSIGTAG_GPG: { const char *name = rpmExpand("%{?_gpg_name}", NULL); aok = (name && *name != '\0'); @@ -662,21 +669,31 @@ verifySizeSignature(const rpmTransactionSet ts, /*@out@*/ char * t) *t = '\0'; t = stpcpy(t, _("Header+Payload size: ")); -/*@-nullpass -nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */ + if (ts->sig == NULL || ts->dig == NULL) { + res = RPMSIG_NOKEY; + t = stpcpy(t, rpmSigString(res)); + goto exit; + } + +/*@=nullpass =nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */ memcpy(&size, ts->sig, sizeof(size)); /*@-type@*/ /*@-nullderef@*/ /* FIX: ts->dig can be NULL */ if (size != ts->dig->nbytes) { res = RPMSIG_BAD; - sprintf(t, "BAD Expected(%d) != (%d)\n", size, ts->dig->nbytes); + t = stpcpy(t, rpmSigString(res)); + sprintf(t, " Expected(%d) != (%d)\n", size, ts->dig->nbytes); } else { res = RPMSIG_OK; - sprintf(t, "OK (%d)\n", ts->dig->nbytes); + t = stpcpy(t, rpmSigString(res)); + sprintf(t, " (%d)", ts->dig->nbytes); } /*@=type@*/ /*@=nullpass =nullderef@*/ +exit: + t = stpcpy(t, "\n"); return res; } @@ -691,7 +708,13 @@ verifyMD5Signature(const rpmTransactionSet ts, /*@out@*/ char * t) *t = '\0'; t = stpcpy(t, _("MD5 digest: ")); -/*@-nullpass -nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */ + if (ts->sig == NULL || ts->dig == NULL) { + res = RPMSIG_NOKEY; + t = stpcpy(t, rpmSigString(res)); + goto exit; + } + +/*@=nullpass =nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */ /*@-type@*/ (void) rpmDigestFinal(rpmDigestDup(ts->dig->md5ctx), (void **)&md5sum, &md5len, 0); @@ -699,21 +722,172 @@ verifyMD5Signature(const rpmTransactionSet ts, /*@out@*/ char * t) if (md5len != ts->siglen || memcmp(md5sum, ts->sig, md5len)) { res = RPMSIG_BAD; - t = stpcpy(t, "BAD Expected("); + t = stpcpy(t, rpmSigString(res)); + t = stpcpy(t, " Expected("); (void) pgpHexCvt(t, ts->sig, ts->siglen); t += strlen(t); t = stpcpy(t, ") != ("); } else { res = RPMSIG_OK; - t = stpcpy(t, "OK ("); + t = stpcpy(t, rpmSigString(res)); + t = stpcpy(t, " ("); } /*@=nullpass =nullderef@*/ (void) pgpHexCvt(t, md5sum, md5len); t += strlen(t); - t = stpcpy(t, ")\n"); + t = stpcpy(t, ")"); +exit: md5sum = _free(md5sum); + t = stpcpy(t, "\n"); + return res; +} + +static rpmVerifySignatureReturn +verifySHA1Signature(const rpmTransactionSet ts, /*@out@*/ char * t) + /*@modifies *t @*/ +{ + rpmVerifySignatureReturn res; + const char * sha1 = NULL; + + *t = '\0'; + t = stpcpy(t, _("SHA1 header digest: ")); + + if (ts->sig == NULL || ts->dig == NULL) { + res = RPMSIG_NOKEY; + t = stpcpy(t, rpmSigString(res)); + goto exit; + } + + /*@-type@*/ + (void) rpmDigestFinal(rpmDigestDup(ts->dig->sha1ctx), + (void **)&sha1, NULL, 1); + /*@=type@*/ + + if (sha1 == NULL || strlen(sha1) != strlen(ts->sig)) { + res = RPMSIG_BAD; + t = stpcpy(t, rpmSigString(res)); + t = stpcpy(t, " Expected("); + t = stpcpy(t, ts->sig); + t = stpcpy(t, ") != ("); + } else { + res = RPMSIG_OK; + t = stpcpy(t, rpmSigString(res)); + t = stpcpy(t, " ("); + } + if (sha1) + t = stpcpy(t, sha1); + t = stpcpy(t, ")"); + +exit: + sha1 = _free(sha1); + t = stpcpy(t, "\n"); + return res; +} + +/** + * Retrieve pubkey from rpm database. + * @param ts rpm transaction + * @return RPMSIG_OK on success, RPMSIG_NOKEY if not found + */ +static rpmVerifySignatureReturn +rpmtsFindPubkey(rpmTransactionSet ts) + /*@modifies ts */ +{ + struct pgpDigParams_s * sigp = NULL; + rpmVerifySignatureReturn res; + /*@unchecked@*/ /*@only@*/ static const byte * pkpkt = NULL; + /*@unchecked@*/ static size_t pkpktlen = 0; + /*@unchecked@*/ static byte pksignid[8]; + int xx; + + if (ts->sig == NULL || ts->dig == NULL) { + res = RPMSIG_NOKEY; + goto exit; + } + sigp = &ts->dig->signature; + + /*@-globs -internalglobs -mods -modfilesys@*/ + if (pkpkt == NULL || memcmp(sigp->signid, pksignid, sizeof(pksignid))) { + int ix = -1; + rpmdbMatchIterator mi; + Header h; + + pkpkt = _free(pkpkt); + pkpktlen = 0; + memset(pksignid, 0, sizeof(pksignid)); + + (void) rpmtsOpenDB(ts, ts->dbmode); + + mi = rpmtsInitIterator(ts, RPMTAG_PUBKEYS, sigp->signid, sizeof(sigp->signid)); + while ((h = rpmdbNextIterator(mi)) != NULL) { + const char ** pubkeys; + int_32 pt, pc; + + if (!headerGetEntry(h, RPMTAG_PUBKEYS, &pt, (void **)&pubkeys, &pc)) + continue; + ix = rpmdbGetIteratorFileNum(mi); + if (ix >= pc + || b64decode(pubkeys[ix], (void **) &pkpkt, &pkpktlen)) + ix = -1; + pubkeys = headerFreeData(pubkeys, pt); + break; + } + mi = rpmdbFreeIterator(mi); + + if (ix < 0 || pkpkt == NULL) { + res = RPMSIG_NOKEY; + goto exit; + } + + /* Make sure the pkt can be parsed, print info if debugging. */ + if (pgpPrtPkts(pkpkt, pkpktlen, NULL, 0)) { + res = RPMSIG_NOKEY; + goto exit; + } + + /* XXX Verify the pubkey signature. */ + + /* Packet looks good, save the signer id. */ + memcpy(pksignid, sigp->signid, sizeof(pksignid)); + } + +#ifdef NOTNOW + { + if (pkpkt == NULL) { + const char * pkfn = rpmExpand("%{_gpg_pubkey}", NULL); + if (pgpReadPkts(pkfn, &pkpkt, &pkpktlen) != PGPARMOR_PUBKEY) { + pkfn = _free(pkfn); + res = RPMSIG_NOKEY; + goto exit; + } + pkfn = _free(pkfn); + } + } +#endif + + rpmMessage(RPMMESS_DEBUG, "========== %s pubkey id %s\n", + (sigp->pubkey_algo == PGPPUBKEYALGO_DSA ? "DSA" : + (sigp->pubkey_algo == PGPPUBKEYALGO_RSA ? "RSA" : "???")), + pgpHexStr(sigp->signid, sizeof(sigp->signid))); + + /* Retrieve parameters from pubkey packet(s). */ + xx = pgpPrtPkts(pkpkt, pkpktlen, ts->dig, 0); + /*@=globs =internalglobs =mods =modfilesys@*/ + + /* Make sure we have the correct public key. */ + if (ts->dig->signature.pubkey_algo == ts->dig->pubkey.pubkey_algo +#ifdef NOTYET + && ts->dig->signature.hash_algo == ts->dig->pubkey.hash_algo +#endif + && !memcmp(ts->dig->signature.signid, ts->dig->pubkey.signid, 8)) + res = RPMSIG_OK; + else + res = RPMSIG_NOKEY; + + /* XXX Verify the signature signature. */ +exit: return res; } @@ -721,22 +895,33 @@ static rpmVerifySignatureReturn verifyPGPSignature(rpmTransactionSet ts, /*@out@*/ char * t) /*@modifies ts, *t */ { -/*@-nullpass -nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */ + struct pgpDigParams_s * sigp = NULL; rpmVerifySignatureReturn res; - struct pgpDigParams_s * digp = &ts->dig->signature; - /*@unchecked@*/ static const byte * pgppk = NULL; - /*@unchecked@*/ static size_t pgppklen = 0; int xx; *t = '\0'; t = stpcpy(t, _("V3 RSA/MD5 signature: ")); + if (ts->sig == NULL || ts->dig == NULL) { + res = RPMSIG_NOKEY; + goto exit; + } + sigp = &ts->dig->signature; + /* XXX sanity check on ts->sigtag and signature agreement. */ + if (!(ts->sigtag == RPMSIGTAG_PGP + && sigp->pubkey_algo == PGPPUBKEYALGO_RSA + && sigp->hash_algo == PGPHASHALGO_MD5)) + { + res = RPMSIG_NOKEY; + goto exit; + } /*@-type@*/ /* FIX: cast? */ { DIGEST_CTX ctx = rpmDigestDup(ts->dig->md5ctx); - xx = rpmDigestUpdate(ctx, digp->hash, digp->hashlen); + if (sigp->hash != NULL) + xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen); xx = rpmDigestFinal(ctx, (void **)&ts->dig->md5, &ts->dig->md5len, 1); /* XXX compare leading 16 bits of digest for quick check. */ @@ -763,46 +948,25 @@ verifyPGPSignature(rpmTransactionSet ts, /*@out@*/ char * t) hexstr = _free(hexstr); } - /* XXX retrieve by keyid from signature. */ - - /*@-globs -internalglobs -mods -modfilesys@*/ - if (pgppk == NULL) { - const char * pkfn = rpmExpand("%{_pgp_pubkey}", NULL); - if (pgpReadPkts(pkfn, &pgppk, &pgppklen) != PGPARMOR_PUBKEY) { - pkfn = _free(pkfn); - res = RPMSIG_NOKEY; - goto exit; - } - rpmMessage(RPMMESS_DEBUG, - "========== PGP RSA/MD5 pubkey %s\n", pkfn); - xx = pgpPrtPkts(pgppk, pgppklen, NULL, rpmIsDebug()); - pkfn = _free(pkfn); - } - - /* Retrieve parameters from pubkey packet(s). */ - xx = pgpPrtPkts(pgppk, pgppklen, ts->dig, 0); - /*@=globs =internalglobs =mods =modfilesys@*/ - - /* Make sure we have the correct public key. */ - if (ts->dig->signature.pubkey_algo != ts->dig->pubkey.pubkey_algo - || memcmp(ts->dig->signature.signid, ts->dig->pubkey.signid, 8)) - { - res = RPMSIG_NOKEY; + /* Retrieve the matching public key. */ + res = rpmtsFindPubkey(ts); + if (res != RPMSIG_OK) goto exit; - } /*@-type@*/ - if (!rsavrfy(&ts->dig->rsa_pk, &ts->dig->rsahm, &ts->dig->c)) - res = RPMSIG_BAD; - else + if (rsavrfy(&ts->dig->rsa_pk, &ts->dig->rsahm, &ts->dig->c)) res = RPMSIG_OK; + else + res = RPMSIG_BAD; /*@=type@*/ -/*@=nullpass =nullderef@*/ exit: - t = stpcpy( stpcpy(t, rpmSigString(res)), ", key ID "); - (void) pgpHexCvt(t, digp->signid+4, sizeof(digp->signid)-4); - t += strlen(t); + t = stpcpy(t, rpmSigString(res)); + if (sigp != NULL) { + t = stpcpy(t, ", key ID "); + (void) pgpHexCvt(t, sigp->signid+4, sizeof(sigp->signid)-4); + t += strlen(t); + } t = stpcpy(t, "\n"); return res; } @@ -811,71 +975,61 @@ static rpmVerifySignatureReturn verifyGPGSignature(rpmTransactionSet ts, /*@out@*/ char * t) /*@modifies ts, *t @*/ { -/*@-nullpass -nullderef@*/ /* FIX: ts->{sig,dig} can be NULL */ + struct pgpDigParams_s * sigp = NULL; rpmVerifySignatureReturn res; - struct pgpDigParams_s * digp = &ts->dig->signature; - /*@unchecked@*/ static const byte * gpgpk = NULL; - /*@unchecked@*/ static size_t gpgpklen = 0; int xx; *t = '\0'; t = stpcpy(t, _("V3 DSA signature: ")); + if (ts->sig == NULL || ts->dig == NULL) { + res = RPMSIG_NOKEY; + goto exit; + } + sigp = &ts->dig->signature; + /* XXX sanity check on ts->sigtag and signature agreement. */ + if (!((ts->sigtag == RPMSIGTAG_GPG || ts->sigtag == RPMSIGTAG_DSA) + && sigp->pubkey_algo == PGPPUBKEYALGO_DSA + && sigp->hash_algo == PGPHASHALGO_SHA1)) + { + res = RPMSIG_NOKEY; + goto exit; + } /*@-type@*/ /* FIX: cast? */ { DIGEST_CTX ctx = rpmDigestDup(ts->dig->sha1ctx); - xx = rpmDigestUpdate(ctx, digp->hash, digp->hashlen); + if (sigp->hash != NULL) + xx = rpmDigestUpdate(ctx, sigp->hash, sigp->hashlen); xx = rpmDigestFinal(ctx, (void **)&ts->dig->sha1, &ts->dig->sha1len, 1); + /* XXX compare leading 16 bits of digest for quick check. */ + mp32nzero(&ts->dig->hm); mp32nsethex(&ts->dig->hm, ts->dig->sha1); } /*@=type@*/ - /* XXX retrieve by keyid from signature. */ - - /*@-globs -internalglobs -mods -modfilesys@*/ - if (gpgpk == NULL) { - const char * pkfn = rpmExpand("%{_gpg_pubkey}", NULL); - int printing = 0; /* XXX was rpmIsDebug() */ - - if (pgpReadPkts(pkfn, &gpgpk, &gpgpklen) != PGPARMOR_PUBKEY) { - pkfn = _free(pkfn); - res = RPMSIG_NOKEY; - goto exit; - } - rpmMessage(RPMMESS_DEBUG, - "========== GPG DSA pubkey %s\n", pkfn); - xx = pgpPrtPkts(gpgpk, gpgpklen, NULL, printing); - pkfn = _free(pkfn); - } - - /* Retrieve parameters from pubkey packet(s). */ - xx = pgpPrtPkts(gpgpk, gpgpklen, ts->dig, 0); - /*@=globs =internalglobs =mods =modfilesys@*/ - - /* Make sure we have the correct public key. */ - if (ts->dig->signature.pubkey_algo != ts->dig->pubkey.pubkey_algo - || memcmp(ts->dig->signature.signid, ts->dig->pubkey.signid, 8)) - { - res = RPMSIG_NOKEY; + /* Retrieve the matching public key. */ + res = rpmtsFindPubkey(ts); + if (res != RPMSIG_OK) goto exit; - } /*@-type@*/ - if (!dsavrfy(&ts->dig->p, &ts->dig->q, &ts->dig->g, + if (dsavrfy(&ts->dig->p, &ts->dig->q, &ts->dig->g, &ts->dig->hm, &ts->dig->y, &ts->dig->r, &ts->dig->s)) - res = RPMSIG_BAD; - else res = RPMSIG_OK; + else + res = RPMSIG_BAD; /*@=type@*/ -/*@=nullpass =nullderef@*/ exit: - t = stpcpy( stpcpy(t, rpmSigString(res)), ", key ID "); - (void) pgpHexCvt(t, digp->signid+4, sizeof(digp->signid)-4); - t += strlen(t); + t = stpcpy(t, rpmSigString(res)); + if (sigp != NULL) { + t = stpcpy(t, ", key ID "); + (void) pgpHexCvt(t, sigp->signid+4, sizeof(sigp->signid)-4); + t += strlen(t); + } t = stpcpy(t, "\n"); return res; } @@ -897,10 +1051,14 @@ rpmVerifySignature(const rpmTransactionSet ts, char * result) case RPMSIGTAG_MD5: res = verifyMD5Signature(ts, result); break; + case RPMSIGTAG_SHA1: + res = verifySHA1Signature(ts, result); + break; case RPMSIGTAG_PGP5: /* XXX legacy */ case RPMSIGTAG_PGP: res = verifyPGPSignature(ts, result); break; + case RPMSIGTAG_DSA: case RPMSIGTAG_GPG: res = verifyGPGSignature(ts, result); break; diff --git a/lib/verify.c b/lib/verify.c index 13a30e3ee..c3f544bf1 100644 --- a/lib/verify.c +++ b/lib/verify.c @@ -572,10 +572,12 @@ int rpmcliVerify(rpmTransactionSet ts, QVA_t qva, const char ** argv) qva->qva_showPackage = showVerifyPackage; switch (qva->qva_source) { +#ifdef DYING case RPMQV_RPM: if (!(qva->qva_flags & VERIFY_DEPS)) break; /*@fallthrough@*/ +#endif default: if (rpmtsOpenDB(ts, O_RDONLY)) return 1; /* XXX W2DO? */ |