rpm  4.5
package.c
Go to the documentation of this file.
1 
5 #include "system.h"
6 
7 #include <netinet/in.h>
8 
9 #include <rpmio_internal.h>
10 #include <rpmlib.h>
11 
12 #if defined(RPM_VENDOR_MANDRIVA)
13 #define _RPMEVR_INTERNAL
14 #include "rpmevr.h"
15 #endif
16 
17 #include "rpmts.h"
18 #include "rpmevr.h"
19 
20 #include "misc.h" /* XXX stripTrailingChar() */
21 #include "rpmlead.h"
22 
23 #include "header_internal.h" /* XXX headerCheck */
24 #include "signature.h"
25 #include "debug.h"
26 
27 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
28 
29 /*@access pgpDig @*/
30 /*@access pgpDigParams @*/
31 /*@access Header @*/ /* XXX compared with NULL */
32 /*@access entryInfo @*/ /* XXX headerCheck */
33 /*@access indexEntry @*/ /* XXX headerCheck */
34 /*@access FD_t @*/ /* XXX stealing digests */
35 
36 /*@unchecked@*/
37 static int _print_pkts = 0;
38 
39 /*@unchecked@*/
40 static unsigned int nkeyids_max = 256;
41 /*@unchecked@*/
42 static unsigned int nkeyids = 0;
43 /*@unchecked@*/
44 static unsigned int nextkeyid = 0;
45 /*@unchecked@*/ /*@only@*/ /*@null@*/
46 static unsigned int * keyids;
47 
48 /*@unchecked@*/
49 static unsigned char header_magic[8] = {
50  0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
51 };
52 
56 /*@observer@*/ /*@unchecked@*/
57 static int typeAlign[16] = {
58  1,
59  1,
60  1,
61  2,
62  4,
63  8,
64  1,
65  1,
66  1,
67  1,
68  0,
69  0,
70  0,
71  0,
72  0,
73  0
74 };
75 
80 #define hdrchkTags(_ntags) ((_ntags) & 0xffff0000)
81 
85 #define hdrchkType(_type) ((_type) < RPM_MIN_TYPE || (_type) > RPM_MAX_TYPE)
86 
91 #define hdrchkData(_nbytes) ((_nbytes) & 0xff000000)
92 
96 #define hdrchkAlign(_type, _off) ((_off) & (typeAlign[_type]-1))
97 
101 #define hdrchkRange(_dl, _off) ((_off) < 0 || (_off) > (_dl))
102 
103 #if defined(RPM_VENDOR_MANDRIVA)
104 /*@-boundsread@*/
105 static int dncmp(const void * a, const void * b)
106  /*@*/
107 {
108  const char *const * first = a;
109  const char *const * second = b;
110  return strcmp(*first, *second);
111 }
112 /*@=boundsread@*/
113 
114 /*@-bounds@*/
119 static void compressFilelist(Header h)
120  /*@modifies h @*/
121 {
123  HAE_t hae = (HAE_t)headerAddEntry;
125  HFD_t hfd = headerFreeData;
126  char ** fileNames;
127  const char ** dirNames;
128  const char ** baseNames;
129  int_32 * dirIndexes;
130  rpmTagType fnt;
131  int count;
132  int i, xx;
133  int dirIndex = -1;
134 
135  /*
136  * This assumes the file list is already sorted, and begins with a
137  * single '/'. That assumption isn't critical, but it makes things go
138  * a bit faster.
139  */
140 
141  if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
142  xx = hre(h, RPMTAG_OLDFILENAMES);
143  return; /* Already converted. */
144  }
145 
146  if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (void **) &fileNames, &count))
147  return; /* no file list */
148  if (fileNames == NULL || count <= 0)
149  return;
150 
151  dirNames = alloca(sizeof(*dirNames) * count); /* worst case */
152  baseNames = alloca(sizeof(*dirNames) * count);
153  dirIndexes = alloca(sizeof(*dirIndexes) * count);
154 
155  if (fileNames[0][0] != '/') {
156  /* HACK. Source RPM, so just do things differently */
157  dirIndex = 0;
158  dirNames[dirIndex] = "";
159  for (i = 0; i < count; i++) {
160  dirIndexes[i] = dirIndex;
161  baseNames[i] = fileNames[i];
162  }
163  goto exit;
164  }
165 
166  /*@-branchstate@*/
167  for (i = 0; i < count; i++) {
168  const char ** needle;
169  char savechar;
170  char * baseName;
171  int len;
172 
173  if (fileNames[i] == NULL) /* XXX can't happen */
174  continue;
175  baseName = strrchr(fileNames[i], '/') + 1;
176  len = baseName - fileNames[i];
177  needle = dirNames;
178  savechar = *baseName;
179  *baseName = '\0';
180 /*@-compdef@*/
181  if (dirIndex < 0 ||
182  (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
183  char *s = alloca(len + 1);
184  memcpy(s, fileNames[i], len + 1);
185  s[len] = '\0';
186  dirIndexes[i] = ++dirIndex;
187  dirNames[dirIndex] = s;
188  } else
189  dirIndexes[i] = needle - dirNames;
190 /*@=compdef@*/
191 
192  *baseName = savechar;
193  baseNames[i] = baseName;
194  }
195  /*@=branchstate@*/
196 
197 exit:
198  if (count > 0) {
199  xx = hae(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
201  baseNames, count);
203  dirNames, dirIndex + 1);
204  }
205 
206  fileNames = hfd(fileNames, fnt);
207 
208  xx = hre(h, RPMTAG_OLDFILENAMES);
209 }
210 /*@=bounds@*/
211 
212 
213 /* copied verbatim from build/pack.c */
214 static void providePackageNVR(Header h)
215  /*@modifies h @*/
216 {
218  HFD_t hfd = headerFreeData;
219  const char *name, *version, *release;
220  int_32 * epoch;
221  const char *pEVR;
222  char *p;
223  int_32 pFlags = RPMSENSE_EQUAL;
224  const char ** provides = NULL;
225  const char ** providesEVR = NULL;
226  rpmTagType pnt, pvt;
227  int_32 * provideFlags = NULL;
228  int providesCount;
229  int i, xx;
230  int bingo = 1;
231 
232  /* Generate provides for this package name-version-release. */
233  xx = headerNVR(h, &name, &version, &release);
234  if (!(name && version && release))
235  return;
236  pEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1);
237  *p = '\0';
238  if (hge(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
239  sprintf(p, "%d:", *epoch);
240  while (*p != '\0')
241  p++;
242  }
243  (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release);
244 
245  /*
246  * Rpm prior to 3.0.3 does not have versioned provides.
247  * If no provides at all are available, we can just add.
248  */
249  if (!hge(h, RPMTAG_PROVIDENAME, &pnt, (void **) &provides, &providesCount))
250  goto exit;
251 
252  /*
253  * Otherwise, fill in entries on legacy packages.
254  */
255  if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt, (void **) &providesEVR, NULL)) {
256  for (i = 0; i < providesCount; i++) {
257  char * vdummy = "";
258  int_32 fdummy = RPMSENSE_ANY;
260  &vdummy, 1);
262  &fdummy, 1);
263  }
264  goto exit;
265  }
266 
267  xx = hge(h, RPMTAG_PROVIDEFLAGS, NULL, (void **) &provideFlags, NULL);
268 
269  /*@-nullderef@*/ /* LCL: providesEVR is not NULL */
270  if (provides && providesEVR && provideFlags)
271  for (i = 0; i < providesCount; i++) {
272  if (!(provides[i] && providesEVR[i]))
273  continue;
274  if (!(provideFlags[i] == RPMSENSE_EQUAL &&
275  !strcmp(name, provides[i]) && !strcmp(pEVR, providesEVR[i])))
276  continue;
277  bingo = 0;
278  break;
279  }
280  /*@=nullderef@*/
281 
282 exit:
283  provides = hfd(provides, pnt);
284  providesEVR = hfd(providesEVR, pvt);
285 
286  if (bingo) {
288  &name, 1);
290  &pFlags, 1);
292  &pEVR, 1);
293  }
294 }
295 
296 static void add_RPMTAG_SOURCERPM(Header h)
297 {
299  /* we have no way to know if this is a srpm or an rpm with no SOURCERPM */
300  /* but since this is an old v3 rpm, we suppose it's not a srpm */
302  }
303 }
304 
305 /* rpm v3 compatibility */
306 static void rpm3to4(Header h) {
307  char * rpmversion;
308  rpmTagType rpmversion_type;
309 
310  (void) headerGetEntry(h, RPMTAG_RPMVERSION, NULL, (void **) &rpmversion, &rpmversion_type);
311 
312  if ((!rpmversion) || rpmversion[0] < '4') {
313  add_RPMTAG_SOURCERPM(h);
315  compressFilelist(h);
316  }
317  headerFreeTag(h, (void *) rpmversion, rpmversion_type);
318  return;
319 }
320 #endif
321 
322 /*@-boundsread@*/
323 static int dncmp(const void * a, const void * b)
324  /*@*/
325 {
326  const char *const * first = a;
327  const char *const * second = b;
328  return strcmp(*first, *second);
329 }
330 /*@=boundsread@*/
331 
332 /*@-bounds@*/
337 static void compressFilelist(Header h)
338  /*@modifies h @*/
339 {
341  HAE_t hae = (HAE_t)headerAddEntry;
343  HFD_t hfd = headerFreeData;
344  char ** fileNames;
345  const char ** dirNames;
346  const char ** baseNames;
347  int_32 * dirIndexes;
348  rpmTagType fnt;
349  int count;
350  int i, xx;
351  int dirIndex = -1;
352 
353  /*
354  * This assumes the file list is already sorted, and begins with a
355  * single '/'. That assumption isn't critical, but it makes things go
356  * a bit faster.
357  */
358 
359  if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
360  xx = hre(h, RPMTAG_OLDFILENAMES);
361  return; /* Already converted. */
362  }
363 
364  if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (void **) &fileNames, &count))
365  return; /* no file list */
366  if (fileNames == NULL || count <= 0)
367  return;
368 
369  dirNames = alloca(sizeof(*dirNames) * count); /* worst case */
370  baseNames = alloca(sizeof(*dirNames) * count);
371  dirIndexes = alloca(sizeof(*dirIndexes) * count);
372 
373  if (fileNames[0][0] != '/') {
374  /* HACK. Source RPM, so just do things differently */
375  dirIndex = 0;
376  dirNames[dirIndex] = "";
377  for (i = 0; i < count; i++) {
378  dirIndexes[i] = dirIndex;
379  baseNames[i] = fileNames[i];
380  }
381  goto exit;
382  }
383 
384  /*@-branchstate@*/
385  for (i = 0; i < count; i++) {
386  const char ** needle;
387  char savechar;
388  char * baseName;
389  int len;
390 
391  if (fileNames[i] == NULL) /* XXX can't happen */
392  continue;
393  baseName = strrchr(fileNames[i], '/') + 1;
394  len = baseName - fileNames[i];
395  needle = dirNames;
396  savechar = *baseName;
397  *baseName = '\0';
398 /*@-compdef@*/
399  if (dirIndex < 0 ||
400  (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
401  char *s = alloca(len + 1);
402  memcpy(s, fileNames[i], len + 1);
403  s[len] = '\0';
404  dirIndexes[i] = ++dirIndex;
405  dirNames[dirIndex] = s;
406  } else
407  dirIndexes[i] = needle - dirNames;
408 /*@=compdef@*/
409 
410  *baseName = savechar;
411  baseNames[i] = baseName;
412  }
413  /*@=branchstate@*/
414 
415 exit:
416  if (count > 0) {
417  xx = hae(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
419  baseNames, count);
421  dirNames, dirIndex + 1);
422  }
423 
424  fileNames = hfd(fileNames, fnt);
425 
426  xx = hre(h, RPMTAG_OLDFILENAMES);
427 }
428 /*@=bounds@*/
429 
430 /* rpm v3 compatibility */
431 static void rpm3to4(Header h) {
432  char * rpmversion;
433  int_32 rpmversion_type;
434 
435  (void) headerGetEntry(h, RPMTAG_RPMVERSION, NULL, (void **) &rpmversion, &rpmversion_type);
436 
437  if ((!rpmversion) || rpmversion[0] < '4') {
438  int *epoch;
439  const char * name, *version, *release;
440  const char *pEVR;
441  char *p;
442  int_32 pFlags = RPMSENSE_EQUAL;
443 
444  if (headerNVR(h, &name, &version, &release) == 0) {
445  pEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1);
446  *p = '\0';
447  if (headerGetEntry(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
448  sprintf(p, "%d:", *epoch);
449  while (*p != '\0')
450  p++;
451  }
452  (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release);
453 
457  }
458  compressFilelist(h);
459  }
460  headerFreeTag(h, (void *) rpmversion, rpmversion_type);
461  return;
462 }
463 
465 {
466  HFD_t hfd = (HFD_t) headerFreeData;
467  HAE_t hae = (HAE_t) headerAddEntry;
468  HeaderIterator hi;
469  int_32 tag, type, count;
470  const void * ptr;
471  int xx;
472 
473  for (hi = headerInitIterator(sigh);
474  headerNextIterator(hi, &tag, &type, &ptr, &count);
475  ptr = hfd(ptr, type))
476  {
477  switch (tag) {
478  /* XXX Translate legacy signature tag values. */
479  case RPMSIGTAG_SIZE:
480  tag = RPMTAG_SIGSIZE;
481  /*@switchbreak@*/ break;
482  case RPMSIGTAG_LEMD5_1:
483  tag = RPMTAG_SIGLEMD5_1;
484  /*@switchbreak@*/ break;
485  case RPMSIGTAG_PGP:
486  tag = RPMTAG_SIGPGP;
487  /*@switchbreak@*/ break;
488  case RPMSIGTAG_LEMD5_2:
489  tag = RPMTAG_SIGLEMD5_2;
490  /*@switchbreak@*/ break;
491  case RPMSIGTAG_MD5:
492  tag = RPMTAG_SIGMD5;
493  /*@switchbreak@*/ break;
494  case RPMSIGTAG_GPG:
495  tag = RPMTAG_SIGGPG;
496  /*@switchbreak@*/ break;
497  case RPMSIGTAG_PGP5:
498  tag = RPMTAG_SIGPGP5;
499  /*@switchbreak@*/ break;
501  tag = RPMTAG_ARCHIVESIZE;
502  /*@switchbreak@*/ break;
503  case RPMSIGTAG_SHA1:
504  case RPMSIGTAG_DSA:
505  case RPMSIGTAG_RSA:
506  default:
507  if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
508  continue;
509  /*@switchbreak@*/ break;
510  }
511  if (ptr == NULL) continue; /* XXX can't happen */
512  if (!headerIsEntry(h, tag)) {
513  if (hdrchkType(type))
514  continue;
515  if (count < 0 || hdrchkData(count))
516  continue;
517  switch(type) {
518  case RPM_NULL_TYPE:
519  continue;
520  /*@notreached@*/ /*@switchbreak@*/ break;
521  case RPM_CHAR_TYPE:
522  case RPM_INT8_TYPE:
523  case RPM_INT16_TYPE:
524  case RPM_INT32_TYPE:
525  if (count != 1)
526  continue;
527  /*@switchbreak@*/ break;
528  case RPM_STRING_TYPE:
529  case RPM_BIN_TYPE:
530  if (count >= 16*1024)
531  continue;
532  /*@switchbreak@*/ break;
534  case RPM_I18NSTRING_TYPE:
535  continue;
536  /*@notreached@*/ /*@switchbreak@*/ break;
537  }
538  xx = hae(h, tag, type, ptr, count);
539  }
540  }
541  hi = headerFreeIterator(hi);
542 }
543 
544 Header headerRegenSigHeader(const Header h, int noArchiveSize)
545 {
546  HFD_t hfd = (HFD_t) headerFreeData;
547  Header sigh = rpmNewSignature();
548  HeaderIterator hi;
549  int_32 tag, stag, type, count;
550  const void * ptr;
551  int xx;
552 
553  for (hi = headerInitIterator(h);
554  headerNextIterator(hi, &tag, &type, &ptr, &count);
555  ptr = hfd(ptr, type))
556  {
557  switch (tag) {
558  /* XXX Translate legacy signature tag values. */
559  case RPMTAG_SIGSIZE:
560  stag = RPMSIGTAG_SIZE;
561  /*@switchbreak@*/ break;
562  case RPMTAG_SIGLEMD5_1:
563  stag = RPMSIGTAG_LEMD5_1;
564  /*@switchbreak@*/ break;
565  case RPMTAG_SIGPGP:
566  stag = RPMSIGTAG_PGP;
567  /*@switchbreak@*/ break;
568  case RPMTAG_SIGLEMD5_2:
569  stag = RPMSIGTAG_LEMD5_2;
570  /*@switchbreak@*/ break;
571  case RPMTAG_SIGMD5:
572  stag = RPMSIGTAG_MD5;
573  /*@switchbreak@*/ break;
574  case RPMTAG_SIGGPG:
575  stag = RPMSIGTAG_GPG;
576  /*@switchbreak@*/ break;
577  case RPMTAG_SIGPGP5:
578  stag = RPMSIGTAG_PGP5;
579  /*@switchbreak@*/ break;
580  case RPMTAG_ARCHIVESIZE:
581  /* XXX rpm-4.1 and later has archive size in signature header. */
582  if (noArchiveSize)
583  continue;
584  stag = RPMSIGTAG_PAYLOADSIZE;
585  /*@switchbreak@*/ break;
586  case RPMTAG_SHA1HEADER:
587  case RPMTAG_DSAHEADER:
588  case RPMTAG_RSAHEADER:
589  default:
590  if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
591  continue;
592  stag = tag;
593  /*@switchbreak@*/ break;
594  }
595  if (ptr == NULL) continue; /* XXX can't happen */
596  if (!headerIsEntry(sigh, stag))
597  xx = headerAddEntry(sigh, stag, type, ptr, count);
598  }
599  hi = headerFreeIterator(hi);
600  return sigh;
601 }
602 
608 static int rpmtsStashKeyid(rpmts ts)
609  /*@globals nextkeyid, nkeyids, keyids @*/
610  /*@modifies nextkeyid, nkeyids, keyids @*/
611 {
612  const void * sig = rpmtsSig(ts);
613  pgpDig dig = rpmtsDig(ts);
614  pgpDigParams sigp = rpmtsSignature(ts);
615  unsigned int keyid;
616  int i;
617 
618  if (sig == NULL || dig == NULL || sigp == NULL)
619  return 0;
620 
621  keyid = pgpGrab(sigp->signid+4, 4);
622  if (keyid == 0)
623  return 0;
624 
625  if (keyids != NULL)
626  for (i = 0; i < nkeyids; i++) {
627 /*@-boundsread@*/
628  if (keyid == keyids[i])
629  return 1;
630 /*@=boundsread@*/
631  }
632 
633  if (nkeyids < nkeyids_max) {
634  nkeyids++;
635  keyids = xrealloc(keyids, nkeyids * sizeof(*keyids));
636  }
637 /*@-boundswrite@*/
638  if (keyids) /* XXX can't happen */
639  keyids[nextkeyid] = keyid;
640 /*@=boundswrite@*/
641  nextkeyid++;
643 
644  return 0;
645 }
646 
647 int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate)
648 {
649 /*@-castexpose@*/
650  entryInfo pe = (entryInfo) pev;
651 /*@=castexpose@*/
652  entryInfo info = iv;
653  int i;
654 
655 /*@-boundsread@*/
656  for (i = 0; i < il; i++) {
657  info->tag = ntohl(pe[i].tag);
658  info->type = ntohl(pe[i].type);
659  info->offset = ntohl(pe[i].offset);
660  if (negate)
661  info->offset = -info->offset;
662  info->count = ntohl(pe[i].count);
663 
664  if (hdrchkType(info->type))
665  return i;
666  if (hdrchkAlign(info->type, info->offset))
667  return i;
668  if (!negate && hdrchkRange(dl, info->offset))
669  return i;
670  if (hdrchkData(info->count))
671  return i;
672 
673  }
674 /*@=boundsread@*/
675  return -1;
676 }
677 
691 rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, const char ** msg)
692 {
693  pgpDig dig;
694  unsigned char buf[8*BUFSIZ];
695  int_32 * ei = (int_32 *) uh;
696 /*@-boundsread@*/
697  int_32 il = ntohl(ei[0]);
698  int_32 dl = ntohl(ei[1]);
699 /*@-castexpose@*/
700  entryInfo pe = (entryInfo) &ei[2];
701 /*@=castexpose@*/
702 /*@=boundsread@*/
703  int_32 ildl[2];
704  int_32 pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl;
705  unsigned char * dataStart = (unsigned char *) (pe + il);
706  indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry));
707  entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info));
708  const void * sig = NULL;
709  const char * b;
710  rpmVSFlags vsflags = rpmtsVSFlags(ts);
711  int siglen = 0;
712  int blen;
713  size_t nb;
714  int_32 ril = 0;
715  unsigned char * regionEnd = NULL;
716  rpmRC rc = RPMRC_FAIL; /* assume failure */
717  int xx;
718  int i;
719  static int hclvl;
720 
721  hclvl++;
722 /*@-boundswrite@*/
723  buf[0] = '\0';
724 /*@=boundswrite@*/
725 
726  /* Is the blob the right size? */
727  if (uc > 0 && pvlen != uc) {
728  (void) snprintf(buf, sizeof(buf),
729  _("blob size(%d): BAD, 8 + 16 * il(%d) + dl(%d)\n"),
730  (int)uc, (int)il, (int)dl);
731  goto exit;
732  }
733 
734  /* Check (and convert) the 1st tag element. */
735  xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
736  if (xx != -1) {
737  (void) snprintf(buf, sizeof(buf),
738  _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
739  0, entry->info.tag, entry->info.type,
740  entry->info.offset, entry->info.count);
741  goto exit;
742  }
743 
744  /* Is there an immutable header region tag? */
745 /*@-sizeoftype@*/
746  if (!(entry->info.tag == RPMTAG_HEADERIMMUTABLE
747  && entry->info.type == RPM_BIN_TYPE
748  && entry->info.count == REGION_TAG_COUNT))
749  {
750  rc = RPMRC_NOTFOUND;
751  goto exit;
752  }
753 /*@=sizeoftype@*/
754 
755  /* Is the offset within the data area? */
756  if (entry->info.offset >= dl) {
757  (void) snprintf(buf, sizeof(buf),
758  _("region offset: BAD, tag %d type %d offset %d count %d\n"),
759  entry->info.tag, entry->info.type,
760  entry->info.offset, entry->info.count);
761  goto exit;
762  }
763 
764  /* Is there an immutable header region tag trailer? */
765  regionEnd = dataStart + entry->info.offset;
766 /*@-sizeoftype@*/
767 /*@-bounds@*/
768  (void) memcpy(info, regionEnd, REGION_TAG_COUNT);
769 /*@=bounds@*/
770  regionEnd += REGION_TAG_COUNT;
771 
772  xx = headerVerifyInfo(1, dl, info, &entry->info, 1);
773  if (xx != -1 ||
774  !(entry->info.tag == RPMTAG_HEADERIMMUTABLE
775  && entry->info.type == RPM_BIN_TYPE
776  && entry->info.count == REGION_TAG_COUNT))
777  {
778  (void) snprintf(buf, sizeof(buf),
779  _("region trailer: BAD, tag %d type %d offset %d count %d\n"),
780  entry->info.tag, entry->info.type,
781  entry->info.offset, entry->info.count);
782  goto exit;
783  }
784 /*@=sizeoftype@*/
785 /*@-boundswrite@*/
786  memset(info, 0, sizeof(*info));
787 /*@=boundswrite@*/
788 
789  /* Is the no. of tags in the region less than the total no. of tags? */
790  ril = entry->info.offset/sizeof(*pe);
791  if ((entry->info.offset % sizeof(*pe)) || ril > il) {
792  (void) snprintf(buf, sizeof(buf),
793  _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
794  goto exit;
795  }
796 
797  /* Find a header-only digest/signature tag. */
798  for (i = ril; i < il; i++) {
799  xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0);
800  if (xx != -1) {
801  (void) snprintf(buf, sizeof(buf),
802  _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
803  i, entry->info.tag, entry->info.type,
804  entry->info.offset, entry->info.count);
805  goto exit;
806  }
807 
808  switch (entry->info.tag) {
809  case RPMTAG_SHA1HEADER:
810  if (vsflags & RPMVSF_NOSHA1HEADER)
811  /*@switchbreak@*/ break;
812  blen = 0;
813 /*@-boundsread@*/
814  for (b = dataStart + entry->info.offset; *b != '\0'; b++) {
815  if (strchr("0123456789abcdefABCDEF", *b) == NULL)
816  /*@innerbreak@*/ break;
817  blen++;
818  }
819  if (entry->info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40)
820  {
821  (void) snprintf(buf, sizeof(buf), _("hdr SHA1: BAD, not hex\n"));
822  goto exit;
823  }
824 /*@=boundsread@*/
825  if (info->tag == 0) {
826 /*@-boundswrite@*/
827  *info = entry->info; /* structure assignment */
828 /*@=boundswrite@*/
829  siglen = blen + 1;
830  }
831  /*@switchbreak@*/ break;
832  case RPMTAG_RSAHEADER:
833  if (vsflags & RPMVSF_NORSAHEADER)
834  /*@switchbreak@*/ break;
835  if (entry->info.type != RPM_BIN_TYPE) {
836  (void) snprintf(buf, sizeof(buf), _("hdr RSA: BAD, not binary\n"));
837  goto exit;
838  }
839 /*@-boundswrite@*/
840  *info = entry->info; /* structure assignment */
841 /*@=boundswrite@*/
842  siglen = info->count;
843  /*@switchbreak@*/ break;
844  case RPMTAG_DSAHEADER:
845  if (vsflags & RPMVSF_NODSAHEADER)
846  /*@switchbreak@*/ break;
847  if (entry->info.type != RPM_BIN_TYPE) {
848  (void) snprintf(buf, sizeof(buf), _("hdr DSA: BAD, not binary\n"));
849  goto exit;
850  }
851 /*@-boundswrite@*/
852  *info = entry->info; /* structure assignment */
853 /*@=boundswrite@*/
854  siglen = info->count;
855  /*@switchbreak@*/ break;
856  default:
857  /*@switchbreak@*/ break;
858  }
859  }
860  rc = RPMRC_NOTFOUND;
861 
862 exit:
863  /* Return determined RPMRC_OK/RPMRC_FAIL conditions. */
864  if (rc != RPMRC_NOTFOUND) {
865 /*@-boundswrite@*/
866  buf[sizeof(buf)-1] = '\0';
867  if (msg) *msg = xstrdup(buf);
868 /*@=boundswrite@*/
869  hclvl--;
870  return rc;
871  }
872 
873  /* If no header-only digest/signature, then do simple sanity check. */
874  if (info->tag == 0) {
875 verifyinfo_exit:
876  xx = headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0);
877  if (xx != -1) {
878  (void) snprintf(buf, sizeof(buf),
879  _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
880  xx+1, entry->info.tag, entry->info.type,
881  entry->info.offset, entry->info.count);
882  rc = RPMRC_FAIL;
883  } else {
884  (void) snprintf(buf, sizeof(buf), "Header sanity check: OK\n");
885  rc = RPMRC_OK;
886  }
887 /*@-boundswrite@*/
888  buf[sizeof(buf)-1] = '\0';
889  if (msg) *msg = xstrdup(buf);
890 /*@=boundswrite@*/
891  hclvl--;
892  return rc;
893  }
894 
895  /* Verify header-only digest/signature. */
896  dig = rpmtsDig(ts);
897  if (dig == NULL)
898  goto verifyinfo_exit;
899  dig->nbytes = 0;
900 
901 /*@-boundsread@*/
902  sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen);
903 /*@=boundsread@*/
904  (void) rpmtsSetSig(ts, info->tag, info->type, sig, info->count);
905 
906  switch (info->tag) {
907  case RPMTAG_RSAHEADER:
908  /* Parse the parameters from the OpenPGP packets that will be needed. */
909  xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
910  if (dig->signature.version != 3 && dig->signature.version != 4) {
912  _("skipping header with unverifiable V%u signature\n"),
913  dig->signature.version);
914  rpmtsCleanDig(ts);
915  rc = RPMRC_FAIL;
916  goto exit;
917  }
918 
919  ildl[0] = htonl(ril);
920  ildl[1] = (regionEnd - dataStart);
921  ildl[1] = htonl(ildl[1]);
922 
923  (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
925 
926  b = (unsigned char *) header_magic;
927  nb = sizeof(header_magic);
928  (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
929  dig->nbytes += nb;
930 
931  b = (unsigned char *) ildl;
932  nb = sizeof(ildl);
933  (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
934  dig->nbytes += nb;
935 
936  b = (unsigned char *) pe;
937  nb = (htonl(ildl[0]) * sizeof(*pe));
938  (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
939  dig->nbytes += nb;
940 
941  b = (unsigned char *) dataStart;
942  nb = htonl(ildl[1]);
943  (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
944  dig->nbytes += nb;
945  (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
946 
947  break;
948  case RPMTAG_DSAHEADER:
949  /* Parse the parameters from the OpenPGP packets that will be needed. */
950  xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
951  if (dig->signature.version != 3 && dig->signature.version != 4) {
953  _("skipping header with unverifiable V%u signature\n"),
954  dig->signature.version);
955  rpmtsCleanDig(ts);
956  rc = RPMRC_FAIL;
957  goto exit;
958  }
959  /*@fallthrough@*/
960  case RPMTAG_SHA1HEADER:
961 /*@-boundswrite@*/
962  ildl[0] = htonl(ril);
963  ildl[1] = (regionEnd - dataStart);
964  ildl[1] = htonl(ildl[1]);
965 /*@=boundswrite@*/
966 
967  (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
969 
970  b = (unsigned char *) header_magic;
971  nb = sizeof(header_magic);
972  (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
973  dig->nbytes += nb;
974 
975  b = (unsigned char *) ildl;
976  nb = sizeof(ildl);
977  (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
978  dig->nbytes += nb;
979 
980  b = (unsigned char *) pe;
981  nb = (htonl(ildl[0]) * sizeof(*pe));
982  (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
983  dig->nbytes += nb;
984 
985  b = (unsigned char *) dataStart;
986  nb = htonl(ildl[1]);
987  (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
988  dig->nbytes += nb;
989  (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
990 
991  break;
992  default:
993  sig = _free(sig);
994  break;
995  }
996 
997 /*@-boundswrite@*/
998  buf[0] = '\0';
999 /*@=boundswrite@*/
1000  rc = rpmVerifySignature(ts, buf);
1001 
1002 /*@-boundswrite@*/
1003  buf[sizeof(buf)-1] = '\0';
1004  if (msg) *msg = xstrdup(buf);
1005 /*@=boundswrite@*/
1006 
1007  /* XXX headerCheck can recurse, free info only at top level. */
1008  if (hclvl == 1)
1009  rpmtsCleanDig(ts);
1010  if (info->tag == RPMTAG_SHA1HEADER)
1011  sig = _free(sig);
1012  hclvl--;
1013  return rc;
1014 }
1015 
1016 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, const char ** msg)
1017 {
1018  char buf[BUFSIZ];
1019  int_32 block[4];
1020  int_32 il;
1021  int_32 dl;
1022  int_32 * ei = NULL;
1023  size_t uc;
1024  size_t startoff;
1025  int_32 nb;
1026  Header h = NULL;
1027  const char * origin = NULL;
1028  rpmRC rc = RPMRC_FAIL; /* assume failure */
1029  int xx;
1030 
1031 /*@-boundswrite@*/
1032  buf[0] = '\0';
1033 
1034  if (hdrp)
1035  *hdrp = NULL;
1036  if (msg)
1037  *msg = NULL;
1038 /*@=boundswrite@*/
1039 
1040  startoff = fd->stats->ops[FDSTAT_READ].bytes;
1041  memset(block, 0, sizeof(block));
1042  if ((xx = timedRead(fd, (char *)block, sizeof(block))) != sizeof(block)) {
1043  (void) snprintf(buf, sizeof(buf),
1044  _("hdr size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx);
1045  goto exit;
1046  }
1047  if (memcmp(block, header_magic, sizeof(header_magic))) {
1048  (void) snprintf(buf, sizeof(buf), _("hdr magic: BAD\n"));
1049  goto exit;
1050  }
1051 /*@-boundsread@*/
1052  il = ntohl(block[2]);
1053 /*@=boundsread@*/
1054  if (hdrchkTags(il)) {
1055  (void) snprintf(buf, sizeof(buf),
1056  _("hdr tags: BAD, no. of tags(%d) out of range\n"), il);
1057 
1058  goto exit;
1059  }
1060 /*@-boundsread@*/
1061  dl = ntohl(block[3]);
1062 /*@=boundsread@*/
1063  if (hdrchkData(dl)) {
1064  (void) snprintf(buf, sizeof(buf),
1065  _("hdr data: BAD, no. of bytes(%d) out of range\n"), dl);
1066  goto exit;
1067  }
1068 
1069 /*@-sizeoftype@*/
1070  nb = (il * sizeof(struct entryInfo_s)) + dl;
1071 /*@=sizeoftype@*/
1072  uc = sizeof(il) + sizeof(dl) + nb;
1073  ei = xmalloc(uc);
1074 /*@-bounds@*/
1075  ei[0] = block[2];
1076  ei[1] = block[3];
1077  if ((xx = timedRead(fd, (char *)&ei[2], nb)) != nb) {
1078  (void) snprintf(buf, sizeof(buf),
1079  _("hdr blob(%d): BAD, read returned %d\n"), nb, xx);
1080  goto exit;
1081  }
1082 /*@=bounds@*/
1083 
1084  /* Sanity check header tags */
1085  rc = headerCheck(ts, ei, uc, msg);
1086  if (rc != RPMRC_OK)
1087  goto exit;
1088 
1089  /* OK, blob looks sane, load the header. */
1090  h = headerLoad(ei);
1091  if (h == NULL) {
1092  (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n"));
1093  goto exit;
1094  }
1096  ei = NULL; /* XXX will be freed with header */
1097 
1098  /* Save the opened path as the header origin. */
1099  origin = fdGetOPath(fd);
1100  if (origin != NULL) {
1101  const char * lpath = NULL;
1102  int ut = urlPath(origin, &lpath);
1103  ut = ut; /* XXX keep gcc quiet. */
1104  if (lpath && *lpath != '/') {
1105  char * rpath = Realpath(origin, NULL);
1106  (void) headerSetOrigin(h, rpath);
1107  rpath = _free(rpath);
1108  } else
1109  (void) headerSetOrigin(h, origin);
1110  }
1111  { struct stat * st = headerGetStatbuf(h);
1112  int saveno = errno;
1113  (void) fstat(Fileno(fd), st);
1114  errno = saveno;
1115  }
1116  (void) headerSetStartOff(h, startoff);
1117  (void) headerSetEndOff(h, fd->stats->ops[FDSTAT_READ].bytes);
1118 
1119 exit:
1120 /*@-boundswrite@*/
1121  if (hdrp && h && rc == RPMRC_OK)
1122  *hdrp = headerLink(h);
1123 /*@=boundswrite@*/
1124  ei = _free(ei);
1125  h = headerFree(h);
1126 
1127 /*@-boundswrite@*/
1128  if (msg != NULL && *msg == NULL && buf[0] != '\0') {
1129  buf[sizeof(buf)-1] = '\0';
1130  *msg = xstrdup(buf);
1131  }
1132 /*@=boundswrite@*/
1133 
1134  return rc;
1135 }
1136 
1137 /*@-bounds@*/ /* LCL: segfault */
1138 rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
1139 {
1140  pgpDig dig;
1141  byte buf[8*BUFSIZ];
1142  ssize_t count;
1143  struct rpmlead * l = alloca(sizeof(*l));
1144  Header sigh = NULL;
1145  int_32 sigtag;
1146  int_32 sigtype;
1147  const void * sig;
1148  int_32 siglen;
1149  rpmtsOpX opx;
1150  size_t nb;
1151  Header h = NULL;
1152  const char * msg;
1153  rpmVSFlags vsflags;
1154  rpmRC rc = RPMRC_FAIL; /* assume failure */
1155  rpmop opsave = memset(alloca(sizeof(*opsave)), 0, sizeof(*opsave));
1156  int xx;
1157  int i;
1158 
1159  if (hdrp) *hdrp = NULL;
1160 
1161 #ifdef DYING
1162  { struct stat st;
1163 /*@-boundswrite@*/
1164  memset(&st, 0, sizeof(st));
1165 /*@=boundswrite@*/
1166  (void) fstat(Fileno(fd), &st);
1167  /* if fd points to a socket, pipe, etc, st.st_size is *always* zero */
1168  if (S_ISREG(st.st_mode) && st.st_size < sizeof(*l)) {
1169  rc = RPMRC_NOTFOUND;
1170  goto exit;
1171  }
1172  }
1173 #endif
1174 
1175  /* Snapshot current I/O counters (cached persistent I/O reuses counters) */
1176  (void) rpmswAdd(opsave, fdstat_op(fd, FDSTAT_READ));
1177 
1178  memset(l, 0, sizeof(*l));
1179  rc = readLead(fd, l);
1180  if (rc != RPMRC_OK)
1181  goto exit;
1182 
1183  switch (l->major) {
1184  case 1:
1186  _("packaging version 1 is not supported by this version of RPM\n"));
1187  rc = RPMRC_NOTFOUND;
1188  goto exit;
1189  /*@notreached@*/ break;
1190  case 2:
1191  case 3:
1192  case 4:
1193  break;
1194  default:
1195  rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 "
1196  "is supported by this version of RPM\n"));
1197  rc = RPMRC_NOTFOUND;
1198  goto exit;
1199  /*@notreached@*/ break;
1200  }
1201 
1202  /* Read the signature header. */
1203  msg = NULL;
1204  rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
1205  switch (rc) {
1206  default:
1207  rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed: %s"), fn,
1208  (msg && *msg ? msg : "\n"));
1209  msg = _free(msg);
1210  goto exit;
1211  /*@notreached@*/ break;
1212  case RPMRC_OK:
1213  if (sigh == NULL) {
1214  rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn);
1215  rc = RPMRC_FAIL;
1216  goto exit;
1217  }
1218  break;
1219  }
1220  msg = _free(msg);
1221 
1222 #define _chk(_mask) (sigtag == 0 && !(vsflags & (_mask)))
1223 
1224  /*
1225  * Figger the most effective available signature.
1226  * Prefer signatures over digests, then header-only over header+payload.
1227  * DSA will be preferred over RSA if both exist because tested first.
1228  * Note that NEEDPAYLOAD prevents header+payload signatures and digests.
1229  */
1230  sigtag = 0;
1231  opx = 0;
1232  vsflags = rpmtsVSFlags(ts);
1234  sigtag = RPMSIGTAG_DSA;
1235  } else
1237  sigtag = RPMSIGTAG_RSA;
1238  } else
1241  {
1242  sigtag = RPMSIGTAG_GPG;
1244  opx = RPMTS_OP_SIGNATURE;
1245  } else
1248  {
1249  sigtag = RPMSIGTAG_PGP;
1250  fdInitDigest(fd, PGPHASHALGO_MD5, 0);
1251  opx = RPMTS_OP_SIGNATURE;
1252  } else
1254  sigtag = RPMSIGTAG_SHA1;
1255  } else
1258  {
1259  sigtag = RPMSIGTAG_MD5;
1260  fdInitDigest(fd, PGPHASHALGO_MD5, 0);
1261  opx = RPMTS_OP_DIGEST;
1262  }
1263 
1264  /* Read the metadata, computing digest(s) on the fly. */
1265  h = NULL;
1266  msg = NULL;
1267 
1268  /* XXX stats will include header i/o and setup overhead. */
1269  /* XXX repackaged packages have appended tags, legacy dig/sig check fails */
1270  if (opx > 0)
1271  (void) rpmswEnter(rpmtsOp(ts, opx), 0);
1272 /*@-type@*/ /* XXX arrow access of non-pointer (FDSTAT_t) */
1273  nb = -fd->stats->ops[FDSTAT_READ].bytes;
1274  rc = rpmReadHeader(ts, fd, &h, &msg);
1275  nb += fd->stats->ops[FDSTAT_READ].bytes;
1276 /*@=type@*/
1277  if (opx > 0)
1278  (void) rpmswExit(rpmtsOp(ts, opx), nb);
1279 
1280  if (rc != RPMRC_OK || h == NULL) {
1281  rpmError(RPMERR_FREAD, _("%s: headerRead failed: %s"), fn,
1282  (msg && *msg ? msg : "\n"));
1283  msg = _free(msg);
1284  goto exit;
1285  }
1286  msg = _free(msg);
1287 
1288  /* Any digests or signatures to check? */
1289  if (sigtag == 0) {
1290  rc = RPMRC_OK;
1291  goto exit;
1292  }
1293 
1294  dig = rpmtsDig(ts);
1295  if (dig == NULL) {
1296  rc = RPMRC_FAIL;
1297  goto exit;
1298  }
1299  dig->nbytes = 0;
1300 
1301  /* Retrieve the tag parameters from the signature header. */
1302  sig = NULL;
1303  xx = headerGetEntry(sigh, sigtag, &sigtype, (void **) &sig, &siglen);
1304  if (sig == NULL) {
1305  rc = RPMRC_FAIL;
1306  goto exit;
1307  }
1308  (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
1309 
1310  switch (sigtag) {
1311  case RPMSIGTAG_RSA:
1312  /* Parse the parameters from the OpenPGP packets that will be needed. */
1313  xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
1314  if (dig->signature.version != 3 && dig->signature.version != 4) {
1316  _("skipping package %s with unverifiable V%u signature\n"),
1317  fn, dig->signature.version);
1318  rc = RPMRC_FAIL;
1319  goto exit;
1320  }
1321  { void * uh = NULL;
1322  int_32 uht;
1323  int_32 uhc;
1324 
1325  if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
1326  break;
1327  (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1329  (void) rpmDigestUpdate(dig->hdrmd5ctx, header_magic, sizeof(header_magic));
1330  dig->nbytes += sizeof(header_magic);
1331  (void) rpmDigestUpdate(dig->hdrmd5ctx, uh, uhc);
1332  dig->nbytes += uhc;
1333  (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
1334  rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */
1335  uh = headerFreeData(uh, uht);
1336  } break;
1337  case RPMSIGTAG_DSA:
1338  /* Parse the parameters from the OpenPGP packets that will be needed. */
1339  xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
1340  if (dig->signature.version != 3 && dig->signature.version != 4) {
1342  _("skipping package %s with unverifiable V%u signature\n"),
1343  fn, dig->signature.version);
1344  rc = RPMRC_FAIL;
1345  goto exit;
1346  }
1347  /*@fallthrough@*/
1348  case RPMSIGTAG_SHA1:
1349  { void * uh = NULL;
1350  int_32 uht;
1351  int_32 uhc;
1352 
1353  if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
1354  break;
1355  (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1357  (void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic));
1358  dig->nbytes += sizeof(header_magic);
1359  (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
1360  dig->nbytes += uhc;
1361  (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
1362  if (sigtag == RPMSIGTAG_SHA1)
1363  rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */
1364  uh = headerFreeData(uh, uht);
1365  } break;
1366  case RPMSIGTAG_GPG:
1367  case RPMSIGTAG_PGP5: /* XXX legacy */
1368  case RPMSIGTAG_PGP:
1369  /* Parse the parameters from the OpenPGP packets that will be needed. */
1370  xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
1371 
1372  if (dig->signature.version != 3 && dig->signature.version != 4) {
1374  _("skipping package %s with unverifiable V%u signature\n"),
1375  fn, dig->signature.version);
1376  rc = RPMRC_FAIL;
1377  goto exit;
1378  }
1379  /*@fallthrough@*/
1380  case RPMSIGTAG_MD5:
1381  /* Legacy signatures need the compressed payload in the digest too. */
1382  (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
1383  while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
1384  dig->nbytes += count;
1385  (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
1386  rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */
1387  dig->nbytes += nb; /* XXX include size of header blob. */
1388  if (count < 0) {
1389  rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
1390  fn, Fstrerror(fd));
1391  rc = RPMRC_FAIL;
1392  goto exit;
1393  }
1394 
1395  /* XXX Steal the digest-in-progress from the file handle. */
1396  for (i = fd->ndigests - 1; i >= 0; i--) {
1397  FDDIGEST_t fddig = fd->digests + i;
1398  if (fddig->hashctx != NULL)
1399  switch (fddig->hashalgo) {
1400  case PGPHASHALGO_MD5:
1401  dig->md5ctx = fddig->hashctx;
1402  fddig->hashctx = NULL;
1403  /*@switchbreak@*/ break;
1404  case PGPHASHALGO_SHA1:
1405  case PGPHASHALGO_RIPEMD160:
1406 #if HAVE_BEECRYPT_API_H
1407  case PGPHASHALGO_SHA256:
1408  case PGPHASHALGO_SHA384:
1409  case PGPHASHALGO_SHA512:
1410 #endif
1411  dig->sha1ctx = fddig->hashctx;
1412  fddig->hashctx = NULL;
1413  /*@switchbreak@*/ break;
1414  default:
1415  /*@switchbreak@*/ break;
1416  }
1417  }
1418  break;
1419  }
1420 
1423 /*@-boundswrite@*/
1424  buf[0] = '\0';
1425 /*@=boundswrite@*/
1426  rc = rpmVerifySignature(ts, buf);
1427  switch (rc) {
1428  case RPMRC_OK: /* Signature is OK. */
1429  rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
1430  break;
1431  case RPMRC_NOTTRUSTED: /* Signature is OK, but key is not trusted. */
1432  case RPMRC_NOKEY: /* Public key is unavailable. */
1433  /* XXX Print NOKEY/NOTTRUSTED warning only once. */
1434  { int lvl = (rpmtsStashKeyid(ts) ? RPMMESS_DEBUG : RPMMESS_WARNING);
1435  rpmMessage(lvl, "%s: %s", fn, buf);
1436  } break;
1437  case RPMRC_NOTFOUND: /* Signature is unknown type. */
1438  rpmMessage(RPMMESS_WARNING, "%s: %s", fn, buf);
1439  break;
1440  default:
1441  case RPMRC_FAIL: /* Signature does not verify. */
1442  rpmMessage(RPMMESS_ERROR, "%s: %s", fn, buf);
1443  break;
1444  }
1445 
1446 exit:
1447  if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
1448 
1449  /* Append (and remap) signature tags to the metadata. */
1450  headerMergeLegacySigs(h, sigh);
1451 
1452 #if defined(RPM_VENDOR_MANDRIVA)
1453  rpm3to4(h);
1454 #endif
1455 
1456  rpm3to4(h);
1457 
1458  /* Bump reference count for return. */
1459 /*@-boundswrite@*/
1460  *hdrp = headerLink(h);
1461 /*@=boundswrite@*/
1462  }
1463  h = headerFree(h);
1464 
1465  /* Accumulate time reading package header. */
1466  (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_READHDR),
1467  fdstat_op(fd, FDSTAT_READ));
1468  (void) rpmswSub(rpmtsOp(ts, RPMTS_OP_READHDR),
1469  opsave);
1470 
1471  rpmtsCleanDig(ts);
1472  sigh = rpmFreeSignature(sigh);
1473  return rc;
1474 }
1475 /*@=bounds@*/