rpm  5.2.1
pkgio.c
Go to the documentation of this file.
1 
6 #include "system.h"
7 
8 #if defined(HAVE_MACHINE_TYPES_H)
9 # include <machine/types.h>
10 #endif
11 
12 #include <netinet/in.h>
13 
14 #define _RPMIOB_INTERNAL
15 #include <rpmiotypes.h>
16 #include <rpmio_internal.h>
17 #include <rpmcb.h>
18 #include <rpmbc.h> /* XXX beecrypt base64 */
19 #include <rpmmacro.h>
20 #include <rpmku.h>
21 
22 #define _RPMTAG_INTERNAL
23 #include "header_internal.h"
24 
25 #include <rpmdb.h>
26 #include <pkgio.h>
27 
28 #define _RPMTS_INTERNAL
29 #include "rpmts.h"
30 
31 #include <rpmxar.h>
32 
33 #include "signature.h"
34 #include "debug.h"
35 
36 /*@access rpmts @*/
37 /*@access rpmxar @*/
38 /*@access pgpDig @*/
39 /*@access pgpDigParams @*/
40 /*@access Header @*/ /* XXX compared with NULL */
41 /*@access entryInfo @*/
42 /*@access indexEntry @*/
43 /*@access FD_t @*/ /* XXX stealing digests */
44 /*@access FDSTAT_t @*/ /* XXX stealing digests */
45 
46 /*@unchecked@*/
47 int _pkgio_debug = 0;
48 
49 /*@unchecked@*/
50 static int _print_pkts = 0;
51 
54 /*@-exportheader@*/
55 /*@unused@*/ ssize_t timedRead(FD_t fd, /*@out@*/ void * bufptr, size_t length)
56  /*@globals fileSystem @*/
57  /*@modifies fd, *bufptr, fileSystem @*/;
58 #define timedRead (ufdio->read)
59 /*@=exportheader@*/
60 
61 /*===============================================*/
69 static
70 rpmRC rpmWriteHeader(FD_t fd, /*@null@*/ Header h, /*@null@*/ const char ** msg)
71  /*@globals fileSystem, internalState @*/
72  /*@modifies fd, h, *msg, fileSystem, internalState @*/
73 {
74  const void * uh = NULL;
75  size_t nb;
76  size_t length;
77  rpmRC rc = RPMRC_FAIL; /* assume failure */
78 
79 if (_pkgio_debug)
80 fprintf(stderr, "--> rpmWriteHeader(%p, %p, %p)\n", fd, h, msg);
81 
82  if (h == NULL) {
83  if (msg)
84  *msg = xstrdup(_("write of NULL header"));
85  goto exit;
86  }
87 
88  uh = headerUnload(h, &length);
89  if (uh == NULL) {
90  if (msg)
91  *msg = xstrdup(_("headerUnload failed"));
92  goto exit;
93  }
94 
95  { unsigned char * hmagic = NULL;
96  size_t nmagic = 0;
97 
98  (void) headerGetMagic(NULL, &hmagic, &nmagic);
99  nb = Fwrite(hmagic, sizeof(hmagic[0]), nmagic, fd);
100  if (nb != nmagic || Ferror(fd)) {
101  if (msg)
102  *msg = (nb > 0
103  ? xstrdup(_("short write of header magic"))
104  : xstrdup(Fstrerror(fd)) );
105  goto exit;
106  }
107  }
108 
109  /*@-sizeoftype@*/
110  nb = Fwrite(uh, sizeof(char), length, fd);
111  /*@=sizeoftype@*/
112  if (nb != length || Ferror(fd)) {
113  if (msg)
114  *msg = (nb > 0
115  ? xstrdup(_("short write of header"))
116  : xstrdup(Fstrerror(fd)) );
117  goto exit;
118  }
119  rc = RPMRC_OK;
120 
121 exit:
122  uh = _free(uh);
123  return rc;
124 }
125 
126 /*===============================================*/
127 
129 {
130  rpmop op = NULL;
131 
132  if (ts != NULL && (int)opx >= 0 && (int)opx < RPMTS_OP_MAX)
133  op = ts->ops + opx;
134 /*@-usereleased -compdef @*/
135  return op;
136 /*@=usereleased =compdef @*/
137 }
138 
140 {
141 /*@-onlytrans@*/
142  return pgpGetPubkey(rpmtsDig(ts));
143 /*@=onlytrans@*/
144 }
145 
147 {
148  rpmdb rdb = NULL;
149  if (ts != NULL) {
150  rdb = ts->rdb;
151  }
152 /*@-compdef -refcounttrans -usereleased @*/
153  return rdb;
154 /*@=compdef =refcounttrans =usereleased @*/
155 }
156 
157 rpmRC rpmtsFindPubkey(rpmts ts, void * _dig)
158 {
159  HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
160  pgpDig dig = (_dig ? _dig : rpmtsDig(ts));
161  pgpDigParams sigp = pgpGetSignature(dig);
162  pgpDigParams pubp = pgpGetPubkey(dig);
163  rpmRC res = RPMRC_NOKEY;
164  const char * pubkeysource = NULL;
165  rpmiob iob = NULL;
166  int krcache = 1; /* XXX assume pubkeys are cached in keyutils keyring. */
167  int xx;
168 
169 assert(dig != NULL);
170 assert(sigp != NULL);
171 assert(pubp != NULL);
172 /*@-sefparams@*/
173 assert(rpmtsDig(ts) == dig);
174 /*@=sefparams@*/
175 
176 #if 0
177 fprintf(stderr, "==> find sig id %08x %08x ts pubkey id %08x %08x\n",
178 pgpGrab(sigp->signid, 4), pgpGrab(sigp->signid+4, 4),
179 pgpGrab(ts->pksignid, 4), pgpGrab(ts->pksignid+4, 4));
180 #endif
181 
182  /* Lazy free of previous pubkey if pubkey does not match this signature. */
183  if (memcmp(sigp->signid, ts->pksignid, sizeof(ts->pksignid))) {
184 #if 0
185 fprintf(stderr, "*** free pkt %p[%d] id %08x %08x\n", ts->pkpkt, ts->pkpktlen, pgpGrab(ts->pksignid, 4), pgpGrab(ts->pksignid+4, 4));
186 #endif
187  ts->pkpkt = _free(ts->pkpkt);
188  ts->pkpktlen = 0;
189  memset(ts->pksignid, 0, sizeof(ts->pksignid));
190  }
191 
192  /* Try keyutils keyring lookup. */
193  if (ts->pkpkt == NULL) {
194  iob = NULL;
195  switch (rpmkuFindPubkey(sigp, &iob)) {
196  case RPMRC_NOTFOUND:
197  case RPMRC_FAIL:
198  case RPMRC_NOTTRUSTED:
199  case RPMRC_NOKEY:
200  break;
201  case RPMRC_OK:
202  pubkeysource = xstrdup("keyutils");
203  krcache = 0; /* XXX don't bother caching. */
204  ts->pkpkt = memcpy(xmalloc(iob->blen), iob->b, iob->blen);
205  ts->pkpktlen = iob->blen;
206  break;
207  }
208  }
209 
210  /* Try rpmdb keyring lookup. */
211  if (ts->pkpkt == NULL) {
212  unsigned hx = 0xffffffff;
213  unsigned ix = 0xffffffff;
214  rpmmi mi;
215  Header h;
216 
217  /* XXX Do a lazy open if not done already. */
218  if (ts->rdb == NULL) {
219  xx = rpmdbOpen(ts->rootDir, &ts->rdb, ts->dbmode, 0644);
220  if (xx) {
221  const char * dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL);
223  _("cannot open Packages database in %s\n"), dn);
224  dn = _free(dn);
225  }
226  }
227 
228  /* Retrieve the pubkey that matches the signature. */
229  he->tag = RPMTAG_PUBKEYS;
230 /*@-nullstate@*/
231  mi = rpmmiInit(rpmtsGetRdb(ts), RPMTAG_PUBKEYS, sigp->signid, sizeof(sigp->signid));
232 /*@=nullstate@*/
233  while ((h = rpmmiNext(mi)) != NULL) {
234  if (!headerGet(h, he, 0))
235  continue;
236  hx = rpmmiInstance(mi);
237  ix = rpmmiFilenum(mi);
238 /*@-moduncon -nullstate @*/
239  if (ix >= (unsigned) he->c
240  || b64decode(he->p.argv[ix], (void **) &ts->pkpkt, &ts->pkpktlen))
241  ix = 0xffffffff;
242 /*@=moduncon =nullstate @*/
243  he->p.ptr = _free(he->p.ptr);
244  break;
245  }
246  mi = rpmmiFree(mi);
247 
248  if (ix < 0xffffffff) {
249  char hnum[32];
250  sprintf(hnum, "h#%u", hx);
251  pubkeysource = xstrdup(hnum);
252  } else {
253  ts->pkpkt = _free(ts->pkpkt);
254  ts->pkpktlen = 0;
255  }
256  }
257 
258  /* Try keyserver lookup. */
259  if (ts->pkpkt == NULL) {
260  const char * fn = rpmExpand("%{_hkp_keyserver_query}",
261  pgpHexStr(sigp->signid, sizeof(sigp->signid)), NULL);
262 
263  xx = 0;
264  if (fn && *fn != '%') {
265  xx = (pgpReadPkts(fn, &ts->pkpkt, &ts->pkpktlen) != PGPARMOR_PUBKEY);
266  }
267  fn = _free(fn);
268  if (xx) {
269  ts->pkpkt = _free(ts->pkpkt);
270  ts->pkpktlen = 0;
271  } else {
272  /* Save new pubkey in local ts keyring for delayed import. */
273  pubkeysource = xstrdup("keyserver");
274  }
275  }
276 
277 #ifdef NOTNOW
278  /* Try filename from macro lookup. */
279  if (ts->pkpkt == NULL) {
280  const char * fn = rpmExpand("%{_gpg_pubkey}", NULL);
281 
282  xx = 0;
283  if (fn && *fn != '%')
284  xx = (pgpReadPkts(fn,&ts->pkpkt,&ts->pkpktlen) != PGPARMOR_PUBKEY);
285  fn = _free(fn);
286  if (xx) {
287  ts->pkpkt = _free(ts->pkpkt);
288  ts->pkpktlen = 0;
289  } else {
290  pubkeysource = xstrdup("macro");
291  }
292  }
293 #endif
294 
295  /* Was a matching pubkey found? */
296  if (ts->pkpkt == NULL || ts->pkpktlen == 0)
297  goto exit;
298 
299  /* Retrieve parameters from pubkey packet(s). */
300  xx = pgpPrtPkts((rpmuint8_t *)ts->pkpkt, ts->pkpktlen, dig, 0);
301 
302  /* Do the parameters match the signature? */
303  if (sigp->pubkey_algo == pubp->pubkey_algo
304 #ifdef NOTYET
305  && sigp->hash_algo == pubp->hash_algo
306 #endif
307  && !memcmp(sigp->signid, pubp->signid, sizeof(sigp->signid)) )
308  {
309 
310  /* XXX Verify any pubkey signatures. */
311 
312  /* Save the pubkey in the keyutils keyring. */
313  if (krcache) {
314  if (iob == NULL) {
315  iob = rpmiobNew(ts->pkpktlen);
316  iob->b = memcpy(iob->b, ts->pkpkt, iob->blen);
317  }
318  (void) rpmkuStorePubkey(sigp, iob);
319  }
320 
321  /* Pubkey packet looks good, save the signer id. */
322  memcpy(ts->pksignid, pubp->signid, sizeof(ts->pksignid));
323 
324  if (pubkeysource)
325  rpmlog(RPMLOG_DEBUG, "========== %s pubkey id %08x %08x (%s)\n",
326  (sigp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_DSA ? "DSA" :
327  (sigp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_RSA ? "RSA" :
328  "???")),
329  pgpGrab(sigp->signid, 4), pgpGrab(sigp->signid+4, 4),
330  pubkeysource);
331 
332  res = RPMRC_OK;
333  }
334 
335 exit:
336  pubkeysource = _free(pubkeysource);
337  if (res != RPMRC_OK) {
338  ts->pkpkt = _free(ts->pkpkt);
339  ts->pkpktlen = 0;
340  }
341 /*@-nullstate@*/
342  return res;
343 /*@=nullstate@*/
344 }
345 
347 {
348 /*@-mods@*/ /* FIX: hide lazy malloc for now */
349  if (ts->dig == NULL) {
350  ts->dig = pgpDigNew(0);
351 /*@-refcounttrans@*/
352  (void) pgpSetFindPubkey(ts->dig, (int (*)(void *, void *))rpmtsFindPubkey, ts);
353 /*@=refcounttrans@*/
354  }
355 /*@=mods@*/
356 /*@-compdef -retexpose -usereleased@*/
357  return ts->dig;
358 /*@=compdef =retexpose =usereleased@*/
359 }
360 
362 {
363  if (ts && ts->dig) {
364  int opx;
365  opx = RPMTS_OP_DIGEST;
366  (void) rpmswAdd(rpmtsOp(ts, opx), pgpStatsAccumulator(ts->dig, opx));
367  opx = RPMTS_OP_SIGNATURE;
368  (void) rpmswAdd(rpmtsOp(ts, opx), pgpStatsAccumulator(ts->dig, opx));
369 /*@-onlytrans@*/
370  (void) pgpDigFree(ts->dig, "rpmtsCleanDig");
371  ts->dig = NULL; /* XXX make sure the ptr is __REALLY__ gone */
372 /*@=onlytrans@*/
373  }
374 }
375 
376 /*===============================================*/
377 
384 struct rpmlead {
385  unsigned char magic[4];
386  unsigned char major;
387  unsigned char minor;
388  unsigned short type;
389  unsigned short archnum;
390  char name[66];
391  unsigned short osnum;
392  unsigned short signature_type;
393 /*@unused@*/
394  char reserved[16];
395 } ;
396 
397 /*@-type@*/
398 /*@unchecked@*/ /*@observer@*/
399 static unsigned char lead_magic[] = {
400  0xed, 0xab, 0xee, 0xdb, 0x00, 0x00, 0x00, 0x00
401 };
402 /*@=type@*/
403 
404 /* The lead needs to be 8 byte aligned */
405 
413 static rpmRC wrLead(FD_t fd, const void * ptr, /*@null@*/ const char ** msg)
414  /*@globals fileSystem @*/
415  /*@modifies fd, fileSystem @*/
416 {
417  struct rpmlead l;
418 
419 if (_pkgio_debug)
420 fprintf(stderr, "--> wrLead(%p, %p, %p)\n", fd, ptr, msg);
421 
422  memcpy(&l, ptr, sizeof(l));
423 
424  /* Set some sane defaults */
425  if ((int)l.major == 0)
426  l.major = (unsigned char) 3;
427  if (l.signature_type == 0)
428  l.signature_type = 5; /* RPMSIGTYPE_HEADERSIG */
429  if (msg && *msg)
430  (void) strncpy(l.name, *msg, sizeof(l.name));
431 
432  memcpy(&l.magic, lead_magic, sizeof(l.magic));
433  l.type = (unsigned short) htons(l.type);
434  l.archnum = (unsigned short) htons(l.archnum);
435  l.osnum = (unsigned short) htons(l.osnum);
436  l.signature_type = (unsigned short) htons(l.signature_type);
437 
438  if (Fwrite(&l, 1, sizeof(l), fd) != sizeof(l))
439  return RPMRC_FAIL;
440 
441  return RPMRC_OK;
442 }
443 
451 static rpmRC rdLead(FD_t fd, /*@out@*/ /*@null@*/ void * ptr,
452  /*@null@*/ const char ** msg)
453  /*@globals fileSystem @*/
454  /*@modifies fd, *ptr, *msg, fileSystem @*/
455 {
456  rpmxar xar = fdGetXAR(fd);
457  struct rpmlead ** leadp = ptr;
458  struct rpmlead * l = xcalloc(1, sizeof(*l));
459  char buf[BUFSIZ];
460  rpmRC rc = RPMRC_FAIL; /* assume failure */
461  int xx;
462 
463 if (_pkgio_debug)
464 fprintf(stderr, "--> rdLead(%p, %p, %p)\n", fd, ptr, msg);
465 
466  buf[0] = '\0';
467  if (leadp != NULL) *leadp = NULL;
468 
469  /* Read the first 96 bytes of the file. */
470  if ((xx = (int) timedRead(fd, (char *)l, sizeof(*l))) != (int) sizeof(*l)) {
471  if (Ferror(fd)) {
472  (void) snprintf(buf, sizeof(buf),
473  _("lead size(%u): BAD, read(%d), %s(%d)"),
474  (unsigned)sizeof(*l), xx, Fstrerror(fd), errno);
475  rc = RPMRC_FAIL;
476  } else {
477  (void) snprintf(buf, sizeof(buf),
478  _("lead size(%u): BAD, read(%d), %s(%d)"),
479  (unsigned)sizeof(*l), xx, strerror(errno), errno);
480  rc = RPMRC_NOTFOUND;
481  }
482  goto exit;
483  }
484 
485  /* Attach rpmxar handler to fd if this is a xar archive. */
486  if (xar == NULL) {
487  unsigned char * bh = (unsigned char *)l;
488  if (bh[0] == 'x' && bh[1] == 'a' && bh[2] == 'r' && bh[3] == '!') {
489  const char * fn = fdGetOPath(fd);
490 assert(fn != NULL);
491  xar = rpmxarNew(fn, "r");
492  fdSetXAR(fd, xar);
493  (void) rpmxarFree(xar, "rdLead");
494  }
495  }
496 
497  /* With XAR, read lead from a xar archive file called "Lead". */
498  xar = fdGetXAR(fd);
499  if (xar != NULL) {
500  unsigned char *b = NULL;
501  size_t nb = 0;
502  const char item[] = "Lead";
503  if ((xx = rpmxarNext(xar)) != 0 || (xx = rpmxarPull(xar, item)) != 0) {
504  (void) snprintf(buf, sizeof(buf),
505  _("XAR file not found (or no XAR support)"));
506  rc = RPMRC_NOTFOUND;
507  goto exit;
508  }
509  (void) rpmxarSwapBuf(xar, NULL, 0, &b, &nb);
510  if (nb != sizeof(*l)) {
511  (void) snprintf(buf, sizeof(buf),
512  _("lead size(%u): BAD, xar read(%u)"),
513  (unsigned)sizeof(*l), (unsigned)nb);
514  b = _free(b);
515  rc = RPMRC_FAIL;
516  goto exit;
517  }
518  memcpy(l, b, nb);
519  b = _free(b);
520  }
521 
522  l->type = (unsigned short) ntohs(l->type);
523  l->archnum = (unsigned short) ntohs(l->archnum);
524  l->osnum = (unsigned short) ntohs(l->osnum);
525  l->signature_type = (unsigned short) ntohs(l->signature_type);
526 
527  if (memcmp(l->magic, lead_magic, sizeof(l->magic))) {
528 /*@+charint@*/
529  (void) snprintf(buf, sizeof(buf), _("lead magic: BAD, read %02x%02x%02x%02x"), l->magic[0], l->magic[1], l->magic[2], l->magic[3]);
530 /*@=charint@*/
531  rc = RPMRC_NOTFOUND;
532  goto exit;
533  }
534 
535  switch (l->major) {
536  default:
537  (void) snprintf(buf, sizeof(buf),
538  _("lead version(%u): UNSUPPORTED"), (unsigned) l->major);
539  rc = RPMRC_NOTFOUND;
540  goto exit;
541  /*@notreached@*/ break;
542  case 3:
543  case 4:
544  break;
545  }
546 
547  if (l->signature_type != 5) { /* RPMSIGTYPE_HEADERSIG */
548  (void) snprintf(buf, sizeof(buf),
549  _("sigh type(%u): UNSUPPORTED"), (unsigned) l->signature_type);
550  rc = RPMRC_NOTFOUND;
551  goto exit;
552  }
553 
554  rc = RPMRC_OK;
555 
556 exit:
557  if (rc == RPMRC_OK && leadp != NULL)
558  *leadp = l;
559  else
560  /*@-dependenttrans@*/ l = _free(l); /*@=dependenttrans@*/
561 
562  if (msg != NULL && buf[0] != '\0') {
563  buf[sizeof(buf)-1] = '\0';
564  *msg = xstrdup(buf);
565  }
566  return rc;
567 }
568 
569 /*===============================================*/
570 
578 static rpmRC wrSignature(FD_t fd, void * ptr,
579  /*@unused@*/ /*@null@*/ const char ** msg)
580  /*@globals fileSystem, internalState @*/
581  /*@modifies fd, ptr, *msg, fileSystem, internalState @*/
582 {
583  Header sigh = ptr;
584  static unsigned char zero[8]
585  = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' };
586  size_t sigSize;
587  size_t pad;
588  rpmRC rc = RPMRC_OK;
589 
590 if (_pkgio_debug)
591 fprintf(stderr, "--> wrSignature(%p, %p, %p)\n", fd, ptr, msg);
592 
593  rc = rpmWriteHeader(fd, sigh, msg);
594  if (rc != RPMRC_OK)
595  return rc;
596 
597  sigSize = headerSizeof(sigh);
598  pad = (8 - (sigSize % 8)) % 8;
599  if (pad) {
600  if (Fwrite(zero, sizeof(zero[0]), pad, fd) != pad)
601  rc = RPMRC_FAIL;
602  }
603  rpmlog(RPMLOG_DEBUG, D_("Signature: size(%u)+pad(%u)\n"), (unsigned)sigSize, (unsigned)pad);
604  return rc;
605 }
606 
615 static inline rpmRC printSize(FD_t fd, size_t siglen, size_t pad, size_t datalen)
616  /*@globals fileSystem, internalState @*/
617  /*@modifies fileSystem, internalState @*/
618 {
619  struct stat sb, * st = &sb;
620  size_t expected;
621  size_t nl = rpmpkgSizeof("Lead", NULL);
622 
623 #ifndef DYING /* XXX Fstat(2) contentLength not gud enuf yet. */
624  int fdno = Fileno(fd);
625  /* HACK: workaround for davRead wiring. */
626  if (fdno == 123456789) {
627 /*@-type@*/
628  st->st_size = 0;
629  st->st_size -= nl + siglen + pad + datalen;
630 /*@=type@*/
631  } else
632 #endif
633  if (Fstat(fd, st) < 0)
634  return RPMRC_FAIL;
635 
636  expected = nl + siglen + pad + datalen;
638  D_("Expected size: %12lu = lead(%u)+sigs(%u)+pad(%u)+data(%lu)\n"),
639  (unsigned long)expected,
640  (unsigned)nl, (unsigned) siglen, (unsigned) pad,
641  (unsigned long)datalen);
643  D_(" Actual size: %12lu\n"), (unsigned long)st->st_size);
644 
645  return RPMRC_OK;
646 }
647 
655 static rpmRC rdSignature(FD_t fd, /*@out@*/ /*@null@*/ void * ptr,
656  /*@null@*/ const char ** msg)
657  /*@globals fileSystem, internalState @*/
658  /*@modifies *ptr, *msg, fileSystem, internalState @*/
659 {
660 rpmxar xar = fdGetXAR(fd);
661  HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
662  Header * sighp = ptr;
663  char buf[BUFSIZ];
664  rpmuint32_t block[4];
665  rpmuint32_t il;
666  rpmuint32_t dl;
667  rpmuint32_t * ei = NULL;
668  entryInfo pe;
669  size_t startoff;
670  size_t nb;
671  rpmuint32_t ril = 0;
672  indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry));
673  entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info));
674  unsigned char * dataStart;
675  unsigned char * dataEnd = NULL;
676  Header sigh = NULL;
677  rpmRC rc = RPMRC_FAIL; /* assume failure */
678  int xx;
679  rpmuint32_t i;
680  static int map = 1;
681 
682 if (_pkgio_debug)
683 fprintf(stderr, "--> rdSignature(%p, %p, %p)\n", fd, ptr, msg);
684 
685  buf[0] = '\0';
686  if (sighp)
687  *sighp = NULL;
688 
689  memset(block, 0, sizeof(block));
690  if (xar != NULL) {
691  const char item[] = "Signature";
692  if ((xx = rpmxarNext(xar)) != 0 || (xx = rpmxarPull(xar, item)) != 0) {
693  (void) snprintf(buf, sizeof(buf),
694  _("XAR file not found (or no XAR support)"));
695  rc = RPMRC_NOTFOUND;
696  goto exit;
697  }
698  }
699  startoff = fd->stats->ops[FDSTAT_READ].bytes;
700  if ((xx = (int) timedRead(fd, (void *)block, sizeof(block))) != (int) sizeof(block)) {
701  (void) snprintf(buf, sizeof(buf),
702  _("sigh size(%d): BAD, read returned %d"), (int)sizeof(block), xx);
703  goto exit;
704  }
705 
706  { unsigned char * hmagic = NULL;
707  size_t nmagic = 0;
708 
709  (void) headerGetMagic(NULL, &hmagic, &nmagic);
710 
711  if (memcmp(block, hmagic, nmagic)) {
712  unsigned char * x = (unsigned char *)block;
713 /*@+charint@*/
714  (void) snprintf(buf, sizeof(buf), _("sigh magic: BAD, read %02x%02x%02x%02x%02x%02x%02x%02x"), x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]);
715 /*@=charint@*/
716  goto exit;
717  }
718  }
719  il = (rpmuint32_t) ntohl(block[2]);
720  if (il > 32) {
721  (void) snprintf(buf, sizeof(buf),
722  _("sigh tags: BAD, no. of tags(%u) out of range"), (unsigned) il);
723  goto exit;
724  }
725  dl = (rpmuint32_t) ntohl(block[3]);
726  if (dl > 8192) {
727  (void) snprintf(buf, sizeof(buf),
728  _("sigh data: BAD, no. of bytes(%u) out of range"), (unsigned) dl);
729  goto exit;
730  }
731 
732 /*@-sizeoftype@*/
733  nb = (il * sizeof(struct entryInfo_s)) + dl;
734 /*@=sizeoftype@*/
735  if (map) {
736  size_t pvlen = (sizeof(il) + sizeof(dl) + nb);
737  static const int prot = PROT_READ | PROT_WRITE;
738  static const int flags = MAP_PRIVATE| MAP_ANONYMOUS;
739  static const int fdno = -1;
740  static const off_t off = 0;
741 
742  ei = mmap(NULL, pvlen, prot, flags, fdno, off);
743  if (ei == NULL || ei == (void *)-1)
744  fprintf(stderr,
745  "==> mmap(%p[%u], 0x%x, 0x%x, %d, 0x%x) error(%d): %s\n",
746  NULL, pvlen, prot, flags, fdno, (unsigned)off,
747  errno, strerror(errno));
748  } else {
749  size_t pvlen = (sizeof(il) + sizeof(dl) + nb);
750  ei = xmalloc(pvlen);
751  }
752 
753  if ((xx = (int) timedRead(fd, (void *)&ei[2], nb)) != (int) nb) {
754  (void) snprintf(buf, sizeof(buf),
755  _("sigh blob(%u): BAD, read returned %d"), (unsigned) nb, xx);
756  goto exit;
757  }
758  ei[0] = block[2];
759  ei[1] = block[3];
760 
761  if (map) {
762  size_t pvlen = (sizeof(il) + sizeof(dl) + nb);
763  if (mprotect(ei, pvlen, PROT_READ) != 0)
764  fprintf(stderr, "==> mprotect(%p[%u],0x%x) error(%d): %s\n",
765  ei, pvlen, PROT_READ,
766  errno, strerror(errno));
767  }
768 
769  pe = (entryInfo) &ei[2];
770  dataStart = (unsigned char *) (pe + il);
771 
772  /* Check (and convert) the 1st tag element. */
773  xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
774  if (xx != -1) {
775  (void) snprintf(buf, sizeof(buf),
776  _("tag[%d]: BAD, tag %u type %u offset %d count %u"),
777  0, (unsigned) entry->info.tag, (unsigned) entry->info.type,
778  (int)entry->info.offset, (unsigned) entry->info.count);
779  goto exit;
780  }
781 
782  /* Is there an immutable header region tag? */
783 /*@-sizeoftype@*/
784  if (entry->info.tag == RPMTAG_HEADERSIGNATURES
785  && entry->info.type == RPM_BIN_TYPE
786  && entry->info.count == (rpmTagCount)REGION_TAG_COUNT)
787  {
788 /*@=sizeoftype@*/
789 
790 /*
791  * XXX http://mysql.mirrors.pair.com/Downloads/MySQL-5.0/MySQL-client-community-5.0.51a-0.rhel4.i386.rpm
792  * built by rpm-4.3.3 (from REL4) has entry->info.offset == 0.
793  */
794 assert(entry->info.offset >= 0); /* XXX insurance */
795  if (entry->info.offset >= (rpmint32_t)dl) {
796  (void) snprintf(buf, sizeof(buf),
797  _("region offset: BAD, tag %u type %u offset %d count %u"),
798  (unsigned) entry->info.tag, (unsigned) entry->info.type,
799  (int)entry->info.offset, (unsigned) entry->info.count);
800  goto exit;
801  }
802 
803  /* Is there an immutable header region tag trailer? */
804  dataEnd = dataStart + entry->info.offset;
805 /*@-sizeoftype@*/
806  (void) memcpy(info, dataEnd, REGION_TAG_COUNT);
807  /* XXX Really old packages have HEADER_IMAGE, not HEADER_SIGNATURES. */
808  if (info->tag == (rpmuint32_t) htonl(RPMTAG_HEADERIMAGE)) {
810  info->tag = stag;
811  memcpy(dataEnd, &stag, sizeof(stag));
812  }
813  dataEnd += REGION_TAG_COUNT;
814 
815  xx = headerVerifyInfo(1, dl, info, &entry->info, 1);
816  if (xx != -1 ||
817  !(entry->info.tag == RPMTAG_HEADERSIGNATURES
818  && entry->info.type == RPM_BIN_TYPE
819  && entry->info.count == (rpmTagCount)REGION_TAG_COUNT))
820  {
821  (void) snprintf(buf, sizeof(buf),
822  _("region trailer: BAD, tag %u type %u offset %d count %u"),
823  (unsigned) entry->info.tag, (unsigned) entry->info.type,
824  (int)entry->info.offset, (unsigned) entry->info.count);
825  goto exit;
826  }
827 /*@=sizeoftype@*/
828  memset(info, 0, sizeof(*info));
829 
830  /* Is the no. of tags in the region less than the total no. of tags? */
831  ril = (rpmuint32_t) (entry->info.offset/sizeof(*pe));
832  if ((entry->info.offset % sizeof(*pe)) || ril > il) {
833  (void) snprintf(buf, sizeof(buf),
834  _("region size: BAD, ril(%u) > il(%u)"), (unsigned) ril, (unsigned) il);
835  goto exit;
836  }
837  }
838 
839  /* Sanity check signature tags */
840  memset(info, 0, sizeof(*info));
841  for (i = 1; i < (unsigned) il; i++) {
842  xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0);
843  if (xx != -1) {
844  (void) snprintf(buf, sizeof(buf),
845  _("sigh tag[%u]: BAD, tag %u type %u offset %d count %u"),
846  (unsigned) i, (unsigned) entry->info.tag, (unsigned) entry->info.type,
847  (int)entry->info.offset, (unsigned) entry->info.count);
848  goto exit;
849  }
850  }
851 
852  /* OK, blob looks sane, load the header. */
853  sigh = headerLoad(ei);
854  if (sigh == NULL) {
855  (void) snprintf(buf, sizeof(buf), _("sigh load: BAD"));
856  goto exit;
857  }
858  if (map) {
859  sigh->flags |= HEADERFLAG_MAPPED;
860  sigh->flags |= HEADERFLAG_RDONLY;
861  } else
862  sigh->flags |= HEADERFLAG_ALLOCATED;
863  sigh->flags |= HEADERFLAG_SIGNATURE;
864 
865  { size_t sigSize = headerSizeof(sigh);
866  size_t pad = (8 - (sigSize % 8)) % 8; /* 8-byte pad */
867 
868  /* Position at beginning of header. */
869  if (pad && (xx = (int) timedRead(fd, (void *)block, pad)) != (int) pad)
870  {
871  (void) snprintf(buf, sizeof(buf),
872  _("sigh pad(%u): BAD, read %d bytes"), (unsigned) pad, xx);
873  goto exit;
874  }
875 
876  /* Print package component sizes. */
877 
878  he->tag = (rpmTag) RPMSIGTAG_SIZE;
879  xx = headerGet(sigh, he, 0);
880  if (xx) {
881  size_t datasize = he->p.ui32p[0];
882  rc = printSize(fd, sigSize, pad, datasize);
883  if (rc != RPMRC_OK)
884  (void) snprintf(buf, sizeof(buf),
885  _("sigh sigSize(%u): BAD, Fstat(2) failed"), (unsigned) sigSize);
886  }
887  he->p.ptr = _free(he->p.ptr);
888  }
889  (void) headerSetStartOff(sigh, (rpmuint32_t)startoff);
890  (void) headerSetEndOff(sigh, fd->stats->ops[FDSTAT_READ].bytes);
891 
892 exit:
893  if (sighp && sigh && rc == RPMRC_OK)
894  *sighp = headerLink(sigh);
895  (void)headerFree(sigh);
896  sigh = NULL;
897 
898  if (msg != NULL) {
899  buf[sizeof(buf)-1] = '\0';
900  *msg = xstrdup(buf);
901  }
902 
903  return rc;
904 }
905 
906 /*===============================================*/
907 
921 rpmRC headerCheck(pgpDig dig, const void * uh, size_t uc, const char ** msg)
922 {
923  char buf[8*BUFSIZ];
924  rpmuint32_t * ei = (rpmuint32_t *) uh;
925  rpmuint32_t il = (rpmuint32_t) ntohl(ei[0]);
926  rpmuint32_t dl = (rpmuint32_t) ntohl(ei[1]);
927 /*@-castexpose@*/
928  entryInfo pe = (entryInfo) &ei[2];
929 /*@=castexpose@*/
930  rpmuint32_t ildl[2];
931  size_t pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl;
932  unsigned char * dataStart = (unsigned char *) (pe + il);
933  indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry));
934  entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info));
935  const void * sig = NULL;
936  unsigned char * b;
938  rpmop op;
939  size_t siglen = 0;
940  int blen;
941  size_t nb;
942  rpmuint32_t ril = 0;
943  unsigned char * regionEnd = NULL;
944  rpmRC rc = RPMRC_FAIL; /* assume failure */
945  int xx;
946  rpmuint32_t i;
947 
948 if (_pkgio_debug)
949 fprintf(stderr, "--> headerCheck(%p, %p[%u], %p)\n", dig, uh, (unsigned) uc, msg);
950 
951  buf[0] = '\0';
952 
953  /* Is the blob the right size? */
954  if (uc > 0 && pvlen != uc) {
955  (void) snprintf(buf, sizeof(buf),
956  _("blob size(%d): BAD, 8 + 16 * il(%u) + dl(%u)"),
957  (int)uc, (unsigned)il, (unsigned)dl);
958  goto exit;
959  }
960 
961  /* Check (and convert) the 1st tag element. */
962  xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
963  if (xx != -1) {
964  (void) snprintf(buf, sizeof(buf),
965  _("tag[%d]: BAD, tag %u type %u offset %d count %u"),
966  0, (unsigned) entry->info.tag, (unsigned) entry->info.type,
967  (int)entry->info.offset, (unsigned) entry->info.count);
968  goto exit;
969  }
970 
971  /* Is there an immutable header region tag? */
972 /*@-sizeoftype@*/
973  if (!(entry->info.tag == RPMTAG_HEADERIMMUTABLE
974  && entry->info.type == RPM_BIN_TYPE
975  && entry->info.count == (rpmTagCount)REGION_TAG_COUNT))
976  {
977  rc = RPMRC_NOTFOUND;
978  goto exit;
979  }
980 /*@=sizeoftype@*/
981 
982  /* Is the offset within the data area? */
983  if (entry->info.offset >= (int) dl) {
984  (void) snprintf(buf, sizeof(buf),
985  _("region offset: BAD, tag %u type %u offset %d count %u"),
986  (unsigned) entry->info.tag, (unsigned) entry->info.type,
987  (int)entry->info.offset, (unsigned) entry->info.count);
988  goto exit;
989  }
990 
991  /* Is there an immutable header region tag trailer? */
992  regionEnd = dataStart + entry->info.offset;
993 /*@-sizeoftype@*/
994  (void) memcpy(info, regionEnd, REGION_TAG_COUNT);
995  regionEnd += REGION_TAG_COUNT;
996 
997  xx = headerVerifyInfo(1, dl, info, &entry->info, 1);
998  if (xx != -1 ||
999  !(entry->info.tag == RPMTAG_HEADERIMMUTABLE
1000  && entry->info.type == RPM_BIN_TYPE
1001  && entry->info.count == (rpmTagCount)REGION_TAG_COUNT))
1002  {
1003  (void) snprintf(buf, sizeof(buf),
1004  _("region trailer: BAD, tag %u type %u offset %d count %u"),
1005  (unsigned) entry->info.tag, (unsigned) entry->info.type,
1006  (int)entry->info.offset, (unsigned) entry->info.count);
1007  goto exit;
1008  }
1009 /*@=sizeoftype@*/
1010  memset(info, 0, sizeof(*info));
1011 
1012  /* Is the no. of tags in the region less than the total no. of tags? */
1013  ril = (rpmuint32_t) (entry->info.offset/sizeof(*pe));
1014  if ((entry->info.offset % sizeof(*pe)) || ril > il) {
1015  (void) snprintf(buf, sizeof(buf),
1016  _("region size: BAD, ril(%u) > il(%u)"), (unsigned) ril, (unsigned)il);
1017  goto exit;
1018  }
1019 
1020  /* Find a header-only digest/signature tag. */
1021  for (i = ril; i < (unsigned) il; i++) {
1022  xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0);
1023  if (xx != -1) {
1024  (void) snprintf(buf, sizeof(buf),
1025  _("tag[%u]: BAD, tag %u type %u offset %d count %u"),
1026  (unsigned) i, (unsigned) entry->info.tag, (unsigned) entry->info.type,
1027  (int)entry->info.offset, (unsigned) entry->info.count);
1028  goto exit;
1029  }
1030 
1031  switch (entry->info.tag) {
1032  case RPMTAG_SHA1HEADER:
1033  if (vsflags & RPMVSF_NOSHA1HEADER)
1034  /*@switchbreak@*/ break;
1035  blen = 0;
1036  for (b = dataStart + entry->info.offset; *b != '\0'; b++) {
1037  if (strchr("0123456789abcdefABCDEF", *b) == NULL)
1038  /*@innerbreak@*/ break;
1039  blen++;
1040  }
1041  if (entry->info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40)
1042  {
1043  (void) snprintf(buf, sizeof(buf), _("hdr SHA1: BAD, not hex"));
1044  goto exit;
1045  }
1046  if (info->tag == 0) {
1047  *info = entry->info; /* structure assignment */
1048  siglen = blen + 1;
1049  }
1050  /*@switchbreak@*/ break;
1051  case RPMTAG_RSAHEADER:
1052  if (vsflags & RPMVSF_NORSAHEADER)
1053  /*@switchbreak@*/ break;
1054  if (entry->info.type != RPM_BIN_TYPE) {
1055  (void) snprintf(buf, sizeof(buf), _("hdr RSA: BAD, not binary"));
1056  goto exit;
1057  }
1058  *info = entry->info; /* structure assignment */
1059  siglen = info->count;
1060  /*@switchbreak@*/ break;
1061  case RPMTAG_DSAHEADER:
1062  if (vsflags & RPMVSF_NODSAHEADER)
1063  /*@switchbreak@*/ break;
1064  if (entry->info.type != RPM_BIN_TYPE) {
1065  (void) snprintf(buf, sizeof(buf), _("hdr DSA: BAD, not binary"));
1066  goto exit;
1067  }
1068  *info = entry->info; /* structure assignment */
1069  siglen = info->count;
1070  /*@switchbreak@*/ break;
1071  default:
1072  /*@switchbreak@*/ break;
1073  }
1074  }
1075  rc = RPMRC_NOTFOUND;
1076 
1077 exit:
1078  /* Return determined RPMRC_OK/RPMRC_FAIL conditions. */
1079  if (rc != RPMRC_NOTFOUND) {
1080  buf[sizeof(buf)-1] = '\0';
1081  if (msg) *msg = xstrdup(buf);
1082 if (_pkgio_debug)
1083 fprintf(stderr, "--> headerCheck #1: rc %d \"%s\"\n", rc, (msg ? *msg: ""));
1084  return rc;
1085  }
1086 
1087  /* If no header-only digest/signature, then do simple sanity check. */
1088  if (info->tag == 0) {
1089  xx = (ril > 0 ? headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0) : -1);
1090  if (xx != -1) {
1091  (void) snprintf(buf, sizeof(buf),
1092  _("tag[%d]: BAD, tag %u type %u offset %d count %u"),
1093  xx+1, (unsigned) entry->info.tag, (unsigned) entry->info.type,
1094  (int)entry->info.offset, (unsigned) entry->info.count);
1095  rc = RPMRC_FAIL;
1096  } else {
1097  (void) snprintf(buf, sizeof(buf), "Header sanity check: OK");
1098  rc = RPMRC_OK;
1099  }
1100  buf[sizeof(buf)-1] = '\0';
1101  if (msg) *msg = xstrdup(buf);
1102 if (_pkgio_debug)
1103 fprintf(stderr, "--> headerCheck #2: rc %d \"%s\"\n", rc, (msg ? *msg: ""));
1104  return rc;
1105  }
1106 
1107  /* Verify header-only digest/signature. */
1108 assert(dig != NULL);
1109  dig->nbytes = 0;
1110 
1111  sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen);
1112  {
1113  const void * osig = pgpGetSig(dig);
1114 /*@-modobserver -observertrans -dependenttrans @*/ /* FIX: pgpSetSig() lazy free. */
1115  osig = _free(osig);
1116 /*@=modobserver =observertrans =dependenttrans @*/
1117  (void) pgpSetSig(dig, info->tag, info->type, sig, info->count);
1118  }
1119 
1120  switch (info->tag) {
1121  case RPMTAG_RSAHEADER:
1122  /* Parse the parameters from the OpenPGP packets that will be needed. */
1123  xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
1124  if (dig->signature.version != (rpmuint8_t)3
1125  && dig->signature.version != (rpmuint8_t)4)
1126  {
1128  _("skipping header with unverifiable V%u signature\n"),
1129  (unsigned) dig->signature.version);
1130  rc = RPMRC_FAIL;
1131  goto exit;
1132  }
1133 
1134  ildl[0] = (rpmuint32_t) htonl(ril);
1135  ildl[1] = (rpmuint32_t) (regionEnd - dataStart);
1136  ildl[1] = (rpmuint32_t) htonl(ildl[1]);
1137 
1138  op = pgpStatsAccumulator(dig, 10); /* RPMTS_OP_DIGEST */
1139  (void) rpmswEnter(op, 0);
1140  dig->hdrctx = rpmDigestInit((pgpHashAlgo)dig->signature.hash_algo, RPMDIGEST_NONE);
1141 
1142  b = NULL; nb = 0;
1143  (void) headerGetMagic(NULL, &b, &nb);
1144  if (b && nb > 0) {
1145  (void) rpmDigestUpdate(dig->hdrctx, b, nb);
1146  dig->nbytes += nb;
1147  }
1148 
1149  b = (unsigned char *) ildl;
1150  nb = sizeof(ildl);
1151  (void) rpmDigestUpdate(dig->hdrctx, b, nb);
1152  dig->nbytes += nb;
1153 
1154  b = (unsigned char *) pe;
1155  nb = (size_t) (htonl(ildl[0]) * sizeof(*pe));
1156  (void) rpmDigestUpdate(dig->hdrctx, b, nb);
1157  dig->nbytes += nb;
1158 
1159  b = (unsigned char *) dataStart;
1160  nb = (size_t) htonl(ildl[1]);
1161  (void) rpmDigestUpdate(dig->hdrctx, b, nb);
1162  dig->nbytes += nb;
1163  (void) rpmswExit(op, dig->nbytes);
1164 
1165  break;
1166  case RPMTAG_DSAHEADER:
1167  /* Parse the parameters from the OpenPGP packets that will be needed. */
1168  xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
1169  if (dig->signature.version != (rpmuint8_t)3
1170  && dig->signature.version != (rpmuint8_t)4)
1171  {
1173  _("skipping header with unverifiable V%u signature\n"),
1174  (unsigned) dig->signature.version);
1175  rc = RPMRC_FAIL;
1176  goto exit;
1177  }
1178  /*@fallthrough@*/
1179  case RPMTAG_SHA1HEADER:
1180  ildl[0] = (rpmuint32_t) htonl(ril);
1181  ildl[1] = (rpmuint32_t) (regionEnd - dataStart);
1182  ildl[1] = (rpmuint32_t) htonl(ildl[1]);
1183 
1184  op = pgpStatsAccumulator(dig, 10); /* RPMTS_OP_DIGEST */
1185  (void) rpmswEnter(op, 0);
1186  dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
1187 
1188  b = NULL; nb = 0;
1189  (void) headerGetMagic(NULL, &b, &nb);
1190  if (b && nb > 0) {
1191  (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
1192  dig->nbytes += nb;
1193  }
1194 
1195  b = (unsigned char *) ildl;
1196  nb = sizeof(ildl);
1197  (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
1198  dig->nbytes += nb;
1199 
1200  b = (unsigned char *) pe;
1201  nb = (size_t) (htonl(ildl[0]) * sizeof(*pe));
1202  (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
1203  dig->nbytes += nb;
1204 
1205  b = (unsigned char *) dataStart;
1206  nb = (size_t) htonl(ildl[1]);
1207  (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
1208  dig->nbytes += nb;
1209  (void) rpmswExit(op, dig->nbytes);
1210 
1211  break;
1212  default:
1213  sig = _free(sig);
1214  break;
1215  }
1216 
1217  buf[0] = '\0';
1218  rc = rpmVerifySignature(dig, buf);
1219 
1220  buf[sizeof(buf)-1] = '\0';
1221  if (msg) *msg = xstrdup(buf);
1222 
1223 if (_pkgio_debug)
1224 fprintf(stderr, "--> headerCheck #3: rc %d \"%s\"\n", rc, (msg ? *msg: ""));
1225  return rc;
1226 }
1227 
1233 static size_t szHeader(/*@null@*/ const void * ptr)
1234  /*@*/
1235 {
1236  rpmuint32_t p[4];
1237 assert(ptr != NULL);
1238  memcpy(p, ptr, sizeof(p));
1239  return (8 + 8 + 16 * ntohl(p[2]) + ntohl(p[3]));
1240 }
1241 
1242 /*@-globuse@*/
1250 static rpmRC ckHeader(/*@unused@*/ FD_t fd, const void * ptr,
1251  /*@unused@*/ /*@null@*/ const char ** msg)
1252  /*@globals fileSystem, internalState @*/
1253  /*@modifies ptr, fileSystem, internalState @*/
1254 {
1255  rpmRC rc = RPMRC_OK;
1256  Header h;
1257 
1258  h = headerLoad((void *)ptr);
1259  if (h == NULL)
1260  rc = RPMRC_FAIL;
1261  (void)headerFree(h);
1262  h = NULL;
1263 
1264  return rc;
1265 }
1266 
1274 static rpmRC rpmReadHeader(FD_t fd, /*@null@*/ Header * hdrp,
1275  /*@null@*/ const char ** msg)
1276  /*@globals fileSystem, internalState @*/
1277  /*@modifies fd, *hdrp, *msg, fileSystem, internalState @*/
1278 {
1279 rpmxar xar = fdGetXAR(fd);
1280  pgpDig dig = pgpDigLink(fdGetDig(fd), "rpmReadHeader");
1281  char buf[BUFSIZ];
1282  rpmuint32_t block[4];
1283  rpmuint32_t il;
1284  rpmuint32_t dl;
1285  rpmuint32_t * ei = NULL;
1286  size_t uc = 0;
1287  unsigned char * b;
1288  size_t startoff;
1289  size_t nb;
1290  Header h = NULL;
1291  const char * origin = NULL;
1292  rpmRC rc = RPMRC_FAIL; /* assume failure */
1293  int xx;
1294  static int map = 1;
1295 
1296 if (_pkgio_debug)
1297 fprintf(stderr, "--> rpmReadHeader(%p, %p, %p)\n", fd, hdrp, msg);
1298 
1299  /* Create (if not already) a signature parameters container. */
1300  if (dig == NULL) {
1301  dig = pgpDigNew(0);
1302  (void) fdSetDig(fd, dig);
1303  }
1304 
1305  buf[0] = '\0';
1306 
1307  if (hdrp)
1308  *hdrp = NULL;
1309 
1310  memset(block, 0, sizeof(block));
1311  if (xar != NULL) {
1312  const char item[] = "Header";
1313  if ((xx = rpmxarNext(xar)) != 0 || (xx = rpmxarPull(xar, item)) != 0) {
1314  (void) snprintf(buf, sizeof(buf),
1315  _("XAR file not found (or no XAR support)"));
1316  rc = RPMRC_NOTFOUND;
1317  goto exit;
1318  }
1319  }
1320 
1321  startoff = fd->stats->ops[FDSTAT_READ].bytes;
1322  if ((xx = (int) timedRead(fd, (char *)block, sizeof(block))) != (int)sizeof(block)) {
1323  /* XXX Handle EOF's as RPMRC_NOTFOUND, not RPMRC_FAIL, returns. */
1324  if (xx == 0)
1325  rc = RPMRC_NOTFOUND;
1326  else
1327  (void) snprintf(buf, sizeof(buf),
1328  _("hdr size(%u): BAD, read returned %d"), (unsigned)sizeof(block), xx);
1329  goto exit;
1330  }
1331 
1332  b = NULL;
1333  nb = 0;
1334  (void) headerGetMagic(NULL, &b, &nb);
1335  if (memcmp(block, b, nb)) {
1336  unsigned char * x = (unsigned char *) block;
1337 /*@+charint@*/
1338  (void) snprintf(buf, sizeof(buf), _("hdr magic: BAD, read %02x%02x%02x%02x%02x%02x%02x%02x"), x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7]);
1339 /*@=charint@*/
1340  goto exit;
1341  }
1342 
1343  il = (rpmuint32_t)ntohl(block[2]);
1344  if (hdrchkTags(il)) {
1345  (void) snprintf(buf, sizeof(buf),
1346  _("hdr tags: BAD, no. of tags(%u) out of range"), (unsigned) il);
1347 
1348  goto exit;
1349  }
1350  dl = (rpmuint32_t)ntohl(block[3]);
1351  if (hdrchkData(dl)) {
1352  (void) snprintf(buf, sizeof(buf),
1353  _("hdr data: BAD, no. of bytes(%u) out of range\n"), (unsigned) dl);
1354  goto exit;
1355  }
1356 
1357 /*@-sizeoftype@*/
1358  nb = (il * sizeof(struct entryInfo_s)) + dl;
1359 /*@=sizeoftype@*/
1360  uc = sizeof(il) + sizeof(dl) + nb;
1361  if (map) {
1362  static const int prot = PROT_READ | PROT_WRITE;
1363  static const int flags = MAP_PRIVATE| MAP_ANONYMOUS;
1364  static const int fdno = -1;
1365  static const off_t off = 0;
1366 
1367  ei = mmap(NULL, uc, prot, flags, fdno, off);
1368  if (ei == NULL || ei == (void *)-1)
1369  fprintf(stderr,
1370  "==> mmap(%p[%u], 0x%x, 0x%x, %d, 0x%x) error(%d): %s\n",
1371  NULL, uc, prot, flags, fdno, (unsigned)off,
1372  errno, strerror(errno));
1373  } else {
1374  ei = (rpmuint32_t *) xmalloc(uc);
1375  }
1376 
1377  if ((xx = (int) timedRead(fd, (char *)&ei[2], nb)) != (int) nb) {
1378  (void) snprintf(buf, sizeof(buf),
1379  _("hdr blob(%u): BAD, read returned %d"), (unsigned)nb, xx);
1380  goto exit;
1381  }
1382  ei[0] = block[2];
1383  ei[1] = block[3];
1384 
1385  if (map) {
1386  if (mprotect(ei, uc, PROT_READ) != 0)
1387  fprintf(stderr, "==> mprotect(%p[%u],0x%x) error(%d): %s\n",
1388  ei, uc, PROT_READ,
1389  errno, strerror(errno));
1390  }
1391 
1392  /* Sanity check header tags */
1393  rc = headerCheck(dig, ei, uc, msg);
1394  if (rc != RPMRC_OK)
1395  goto exit;
1396 
1397  /* OK, blob looks sane, load the header. */
1398  h = headerLoad(ei);
1399  if (h == NULL) {
1400  (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n"));
1401  goto exit;
1402  }
1403  if (map) {
1404  h->flags |= HEADERFLAG_MAPPED;
1405  h->flags |= HEADERFLAG_RDONLY;
1406  } else
1408  ei = NULL; /* XXX will be freed with header */
1409 
1410  /* Save the opened path as the header origin. */
1411  /* XXX TODO: push the Realpath() underneath fdGetOPath(). */
1412  origin = fdGetOPath(fd);
1413  if (origin != NULL) {
1414  const char * lpath = NULL;
1415  int ut = urlPath(origin, &lpath);
1416  ut = ut; /* XXX keep gcc quiet. */
1417  if (lpath && *lpath != '/') {
1418  char * rpath = Realpath(origin, NULL);
1419  (void) headerSetOrigin(h, rpath);
1420  rpath = _free(rpath);
1421  } else
1422  (void) headerSetOrigin(h, origin);
1423  }
1424 /*@-mods@*/
1425  { struct stat * st = headerGetStatbuf(h);
1426  int saveno = errno;
1427  (void) Fstat(fd, st);
1428  errno = saveno;
1429  }
1430 /*@=mods@*/
1431  (void) headerSetStartOff(h, (rpmuint32_t)startoff);
1432  (void) headerSetEndOff(h, fd->stats->ops[FDSTAT_READ].bytes);
1433 
1434 exit:
1435  if (hdrp && h && rc == RPMRC_OK)
1436  *hdrp = headerLink(h);
1437  if (ei != NULL && uc > 0) {
1438  if (map) {
1439  if (munmap(ei, uc) != 0)
1440  fprintf(stderr, "==> munmap(%p[%u]) error(%d): %s\n",
1441  ei, uc, errno, strerror(errno));
1442  ei = NULL;
1443  } else
1444  ei = _free(ei);
1445  }
1446  dig = pgpDigFree(dig, "rpmReadHeader");
1447  (void)headerFree(h);
1448  h = NULL;
1449 
1450  if (msg != NULL && *msg == NULL && buf[0] != '\0') {
1451  buf[sizeof(buf)-1] = '\0';
1452  *msg = xstrdup(buf);
1453  }
1454 
1455 if (_pkgio_debug)
1456 fprintf(stderr, "--> rpmReadHeader: rc %d \"%s\"\n", rc, (msg ? *msg: ""));
1457  return rc;
1458 }
1459 
1467 static rpmRC rdHeader(FD_t fd, /*@out@*/ /*@null@*/ void * ptr,
1468  /*@null@*/ const char ** msg)
1469  /*@globals fileSystem, internalState @*/
1470  /*@modifies fd, *ptr, *msg, fileSystem, internalState @*/
1471 {
1472  Header * hdrp = ptr;
1473 /*@-compdef@*/
1474  return rpmReadHeader(fd, hdrp, msg);
1475 /*@=compdef@*/
1476 }
1477 
1485 static rpmRC wrHeader(FD_t fd, void * ptr,
1486  /*@unused@*/ /*@null@*/ const char ** msg)
1487  /*@globals fileSystem, internalState @*/
1488  /*@modifies fd, ptr, *msg, fileSystem, internalState @*/
1489 {
1490  Header h = ptr;
1491  return rpmWriteHeader(fd, h, msg);
1492 }
1493 /*@=globuse@*/
1494 
1495 /*===============================================*/
1496 
1497 size_t rpmpkgSizeof(const char * fn, const void * ptr)
1498 {
1499  size_t len = 0;
1500 
1501  if (!strcmp(fn, "Lead"))
1502  len = 96; /* RPMLEAD_SIZE */
1503  else
1504  if (!strcmp(fn, "Signature")) {
1505  len = szHeader(ptr);
1506  len += ((8 - (len % 8)) % 8); /* padding */
1507  } else
1508  if (!strcmp(fn, "Header"))
1509  len = szHeader(ptr);
1510  return len;
1511 }
1512 
1513 rpmRC rpmpkgCheck(const char * fn, FD_t fd, const void * ptr, const char ** msg)
1514 {
1515  rpmRC rc = RPMRC_FAIL;
1516 
1517  if (msg)
1518  *msg = NULL;
1519 
1520  if (!strcmp(fn, "Header"))
1521  rc = ckHeader(fd, ptr, msg);
1522  return rc;
1523 }
1524 
1525 rpmRC rpmpkgRead(const char * fn, FD_t fd, void * ptr, const char ** msg)
1526 {
1527  rpmRC rc = RPMRC_FAIL;
1528 
1529  if (msg)
1530  *msg = NULL;
1531 
1532  if (!strcmp(fn, "Lead"))
1533  rc = rdLead(fd, ptr, msg);
1534  else
1535  if (!strcmp(fn, "Signature"))
1536  rc = rdSignature(fd, ptr, msg);
1537  else
1538  if (!strcmp(fn, "Header"))
1539  rc = rdHeader(fd, ptr, msg);
1540  return rc;
1541 }
1542 
1543 rpmRC rpmpkgWrite(const char * fn, FD_t fd, void * ptr, const char ** msg)
1544 {
1545  rpmRC rc = RPMRC_FAIL;
1546 
1547  if (msg)
1548  *msg = NULL;
1549 
1550  if (!strcmp(fn, "Lead"))
1551  rc = wrLead(fd, ptr, msg);
1552  else
1553  if (!strcmp(fn, "Signature"))
1554  rc = wrSignature(fd, ptr, msg);
1555  else
1556  if (!strcmp(fn, "Header"))
1557  rc = wrHeader(fd, ptr, msg);
1558  return rc;
1559 }