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