5871629ae50ebc33586f739642a40995fc23735e
[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 <rpmio_internal.h>
10 #include <rpmlib.h>
11
12 #define _RPMTS_INTERNAL
13 #include "rpmts.h"
14
15 #include "misc.h"       /* XXX stripTrailingChar() */
16 #include "legacy.h"     /* XXX legacyRetrofit() */
17 #include "rpmlead.h"
18
19 #include "header_internal.h"    /* XXX headerCheck */
20 #include "signature.h"
21 #include "debug.h"
22
23 #define alloca_strdup(_s)       strcpy(alloca(strlen(_s)+1), (_s))
24
25 /*@access pgpDig @*/
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 */
31
32 /*@unchecked@*/
33 static int _print_pkts = 0;
34
35 /*@unchecked@*/
36 static unsigned int nkeyids_max = 256;
37 /*@unchecked@*/
38 static unsigned int nkeyids = 0;
39 /*@unchecked@*/
40 static unsigned int nextkeyid  = 0;
41 /*@unchecked@*/ /*@only@*/ /*@null@*/
42 static unsigned int * keyids;
43
44 /*@unchecked@*/
45 static unsigned char header_magic[8] = {
46         0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
47 };
48
49 /**
50  * Alignment needs (and sizeof scalars types) for internal rpm data types.
51  */
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 */
64     0,
65     0,
66     0,
67     0,
68     0,
69     0
70 };
71
72 /**
73  * Sanity check on no. of tags.
74  * This check imposes a limit of 65K tags, more than enough.
75  */
76 #define hdrchkTags(_ntags)      ((_ntags) & 0xffff0000)
77
78 /**
79  * Sanity check on type values.
80  */
81 #define hdrchkType(_type) ((_type) < RPM_MIN_TYPE || (_type) > RPM_MAX_TYPE)
82
83 /**
84  * Sanity check on data size and/or offset and/or count.
85  * This check imposes a limit of 16 MB, more than enough.
86  */
87 #define hdrchkData(_nbytes) ((_nbytes) & 0xff000000)
88
89 /**
90  * Sanity check on data alignment for data type.
91  */
92 #define hdrchkAlign(_type, _off)        ((_off) & (typeAlign[_type]-1))
93
94 /**
95  * Sanity check on range of data offset.
96  */
97 #define hdrchkRange(_dl, _off)          ((_off) < 0 || (_off) > (_dl))
98
99 void headerMergeLegacySigs(Header h, const Header sigh)
100 {
101     HFD_t hfd = (HFD_t) headerFreeData;
102     HAE_t hae = (HAE_t) headerAddEntry;
103     HeaderIterator hi;
104     int_32 tag, type, count;
105     const void * ptr;
106     int xx;
107
108     for (hi = headerInitIterator(sigh);
109         headerNextIterator(hi, &tag, &type, &ptr, &count);
110         ptr = hfd(ptr, type))
111     {
112         switch (tag) {
113         /* XXX Translate legacy signature tag values. */
114         case RPMSIGTAG_SIZE:
115             tag = RPMTAG_SIGSIZE;
116             /*@switchbreak@*/ break;
117         case RPMSIGTAG_LEMD5_1:
118             tag = RPMTAG_SIGLEMD5_1;
119             /*@switchbreak@*/ break;
120         case RPMSIGTAG_PGP:
121             tag = RPMTAG_SIGPGP;
122             /*@switchbreak@*/ break;
123         case RPMSIGTAG_LEMD5_2:
124             tag = RPMTAG_SIGLEMD5_2;
125             /*@switchbreak@*/ break;
126         case RPMSIGTAG_MD5:
127             tag = RPMTAG_SIGMD5;
128             /*@switchbreak@*/ break;
129         case RPMSIGTAG_GPG:
130             tag = RPMTAG_SIGGPG;
131             /*@switchbreak@*/ break;
132         case RPMSIGTAG_PGP5:
133             tag = RPMTAG_SIGPGP5;
134             /*@switchbreak@*/ break;
135         case RPMSIGTAG_PAYLOADSIZE:
136             tag = RPMTAG_ARCHIVESIZE;
137             /*@switchbreak@*/ break;
138         case RPMSIGTAG_SHA1:
139         case RPMSIGTAG_DSA:
140         case RPMSIGTAG_RSA:
141         default:
142             if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
143                 continue;
144             /*@switchbreak@*/ break;
145         }
146         if (ptr == NULL) continue;      /* XXX can't happen */
147         if (!headerIsEntry(h, tag)) {
148             if (hdrchkType(type))
149                 continue;
150             if (count < 0 || hdrchkData(count))
151                 continue;
152             switch(type) {
153             case RPM_NULL_TYPE:
154                 continue;
155                 /*@notreached@*/ /*@switchbreak@*/ break;
156             case RPM_CHAR_TYPE:
157             case RPM_INT8_TYPE:
158             case RPM_INT16_TYPE:
159             case RPM_INT32_TYPE:
160                 if (count != 1)
161                     continue;
162                 /*@switchbreak@*/ break;
163             case RPM_STRING_TYPE:
164             case RPM_BIN_TYPE:
165                 if (count >= 16*1024)
166                     continue;
167                 /*@switchbreak@*/ break;
168             case RPM_STRING_ARRAY_TYPE:
169             case RPM_I18NSTRING_TYPE:
170                 continue;
171                 /*@notreached@*/ /*@switchbreak@*/ break;
172             }
173             xx = hae(h, tag, type, ptr, count);
174         }
175     }
176     hi = headerFreeIterator(hi);
177 }
178
179 Header headerRegenSigHeader(const Header h, int noArchiveSize)
180 {
181     HFD_t hfd = (HFD_t) headerFreeData;
182     Header sigh = rpmNewSignature();
183     HeaderIterator hi;
184     int_32 tag, stag, type, count;
185     const void * ptr;
186     int xx;
187
188     for (hi = headerInitIterator(h);
189         headerNextIterator(hi, &tag, &type, &ptr, &count);
190         ptr = hfd(ptr, type))
191     {
192         switch (tag) {
193         /* XXX Translate legacy signature tag values. */
194         case RPMTAG_SIGSIZE:
195             stag = RPMSIGTAG_SIZE;
196             /*@switchbreak@*/ break;
197         case RPMTAG_SIGLEMD5_1:
198             stag = RPMSIGTAG_LEMD5_1;
199             /*@switchbreak@*/ break;
200         case RPMTAG_SIGPGP:
201             stag = RPMSIGTAG_PGP;
202             /*@switchbreak@*/ break;
203         case RPMTAG_SIGLEMD5_2:
204             stag = RPMSIGTAG_LEMD5_2;
205             /*@switchbreak@*/ break;
206         case RPMTAG_SIGMD5:
207             stag = RPMSIGTAG_MD5;
208             /*@switchbreak@*/ break;
209         case RPMTAG_SIGGPG:
210             stag = RPMSIGTAG_GPG;
211             /*@switchbreak@*/ break;
212         case RPMTAG_SIGPGP5:
213             stag = RPMSIGTAG_PGP5;
214             /*@switchbreak@*/ break;
215         case RPMTAG_ARCHIVESIZE:
216             /* XXX rpm-4.1 and later has archive size in signature header. */
217             if (noArchiveSize)
218                 continue;
219             stag = RPMSIGTAG_PAYLOADSIZE;
220             /*@switchbreak@*/ break;
221         case RPMTAG_SHA1HEADER:
222         case RPMTAG_DSAHEADER:
223         case RPMTAG_RSAHEADER:
224         default:
225             if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
226                 continue;
227             stag = tag;
228             /*@switchbreak@*/ break;
229         }
230         if (ptr == NULL) continue;      /* XXX can't happen */
231         if (!headerIsEntry(sigh, stag))
232             xx = headerAddEntry(sigh, stag, type, ptr, count);
233     }
234     hi = headerFreeIterator(hi);
235     return sigh;
236 }
237
238 /**
239  * Remember current key id.
240  * @param ts            transaction set
241  * @return              0 if new keyid, otherwise 1
242  */
243 static int rpmtsStashKeyid(rpmts ts)
244         /*@globals nextkeyid, nkeyids, keyids @*/
245         /*@modifies nextkeyid, nkeyids, keyids @*/
246 {
247     const void * sig = rpmtsSig(ts);
248     pgpDig dig = rpmtsDig(ts);
249     pgpDigParams sigp = rpmtsSignature(ts);
250     unsigned int keyid;
251     int i;
252
253     if (sig == NULL || dig == NULL || sigp == NULL)
254         return 0;
255
256     keyid = pgpGrab(sigp->signid+4, 4);
257     if (keyid == 0)
258         return 0;
259
260     if (keyids != NULL)
261     for (i = 0; i < nkeyids; i++) {
262 /*@-boundsread@*/
263         if (keyid == keyids[i])
264             return 1;
265 /*@=boundsread@*/
266     }
267
268     if (nkeyids < nkeyids_max) {
269         nkeyids++;
270         keyids = xrealloc(keyids, nkeyids * sizeof(*keyids));
271     }
272 /*@-boundswrite@*/
273     if (keyids)         /* XXX can't happen */
274         keyids[nextkeyid] = keyid;
275 /*@=boundswrite@*/
276     nextkeyid++;
277     nextkeyid %= nkeyids_max;
278
279     return 0;
280 }
281
282 int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate)
283 {
284 /*@-castexpose@*/
285     entryInfo pe = (entryInfo) pev;
286 /*@=castexpose@*/
287     entryInfo info = iv;
288     int i;
289
290 /*@-boundsread@*/
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);
295         if (negate)
296             info->offset = -info->offset;
297         info->count = ntohl(pe[i].count);
298
299         if (hdrchkType(info->type))
300             return i;
301         if (hdrchkAlign(info->type, info->offset))
302             return i;
303         if (!negate && hdrchkRange(dl, info->offset))
304             return i;
305         if (hdrchkData(info->count))
306             return i;
307
308     }
309 /*@=boundsread@*/
310     return -1;
311 }
312
313 /**
314  * Check header consistency, performing headerGetEntry() the hard way.
315  *
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.
319  *
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
325  */
326 rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, const char ** msg)
327 {
328     pgpDig dig;
329     unsigned char buf[8*BUFSIZ];
330     int_32 * ei = (int_32 *) uh;
331 /*@-boundsread@*/
332     int_32 il = ntohl(ei[0]);
333     int_32 dl = ntohl(ei[1]);
334 /*@-castexpose@*/
335     entryInfo pe = (entryInfo) &ei[2];
336 /*@=castexpose@*/
337 /*@=boundsread@*/
338     int_32 ildl[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;
344     const char * b;
345     rpmVSFlags vsflags = rpmtsVSFlags(ts);
346     int siglen = 0;
347     int blen;
348     size_t nb;
349     int_32 ril = 0;
350     unsigned char * regionEnd = NULL;
351     rpmRC rc = RPMRC_FAIL;      /* assume failure */
352     int xx;
353     int i;
354
355 /*@-boundswrite@*/
356     buf[0] = '\0';
357 /*@=boundswrite@*/
358
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);
364         goto exit;
365     }
366
367     /* Check (and convert) the 1st tag element. */
368     xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
369     if (xx != -1) {
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);
374         goto exit;
375     }
376
377     /* Is there an immutable header region tag? */
378 /*@-sizeoftype@*/
379     if (!(entry->info.tag == RPMTAG_HEADERIMMUTABLE
380        && entry->info.type == RPM_BIN_TYPE
381        && entry->info.count == REGION_TAG_COUNT))
382     {
383         rc = RPMRC_NOTFOUND;
384         goto exit;
385     }
386 /*@=sizeoftype@*/
387
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);
394         goto exit;
395     }
396
397     /* Is there an immutable header region tag trailer? */
398     regionEnd = dataStart + entry->info.offset;
399 /*@-sizeoftype@*/
400 /*@-bounds@*/
401     (void) memcpy(info, regionEnd, REGION_TAG_COUNT);
402 /*@=bounds@*/
403     regionEnd += REGION_TAG_COUNT;
404
405     xx = headerVerifyInfo(1, dl, info, &entry->info, 1);
406     if (xx != -1 ||
407         !(entry->info.tag == RPMTAG_HEADERIMMUTABLE
408        && entry->info.type == RPM_BIN_TYPE
409        && entry->info.count == REGION_TAG_COUNT))
410     {
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);
415         goto exit;
416     }
417 /*@=sizeoftype@*/
418 /*@-boundswrite@*/
419     memset(info, 0, sizeof(*info));
420 /*@=boundswrite@*/
421
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);
427         goto exit;
428     }
429
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);
433         if (xx != -1) {
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);
438             goto exit;
439         }
440
441         switch (entry->info.tag) {
442         case RPMTAG_SHA1HEADER:
443             if (vsflags & RPMVSF_NOSHA1HEADER)
444                 /*@switchbreak@*/ break;
445             blen = 0;
446 /*@-boundsread@*/
447             for (b = dataStart + entry->info.offset; *b != '\0'; b++) {
448                 if (strchr("0123456789abcdefABCDEF", *b) == NULL)
449                     /*@innerbreak@*/ break;
450                 blen++;
451             }
452             if (entry->info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40)
453             {
454                 (void) snprintf(buf, sizeof(buf), _("hdr SHA1: BAD, not hex\n"));
455                 goto exit;
456             }
457 /*@=boundsread@*/
458             if (info->tag == 0) {
459 /*@-boundswrite@*/
460                 *info = entry->info;    /* structure assignment */
461 /*@=boundswrite@*/
462                 siglen = blen + 1;
463             }
464             /*@switchbreak@*/ break;
465 #ifdef  NOTYET
466         case RPMTAG_RSAHEADER:
467 #endif
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"));
473                 goto exit;
474             }
475 /*@-boundswrite@*/
476             *info = entry->info;        /* structure assignment */
477 /*@=boundswrite@*/
478             siglen = info->count;
479             /*@switchbreak@*/ break;
480         default:
481             /*@switchbreak@*/ break;
482         }
483     }
484     rc = RPMRC_NOTFOUND;
485
486 exit:
487     /* Return determined RPMRC_OK/RPMRC_FAIL conditions. */
488     if (rc != RPMRC_NOTFOUND) {
489 /*@-boundswrite@*/
490         buf[sizeof(buf)-1] = '\0';
491         if (msg) *msg = xstrdup(buf);
492 /*@=boundswrite@*/
493         return rc;
494     }
495
496     /* If no header-only digest/signature, then do simple sanity check. */
497     if (info->tag == 0) {
498 verifyinfo_exit:
499         xx = headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0);
500         if (xx != -1) {
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);
505             rc = RPMRC_FAIL;
506         } else {
507             (void) snprintf(buf, sizeof(buf), "Header sanity check: OK\n");
508             rc = RPMRC_OK;
509         }
510 /*@-boundswrite@*/
511         buf[sizeof(buf)-1] = '\0';
512         if (msg) *msg = xstrdup(buf);
513 /*@=boundswrite@*/
514         return rc;
515     }
516
517     /* Verify header-only digest/signature. */
518     dig = rpmtsDig(ts);
519     if (dig == NULL)
520         goto verifyinfo_exit;
521     dig->nbytes = 0;
522
523 /*@-boundsread@*/
524     sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen);
525 /*@=boundsread@*/
526     (void) rpmtsSetSig(ts, info->tag, info->type, sig, info->count);
527
528     switch (info->tag) {
529 #ifdef  NOTYET
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);
538             rpmtsCleanDig(ts);
539             goto verifyinfo_exit;
540         }
541
542         ildl[0] = htonl(ril);
543         ildl[1] = (regionEnd - dataStart);
544         ildl[1] = htonl(ildl[1]);
545
546         (void) rpmswEnter(&ts->op_digest, 0);
547         dig->hdrmd5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
548
549         b = (unsigned char *) header_magic;
550         nb = sizeof(header_magic);
551         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
552         dig->nbytes += nb;
553
554         b = (unsigned char *) ildl;
555         nb = sizeof(ildl);
556         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
557         dig->nbytes += nb;
558
559         b = (unsigned char *) pe;
560         nb = (htonl(ildl[0]) * sizeof(*pe));
561         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
562         dig->nbytes += nb;
563
564         b = (unsigned char *) dataStart;
565         nb = htonl(ildl[1]);
566         (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
567         dig->nbytes += nb;
568         (void) rpmswExit(&ts->op_digest, dig->nbytes);
569
570         break;
571 #endif
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);
580             rpmtsCleanDig(ts);
581             goto verifyinfo_exit;
582         }
583         /*@fallthrough@*/
584     case RPMTAG_SHA1HEADER:
585 /*@-boundswrite@*/
586         ildl[0] = htonl(ril);
587         ildl[1] = (regionEnd - dataStart);
588         ildl[1] = htonl(ildl[1]);
589 /*@=boundswrite@*/
590
591         (void) rpmswEnter(&ts->op_digest, 0);
592         dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
593
594         b = (unsigned char *) header_magic;
595         nb = sizeof(header_magic);
596         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
597         dig->nbytes += nb;
598
599         b = (unsigned char *) ildl;
600         nb = sizeof(ildl);
601         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
602         dig->nbytes += nb;
603
604         b = (unsigned char *) pe;
605         nb = (htonl(ildl[0]) * sizeof(*pe));
606         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
607         dig->nbytes += nb;
608
609         b = (unsigned char *) dataStart;
610         nb = htonl(ildl[1]);
611         (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
612         dig->nbytes += nb;
613         (void) rpmswExit(&ts->op_digest, dig->nbytes);
614
615         break;
616     default:
617         sig = _free(sig);
618         break;
619     }
620
621 /*@-boundswrite@*/
622     buf[0] = '\0';
623 /*@=boundswrite@*/
624     rc = rpmVerifySignature(ts, buf);
625
626 /*@-boundswrite@*/
627     buf[sizeof(buf)-1] = '\0';
628     if (msg) *msg = xstrdup(buf);
629 /*@=boundswrite@*/
630
631     rpmtsCleanDig(ts);
632     if (info->tag == RPMTAG_SHA1HEADER)
633         sig = _free(sig);
634     return rc;
635 }
636
637 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, const char ** msg)
638 {
639     char buf[BUFSIZ];
640     int_32 block[4];
641     int_32 il;
642     int_32 dl;
643     int_32 * ei = NULL;
644     size_t uc;
645     int_32 nb;
646     Header h = NULL;
647     rpmRC rc = RPMRC_FAIL;              /* assume failure */
648     int xx;
649
650 /*@-boundswrite@*/
651     buf[0] = '\0';
652
653     if (hdrp)
654         *hdrp = NULL;
655     if (msg)
656         *msg = NULL;
657 /*@=boundswrite@*/
658
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);
663         goto exit;
664     }
665     if (memcmp(block, header_magic, sizeof(header_magic))) {
666         (void) snprintf(buf, sizeof(buf), _("hdr magic: BAD\n"));
667         goto exit;
668     }
669 /*@-boundsread@*/
670     il = ntohl(block[2]);
671 /*@=boundsread@*/
672     if (hdrchkTags(il)) {
673         (void) snprintf(buf, sizeof(buf),
674                 _("hdr tags: BAD, no. of tags(%d) out of range\n"), il);
675
676         goto exit;
677     }
678 /*@-boundsread@*/
679     dl = ntohl(block[3]);
680 /*@=boundsread@*/
681     if (hdrchkData(dl)) {
682         (void) snprintf(buf, sizeof(buf),
683                 _("hdr data: BAD, no. of bytes(%d) out of range\n"), dl);
684         goto exit;
685     }
686
687 /*@-sizeoftype@*/
688     nb = (il * sizeof(struct entryInfo_s)) + dl;
689 /*@=sizeoftype@*/
690     uc = sizeof(il) + sizeof(dl) + nb;
691     ei = xmalloc(uc);
692 /*@-bounds@*/
693     ei[0] = block[2];
694     ei[1] = block[3];
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);
698         goto exit;
699     }
700 /*@=bounds@*/
701
702     /* Sanity check header tags */
703     rc = headerCheck(ts, ei, uc, msg);
704     if (rc != RPMRC_OK)
705         goto exit;
706
707     /* OK, blob looks sane, load the header. */
708     h = headerLoad(ei);
709     if (h == NULL) {
710         (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n"));
711         goto exit;
712     }
713     h->flags |= HEADERFLAG_ALLOCATED;
714     ei = NULL;  /* XXX will be freed with header */
715     
716 exit:
717 /*@-boundswrite@*/
718     if (hdrp && h && rc == RPMRC_OK)
719         *hdrp = headerLink(h);
720 /*@=boundswrite@*/
721     ei = _free(ei);
722     h = headerFree(h);
723
724 /*@-boundswrite@*/
725     if (msg != NULL && *msg == NULL && buf[0] != '\0') {
726         buf[sizeof(buf)-1] = '\0';
727         *msg = xstrdup(buf);
728     }
729 /*@=boundswrite@*/
730
731     return rc;
732 }
733
734 /*@-bounds@*/   /* LCL: segfault */
735 int rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
736 {
737     pgpDig dig;
738     byte buf[8*BUFSIZ];
739     ssize_t count;
740     struct rpmlead * l = alloca(sizeof(*l));
741     Header sigh = NULL;
742     int_32 sigtag;
743     int_32 sigtype;
744     const void * sig;
745     int_32 siglen;
746     Header h = NULL;
747     const char * msg;
748     int hmagic;
749     rpmVSFlags vsflags;
750     rpmRC rc = RPMRC_FAIL;      /* assume failure */
751     int xx;
752     int i;
753
754     if (hdrp) *hdrp = NULL;
755     {   struct stat st;
756 /*@-boundswrite@*/
757         memset(&st, 0, sizeof(st));
758 /*@=boundswrite@*/
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))
762             goto exit;
763     }
764
765     memset(l, 0, sizeof(*l));
766     rc = readLead(fd, l);
767     if (rc != RPMRC_OK) {
768         rc = RPMRC_NOTFOUND;
769         goto exit;
770     }
771
772     switch (l->major) {
773     case 1:
774         rpmError(RPMERR_NEWPACKAGE,
775             _("packaging version 1 is not supported by this version of RPM\n"));
776         goto exit;
777         /*@notreached@*/ break;
778     case 2:
779     case 3:
780     case 4:
781         break;
782     default:
783         rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 "
784                 "is supported by this version of RPM\n"));
785         goto exit;
786         /*@notreached@*/ break;
787     }
788
789     /* Read the signature header. */
790     msg = NULL;
791     rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
792     switch (rc) {
793     default:
794         rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed: %s"), fn,
795                 (msg && *msg ? msg : "\n"));
796         msg = _free(msg);
797         goto exit;
798         /*@notreached@*/ break;
799     case RPMRC_OK:
800         if (sigh == NULL) {
801             rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn);
802             rc = RPMRC_FAIL;
803             goto exit;
804         }
805         break;
806     }
807     msg = _free(msg);
808
809 #define _chk(_mask)     (sigtag == 0 && !(vsflags & (_mask)))
810
811     /* Figger the most effective available signature. */
812     sigtag = 0;
813     vsflags = rpmtsVSFlags(ts);
814 #ifdef  DYING
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;
819 #endif
820     if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD) &&
821         headerIsEntry(sigh, RPMSIGTAG_GPG))
822     {
823         sigtag = RPMSIGTAG_GPG;
824         fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
825     }
826     if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD) &&
827         headerIsEntry(sigh, RPMSIGTAG_PGP))
828     {
829         sigtag = RPMSIGTAG_PGP;
830         fdInitDigest(fd, PGPHASHALGO_MD5, 0);
831     }
832 #ifdef  DYING
833     if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, RPMSIGTAG_SHA1))
834         sigtag = RPMSIGTAG_SHA1;
835 #endif
836     if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
837         headerIsEntry(sigh, RPMSIGTAG_MD5))
838     {
839         sigtag = RPMSIGTAG_MD5;
840         fdInitDigest(fd, PGPHASHALGO_MD5, 0);
841     }
842
843     /* Read the metadata, computing digest(s) on the fly. */
844     h = NULL;
845     msg = NULL;
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"));
850         msg = _free(msg);
851         goto exit;
852     }
853     msg = _free(msg);
854
855     /* Any signatures to check? */
856     if (sigtag == 0) {
857         rc = RPMRC_OK;
858         goto exit;
859     }
860
861     dig = rpmtsDig(ts);
862     if (dig == NULL) {
863         rc = RPMRC_FAIL;
864         goto exit;
865     }
866     dig->nbytes = 0;
867
868     /* Retrieve the tag parameters from the signature header. */
869     sig = NULL;
870     xx = headerGetEntry(sigh, sigtag, &sigtype, (void **) &sig, &siglen);
871     if (sig == NULL) {
872         rc = RPMRC_FAIL;
873         goto exit;
874     }
875     (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
876
877     switch (sigtag) {
878     case RPMSIGTAG_RSA:
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);
886             rc = RPMRC_OK;
887             goto exit;
888         }
889     {   void * uh = NULL;
890         int_32 uht;
891         int_32 uhc;
892
893         if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
894             break;
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);
899         dig->nbytes += uhc;
900         uh = headerFreeData(uh, uht);
901     }   break;
902     case RPMSIGTAG_DSA:
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);
910             rc = RPMRC_OK;
911             goto exit;
912         }
913         /*@fallthrough@*/
914     case RPMSIGTAG_SHA1:
915     {   void * uh = NULL;
916         int_32 uht;
917         int_32 uhc;
918
919         if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
920             break;
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);
925         dig->nbytes += uhc;
926         uh = headerFreeData(uh, uht);
927     }   break;
928     case RPMSIGTAG_GPG:
929     case RPMSIGTAG_PGP5:        /* XXX legacy */
930     case RPMSIGTAG_PGP:
931         /* Parse the parameters from the OpenPGP packets that will be needed. */
932         xx = pgpPrtPkts(sig, siglen, dig,
933                         (_print_pkts & rpmIsDebug()));
934
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);
940             rc = RPMRC_OK;
941             goto exit;
942         }
943         /*@fallthrough@*/
944     case RPMSIGTAG_MD5:
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;
950         if (count < 0) {
951             rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
952                                         fn, Fstrerror(fd));
953             rc = RPMRC_FAIL;
954             goto exit;
955         }
956         dig->nbytes += count;
957
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)
962                 continue;
963             if (fddig->hashalgo == PGPHASHALGO_MD5) {
964                 dig->md5ctx = fddig->hashctx;
965                 fddig->hashctx = NULL;
966                 continue;
967             }
968             if (fddig->hashalgo == PGPHASHALGO_SHA1) {
969                 dig->sha1ctx = fddig->hashctx;
970                 fddig->hashctx = NULL;
971                 continue;
972             }
973         }
974         break;
975     }
976
977 /** @todo Implement disable/enable/warn/error/anal policy. */
978
979 /*@-boundswrite@*/
980     buf[0] = '\0';
981 /*@=boundswrite@*/
982     rc = rpmVerifySignature(ts, buf);
983     switch (rc) {
984     case RPMRC_OK:              /* Signature is OK. */
985         rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
986         break;
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);
992     }   break;
993     case RPMRC_NOTFOUND:        /* Signature is unknown type. */
994         rpmMessage(RPMMESS_WARNING, "%s: %s", fn, buf);
995         break;
996     default:
997     case RPMRC_FAIL:            /* Signature does not verify. */
998         rpmMessage(RPMMESS_ERROR, "%s: %s", fn, buf);
999         break;
1000     }
1001
1002 exit:
1003     if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
1004         /* Convert legacy headers on the fly ... */
1005         legacyRetrofit(h, l);
1006         
1007         /* Append (and remap) signature tags to the metadata. */
1008         headerMergeLegacySigs(h, sigh);
1009
1010         /* Bump reference count for return. */
1011 /*@-boundswrite@*/
1012         *hdrp = headerLink(h);
1013 /*@=boundswrite@*/
1014     }
1015     h = headerFree(h);
1016     rpmtsCleanDig(ts);
1017     sigh = rpmFreeSignature(sigh);
1018     return rc;
1019 }
1020 /*@=bounds@*/