static unsigned hacked_headerSizeof(Header hdr) { unsigned hdr_size; #ifdef HAVE_RPM_HEADER_MAGIC_YES hdr_size = headerSizeof(hdr, HEADER_MAGIC_NO); #else /* rpm >= 5 */ # define HEADER_MAGIC_SIZE 8 hdr_size = headerSizeof(hdr); hdr_size = hdr_size - HEADER_MAGIC_SIZE; /* XXX: hack */ #endif return hdr_size; }
/** * Print package size (debug purposes only) * @param fd package file handle * @param sigh signature header */ static void printSize(FD_t fd, Header sigh) { struct stat st; int fdno = Fileno(fd); size_t siglen = headerSizeof(sigh, HEADER_MAGIC_YES); size_t pad = (8 - (siglen % 8)) % 8; /* 8-byte pad */ struct rpmtd_s sizetag; rpm_loff_t datalen = 0; /* Print package component sizes. */ if (headerGet(sigh, RPMSIGTAG_LONGSIZE, &sizetag, HEADERGET_DEFAULT)) { rpm_loff_t *tsize = rpmtdGetUint64(&sizetag); datalen = (tsize) ? *tsize : 0; } else if (headerGet(sigh, RPMSIGTAG_SIZE, &sizetag, HEADERGET_DEFAULT)) { rpm_off_t *tsize = rpmtdGetUint32(&sizetag); datalen = (tsize) ? *tsize : 0; } rpmtdFreeData(&sizetag); rpmlog(RPMLOG_DEBUG, "Expected size: %12" PRIu64 \ " = lead(%d)+sigs(%zd)+pad(%zd)+data(%" PRIu64 ")\n", RPMLEAD_SIZE+siglen+pad+datalen, RPMLEAD_SIZE, siglen, pad, datalen); if (fstat(fdno, &st) == 0) { rpmlog(RPMLOG_DEBUG, " Actual size: %12" PRIu64 "\n", (rpm_loff_t) st.st_size); } }
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; }
int rpmWriteSignature(FD_t fd, Header sigh) { static uint8_t buf[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; int sigSize, pad; int rc; rc = headerWrite(fd, sigh, HEADER_MAGIC_YES); if (rc) return rc; sigSize = headerSizeof(sigh, HEADER_MAGIC_YES); pad = (8 - (sigSize % 8)) % 8; if (pad) { if (Fwrite(buf, sizeof(buf[0]), pad, fd) != pad) rc = 1; } rpmlog(RPMLOG_DEBUG, "Signature: size(%d)+pad(%d)\n", sigSize, pad); return rc; }
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; }
/** \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 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; struct indexEntry_s entry; unsigned char * dataStart; 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 = Freadall(fd, block, sizeof(block))) != sizeof(block)) { rasprintf(&buf, _("sigh size(%d): BAD, read returned %d"), (int)sizeof(block), xx); goto exit; } if (memcmp(block, rpm_header_magic, sizeof(rpm_header_magic))) { rasprintf(&buf, _("sigh magic: BAD")); goto exit; } il = ntohl(block[2]); if (il < 0 || il > 32) { rasprintf(&buf, _("sigh tags: BAD, no. of tags(%d) out of range"), il); goto exit; } dl = ntohl(block[3]); if (dl < 0 || dl > 8192) { rasprintf(&buf, _("sigh data: BAD, no. of bytes(%d) out of range"), dl); goto exit; } memset(&entry, 0, sizeof(entry)); 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 = Freadall(fd, pe, nb)) != nb) { rasprintf(&buf, _("sigh blob(%d): BAD, read returned %d"), (int)nb, xx); goto exit; } /* Verify header immutable region if there is one */ xx = headerVerifyRegion(RPMTAG_HEADERSIGNATURES, &entry, il, dl, pe, dataStart, NULL, NULL, &buf); /* Not found means a legacy V3 package with no immutable region */ if (xx != RPMRC_OK && xx != RPMRC_NOTFOUND) goto exit; /* Sanity check signature tags */ 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"), 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")); goto exit; } ei = NULL; /* XXX will be freed with header */ { 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 = Freadall(fd, block, pad)) != pad) { rasprintf(&buf, _("sigh pad(%zd): BAD, read %zd bytes"), 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"), sigSize); goto exit; } } exit: if (sighp && sigh && rc == RPMRC_OK) *sighp = headerLink(sigh); headerFree(sigh); free(ei); if (msg != NULL) { *msg = buf; } else { free(buf); } return rc; }