static rpmRC fdConsume(FD_t fd, off_t start, off_t nbytes) { size_t bufsiz = 32*BUFSIZ; unsigned char buf[bufsiz]; off_t left = nbytes; ssize_t nb; if (start && fdJump(fd, start)) return RPMRC_FAIL; while (left > 0) { nb = Fread(buf, 1, (left < bufsiz) ? left : bufsiz, fd); if (nb > 0) left -= nb; else break; }; if (left) { rpmlog(RPMLOG_ERR, _("Failed to read %jd bytes in file %s: %s\n"), (intmax_t) nbytes, Fdescr(fd), Fstrerror(fd)); } return (left == 0) ? RPMRC_OK : RPMRC_FAIL; }
static rpmRC fdJump(FD_t fd, off_t offset) { if (Fseek(fd, offset, SEEK_SET) < 0) { rpmlog(RPMLOG_ERR, _("Could not seek in file %s: %s\n"), Fdescr(fd), Fstrerror(fd)); return RPMRC_FAIL; } return RPMRC_OK; }
rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp) { rpmRC rc; rpmVSFlags vsflags = rpmtsVSFlags(ts); rpmKeyring keyring = rpmtsGetKeyring(ts, 1); unsigned int keyid = 0; char *msg = NULL; if (fn == NULL) fn = Fdescr(fd); rc = rpmpkgRead(keyring, vsflags, fd, hdrp, &keyid, &msg); switch (rc) { case RPMRC_OK: /* Signature is OK. */ rpmlog(RPMLOG_DEBUG, "%s: %s\n", 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(keyid) ? RPMLOG_DEBUG : RPMLOG_WARNING); rpmlog(lvl, "%s: %s\n", fn, msg); } break; case RPMRC_NOTFOUND: /* Signature is unknown type or manifest. */ /* msg == NULL is probably a manifest */ if (msg) rpmlog(RPMLOG_WARNING, "%s: %s\n", fn, msg); break; default: case RPMRC_FAIL: /* Signature does not verify. */ rpmlog(RPMLOG_ERR, "%s: %s\n", fn, msg); break; } rpmKeyringFree(keyring); free(msg); return rc; }
static rpmRC writeHdr(FD_t fd, Header pkgh) { /* Reallocate the header into one contiguous region for writing. */ Header h = headerReload(headerCopy(pkgh), RPMTAG_HEADERIMMUTABLE); rpmRC rc = RPMRC_FAIL; if (h == NULL) { rpmlog(RPMLOG_ERR,_("Unable to create immutable header region\n")); goto exit; } if (headerWrite(fd, h, HEADER_MAGIC_YES)) { rpmlog(RPMLOG_ERR, _("Unable to write header to %s: %s\n"), Fdescr(fd), Fstrerror(fd)); goto exit; } (void) Fflush(fd); rc = RPMRC_OK; exit: headerFree(h); return rc; }
static PyObject *rpmfd_get_name(rpmfdObject *s) { /* XXX: rpm returns non-paths with [mumble], python files use <mumble> */ return Py_BuildValue("s", Fdescr(s->fd)); }
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, const char * fn, Header * hdrp) { pgpDigParams sig = NULL; char buf[8*BUFSIZ]; ssize_t count; Header sigh = NULL; rpmTagVal sigtag; struct rpmtd_s sigtd; Header h = NULL; char * msg = NULL; rpmRC rc = RPMRC_FAIL; /* assume failure */ int leadtype = -1; headerGetFlags hgeflags = HEADERGET_DEFAULT; DIGEST_CTX ctx = NULL; if (hdrp) *hdrp = NULL; if (fn == NULL) fn = Fdescr(fd); rpmtdReset(&sigtd); if ((rc = rpmLeadRead(fd, NULL, &leadtype, &msg)) != RPMRC_OK) { /* Avoid message spew on manifests */ if (rc != RPMRC_NOTFOUND) rpmlog(RPMLOG_ERR, "%s: %s\n", fn, msg); free(msg); goto exit; } /* Read the signature header. */ 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; } /* 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 (parsePGPSig(&sigtd, "package", fn, &sig)) goto exit; /* fallthrough */ case RPMSIGTAG_SHA1: { struct rpmtd_s utd; unsigned int hashalgo = (sigtag == RPMSIGTAG_SHA1) ? PGPHASHALGO_SHA1 : pgpDigParamsAlgo(sig, PGPVAL_HASHALGO); 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 (parsePGPSig(&sigtd, "package", fn, &sig)) 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 : pgpDigParamsAlgo(sig, PGPVAL_HASHALGO)); break; default: break; } /** @todo Implement disable/enable/warn/error/anal policy. */ rc = rpmVerifySignature(keyring, &sigtd, sig, 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(sig) ? 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); pgpDigParamsFree(sig); sigh = rpmFreeSignature(sigh); return rc; }