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; }
/** \ingroup rpmcli * Create/modify elements in signature header. * @param rpm path to package * @param deleting adding or deleting signature? * @param signfiles sign files if non-zero * @return 0 on success, -1 on error */ static int rpmSign(const char *rpm, int deleting, int signfiles) { FD_t fd = NULL; FD_t ofd = NULL; char *trpm = NULL; Header sigh = NULL; Header h = NULL; char *msg = NULL; int res = -1; /* assume failure */ rpmRC rc; struct rpmtd_s utd; off_t headerStart; off_t sigStart; struct sigTarget_s sigt_v3; struct sigTarget_s sigt_v4; unsigned int origSigSize; int insSig = 0; fprintf(stdout, "%s:\n", rpm); if (manageFile(&fd, rpm, O_RDWR)) goto exit; if ((rc = rpmLeadRead(fd, &msg)) != RPMRC_OK) { rpmlog(RPMLOG_ERR, "%s: %s\n", rpm, msg); goto exit; } sigStart = Ftell(fd); rc = rpmReadSignature(fd, &sigh, &msg); if (rc != RPMRC_OK) { rpmlog(RPMLOG_ERR, _("%s: rpmReadSignature failed: %s"), rpm, (msg && *msg ? msg : "\n")); goto exit; } headerStart = Ftell(fd); if (rpmReadHeader(NULL, fd, &h, &msg) != RPMRC_OK) { rpmlog(RPMLOG_ERR, _("%s: headerRead failed: %s\n"), rpm, msg); goto exit; } if (!headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) { rpmlog(RPMLOG_ERR, _("Cannot sign RPM v3 packages\n")); goto exit; } 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 { /* Signature target containing header + payload */ sigt_v3.fd = fd; sigt_v3.start = headerStart; sigt_v3.fileName = rpm; sigt_v3.size = fdSize(fd) - headerStart; /* Signature target containing only header */ sigt_v4 = sigt_v3; sigt_v4.size = headerSizeof(h, HEADER_MAGIC_YES); res = replaceSignature(sigh, &sigt_v3, &sigt_v4); if (res != 0) { if (res == 1) { rpmlog(RPMLOG_WARNING, _("%s already contains identical signature, skipping\n"), rpm); /* Identical signature is not an error */ res = 0; } goto exit; } res = -1; } /* Try to make new signature smaller to have size of original signature */ rpmtdReset(&utd); if (headerGet(sigh, RPMSIGTAG_RESERVEDSPACE, &utd, HEADERGET_MINMEM)) { int diff; int count; char *reservedSpace = NULL; count = utd.count; diff = headerSizeof(sigh, HEADER_MAGIC_YES) - origSigSize; if (diff < count) { reservedSpace = xcalloc(count - diff, sizeof(char)); headerDel(sigh, RPMSIGTAG_RESERVEDSPACE); rpmtdReset(&utd); utd.tag = RPMSIGTAG_RESERVEDSPACE; utd.count = count - diff; utd.type = RPM_BIN_TYPE; utd.data = reservedSpace; headerPut(sigh, &utd, HEADERPUT_DEFAULT); free(reservedSpace); insSig = 1; } } /* Reallocate the signature into one contiguous region. */ sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES); if (sigh == NULL) /* XXX can't happen */ goto exit; if (insSig) { /* Insert new signature into original rpm */ if (Fseek(fd, sigStart, SEEK_SET) < 0) { rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"), rpm, Fstrerror(fd)); goto exit; } if (rpmWriteSignature(fd, sigh)) { rpmlog(RPMLOG_ERR, _("%s: rpmWriteSignature failed: %s\n"), rpm, Fstrerror(fd)); goto exit; } res = 0; } else { /* Replace orignal rpm with new rpm containing new signature */ rasprintf(&trpm, "%s.XXXXXX", rpm); ofd = rpmMkTemp(trpm); if (ofd == NULL || Ferror(ofd)) { rpmlog(RPMLOG_ERR, _("rpmMkTemp failed\n")); goto exit; } /* Write the lead/signature of the output rpm */ rc = rpmLeadWrite(ofd, h); if (rc != RPMRC_OK) { rpmlog(RPMLOG_ERR, _("%s: writeLead failed: %s\n"), trpm, Fstrerror(ofd)); goto exit; } if (rpmWriteSignature(ofd, sigh)) { rpmlog(RPMLOG_ERR, _("%s: rpmWriteSignature failed: %s\n"), trpm, Fstrerror(ofd)); goto exit; } if (Fseek(fd, headerStart, SEEK_SET) < 0) { rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"), rpm, Fstrerror(fd)); goto exit; } /* Append the header and archive from the temp file */ if (copyFile(&fd, rpm, &ofd, trpm) == 0) { struct stat st; /* Move final target into place, restore file permissions. */ if (stat(rpm, &st) == 0 && unlink(rpm) == 0 && rename(trpm, rpm) == 0 && chmod(rpm, st.st_mode) == 0) { res = 0; } else { rpmlog(RPMLOG_ERR, _("replacing %s failed: %s\n"), rpm, strerror(errno)); } } } exit: if (fd) (void) closeFile(&fd); if (ofd) (void) closeFile(&ofd); headerFree(sigh); headerFree(h); free(msg); /* Clean up intermediate target */ if (trpm) { (void) unlink(trpm); free(trpm); } return res; }
rpmRC rpmpkgRead(rpmKeyring keyring, rpmVSFlags flags, FD_t fd, rpmsinfoCb cb, void *cbdata, Header *hdrp) { char * msg = NULL; rpmRC xx, rc = RPMRC_FAIL; /* assume failure */ int failed = 0; int leadtype = -1; struct hdrblob_s sigblob, blob; struct rpmvs_s *sigset = NULL; Header h = NULL; Header sigh = NULL; rpmDigestBundle bundle = fdGetBundle(fd, 1); /* freed with fd */ memset(&blob, 0, sizeof(blob)); memset(&sigblob, 0, sizeof(sigblob)); if ((xx = rpmLeadRead(fd, &leadtype, &msg)) != RPMRC_OK) { /* Avoid message spew on manifests */ if (xx == RPMRC_NOTFOUND) msg = _free(msg); rc = xx; goto exit; } /* Read the signature header. Might not be in a contiguous region. */ if (hdrblobRead(fd, 1, 0, RPMTAG_HEADERSIGNATURES, &sigblob, &msg)) goto exit; sigset = rpmvsCreate(&sigblob, flags); /* Initialize digests ranging over the header */ rpmvsInitDigests(sigset, RPMSIG_HEADER, bundle); /* Read the header from the package. */ if (hdrblobRead(fd, 1, 1, RPMTAG_HEADERIMMUTABLE, &blob, &msg)) goto exit; /* Fish interesting tags from the main header. This is a bit hacky... */ if (!(flags & (RPMVSF_NOPAYLOAD|RPMVSF_NEEDPAYLOAD))) rpmvsAppend(sigset, &blob, RPMTAG_PAYLOADDIGEST); /* Initialize digests ranging over the payload only */ rpmvsInitDigests(sigset, RPMSIG_PAYLOAD, bundle); /* Verify header signatures and digests */ failed += rpmvsVerifyItems(sigset, (RPMSIG_HEADER), bundle, keyring, cb, cbdata); /* Unless disabled, read the file, generating digest(s) on the fly. */ if (!(flags & RPMVSF_NEEDPAYLOAD)) { if (readFile(fd, &msg)) goto exit; } /* Verify signatures and digests ranging over the payload */ failed += rpmvsVerifyItems(sigset, (RPMSIG_PAYLOAD), bundle, keyring, cb, cbdata); failed += rpmvsVerifyItems(sigset, (RPMSIG_HEADER|RPMSIG_PAYLOAD), bundle, keyring, cb, cbdata); if (failed == 0) { /* Finally import the headers and do whatever required retrofits etc */ if (hdrp) { if (hdrblobImport(&sigblob, 0, &sigh, &msg)) goto exit; if (hdrblobImport(&blob, 0, &h, &msg)) goto exit; /* Append (and remap) signature tags to the metadata. */ headerMergeLegacySigs(h, sigh); applyRetrofits(h, leadtype); /* Bump reference count for return. */ *hdrp = headerLink(h); } rc = RPMRC_OK; } exit: if (rc && msg != NULL) rpmlog(RPMLOG_ERR, "%s: %s\n", Fdescr(fd), msg); free(msg); free(sigblob.ei); free(blob.ei); headerFree(h); headerFree(sigh); rpmvsFree(sigset); return rc; }
static rpmRC rpmpkgRead(rpmKeyring keyring, rpmVSFlags vsflags, FD_t fd, Header * hdrp, unsigned int *keyidp, char **msg) { pgpDigParams sig = NULL; Header sigh = NULL; rpmTagVal sigtag; struct rpmtd_s sigtd; struct sigtInfo_s sinfo; Header h = NULL; rpmRC rc = RPMRC_FAIL; /* assume failure */ int leadtype = -1; headerGetFlags hgeflags = HEADERGET_DEFAULT; if (hdrp) *hdrp = NULL; rpmtdReset(&sigtd); if ((rc = rpmLeadRead(fd, &leadtype, msg)) != RPMRC_OK) { /* Avoid message spew on manifests */ if (rc == RPMRC_NOTFOUND) { *msg = _free(*msg); } goto exit; } /* Read the signature header. */ rc = rpmReadSignature(fd, &sigh, msg); if (rc != RPMRC_OK) { goto exit; } #define _chk(_mask, _tag) \ (sigtag == 0 && !(vsflags & (_mask)) && headerIsEntry(sigh, (_tag))) /* * Figger the most effective means of verification available, prefer * signatures over digests. Legacy header+payload entries are not used. * DSA will be preferred over RSA if both exist because tested first. */ sigtag = 0; if (_chk(RPMVSF_NODSAHEADER, RPMSIGTAG_DSA)) { sigtag = RPMSIGTAG_DSA; } else if (_chk(RPMVSF_NORSAHEADER, RPMSIGTAG_RSA)) { sigtag = RPMSIGTAG_RSA; } else if (_chk(RPMVSF_NOSHA1HEADER, RPMSIGTAG_SHA1)) { sigtag = RPMSIGTAG_SHA1; } /* Read the metadata, computing digest(s) on the fly. */ h = NULL; rc = rpmpkgReadHeader(fd, &h, msg); if (rc != RPMRC_OK || h == NULL) { goto exit; } /* Any digests or signatures to check? */ if (sigtag == 0) { rc = RPMRC_OK; goto exit; } /* Free up any previous "ok" message before signature/digest check */ *msg = _free(*msg); /* Retrieve the tag parameters from the signature header. */ if (!headerGet(sigh, sigtag, &sigtd, hgeflags)) { rc = RPMRC_FAIL; goto exit; } if (rpmSigInfoParse(&sigtd, "package", &sinfo, &sig, msg) == RPMRC_OK) { struct rpmtd_s utd; DIGEST_CTX ctx = rpmDigestInit(sinfo.hashalgo, RPMDIGEST_NONE); if (headerGet(h, RPMTAG_HEADERIMMUTABLE, &utd, hgeflags)) { rpmDigestUpdate(ctx, rpm_header_magic, sizeof(rpm_header_magic)); rpmDigestUpdate(ctx, utd.data, utd.count); rpmtdFreeData(&utd); } /** @todo Implement disable/enable/warn/error/anal policy. */ rc = rpmVerifySignature(keyring, &sigtd, sig, ctx, msg); rpmDigestFinal(ctx, NULL, NULL, 0); } else { rc = RPMRC_FAIL; } exit: if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) { /* Retrofit RPMTAG_SOURCEPACKAGE to srpms for compatibility */ if (leadtype == RPMLEAD_SOURCE && headerIsSource(h)) { if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE)) { uint32_t one = 1; headerPutUint32(h, RPMTAG_SOURCEPACKAGE, &one, 1); } } /* * Try to make sure binary rpms have RPMTAG_SOURCERPM set as that's * what we use for differentiating binary vs source elsewhere. */ if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE) && headerIsSource(h)) { headerPutString(h, RPMTAG_SOURCERPM, "(none)"); } /* * Convert legacy headers on the fly. Not having immutable region * equals a truly ancient package, do full retrofit. OTOH newer * packages might have been built with --nodirtokens, test and handle * the non-compressed filelist case separately. */ if (!headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) headerConvert(h, HEADERCONV_RETROFIT_V3); else if (headerIsEntry(h, RPMTAG_OLDFILENAMES)) headerConvert(h, HEADERCONV_COMPRESSFILELIST); /* Append (and remap) signature tags to the metadata. */ headerMergeLegacySigs(h, sigh); /* Bump reference count for return. */ *hdrp = headerLink(h); if (keyidp) *keyidp = getKeyid(sig); } rpmtdFreeData(&sigtd); h = headerFree(h); pgpDigParamsFree(sig); sigh = headerFree(sigh); return rc; }
static rpmRC rpmpkgRead(rpmKeyring keyring, rpmVSFlags vsflags, FD_t fd, const char * fn, Header * hdrp) { pgpDig dig = NULL; char buf[8*BUFSIZ]; ssize_t count; rpmlead l = NULL; Header sigh = NULL; rpmSigTag sigtag; struct rpmtd_s sigtd; Header h = NULL; char * msg; rpmRC rc = RPMRC_FAIL; /* assume failure */ int leadtype = -1; headerGetFlags hgeflags = HEADERGET_DEFAULT; DIGEST_CTX ctx = NULL; if (hdrp) *hdrp = NULL; rpmtdReset(&sigtd); l = rpmLeadNew(); if ((rc = rpmLeadRead(fd, l)) == RPMRC_OK) { const char * err = NULL; if ((rc = rpmLeadCheck(l, &err)) == RPMRC_FAIL) { rpmlog(RPMLOG_ERR, "%s: %s\n", fn, err); } leadtype = rpmLeadType(l); } l = rpmLeadFree(l); if (rc != RPMRC_OK) goto exit; /* Read the signature header. */ msg = NULL; rc = rpmReadSignature(fd, &sigh, RPMSIGTYPE_HEADERSIG, &msg); switch (rc) { default: rpmlog(RPMLOG_ERR, _("%s: rpmReadSignature failed: %s"), fn, (msg && *msg ? msg : "\n")); msg = _free(msg); goto exit; break; case RPMRC_OK: if (sigh == NULL) { rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), fn); rc = RPMRC_FAIL; goto exit; } break; } msg = _free(msg); #define _chk(_mask, _tag) \ (sigtag == 0 && !(vsflags & (_mask)) && headerIsEntry(sigh, (_tag))) /* * Figger the most effective available signature. * Prefer signatures over digests, then header-only over header+payload. * DSA will be preferred over RSA if both exist because tested first. * Note that NEEDPAYLOAD prevents header+payload signatures and digests. */ sigtag = 0; if (_chk(RPMVSF_NODSAHEADER, RPMSIGTAG_DSA)) { sigtag = RPMSIGTAG_DSA; } else if (_chk(RPMVSF_NORSAHEADER, RPMSIGTAG_RSA)) { sigtag = RPMSIGTAG_RSA; } else if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD, RPMSIGTAG_GPG)) { sigtag = RPMSIGTAG_GPG; fdInitDigest(fd, PGPHASHALGO_SHA1, 0); } else if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD, RPMSIGTAG_PGP)) { sigtag = RPMSIGTAG_PGP; fdInitDigest(fd, PGPHASHALGO_MD5, 0); } else if (_chk(RPMVSF_NOSHA1HEADER, RPMSIGTAG_SHA1)) { sigtag = RPMSIGTAG_SHA1; } else if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD, RPMSIGTAG_MD5)) { sigtag = RPMSIGTAG_MD5; fdInitDigest(fd, PGPHASHALGO_MD5, 0); } /* Read the metadata, computing digest(s) on the fly. */ h = NULL; msg = NULL; rc = rpmpkgReadHeader(keyring, vsflags, fd, &h, &msg); if (rc != RPMRC_OK || h == NULL) { rpmlog(RPMLOG_ERR, _("%s: headerRead failed: %s"), fn, (msg && *msg ? msg : "\n")); msg = _free(msg); goto exit; } msg = _free(msg); /* Any digests or signatures to check? */ if (sigtag == 0) { rc = RPMRC_OK; goto exit; } dig = pgpNewDig(); if (dig == NULL) { rc = RPMRC_FAIL; goto exit; } /* Retrieve the tag parameters from the signature header. */ if (!headerGet(sigh, sigtag, &sigtd, hgeflags)) { rc = RPMRC_FAIL; goto exit; } switch (sigtag) { case RPMSIGTAG_RSA: case RPMSIGTAG_DSA: if ((rc = parsePGP(&sigtd, "package", dig)) != RPMRC_OK) { goto exit; } /* fallthrough */ case RPMSIGTAG_SHA1: { struct rpmtd_s utd; pgpHashAlgo hashalgo = (sigtag == RPMSIGTAG_SHA1) ? PGPHASHALGO_SHA1 : dig->signature.hash_algo; if (!headerGet(h, RPMTAG_HEADERIMMUTABLE, &utd, hgeflags)) break; ctx = rpmDigestInit(hashalgo, RPMDIGEST_NONE); (void) rpmDigestUpdate(ctx, rpm_header_magic, sizeof(rpm_header_magic)); (void) rpmDigestUpdate(ctx, utd.data, utd.count); rpmtdFreeData(&utd); } break; case RPMSIGTAG_GPG: case RPMSIGTAG_PGP5: /* XXX legacy */ case RPMSIGTAG_PGP: if ((rc = parsePGP(&sigtd, "package", dig)) != RPMRC_OK) { goto exit; } /* fallthrough */ case RPMSIGTAG_MD5: /* Legacy signatures need the compressed payload in the digest too. */ while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0) {} if (count < 0) { rpmlog(RPMLOG_ERR, _("%s: Fread failed: %s\n"), fn, Fstrerror(fd)); rc = RPMRC_FAIL; goto exit; } ctx = rpmDigestBundleDupCtx(fdGetBundle(fd), (sigtag == RPMSIGTAG_MD5) ? PGPHASHALGO_MD5 : dig->signature.hash_algo); break; default: break; } /** @todo Implement disable/enable/warn/error/anal policy. */ rc = rpmVerifySignature(keyring, &sigtd, dig, ctx, &msg); switch (rc) { case RPMRC_OK: /* Signature is OK. */ rpmlog(RPMLOG_DEBUG, "%s: %s", fn, msg); break; case RPMRC_NOTTRUSTED: /* Signature is OK, but key is not trusted. */ case RPMRC_NOKEY: /* Public key is unavailable. */ /* XXX Print NOKEY/NOTTRUSTED warning only once. */ { int lvl = (stashKeyid(dig) ? RPMLOG_DEBUG : RPMLOG_WARNING); rpmlog(lvl, "%s: %s", fn, msg); } break; case RPMRC_NOTFOUND: /* Signature is unknown type. */ rpmlog(RPMLOG_WARNING, "%s: %s", fn, msg); break; default: case RPMRC_FAIL: /* Signature does not verify. */ rpmlog(RPMLOG_ERR, "%s: %s", fn, msg); break; } free(msg); exit: if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) { /* Retrofit RPMTAG_SOURCEPACKAGE to srpms for compatibility */ if (leadtype == RPMLEAD_SOURCE && headerIsSource(h)) { if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE)) { uint32_t one = 1; headerPutUint32(h, RPMTAG_SOURCEPACKAGE, &one, 1); } } /* * Try to make sure binary rpms have RPMTAG_SOURCERPM set as that's * what we use for differentiating binary vs source elsewhere. */ if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE) && headerIsSource(h)) { headerPutString(h, RPMTAG_SOURCERPM, "(none)"); } /* * Convert legacy headers on the fly. Not having "new" style compressed * filenames is close enough estimate for legacy indication... */ if (!headerIsEntry(h, RPMTAG_DIRNAMES)) { headerConvert(h, HEADERCONV_RETROFIT_V3); } /* Append (and remap) signature tags to the metadata. */ headerMergeLegacySigs(h, sigh); /* Bump reference count for return. */ *hdrp = headerLink(h); } rpmtdFreeData(&sigtd); rpmDigestFinal(ctx, NULL, NULL, 0); h = headerFree(h); pgpFreeDig(dig); sigh = rpmFreeSignature(sigh); return rc; }