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