static VALUE rpmmi_next(VALUE s) { rpmmi mi = rpmmi_ptr(s); Header h = rpmmiNext(mi); return (h != NULL ? rpmrb_NewHdr(headerLink(h)) : Qnil); }
rpmRC rpmReadSignature(FD_t fd, Header * sighp, char ** msg) { char *buf = NULL; struct hdrblob_s blob; Header sigh = NULL; rpmRC rc = RPMRC_FAIL; /* assume failure */ if (sighp) *sighp = NULL; if (hdrblobRead(fd, 1, 1, RPMTAG_HEADERSIGNATURES, &blob, &buf) != RPMRC_OK) goto exit; /* OK, blob looks sane, load the header. */ if (hdrblobImport(&blob, 0, &sigh, &buf) != RPMRC_OK) goto exit; printSize(fd, sigh); rc = RPMRC_OK; exit: if (sighp && sigh && rc == RPMRC_OK) *sighp = headerLink(sigh); headerFree(sigh); if (msg != NULL) { *msg = buf; } else { free(buf); } return rc; }
static PyObject * hdrUnload(hdrObject * s, PyObject * args, PyObject *keywords) { char * buf; PyObject * rc; int len, legacy = 0; Header h; static char *kwlist[] = { "legacyHeader", NULL}; if (!PyArg_ParseTupleAndKeywords(args, keywords, "|i", kwlist, &legacy)) return NULL; h = headerLink(s->h); /* XXX this legacy switch is a hack, needs to be removed. */ if (legacy) { h = headerCopy(s->h); /* XXX strip region tags, etc */ headerFree(s->h); } len = headerSizeof(h, HEADER_MAGIC_NO); buf = headerUnload(h); h = headerFree(h); if (buf == NULL || len == 0) { PyErr_SetString(pyrpmError, "can't unload bad header\n"); return NULL; } rc = PyBytes_FromStringAndSize(buf, len); buf = _free(buf); return rc; }
static rpmRC rpmpkgReadHeader(FD_t fd, Header *hdrp, char ** msg) { char *buf = NULL; struct hdrblob_s blob; Header h = NULL; rpmRC rc = RPMRC_FAIL; /* assume failure */ if (hdrp) *hdrp = NULL; if (msg) *msg = NULL; if (hdrblobRead(fd, 1, 1, RPMTAG_HEADERIMMUTABLE, &blob, &buf) != RPMRC_OK) goto exit; /* OK, blob looks sane, load the header. */ rc = hdrblobImport(&blob, 0, &h, &buf); exit: if (hdrp && h && rc == RPMRC_OK) *hdrp = headerLink(h); headerFree(h); if (msg != NULL && *msg == NULL && buf != NULL) { *msg = buf; } else { free(buf); } return rc; }
static void unloadImmutableRegion(Header *hdrp, rpmTagVal tag) { struct rpmtd_s copytd, td; rpmtd utd = &td; Header nh; Header oh; HeaderIterator hi; if (headerGet(*hdrp, tag, utd, HEADERGET_DEFAULT)) { nh = headerNew(); oh = headerCopyLoad(utd->data); hi = headerInitIterator(oh); while (headerNext(hi, ©td)) { if (copytd.data) headerPut(nh, ©td, HEADERPUT_DEFAULT); rpmtdFreeData(©td); } headerFreeIterator(hi); headerFree(oh); rpmtdFreeData(utd); headerFree(*hdrp); *hdrp = headerLink(nh); headerFree(nh); } }
PyObject * hdr_Wrap(PyTypeObject *subtype, Header h) { hdrObject * hdr = (hdrObject *)subtype->tp_alloc(subtype, 0); if (hdr == NULL) return NULL; hdr->h = headerLink(h); return (PyObject *) hdr; }
/* --- Object methods */ static VALUE rpmmi_each(VALUE s) { rpmmi mi = rpmmi_ptr(s); Header h; while((h = rpmmiNext(mi)) != NULL) rb_yield (rpmrb_NewHdr(headerLink(h))); return Qnil; }
HeaderIterator headerInitIterator(Header h) { HeaderIterator hi = xmalloc(sizeof(*hi)); headerSort(h); hi->h = headerLink(h); hi->next_index = 0; return hi; }
int Save_HR_SW_info(int ix) { SWI_t *swi = &_myswi; /* XXX static for now */ #ifdef HAVE_LIBRPM /* * XXX Watchout: ix starts with 1 */ if (1 <= ix && ix <= swi->swi_nrec && ix != swi->swi_prevx) { int offset; Header h; char *n, *v, *r; offset = swi->swi_recs[ix - 1]; { rpmdbMatchIterator mi; mi = rpmtsInitIterator(swi->swi_rpmts, RPMDBI_PACKAGES, &offset, sizeof(offset)); if ((h = rpmdbNextIterator(mi)) != NULL) h = headerLink(h); rpmdbFreeIterator(mi); } if (h == NULL) { DEBUGMSGTL(("host/hr_swinst", "RPM cache has probably expired when reading entry %d, " "reloading...\n", ix)); swi->swi_timestamp = 0; return -1; } if (swi->swi_h != NULL) headerFree(swi->swi_h); swi->swi_h = h; swi->swi_prevx = ix; headerGetEntry(swi->swi_h, RPMTAG_NAME, NULL, (void **) &n, NULL); headerGetEntry(swi->swi_h, RPMTAG_VERSION, NULL, (void **) &v, NULL); headerGetEntry(swi->swi_h, RPMTAG_RELEASE, NULL, (void **) &r, NULL); snprintf(swi->swi_name, sizeof(swi->swi_name), "%s-%s-%s", n, v, r); swi->swi_name[ sizeof(swi->swi_name)-1 ] = 0; } #else snprintf(swi->swi_name, sizeof(swi->swi_name), "%s", swi->swi_dep->d_name); swi->swi_name[ sizeof(swi->swi_name)-1 ] = 0; #endif return 0; }
rpmfi rpmfiNewPool(rpmstrPool pool, Header h, rpmTagVal tagN, rpmfiFlags flags) { rpmfi fi = xcalloc(1, sizeof(*fi)); struct rpmtd_s bn, dn, dx; fi->magic = RPMFIMAGIC; fi->i = -1; fi->fiflags = flags; /* * Grab and validate file triplet data. Headers with no files simply * fall through here and an empty file set is returned. */ if (headerGet(h, RPMTAG_BASENAMES, &bn, HEADERGET_MINMEM)) { headerGet(h, RPMTAG_DIRNAMES, &dn, HEADERGET_MINMEM); headerGet(h, RPMTAG_DIRINDEXES, &dx, HEADERGET_ALLOC); if (indexSane(&bn, &dn, &dx)) { /* private or shared pool? */ fi->pool = (pool != NULL) ? rpmstrPoolLink(pool) : rpmstrPoolCreate(); /* init the file triplet data */ fi->fc = rpmtdCount(&bn); fi->dc = rpmtdCount(&dn); fi->bnid = rpmtdToPool(&bn, fi->pool); fi->dnid = rpmtdToPool(&dn, fi->pool); /* steal index data from the td (pooh...) */ fi->dil = dx.data; dx.data = NULL; /* populate the rest of the stuff */ rpmfiPopulate(fi, h, flags); /* freeze the pool to save memory, but only if private pool */ if (fi->pool != pool) rpmstrPoolFreeze(fi->pool, 0); fi->h = (fi->fiflags & RPMFI_KEEPHEADER) ? headerLink(h) : NULL; } else { /* broken data, free and return NULL */ fi = _free(fi); } rpmtdFreeData(&bn); rpmtdFreeData(&dn); rpmtdFreeData(&dx); } return rpmfiLink(fi); }
void Save_HR_SW_info(int ix) { SWI_t *swi = &_myswi; /* XXX static for now */ #ifdef HAVE_LIBRPM /* * XXX Watchout: ix starts with 1 */ if (1 <= ix && ix <= swi->swi_nrec && ix != swi->swi_prevx) { int offset; Header h; char *n, *v, *r; offset = swi->swi_recs[ix - 1]; #if defined(RPMDBI_PACKAGES) { rpmdbMatchIterator mi; mi = rpmdbInitIterator(swi->swi_rpmdb, RPMDBI_PACKAGES, &offset, sizeof(offset)); if ((h = rpmdbNextIterator(mi)) != NULL) h = headerLink(h); rpmdbFreeIterator(mi); } #else h = rpmdbGetRecord(swi->swi_rpmdb, offset); #endif if (h == NULL) return; if (swi->swi_h != NULL) headerFree(swi->swi_h); swi->swi_h = h; swi->swi_prevx = ix; headerGetEntry(swi->swi_h, RPMTAG_NAME, NULL, (void **) &n, NULL); headerGetEntry(swi->swi_h, RPMTAG_VERSION, NULL, (void **) &v, NULL); headerGetEntry(swi->swi_h, RPMTAG_RELEASE, NULL, (void **) &r, NULL); snprintf(swi->swi_name, sizeof(swi->swi_name), "%s-%s-%s", n, v, r); swi->swi_name[ sizeof(swi->swi_name)-1 ] = 0; } #else snprintf(swi->swi_name, sizeof(swi->swi_name), swi->swi_dep->d_name); swi->swi_name[ sizeof(swi->swi_name)-1 ] = 0; #endif }
static void unloadImmutableRegion(Header *hdrp, rpmTagVal tag) { struct rpmtd_s td; rpmtd utd = &td; Header nh; Header oh; if (headerGet(*hdrp, tag, utd, HEADERGET_DEFAULT)) { oh = headerCopyLoad(utd->data); nh = headerCopy(oh); headerFree(oh); rpmtdFreeData(utd); headerFree(*hdrp); *hdrp = headerLink(nh); headerFree(nh); } }
Header headerNew(void) { Header h = xcalloc(1, sizeof(*h)); h->blob = NULL; h->indexAlloced = INDEX_MALLOC_SIZE; h->indexUsed = 0; h->instance = 0; h->flags |= HEADERFLAG_SORTED; h->index = (h->indexAlloced ? xcalloc(h->indexAlloced, sizeof(*h->index)) : NULL); h->nrefs = 0; return headerLink(h); }
/** * Read next header from package, lazily expanding manifests as found. * @todo An empty file read as manifest truncates argv returning RPMRC_NOTFOUND. * @todo Errors, e.g. non-existent path in manifest, will terminate iteration. * @todo Chained manifests lose an arg someplace. * @param gi generalized iterator * @return RPMRC_OK on success */ static rpmRC rpmgiLoadReadHeader(rpmgi gi) /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/ { rpmRC rpmrc = RPMRC_NOTFOUND; Header h = NULL; if (gi->argv != NULL && gi->argv[gi->i] != NULL) do { const char * fn; /* XXX gi->hdrPath? */ fn = gi->argv[gi->i]; /* XXX Skip +bing -bang =boom special arguments. */ if (strchr("-+=", *fn) == NULL && !(gi->flags & RPMGI_NOHEADER)) { h = rpmgiReadHeader(gi, fn); if (h != NULL) rpmrc = RPMRC_OK; } else rpmrc = RPMRC_OK; if (rpmrc == RPMRC_OK || gi->flags & RPMGI_NOMANIFEST) break; if (errno == ENOENT) break; /* Not a header, so try for a manifest. */ gi->argv[gi->i] = NULL; /* Mark the insertion point */ rpmrc = rpmgiLoadManifest(gi, fn); /* XXX its unclear if RPMRC_NOTFOUND should fail or continue here. */ if (rpmrc != RPMRC_OK) { gi->argv[gi->i] = fn; /* Manifest failed, restore fn */ break; } fn = _free(fn); rpmrc = RPMRC_NOTFOUND; } while (1); if (rpmrc == RPMRC_OK && h != NULL) gi->h = headerLink(h); (void)headerFree(h); h = NULL; return rpmrc; }
static Header headerCreate(void *blob, unsigned int pvlen, int32_t indexLen) { Header h = xcalloc(1, sizeof(*h)); if (blob) { h->blob = (pvlen > 0) ? memcpy(xmalloc(pvlen), blob, pvlen) : blob; h->indexAlloced = indexLen + 1; h->indexUsed = indexLen; } else { h->indexAlloced = INDEX_MALLOC_SIZE; h->indexUsed = 0; } h->instance = 0; h->sorted = HEADERSORT_NONE; h->index = (h->indexAlloced ? xcalloc(h->indexAlloced, sizeof(*h->index)) : NULL); h->nrefs = 0; return headerLink(h); }
static PyObject * hdrAsBytes(hdrObject * s, int legacy) { PyObject *res = NULL; char *buf = NULL; unsigned int len; Header h = headerLink(s->h); /* XXX this legacy switch is a hack, needs to be removed. */ if (legacy) { h = headerCopy(s->h); /* XXX strip region tags, etc */ headerFree(s->h); } buf = headerExport(h, &len); h = headerFree(h); if (buf == NULL || len == 0) { PyErr_SetString(pyrpmError, "can't unload bad header\n"); } else { res = PyBytes_FromStringAndSize(buf, len); } free(buf); return res; }
/* TODO: permit keyring check + retrofits on copy/load */ static PyObject *hdr_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds) { PyObject *obj = NULL; rpmfdObject *fdo = NULL; Header h = NULL; char *kwlist[] = { "obj", NULL }; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist, &obj)) { return NULL; } if (obj == NULL) { h = headerNew(); } else if (CAPSULE_CHECK(obj)) { h = CAPSULE_EXTRACT(obj, "rpm._C_Header"); headerLink(h); } else if (hdrObject_Check(obj)) { h = headerCopy(((hdrObject*) obj)->h); } else if (PyBytes_Check(obj)) { h = headerCopyLoad(PyBytes_AsString(obj)); } else if (rpmfdFromPyObject(obj, &fdo)) { Py_BEGIN_ALLOW_THREADS; h = headerRead(rpmfdGetFd(fdo), HEADER_MAGIC_YES); Py_END_ALLOW_THREADS; Py_XDECREF(fdo); } else { PyErr_SetString(PyExc_TypeError, "header, blob or file expected"); return NULL; } if (h == NULL) { PyErr_SetString(pyrpmError, "bad header"); return NULL; } return hdr_Wrap(subtype, h); }
static struct RpmHeaders * rpmhdrs_new (RpmOstreeRefTs *refts, const GPtrArray *patterns) { rpmdbMatchIterator iter; Header h1; GPtrArray *hs = NULL; struct RpmHeaders *ret = NULL; gsize patprefixlen = pat_fnmatch_prefix (patterns); /* iter = rpmtsInitIterator (ts, RPMTAG_NAME, "yum", 0); */ iter = rpmtsInitIterator (refts->ts, RPMDBI_PACKAGES, NULL, 0); hs = g_ptr_array_new_with_free_func (header_free_p); while ((h1 = rpmdbNextIterator (iter))) { const char* name = headerGetString (h1, RPMTAG_NAME); if (g_str_equal (name, "gpg-pubkey")) continue; /* rpmdb abstraction leak */ if (!pat_fnmatch_match (h1, name, patprefixlen, patterns)) continue; h1 = headerLink (h1); g_ptr_array_add (hs, h1); } iter = rpmdbFreeIterator (iter); g_ptr_array_sort (hs, header_cmp_p); ret = g_malloc0 (sizeof (struct RpmHeaders)); ret->refts = rpmostree_refts_ref (refts); ret->hs = hs; return ret; }
/*@null@*/ static rpmRC rpmgiWalkReadHeader(rpmgi gi) /*@globals rpmGlobalMacroContext, h_errno, internalState @*/ /*@modifies gi, rpmGlobalMacroContext, h_errno, internalState @*/ { rpmRC rpmrc = RPMRC_NOTFOUND; if (gi->ftsp != NULL) while ((gi->fts = Fts_read(gi->ftsp)) != NULL) { if (gi->walkPathFilter) rpmrc = (*gi->walkPathFilter) (gi); else rpmrc = rpmgiWalkPathFilter(gi); if (rpmrc == RPMRC_OK) break; } if (rpmrc == RPMRC_OK) { Header h = NULL; if (!(gi->flags & RPMGI_NOHEADER)) { /* XXX rpmrc = rpmgiLoadReadHeader(gi); */ if (gi->fts != NULL) /* XXX can't happen */ h = rpmgiReadHeader(gi, gi->fts->fts_path); } if (h != NULL) { gi->h = headerLink(h); (void)headerFree(h); h = NULL; /*@-noeffectuncon@*/ if (gi->stash != NULL) (void) (*gi->stash) (gi, gi->h); /*@=noeffectuncon@*/ } } return rpmrc; }
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 writeRPM(Header *hdrp, unsigned char ** pkgidp, const char *fileName, CSA_t csa, char **cookie) { FD_t fd = NULL; FD_t ifd = NULL; ssize_t count; char * sigtarget = NULL;; char * rpmio_flags = NULL; char * SHA1 = NULL; const char *s; char *buf = NULL; Header h; Header sig = NULL; int xx; rpmRC rc = RPMRC_OK; struct rpmtd_s td; rpmTagVal sizetag; rpmTagVal payloadtag; /* Transfer header reference form *hdrp to h. */ h = headerLink(*hdrp); *hdrp = headerFree(*hdrp); if (pkgidp) *pkgidp = NULL; /* Save payload information */ if (headerIsSource(h)) rpmio_flags = rpmExpand("%{?_source_payload}", NULL); else rpmio_flags = rpmExpand("%{?_binary_payload}", NULL); if (!(rpmio_flags && *rpmio_flags)) { rpmio_flags = _free(rpmio_flags); rpmio_flags = xstrdup("w9.gzdio"); } s = strchr(rpmio_flags, '.'); if (s) { const char *compr = NULL; headerPutString(h, RPMTAG_PAYLOADFORMAT, "cpio"); if (rstreq(s+1, "ufdio")) { compr = NULL; } else if (rstreq(s+1, "gzdio")) { compr = "gzip"; #if HAVE_BZLIB_H } else if (rstreq(s+1, "bzdio")) { compr = "bzip2"; /* Add prereq on rpm version that understands bzip2 payloads */ (void) rpmlibNeedsFeature(h, "PayloadIsBzip2", "3.0.5-1"); #endif #if HAVE_LZMA_H } else if (rstreq(s+1, "xzdio")) { compr = "xz"; (void) rpmlibNeedsFeature(h, "PayloadIsXz", "5.2-1"); } else if (rstreq(s+1, "lzdio")) { compr = "lzma"; (void) rpmlibNeedsFeature(h, "PayloadIsLzma", "4.4.6-1"); #endif } else { rpmlog(RPMLOG_ERR, _("Unknown payload compression: %s\n"), rpmio_flags); rc = RPMRC_FAIL; goto exit; } if (compr) headerPutString(h, RPMTAG_PAYLOADCOMPRESSOR, compr); buf = xstrdup(rpmio_flags); buf[s - rpmio_flags] = '\0'; headerPutString(h, RPMTAG_PAYLOADFLAGS, buf+1); free(buf); } /* Create and add the cookie */ if (cookie) { rasprintf(cookie, "%s %d", buildHost(), (int) (*getBuildTime())); headerPutString(h, RPMTAG_COOKIE, *cookie); } /* Reallocate the header into one contiguous region. */ h = headerReload(h, RPMTAG_HEADERIMMUTABLE); if (h == NULL) { /* XXX can't happen */ rc = RPMRC_FAIL; rpmlog(RPMLOG_ERR, _("Unable to create immutable header region.\n")); goto exit; } /* Re-reference reallocated header. */ *hdrp = headerLink(h); /* * Write the header+archive into a temp file so that the size of * archive (after compression) can be added to the header. */ fd = rpmMkTempFile(NULL, &sigtarget); if (fd == NULL || Ferror(fd)) { rc = RPMRC_FAIL; rpmlog(RPMLOG_ERR, _("Unable to open temp file.\n")); goto exit; } fdInitDigest(fd, PGPHASHALGO_SHA1, 0); if (headerWrite(fd, h, HEADER_MAGIC_YES)) { rc = RPMRC_FAIL; rpmlog(RPMLOG_ERR, _("Unable to write temp header\n")); } else { /* Write the archive and get the size */ (void) Fflush(fd); fdFiniDigest(fd, PGPHASHALGO_SHA1, (void **)&SHA1, NULL, 1); if (csa->cpioList != NULL) { rc = cpio_doio(fd, h, csa, rpmio_flags); } else if (Fileno(csa->cpioFdIn) >= 0) { rc = cpio_copy(fd, csa); } else { rc = RPMRC_FAIL; rpmlog(RPMLOG_ERR, _("Bad CSA data\n")); } } if (rc != RPMRC_OK) goto exit; (void) Fclose(fd); fd = NULL; (void) unlink(fileName); /* Generate the signature */ (void) fflush(stdout); sig = rpmNewSignature(); /* * There should be rpmlib() dependency on this, but that doesn't * really do much good as these are signature tags that get read * way before dependency checking has a chance to figure out anything. * On the positive side, not inserting the 32bit tag at all means * older rpm will just bail out with error message on attempt to read * such a package. */ if (csa->cpioArchiveSize < UINT32_MAX) { sizetag = RPMSIGTAG_SIZE; payloadtag = RPMSIGTAG_PAYLOADSIZE; } else { sizetag = RPMSIGTAG_LONGSIZE; payloadtag = RPMSIGTAG_LONGARCHIVESIZE; } (void) rpmGenDigest(sig, sigtarget, sizetag); (void) rpmGenDigest(sig, sigtarget, RPMSIGTAG_MD5); if (SHA1) { /* XXX can't use rpmtdFromFoo() on RPMSIGTAG_* items */ rpmtdReset(&td); td.tag = RPMSIGTAG_SHA1; td.type = RPM_STRING_TYPE; td.data = SHA1; td.count = 1; headerPut(sig, &td, HEADERPUT_DEFAULT); SHA1 = _free(SHA1); } { /* XXX can't use headerPutType() on legacy RPMSIGTAG_* items */ rpmtdReset(&td); td.tag = payloadtag; td.count = 1; if (payloadtag == RPMSIGTAG_PAYLOADSIZE) { rpm_off_t asize = csa->cpioArchiveSize; td.type = RPM_INT32_TYPE; td.data = &asize; headerPut(sig, &td, HEADERPUT_DEFAULT); } else { rpm_loff_t asize = csa->cpioArchiveSize; td.type = RPM_INT64_TYPE; td.data = &asize; headerPut(sig, &td, HEADERPUT_DEFAULT); } } /* Reallocate the signature into one contiguous region. */ sig = headerReload(sig, RPMTAG_HEADERSIGNATURES); if (sig == NULL) { /* XXX can't happen */ rc = RPMRC_FAIL; rpmlog(RPMLOG_ERR, _("Unable to reload signature header.\n")); goto exit; } /* Open the output file */ fd = Fopen(fileName, "w.ufdio"); if (fd == NULL || Ferror(fd)) { rc = RPMRC_FAIL; rpmlog(RPMLOG_ERR, _("Could not open %s: %s\n"), fileName, Fstrerror(fd)); goto exit; } /* Write the lead section into the package. */ { rpmlead lead = rpmLeadFromHeader(h); rc = rpmLeadWrite(fd, lead); lead = rpmLeadFree(lead); if (rc != RPMRC_OK) { rc = RPMRC_FAIL; rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"), Fstrerror(fd)); goto exit; } } /* Write the signature section into the package. */ if (rpmWriteSignature(fd, sig)) { rc = RPMRC_FAIL; goto exit; } /* Append the header and archive */ ifd = Fopen(sigtarget, "r.ufdio"); if (ifd == NULL || Ferror(ifd)) { rc = RPMRC_FAIL; rpmlog(RPMLOG_ERR, _("Unable to open sigtarget %s: %s\n"), sigtarget, Fstrerror(ifd)); goto exit; } /* Add signatures to header, and write header into the package. */ /* XXX header+payload digests/signatures might be checked again here. */ { Header nh = headerRead(ifd, HEADER_MAGIC_YES); if (nh == NULL) { rc = RPMRC_FAIL; rpmlog(RPMLOG_ERR, _("Unable to read header from %s: %s\n"), sigtarget, Fstrerror(ifd)); goto exit; } #ifdef NOTYET (void) headerMergeLegacySigs(nh, sig); #endif xx = headerWrite(fd, nh, HEADER_MAGIC_YES); nh = headerFree(nh); if (xx) { rc = RPMRC_FAIL; rpmlog(RPMLOG_ERR, _("Unable to write header to %s: %s\n"), fileName, Fstrerror(fd)); goto exit; } } /* Write the payload into the package. */ buf = xmalloc(BUFSIZ); while ((count = Fread(buf, 1, BUFSIZ, ifd)) > 0) { if (count == -1) { free(buf); rc = RPMRC_FAIL; rpmlog(RPMLOG_ERR, _("Unable to read payload from %s: %s\n"), sigtarget, Fstrerror(ifd)); goto exit; } if (Fwrite(buf, sizeof(buf[0]), count, fd) != count) { free(buf); rc = RPMRC_FAIL; rpmlog(RPMLOG_ERR, _("Unable to write payload to %s: %s\n"), fileName, Fstrerror(fd)); goto exit; } } free(buf); rc = RPMRC_OK; exit: rpmio_flags = _free(rpmio_flags); SHA1 = _free(SHA1); h = headerFree(h); /* XXX Fish the pkgid out of the signature header. */ if (sig != NULL && pkgidp != NULL) { struct rpmtd_s md5tag; headerGet(sig, RPMSIGTAG_MD5, &md5tag, HEADERGET_DEFAULT); if (rpmtdType(&md5tag) == RPM_BIN_TYPE && md5tag.count == 16 && md5tag.data != NULL) { *pkgidp = md5tag.data; } } sig = rpmFreeSignature(sig); if (ifd) { (void) Fclose(ifd); ifd = NULL; } if (fd) { (void) Fclose(fd); fd = NULL; } if (sigtarget) { (void) unlink(sigtarget); sigtarget = _free(sigtarget); } if (rc == RPMRC_OK) rpmlog(RPMLOG_NOTICE, _("Wrote: %s\n"), fileName); else (void) unlink(fileName); return rc; }
Header headerLoad(void * uh) { int32_t * ei = (int32_t *) uh; int32_t il = ntohl(ei[0]); /* index length */ int32_t dl = ntohl(ei[1]); /* data length */ size_t pvlen = sizeof(il) + sizeof(dl) + (il * sizeof(struct entryInfo_s)) + dl; void * pv = uh; Header h = NULL; entryInfo pe; unsigned char * dataStart; unsigned char * dataEnd; indexEntry entry; int rdlen; /* Sanity checks on header intro. */ if (hdrchkTags(il) || hdrchkData(dl)) goto errxit; ei = (int32_t *) pv; pe = (entryInfo) &ei[2]; dataStart = (unsigned char *) (pe + il); dataEnd = dataStart + dl; h = xcalloc(1, sizeof(*h)); h->blob = uh; h->indexAlloced = il + 1; h->indexUsed = il; h->instance = 0; h->index = xcalloc(h->indexAlloced, sizeof(*h->index)); h->flags |= HEADERFLAG_SORTED; h->nrefs = 0; h = headerLink(h); entry = h->index; if (!(htonl(pe->tag) < HEADER_I18NTABLE)) { h->flags |= HEADERFLAG_LEGACY; entry->info.type = REGION_TAG_TYPE; entry->info.tag = HEADER_IMAGE; entry->info.count = REGION_TAG_COUNT; entry->info.offset = ((unsigned char *)pe - dataStart); /* negative offset */ entry->data = pe; entry->length = pvlen - sizeof(il) - sizeof(dl); rdlen = regionSwab(entry+1, il, 0, pe, dataStart, dataEnd, entry->info.offset); if (rdlen != dl) goto errxit; entry->rdlen = rdlen; h->indexUsed++; } else { int32_t rdl; int32_t ril; h->flags &= ~HEADERFLAG_LEGACY; entry->info.type = htonl(pe->type); entry->info.count = htonl(pe->count); if (hdrchkType(entry->info.type)) goto errxit; if (hdrchkTags(entry->info.count)) goto errxit; { int off = ntohl(pe->offset); if (hdrchkData(off)) goto errxit; if (off) { size_t nb = REGION_TAG_COUNT; int32_t stei[nb]; /* XXX Hmm, why the copy? */ memcpy(&stei, dataStart + off, nb); rdl = -ntohl(stei[2]); /* negative offset */ ril = rdl/sizeof(*pe); if (hdrchkTags(ril) || hdrchkData(rdl)) goto errxit; entry->info.tag = htonl(pe->tag); } else { ril = il; rdl = (ril * sizeof(struct entryInfo_s)); entry->info.tag = HEADER_IMAGE; } } entry->info.offset = -rdl; /* negative offset */ entry->data = pe; entry->length = pvlen - sizeof(il) - sizeof(dl); rdlen = regionSwab(entry+1, ril-1, 0, pe+1, dataStart, dataEnd, entry->info.offset); if (rdlen < 0) goto errxit; entry->rdlen = rdlen; if (ril < h->indexUsed) { indexEntry newEntry = entry + ril; int ne = (h->indexUsed - ril); int rid = entry->info.offset+1; int rc; /* Load dribble entries from region. */ rc = regionSwab(newEntry, ne, 0, pe+ril, dataStart, dataEnd, rid); if (rc < 0) goto errxit; rdlen += rc; { indexEntry firstEntry = newEntry; int save = h->indexUsed; int j; /* Dribble entries replace duplicate region entries. */ h->indexUsed -= ne; for (j = 0; j < ne; j++, newEntry++) { (void) headerDel(h, newEntry->info.tag); if (newEntry->info.tag == RPMTAG_BASENAMES) (void) headerDel(h, RPMTAG_OLDFILENAMES); } /* If any duplicate entries were replaced, move new entries down. */ if (h->indexUsed < (save - ne)) { memmove(h->index + h->indexUsed, firstEntry, (ne * sizeof(*entry))); } h->indexUsed += ne; } } } h->flags &= ~HEADERFLAG_SORTED; headerSort(h); h->flags |= HEADERFLAG_ALLOCATED; return h; errxit: if (h) { h->index = _free(h->index); h = _free(h); } return h; }
static rpmRC rpmpkgReadHeader(rpmKeyring keyring, rpmVSFlags vsflags, FD_t fd, Header *hdrp, char ** msg) { char *buf = NULL; int32_t block[4]; int32_t il; int32_t dl; int32_t * ei = NULL; size_t uc; size_t nb; Header h = NULL; rpmRC rc = RPMRC_FAIL; /* assume failure */ int xx; if (hdrp) *hdrp = NULL; if (msg) *msg = NULL; memset(block, 0, sizeof(block)); if ((xx = timedRead(fd, (char *)block, sizeof(block))) != sizeof(block)) { rasprintf(&buf, _("hdr size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx); goto exit; } if (memcmp(block, rpm_header_magic, sizeof(rpm_header_magic))) { rasprintf(&buf, _("hdr magic: BAD\n")); goto exit; } il = ntohl(block[2]); if (hdrchkTags(il)) { rasprintf(&buf, _("hdr tags: BAD, no. of tags(%d) out of range\n"), il); goto exit; } dl = ntohl(block[3]); if (hdrchkData(dl)) { rasprintf(&buf, _("hdr data: BAD, no. of bytes(%d) out of range\n"), dl); goto exit; } nb = (il * sizeof(struct entryInfo_s)) + dl; uc = sizeof(il) + sizeof(dl) + nb; ei = xmalloc(uc); ei[0] = block[2]; ei[1] = block[3]; if ((xx = timedRead(fd, (char *)&ei[2], nb)) != nb) { rasprintf(&buf, _("hdr blob(%zd): BAD, read returned %d\n"), nb, xx); goto exit; } /* Sanity check header tags */ rc = headerVerify(keyring, vsflags, ei, uc, msg); if (rc != RPMRC_OK) goto exit; /* OK, blob looks sane, load the header. */ h = headerLoad(ei); if (h == NULL) { rasprintf(&buf, _("hdr load: BAD\n")); rc = RPMRC_FAIL; goto exit; } ei = NULL; /* XXX will be freed with header */ exit: if (hdrp && h && rc == RPMRC_OK) *hdrp = headerLink(h); ei = _free(ei); h = headerFree(h); if (msg != NULL && *msg == NULL && buf != NULL) { *msg = buf; } else { free(buf); } return rc; }
rpmfi rpmfiNew(const rpmts ts, Header h, rpmTag tagN, rpmfiFlags flags) { rpmfi fi = NULL; rpm_loff_t *asize = NULL; unsigned char * t; int isBuild, isSource; struct rpmtd_s fdigests, digalgo; struct rpmtd_s td; headerGetFlags scareFlags = (flags & RPMFI_KEEPHEADER) ? HEADERGET_MINMEM : HEADERGET_ALLOC; headerGetFlags defFlags = HEADERGET_ALLOC; fi = xcalloc(1, sizeof(*fi)); if (fi == NULL) /* XXX can't happen */ goto exit; fi->magic = RPMFIMAGIC; fi->i = -1; fi->fiflags = flags; fi->scareFlags = scareFlags; if (headerGet(h, RPMTAG_LONGARCHIVESIZE, &td, HEADERGET_EXT)) { asize = rpmtdGetUint64(&td); } /* 0 means unknown */ fi->archiveSize = asize ? *asize : 0; rpmtdFreeData(&td); /* Archive size is not set when this gets called from build */ isBuild = (asize == NULL); isSource = headerIsSource(h); if (isBuild) fi->fiflags |= RPMFI_ISBUILD; if (isSource) fi->fiflags |= RPMFI_ISSOURCE; _hgfi(h, RPMTAG_BASENAMES, &td, defFlags, fi->bnl); fi->fc = rpmtdCount(&td); if (fi->fc == 0) { goto exit; } _hgfi(h, RPMTAG_DIRNAMES, &td, defFlags, fi->dnl); fi->dc = rpmtdCount(&td); _hgfi(h, RPMTAG_DIRINDEXES, &td, scareFlags, fi->dil); if (!(flags & RPMFI_NOFILEMODES)) _hgfi(h, RPMTAG_FILEMODES, &td, scareFlags, fi->fmodes); if (!(flags & RPMFI_NOFILEFLAGS)) _hgfi(h, RPMTAG_FILEFLAGS, &td, scareFlags, fi->fflags); if (!(flags & RPMFI_NOFILEVERIFYFLAGS)) _hgfi(h, RPMTAG_FILEVERIFYFLAGS, &td, scareFlags, fi->vflags); if (!(flags & RPMFI_NOFILESIZES)) _hgfi(h, RPMTAG_FILESIZES, &td, scareFlags, fi->fsizes); if (!(flags & RPMFI_NOFILECOLORS)) _hgfi(h, RPMTAG_FILECOLORS, &td, scareFlags, fi->fcolors); if (!(flags & RPMFI_NOFILECLASS)) { _hgfi(h, RPMTAG_CLASSDICT, &td, scareFlags, fi->cdict); fi->ncdict = rpmtdCount(&td); _hgfi(h, RPMTAG_FILECLASS, &td, scareFlags, fi->fcdictx); } if (!(flags & RPMFI_NOFILEDEPS)) { _hgfi(h, RPMTAG_DEPENDSDICT, &td, scareFlags, fi->ddict); fi->nddict = rpmtdCount(&td); _hgfi(h, RPMTAG_FILEDEPENDSX, &td, scareFlags, fi->fddictx); _hgfi(h, RPMTAG_FILEDEPENDSN, &td, scareFlags, fi->fddictn); } if (!(flags & RPMFI_NOFILESTATES)) _hgfi(h, RPMTAG_FILESTATES, &td, defFlags, fi->fstates); if (!(flags & RPMFI_NOFILECAPS) && headerIsEntry(h, RPMTAG_FILECAPS)) { fi->fcapcache = strcacheNew(); fi->fcaps = cacheTag(fi->fcapcache, h, RPMTAG_FILECAPS); } if (!(flags & RPMFI_NOFILELINKTOS)) { fi->flinkcache = strcacheNew(); fi->flinks = cacheTag(fi->flinkcache, h, RPMTAG_FILELINKTOS); } /* FILELANGS are only interesting when installing */ if ((headerGetInstance(h) == 0) && !(flags & RPMFI_NOFILELANGS)) fi->flangs = cacheTag(langcache, h, RPMTAG_FILELANGS); /* See if the package has non-md5 file digests */ fi->digestalgo = PGPHASHALGO_MD5; if (headerGet(h, RPMTAG_FILEDIGESTALGO, &digalgo, HEADERGET_MINMEM)) { pgpHashAlgo *algo = rpmtdGetUint32(&digalgo); /* Hmm, what to do with unknown digest algorithms? */ if (algo && rpmDigestLength(*algo) != 0) { fi->digestalgo = *algo; } } fi->digests = NULL; /* grab hex digests from header and store in binary format */ if (!(flags & RPMFI_NOFILEDIGESTS) && headerGet(h, RPMTAG_FILEDIGESTS, &fdigests, HEADERGET_MINMEM)) { const char *fdigest; size_t diglen = rpmDigestLength(fi->digestalgo); fi->digests = t = xmalloc(rpmtdCount(&fdigests) * diglen); while ((fdigest = rpmtdNextString(&fdigests))) { if (!(fdigest && *fdigest != '\0')) { memset(t, 0, diglen); t += diglen; continue; } for (int j = 0; j < diglen; j++, t++, fdigest += 2) *t = (rnibble(fdigest[0]) << 4) | rnibble(fdigest[1]); } rpmtdFreeData(&fdigests); } /* XXX TR_REMOVED doesn;t need fmtimes, frdevs, finodes */ if (!(flags & RPMFI_NOFILEMTIMES)) _hgfi(h, RPMTAG_FILEMTIMES, &td, scareFlags, fi->fmtimes); if (!(flags & RPMFI_NOFILERDEVS)) _hgfi(h, RPMTAG_FILERDEVS, &td, scareFlags, fi->frdevs); if (!(flags & RPMFI_NOFILEINODES)) _hgfi(h, RPMTAG_FILEINODES, &td, scareFlags, fi->finodes); if (!(flags & RPMFI_NOFILEUSER)) fi->fuser = cacheTag(ugcache, h, RPMTAG_FILEUSERNAME); if (!(flags & RPMFI_NOFILEGROUP)) fi->fgroup = cacheTag(ugcache, h, RPMTAG_FILEGROUPNAME); /* lazily alloced from rpmfiFN() */ fi->fn = NULL; exit: if (_rpmfi_debug < 0) fprintf(stderr, "*** fi %p\t[%d]\n", fi, (fi ? fi->fc : 0)); if (fi != NULL) { fi->h = (fi->fiflags & RPMFI_KEEPHEADER) ? headerLink(h) : NULL; } /* FIX: rpmfi null annotations */ return rpmfiLink(fi, __FUNCTION__); }
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; }
/* Check files in the transactions against the rpmdb * Lookup all files with the same basename in the rpmdb * and then check for matching finger prints * @param ts transaction set * @param fpc global finger print cache */ static void checkInstalledFiles(rpmts ts, uint64_t fileCount, fingerPrintCache fpc) { tsMembers tsmem = rpmtsMembers(ts); rpmte p; rpmfiles fi; rpmfs fs; int j; unsigned int fileNum; rpmdbMatchIterator mi; Header h, newheader; rpmlog(RPMLOG_DEBUG, "computing file dispositions\n"); mi = rpmFindBaseNamesInDB(ts, fileCount); /* For all installed headers with matching basename's ... */ if (mi == NULL) return; if (rpmdbGetIteratorCount(mi) == 0) { mi = rpmdbFreeIterator(mi); return; } /* Loop over all packages from the rpmdb */ h = newheader = rpmdbNextIterator(mi); while (h != NULL) { headerGetFlags hgflags = HEADERGET_MINMEM; struct rpmtd_s bnames, dnames, dindexes, ostates; fingerPrint *fpp = NULL; unsigned int installedPkg; int beingRemoved = 0; rpmfiles otherFi = NULL; rpmte *removedPkg = NULL; /* Is this package being removed? */ installedPkg = rpmdbGetIteratorOffset(mi); if (packageHashGetEntry(tsmem->removedPackages, installedPkg, &removedPkg, NULL, NULL)) { beingRemoved = 1; otherFi = rpmteFiles(removedPkg[0]); } h = headerLink(h); /* For packages being removed we can use its rpmfi to avoid all this */ if (!beingRemoved) { headerGet(h, RPMTAG_BASENAMES, &bnames, hgflags); headerGet(h, RPMTAG_DIRNAMES, &dnames, hgflags); headerGet(h, RPMTAG_DIRINDEXES, &dindexes, hgflags); headerGet(h, RPMTAG_FILESTATES, &ostates, hgflags); } /* loop over all interesting files in that package */ do { int fpIx; struct rpmffi_s * recs; int numRecs; const char * dirName; const char * baseName; /* lookup finger print for this file */ fileNum = rpmdbGetIteratorFileNum(mi); if (!beingRemoved) { rpmtdSetIndex(&bnames, fileNum); rpmtdSetIndex(&dindexes, fileNum); rpmtdSetIndex(&dnames, *rpmtdGetUint32(&dindexes)); rpmtdSetIndex(&ostates, fileNum); dirName = rpmtdGetString(&dnames); baseName = rpmtdGetString(&bnames); fpLookup(fpc, dirName, baseName, &fpp); fpIx = 0; } else { fpp = rpmfilesFps(otherFi); fpIx = fileNum; } /* search for files in the transaction with same finger print */ fpCacheGetByFp(fpc, fpp, fpIx, &recs, &numRecs); for (j = 0; j < numRecs; j++) { p = recs[j].p; fi = rpmteFiles(p); fs = rpmteGetFileStates(p); /* Determine the fate of each file. */ switch (rpmteType(p)) { case TR_ADDED: if (!otherFi) { /* XXX What to do if this fails? */ otherFi = rpmfilesNew(NULL, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER); } handleInstInstalledFile(ts, p, fi, recs[j].fileno, h, otherFi, fileNum, beingRemoved); break; case TR_REMOVED: if (!beingRemoved) { if (*rpmtdGetChar(&ostates) == RPMFILE_STATE_NORMAL) rpmfsSetAction(fs, recs[j].fileno, FA_SKIP); } break; } rpmfilesFree(fi); } newheader = rpmdbNextIterator(mi); } while (newheader==h); otherFi = rpmfilesFree(otherFi); if (!beingRemoved) { rpmtdFreeData(&ostates); rpmtdFreeData(&bnames); rpmtdFreeData(&dnames); rpmtdFreeData(&dindexes); free(fpp); } headerFree(h); h = newheader; } rpmdbFreeIterator(mi); }
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; }
/* --------------------------------------------------------------------- */ int netsnmp_swinst_arch_load( netsnmp_container *container, u_int flags) { rpmts ts; rpmdbMatchIterator mi; Header h; char *n, *v, *r, *g; int32_t *t; time_t install_time; size_t date_len; int i = 1; netsnmp_swinst_entry *entry; ts = rpmtsCreate(); rpmtsSetVSFlags( ts, (_RPMVSF_NOSIGNATURES|_RPMVSF_NODIGESTS)); mi = rpmtsInitIterator( ts, RPMDBI_PACKAGES, NULL, 0); if (mi == NULL) NETSNMP_LOGONCE((LOG_ERR, "rpmdbOpen() failed\n")); while (NULL != (h = rpmdbNextIterator( mi ))) { const u_char *dt; entry = netsnmp_swinst_entry_create( i++ ); if (NULL == entry) continue; /* error already logged by function */ CONTAINER_INSERT(container, entry); h = headerLink( h ); headerGetEntry( h, RPMTAG_NAME, NULL, (void**)&n, NULL); headerGetEntry( h, RPMTAG_VERSION, NULL, (void**)&v, NULL); headerGetEntry( h, RPMTAG_RELEASE, NULL, (void**)&r, NULL); headerGetEntry( h, RPMTAG_GROUP, NULL, (void**)&g, NULL); headerGetEntry( h, RPMTAG_INSTALLTIME, NULL, (void**)&t, NULL); entry->swName_len = snprintf( entry->swName, sizeof(entry->swName), "%s-%s-%s", n, v, r); if (entry->swName_len > sizeof(entry->swName)) entry->swName_len = sizeof(entry->swName); entry->swType = (NULL != strstr( g, "System Environment")) ? 2 /* operatingSystem */ : 4; /* application */ install_time = *t; dt = date_n_time( &install_time, &date_len ); if (date_len != 8 && date_len != 11) { snmp_log(LOG_ERR, "Bogus length from date_n_time for %s", entry->swName); entry->swDate_len = 0; } else { entry->swDate_len = date_len; memcpy(entry->swDate, dt, entry->swDate_len); } headerFree( h ); } rpmdbFreeIterator( mi ); rpmtsFree( ts ); DEBUGMSGTL(("swinst:load:arch", "loaded %d entries\n", (int)CONTAINER_SIZE(container))); return 0; }
rpmRC rpmReadSignature(FD_t fd, Header * sighp, sigType sig_type, char ** msg) { char *buf = NULL; int32_t block[4]; int32_t il; int32_t dl; int32_t * ei = NULL; entryInfo pe; unsigned int nb, uc; int32_t ril = 0; struct indexEntry_s entry; struct entryInfo_s info; unsigned char * dataStart; unsigned char * dataEnd = NULL; Header sigh = NULL; rpmRC rc = RPMRC_FAIL; /* assume failure */ int xx; int i; if (sighp) *sighp = NULL; if (sig_type != RPMSIGTYPE_HEADERSIG) goto exit; memset(block, 0, sizeof(block)); if ((xx = Fread(block, 1, sizeof(block), fd)) != sizeof(block)) { rasprintf(&buf, _("sigh size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx); goto exit; } if (memcmp(block, rpm_header_magic, sizeof(rpm_header_magic))) { rasprintf(&buf, _("sigh magic: BAD\n")); goto exit; } il = ntohl(block[2]); if (il < 0 || il > 32) { rasprintf(&buf, _("sigh tags: BAD, no. of tags(%d) out of range\n"), il); goto exit; } dl = ntohl(block[3]); if (dl < 0 || dl > 8192) { rasprintf(&buf, _("sigh data: BAD, no. of bytes(%d) out of range\n"), dl); goto exit; } memset(&entry, 0, sizeof(entry)); memset(&info, 0, sizeof(info)); nb = (il * sizeof(struct entryInfo_s)) + dl; uc = sizeof(il) + sizeof(dl) + nb; ei = xmalloc(uc); ei[0] = block[2]; ei[1] = block[3]; pe = (entryInfo) &ei[2]; dataStart = (unsigned char *) (pe + il); if ((xx = Fread(pe, 1, nb, fd)) != nb) { rasprintf(&buf, _("sigh blob(%d): BAD, read returned %d\n"), (int)nb, xx); goto exit; } /* Check (and convert) the 1st tag element. */ xx = headerVerifyInfo(1, dl, pe, &entry.info, 0); if (xx != -1) { rasprintf(&buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"), 0, entry.info.tag, entry.info.type, entry.info.offset, entry.info.count); goto exit; } /* Is there an immutable header region tag? */ if (entry.info.tag == RPMTAG_HEADERSIGNATURES) { /* Is the region tag sane? */ if (!(entry.info.type == REGION_TAG_TYPE && entry.info.count == REGION_TAG_COUNT)) { rasprintf(&buf, _("region tag: BAD, tag %d type %d offset %d count %d\n"), entry.info.tag, entry.info.type, entry.info.offset, entry.info.count); goto exit; } /* Is the trailer within the data area? */ if (entry.info.offset + REGION_TAG_COUNT > dl) { rasprintf(&buf, _("region offset: BAD, tag %d type %d offset %d count %d\n"), entry.info.tag, entry.info.type, entry.info.offset, entry.info.count); goto exit; } /* Is there an immutable header region tag trailer? */ dataEnd = dataStart + entry.info.offset; (void) memcpy(&info, dataEnd, REGION_TAG_COUNT); /* XXX Really old packages have HEADER_IMAGE, not HEADER_SIGNATURES. */ if (info.tag == htonl(RPMTAG_HEADERIMAGE)) { rpmTagVal stag = htonl(RPMTAG_HEADERSIGNATURES); info.tag = stag; memcpy(dataEnd, &stag, sizeof(stag)); } dataEnd += REGION_TAG_COUNT; xx = headerVerifyInfo(1, il * sizeof(*pe), &info, &entry.info, 1); if (xx != -1 || !((entry.info.tag == RPMTAG_HEADERSIGNATURES || entry.info.tag == RPMTAG_HEADERIMAGE) && entry.info.type == REGION_TAG_TYPE && entry.info.count == REGION_TAG_COUNT)) { rasprintf(&buf, _("region trailer: BAD, tag %d type %d offset %d count %d\n"), entry.info.tag, entry.info.type, entry.info.offset, entry.info.count); goto exit; } memset(&info, 0, sizeof(info)); /* Is the no. of tags in the region less than the total no. of tags? */ ril = entry.info.offset/sizeof(*pe); if ((entry.info.offset % sizeof(*pe)) || ril > il) { rasprintf(&buf, _("region size: BAD, ril(%d) > il(%d)\n"), ril, il); goto exit; } } /* Sanity check signature tags */ memset(&info, 0, sizeof(info)); for (i = 1; i < il; i++) { xx = headerVerifyInfo(1, dl, pe+i, &entry.info, 0); if (xx != -1) { rasprintf(&buf, _("sigh tag[%d]: BAD, tag %d type %d offset %d count %d\n"), i, entry.info.tag, entry.info.type, entry.info.offset, entry.info.count); goto exit; } } /* OK, blob looks sane, load the header. */ sigh = headerImport(ei, uc, 0); if (sigh == NULL) { rasprintf(&buf, _("sigh load: BAD\n")); goto exit; } { size_t sigSize = headerSizeof(sigh, HEADER_MAGIC_YES); size_t pad = (8 - (sigSize % 8)) % 8; /* 8-byte pad */ ssize_t trc; struct rpmtd_s sizetag; rpm_loff_t archSize = 0; /* Position at beginning of header. */ if (pad && (trc = Fread(block, 1, pad, fd)) != pad) { rasprintf(&buf, _("sigh pad(%zd): BAD, read %zd bytes\n"), pad, trc); goto exit; } /* Print package component sizes. */ if (headerGet(sigh, RPMSIGTAG_LONGSIZE, &sizetag, HEADERGET_DEFAULT)) { rpm_loff_t *tsize = rpmtdGetUint64(&sizetag); archSize = (tsize) ? *tsize : 0; } else if (headerGet(sigh, RPMSIGTAG_SIZE, &sizetag, HEADERGET_DEFAULT)) { rpm_off_t *tsize = rpmtdGetUint32(&sizetag); archSize = (tsize) ? *tsize : 0; } rpmtdFreeData(&sizetag); rc = printSize(fd, sigSize, pad, archSize); if (rc != RPMRC_OK) { rasprintf(&buf, _("sigh sigSize(%zd): BAD, fstat(2) failed\n"), sigSize); goto exit; } } ei = NULL; /* XXX will be freed with header */ exit: if (sighp && sigh && rc == RPMRC_OK) *sighp = headerLink(sigh); headerFree(sigh); free(ei); if (msg != NULL) { *msg = buf; } else { free(buf); } return rc; }
/* Check files in the transactions against the rpmdb * Lookup all files with the same basename in the rpmdb * and then check for matching finger prints * @param ts transaction set * @param fpc global finger print cache */ static void checkInstalledFiles(rpmts ts, fingerPrintCache fpc) { rpmps ps; rpmte p; rpmfi fi; rpmfs fs; rpmfi otherFi=NULL; int j; int xx; unsigned int fileNum; const char * oldDir; rpmdbMatchIterator mi; Header h, newheader; int beingRemoved; rpmlog(RPMLOG_DEBUG, "computing file dispositions\n"); mi = rpmFindBaseNamesInDB(ts); /* For all installed headers with matching basename's ... */ if (mi == NULL) return; if (rpmdbGetIteratorCount(mi) == 0) { mi = rpmdbFreeIterator(mi); return; } ps = rpmtsProblems(ts); /* Loop over all packages from the rpmdb */ h = newheader = rpmdbNextIterator(mi); while (h != NULL) { headerGetFlags hgflags = HEADERGET_MINMEM; struct rpmtd_s bnames, dnames, dindexes, ostates; fingerPrint fp; unsigned int installedPkg; /* Is this package being removed? */ installedPkg = rpmdbGetIteratorOffset(mi); beingRemoved = 0; if (ts->removedPackages != NULL) for (j = 0; j < ts->numRemovedPackages; j++) { if (ts->removedPackages[j] != installedPkg) continue; beingRemoved = 1; break; } h = headerLink(h); headerGet(h, RPMTAG_BASENAMES, &bnames, hgflags); headerGet(h, RPMTAG_DIRNAMES, &dnames, hgflags); headerGet(h, RPMTAG_DIRINDEXES, &dindexes, hgflags); headerGet(h, RPMTAG_FILESTATES, &ostates, hgflags); oldDir = NULL; /* loop over all interesting files in that package */ do { int gotRecs; struct rpmffi_s * recs; int numRecs; const char * dirName; const char * baseName; fileNum = rpmdbGetIteratorFileNum(mi); rpmtdSetIndex(&bnames, fileNum); rpmtdSetIndex(&dindexes, fileNum); rpmtdSetIndex(&dnames, *rpmtdGetUint32(&dindexes)); rpmtdSetIndex(&ostates, fileNum); dirName = rpmtdGetString(&dnames); baseName = rpmtdGetString(&bnames); /* lookup finger print for this file */ if ( dirName == oldDir) { /* directory is the same as last round */ fp.baseName = baseName; } else { fp = fpLookup(fpc, dirName, baseName, 1); oldDir = dirName; } /* search for files in the transaction with same finger print */ gotRecs = rpmFpHashGetEntry(ts->ht, &fp, &recs, &numRecs, NULL); for (j=0; (j<numRecs)&&gotRecs; j++) { p = recs[j].p; fi = rpmteFI(p); fs = rpmteGetFileStates(p); /* Determine the fate of each file. */ switch (rpmteType(p)) { case TR_ADDED: if (!otherFi) { otherFi = rpmfiNew(ts, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER); } rpmfiSetFX(fi, recs[j].fileno); rpmfiSetFX(otherFi, fileNum); xx = handleInstInstalledFile(ts, p, fi, h, otherFi, beingRemoved); break; case TR_REMOVED: if (!beingRemoved) { rpmfiSetFX(fi, recs[j].fileno); if (*rpmtdGetChar(&ostates) == RPMFILE_STATE_NORMAL) rpmfsSetAction(fs, recs[j].fileno, FA_SKIP); } break; } } newheader = rpmdbNextIterator(mi); } while (newheader==h); otherFi = rpmfiFree(otherFi); rpmtdFreeData(&ostates); rpmtdFreeData(&bnames); rpmtdFreeData(&dnames); rpmtdFreeData(&dindexes); headerFree(h); h = newheader; } mi = rpmdbFreeIterator(mi); }