Sanitize python object -> tag number exception handling
[platform/upstream/rpm.git] / lib / package.c
1 /** \ingroup header
2  * \file lib/package.c
3  */
4
5 #include "system.h"
6
7 #include <netinet/in.h>
8
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>
14
15 #include "lib/rpmlead.h"
16 #include "lib/signature.h"
17 #include "rpmio/digest.h"
18 #include "rpmio/rpmio_internal.h"       /* fd*Digest(), fd stats */
19 #include "lib/header_internal.h"        /* XXX headerCheck */
20
21 #include "debug.h"
22
23 static int _print_pkts = 0;
24
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;
29
30 void headerMergeLegacySigs(Header h, const Header sigh)
31 {
32     HeaderIterator hi;
33     struct rpmtd_s td;
34
35     hi = headerInitIterator(sigh);
36     for (; headerNext(hi, &td); rpmtdFreeData(&td))
37     {
38         switch (td.tag) {
39         /* XXX Translate legacy signature tag values. */
40         case RPMSIGTAG_SIZE:
41             td.tag = RPMTAG_SIGSIZE;
42             break;
43         case RPMSIGTAG_PGP:
44             td.tag = RPMTAG_SIGPGP;
45             break;
46         case RPMSIGTAG_MD5:
47             td.tag = RPMTAG_SIGMD5;
48             break;
49         case RPMSIGTAG_GPG:
50             td.tag = RPMTAG_SIGGPG;
51             break;
52         case RPMSIGTAG_PGP5:
53             td.tag = RPMTAG_SIGPGP5;
54             break;
55         case RPMSIGTAG_PAYLOADSIZE:
56             td.tag = RPMTAG_ARCHIVESIZE;
57             break;
58         case RPMSIGTAG_SHA1:
59         case RPMSIGTAG_DSA:
60         case RPMSIGTAG_RSA:
61         default:
62             if (!(td.tag >= HEADER_SIGBASE && td.tag < HEADER_TAGBASE))
63                 continue;
64             break;
65         }
66         if (td.data == NULL) continue;  /* XXX can't happen */
67         if (!headerIsEntry(h, td.tag)) {
68             if (hdrchkType(td.type))
69                 continue;
70             if (td.count < 0 || hdrchkData(td.count))
71                 continue;
72             switch(td.type) {
73             case RPM_NULL_TYPE:
74                 continue;
75                 break;
76             case RPM_CHAR_TYPE:
77             case RPM_INT8_TYPE:
78             case RPM_INT16_TYPE:
79             case RPM_INT32_TYPE:
80             case RPM_INT64_TYPE:
81                 if (td.count != 1)
82                     continue;
83                 break;
84             case RPM_STRING_TYPE:
85             case RPM_BIN_TYPE:
86                 if (td.count >= 16*1024)
87                     continue;
88                 break;
89             case RPM_STRING_ARRAY_TYPE:
90             case RPM_I18NSTRING_TYPE:
91                 continue;
92                 break;
93             }
94             (void) headerPut(h, &td, HEADERPUT_DEFAULT);
95         }
96     }
97     hi = headerFreeIterator(hi);
98 }
99
100 Header headerRegenSigHeader(const Header h, int noArchiveSize)
101 {
102     Header sigh = rpmNewSignature();
103     HeaderIterator hi;
104     struct rpmtd_s td;
105
106     for (hi = headerInitIterator(h); headerNext(hi, &td); rpmtdFreeData(&td)) {
107         switch (td.tag) {
108         /* XXX Translate legacy signature tag values. */
109         case RPMTAG_SIGSIZE:
110             td.tag = RPMSIGTAG_SIZE;
111             break;
112         case RPMTAG_SIGPGP:
113             td.tag = RPMSIGTAG_PGP;
114             break;
115         case RPMTAG_SIGMD5:
116             td.tag = RPMSIGTAG_MD5;
117             break;
118         case RPMTAG_SIGGPG:
119             td.tag = RPMSIGTAG_GPG;
120             break;
121         case RPMTAG_SIGPGP5:
122             td.tag = RPMSIGTAG_PGP5;
123             break;
124         case RPMTAG_ARCHIVESIZE:
125             /* XXX rpm-4.1 and later has archive size in signature header. */
126             if (noArchiveSize)
127                 continue;
128             td.tag = RPMSIGTAG_PAYLOADSIZE;
129             break;
130         case RPMTAG_SHA1HEADER:
131         case RPMTAG_DSAHEADER:
132         case RPMTAG_RSAHEADER:
133         default:
134             if (!(td.tag >= HEADER_SIGBASE && td.tag < HEADER_TAGBASE))
135                 continue;
136             break;
137         }
138         if (td.data == NULL) continue;  /* XXX can't happen */
139         if (!headerIsEntry(sigh, td.tag))
140             (void) headerPut(sigh, &td, HEADERPUT_DEFAULT);
141     }
142     hi = headerFreeIterator(hi);
143     return sigh;
144 }
145
146 /**
147  * Remember current key id.
148  * @param dig           OpenPGP packet containter
149  * @return              0 if new keyid, otherwise 1
150  */
151 static int stashKeyid(pgpDig dig)
152 {
153     pgpDigParams sigp = dig ? &dig->signature : NULL;
154     unsigned int keyid;
155     int i;
156
157     if (dig == NULL || sigp == NULL)
158         return 0;
159
160     keyid = pgpGrab(sigp->signid+4, 4);
161     if (keyid == 0)
162         return 0;
163
164     if (keyids != NULL)
165     for (i = 0; i < nkeyids; i++) {
166         if (keyid == keyids[i])
167             return 1;
168     }
169
170     if (nkeyids < nkeyids_max) {
171         nkeyids++;
172         keyids = xrealloc(keyids, nkeyids * sizeof(*keyids));
173     }
174     if (keyids)         /* XXX can't happen */
175         keyids[nextkeyid] = keyid;
176     nextkeyid++;
177     nextkeyid %= nkeyids_max;
178
179     return 0;
180 }
181
182 /* Parse the parameters from the OpenPGP packets that will be needed. */
183 static rpmRC parsePGP(rpmtd sigtd, const char *type, pgpDig dig)
184 {
185     rpmRC rc = RPMRC_FAIL;
186     int debug = (_print_pkts & rpmIsDebug());
187     if ((pgpPrtPkts(sigtd->data, sigtd->count, dig, debug) == 0) &&
188          (dig->signature.version == 3 || dig->signature.version == 4)) {
189         rc = RPMRC_OK;
190     } else {
191         rpmlog(RPMLOG_ERR,
192             _("skipping %s with unverifiable V%u signature\n"), type,
193             dig->signature.version);
194     }
195     return rc;
196 }
197
198 static rpmRC headerVerify(rpmKeyring keyring, rpmVSFlags vsflags,
199                           const void * uh, size_t uc, char ** msg)
200 {
201     pgpDig dig = NULL;
202     char *buf = NULL;
203     int32_t * ei = (int32_t *) uh;
204     int32_t il = ntohl(ei[0]);
205     int32_t dl = ntohl(ei[1]);
206     entryInfo pe = (entryInfo) &ei[2];
207     int32_t ildl[2];
208     int32_t pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl;
209     unsigned char * dataStart = (unsigned char *) (pe + il);
210     struct indexEntry_s entry;
211     struct entryInfo_s info;
212     unsigned const char * b;
213     size_t siglen = 0;
214     size_t blen;
215     size_t nb;
216     int32_t ril = 0;
217     unsigned char * regionEnd = NULL;
218     rpmRC rc = RPMRC_FAIL;      /* assume failure */
219     int xx;
220     int i;
221     struct rpmtd_s sigtd;
222     DIGEST_CTX ctx = NULL;
223
224     /* Is the blob the right size? */
225     if (uc > 0 && pvlen != uc) {
226         rasprintf(&buf, _("blob size(%d): BAD, 8 + 16 * il(%d) + dl(%d)\n"),
227                 (int)uc, (int)il, (int)dl);
228         goto exit;
229     }
230
231     memset(&entry, 0, sizeof(entry));
232     memset(&info, 0, sizeof(info));
233
234     /* Check (and convert) the 1st tag element. */
235     xx = headerVerifyInfo(1, dl, pe, &entry.info, 0);
236     if (xx != -1) {
237         rasprintf(&buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
238                 0, entry.info.tag, entry.info.type,
239                 entry.info.offset, entry.info.count);
240         goto exit;
241     }
242
243     /* Is there an immutable header region tag? */
244     if (!(entry.info.tag == RPMTAG_HEADERIMMUTABLE
245        && entry.info.type == RPM_BIN_TYPE
246        && entry.info.count == REGION_TAG_COUNT))
247     {
248         rc = RPMRC_NOTFOUND;
249         goto exit;
250     }
251
252     /* Is the offset within the data area? */
253     if (entry.info.offset >= dl) {
254         rasprintf(&buf, 
255                 _("region offset: BAD, tag %d type %d offset %d count %d\n"),
256                 entry.info.tag, entry.info.type,
257                 entry.info.offset, entry.info.count);
258         goto exit;
259     }
260
261     /* Is there an immutable header region tag trailer? */
262     regionEnd = dataStart + entry.info.offset;
263     (void) memcpy(&info, regionEnd, REGION_TAG_COUNT);
264     regionEnd += REGION_TAG_COUNT;
265
266     xx = headerVerifyInfo(1, dl, &info, &entry.info, 1);
267     if (xx != -1 ||
268         !(entry.info.tag == RPMTAG_HEADERIMMUTABLE
269        && entry.info.type == RPM_BIN_TYPE
270        && entry.info.count == REGION_TAG_COUNT))
271     {
272         rasprintf(&buf, 
273                 _("region trailer: BAD, tag %d type %d offset %d count %d\n"),
274                 entry.info.tag, entry.info.type,
275                 entry.info.offset, entry.info.count);
276         goto exit;
277     }
278     memset(&info, 0, sizeof(info));
279
280     /* Is the no. of tags in the region less than the total no. of tags? */
281     ril = entry.info.offset/sizeof(*pe);
282     if ((entry.info.offset % sizeof(*pe)) || ril > il) {
283         rasprintf(&buf, _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
284         goto exit;
285     }
286
287     /* Find a header-only digest/signature tag. */
288     for (i = ril; i < il; i++) {
289         xx = headerVerifyInfo(1, dl, pe+i, &entry.info, 0);
290         if (xx != -1) {
291             rasprintf(&buf,
292                 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
293                 i, entry.info.tag, entry.info.type,
294                 entry.info.offset, entry.info.count);
295             goto exit;
296         }
297
298         switch (entry.info.tag) {
299         case RPMTAG_SHA1HEADER:
300             if (vsflags & RPMVSF_NOSHA1HEADER)
301                 break;
302             blen = 0;
303             for (b = dataStart + entry.info.offset; *b != '\0'; b++) {
304                 if (strchr("0123456789abcdefABCDEF", *b) == NULL)
305                     break;
306                 blen++;
307             }
308             if (entry.info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40)
309             {
310                 rasprintf(&buf, _("hdr SHA1: BAD, not hex\n"));
311                 goto exit;
312             }
313             if (info.tag == 0) {
314                 info = entry.info;      /* structure assignment */
315                 siglen = blen + 1;
316             }
317             break;
318         case RPMTAG_RSAHEADER:
319             if (vsflags & RPMVSF_NORSAHEADER)
320                 break;
321             if (entry.info.type != RPM_BIN_TYPE) {
322                 rasprintf(&buf, _("hdr RSA: BAD, not binary\n"));
323                 goto exit;
324             }
325             info = entry.info;  /* structure assignment */
326             siglen = info.count;
327             break;
328         case RPMTAG_DSAHEADER:
329             if (vsflags & RPMVSF_NODSAHEADER)
330                 break;
331             if (entry.info.type != RPM_BIN_TYPE) {
332                 rasprintf(&buf, _("hdr DSA: BAD, not binary\n"));
333                 goto exit;
334             }
335             info = entry.info;  /* structure assignment */
336             siglen = info.count;
337             break;
338         default:
339             break;
340         }
341     }
342     rc = RPMRC_NOTFOUND;
343
344 exit:
345     /* Return determined RPMRC_OK/RPMRC_FAIL conditions. */
346     if (rc != RPMRC_NOTFOUND) {
347         if (msg) 
348             *msg = buf;
349         else
350             free(buf);
351         return rc;
352     }
353
354     /* If no header-only digest/signature, then do simple sanity check. */
355     if (info.tag == 0) {
356 verifyinfo_exit:
357         xx = headerVerifyInfo(ril-1, dl, pe+1, &entry.info, 0);
358         if (xx != -1) {
359             rasprintf(&buf,
360                 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
361                 xx+1, entry.info.tag, entry.info.type,
362                 entry.info.offset, entry.info.count);
363             rc = RPMRC_FAIL;
364         } else {
365             rasprintf(&buf, "Header sanity check: OK\n");
366             rc = RPMRC_OK;
367         }
368         if (msg) 
369             *msg = buf;
370         else
371             free(buf);
372         return rc;
373     }
374
375     /* Verify header-only digest/signature. */
376     dig = pgpNewDig();
377     if (dig == NULL)
378         goto verifyinfo_exit;
379
380     sigtd.tag = info.tag;
381     sigtd.type = info.type;
382     sigtd.count = info.count;
383     sigtd.data = memcpy(xmalloc(siglen), dataStart + info.offset, siglen);
384     sigtd.flags = RPMTD_ALLOCED;
385
386     switch (info.tag) {
387     case RPMTAG_RSAHEADER:
388     case RPMTAG_DSAHEADER:
389         if ((rc = parsePGP(&sigtd, "header", dig)) != RPMRC_OK) {
390             pgpFreeDig(dig);
391             goto exit;
392         }
393         /* fallthrough */
394     case RPMTAG_SHA1HEADER: {
395         pgpHashAlgo hashalgo = (info.tag == RPMTAG_SHA1HEADER) ?
396                                 PGPHASHALGO_SHA1 : dig->signature.hash_algo;
397         ildl[0] = htonl(ril);
398         ildl[1] = (regionEnd - dataStart);
399         ildl[1] = htonl(ildl[1]);
400
401         ctx = rpmDigestInit(hashalgo, RPMDIGEST_NONE);
402
403         b = (unsigned char *) rpm_header_magic;
404         nb = sizeof(rpm_header_magic);
405         (void) rpmDigestUpdate(ctx, b, nb);
406
407         b = (unsigned char *) ildl;
408         nb = sizeof(ildl);
409         (void) rpmDigestUpdate(ctx, b, nb);
410
411         b = (unsigned char *) pe;
412         nb = (htonl(ildl[0]) * sizeof(*pe));
413         (void) rpmDigestUpdate(ctx, b, nb);
414
415         b = (unsigned char *) dataStart;
416         nb = htonl(ildl[1]);
417         (void) rpmDigestUpdate(ctx, b, nb);
418         } break;
419     default:
420         sigtd.data = _free(sigtd.data); /* Hmm...? */
421         break;
422     }
423
424     rc = rpmVerifySignature(keyring, &sigtd, dig, ctx, &buf);
425
426     if (msg) 
427         *msg = buf;
428     else
429         free(buf);
430
431     rpmtdFreeData(&sigtd);
432     pgpFreeDig(dig);
433     rpmDigestFinal(ctx, NULL, NULL, 0);
434     return rc;
435 }
436
437 rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, char ** msg)
438 {
439     rpmRC rc;
440     rpmVSFlags vsflags = rpmtsVSFlags(ts);
441     rpmKeyring keyring = rpmtsGetKeyring(ts, 1);
442
443     rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
444     rc = headerVerify(keyring, vsflags, uh, uc, msg);
445     rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), uc);
446     rpmKeyringFree(keyring);
447
448     return rc;
449 }
450
451 static rpmRC rpmpkgReadHeader(rpmKeyring keyring, rpmVSFlags vsflags, 
452                        FD_t fd, Header *hdrp, char ** msg)
453 {
454     char *buf = NULL;
455     int32_t block[4];
456     int32_t il;
457     int32_t dl;
458     int32_t * ei = NULL;
459     size_t uc;
460     size_t nb;
461     Header h = NULL;
462     rpmRC rc = RPMRC_FAIL;              /* assume failure */
463     int xx;
464
465     if (hdrp)
466         *hdrp = NULL;
467     if (msg)
468         *msg = NULL;
469
470     memset(block, 0, sizeof(block));
471     if ((xx = timedRead(fd, (char *)block, sizeof(block))) != sizeof(block)) {
472         rasprintf(&buf, 
473                 _("hdr size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx);
474         goto exit;
475     }
476     if (memcmp(block, rpm_header_magic, sizeof(rpm_header_magic))) {
477         rasprintf(&buf, _("hdr magic: BAD\n"));
478         goto exit;
479     }
480     il = ntohl(block[2]);
481     if (hdrchkTags(il)) {
482         rasprintf(&buf, _("hdr tags: BAD, no. of tags(%d) out of range\n"), il);
483         goto exit;
484     }
485     dl = ntohl(block[3]);
486     if (hdrchkData(dl)) {
487         rasprintf(&buf,
488                   _("hdr data: BAD, no. of bytes(%d) out of range\n"), dl);
489         goto exit;
490     }
491
492     nb = (il * sizeof(struct entryInfo_s)) + dl;
493     uc = sizeof(il) + sizeof(dl) + nb;
494     ei = xmalloc(uc);
495     ei[0] = block[2];
496     ei[1] = block[3];
497     if ((xx = timedRead(fd, (char *)&ei[2], nb)) != nb) {
498         rasprintf(&buf, _("hdr blob(%zd): BAD, read returned %d\n"), nb, xx);
499         goto exit;
500     }
501
502     /* Sanity check header tags */
503     rc = headerVerify(keyring, vsflags, ei, uc, msg);
504     if (rc != RPMRC_OK)
505         goto exit;
506
507     /* OK, blob looks sane, load the header. */
508     h = headerLoad(ei);
509     if (h == NULL) {
510         rasprintf(&buf, _("hdr load: BAD\n"));
511         rc = RPMRC_FAIL;
512         goto exit;
513     }
514     ei = NULL;  /* XXX will be freed with header */
515     
516 exit:
517     if (hdrp && h && rc == RPMRC_OK)
518         *hdrp = headerLink(h);
519     ei = _free(ei);
520     h = headerFree(h);
521
522     if (msg != NULL && *msg == NULL && buf != NULL) {
523         *msg = buf;
524     } else {
525         free(buf);
526     }
527
528     return rc;
529 }
530
531 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, char ** msg)
532 {
533     rpmRC rc;
534     rpmKeyring keyring = rpmtsGetKeyring(ts, 1);
535     rpmVSFlags vsflags = rpmtsVSFlags(ts);
536
537     rc = rpmpkgReadHeader(keyring, vsflags, fd, hdrp, msg);
538
539     rpmKeyringFree(keyring);
540     return rc;
541 }
542
543 static rpmRC rpmpkgRead(rpmKeyring keyring, rpmVSFlags vsflags, 
544                         FD_t fd, const char * fn, Header * hdrp)
545 {
546     pgpDig dig = NULL;
547     char buf[8*BUFSIZ];
548     ssize_t count;
549     rpmlead l = NULL;
550     Header sigh = NULL;
551     rpmSigTag sigtag;
552     struct rpmtd_s sigtd;
553     Header h = NULL;
554     char * msg;
555     rpmRC rc = RPMRC_FAIL;      /* assume failure */
556     int leadtype = -1;
557     headerGetFlags hgeflags = HEADERGET_DEFAULT;
558     DIGEST_CTX ctx = NULL;
559
560     if (hdrp) *hdrp = NULL;
561
562     rpmtdReset(&sigtd);
563     l = rpmLeadNew();
564
565     if ((rc = rpmLeadRead(fd, l)) == RPMRC_OK) {
566         const char * err = NULL;
567         if ((rc = rpmLeadCheck(l, &err)) == RPMRC_FAIL) {
568             rpmlog(RPMLOG_ERR, "%s: %s\n", fn, err);
569         }
570         leadtype = rpmLeadType(l);
571     }
572     l = rpmLeadFree(l);
573
574     if (rc != RPMRC_OK)
575         goto exit;
576
577     /* Read the signature header. */
578     msg = NULL;
579     rc = rpmReadSignature(fd, &sigh, RPMSIGTYPE_HEADERSIG, &msg);
580     switch (rc) {
581     default:
582         rpmlog(RPMLOG_ERR, _("%s: rpmReadSignature failed: %s"), fn,
583                 (msg && *msg ? msg : "\n"));
584         msg = _free(msg);
585         goto exit;
586         break;
587     case RPMRC_OK:
588         if (sigh == NULL) {
589             rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), fn);
590             rc = RPMRC_FAIL;
591             goto exit;
592         }
593         break;
594     }
595     msg = _free(msg);
596
597 #define _chk(_mask, _tag) \
598         (sigtag == 0 && !(vsflags & (_mask)) && headerIsEntry(sigh, (_tag)))
599
600     /*
601      * Figger the most effective available signature.
602      * Prefer signatures over digests, then header-only over header+payload.
603      * DSA will be preferred over RSA if both exist because tested first.
604      * Note that NEEDPAYLOAD prevents header+payload signatures and digests.
605      */
606     sigtag = 0;
607     if (_chk(RPMVSF_NODSAHEADER, RPMSIGTAG_DSA)) {
608         sigtag = RPMSIGTAG_DSA;
609     } else if (_chk(RPMVSF_NORSAHEADER, RPMSIGTAG_RSA)) {
610         sigtag = RPMSIGTAG_RSA;
611     } else if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD, RPMSIGTAG_GPG)) {
612         sigtag = RPMSIGTAG_GPG;
613         fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
614     } else if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD, RPMSIGTAG_PGP)) {
615         sigtag = RPMSIGTAG_PGP;
616         fdInitDigest(fd, PGPHASHALGO_MD5, 0);
617     } else if (_chk(RPMVSF_NOSHA1HEADER, RPMSIGTAG_SHA1)) {
618         sigtag = RPMSIGTAG_SHA1;
619     } else if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD, RPMSIGTAG_MD5)) {
620         sigtag = RPMSIGTAG_MD5;
621         fdInitDigest(fd, PGPHASHALGO_MD5, 0);
622     }
623
624     /* Read the metadata, computing digest(s) on the fly. */
625     h = NULL;
626     msg = NULL;
627
628     rc = rpmpkgReadHeader(keyring, vsflags, fd, &h, &msg);
629
630     if (rc != RPMRC_OK || h == NULL) {
631         rpmlog(RPMLOG_ERR, _("%s: headerRead failed: %s"), fn,
632                 (msg && *msg ? msg : "\n"));
633         msg = _free(msg);
634         goto exit;
635     }
636     msg = _free(msg);
637
638     /* Any digests or signatures to check? */
639     if (sigtag == 0) {
640         rc = RPMRC_OK;
641         goto exit;
642     }
643
644     dig = pgpNewDig();
645     if (dig == NULL) {
646         rc = RPMRC_FAIL;
647         goto exit;
648     }
649
650     /* Retrieve the tag parameters from the signature header. */
651     if (!headerGet(sigh, sigtag, &sigtd, hgeflags)) {
652         rc = RPMRC_FAIL;
653         goto exit;
654     }
655
656     switch (sigtag) {
657     case RPMSIGTAG_RSA:
658     case RPMSIGTAG_DSA:
659         if ((rc = parsePGP(&sigtd, "package", dig)) != RPMRC_OK) {
660             goto exit;
661         }
662         /* fallthrough */
663     case RPMSIGTAG_SHA1:
664     {   struct rpmtd_s utd;
665         pgpHashAlgo hashalgo = (sigtag == RPMSIGTAG_SHA1) ?
666                             PGPHASHALGO_SHA1 : dig->signature.hash_algo;
667
668         if (!headerGet(h, RPMTAG_HEADERIMMUTABLE, &utd, hgeflags))
669             break;
670         ctx = rpmDigestInit(hashalgo, RPMDIGEST_NONE);
671         (void) rpmDigestUpdate(ctx, rpm_header_magic, sizeof(rpm_header_magic));
672         (void) rpmDigestUpdate(ctx, utd.data, utd.count);
673         rpmtdFreeData(&utd);
674     }   break;
675     case RPMSIGTAG_GPG:
676     case RPMSIGTAG_PGP5:        /* XXX legacy */
677     case RPMSIGTAG_PGP:
678         if ((rc = parsePGP(&sigtd, "package", dig)) != RPMRC_OK) {
679             goto exit;
680         }
681         /* fallthrough */
682     case RPMSIGTAG_MD5:
683         /* Legacy signatures need the compressed payload in the digest too. */
684         while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0) {}
685         if (count < 0) {
686             rpmlog(RPMLOG_ERR, _("%s: Fread failed: %s\n"),
687                                         fn, Fstrerror(fd));
688             rc = RPMRC_FAIL;
689             goto exit;
690         }
691
692         ctx = rpmDigestBundleDupCtx(fd->digests, (sigtag == RPMSIGTAG_MD5) ?
693                                     PGPHASHALGO_MD5 : dig->signature.hash_algo);
694         break;
695     default:
696         break;
697     }
698
699     /** @todo Implement disable/enable/warn/error/anal policy. */
700     rc = rpmVerifySignature(keyring, &sigtd, dig, ctx, &msg);
701         
702     switch (rc) {
703     case RPMRC_OK:              /* Signature is OK. */
704         rpmlog(RPMLOG_DEBUG, "%s: %s", fn, msg);
705         break;
706     case RPMRC_NOTTRUSTED:      /* Signature is OK, but key is not trusted. */
707     case RPMRC_NOKEY:           /* Public key is unavailable. */
708         /* XXX Print NOKEY/NOTTRUSTED warning only once. */
709     {   int lvl = (stashKeyid(dig) ? RPMLOG_DEBUG : RPMLOG_WARNING);
710         rpmlog(lvl, "%s: %s", fn, msg);
711     }   break;
712     case RPMRC_NOTFOUND:        /* Signature is unknown type. */
713         rpmlog(RPMLOG_WARNING, "%s: %s", fn, msg);
714         break;
715     default:
716     case RPMRC_FAIL:            /* Signature does not verify. */
717         rpmlog(RPMLOG_ERR, "%s: %s", fn, msg);
718         break;
719     }
720     free(msg);
721
722 exit:
723     if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
724         /* Retrofit RPMTAG_SOURCEPACKAGE to srpms for compatibility */
725         if (leadtype == RPMLEAD_SOURCE && headerIsSource(h)) {
726             if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE)) {
727                 uint32_t one = 1;
728                 headerPutUint32(h, RPMTAG_SOURCEPACKAGE, &one, 1);
729             }
730         }
731         /*
732          * Try to make sure binary rpms have RPMTAG_SOURCERPM set as that's
733          * what we use for differentiating binary vs source elsewhere.
734          */
735         if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE) && headerIsSource(h)) {
736             headerPutString(h, RPMTAG_SOURCERPM, "(none)");
737         }
738         /* 
739          * Convert legacy headers on the fly. Not having "new" style compressed
740          * filenames is close enough estimate for legacy indication... 
741          */
742         if (!headerIsEntry(h, RPMTAG_DIRNAMES)) {
743             headerConvert(h, HEADERCONV_RETROFIT_V3);
744         }
745         
746         /* Append (and remap) signature tags to the metadata. */
747         headerMergeLegacySigs(h, sigh);
748
749         /* Bump reference count for return. */
750         *hdrp = headerLink(h);
751     }
752     rpmtdFreeData(&sigtd);
753     rpmDigestFinal(ctx, NULL, NULL, 0);
754     h = headerFree(h);
755     pgpFreeDig(dig);
756     sigh = rpmFreeSignature(sigh);
757     return rc;
758 }
759
760 rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
761 {
762     rpmRC rc;
763     rpmKeyring keyring = rpmtsGetKeyring(ts, 1);
764     rpmVSFlags vsflags = rpmtsVSFlags(ts);
765
766     rc = rpmpkgRead(keyring, vsflags, fd, fn, hdrp);
767
768     rpmKeyringFree(keyring);
769     return rc;
770 }
771
772 /**
773  * Check for supported payload format in header.
774  * @param h             header to check
775  * @return              RPMRC_OK if supported, RPMRC_FAIL otherwise
776  */
777 rpmRC headerCheckPayloadFormat(Header h) {
778     rpmRC rc = RPMRC_OK;
779     const char *payloadfmt = headerGetString(h, RPMTAG_PAYLOADFORMAT);
780     /* 
781      * XXX Ugh, rpm 3.x packages don't have payload format tag. Instead
782      * of blinly allowing, should check somehow (HDRID existence or... ?)
783      */
784     if (!payloadfmt) return rc;
785
786     if (!rstreq(payloadfmt, "cpio")) {
787         char *nevra = headerGetAsString(h, RPMTAG_NEVRA);
788         if (payloadfmt && rstreq(payloadfmt, "drpm")) {
789             rpmlog(RPMLOG_ERR,
790                      _("%s is a Delta RPM and cannot be directly installed\n"),
791                      nevra);
792         } else {
793             rpmlog(RPMLOG_ERR, 
794                      _("Unsupported payload (%s) in package %s\n"),
795                      payloadfmt ? payloadfmt : "none", nevra);
796         } 
797         nevra = _free(nevra);
798         rc = RPMRC_FAIL;
799     }
800     return rc;
801 }
802
803