7 #include <netinet/in.h>
9 #include <rpmio_internal.h>
14 #include "misc.h" /* XXX stripTrailingChar() */
15 #include "legacy.h" /* XXX legacyRetrofit() */
18 #include "header_internal.h" /* XXX headerCheck */
19 #include "signature.h"
22 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
25 /*@access pgpDigParams @*/
26 /*@access Header @*/ /* XXX compared with NULL */
27 /*@access entryInfo @*/ /* XXX headerCheck */
28 /*@access indexEntry @*/ /* XXX headerCheck */
29 /*@access FD_t @*/ /* XXX stealing digests */
32 static int _print_pkts = 0;
35 static unsigned int nkeyids_max = 256;
37 static unsigned int nkeyids = 0;
39 static unsigned int nextkeyid = 0;
40 /*@unchecked@*/ /*@only@*/ /*@null@*/
41 static unsigned int * keyids;
44 static unsigned char header_magic[8] = {
45 0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
49 * Alignment needs (and sizeof scalars types) for internal rpm data types.
51 /*@observer@*/ /*@unchecked@*/
52 static int typeAlign[16] = {
53 1, /*!< RPM_NULL_TYPE */
54 1, /*!< RPM_CHAR_TYPE */
55 1, /*!< RPM_INT8_TYPE */
56 2, /*!< RPM_INT16_TYPE */
57 4, /*!< RPM_INT32_TYPE */
58 8, /*!< RPM_INT64_TYPE */
59 1, /*!< RPM_STRING_TYPE */
60 1, /*!< RPM_BIN_TYPE */
61 1, /*!< RPM_STRING_ARRAY_TYPE */
62 1, /*!< RPM_I18NSTRING_TYPE */
72 * Sanity check on no. of tags.
73 * This check imposes a limit of 65K tags, more than enough.
75 #define hdrchkTags(_ntags) ((_ntags) & 0xffff0000)
78 * Sanity check on type values.
80 #define hdrchkType(_type) ((_type) < RPM_MIN_TYPE || (_type) > RPM_MAX_TYPE)
83 * Sanity check on data size and/or offset and/or count.
84 * This check imposes a limit of 16 MB, more than enough.
86 #define hdrchkData(_nbytes) ((_nbytes) & 0xff000000)
89 * Sanity check on data alignment for data type.
91 #define hdrchkAlign(_type, _off) ((_off) & (typeAlign[_type]-1))
94 * Sanity check on range of data offset.
96 #define hdrchkRange(_dl, _off) ((_off) < 0 || (_off) > (_dl))
98 void headerMergeLegacySigs(Header h, const Header sigh)
100 HFD_t hfd = (HFD_t) headerFreeData;
101 HAE_t hae = (HAE_t) headerAddEntry;
103 int_32 tag, type, count;
107 for (hi = headerInitIterator(sigh);
108 headerNextIterator(hi, &tag, &type, &ptr, &count);
109 ptr = hfd(ptr, type))
112 /* XXX Translate legacy signature tag values. */
114 tag = RPMTAG_SIGSIZE;
115 /*@switchbreak@*/ break;
116 case RPMSIGTAG_LEMD5_1:
117 tag = RPMTAG_SIGLEMD5_1;
118 /*@switchbreak@*/ break;
121 /*@switchbreak@*/ break;
122 case RPMSIGTAG_LEMD5_2:
123 tag = RPMTAG_SIGLEMD5_2;
124 /*@switchbreak@*/ break;
127 /*@switchbreak@*/ break;
130 /*@switchbreak@*/ break;
132 tag = RPMTAG_SIGPGP5;
133 /*@switchbreak@*/ break;
134 case RPMSIGTAG_PAYLOADSIZE:
135 tag = RPMTAG_ARCHIVESIZE;
136 /*@switchbreak@*/ break;
141 if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
143 /*@switchbreak@*/ break;
145 if (ptr == NULL) continue; /* XXX can't happen */
146 if (!headerIsEntry(h, tag)) {
147 if (hdrchkType(type))
149 if (count < 0 || hdrchkData(count))
154 /*@notreached@*/ /*@switchbreak@*/ break;
161 /*@switchbreak@*/ break;
162 case RPM_STRING_TYPE:
164 if (count >= 16*1024)
166 /*@switchbreak@*/ break;
167 case RPM_STRING_ARRAY_TYPE:
168 case RPM_I18NSTRING_TYPE:
170 /*@notreached@*/ /*@switchbreak@*/ break;
172 xx = hae(h, tag, type, ptr, count);
175 hi = headerFreeIterator(hi);
178 Header headerRegenSigHeader(const Header h, int noArchiveSize)
180 HFD_t hfd = (HFD_t) headerFreeData;
181 Header sigh = rpmNewSignature();
183 int_32 tag, stag, type, count;
187 for (hi = headerInitIterator(h);
188 headerNextIterator(hi, &tag, &type, &ptr, &count);
189 ptr = hfd(ptr, type))
192 /* XXX Translate legacy signature tag values. */
194 stag = RPMSIGTAG_SIZE;
195 /*@switchbreak@*/ break;
196 case RPMTAG_SIGLEMD5_1:
197 stag = RPMSIGTAG_LEMD5_1;
198 /*@switchbreak@*/ break;
200 stag = RPMSIGTAG_PGP;
201 /*@switchbreak@*/ break;
202 case RPMTAG_SIGLEMD5_2:
203 stag = RPMSIGTAG_LEMD5_2;
204 /*@switchbreak@*/ break;
206 stag = RPMSIGTAG_MD5;
207 /*@switchbreak@*/ break;
209 stag = RPMSIGTAG_GPG;
210 /*@switchbreak@*/ break;
212 stag = RPMSIGTAG_PGP5;
213 /*@switchbreak@*/ break;
214 case RPMTAG_ARCHIVESIZE:
215 /* XXX rpm-4.1 and later has archive size in signature header. */
218 stag = RPMSIGTAG_PAYLOADSIZE;
219 /*@switchbreak@*/ break;
220 case RPMTAG_SHA1HEADER:
221 case RPMTAG_DSAHEADER:
222 case RPMTAG_RSAHEADER:
224 if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
227 /*@switchbreak@*/ break;
229 if (ptr == NULL) continue; /* XXX can't happen */
230 if (!headerIsEntry(sigh, stag))
231 xx = headerAddEntry(sigh, stag, type, ptr, count);
233 hi = headerFreeIterator(hi);
238 * Remember current key id.
239 * @param ts transaction set
240 * @return 0 if new keyid, otherwise 1
242 static int rpmtsStashKeyid(rpmts ts)
243 /*@globals nextkeyid, nkeyids, keyids @*/
244 /*@modifies nextkeyid, nkeyids, keyids @*/
246 const void * sig = rpmtsSig(ts);
247 pgpDig dig = rpmtsDig(ts);
248 pgpDigParams sigp = rpmtsSignature(ts);
252 if (sig == NULL || dig == NULL || sigp == NULL)
255 keyid = pgpGrab(sigp->signid+4, 4);
260 for (i = 0; i < nkeyids; i++) {
262 if (keyid == keyids[i])
267 if (nkeyids < nkeyids_max) {
269 keyids = xrealloc(keyids, nkeyids * sizeof(*keyids));
272 if (keyids) /* XXX can't happen */
273 keyids[nextkeyid] = keyid;
276 nextkeyid %= nkeyids_max;
281 int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate)
284 entryInfo pe = (entryInfo) pev;
290 for (i = 0; i < il; i++) {
291 info->tag = ntohl(pe[i].tag);
292 info->type = ntohl(pe[i].type);
293 info->offset = ntohl(pe[i].offset);
295 info->offset = -info->offset;
296 info->count = ntohl(pe[i].count);
298 if (hdrchkType(info->type))
300 if (hdrchkAlign(info->type, info->offset))
302 if (!negate && hdrchkRange(dl, info->offset))
304 if (hdrchkData(info->count))
313 * Check header consistency, performing headerGetEntry() the hard way.
315 * Sanity checks on the header are performed while looking for a
316 * header-only digest or signature to verify the blob. If found,
317 * the digest or signature is verified.
319 * @param ts transaction set
320 * @param uh unloaded header blob
321 * @param uc no. of bytes in blob (or 0 to disable)
322 * @retval *msg signature verification msg
323 * @return RPMRC_OK/RPMRC_NOTFOUND/RPMRC_FAIL
325 rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, const char ** msg)
328 unsigned char buf[8*BUFSIZ];
329 int_32 * ei = (int_32 *) uh;
331 int_32 il = ntohl(ei[0]);
332 int_32 dl = ntohl(ei[1]);
334 entryInfo pe = (entryInfo) &ei[2];
338 int_32 pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl;
339 unsigned char * dataStart = (unsigned char *) (pe + il);
340 indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry));
341 entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info));
342 const void * sig = NULL;
344 rpmVSFlags vsflags = rpmtsVSFlags(ts);
349 unsigned char * regionEnd = NULL;
350 rpmRC rc = RPMRC_FAIL; /* assume failure */
358 /* Is the blob the right size? */
359 if (uc > 0 && pvlen != uc) {
360 (void) snprintf(buf, sizeof(buf),
361 _("blob size(%d): BAD, 8 + 16 * il(%d) + dl(%d)\n"),
362 (int)uc, (int)il, (int)dl);
366 /* Check (and convert) the 1st tag element. */
367 xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
369 (void) snprintf(buf, sizeof(buf),
370 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
371 0, entry->info.tag, entry->info.type,
372 entry->info.offset, entry->info.count);
376 /* Is there an immutable header region tag? */
378 if (!(entry->info.tag == RPMTAG_HEADERIMMUTABLE
379 && entry->info.type == RPM_BIN_TYPE
380 && entry->info.count == REGION_TAG_COUNT))
387 /* Is the offset within the data area? */
388 if (entry->info.offset >= dl) {
389 (void) snprintf(buf, sizeof(buf),
390 _("region offset: BAD, tag %d type %d offset %d count %d\n"),
391 entry->info.tag, entry->info.type,
392 entry->info.offset, entry->info.count);
396 /* Is there an immutable header region tag trailer? */
397 regionEnd = dataStart + entry->info.offset;
400 (void) memcpy(info, regionEnd, REGION_TAG_COUNT);
402 regionEnd += REGION_TAG_COUNT;
404 xx = headerVerifyInfo(1, dl, info, &entry->info, 1);
406 !(entry->info.tag == RPMTAG_HEADERIMMUTABLE
407 && entry->info.type == RPM_BIN_TYPE
408 && entry->info.count == REGION_TAG_COUNT))
410 (void) snprintf(buf, sizeof(buf),
411 _("region trailer: BAD, tag %d type %d offset %d count %d\n"),
412 entry->info.tag, entry->info.type,
413 entry->info.offset, entry->info.count);
418 memset(info, 0, sizeof(*info));
421 /* Is the no. of tags in the region less than the total no. of tags? */
422 ril = entry->info.offset/sizeof(*pe);
423 if ((entry->info.offset % sizeof(*pe)) || ril > il) {
424 (void) snprintf(buf, sizeof(buf),
425 _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
429 /* Find a header-only digest/signature tag. */
430 for (i = ril; i < il; i++) {
431 xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0);
433 (void) snprintf(buf, sizeof(buf),
434 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
435 i, entry->info.tag, entry->info.type,
436 entry->info.offset, entry->info.count);
440 switch (entry->info.tag) {
441 case RPMTAG_SHA1HEADER:
442 if (vsflags & RPMVSF_NOSHA1HEADER)
443 /*@switchbreak@*/ break;
446 for (b = dataStart + entry->info.offset; *b != '\0'; b++) {
447 if (strchr("0123456789abcdefABCDEF", *b) == NULL)
448 /*@innerbreak@*/ break;
451 if (entry->info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40)
453 (void) snprintf(buf, sizeof(buf), _("hdr SHA1: BAD, not hex\n"));
457 if (info->tag == 0) {
459 *info = entry->info; /* structure assignment */
463 /*@switchbreak@*/ break;
465 case RPMTAG_RSAHEADER:
467 case RPMTAG_DSAHEADER:
468 if (vsflags & RPMVSF_NODSAHEADER)
469 /*@switchbreak@*/ break;
470 if (entry->info.type != RPM_BIN_TYPE) {
471 (void) snprintf(buf, sizeof(buf), _("hdr DSA: BAD, not binary\n"));
475 *info = entry->info; /* structure assignment */
477 siglen = info->count;
478 /*@switchbreak@*/ break;
480 /*@switchbreak@*/ break;
486 /* Return determined RPMRC_OK/RPMRC_FAIL conditions. */
487 if (rc != RPMRC_NOTFOUND) {
489 buf[sizeof(buf)-1] = '\0';
490 if (msg) *msg = xstrdup(buf);
495 /* If no header-only digest/signature, then do simple sanity check. */
496 if (info->tag == 0) {
498 xx = headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0);
500 (void) snprintf(buf, sizeof(buf),
501 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
502 xx+1, entry->info.tag, entry->info.type,
503 entry->info.offset, entry->info.count);
506 (void) snprintf(buf, sizeof(buf), "Header sanity check: OK\n");
510 buf[sizeof(buf)-1] = '\0';
511 if (msg) *msg = xstrdup(buf);
516 /* Verify header-only digest/signature. */
519 goto verifyinfo_exit;
523 sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen);
525 (void) rpmtsSetSig(ts, info->tag, info->type, sig, info->count);
529 case RPMTAG_RSAHEADER:
530 /* Parse the parameters from the OpenPGP packets that will be needed. */
531 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
532 /* XXX only V3 signatures for now. */
533 if (dig->signature.version != 3) {
534 rpmMessage(RPMMESS_WARNING,
535 _("only V3 signatures can be verified, skipping V%u signature\n"),
536 dig->signature.version);
538 goto verifyinfo_exit;
541 ildl[0] = htonl(ril);
542 ildl[1] = (regionEnd - dataStart);
543 ildl[1] = htonl(ildl[1]);
545 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
546 dig->hdrmd5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
548 b = (unsigned char *) header_magic;
549 nb = sizeof(header_magic);
550 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
553 b = (unsigned char *) ildl;
555 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
558 b = (unsigned char *) pe;
559 nb = (htonl(ildl[0]) * sizeof(*pe));
560 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
563 b = (unsigned char *) dataStart;
565 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
567 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
571 case RPMTAG_DSAHEADER:
572 /* Parse the parameters from the OpenPGP packets that will be needed. */
573 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
574 /* XXX only V3 signatures for now. */
575 if (dig->signature.version != 3) {
576 rpmMessage(RPMMESS_WARNING,
577 _("only V3 signatures can be verified, skipping V%u signature\n"),
578 dig->signature.version);
580 goto verifyinfo_exit;
583 case RPMTAG_SHA1HEADER:
585 ildl[0] = htonl(ril);
586 ildl[1] = (regionEnd - dataStart);
587 ildl[1] = htonl(ildl[1]);
590 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
591 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
593 b = (unsigned char *) header_magic;
594 nb = sizeof(header_magic);
595 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
598 b = (unsigned char *) ildl;
600 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
603 b = (unsigned char *) pe;
604 nb = (htonl(ildl[0]) * sizeof(*pe));
605 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
608 b = (unsigned char *) dataStart;
610 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
612 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
623 rc = rpmVerifySignature(ts, buf);
626 buf[sizeof(buf)-1] = '\0';
627 if (msg) *msg = xstrdup(buf);
631 if (info->tag == RPMTAG_SHA1HEADER)
636 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, const char ** msg)
646 rpmRC rc = RPMRC_FAIL; /* assume failure */
658 memset(block, 0, sizeof(block));
659 if ((xx = timedRead(fd, (char *)block, sizeof(block))) != sizeof(block)) {
660 (void) snprintf(buf, sizeof(buf),
661 _("hdr size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx);
664 if (memcmp(block, header_magic, sizeof(header_magic))) {
665 (void) snprintf(buf, sizeof(buf), _("hdr magic: BAD\n"));
669 il = ntohl(block[2]);
671 if (hdrchkTags(il)) {
672 (void) snprintf(buf, sizeof(buf),
673 _("hdr tags: BAD, no. of tags(%d) out of range\n"), il);
678 dl = ntohl(block[3]);
680 if (hdrchkData(dl)) {
681 (void) snprintf(buf, sizeof(buf),
682 _("hdr data: BAD, no. of bytes(%d) out of range\n"), dl);
687 nb = (il * sizeof(struct entryInfo_s)) + dl;
689 uc = sizeof(il) + sizeof(dl) + nb;
694 if ((xx = timedRead(fd, (char *)&ei[2], nb)) != nb) {
695 (void) snprintf(buf, sizeof(buf),
696 _("hdr blob(%d): BAD, read returned %d\n"), nb, xx);
701 /* Sanity check header tags */
702 rc = headerCheck(ts, ei, uc, msg);
706 /* OK, blob looks sane, load the header. */
709 (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n"));
712 h->flags |= HEADERFLAG_ALLOCATED;
713 ei = NULL; /* XXX will be freed with header */
717 if (hdrp && h && rc == RPMRC_OK)
718 *hdrp = headerLink(h);
724 if (msg != NULL && *msg == NULL && buf[0] != '\0') {
725 buf[sizeof(buf)-1] = '\0';
733 /*@-bounds@*/ /* LCL: segfault */
734 rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
739 struct rpmlead * l = alloca(sizeof(*l));
749 rpmRC rc = RPMRC_FAIL; /* assume failure */
753 if (hdrp) *hdrp = NULL;
758 memset(&st, 0, sizeof(st));
760 (void) fstat(Fileno(fd), &st);
761 /* if fd points to a socket, pipe, etc, st.st_size is *always* zero */
762 if (S_ISREG(st.st_mode) && st.st_size < sizeof(*l)) {
769 memset(l, 0, sizeof(*l));
770 rc = readLead(fd, l);
776 rpmError(RPMERR_NEWPACKAGE,
777 _("packaging version 1 is not supported by this version of RPM\n"));
780 /*@notreached@*/ break;
786 rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 "
787 "is supported by this version of RPM\n"));
790 /*@notreached@*/ break;
793 /* Read the signature header. */
795 rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
798 rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed: %s"), fn,
799 (msg && *msg ? msg : "\n"));
802 /*@notreached@*/ break;
805 rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn);
813 #define _chk(_mask) (sigtag == 0 && !(vsflags & (_mask)))
815 /* Figger the most effective available signature. */
817 vsflags = rpmtsVSFlags(ts);
819 if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_DSA))
820 sigtag = RPMSIGTAG_DSA;
821 if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_RSA))
822 sigtag = RPMSIGTAG_RSA;
824 if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD) &&
825 headerIsEntry(sigh, RPMSIGTAG_GPG))
827 sigtag = RPMSIGTAG_GPG;
828 fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
830 if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD) &&
831 headerIsEntry(sigh, RPMSIGTAG_PGP))
833 sigtag = RPMSIGTAG_PGP;
834 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
837 if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, RPMSIGTAG_SHA1))
838 sigtag = RPMSIGTAG_SHA1;
840 if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
841 headerIsEntry(sigh, RPMSIGTAG_MD5))
843 sigtag = RPMSIGTAG_MD5;
844 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
847 /* Read the metadata, computing digest(s) on the fly. */
850 rc = rpmReadHeader(ts, fd, &h, &msg);
851 if (rc != RPMRC_OK || h == NULL) {
852 rpmError(RPMERR_FREAD, _("%s: headerRead failed: %s"), fn,
853 (msg && *msg ? msg : "\n"));
859 /* Any signatures to check? */
872 /* Retrieve the tag parameters from the signature header. */
874 xx = headerGetEntry(sigh, sigtag, &sigtype, (void **) &sig, &siglen);
879 (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
883 /* Parse the parameters from the OpenPGP packets that will be needed. */
884 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
885 /* XXX only V3 signatures for now. */
886 if (dig->signature.version != 3) {
887 rpmMessage(RPMMESS_WARNING,
888 _("only V3 signatures can be verified, skipping V%u signature\n"),
889 dig->signature.version);
897 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
899 dig->md5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
900 (void) rpmDigestUpdate(dig->md5ctx, header_magic, sizeof(header_magic));
901 dig->nbytes += sizeof(header_magic);
902 (void) rpmDigestUpdate(dig->md5ctx, uh, uhc);
904 uh = headerFreeData(uh, uht);
907 /* Parse the parameters from the OpenPGP packets that will be needed. */
908 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
909 /* XXX only V3 signatures for now. */
910 if (dig->signature.version != 3) {
911 rpmMessage(RPMMESS_WARNING,
912 _("only V3 signatures can be verified, skipping V%u signature\n"),
913 dig->signature.version);
923 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
925 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
926 (void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic));
927 dig->nbytes += sizeof(header_magic);
928 (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
930 uh = headerFreeData(uh, uht);
933 case RPMSIGTAG_PGP5: /* XXX legacy */
935 /* Parse the parameters from the OpenPGP packets that will be needed. */
936 xx = pgpPrtPkts(sig, siglen, dig,
937 (_print_pkts & rpmIsDebug()));
939 /* XXX only V3 signatures for now. */
940 if (dig->signature.version != 3) {
941 rpmMessage(RPMMESS_WARNING,
942 _("only V3 signatures can be verified, skipping V%u signature\n"),
943 dig->signature.version);
949 /* Legacy signatures need the compressed payload in the digest too. */
950 hmagic = ((l->major >= 3) ? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
951 dig->nbytes += headerSizeof(h, hmagic);
952 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
953 dig->nbytes += count;
955 rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
960 dig->nbytes += count;
962 /* XXX Steal the digest-in-progress from the file handle. */
963 for (i = fd->ndigests - 1; i >= 0; i--) {
964 FDDIGEST_t fddig = fd->digests + i;
965 if (fddig->hashctx == NULL)
967 if (fddig->hashalgo == PGPHASHALGO_MD5) {
968 dig->md5ctx = fddig->hashctx;
969 fddig->hashctx = NULL;
972 if (fddig->hashalgo == PGPHASHALGO_SHA1) {
973 dig->sha1ctx = fddig->hashctx;
974 fddig->hashctx = NULL;
981 /** @todo Implement disable/enable/warn/error/anal policy. */
986 rc = rpmVerifySignature(ts, buf);
988 case RPMRC_OK: /* Signature is OK. */
989 rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
991 case RPMRC_NOTTRUSTED: /* Signature is OK, but key is not trusted. */
992 case RPMRC_NOKEY: /* Public key is unavailable. */
993 /* XXX Print NOKEY/NOTTRUSTED warning only once. */
994 { int lvl = (rpmtsStashKeyid(ts) ? RPMMESS_DEBUG : RPMMESS_WARNING);
995 rpmMessage(lvl, "%s: %s", fn, buf);
997 case RPMRC_NOTFOUND: /* Signature is unknown type. */
998 rpmMessage(RPMMESS_WARNING, "%s: %s", fn, buf);
1001 case RPMRC_FAIL: /* Signature does not verify. */
1002 rpmMessage(RPMMESS_ERROR, "%s: %s", fn, buf);
1007 if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
1008 /* Convert legacy headers on the fly ... */
1009 legacyRetrofit(h, l);
1011 /* Append (and remap) signature tags to the metadata. */
1012 headerMergeLegacySigs(h, sigh);
1014 /* Bump reference count for return. */
1016 *hdrp = headerLink(h);
1021 sigh = rpmFreeSignature(sigh);