Mark another pile of header_magic duplicates as read-only
[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
13 #include "lib/legacy.h" /* XXX legacyRetrofit() */
14 #include "lib/rpmlead.h"
15 #include "lib/signature.h"
16 #include "rpmio/digest.h"
17 #include "rpmio/rpmio_internal.h"       /* fd*Digest(), fd stats */
18 #include "rpmdb/header_internal.h"      /* XXX headerCheck */
19
20 #include "debug.h"
21
22 #define alloca_strdup(_s)       strcpy(alloca(strlen(_s)+1), (_s))
23
24 static int _print_pkts = 0;
25
26 static unsigned int nkeyids_max = 256;
27 static unsigned int nkeyids = 0;
28 static unsigned int nextkeyid  = 0;
29 static unsigned int * keyids;
30
31 /* XXX FIXME: these are doubled here and header.c and .. */
32 static unsigned char const header_magic[8] = {
33         0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
34 };
35
36 /**
37  * Alignment needs (and sizeof scalars types) for internal rpm data types.
38  */
39 static int const typeAlign[16] =  {
40     1,  /*!< RPM_NULL_TYPE */
41     1,  /*!< RPM_CHAR_TYPE */
42     1,  /*!< RPM_INT8_TYPE */
43     2,  /*!< RPM_INT16_TYPE */
44     4,  /*!< RPM_INT32_TYPE */
45     8,  /*!< RPM_INT64_TYPE */
46     1,  /*!< RPM_STRING_TYPE */
47     1,  /*!< RPM_BIN_TYPE */
48     1,  /*!< RPM_STRING_ARRAY_TYPE */
49     1,  /*!< RPM_I18NSTRING_TYPE */
50     0,
51     0,
52     0,
53     0,
54     0,
55     0
56 };
57
58 /**
59  * Sanity check on no. of tags.
60  * This check imposes a limit of 65K tags, more than enough.
61  */
62 #define hdrchkTags(_ntags)      ((_ntags) & 0xffff0000)
63
64 /**
65  * Sanity check on type values.
66  */
67 #define hdrchkType(_type) ((_type) < RPM_MIN_TYPE || (_type) > RPM_MAX_TYPE)
68
69 /**
70  * Sanity check on data size and/or offset and/or count.
71  * This check imposes a limit of 16 MB, more than enough.
72  */
73 #define hdrchkData(_nbytes) ((_nbytes) & 0xff000000)
74
75 /**
76  * Sanity check on data alignment for data type.
77  */
78 #define hdrchkAlign(_type, _off)        ((_off) & (typeAlign[_type]-1))
79
80 /**
81  * Sanity check on range of data offset.
82  */
83 #define hdrchkRange(_dl, _off)          ((_off) < 0 || (_off) > (_dl))
84
85 void headerMergeLegacySigs(Header h, const Header sigh)
86 {
87     HFD_t hfd = (HFD_t) headerFreeData;
88     HAE_t hae = (HAE_t) headerAddEntry;
89     HeaderIterator hi;
90     rpmTagType type;
91     rpmTag tag;
92     rpm_count_t count;
93     rpm_data_t ptr;
94     int xx;
95
96     for (hi = headerInitIterator(sigh);
97         headerNextIterator(hi, &tag, &type, &ptr, &count);
98         ptr = hfd(ptr, type))
99     {
100         switch (tag) {
101         /* XXX Translate legacy signature tag values. */
102         case RPMSIGTAG_SIZE:
103             tag = RPMTAG_SIGSIZE;
104             break;
105         case RPMSIGTAG_LEMD5_1:
106             tag = RPMTAG_SIGLEMD5_1;
107             break;
108         case RPMSIGTAG_PGP:
109             tag = RPMTAG_SIGPGP;
110             break;
111         case RPMSIGTAG_LEMD5_2:
112             tag = RPMTAG_SIGLEMD5_2;
113             break;
114         case RPMSIGTAG_MD5:
115             tag = RPMTAG_SIGMD5;
116             break;
117         case RPMSIGTAG_GPG:
118             tag = RPMTAG_SIGGPG;
119             break;
120         case RPMSIGTAG_PGP5:
121             tag = RPMTAG_SIGPGP5;
122             break;
123         case RPMSIGTAG_PAYLOADSIZE:
124             tag = RPMTAG_ARCHIVESIZE;
125             break;
126         case RPMSIGTAG_SHA1:
127         case RPMSIGTAG_DSA:
128         case RPMSIGTAG_RSA:
129         default:
130             if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
131                 continue;
132             break;
133         }
134         if (ptr == NULL) continue;      /* XXX can't happen */
135         if (!headerIsEntry(h, tag)) {
136             if (hdrchkType(type))
137                 continue;
138             if (count < 0 || hdrchkData(count))
139                 continue;
140             switch(type) {
141             case RPM_NULL_TYPE:
142                 continue;
143                 break;
144             case RPM_CHAR_TYPE:
145             case RPM_INT8_TYPE:
146             case RPM_INT16_TYPE:
147             case RPM_INT32_TYPE:
148                 if (count != 1)
149                     continue;
150                 break;
151             case RPM_STRING_TYPE:
152             case RPM_BIN_TYPE:
153                 if (count >= 16*1024)
154                     continue;
155                 break;
156             case RPM_STRING_ARRAY_TYPE:
157             case RPM_I18NSTRING_TYPE:
158                 continue;
159                 break;
160             }
161             xx = hae(h, tag, type, ptr, count);
162         }
163     }
164     hi = headerFreeIterator(hi);
165 }
166
167 Header headerRegenSigHeader(const Header h, int noArchiveSize)
168 {
169     HFD_t hfd = (HFD_t) headerFreeData;
170     Header sigh = rpmNewSignature();
171     HeaderIterator hi;
172     rpm_count_t count;
173     rpmTag tag, stag;
174     rpmTagType type;
175     rpm_data_t ptr;
176     int xx;
177
178     for (hi = headerInitIterator(h);
179         headerNextIterator(hi, &tag, &type, &ptr, &count);
180         ptr = hfd(ptr, type))
181     {
182         switch (tag) {
183         /* XXX Translate legacy signature tag values. */
184         case RPMTAG_SIGSIZE:
185             stag = RPMSIGTAG_SIZE;
186             break;
187         case RPMTAG_SIGLEMD5_1:
188             stag = RPMSIGTAG_LEMD5_1;
189             break;
190         case RPMTAG_SIGPGP:
191             stag = RPMSIGTAG_PGP;
192             break;
193         case RPMTAG_SIGLEMD5_2:
194             stag = RPMSIGTAG_LEMD5_2;
195             break;
196         case RPMTAG_SIGMD5:
197             stag = RPMSIGTAG_MD5;
198             break;
199         case RPMTAG_SIGGPG:
200             stag = RPMSIGTAG_GPG;
201             break;
202         case RPMTAG_SIGPGP5:
203             stag = RPMSIGTAG_PGP5;
204             break;
205         case RPMTAG_ARCHIVESIZE:
206             /* XXX rpm-4.1 and later has archive size in signature header. */
207             if (noArchiveSize)
208                 continue;
209             stag = RPMSIGTAG_PAYLOADSIZE;
210             break;
211         case RPMTAG_SHA1HEADER:
212         case RPMTAG_DSAHEADER:
213         case RPMTAG_RSAHEADER:
214         default:
215             if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
216                 continue;
217             stag = tag;
218             break;
219         }
220         if (ptr == NULL) continue;      /* XXX can't happen */
221         if (!headerIsEntry(sigh, stag))
222             xx = headerAddEntry(sigh, stag, type, ptr, count);
223     }
224     hi = headerFreeIterator(hi);
225     return sigh;
226 }
227
228 /**
229  * Remember current key id.
230  * @param ts            transaction set
231  * @return              0 if new keyid, otherwise 1
232  */
233 static int rpmtsStashKeyid(rpmts ts)
234 {
235     const void * sig = rpmtsSig(ts);
236     pgpDig dig = rpmtsDig(ts);
237     pgpDigParams sigp = rpmtsSignature(ts);
238     unsigned int keyid;
239     int i;
240
241     if (sig == NULL || dig == NULL || sigp == NULL)
242         return 0;
243
244     keyid = pgpGrab(sigp->signid+4, 4);
245     if (keyid == 0)
246         return 0;
247
248     if (keyids != NULL)
249     for (i = 0; i < nkeyids; i++) {
250         if (keyid == keyids[i])
251             return 1;
252     }
253
254     if (nkeyids < nkeyids_max) {
255         nkeyids++;
256         keyids = xrealloc(keyids, nkeyids * sizeof(*keyids));
257     }
258     if (keyids)         /* XXX can't happen */
259         keyids[nextkeyid] = keyid;
260     nextkeyid++;
261     nextkeyid %= nkeyids_max;
262
263     return 0;
264 }
265
266 int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate)
267 {
268     entryInfo pe = (entryInfo) pev;
269     entryInfo info = iv;
270     int i;
271
272     for (i = 0; i < il; i++) {
273         info->tag = ntohl(pe[i].tag);
274         info->type = ntohl(pe[i].type);
275         info->offset = ntohl(pe[i].offset);
276         if (negate)
277             info->offset = -info->offset;
278         info->count = ntohl(pe[i].count);
279
280         if (hdrchkType(info->type))
281             return i;
282         if (hdrchkAlign(info->type, info->offset))
283             return i;
284         if (!negate && hdrchkRange(dl, info->offset))
285             return i;
286         if (hdrchkData(info->count))
287             return i;
288
289     }
290     return -1;
291 }
292
293 /**
294  * Check header consistency, performing headerGetEntry() the hard way.
295  *
296  * Sanity checks on the header are performed while looking for a
297  * header-only digest or signature to verify the blob. If found,
298  * the digest or signature is verified.
299  *
300  * @param ts            transaction set
301  * @param uh            unloaded header blob
302  * @param uc            no. of bytes in blob (or 0 to disable)
303  * @retval *msg         signature verification msg
304  * @return              RPMRC_OK/RPMRC_NOTFOUND/RPMRC_FAIL
305  */
306 rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, char ** msg)
307 {
308     pgpDig dig;
309     char buf[8*BUFSIZ];
310     int32_t * ei = (int32_t *) uh;
311     int32_t il = ntohl(ei[0]);
312     int32_t dl = ntohl(ei[1]);
313     entryInfo pe = (entryInfo) &ei[2];
314     int32_t ildl[2];
315     int32_t pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl;
316     unsigned char * dataStart = (unsigned char *) (pe + il);
317     indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry));
318     entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info));
319     void * sig = NULL;
320     unsigned const char * b;
321     rpmVSFlags vsflags = rpmtsVSFlags(ts);
322     size_t siglen = 0;
323     size_t blen;
324     size_t nb;
325     int32_t ril = 0;
326     unsigned char * regionEnd = NULL;
327     rpmRC rc = RPMRC_FAIL;      /* assume failure */
328     int xx;
329     int i;
330     static int hclvl;
331
332     hclvl++;
333     buf[0] = '\0';
334
335     /* Is the blob the right size? */
336     if (uc > 0 && pvlen != uc) {
337         (void) snprintf(buf, sizeof(buf),
338                 _("blob size(%d): BAD, 8 + 16 * il(%d) + dl(%d)\n"),
339                 (int)uc, (int)il, (int)dl);
340         goto exit;
341     }
342
343     /* Check (and convert) the 1st tag element. */
344     xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
345     if (xx != -1) {
346         (void) snprintf(buf, sizeof(buf),
347                 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
348                 0, entry->info.tag, entry->info.type,
349                 entry->info.offset, entry->info.count);
350         goto exit;
351     }
352
353     /* Is there an immutable header region tag? */
354     if (!(entry->info.tag == RPMTAG_HEADERIMMUTABLE
355        && entry->info.type == RPM_BIN_TYPE
356        && entry->info.count == REGION_TAG_COUNT))
357     {
358         rc = RPMRC_NOTFOUND;
359         goto exit;
360     }
361
362     /* Is the offset within the data area? */
363     if (entry->info.offset >= dl) {
364         (void) snprintf(buf, sizeof(buf),
365                 _("region offset: BAD, tag %d type %d offset %d count %d\n"),
366                 entry->info.tag, entry->info.type,
367                 entry->info.offset, entry->info.count);
368         goto exit;
369     }
370
371     /* Is there an immutable header region tag trailer? */
372     regionEnd = dataStart + entry->info.offset;
373     (void) memcpy(info, regionEnd, REGION_TAG_COUNT);
374     regionEnd += REGION_TAG_COUNT;
375
376     xx = headerVerifyInfo(1, dl, info, &entry->info, 1);
377     if (xx != -1 ||
378         !(entry->info.tag == RPMTAG_HEADERIMMUTABLE
379        && entry->info.type == RPM_BIN_TYPE
380        && entry->info.count == REGION_TAG_COUNT))
381     {
382         (void) snprintf(buf, sizeof(buf),
383                 _("region trailer: BAD, tag %d type %d offset %d count %d\n"),
384                 entry->info.tag, entry->info.type,
385                 entry->info.offset, entry->info.count);
386         goto exit;
387     }
388     memset(info, 0, sizeof(*info));
389
390     /* Is the no. of tags in the region less than the total no. of tags? */
391     ril = entry->info.offset/sizeof(*pe);
392     if ((entry->info.offset % sizeof(*pe)) || ril > il) {
393         (void) snprintf(buf, sizeof(buf),
394                 _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
395         goto exit;
396     }
397
398     /* Find a header-only digest/signature tag. */
399     for (i = ril; i < il; i++) {
400         xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0);
401         if (xx != -1) {
402             (void) snprintf(buf, sizeof(buf),
403                 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
404                 i, entry->info.tag, entry->info.type,
405                 entry->info.offset, entry->info.count);
406             goto exit;
407         }
408
409         switch (entry->info.tag) {
410         case RPMTAG_SHA1HEADER:
411             if (vsflags & RPMVSF_NOSHA1HEADER)
412                 break;
413             blen = 0;
414             for (b = dataStart + entry->info.offset; *b != '\0'; b++) {
415                 if (strchr("0123456789abcdefABCDEF", *b) == NULL)
416                     break;
417                 blen++;
418             }
419             if (entry->info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40)
420             {
421                 (void) snprintf(buf, sizeof(buf), _("hdr SHA1: BAD, not hex\n"));
422                 goto exit;
423             }
424             if (info->tag == 0) {
425                 *info = entry->info;    /* structure assignment */
426                 siglen = blen + 1;
427             }
428             break;
429         case RPMTAG_RSAHEADER:
430             if (vsflags & RPMVSF_NORSAHEADER)
431                 break;
432             if (entry->info.type != RPM_BIN_TYPE) {
433                 (void) snprintf(buf, sizeof(buf), _("hdr RSA: BAD, not binary\n"));
434                 goto exit;
435             }
436             *info = entry->info;        /* structure assignment */
437             siglen = info->count;
438             break;
439         case RPMTAG_DSAHEADER:
440             if (vsflags & RPMVSF_NODSAHEADER)
441                 break;
442             if (entry->info.type != RPM_BIN_TYPE) {
443                 (void) snprintf(buf, sizeof(buf), _("hdr DSA: BAD, not binary\n"));
444                 goto exit;
445             }
446             *info = entry->info;        /* structure assignment */
447             siglen = info->count;
448             break;
449         default:
450             break;
451         }
452     }
453     rc = RPMRC_NOTFOUND;
454
455 exit:
456     /* Return determined RPMRC_OK/RPMRC_FAIL conditions. */
457     if (rc != RPMRC_NOTFOUND) {
458         buf[sizeof(buf)-1] = '\0';
459         if (msg) *msg = xstrdup(buf);
460         hclvl--;
461         return rc;
462     }
463
464     /* If no header-only digest/signature, then do simple sanity check. */
465     if (info->tag == 0) {
466 verifyinfo_exit:
467         xx = headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0);
468         if (xx != -1) {
469             (void) snprintf(buf, sizeof(buf),
470                 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
471                 xx+1, entry->info.tag, entry->info.type,
472                 entry->info.offset, entry->info.count);
473             rc = RPMRC_FAIL;
474         } else {
475             (void) snprintf(buf, sizeof(buf), "Header sanity check: OK\n");
476             rc = RPMRC_OK;
477         }
478         buf[sizeof(buf)-1] = '\0';
479         if (msg) *msg = xstrdup(buf);
480         hclvl--;
481         return rc;
482     }
483
484     /* Verify header-only digest/signature. */
485     dig = rpmtsDig(ts);
486     if (dig == NULL)
487         goto verifyinfo_exit;
488     dig->nbytes = 0;
489
490     sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen);
491     (void) rpmtsSetSig(ts, info->tag, info->type, sig, (size_t) info->count);
492
493     switch (info->tag) {
494     case RPMTAG_RSAHEADER:
495         /* Parse the parameters from the OpenPGP packets that will be needed. */
496         xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
497         if (dig->signature.version != 3 && dig->signature.version != 4) {
498             rpmlog(RPMLOG_ERR,
499                 _("skipping header with unverifiable V%u signature\n"),
500                 dig->signature.version);
501             rpmtsCleanDig(ts);
502             rc = RPMRC_FAIL;
503             goto exit;
504         }
505
506         ildl[0] = htonl(ril);
507         ildl[1] = (regionEnd - dataStart);
508         ildl[1] = htonl(ildl[1]);
509
510         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
511         dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
512
513         b = (unsigned char *) header_magic;
514         nb = sizeof(header_magic);
515         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
516         dig->nbytes += nb;
517
518         b = (unsigned char *) ildl;
519         nb = sizeof(ildl);
520         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
521         dig->nbytes += nb;
522
523         b = (unsigned char *) pe;
524         nb = (htonl(ildl[0]) * sizeof(*pe));
525         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
526         dig->nbytes += nb;
527
528         b = (unsigned char *) dataStart;
529         nb = htonl(ildl[1]);
530         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
531         dig->nbytes += nb;
532         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
533
534         break;
535     case RPMTAG_DSAHEADER:
536         /* Parse the parameters from the OpenPGP packets that will be needed. */
537         xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
538         if (dig->signature.version != 3 && dig->signature.version != 4) {
539             rpmlog(RPMLOG_ERR,
540                 _("skipping header with unverifiable V%u signature\n"),
541                 dig->signature.version);
542             rpmtsCleanDig(ts);
543             rc = RPMRC_FAIL;
544             goto exit;
545         }
546     case RPMTAG_SHA1HEADER:
547         ildl[0] = htonl(ril);
548         ildl[1] = (regionEnd - dataStart);
549         ildl[1] = htonl(ildl[1]);
550
551         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
552         dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
553
554         b = (unsigned char *) header_magic;
555         nb = sizeof(header_magic);
556         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
557         dig->nbytes += nb;
558
559         b = (unsigned char *) ildl;
560         nb = sizeof(ildl);
561         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
562         dig->nbytes += nb;
563
564         b = (unsigned char *) pe;
565         nb = (htonl(ildl[0]) * sizeof(*pe));
566         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
567         dig->nbytes += nb;
568
569         b = (unsigned char *) dataStart;
570         nb = htonl(ildl[1]);
571         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
572         dig->nbytes += nb;
573         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
574
575         break;
576     default:
577         sig = _free(sig);
578         break;
579     }
580
581     buf[0] = '\0';
582     rc = rpmVerifySignature(ts, buf);
583
584     buf[sizeof(buf)-1] = '\0';
585     if (msg) *msg = xstrdup(buf);
586
587     /* XXX headerCheck can recurse, free info only at top level. */
588     if (hclvl == 1)
589         rpmtsCleanDig(ts);
590     if (info->tag == RPMTAG_SHA1HEADER)
591         sig = _free(sig);
592     hclvl--;
593     return rc;
594 }
595
596 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, char ** msg)
597 {
598     char buf[BUFSIZ];
599     int32_t block[4];
600     int32_t il;
601     int32_t dl;
602     int32_t * ei = NULL;
603     size_t uc;
604     size_t nb;
605     Header h = NULL;
606     rpmRC rc = RPMRC_FAIL;              /* assume failure */
607     int xx;
608
609     buf[0] = '\0';
610
611     if (hdrp)
612         *hdrp = NULL;
613     if (msg)
614         *msg = NULL;
615
616     memset(block, 0, sizeof(block));
617     if ((xx = timedRead(fd, (char *)block, sizeof(block))) != sizeof(block)) {
618         (void) snprintf(buf, sizeof(buf),
619                 _("hdr size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx);
620         goto exit;
621     }
622     if (memcmp(block, header_magic, sizeof(header_magic))) {
623         (void) snprintf(buf, sizeof(buf), _("hdr magic: BAD\n"));
624         goto exit;
625     }
626     il = ntohl(block[2]);
627     if (hdrchkTags(il)) {
628         (void) snprintf(buf, sizeof(buf),
629                 _("hdr tags: BAD, no. of tags(%d) out of range\n"), il);
630
631         goto exit;
632     }
633     dl = ntohl(block[3]);
634     if (hdrchkData(dl)) {
635         (void) snprintf(buf, sizeof(buf),
636                 _("hdr data: BAD, no. of bytes(%d) out of range\n"), dl);
637         goto exit;
638     }
639
640     nb = (il * sizeof(struct entryInfo_s)) + dl;
641     uc = sizeof(il) + sizeof(dl) + nb;
642     ei = xmalloc(uc);
643     ei[0] = block[2];
644     ei[1] = block[3];
645     if ((xx = timedRead(fd, (char *)&ei[2], nb)) != nb) {
646         (void) snprintf(buf, sizeof(buf),
647                 _("hdr blob(%zd): BAD, read returned %d\n"), nb, xx);
648         goto exit;
649     }
650
651     /* Sanity check header tags */
652     rc = headerCheck(ts, ei, uc, msg);
653     if (rc != RPMRC_OK)
654         goto exit;
655
656     /* OK, blob looks sane, load the header. */
657     h = headerLoad(ei);
658     if (h == NULL) {
659         (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n"));
660         goto exit;
661     }
662     h->flags |= HEADERFLAG_ALLOCATED;
663     ei = NULL;  /* XXX will be freed with header */
664     
665 exit:
666     if (hdrp && h && rc == RPMRC_OK)
667         *hdrp = headerLink(h);
668     ei = _free(ei);
669     h = headerFree(h);
670
671     if (msg != NULL && *msg == NULL && buf[0] != '\0') {
672         buf[sizeof(buf)-1] = '\0';
673         *msg = xstrdup(buf);
674     }
675
676     return rc;
677 }
678
679 rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
680 {
681     pgpDig dig;
682     char buf[8*BUFSIZ];
683     ssize_t count;
684     rpmlead l = NULL;
685     Header sigh = NULL;
686     rpmSigTag sigtag;
687     rpmTagType sigtype;
688     rpm_data_t sig;
689     rpm_count_t siglen;
690     rpmtsOpX opx;
691     size_t nb;
692     Header h = NULL;
693     char * msg;
694     rpmVSFlags vsflags;
695     rpmRC rc = RPMRC_FAIL;      /* assume failure */
696     int xx;
697
698     if (hdrp) *hdrp = NULL;
699
700     l = rpmLeadNew();
701
702     if ((rc = rpmLeadRead(fd, l)) == RPMRC_OK) {
703         rc = rpmLeadCheck(l, fn);
704     }
705     l = rpmLeadFree(l);
706
707     if (rc != RPMRC_OK)
708         goto exit;
709
710     /* Read the signature header. */
711     msg = NULL;
712     rc = rpmReadSignature(fd, &sigh, RPMSIGTYPE_HEADERSIG, &msg);
713     switch (rc) {
714     default:
715         rpmlog(RPMLOG_ERR, _("%s: rpmReadSignature failed: %s"), fn,
716                 (msg && *msg ? msg : "\n"));
717         msg = _free(msg);
718         goto exit;
719         break;
720     case RPMRC_OK:
721         if (sigh == NULL) {
722             rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), fn);
723             rc = RPMRC_FAIL;
724             goto exit;
725         }
726         break;
727     }
728     msg = _free(msg);
729
730 #define _chk(_mask)     (sigtag == 0 && !(vsflags & (_mask)))
731
732     /*
733      * Figger the most effective available signature.
734      * Prefer signatures over digests, then header-only over header+payload.
735      * DSA will be preferred over RSA if both exist because tested first.
736      * Note that NEEDPAYLOAD prevents header+payload signatures and digests.
737      */
738     sigtag = 0;
739     opx = 0;
740     vsflags = rpmtsVSFlags(ts);
741     if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_DSA)) {
742         sigtag = RPMSIGTAG_DSA;
743     } else
744     if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_RSA)) {
745         sigtag = RPMSIGTAG_RSA;
746     } else
747     if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD) &&
748         headerIsEntry(sigh, RPMSIGTAG_GPG))
749     {
750         sigtag = RPMSIGTAG_GPG;
751         fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
752         opx = RPMTS_OP_SIGNATURE;
753     } else
754     if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD) &&
755         headerIsEntry(sigh, RPMSIGTAG_PGP))
756     {
757         sigtag = RPMSIGTAG_PGP;
758         fdInitDigest(fd, PGPHASHALGO_MD5, 0);
759         opx = RPMTS_OP_SIGNATURE;
760     } else
761     if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, RPMSIGTAG_SHA1)) {
762         sigtag = RPMSIGTAG_SHA1;
763     } else
764     if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
765         headerIsEntry(sigh, RPMSIGTAG_MD5))
766     {
767         sigtag = RPMSIGTAG_MD5;
768         fdInitDigest(fd, PGPHASHALGO_MD5, 0);
769         opx = RPMTS_OP_DIGEST;
770     }
771
772     /* Read the metadata, computing digest(s) on the fly. */
773     h = NULL;
774     msg = NULL;
775
776     /* XXX stats will include header i/o and setup overhead. */
777     /* XXX repackaged packages have appended tags, legacy dig/sig check fails */
778     if (opx > 0)
779         (void) rpmswEnter(rpmtsOp(ts, opx), 0);
780     nb = -fd->stats->ops[FDSTAT_READ].bytes;
781     rc = rpmReadHeader(ts, fd, &h, &msg);
782     nb += fd->stats->ops[FDSTAT_READ].bytes;
783     if (opx > 0)
784         (void) rpmswExit(rpmtsOp(ts, opx), nb);
785
786     if (rc != RPMRC_OK || h == NULL) {
787         rpmlog(RPMLOG_ERR, _("%s: headerRead failed: %s"), fn,
788                 (msg && *msg ? msg : "\n"));
789         msg = _free(msg);
790         goto exit;
791     }
792     msg = _free(msg);
793
794     /* Any digests or signatures to check? */
795     if (sigtag == 0) {
796         rc = RPMRC_OK;
797         goto exit;
798     }
799
800     dig = rpmtsDig(ts);
801     if (dig == NULL) {
802         rc = RPMRC_FAIL;
803         goto exit;
804     }
805     dig->nbytes = 0;
806
807     /* Retrieve the tag parameters from the signature header. */
808     sig = NULL;
809     xx = headerGetEntry(sigh, sigtag, &sigtype, &sig, &siglen);
810     if (sig == NULL) {
811         rc = RPMRC_FAIL;
812         goto exit;
813     }
814     (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
815
816     switch (sigtag) {
817     case RPMSIGTAG_RSA:
818         /* Parse the parameters from the OpenPGP packets that will be needed. */
819         xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
820         if (dig->signature.version != 3 && dig->signature.version != 4) {
821             rpmlog(RPMLOG_ERR,
822                 _("skipping package %s with unverifiable V%u signature\n"),
823                 fn, dig->signature.version);
824             rc = RPMRC_FAIL;
825             goto exit;
826         }
827     {   void * uh = NULL;
828         rpmTagType uht;
829         rpm_count_t uhc;
830
831         if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
832             break;
833         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
834         dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
835         (void) rpmDigestUpdate(dig->hdrmd5ctx, header_magic, sizeof(header_magic));
836         dig->nbytes += sizeof(header_magic);
837         (void) rpmDigestUpdate(dig->hdrmd5ctx, uh, uhc);
838         dig->nbytes += uhc;
839         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
840         rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;  /* XXX one too many */
841         uh = headerFreeData(uh, uht);
842     }   break;
843     case RPMSIGTAG_DSA:
844         /* Parse the parameters from the OpenPGP packets that will be needed. */
845         xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
846         if (dig->signature.version != 3 && dig->signature.version != 4) {
847             rpmlog(RPMLOG_ERR,
848                 _("skipping package %s with unverifiable V%u signature\n"), 
849                 fn, dig->signature.version);
850             rc = RPMRC_FAIL;
851             goto exit;
852         }
853     case RPMSIGTAG_SHA1:
854     {   void * uh = NULL;
855         rpmTagType uht;
856         rpm_count_t uhc;
857
858         if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
859             break;
860         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
861         dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
862         (void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic));
863         dig->nbytes += sizeof(header_magic);
864         (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
865         dig->nbytes += uhc;
866         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
867         if (sigtag == RPMSIGTAG_SHA1)
868             rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;      /* XXX one too many */
869         uh = headerFreeData(uh, uht);
870     }   break;
871     case RPMSIGTAG_GPG:
872     case RPMSIGTAG_PGP5:        /* XXX legacy */
873     case RPMSIGTAG_PGP:
874         /* Parse the parameters from the OpenPGP packets that will be needed. */
875         xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
876
877         if (dig->signature.version != 3 && dig->signature.version != 4) {
878             rpmlog(RPMLOG_ERR,
879                 _("skipping package %s with unverifiable V%u signature\n"),
880                 fn, dig->signature.version);
881             rc = RPMRC_FAIL;
882             goto exit;
883         }
884     case RPMSIGTAG_MD5:
885         /* Legacy signatures need the compressed payload in the digest too. */
886         (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
887         while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
888             dig->nbytes += count;
889         (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
890         rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;  /* XXX one too many */
891         dig->nbytes += nb;      /* XXX include size of header blob. */
892         if (count < 0) {
893             rpmlog(RPMLOG_ERR, _("%s: Fread failed: %s\n"),
894                                         fn, Fstrerror(fd));
895             rc = RPMRC_FAIL;
896             goto exit;
897         }
898
899         fdStealDigest(fd, dig);
900         break;
901     /* shut up gcc */
902     case RPMSIGTAG_LEMD5_1:
903     case RPMSIGTAG_LEMD5_2:
904     case RPMSIGTAG_BADSHA1_1:
905     case RPMSIGTAG_BADSHA1_2:
906     case RPMSIGTAG_SIZE:
907     case RPMSIGTAG_PAYLOADSIZE:
908         break;
909     }
910
911 /** @todo Implement disable/enable/warn/error/anal policy. */
912
913     buf[0] = '\0';
914     rc = rpmVerifySignature(ts, buf);
915     switch (rc) {
916     case RPMRC_OK:              /* Signature is OK. */
917         rpmlog(RPMLOG_DEBUG, "%s: %s", fn, buf);
918         break;
919     case RPMRC_NOTTRUSTED:      /* Signature is OK, but key is not trusted. */
920     case RPMRC_NOKEY:           /* Public key is unavailable. */
921         /* XXX Print NOKEY/NOTTRUSTED warning only once. */
922     {   int lvl = (rpmtsStashKeyid(ts) ? RPMLOG_DEBUG : RPMLOG_WARNING);
923         rpmlog(lvl, "%s: %s", fn, buf);
924     }   break;
925     case RPMRC_NOTFOUND:        /* Signature is unknown type. */
926         rpmlog(RPMLOG_WARNING, "%s: %s", fn, buf);
927         break;
928     default:
929     case RPMRC_FAIL:            /* Signature does not verify. */
930         rpmlog(RPMLOG_ERR, "%s: %s", fn, buf);
931         break;
932     }
933
934 exit:
935     if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
936         /* 
937          * Convert legacy headers on the fly. Not having "new" style compressed
938          * filenames is close enough estimate for legacy indication... 
939          */
940         if (!headerIsEntry(h, RPMTAG_DIRNAMES)) {
941             legacyRetrofit(h);
942         }
943         
944         /* Append (and remap) signature tags to the metadata. */
945         headerMergeLegacySigs(h, sigh);
946
947         /* Bump reference count for return. */
948         *hdrp = headerLink(h);
949     }
950     h = headerFree(h);
951     rpmtsCleanDig(ts);
952     sigh = rpmFreeSignature(sigh);
953     return rc;
954 }
955
956 /**
957  * Check for supported payload format in header.
958  * @param h             header to check
959  * @return              RPMRC_OK if supported, RPMRC_FAIL otherwise
960  */
961 rpmRC headerCheckPayloadFormat(Header h) {
962     rpmRC rc = RPMRC_FAIL;
963     int xx;
964     const char *payloadfmt = NULL;
965
966     xx = headerGetEntry(h, RPMTAG_PAYLOADFORMAT, NULL, 
967                         (rpm_data_t *)&payloadfmt, NULL);
968     /* 
969      * XXX Ugh, rpm 3.x packages don't have payload format tag. Instead
970      * of blinly allowing, should check somehow (HDRID existence or... ?)
971      */
972     if (!payloadfmt)
973         return RPMRC_OK;
974
975     if (payloadfmt && strncmp(payloadfmt, "cpio", strlen("cpio")) == 0) {
976         rc = RPMRC_OK;
977     } else {
978         char *nevra = headerGetNEVRA(h, NULL);
979         if (payloadfmt && strncmp(payloadfmt, "drpm", strlen("drpm")) == 0) {
980             rpmlog(RPMLOG_ERR,
981                      _("%s is a Delta RPM and cannot be directly installed\n"),
982                      nevra);
983         } else {
984             rpmlog(RPMLOG_ERR, 
985                      _("Unsupported payload (%s) in package %s\n"),
986                      payloadfmt ? payloadfmt : "none", nevra);
987         } 
988         nevra = _free(nevra);
989     }
990     return rc;
991 }
992
993