rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

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
128 rpmop rpmtsOp(rpmts ts, rpmtsOpX opx)
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
139 pgpDigParams rpmtsPubkey(const rpmts ts)
140 {
141 /*@-onlytrans@*/
142 return pgpGetPubkey(rpmtsDig(ts));
143 /*@=onlytrans@*/
144 }
145
146 rpmdb rpmtsGetRdb(rpmts ts)
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);
222 rpmlog(RPMLOG_ERR,
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
346 pgpDig rpmtsDig(rpmts ts)
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
361 void rpmtsCleanDig(rpmts ts)
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;
637 rpmlog(RPMLOG_DEBUG,
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);
642 rpmlog(RPMLOG_DEBUG,
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)) {
809 rpmuint32_t stag = (rpmuint32_t) htonl(RPMTAG_HEADERSIGNATURES);
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;
937 rpmVSFlags vsflags = pgpDigVSFlags;
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 {
1127 rpmlog(RPMLOG_ERR,
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 {
1172 rpmlog(RPMLOG_ERR,
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
1407 h->flags |= HEADERFLAG_ALLOCATED;
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 }