FD_t fdFree( FD_t fd) { if (fd) { if (--fd->nrefs > 0) return fd; fd->stats = _free(fd->stats); if (fd->digests) { fd->digests = rpmDigestBundleFree(fd->digests); } free(fd->descr); free(fd); } return NULL; }
static int rpmpkgVerifySigs(rpmKeyring keyring, rpmQueryFlags flags, FD_t fd, const char *fn) { char *buf = NULL; char *missingKeys = NULL; char *untrustedKeys = NULL; struct rpmtd_s sigtd; pgpDigParams sig = NULL; Header sigh = NULL; HeaderIterator hi = NULL; char * msg = NULL; int res = 1; /* assume failure */ rpmRC rc; int failed = 0; int nodigests = !(flags & VERIFY_DIGEST); int nosignatures = !(flags & VERIFY_SIGNATURE); struct sigtInfo_s sinfo; rpmDigestBundle plbundle = rpmDigestBundleNew(); rpmDigestBundle hdrbundle = rpmDigestBundleNew(); if ((rc = rpmLeadRead(fd, NULL, NULL, &msg)) != RPMRC_OK) { goto exit; } rc = rpmReadSignature(fd, &sigh, RPMSIGTYPE_HEADERSIG, &msg); if (rc != RPMRC_OK) { goto exit; } /* Initialize all digests we'll be needing */ hi = headerInitIterator(sigh); for (; headerNext(hi, &sigtd) != 0; rpmtdFreeData(&sigtd)) { rc = rpmSigInfoParse(&sigtd, "package", &sinfo, NULL, NULL); if (nosignatures && sinfo.type == RPMSIG_SIGNATURE_TYPE) continue; if (nodigests && sinfo.type == RPMSIG_DIGEST_TYPE) continue; if (rc == RPMRC_OK && sinfo.hashalgo) { rpmDigestBundleAdd(sinfo.payload ? plbundle : hdrbundle, sinfo.hashalgo, RPMDIGEST_NONE); } } hi = headerFreeIterator(hi); /* Read the file, generating digest(s) on the fly. */ fdSetBundle(fd, plbundle); if (readFile(fd, fn, plbundle, hdrbundle)) { goto exit; } rasprintf(&buf, "%s:%c", fn, (rpmIsVerbose() ? '\n' : ' ') ); hi = headerInitIterator(sigh); for (; headerNext(hi, &sigtd) != 0; rpmtdFreeData(&sigtd)) { char *result = NULL; DIGEST_CTX ctx = NULL; if (sigtd.data == NULL) /* XXX can't happen */ continue; /* Clean up parameters from previous sigtag. */ sig = pgpDigParamsFree(sig); /* Note: we permit failures to be ignored via disablers */ rc = rpmSigInfoParse(&sigtd, "package", &sinfo, &sig, &result); if (nosignatures && sinfo.type == RPMSIG_SIGNATURE_TYPE) continue; if (nodigests && sinfo.type == RPMSIG_DIGEST_TYPE) continue; if (sinfo.type == RPMSIG_OTHER_TYPE) continue; if (rc == RPMRC_OK) { ctx = rpmDigestBundleDupCtx(sinfo.payload ? plbundle : hdrbundle, sinfo.hashalgo); rc = rpmVerifySignature(keyring, &sigtd, sig, ctx, &result); rpmDigestFinal(ctx, NULL, NULL, 0); } if (result) { formatResult(sigtd.tag, rc, result, (rc == RPMRC_NOKEY ? &missingKeys : &untrustedKeys), &buf); free(result); } if (rc != RPMRC_OK) { failed = 1; } } res = failed; if (rpmIsVerbose()) { rpmlog(RPMLOG_NOTICE, "%s", buf); } else { const char *ok = (failed ? _("NOT OK") : _("OK")); rpmlog(RPMLOG_NOTICE, "%s%s%s%s%s%s%s%s\n", buf, ok, missingKeys ? _(" (MISSING KEYS:") : "", missingKeys ? missingKeys : "", missingKeys ? _(") ") : "", untrustedKeys ? _(" (UNTRUSTED KEYS:") : "", untrustedKeys ? untrustedKeys : "", untrustedKeys ? _(")") : ""); } free(missingKeys); free(untrustedKeys); exit: if (res && msg != NULL) rpmlog(RPMLOG_ERR, "%s: %s\n", fn, msg); free(msg); free(buf); rpmDigestBundleFree(hdrbundle); rpmDigestBundleFree(plbundle); fdSetBundle(fd, NULL); /* XXX avoid double-free from fd close */ sigh = rpmFreeSignature(sigh); hi = headerFreeIterator(hi); pgpDigParamsFree(sig); return res; }