Backport of the signature comparison on package resigning fixes: http://rpm.org/gitweb?p=rpm.git;a=commitdiff;h=e29313061313a9e29d38a005f1b5f5bdc47ccd84 http://rpm.org/gitweb?p=rpm.git;a=commitdiff;h=c0aad81e9b17afcbea4008485d354673495eb148 http://rpm.org/gitweb?p=rpm.git;a=commitdiff;h=17b433ce8c8613199e40b3b27e9ca5398a2027e3 diff --git a/lib/rpmchecksig.c b/lib/rpmchecksig.c index babbe76..1545269 100644 --- a/lib/rpmchecksig.c +++ b/lib/rpmchecksig.c @@ -105,28 +105,96 @@ exit: } /** - * Retrieve signer fingerprint from an OpenPGP signature tag. - * @param sig signature header + * Retrieve signature from header tag + * @param sigh signature header * @param sigtag signature tag - * @retval signid signer fingerprint - * @return 0 on success + * @return parsed pgp dig or NULL */ -static int getSignid(Header sig, rpmSigTag sigtag, pgpKeyID_t signid) +static pgpDig getSig(Header sigh, rpmSigTag sigtag) { struct rpmtd_s pkt; - int rc = 1; + pgpDig dig = NULL; - if (headerGet(sig, sigtag, &pkt, HEADERGET_DEFAULT) && pkt.data != NULL) { - pgpDig dig = pgpNewDig(); + if (headerGet(sigh, sigtag, &pkt, HEADERGET_DEFAULT) && pkt.data != NULL) { + dig = pgpNewDig(); - if (!pgpPrtPkts(pkt.data, pkt.count, dig, 0)) { - memcpy(signid, dig->signature.signid, sizeof(dig->signature.signid)); - rc = 0; + if (pgpPrtPkts(pkt.data, pkt.count, dig, 0) != 0) { + dig = pgpFreeDig(dig); } - - dig = pgpFreeDig(dig); rpmtdFreeData(&pkt); } + return dig; +} + +static void deleteSigs(Header sigh) +{ + headerDel(sigh, RPMSIGTAG_GPG); + headerDel(sigh, RPMSIGTAG_PGP); + headerDel(sigh, RPMSIGTAG_DSA); + headerDel(sigh, RPMSIGTAG_RSA); + headerDel(sigh, RPMSIGTAG_PGP5); +} + +static int sameSignature(rpmSigTag sigtag, Header h1, Header h2) +{ + pgpDig dig1 = getSig(h1, sigtag); + pgpDig dig2 = getSig(h2, sigtag); + int rc = 0; /* assume different, eg if either signature doesn't exist */ + + /* XXX This part really belongs to rpmpgp.[ch] */ + if (dig1 && dig2) { + pgpDigParams sig1 = &dig1->signature; + pgpDigParams sig2 = &dig2->signature; + + /* XXX Should we compare something else too? */ + if (sig1->hash_algo != sig2->hash_algo) + goto exit; + if (sig1->pubkey_algo != sig2->pubkey_algo) + goto exit; + if (sig1->version != sig2->version) + goto exit; + if (sig1->sigtype != sig2->sigtype) + goto exit; + if (memcmp(sig1->signid, sig2->signid, sizeof(sig1->signid)) != 0) + goto exit; + + /* Parameters match, assume same signature */ + rc = 1; + } + +exit: + pgpFreeDig(dig1); + pgpFreeDig(dig2); + return rc; +} + +static int replaceSignature(Header sigh, const char *sigtarget, + const char *passPhrase) +{ + /* Grab a copy of the header so we can compare the result */ + Header oldsigh = headerCopy(sigh); + int rc = -1; + + /* Nuke all signature tags */ + deleteSigs(sigh); + + /* + * rpmAddSignature() internals parse the actual signing result and + * use appropriate DSA/RSA tags regardless of what we pass from here. + * RPMSIGTAG_GPG is only used to signal its an actual signature + * and not just a digest we're adding, and says nothing + * about the actual tags that gets created. + */ + if (rpmAddSignature(sigh, sigtarget, RPMSIGTAG_GPG, passPhrase) == 0) { + /* Lets see what we got and whether its the same signature as before */ + rpmSigTag sigtag = headerIsEntry(sigh, RPMSIGTAG_DSA) ? + RPMSIGTAG_DSA : RPMSIGTAG_RSA; + + rc = sameSignature(sigtag, sigh, oldsigh); + + } + + headerFree(oldsigh); return rc; } @@ -253,62 +321,18 @@ static int rpmReSign(rpmts ts, QVA_t qva, ARGV_const_t argv) } if (deleting) { /* Nuke all the signature tags. */ - xx = headerDel(sigh, RPMSIGTAG_GPG); - xx = headerDel(sigh, RPMSIGTAG_DSA); - xx = headerDel(sigh, RPMSIGTAG_PGP5); - xx = headerDel(sigh, RPMSIGTAG_PGP); - xx = headerDel(sigh, RPMSIGTAG_RSA); - } else /* If gpg/pgp is configured, replace the signature. */ - if ((sigtag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0) { - pgpKeyID_t oldsignid, newsignid; - - /* Grab the old signature fingerprint (if any) */ - memset(oldsignid, 0, sizeof(oldsignid)); - xx = getSignid(sigh, sigtag, oldsignid); - - switch (sigtag) { - case RPMSIGTAG_DSA: - xx = headerDel(sigh, RPMSIGTAG_GPG); - break; - case RPMSIGTAG_RSA: - xx = headerDel(sigh, RPMSIGTAG_PGP); - break; - case RPMSIGTAG_GPG: - xx = headerDel(sigh, RPMSIGTAG_DSA); - case RPMSIGTAG_PGP5: - case RPMSIGTAG_PGP: - xx = headerDel(sigh, RPMSIGTAG_RSA); - break; - default: - break; - } - - xx = headerDel(sigh, sigtag); - if (rpmAddSignature(sigh, sigtarget, sigtag, qva->passPhrase)) { - goto exit; - } - - /* If package was previously signed, check for same signer. */ - memset(newsignid, 0, sizeof(newsignid)); - if (memcmp(oldsignid, newsignid, sizeof(oldsignid))) { - - /* Grab the new signature fingerprint */ - xx = getSignid(sigh, sigtag, newsignid); - - /* If same signer, skip resigning the package. */ - if (!memcmp(oldsignid, newsignid, sizeof(oldsignid))) { - - char *signid = pgpHexStr(newsignid+4, sizeof(newsignid)-4); + deleteSigs(sigh); + } else if ((sigtag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0) { + res = replaceSignature(sigh, sigtarget, qva->passPhrase); + if (res != 0) { + if (res == 1) { rpmlog(RPMLOG_WARNING, - _("%s: was already signed by key ID %s, skipping\n"), - rpm, signid); - free(signid); - - /* Clean up intermediate target */ - xx = unlink(sigtarget); - sigtarget = _free(sigtarget); - continue; + _("%s already contains identical signature, skipping\n"), + rpm); + /* Identical signature is not an error */ + res = 0; } + goto exit; } } diff --git a/lib/signature.c b/lib/signature.c index 7d50db7..d5aad52 100644 --- a/lib/signature.c +++ b/lib/signature.c @@ -584,12 +584,12 @@ int rpmAddSignature(Header sigh, const char * file, rpmSigTag sigTag, case RPMSIGTAG_PGP5: /* XXX legacy */ case RPMSIGTAG_PGP: case RPMSIGTAG_GPG: { - rpmSigTag hdrtag = (sigTag == RPMSIGTAG_GPG) ? - RPMSIGTAG_DSA : RPMSIGTAG_RSA; + rpmSigTag hdrtag; if (makeGPGSignature(file, &sigTag, &pkt, &pktlen, passPhrase) || !sighdrPut(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen)) break; /* XXX Piggyback a header-only DSA/RSA signature as well. */ + hdrtag = (sigTag == RPMSIGTAG_GPG) ? RPMSIGTAG_DSA : RPMSIGTAG_RSA; ret = makeHDRSignature(sigh, file, hdrtag, passPhrase); } break; case RPMSIGTAG_RSA: