7 #include <netinet/in.h>
9 #include <rpmio_internal.h>
12 #define _RPMTS_INTERNAL
15 #include "misc.h" /* XXX stripTrailingChar() */
16 #include "legacy.h" /* XXX legacyRetrofit() */
19 #include "header_internal.h" /* XXX headerCheck */
20 #include "signature.h"
23 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
26 /*@access pgpDigParams @*/
27 /*@access Header @*/ /* XXX compared with NULL */
28 /*@access entryInfo @*/ /* XXX headerCheck */
29 /*@access indexEntry @*/ /* XXX headerCheck */
30 /*@access FD_t @*/ /* XXX stealing digests */
33 static int _print_pkts = 0;
36 static unsigned int nkeyids_max = 256;
38 static unsigned int nkeyids = 0;
40 static unsigned int nextkeyid = 0;
41 /*@unchecked@*/ /*@only@*/ /*@null@*/
42 static unsigned int * keyids;
45 static unsigned char header_magic[8] = {
46 0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
50 * Alignment needs (and sizeof scalars types) for internal rpm data types.
52 /*@observer@*/ /*@unchecked@*/
53 static int typeAlign[16] = {
54 1, /*!< RPM_NULL_TYPE */
55 1, /*!< RPM_CHAR_TYPE */
56 1, /*!< RPM_INT8_TYPE */
57 2, /*!< RPM_INT16_TYPE */
58 4, /*!< RPM_INT32_TYPE */
59 8, /*!< RPM_INT64_TYPE */
60 1, /*!< RPM_STRING_TYPE */
61 1, /*!< RPM_BIN_TYPE */
62 1, /*!< RPM_STRING_ARRAY_TYPE */
63 1, /*!< RPM_I18NSTRING_TYPE */
73 * Sanity check on no. of tags.
74 * This check imposes a limit of 65K tags, more than enough.
76 #define hdrchkTags(_ntags) ((_ntags) & 0xffff0000)
79 * Sanity check on type values.
81 #define hdrchkType(_type) ((_type) < RPM_MIN_TYPE || (_type) > RPM_MAX_TYPE)
84 * Sanity check on data size and/or offset and/or count.
85 * This check imposes a limit of 16 MB, more than enough.
87 #define hdrchkData(_nbytes) ((_nbytes) & 0xff000000)
90 * Sanity check on data alignment for data type.
92 #define hdrchkAlign(_type, _off) ((_off) & (typeAlign[_type]-1))
95 * Sanity check on range of data offset.
97 #define hdrchkRange(_dl, _off) ((_off) < 0 || (_off) > (_dl))
99 void headerMergeLegacySigs(Header h, const Header sigh)
101 HFD_t hfd = (HFD_t) headerFreeData;
102 HAE_t hae = (HAE_t) headerAddEntry;
104 int_32 tag, type, count;
108 for (hi = headerInitIterator(sigh);
109 headerNextIterator(hi, &tag, &type, &ptr, &count);
110 ptr = hfd(ptr, type))
113 /* XXX Translate legacy signature tag values. */
115 tag = RPMTAG_SIGSIZE;
116 /*@switchbreak@*/ break;
117 case RPMSIGTAG_LEMD5_1:
118 tag = RPMTAG_SIGLEMD5_1;
119 /*@switchbreak@*/ break;
122 /*@switchbreak@*/ break;
123 case RPMSIGTAG_LEMD5_2:
124 tag = RPMTAG_SIGLEMD5_2;
125 /*@switchbreak@*/ break;
128 /*@switchbreak@*/ break;
131 /*@switchbreak@*/ break;
133 tag = RPMTAG_SIGPGP5;
134 /*@switchbreak@*/ break;
135 case RPMSIGTAG_PAYLOADSIZE:
136 tag = RPMTAG_ARCHIVESIZE;
137 /*@switchbreak@*/ break;
142 if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
144 /*@switchbreak@*/ break;
146 if (ptr == NULL) continue; /* XXX can't happen */
147 if (!headerIsEntry(h, tag)) {
148 if (hdrchkType(type))
150 if (count < 0 || hdrchkData(count))
155 /*@notreached@*/ /*@switchbreak@*/ break;
162 /*@switchbreak@*/ break;
163 case RPM_STRING_TYPE:
165 if (count >= 16*1024)
167 /*@switchbreak@*/ break;
168 case RPM_STRING_ARRAY_TYPE:
169 case RPM_I18NSTRING_TYPE:
171 /*@notreached@*/ /*@switchbreak@*/ break;
173 xx = hae(h, tag, type, ptr, count);
176 hi = headerFreeIterator(hi);
179 Header headerRegenSigHeader(const Header h, int noArchiveSize)
181 HFD_t hfd = (HFD_t) headerFreeData;
182 Header sigh = rpmNewSignature();
184 int_32 tag, stag, type, count;
188 for (hi = headerInitIterator(h);
189 headerNextIterator(hi, &tag, &type, &ptr, &count);
190 ptr = hfd(ptr, type))
193 /* XXX Translate legacy signature tag values. */
195 stag = RPMSIGTAG_SIZE;
196 /*@switchbreak@*/ break;
197 case RPMTAG_SIGLEMD5_1:
198 stag = RPMSIGTAG_LEMD5_1;
199 /*@switchbreak@*/ break;
201 stag = RPMSIGTAG_PGP;
202 /*@switchbreak@*/ break;
203 case RPMTAG_SIGLEMD5_2:
204 stag = RPMSIGTAG_LEMD5_2;
205 /*@switchbreak@*/ break;
207 stag = RPMSIGTAG_MD5;
208 /*@switchbreak@*/ break;
210 stag = RPMSIGTAG_GPG;
211 /*@switchbreak@*/ break;
213 stag = RPMSIGTAG_PGP5;
214 /*@switchbreak@*/ break;
215 case RPMTAG_ARCHIVESIZE:
216 /* XXX rpm-4.1 and later has archive size in signature header. */
219 stag = RPMSIGTAG_PAYLOADSIZE;
220 /*@switchbreak@*/ break;
221 case RPMTAG_SHA1HEADER:
222 case RPMTAG_DSAHEADER:
223 case RPMTAG_RSAHEADER:
225 if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
228 /*@switchbreak@*/ break;
230 if (ptr == NULL) continue; /* XXX can't happen */
231 if (!headerIsEntry(sigh, stag))
232 xx = headerAddEntry(sigh, stag, type, ptr, count);
234 hi = headerFreeIterator(hi);
239 * Remember current key id.
240 * @param ts transaction set
241 * @return 0 if new keyid, otherwise 1
243 static int rpmtsStashKeyid(rpmts ts)
244 /*@globals nextkeyid, nkeyids, keyids @*/
245 /*@modifies nextkeyid, nkeyids, keyids @*/
247 const void * sig = rpmtsSig(ts);
248 pgpDig dig = rpmtsDig(ts);
249 pgpDigParams sigp = rpmtsSignature(ts);
253 if (sig == NULL || dig == NULL || sigp == NULL)
256 keyid = pgpGrab(sigp->signid+4, 4);
261 for (i = 0; i < nkeyids; i++) {
263 if (keyid == keyids[i])
268 if (nkeyids < nkeyids_max) {
270 keyids = xrealloc(keyids, nkeyids * sizeof(*keyids));
273 if (keyids) /* XXX can't happen */
274 keyids[nextkeyid] = keyid;
277 nextkeyid %= nkeyids_max;
282 int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate)
285 entryInfo pe = (entryInfo) pev;
291 for (i = 0; i < il; i++) {
292 info->tag = ntohl(pe[i].tag);
293 info->type = ntohl(pe[i].type);
294 info->offset = ntohl(pe[i].offset);
296 info->offset = -info->offset;
297 info->count = ntohl(pe[i].count);
299 if (hdrchkType(info->type))
301 if (hdrchkAlign(info->type, info->offset))
303 if (!negate && hdrchkRange(dl, info->offset))
305 if (hdrchkData(info->count))
314 * Check header consistency, performing headerGetEntry() the hard way.
316 * Sanity checks on the header are performed while looking for a
317 * header-only digest or signature to verify the blob. If found,
318 * the digest or signature is verified.
320 * @param ts transaction set
321 * @param uh unloaded header blob
322 * @param uc no. of bytes in blob (or 0 to disable)
323 * @retval *msg signature verification msg
324 * @return RPMRC_OK/RPMRC_NOTFOUND/RPMRC_FAIL
326 rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, const char ** msg)
329 unsigned char buf[8*BUFSIZ];
330 int_32 * ei = (int_32 *) uh;
332 int_32 il = ntohl(ei[0]);
333 int_32 dl = ntohl(ei[1]);
335 entryInfo pe = (entryInfo) &ei[2];
339 int_32 pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl;
340 unsigned char * dataStart = (unsigned char *) (pe + il);
341 indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry));
342 entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info));
343 const void * sig = NULL;
345 rpmVSFlags vsflags = rpmtsVSFlags(ts);
350 unsigned char * regionEnd = NULL;
351 rpmRC rc = RPMRC_FAIL; /* assume failure */
359 /* Is the blob the right size? */
360 if (uc > 0 && pvlen != uc) {
361 (void) snprintf(buf, sizeof(buf),
362 _("blob size(%d): BAD, 8 + 16 * il(%d) + dl(%d)\n"),
363 (int)uc, (int)il, (int)dl);
367 /* Check (and convert) the 1st tag element. */
368 xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
370 (void) snprintf(buf, sizeof(buf),
371 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
372 0, entry->info.tag, entry->info.type,
373 entry->info.offset, entry->info.count);
377 /* Is there an immutable header region tag? */
379 if (!(entry->info.tag == RPMTAG_HEADERIMMUTABLE
380 && entry->info.type == RPM_BIN_TYPE
381 && entry->info.count == REGION_TAG_COUNT))
388 /* Is the offset within the data area? */
389 if (entry->info.offset >= dl) {
390 (void) snprintf(buf, sizeof(buf),
391 _("region offset: BAD, tag %d type %d offset %d count %d\n"),
392 entry->info.tag, entry->info.type,
393 entry->info.offset, entry->info.count);
397 /* Is there an immutable header region tag trailer? */
398 regionEnd = dataStart + entry->info.offset;
401 (void) memcpy(info, regionEnd, REGION_TAG_COUNT);
403 regionEnd += REGION_TAG_COUNT;
405 xx = headerVerifyInfo(1, dl, info, &entry->info, 1);
407 !(entry->info.tag == RPMTAG_HEADERIMMUTABLE
408 && entry->info.type == RPM_BIN_TYPE
409 && entry->info.count == REGION_TAG_COUNT))
411 (void) snprintf(buf, sizeof(buf),
412 _("region trailer: BAD, tag %d type %d offset %d count %d\n"),
413 entry->info.tag, entry->info.type,
414 entry->info.offset, entry->info.count);
419 memset(info, 0, sizeof(*info));
422 /* Is the no. of tags in the region less than the total no. of tags? */
423 ril = entry->info.offset/sizeof(*pe);
424 if ((entry->info.offset % sizeof(*pe)) || ril > il) {
425 (void) snprintf(buf, sizeof(buf),
426 _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
430 /* Find a header-only digest/signature tag. */
431 for (i = ril; i < il; i++) {
432 xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0);
434 (void) snprintf(buf, sizeof(buf),
435 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
436 i, entry->info.tag, entry->info.type,
437 entry->info.offset, entry->info.count);
441 switch (entry->info.tag) {
442 case RPMTAG_SHA1HEADER:
443 if (vsflags & RPMVSF_NOSHA1HEADER)
444 /*@switchbreak@*/ break;
447 for (b = dataStart + entry->info.offset; *b != '\0'; b++) {
448 if (strchr("0123456789abcdefABCDEF", *b) == NULL)
449 /*@innerbreak@*/ break;
452 if (entry->info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40)
454 (void) snprintf(buf, sizeof(buf), _("hdr SHA1: BAD, not hex\n"));
458 if (info->tag == 0) {
460 *info = entry->info; /* structure assignment */
464 /*@switchbreak@*/ break;
466 case RPMTAG_RSAHEADER:
468 case RPMTAG_DSAHEADER:
469 if (vsflags & RPMVSF_NODSAHEADER)
470 /*@switchbreak@*/ break;
471 if (entry->info.type != RPM_BIN_TYPE) {
472 (void) snprintf(buf, sizeof(buf), _("hdr DSA: BAD, not binary\n"));
476 *info = entry->info; /* structure assignment */
478 siglen = info->count;
479 /*@switchbreak@*/ break;
481 /*@switchbreak@*/ break;
487 /* Return determined RPMRC_OK/RPMRC_FAIL conditions. */
488 if (rc != RPMRC_NOTFOUND) {
490 buf[sizeof(buf)-1] = '\0';
491 if (msg) *msg = xstrdup(buf);
496 /* If no header-only digest/signature, then do simple sanity check. */
497 if (info->tag == 0) {
499 xx = headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0);
501 (void) snprintf(buf, sizeof(buf),
502 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
503 xx+1, entry->info.tag, entry->info.type,
504 entry->info.offset, entry->info.count);
507 (void) snprintf(buf, sizeof(buf), "Header sanity check: OK\n");
511 buf[sizeof(buf)-1] = '\0';
512 if (msg) *msg = xstrdup(buf);
517 /* Verify header-only digest/signature. */
520 goto verifyinfo_exit;
524 sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen);
526 (void) rpmtsSetSig(ts, info->tag, info->type, sig, info->count);
530 case RPMTAG_RSAHEADER:
531 /* Parse the parameters from the OpenPGP packets that will be needed. */
532 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
533 /* XXX only V3 signatures for now. */
534 if (dig->signature.version != 3) {
535 rpmMessage(RPMMESS_WARNING,
536 _("only V3 signatures can be verified, skipping V%u signature\n"),
537 dig->signature.version);
539 goto verifyinfo_exit;
542 ildl[0] = htonl(ril);
543 ildl[1] = (regionEnd - dataStart);
544 ildl[1] = htonl(ildl[1]);
546 (void) rpmswEnter(&ts->op_digest, 0);
547 dig->hdrmd5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
549 b = (unsigned char *) header_magic;
550 nb = sizeof(header_magic);
551 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
554 b = (unsigned char *) ildl;
556 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
559 b = (unsigned char *) pe;
560 nb = (htonl(ildl[0]) * sizeof(*pe));
561 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
564 b = (unsigned char *) dataStart;
566 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
568 (void) rpmswExit(&ts->op_digest, dig->nbytes);
572 case RPMTAG_DSAHEADER:
573 /* Parse the parameters from the OpenPGP packets that will be needed. */
574 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
575 /* XXX only V3 signatures for now. */
576 if (dig->signature.version != 3) {
577 rpmMessage(RPMMESS_WARNING,
578 _("only V3 signatures can be verified, skipping V%u signature\n"),
579 dig->signature.version);
581 goto verifyinfo_exit;
584 case RPMTAG_SHA1HEADER:
586 ildl[0] = htonl(ril);
587 ildl[1] = (regionEnd - dataStart);
588 ildl[1] = htonl(ildl[1]);
591 (void) rpmswEnter(&ts->op_digest, 0);
592 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
594 b = (unsigned char *) header_magic;
595 nb = sizeof(header_magic);
596 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
599 b = (unsigned char *) ildl;
601 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
604 b = (unsigned char *) pe;
605 nb = (htonl(ildl[0]) * sizeof(*pe));
606 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
609 b = (unsigned char *) dataStart;
611 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
613 (void) rpmswExit(&ts->op_digest, dig->nbytes);
624 rc = rpmVerifySignature(ts, buf);
627 buf[sizeof(buf)-1] = '\0';
628 if (msg) *msg = xstrdup(buf);
632 if (info->tag == RPMTAG_SHA1HEADER)
637 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, const char ** msg)
647 rpmRC rc = RPMRC_FAIL; /* assume failure */
659 memset(block, 0, sizeof(block));
660 if ((xx = timedRead(fd, (char *)block, sizeof(block))) != sizeof(block)) {
661 (void) snprintf(buf, sizeof(buf),
662 _("hdr size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx);
665 if (memcmp(block, header_magic, sizeof(header_magic))) {
666 (void) snprintf(buf, sizeof(buf), _("hdr magic: BAD\n"));
670 il = ntohl(block[2]);
672 if (hdrchkTags(il)) {
673 (void) snprintf(buf, sizeof(buf),
674 _("hdr tags: BAD, no. of tags(%d) out of range\n"), il);
679 dl = ntohl(block[3]);
681 if (hdrchkData(dl)) {
682 (void) snprintf(buf, sizeof(buf),
683 _("hdr data: BAD, no. of bytes(%d) out of range\n"), dl);
688 nb = (il * sizeof(struct entryInfo_s)) + dl;
690 uc = sizeof(il) + sizeof(dl) + nb;
695 if ((xx = timedRead(fd, (char *)&ei[2], nb)) != nb) {
696 (void) snprintf(buf, sizeof(buf),
697 _("hdr blob(%d): BAD, read returned %d\n"), nb, xx);
702 /* Sanity check header tags */
703 rc = headerCheck(ts, ei, uc, msg);
707 /* OK, blob looks sane, load the header. */
710 (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n"));
713 h->flags |= HEADERFLAG_ALLOCATED;
714 ei = NULL; /* XXX will be freed with header */
718 if (hdrp && h && rc == RPMRC_OK)
719 *hdrp = headerLink(h);
725 if (msg != NULL && *msg == NULL && buf[0] != '\0') {
726 buf[sizeof(buf)-1] = '\0';
734 /*@-bounds@*/ /* LCL: segfault */
735 int rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
740 struct rpmlead * l = alloca(sizeof(*l));
750 rpmRC rc = RPMRC_FAIL; /* assume failure */
754 if (hdrp) *hdrp = NULL;
757 memset(&st, 0, sizeof(st));
759 (void) fstat(Fileno(fd), &st);
760 /* if fd points to a socket, pipe, etc, st.st_size is *always* zero */
761 if (S_ISREG(st.st_mode) && st.st_size < sizeof(*l))
765 memset(l, 0, sizeof(*l));
766 rc = readLead(fd, l);
767 if (rc != RPMRC_OK) {
774 rpmError(RPMERR_NEWPACKAGE,
775 _("packaging version 1 is not supported by this version of RPM\n"));
777 /*@notreached@*/ break;
783 rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 "
784 "is supported by this version of RPM\n"));
786 /*@notreached@*/ break;
789 /* Read the signature header. */
791 rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
794 rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed: %s"), fn,
795 (msg && *msg ? msg : "\n"));
798 /*@notreached@*/ break;
801 rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn);
809 #define _chk(_mask) (sigtag == 0 && !(vsflags & (_mask)))
811 /* Figger the most effective available signature. */
813 vsflags = rpmtsVSFlags(ts);
815 if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_DSA))
816 sigtag = RPMSIGTAG_DSA;
817 if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_RSA))
818 sigtag = RPMSIGTAG_RSA;
820 if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD) &&
821 headerIsEntry(sigh, RPMSIGTAG_GPG))
823 sigtag = RPMSIGTAG_GPG;
824 fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
826 if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD) &&
827 headerIsEntry(sigh, RPMSIGTAG_PGP))
829 sigtag = RPMSIGTAG_PGP;
830 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
833 if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, RPMSIGTAG_SHA1))
834 sigtag = RPMSIGTAG_SHA1;
836 if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
837 headerIsEntry(sigh, RPMSIGTAG_MD5))
839 sigtag = RPMSIGTAG_MD5;
840 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
843 /* Read the metadata, computing digest(s) on the fly. */
846 rc = rpmReadHeader(ts, fd, &h, &msg);
847 if (rc != RPMRC_OK || h == NULL) {
848 rpmError(RPMERR_FREAD, _("%s: headerRead failed: %s"), fn,
849 (msg && *msg ? msg : "\n"));
855 /* Any signatures to check? */
868 /* Retrieve the tag parameters from the signature header. */
870 xx = headerGetEntry(sigh, sigtag, &sigtype, (void **) &sig, &siglen);
875 (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
879 /* Parse the parameters from the OpenPGP packets that will be needed. */
880 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
881 /* XXX only V3 signatures for now. */
882 if (dig->signature.version != 3) {
883 rpmMessage(RPMMESS_WARNING,
884 _("only V3 signatures can be verified, skipping V%u signature\n"),
885 dig->signature.version);
893 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
895 dig->md5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
896 (void) rpmDigestUpdate(dig->md5ctx, header_magic, sizeof(header_magic));
897 dig->nbytes += sizeof(header_magic);
898 (void) rpmDigestUpdate(dig->md5ctx, uh, uhc);
900 uh = headerFreeData(uh, uht);
903 /* Parse the parameters from the OpenPGP packets that will be needed. */
904 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
905 /* XXX only V3 signatures for now. */
906 if (dig->signature.version != 3) {
907 rpmMessage(RPMMESS_WARNING,
908 _("only V3 signatures can be verified, skipping V%u signature\n"),
909 dig->signature.version);
919 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
921 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
922 (void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic));
923 dig->nbytes += sizeof(header_magic);
924 (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
926 uh = headerFreeData(uh, uht);
929 case RPMSIGTAG_PGP5: /* XXX legacy */
931 /* Parse the parameters from the OpenPGP packets that will be needed. */
932 xx = pgpPrtPkts(sig, siglen, dig,
933 (_print_pkts & rpmIsDebug()));
935 /* XXX only V3 signatures for now. */
936 if (dig->signature.version != 3) {
937 rpmMessage(RPMMESS_WARNING,
938 _("only V3 signatures can be verified, skipping V%u signature\n"),
939 dig->signature.version);
945 /* Legacy signatures need the compressed payload in the digest too. */
946 hmagic = ((l->major >= 3) ? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
947 dig->nbytes += headerSizeof(h, hmagic);
948 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
949 dig->nbytes += count;
951 rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
956 dig->nbytes += count;
958 /* XXX Steal the digest-in-progress from the file handle. */
959 for (i = fd->ndigests - 1; i >= 0; i--) {
960 FDDIGEST_t fddig = fd->digests + i;
961 if (fddig->hashctx == NULL)
963 if (fddig->hashalgo == PGPHASHALGO_MD5) {
964 dig->md5ctx = fddig->hashctx;
965 fddig->hashctx = NULL;
968 if (fddig->hashalgo == PGPHASHALGO_SHA1) {
969 dig->sha1ctx = fddig->hashctx;
970 fddig->hashctx = NULL;
977 /** @todo Implement disable/enable/warn/error/anal policy. */
982 rc = rpmVerifySignature(ts, buf);
984 case RPMRC_OK: /* Signature is OK. */
985 rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
987 case RPMRC_NOTTRUSTED: /* Signature is OK, but key is not trusted. */
988 case RPMRC_NOKEY: /* Public key is unavailable. */
989 /* XXX Print NOKEY/NOTTRUSTED warning only once. */
990 { int lvl = (rpmtsStashKeyid(ts) ? RPMMESS_DEBUG : RPMMESS_WARNING);
991 rpmMessage(lvl, "%s: %s", fn, buf);
993 case RPMRC_NOTFOUND: /* Signature is unknown type. */
994 rpmMessage(RPMMESS_WARNING, "%s: %s", fn, buf);
997 case RPMRC_FAIL: /* Signature does not verify. */
998 rpmMessage(RPMMESS_ERROR, "%s: %s", fn, buf);
1003 if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
1004 /* Convert legacy headers on the fly ... */
1005 legacyRetrofit(h, l);
1007 /* Append (and remap) signature tags to the metadata. */
1008 headerMergeLegacySigs(h, sigh);
1010 /* Bump reference count for return. */
1012 *hdrp = headerLink(h);
1017 sigh = rpmFreeSignature(sigh);