7 #include <netinet/in.h>
9 #include <rpm/rpmlib.h> /* XXX RPMSIGTAG, other sig stuff */
10 #include <rpm/rpmts.h>
11 #include <rpm/rpmlog.h>
12 #include <rpm/rpmstring.h>
13 #include <rpm/rpmkeyring.h>
15 #include "lib/rpmlead.h"
16 #include "lib/signature.h"
17 #include "rpmio/digest.h"
18 #include "rpmio/rpmio_internal.h" /* fd digest bits */
19 #include "lib/header_internal.h" /* XXX headerCheck */
21 #include "lib/rpmplugins.h" /* rpm plugins hooks */
25 static const unsigned int nkeyids_max = 256;
26 static unsigned int nkeyids = 0;
27 static unsigned int nextkeyid = 0;
28 static unsigned int * keyids;
31 * Translate and merge legacy signature tags into header.
32 * @param h header (dest)
33 * @param sigh signature header (src)
35 static void headerMergeLegacySigs(Header h, Header sigh)
40 hi = headerInitIterator(sigh);
41 for (; headerNext(hi, &td); rpmtdFreeData(&td))
44 /* XXX Translate legacy signature tag values. */
46 td.tag = RPMTAG_SIGSIZE;
49 td.tag = RPMTAG_SIGPGP;
52 td.tag = RPMTAG_SIGMD5;
55 td.tag = RPMTAG_SIGGPG;
58 td.tag = RPMTAG_SIGPGP5;
60 case RPMSIGTAG_PAYLOADSIZE:
61 td.tag = RPMTAG_ARCHIVESIZE;
67 if (!(td.tag >= HEADER_SIGBASE && td.tag < HEADER_TAGBASE))
71 if (td.data == NULL) continue; /* XXX can't happen */
72 if (!headerIsEntry(h, td.tag)) {
73 if (hdrchkType(td.type))
75 if (td.count < 0 || hdrchkData(td.count))
91 if (td.count >= 16*1024)
94 case RPM_STRING_ARRAY_TYPE:
95 case RPM_I18NSTRING_TYPE:
99 (void) headerPut(h, &td, HEADERPUT_DEFAULT);
102 headerFreeIterator(hi);
106 * Remember current key id.
107 * @param dig OpenPGP packet containter
108 * @return 0 if new keyid, otherwise 1
110 static int stashKeyid(pgpDigParams sigp)
118 keyid = pgpGrab(sigp->signid+4, 4);
123 for (i = 0; i < nkeyids; i++) {
124 if (keyid == keyids[i])
128 if (nkeyids < nkeyids_max) {
130 keyids = xrealloc(keyids, nkeyids * sizeof(*keyids));
132 if (keyids) /* XXX can't happen */
133 keyids[nextkeyid] = keyid;
135 nextkeyid %= nkeyids_max;
140 int parsePGPSig(rpmtd sigtd, const char *type, const char *fn,
143 int rc = pgpPrtParams(sigtd->data, sigtd->count, PGPTAG_SIGNATURE, sig);
148 _("skipping %s %s with unverifiable signature\n"), type, fn);
151 _("skipping %s with unverifiable signature\n"), type);
158 * Argument monster to verify header-only signature/digest if there is
159 * one, otherwisereturn RPMRC_NOTFOUND to signal for plain sanity check.
161 static rpmRC headerSigVerify(rpmKeyring keyring, rpmVSFlags vsflags,
162 int il, int dl, int ril, int rdl,
163 entryInfo pe, unsigned char * dataStart,
167 rpmRC rc = RPMRC_FAIL;
168 pgpDigParams sig = NULL;
169 struct rpmtd_s sigtd;
170 struct entryInfo_s info, einfo;
171 unsigned int hashalgo = 0;
174 memset(&info, 0, sizeof(info));
175 memset(&einfo, 0, sizeof(einfo));
177 /* Find a header-only digest/signature tag. */
178 for (int i = ril; i < il; i++) {
179 if (headerVerifyInfo(1, dl, pe+i, &einfo, 0) != -1) {
181 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
182 i, einfo.tag, einfo.type,
183 einfo.offset, einfo.count);
188 case RPMTAG_SHA1HEADER: {
190 unsigned const char * b;
191 if (vsflags & RPMVSF_NOSHA1HEADER)
193 for (b = dataStart + einfo.offset; *b != '\0'; b++) {
194 if (strchr("0123456789abcdefABCDEF", *b) == NULL)
198 if (einfo.type != RPM_STRING_TYPE || *b != '\0' || blen != 40)
200 rasprintf(buf, _("hdr SHA1: BAD, not hex\n"));
204 info = einfo; /* structure assignment */
208 case RPMTAG_RSAHEADER:
209 if (vsflags & RPMVSF_NORSAHEADER)
211 if (einfo.type != RPM_BIN_TYPE) {
212 rasprintf(buf, _("hdr RSA: BAD, not binary\n"));
215 info = einfo; /* structure assignment */
218 case RPMTAG_DSAHEADER:
219 if (vsflags & RPMVSF_NODSAHEADER)
221 if (einfo.type != RPM_BIN_TYPE) {
222 rasprintf(buf, _("hdr DSA: BAD, not binary\n"));
225 info = einfo; /* structure assignment */
233 /* No header-only digest/signature found, get outta here */
239 sigtd.tag = info.tag;
240 sigtd.type = info.type;
241 sigtd.count = info.count;
242 sigtd.data = memcpy(xmalloc(siglen), dataStart + info.offset, siglen);
243 sigtd.flags = RPMTD_ALLOCED;
246 case RPMTAG_RSAHEADER:
247 case RPMTAG_DSAHEADER:
248 if (parsePGPSig(&sigtd, "header", NULL, &sig))
250 hashalgo = pgpDigParamsAlgo(sig, PGPVAL_HASHALGO);
252 case RPMTAG_SHA1HEADER:
253 hashalgo = PGPHASHALGO_SHA1;
260 DIGEST_CTX ctx = rpmDigestInit(hashalgo, RPMDIGEST_NONE);
261 int32_t ildl[2] = { htonl(ril), htonl(rdl) };
263 rpmDigestUpdate(ctx, rpm_header_magic, sizeof(rpm_header_magic));
264 rpmDigestUpdate(ctx, ildl, sizeof(ildl));
265 rpmDigestUpdate(ctx, pe, (ril * sizeof(*pe)));
266 rpmDigestUpdate(ctx, dataStart, rdl);
268 rc = rpmVerifySignature(keyring, &sigtd, sig, ctx, buf);
270 rpmDigestFinal(ctx, NULL, NULL, 0);
274 rpmtdFreeData(&sigtd);
275 pgpDigParamsFree(sig);
280 static rpmRC headerVerify(rpmKeyring keyring, rpmVSFlags vsflags,
281 const void * uh, size_t uc, char ** msg)
284 int32_t * ei = (int32_t *) uh;
285 int32_t il = ntohl(ei[0]);
286 int32_t dl = ntohl(ei[1]);
287 entryInfo pe = (entryInfo) &ei[2];
288 int32_t pvlen = sizeof(il) + sizeof(dl) + (il * sizeof(*pe)) + dl;
289 unsigned char * dataStart = (unsigned char *) (pe + il);
290 struct indexEntry_s entry;
291 struct entryInfo_s info;
293 unsigned char * regionEnd = NULL;
294 rpmRC rc = RPMRC_FAIL; /* assume failure */
296 /* Is the blob the right size? */
297 if (uc > 0 && pvlen != uc) {
298 rasprintf(&buf, _("blob size(%d): BAD, 8 + 16 * il(%d) + dl(%d)\n"),
299 (int)uc, (int)il, (int)dl);
303 memset(&entry, 0, sizeof(entry));
304 memset(&info, 0, sizeof(info));
306 /* Check (and convert) the 1st tag element. */
307 if (headerVerifyInfo(1, dl, pe, &entry.info, 0) != -1) {
308 rasprintf(&buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
309 0, entry.info.tag, entry.info.type,
310 entry.info.offset, entry.info.count);
314 /* Is there an immutable header region tag? */
315 if (!(entry.info.tag == RPMTAG_HEADERIMMUTABLE)) {
320 /* Is the region tag sane? */
321 if (!(entry.info.type == REGION_TAG_TYPE &&
322 entry.info.count == REGION_TAG_COUNT)) {
324 _("region tag: BAD, tag %d type %d offset %d count %d\n"),
325 entry.info.tag, entry.info.type,
326 entry.info.offset, entry.info.count);
330 /* Is the trailer within the data area? */
331 if (entry.info.offset + REGION_TAG_COUNT > dl) {
333 _("region offset: BAD, tag %d type %d offset %d count %d\n"),
334 entry.info.tag, entry.info.type,
335 entry.info.offset, entry.info.count);
339 /* Is there an immutable header region tag trailer? */
340 regionEnd = dataStart + entry.info.offset;
341 (void) memcpy(&info, regionEnd, REGION_TAG_COUNT);
342 regionEnd += REGION_TAG_COUNT;
344 if (headerVerifyInfo(1, il * sizeof(*pe), &info, &entry.info, 1) != -1 ||
345 !(entry.info.tag == RPMTAG_HEADERIMMUTABLE
346 && entry.info.type == REGION_TAG_TYPE
347 && entry.info.count == REGION_TAG_COUNT))
350 _("region trailer: BAD, tag %d type %d offset %d count %d\n"),
351 entry.info.tag, entry.info.type,
352 entry.info.offset, entry.info.count);
355 memset(&info, 0, sizeof(info));
357 /* Is the no. of tags in the region less than the total no. of tags? */
358 ril = entry.info.offset/sizeof(*pe);
359 if ((entry.info.offset % sizeof(*pe)) || ril > il) {
360 rasprintf(&buf, _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
364 /* Verify header-only digest/signature if there is one we can use. */
365 rc = headerSigVerify(keyring, vsflags,
366 il, dl, ril, (regionEnd - dataStart),
367 pe, dataStart, &buf);
370 /* If no header-only digest/signature, then do simple sanity check. */
371 if (rc == RPMRC_NOTFOUND) {
372 int xx = headerVerifyInfo(ril-1, dl, pe+1, &entry.info, 0);
375 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
376 xx+1, entry.info.tag, entry.info.type,
377 entry.info.offset, entry.info.count);
380 rasprintf(&buf, "Header sanity check: OK\n");
393 rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, char ** msg)
396 rpmVSFlags vsflags = rpmtsVSFlags(ts);
397 rpmKeyring keyring = rpmtsGetKeyring(ts, 1);
399 rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
400 rc = headerVerify(keyring, vsflags, uh, uc, msg);
401 rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), uc);
402 rpmKeyringFree(keyring);
407 static rpmRC rpmpkgReadHeader(rpmKeyring keyring, rpmVSFlags vsflags,
408 FD_t fd, Header *hdrp, char ** msg)
418 rpmRC rc = RPMRC_FAIL; /* assume failure */
426 memset(block, 0, sizeof(block));
427 if ((xx = Freadall(fd, block, sizeof(block))) != sizeof(block)) {
429 _("hdr size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx);
432 if (memcmp(block, rpm_header_magic, sizeof(rpm_header_magic))) {
433 rasprintf(&buf, _("hdr magic: BAD\n"));
436 il = ntohl(block[2]);
437 if (hdrchkTags(il)) {
438 rasprintf(&buf, _("hdr tags: BAD, no. of tags(%d) out of range\n"), il);
441 dl = ntohl(block[3]);
442 if (hdrchkData(dl)) {
444 _("hdr data: BAD, no. of bytes(%d) out of range\n"), dl);
448 nb = (il * sizeof(struct entryInfo_s)) + dl;
449 uc = sizeof(il) + sizeof(dl) + nb;
453 if ((xx = Freadall(fd, (char *)&ei[2], nb)) != nb) {
454 rasprintf(&buf, _("hdr blob(%zd): BAD, read returned %d\n"), nb, xx);
458 /* Sanity check header tags */
459 rc = headerVerify(keyring, vsflags, ei, uc, &buf);
463 /* OK, blob looks sane, load the header. */
464 h = headerImport(ei, uc, 0);
467 rasprintf(&buf, _("hdr load: BAD\n"));
471 ei = NULL; /* XXX will be freed with header */
474 if (hdrp && h && rc == RPMRC_OK)
475 *hdrp = headerLink(h);
479 if (msg != NULL && *msg == NULL && buf != NULL) {
488 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, char ** msg)
491 rpmKeyring keyring = rpmtsGetKeyring(ts, 1);
492 rpmVSFlags vsflags = rpmtsVSFlags(ts);
494 rc = rpmpkgReadHeader(keyring, vsflags, fd, hdrp, msg);
496 rpmKeyringFree(keyring);
500 static rpmRC rpmpkgRead(rpmPlugins plugins, rpmKeyring keyring, rpmVSFlags vsflags,
501 FD_t fd, const char * fn, Header * hdrp)
503 pgpDigParams sig = NULL;
508 struct rpmtd_s sigtd;
511 rpmRC rc = RPMRC_FAIL; /* assume failure */
513 headerGetFlags hgeflags = HEADERGET_DEFAULT;
514 DIGEST_CTX ctx = NULL;
516 if (hdrp) *hdrp = NULL;
522 if ((rc = rpmLeadRead(fd, NULL, &leadtype, &msg)) != RPMRC_OK) {
523 /* Avoid message spew on manifests */
524 if (rc != RPMRC_NOTFOUND)
525 rpmlog(RPMLOG_ERR, "%s: %s\n", fn, msg);
530 /* Read the signature header. */
531 rc = rpmReadSignature(fd, &sigh, RPMSIGTYPE_HEADERSIG, &msg);
534 rpmlog(RPMLOG_ERR, _("%s: rpmReadSignature failed: %s"), fn,
535 (msg && *msg ? msg : "\n"));
541 rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), fn);
549 #define _chk(_mask, _tag) \
550 (sigtag == 0 && !(vsflags & (_mask)) && headerIsEntry(sigh, (_tag)))
553 * Figger the most effective available signature.
554 * Prefer signatures over digests, then header-only over header+payload.
555 * DSA will be preferred over RSA if both exist because tested first.
556 * Note that NEEDPAYLOAD prevents header+payload signatures and digests.
559 if (_chk(RPMVSF_NODSAHEADER, RPMSIGTAG_DSA)) {
560 sigtag = RPMSIGTAG_DSA;
561 } else if (_chk(RPMVSF_NORSAHEADER, RPMSIGTAG_RSA)) {
562 sigtag = RPMSIGTAG_RSA;
563 } else if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD, RPMSIGTAG_GPG)) {
564 sigtag = RPMSIGTAG_GPG;
565 fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
566 } else if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD, RPMSIGTAG_PGP)) {
567 sigtag = RPMSIGTAG_PGP;
568 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
569 } else if (_chk(RPMVSF_NOSHA1HEADER, RPMSIGTAG_SHA1)) {
570 sigtag = RPMSIGTAG_SHA1;
571 } else if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD, RPMSIGTAG_MD5)) {
572 sigtag = RPMSIGTAG_MD5;
573 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
576 /* Read the metadata, computing digest(s) on the fly. */
580 rc = rpmpkgReadHeader(keyring, vsflags, fd, &h, &msg);
582 if (rc != RPMRC_OK || h == NULL) {
583 rpmlog(RPMLOG_ERR, _("%s: headerRead failed: %s"), fn,
584 (msg && *msg ? msg : "\n"));
590 /* Any digests or signatures to check? */
596 /* Retrieve the tag parameters from the signature header. */
597 if (!headerGet(sigh, sigtag, &sigtd, hgeflags)) {
605 if (parsePGPSig(&sigtd, "package", fn, &sig)) {
611 { struct rpmtd_s utd;
612 unsigned int hashalgo = (sigtag == RPMSIGTAG_SHA1) ?
614 pgpDigParamsAlgo(sig, PGPVAL_HASHALGO);
616 if (!headerGet(h, RPMTAG_HEADERIMMUTABLE, &utd, hgeflags))
618 ctx = rpmDigestInit(hashalgo, RPMDIGEST_NONE);
619 (void) rpmDigestUpdate(ctx, rpm_header_magic, sizeof(rpm_header_magic));
620 (void) rpmDigestUpdate(ctx, utd.data, utd.count);
624 case RPMSIGTAG_PGP5: /* XXX legacy */
626 if (parsePGPSig(&sigtd, "package", fn, &sig)) {
632 /* Legacy signatures need the compressed payload in the digest too. */
633 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0) {}
635 rpmlog(RPMLOG_ERR, _("%s: Fread failed: %s\n"),
641 ctx = rpmDigestBundleDupCtx(fdGetBundle(fd),(sigtag == RPMSIGTAG_MD5) ?
643 pgpDigParamsAlgo(sig, PGPVAL_HASHALGO));
649 /** @todo Implement disable/enable/warn/error/anal policy. */
650 rc = rpmVerifySignature(keyring, &sigtd, sig, ctx, &msg);
652 /* Run verify hook for all plugins */
653 rc = rpmpluginsCallVerify(plugins, keyring, &sigtd, sig, ctx, rc);
656 case RPMRC_OK: /* Signature is OK. */
657 rpmlog(RPMLOG_DEBUG, "%s: %s", fn, msg);
659 case RPMRC_NOTTRUSTED: /* Signature is OK, but key is not trusted. */
660 case RPMRC_NOKEY: /* Public key is unavailable. */
661 /* XXX Print NOKEY/NOTTRUSTED warning only once. */
662 { int lvl = (stashKeyid(sig) ? RPMLOG_DEBUG : RPMLOG_WARNING);
663 rpmlog(lvl, "%s: %s", fn, msg);
665 case RPMRC_NOTFOUND: /* Signature is unknown type. */
666 rpmlog(RPMLOG_WARNING, "%s: %s", fn, msg);
669 case RPMRC_FAIL: /* Signature does not verify. */
670 rpmlog(RPMLOG_ERR, "%s: %s", fn, msg);
676 if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
677 /* Retrofit RPMTAG_SOURCEPACKAGE to srpms for compatibility */
678 if (leadtype == RPMLEAD_SOURCE && headerIsSource(h)) {
679 if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE)) {
681 headerPutUint32(h, RPMTAG_SOURCEPACKAGE, &one, 1);
685 * Try to make sure binary rpms have RPMTAG_SOURCERPM set as that's
686 * what we use for differentiating binary vs source elsewhere.
688 if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE) && headerIsSource(h)) {
689 headerPutString(h, RPMTAG_SOURCERPM, "(none)");
692 * Convert legacy headers on the fly. Not having immutable region
693 * equals a truly ancient package, do full retrofit. OTOH newer
694 * packages might have been built with --nodirtokens, test and handle
695 * the non-compressed filelist case separately.
697 if (!headerIsEntry(h, RPMTAG_HEADERIMMUTABLE))
698 headerConvert(h, HEADERCONV_RETROFIT_V3);
699 else if (headerIsEntry(h, RPMTAG_OLDFILENAMES))
700 headerConvert(h, HEADERCONV_COMPRESSFILELIST);
702 /* Append (and remap) signature tags to the metadata. */
703 headerMergeLegacySigs(h, sigh);
705 /* Bump reference count for return. */
706 *hdrp = headerLink(h);
708 rpmtdFreeData(&sigtd);
709 rpmDigestFinal(ctx, NULL, NULL, 0);
711 pgpDigParamsFree(sig);
712 sigh = rpmFreeSignature(sigh);
716 rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
719 rpmVSFlags vsflags = rpmtsVSFlags(ts);
720 rpmKeyring keyring = rpmtsGetKeyring(ts, 1);
722 rc = rpmpkgRead(rpmtsPlugins(ts), keyring, vsflags, fd, fn, hdrp);
724 rpmKeyringFree(keyring);