rpm 5.2.1
|
00001 00006 #include "system.h" 00007 00008 #if defined(HAVE_MACHINE_TYPES_H) 00009 # include <machine/types.h> 00010 #endif 00011 00012 #include <netinet/in.h> 00013 00014 #define _RPMIOB_INTERNAL 00015 #include <rpmiotypes.h> 00016 #include <rpmio_internal.h> 00017 #include <rpmcb.h> 00018 #include <rpmbc.h> /* XXX beecrypt base64 */ 00019 #include <rpmmacro.h> 00020 #include <rpmku.h> 00021 00022 #define _RPMTAG_INTERNAL 00023 #include "header_internal.h" 00024 00025 #include <rpmdb.h> 00026 #include <pkgio.h> 00027 00028 #define _RPMTS_INTERNAL 00029 #include "rpmts.h" 00030 00031 #include <rpmxar.h> 00032 00033 #include "signature.h" 00034 #include "debug.h" 00035 00036 /*@access rpmts @*/ 00037 /*@access rpmxar @*/ 00038 /*@access pgpDig @*/ 00039 /*@access pgpDigParams @*/ 00040 /*@access Header @*/ /* XXX compared with NULL */ 00041 /*@access entryInfo @*/ 00042 /*@access indexEntry @*/ 00043 /*@access FD_t @*/ /* XXX stealing digests */ 00044 /*@access FDSTAT_t @*/ /* XXX stealing digests */ 00045 00046 /*@unchecked@*/ 00047 int _pkgio_debug = 0; 00048 00049 /*@unchecked@*/ 00050 static int _print_pkts = 0; 00051 00054 /*@-exportheader@*/ 00055 /*@unused@*/ ssize_t timedRead(FD_t fd, /*@out@*/ void * bufptr, size_t length) 00056 /*@globals fileSystem @*/ 00057 /*@modifies fd, *bufptr, fileSystem @*/; 00058 #define timedRead (ufdio->read) 00059 /*@=exportheader@*/ 00060 00061 /*===============================================*/ 00069 static 00070 rpmRC rpmWriteHeader(FD_t fd, /*@null@*/ Header h, /*@null@*/ const char ** msg) 00071 /*@globals fileSystem, internalState @*/ 00072 /*@modifies fd, h, *msg, fileSystem, internalState @*/ 00073 { 00074 const void * uh = NULL; 00075 size_t nb; 00076 size_t length; 00077 rpmRC rc = RPMRC_FAIL; /* assume failure */ 00078 00079 if (_pkgio_debug) 00080 fprintf(stderr, "--> rpmWriteHeader(%p, %p, %p)\n", fd, h, msg); 00081 00082 if (h == NULL) { 00083 if (msg) 00084 *msg = xstrdup(_("write of NULL header")); 00085 goto exit; 00086 } 00087 00088 uh = headerUnload(h, &length); 00089 if (uh == NULL) { 00090 if (msg) 00091 *msg = xstrdup(_("headerUnload failed")); 00092 goto exit; 00093 } 00094 00095 { unsigned char * hmagic = NULL; 00096 size_t nmagic = 0; 00097 00098 (void) headerGetMagic(NULL, &hmagic, &nmagic); 00099 nb = Fwrite(hmagic, sizeof(hmagic[0]), nmagic, fd); 00100 if (nb != nmagic || Ferror(fd)) { 00101 if (msg) 00102 *msg = (nb > 0 00103 ? xstrdup(_("short write of header magic")) 00104 : xstrdup(Fstrerror(fd)) ); 00105 goto exit; 00106 } 00107 } 00108 00109 /*@-sizeoftype@*/ 00110 nb = Fwrite(uh, sizeof(char), length, fd); 00111 /*@=sizeoftype@*/ 00112 if (nb != length || Ferror(fd)) { 00113 if (msg) 00114 *msg = (nb > 0 00115 ? xstrdup(_("short write of header")) 00116 : xstrdup(Fstrerror(fd)) ); 00117 goto exit; 00118 } 00119 rc = RPMRC_OK; 00120 00121 exit: 00122 uh = _free(uh); 00123 return rc; 00124 } 00125 00126 /*===============================================*/ 00127 00128 rpmop rpmtsOp(rpmts ts, rpmtsOpX opx) 00129 { 00130 rpmop op = NULL; 00131 00132 if (ts != NULL && (int)opx >= 0 && (int)opx < RPMTS_OP_MAX) 00133 op = ts->ops + opx; 00134 /*@-usereleased -compdef @*/ 00135 return op; 00136 /*@=usereleased =compdef @*/ 00137 } 00138 00139 pgpDigParams rpmtsPubkey(const rpmts ts) 00140 { 00141 /*@-onlytrans@*/ 00142 return pgpGetPubkey(rpmtsDig(ts)); 00143 /*@=onlytrans@*/ 00144 } 00145 00146 rpmdb rpmtsGetRdb(rpmts ts) 00147 { 00148 rpmdb rdb = NULL; 00149 if (ts != NULL) { 00150 rdb = ts->rdb; 00151 } 00152 /*@-compdef -refcounttrans -usereleased @*/ 00153 return rdb; 00154 /*@=compdef =refcounttrans =usereleased @*/ 00155 } 00156 00157 rpmRC rpmtsFindPubkey(rpmts ts, void * _dig) 00158 { 00159 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00160 pgpDig dig = (_dig ? _dig : rpmtsDig(ts)); 00161 pgpDigParams sigp = pgpGetSignature(dig); 00162 pgpDigParams pubp = pgpGetPubkey(dig); 00163 rpmRC res = RPMRC_NOKEY; 00164 const char * pubkeysource = NULL; 00165 rpmiob iob = NULL; 00166 int krcache = 1; /* XXX assume pubkeys are cached in keyutils keyring. */ 00167 int xx; 00168 00169 assert(dig != NULL); 00170 assert(sigp != NULL); 00171 assert(pubp != NULL); 00172 /*@-sefparams@*/ 00173 assert(rpmtsDig(ts) == dig); 00174 /*@=sefparams@*/ 00175 00176 #if 0 00177 fprintf(stderr, "==> find sig id %08x %08x ts pubkey id %08x %08x\n", 00178 pgpGrab(sigp->signid, 4), pgpGrab(sigp->signid+4, 4), 00179 pgpGrab(ts->pksignid, 4), pgpGrab(ts->pksignid+4, 4)); 00180 #endif 00181 00182 /* Lazy free of previous pubkey if pubkey does not match this signature. */ 00183 if (memcmp(sigp->signid, ts->pksignid, sizeof(ts->pksignid))) { 00184 #if 0 00185 fprintf(stderr, "*** free pkt %p[%d] id %08x %08x\n", ts->pkpkt, ts->pkpktlen, pgpGrab(ts->pksignid, 4), pgpGrab(ts->pksignid+4, 4)); 00186 #endif 00187 ts->pkpkt = _free(ts->pkpkt); 00188 ts->pkpktlen = 0; 00189 memset(ts->pksignid, 0, sizeof(ts->pksignid)); 00190 } 00191 00192 /* Try keyutils keyring lookup. */ 00193 if (ts->pkpkt == NULL) { 00194 iob = NULL; 00195 switch (rpmkuFindPubkey(sigp, &iob)) { 00196 case RPMRC_NOTFOUND: 00197 case RPMRC_FAIL: 00198 case RPMRC_NOTTRUSTED: 00199 case RPMRC_NOKEY: 00200 break; 00201 case RPMRC_OK: 00202 pubkeysource = xstrdup("keyutils"); 00203 krcache = 0; /* XXX don't bother caching. */ 00204 ts->pkpkt = memcpy(xmalloc(iob->blen), iob->b, iob->blen); 00205 ts->pkpktlen = iob->blen; 00206 break; 00207 } 00208 } 00209 00210 /* Try rpmdb keyring lookup. */ 00211 if (ts->pkpkt == NULL) { 00212 unsigned hx = 0xffffffff; 00213 unsigned ix = 0xffffffff; 00214 rpmmi mi; 00215 Header h; 00216 00217 /* XXX Do a lazy open if not done already. */ 00218 if (ts->rdb == NULL) { 00219 xx = rpmdbOpen(ts->rootDir, &ts->rdb, ts->dbmode, 0644); 00220 if (xx) { 00221 const char * dn = rpmGetPath(ts->rootDir, "%{_dbpath}", NULL); 00222 rpmlog(RPMLOG_ERR, 00223 _("cannot open Packages database in %s\n"), dn); 00224 dn = _free(dn); 00225 } 00226 } 00227 00228 /* Retrieve the pubkey that matches the signature. */ 00229 he->tag = RPMTAG_PUBKEYS; 00230 /*@-nullstate@*/ 00231 mi = rpmmiInit(rpmtsGetRdb(ts), RPMTAG_PUBKEYS, sigp->signid, sizeof(sigp->signid)); 00232 /*@=nullstate@*/ 00233 while ((h = rpmmiNext(mi)) != NULL) { 00234 if (!headerGet(h, he, 0)) 00235 continue; 00236 hx = rpmmiInstance(mi); 00237 ix = rpmmiFilenum(mi); 00238 /*@-moduncon -nullstate @*/ 00239 if (ix >= (unsigned) he->c 00240 || b64decode(he->p.argv[ix], (void **) &ts->pkpkt, &ts->pkpktlen)) 00241 ix = 0xffffffff; 00242 /*@=moduncon =nullstate @*/ 00243 he->p.ptr = _free(he->p.ptr); 00244 break; 00245 } 00246 mi = rpmmiFree(mi); 00247 00248 if (ix < 0xffffffff) { 00249 char hnum[32]; 00250 sprintf(hnum, "h#%u", hx); 00251 pubkeysource = xstrdup(hnum); 00252 } else { 00253 ts->pkpkt = _free(ts->pkpkt); 00254 ts->pkpktlen = 0; 00255 } 00256 } 00257 00258 /* Try keyserver lookup. */ 00259 if (ts->pkpkt == NULL) { 00260 const char * fn = rpmExpand("%{_hkp_keyserver_query}", 00261 pgpHexStr(sigp->signid, sizeof(sigp->signid)), NULL); 00262 00263 xx = 0; 00264 if (fn && *fn != '%') { 00265 xx = (pgpReadPkts(fn, &ts->pkpkt, &ts->pkpktlen) != PGPARMOR_PUBKEY); 00266 } 00267 fn = _free(fn); 00268 if (xx) { 00269 ts->pkpkt = _free(ts->pkpkt); 00270 ts->pkpktlen = 0; 00271 } else { 00272 /* Save new pubkey in local ts keyring for delayed import. */ 00273 pubkeysource = xstrdup("keyserver"); 00274 } 00275 } 00276 00277 #ifdef NOTNOW 00278 /* Try filename from macro lookup. */ 00279 if (ts->pkpkt == NULL) { 00280 const char * fn = rpmExpand("%{_gpg_pubkey}", NULL); 00281 00282 xx = 0; 00283 if (fn && *fn != '%') 00284 xx = (pgpReadPkts(fn,&ts->pkpkt,&ts->pkpktlen) != PGPARMOR_PUBKEY); 00285 fn = _free(fn); 00286 if (xx) { 00287 ts->pkpkt = _free(ts->pkpkt); 00288 ts->pkpktlen = 0; 00289 } else { 00290 pubkeysource = xstrdup("macro"); 00291 } 00292 } 00293 #endif 00294 00295 /* Was a matching pubkey found? */ 00296 if (ts->pkpkt == NULL || ts->pkpktlen == 0) 00297 goto exit; 00298 00299 /* Retrieve parameters from pubkey packet(s). */ 00300 xx = pgpPrtPkts((rpmuint8_t *)ts->pkpkt, ts->pkpktlen, dig, 0); 00301 00302 /* Do the parameters match the signature? */ 00303 if (sigp->pubkey_algo == pubp->pubkey_algo 00304 #ifdef NOTYET 00305 && sigp->hash_algo == pubp->hash_algo 00306 #endif 00307 && !memcmp(sigp->signid, pubp->signid, sizeof(sigp->signid)) ) 00308 { 00309 00310 /* XXX Verify any pubkey signatures. */ 00311 00312 /* Save the pubkey in the keyutils keyring. */ 00313 if (krcache) { 00314 if (iob == NULL) { 00315 iob = rpmiobNew(ts->pkpktlen); 00316 iob->b = memcpy(iob->b, ts->pkpkt, iob->blen); 00317 } 00318 (void) rpmkuStorePubkey(sigp, iob); 00319 } 00320 00321 /* Pubkey packet looks good, save the signer id. */ 00322 memcpy(ts->pksignid, pubp->signid, sizeof(ts->pksignid)); 00323 00324 if (pubkeysource) 00325 rpmlog(RPMLOG_DEBUG, "========== %s pubkey id %08x %08x (%s)\n", 00326 (sigp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_DSA ? "DSA" : 00327 (sigp->pubkey_algo == (rpmuint8_t)PGPPUBKEYALGO_RSA ? "RSA" : 00328 "???")), 00329 pgpGrab(sigp->signid, 4), pgpGrab(sigp->signid+4, 4), 00330 pubkeysource); 00331 00332 res = RPMRC_OK; 00333 } 00334 00335 exit: 00336 pubkeysource = _free(pubkeysource); 00337 if (res != RPMRC_OK) { 00338 ts->pkpkt = _free(ts->pkpkt); 00339 ts->pkpktlen = 0; 00340 } 00341 /*@-nullstate@*/ 00342 return res; 00343 /*@=nullstate@*/ 00344 } 00345 00346 pgpDig rpmtsDig(rpmts ts) 00347 { 00348 /*@-mods@*/ /* FIX: hide lazy malloc for now */ 00349 if (ts->dig == NULL) { 00350 ts->dig = pgpDigNew(0); 00351 /*@-refcounttrans@*/ 00352 (void) pgpSetFindPubkey(ts->dig, (int (*)(void *, void *))rpmtsFindPubkey, ts); 00353 /*@=refcounttrans@*/ 00354 } 00355 /*@=mods@*/ 00356 /*@-compdef -retexpose -usereleased@*/ 00357 return ts->dig; 00358 /*@=compdef =retexpose =usereleased@*/ 00359 } 00360 00361 void rpmtsCleanDig(rpmts ts) 00362 { 00363 if (ts && ts->dig) { 00364 int opx; 00365 opx = RPMTS_OP_DIGEST; 00366 (void) rpmswAdd(rpmtsOp(ts, opx), pgpStatsAccumulator(ts->dig, opx)); 00367 opx = RPMTS_OP_SIGNATURE; 00368 (void) rpmswAdd(rpmtsOp(ts, opx), pgpStatsAccumulator(ts->dig, opx)); 00369 /*@-onlytrans@*/ 00370 (void) pgpDigFree(ts->dig, "rpmtsCleanDig"); 00371 ts->dig = NULL; /* XXX make sure the ptr is __REALLY__ gone */ 00372 /*@=onlytrans@*/ 00373 } 00374 } 00375 00376 /*===============================================*/ 00377 00384 struct rpmlead { 00385 unsigned char magic[4]; 00386 unsigned char major; 00387 unsigned char minor; 00388 unsigned short type; 00389 unsigned short archnum; 00390 char name[66]; 00391 unsigned short osnum; 00392 unsigned short signature_type; 00393 /*@unused@*/ 00394 char reserved[16]; 00395 } ; 00396 00397 /*@-type@*/ 00398 /*@unchecked@*/ /*@observer@*/ 00399 static unsigned char lead_magic[] = { 00400 0xed, 0xab, 0xee, 0xdb, 0x00, 0x00, 0x00, 0x00 00401 }; 00402 /*@=type@*/ 00403 00404 /* The lead needs to be 8 byte aligned */ 00405 00413 static rpmRC wrLead(FD_t fd, const void * ptr, /*@null@*/ const char ** msg) 00414 /*@globals fileSystem @*/ 00415 /*@modifies fd, fileSystem @*/ 00416 { 00417 struct rpmlead l; 00418 00419 if (_pkgio_debug) 00420 fprintf(stderr, "--> wrLead(%p, %p, %p)\n", fd, ptr, msg); 00421 00422 memcpy(&l, ptr, sizeof(l)); 00423 00424 /* Set some sane defaults */ 00425 if ((int)l.major == 0) 00426 l.major = (unsigned char) 3; 00427 if (l.signature_type == 0) 00428 l.signature_type = 5; /* RPMSIGTYPE_HEADERSIG */ 00429 if (msg && *msg) 00430 (void) strncpy(l.name, *msg, sizeof(l.name)); 00431 00432 memcpy(&l.magic, lead_magic, sizeof(l.magic)); 00433 l.type = (unsigned short) htons(l.type); 00434 l.archnum = (unsigned short) htons(l.archnum); 00435 l.osnum = (unsigned short) htons(l.osnum); 00436 l.signature_type = (unsigned short) htons(l.signature_type); 00437 00438 if (Fwrite(&l, 1, sizeof(l), fd) != sizeof(l)) 00439 return RPMRC_FAIL; 00440 00441 return RPMRC_OK; 00442 } 00443 00451 static rpmRC rdLead(FD_t fd, /*@out@*/ /*@null@*/ void * ptr, 00452 /*@null@*/ const char ** msg) 00453 /*@globals fileSystem @*/ 00454 /*@modifies fd, *ptr, *msg, fileSystem @*/ 00455 { 00456 rpmxar xar = fdGetXAR(fd); 00457 struct rpmlead ** leadp = ptr; 00458 struct rpmlead * l = xcalloc(1, sizeof(*l)); 00459 char buf[BUFSIZ]; 00460 rpmRC rc = RPMRC_FAIL; /* assume failure */ 00461 int xx; 00462 00463 if (_pkgio_debug) 00464 fprintf(stderr, "--> rdLead(%p, %p, %p)\n", fd, ptr, msg); 00465 00466 buf[0] = '\0'; 00467 if (leadp != NULL) *leadp = NULL; 00468 00469 /* Read the first 96 bytes of the file. */ 00470 if ((xx = (int) timedRead(fd, (char *)l, sizeof(*l))) != (int) sizeof(*l)) { 00471 if (Ferror(fd)) { 00472 (void) snprintf(buf, sizeof(buf), 00473 _("lead size(%u): BAD, read(%d), %s(%d)"), 00474 (unsigned)sizeof(*l), xx, Fstrerror(fd), errno); 00475 rc = RPMRC_FAIL; 00476 } else { 00477 (void) snprintf(buf, sizeof(buf), 00478 _("lead size(%u): BAD, read(%d), %s(%d)"), 00479 (unsigned)sizeof(*l), xx, strerror(errno), errno); 00480 rc = RPMRC_NOTFOUND; 00481 } 00482 goto exit; 00483 } 00484 00485 /* Attach rpmxar handler to fd if this is a xar archive. */ 00486 if (xar == NULL) { 00487 unsigned char * bh = (unsigned char *)l; 00488 if (bh[0] == 'x' && bh[1] == 'a' && bh[2] == 'r' && bh[3] == '!') { 00489 const char * fn = fdGetOPath(fd); 00490 assert(fn != NULL); 00491 xar = rpmxarNew(fn, "r"); 00492 fdSetXAR(fd, xar); 00493 (void) rpmxarFree(xar, "rdLead"); 00494 } 00495 } 00496 00497 /* With XAR, read lead from a xar archive file called "Lead". */ 00498 xar = fdGetXAR(fd); 00499 if (xar != NULL) { 00500 unsigned char *b = NULL; 00501 size_t nb = 0; 00502 const char item[] = "Lead"; 00503 if ((xx = rpmxarNext(xar)) != 0 || (xx = rpmxarPull(xar, item)) != 0) { 00504 (void) snprintf(buf, sizeof(buf), 00505 _("XAR file not found (or no XAR support)")); 00506 rc = RPMRC_NOTFOUND; 00507 goto exit; 00508 } 00509 (void) rpmxarSwapBuf(xar, NULL, 0, &b, &nb); 00510 if (nb != sizeof(*l)) { 00511 (void) snprintf(buf, sizeof(buf), 00512 _("lead size(%u): BAD, xar read(%u)"), 00513 (unsigned)sizeof(*l), (unsigned)nb); 00514 b = _free(b); 00515 rc = RPMRC_FAIL; 00516 goto exit; 00517 } 00518 memcpy(l, b, nb); 00519 b = _free(b); 00520 } 00521 00522 l->type = (unsigned short) ntohs(l->type); 00523 l->archnum = (unsigned short) ntohs(l->archnum); 00524 l->osnum = (unsigned short) ntohs(l->osnum); 00525 l->signature_type = (unsigned short) ntohs(l->signature_type); 00526 00527 if (memcmp(l->magic, lead_magic, sizeof(l->magic))) { 00528 /*@+charint@*/ 00529 (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]); 00530 /*@=charint@*/ 00531 rc = RPMRC_NOTFOUND; 00532 goto exit; 00533 } 00534 00535 switch (l->major) { 00536 default: 00537 (void) snprintf(buf, sizeof(buf), 00538 _("lead version(%u): UNSUPPORTED"), (unsigned) l->major); 00539 rc = RPMRC_NOTFOUND; 00540 goto exit; 00541 /*@notreached@*/ break; 00542 case 3: 00543 case 4: 00544 break; 00545 } 00546 00547 if (l->signature_type != 5) { /* RPMSIGTYPE_HEADERSIG */ 00548 (void) snprintf(buf, sizeof(buf), 00549 _("sigh type(%u): UNSUPPORTED"), (unsigned) l->signature_type); 00550 rc = RPMRC_NOTFOUND; 00551 goto exit; 00552 } 00553 00554 rc = RPMRC_OK; 00555 00556 exit: 00557 if (rc == RPMRC_OK && leadp != NULL) 00558 *leadp = l; 00559 else 00560 /*@-dependenttrans@*/ l = _free(l); /*@=dependenttrans@*/ 00561 00562 if (msg != NULL && buf[0] != '\0') { 00563 buf[sizeof(buf)-1] = '\0'; 00564 *msg = xstrdup(buf); 00565 } 00566 return rc; 00567 } 00568 00569 /*===============================================*/ 00570 00578 static rpmRC wrSignature(FD_t fd, void * ptr, 00579 /*@unused@*/ /*@null@*/ const char ** msg) 00580 /*@globals fileSystem, internalState @*/ 00581 /*@modifies fd, ptr, *msg, fileSystem, internalState @*/ 00582 { 00583 Header sigh = ptr; 00584 static unsigned char zero[8] 00585 = { '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }; 00586 size_t sigSize; 00587 size_t pad; 00588 rpmRC rc = RPMRC_OK; 00589 00590 if (_pkgio_debug) 00591 fprintf(stderr, "--> wrSignature(%p, %p, %p)\n", fd, ptr, msg); 00592 00593 rc = rpmWriteHeader(fd, sigh, msg); 00594 if (rc != RPMRC_OK) 00595 return rc; 00596 00597 sigSize = headerSizeof(sigh); 00598 pad = (8 - (sigSize % 8)) % 8; 00599 if (pad) { 00600 if (Fwrite(zero, sizeof(zero[0]), pad, fd) != pad) 00601 rc = RPMRC_FAIL; 00602 } 00603 rpmlog(RPMLOG_DEBUG, D_("Signature: size(%u)+pad(%u)\n"), (unsigned)sigSize, (unsigned)pad); 00604 return rc; 00605 } 00606 00615 static inline rpmRC printSize(FD_t fd, size_t siglen, size_t pad, size_t datalen) 00616 /*@globals fileSystem, internalState @*/ 00617 /*@modifies fileSystem, internalState @*/ 00618 { 00619 struct stat sb, * st = &sb; 00620 size_t expected; 00621 size_t nl = rpmpkgSizeof("Lead", NULL); 00622 00623 #ifndef DYING /* XXX Fstat(2) contentLength not gud enuf yet. */ 00624 int fdno = Fileno(fd); 00625 /* HACK: workaround for davRead wiring. */ 00626 if (fdno == 123456789) { 00627 /*@-type@*/ 00628 st->st_size = 0; 00629 st->st_size -= nl + siglen + pad + datalen; 00630 /*@=type@*/ 00631 } else 00632 #endif 00633 if (Fstat(fd, st) < 0) 00634 return RPMRC_FAIL; 00635 00636 expected = nl + siglen + pad + datalen; 00637 rpmlog(RPMLOG_DEBUG, 00638 D_("Expected size: %12lu = lead(%u)+sigs(%u)+pad(%u)+data(%lu)\n"), 00639 (unsigned long)expected, 00640 (unsigned)nl, (unsigned) siglen, (unsigned) pad, 00641 (unsigned long)datalen); 00642 rpmlog(RPMLOG_DEBUG, 00643 D_(" Actual size: %12lu\n"), (unsigned long)st->st_size); 00644 00645 return RPMRC_OK; 00646 } 00647 00655 static rpmRC rdSignature(FD_t fd, /*@out@*/ /*@null@*/ void * ptr, 00656 /*@null@*/ const char ** msg) 00657 /*@globals fileSystem, internalState @*/ 00658 /*@modifies *ptr, *msg, fileSystem, internalState @*/ 00659 { 00660 rpmxar xar = fdGetXAR(fd); 00661 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he)); 00662 Header * sighp = ptr; 00663 char buf[BUFSIZ]; 00664 rpmuint32_t block[4]; 00665 rpmuint32_t il; 00666 rpmuint32_t dl; 00667 rpmuint32_t * ei = NULL; 00668 entryInfo pe; 00669 size_t startoff; 00670 size_t nb; 00671 rpmuint32_t ril = 0; 00672 indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry)); 00673 entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info)); 00674 unsigned char * dataStart; 00675 unsigned char * dataEnd = NULL; 00676 Header sigh = NULL; 00677 rpmRC rc = RPMRC_FAIL; /* assume failure */ 00678 int xx; 00679 rpmuint32_t i; 00680 static int map = 1; 00681 00682 if (_pkgio_debug) 00683 fprintf(stderr, "--> rdSignature(%p, %p, %p)\n", fd, ptr, msg); 00684 00685 buf[0] = '\0'; 00686 if (sighp) 00687 *sighp = NULL; 00688 00689 memset(block, 0, sizeof(block)); 00690 if (xar != NULL) { 00691 const char item[] = "Signature"; 00692 if ((xx = rpmxarNext(xar)) != 0 || (xx = rpmxarPull(xar, item)) != 0) { 00693 (void) snprintf(buf, sizeof(buf), 00694 _("XAR file not found (or no XAR support)")); 00695 rc = RPMRC_NOTFOUND; 00696 goto exit; 00697 } 00698 } 00699 startoff = fd->stats->ops[FDSTAT_READ].bytes; 00700 if ((xx = (int) timedRead(fd, (void *)block, sizeof(block))) != (int) sizeof(block)) { 00701 (void) snprintf(buf, sizeof(buf), 00702 _("sigh size(%d): BAD, read returned %d"), (int)sizeof(block), xx); 00703 goto exit; 00704 } 00705 00706 { unsigned char * hmagic = NULL; 00707 size_t nmagic = 0; 00708 00709 (void) headerGetMagic(NULL, &hmagic, &nmagic); 00710 00711 if (memcmp(block, hmagic, nmagic)) { 00712 unsigned char * x = (unsigned char *)block; 00713 /*@+charint@*/ 00714 (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]); 00715 /*@=charint@*/ 00716 goto exit; 00717 } 00718 } 00719 il = (rpmuint32_t) ntohl(block[2]); 00720 if (il > 32) { 00721 (void) snprintf(buf, sizeof(buf), 00722 _("sigh tags: BAD, no. of tags(%u) out of range"), (unsigned) il); 00723 goto exit; 00724 } 00725 dl = (rpmuint32_t) ntohl(block[3]); 00726 if (dl > 8192) { 00727 (void) snprintf(buf, sizeof(buf), 00728 _("sigh data: BAD, no. of bytes(%u) out of range"), (unsigned) dl); 00729 goto exit; 00730 } 00731 00732 /*@-sizeoftype@*/ 00733 nb = (il * sizeof(struct entryInfo_s)) + dl; 00734 /*@=sizeoftype@*/ 00735 if (map) { 00736 size_t pvlen = (sizeof(il) + sizeof(dl) + nb); 00737 static const int prot = PROT_READ | PROT_WRITE; 00738 static const int flags = MAP_PRIVATE| MAP_ANONYMOUS; 00739 static const int fdno = -1; 00740 static const off_t off = 0; 00741 00742 ei = mmap(NULL, pvlen, prot, flags, fdno, off); 00743 if (ei == NULL || ei == (void *)-1) 00744 fprintf(stderr, 00745 "==> mmap(%p[%u], 0x%x, 0x%x, %d, 0x%x) error(%d): %s\n", 00746 NULL, pvlen, prot, flags, fdno, (unsigned)off, 00747 errno, strerror(errno)); 00748 } else { 00749 size_t pvlen = (sizeof(il) + sizeof(dl) + nb); 00750 ei = xmalloc(pvlen); 00751 } 00752 00753 if ((xx = (int) timedRead(fd, (void *)&ei[2], nb)) != (int) nb) { 00754 (void) snprintf(buf, sizeof(buf), 00755 _("sigh blob(%u): BAD, read returned %d"), (unsigned) nb, xx); 00756 goto exit; 00757 } 00758 ei[0] = block[2]; 00759 ei[1] = block[3]; 00760 00761 if (map) { 00762 size_t pvlen = (sizeof(il) + sizeof(dl) + nb); 00763 if (mprotect(ei, pvlen, PROT_READ) != 0) 00764 fprintf(stderr, "==> mprotect(%p[%u],0x%x) error(%d): %s\n", 00765 ei, pvlen, PROT_READ, 00766 errno, strerror(errno)); 00767 } 00768 00769 pe = (entryInfo) &ei[2]; 00770 dataStart = (unsigned char *) (pe + il); 00771 00772 /* Check (and convert) the 1st tag element. */ 00773 xx = headerVerifyInfo(1, dl, pe, &entry->info, 0); 00774 if (xx != -1) { 00775 (void) snprintf(buf, sizeof(buf), 00776 _("tag[%d]: BAD, tag %u type %u offset %d count %u"), 00777 0, (unsigned) entry->info.tag, (unsigned) entry->info.type, 00778 (int)entry->info.offset, (unsigned) entry->info.count); 00779 goto exit; 00780 } 00781 00782 /* Is there an immutable header region tag? */ 00783 /*@-sizeoftype@*/ 00784 if (entry->info.tag == RPMTAG_HEADERSIGNATURES 00785 && entry->info.type == RPM_BIN_TYPE 00786 && entry->info.count == (rpmTagCount)REGION_TAG_COUNT) 00787 { 00788 /*@=sizeoftype@*/ 00789 00790 /* 00791 * XXX http://mysql.mirrors.pair.com/Downloads/MySQL-5.0/MySQL-client-community-5.0.51a-0.rhel4.i386.rpm 00792 * built by rpm-4.3.3 (from REL4) has entry->info.offset == 0. 00793 */ 00794 assert(entry->info.offset >= 0); /* XXX insurance */ 00795 if (entry->info.offset >= (rpmint32_t)dl) { 00796 (void) snprintf(buf, sizeof(buf), 00797 _("region offset: BAD, tag %u type %u offset %d count %u"), 00798 (unsigned) entry->info.tag, (unsigned) entry->info.type, 00799 (int)entry->info.offset, (unsigned) entry->info.count); 00800 goto exit; 00801 } 00802 00803 /* Is there an immutable header region tag trailer? */ 00804 dataEnd = dataStart + entry->info.offset; 00805 /*@-sizeoftype@*/ 00806 (void) memcpy(info, dataEnd, REGION_TAG_COUNT); 00807 /* XXX Really old packages have HEADER_IMAGE, not HEADER_SIGNATURES. */ 00808 if (info->tag == (rpmuint32_t) htonl(RPMTAG_HEADERIMAGE)) { 00809 rpmuint32_t stag = (rpmuint32_t) htonl(RPMTAG_HEADERSIGNATURES); 00810 info->tag = stag; 00811 memcpy(dataEnd, &stag, sizeof(stag)); 00812 } 00813 dataEnd += REGION_TAG_COUNT; 00814 00815 xx = headerVerifyInfo(1, dl, info, &entry->info, 1); 00816 if (xx != -1 || 00817 !(entry->info.tag == RPMTAG_HEADERSIGNATURES 00818 && entry->info.type == RPM_BIN_TYPE 00819 && entry->info.count == (rpmTagCount)REGION_TAG_COUNT)) 00820 { 00821 (void) snprintf(buf, sizeof(buf), 00822 _("region trailer: BAD, tag %u type %u offset %d count %u"), 00823 (unsigned) entry->info.tag, (unsigned) entry->info.type, 00824 (int)entry->info.offset, (unsigned) entry->info.count); 00825 goto exit; 00826 } 00827 /*@=sizeoftype@*/ 00828 memset(info, 0, sizeof(*info)); 00829 00830 /* Is the no. of tags in the region less than the total no. of tags? */ 00831 ril = (rpmuint32_t) (entry->info.offset/sizeof(*pe)); 00832 if ((entry->info.offset % sizeof(*pe)) || ril > il) { 00833 (void) snprintf(buf, sizeof(buf), 00834 _("region size: BAD, ril(%u) > il(%u)"), (unsigned) ril, (unsigned) il); 00835 goto exit; 00836 } 00837 } 00838 00839 /* Sanity check signature tags */ 00840 memset(info, 0, sizeof(*info)); 00841 for (i = 1; i < (unsigned) il; i++) { 00842 xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0); 00843 if (xx != -1) { 00844 (void) snprintf(buf, sizeof(buf), 00845 _("sigh tag[%u]: BAD, tag %u type %u offset %d count %u"), 00846 (unsigned) i, (unsigned) entry->info.tag, (unsigned) entry->info.type, 00847 (int)entry->info.offset, (unsigned) entry->info.count); 00848 goto exit; 00849 } 00850 } 00851 00852 /* OK, blob looks sane, load the header. */ 00853 sigh = headerLoad(ei); 00854 if (sigh == NULL) { 00855 (void) snprintf(buf, sizeof(buf), _("sigh load: BAD")); 00856 goto exit; 00857 } 00858 if (map) { 00859 sigh->flags |= HEADERFLAG_MAPPED; 00860 sigh->flags |= HEADERFLAG_RDONLY; 00861 } else 00862 sigh->flags |= HEADERFLAG_ALLOCATED; 00863 sigh->flags |= HEADERFLAG_SIGNATURE; 00864 00865 { size_t sigSize = headerSizeof(sigh); 00866 size_t pad = (8 - (sigSize % 8)) % 8; /* 8-byte pad */ 00867 00868 /* Position at beginning of header. */ 00869 if (pad && (xx = (int) timedRead(fd, (void *)block, pad)) != (int) pad) 00870 { 00871 (void) snprintf(buf, sizeof(buf), 00872 _("sigh pad(%u): BAD, read %d bytes"), (unsigned) pad, xx); 00873 goto exit; 00874 } 00875 00876 /* Print package component sizes. */ 00877 00878 he->tag = (rpmTag) RPMSIGTAG_SIZE; 00879 xx = headerGet(sigh, he, 0); 00880 if (xx) { 00881 size_t datasize = he->p.ui32p[0]; 00882 rc = printSize(fd, sigSize, pad, datasize); 00883 if (rc != RPMRC_OK) 00884 (void) snprintf(buf, sizeof(buf), 00885 _("sigh sigSize(%u): BAD, Fstat(2) failed"), (unsigned) sigSize); 00886 } 00887 he->p.ptr = _free(he->p.ptr); 00888 } 00889 (void) headerSetStartOff(sigh, (rpmuint32_t)startoff); 00890 (void) headerSetEndOff(sigh, fd->stats->ops[FDSTAT_READ].bytes); 00891 00892 exit: 00893 if (sighp && sigh && rc == RPMRC_OK) 00894 *sighp = headerLink(sigh); 00895 (void)headerFree(sigh); 00896 sigh = NULL; 00897 00898 if (msg != NULL) { 00899 buf[sizeof(buf)-1] = '\0'; 00900 *msg = xstrdup(buf); 00901 } 00902 00903 return rc; 00904 } 00905 00906 /*===============================================*/ 00907 00921 rpmRC headerCheck(pgpDig dig, const void * uh, size_t uc, const char ** msg) 00922 { 00923 char buf[8*BUFSIZ]; 00924 rpmuint32_t * ei = (rpmuint32_t *) uh; 00925 rpmuint32_t il = (rpmuint32_t) ntohl(ei[0]); 00926 rpmuint32_t dl = (rpmuint32_t) ntohl(ei[1]); 00927 /*@-castexpose@*/ 00928 entryInfo pe = (entryInfo) &ei[2]; 00929 /*@=castexpose@*/ 00930 rpmuint32_t ildl[2]; 00931 size_t pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl; 00932 unsigned char * dataStart = (unsigned char *) (pe + il); 00933 indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry)); 00934 entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info)); 00935 const void * sig = NULL; 00936 unsigned char * b; 00937 rpmVSFlags vsflags = pgpDigVSFlags; 00938 rpmop op; 00939 size_t siglen = 0; 00940 int blen; 00941 size_t nb; 00942 rpmuint32_t ril = 0; 00943 unsigned char * regionEnd = NULL; 00944 rpmRC rc = RPMRC_FAIL; /* assume failure */ 00945 int xx; 00946 rpmuint32_t i; 00947 00948 if (_pkgio_debug) 00949 fprintf(stderr, "--> headerCheck(%p, %p[%u], %p)\n", dig, uh, (unsigned) uc, msg); 00950 00951 buf[0] = '\0'; 00952 00953 /* Is the blob the right size? */ 00954 if (uc > 0 && pvlen != uc) { 00955 (void) snprintf(buf, sizeof(buf), 00956 _("blob size(%d): BAD, 8 + 16 * il(%u) + dl(%u)"), 00957 (int)uc, (unsigned)il, (unsigned)dl); 00958 goto exit; 00959 } 00960 00961 /* Check (and convert) the 1st tag element. */ 00962 xx = headerVerifyInfo(1, dl, pe, &entry->info, 0); 00963 if (xx != -1) { 00964 (void) snprintf(buf, sizeof(buf), 00965 _("tag[%d]: BAD, tag %u type %u offset %d count %u"), 00966 0, (unsigned) entry->info.tag, (unsigned) entry->info.type, 00967 (int)entry->info.offset, (unsigned) entry->info.count); 00968 goto exit; 00969 } 00970 00971 /* Is there an immutable header region tag? */ 00972 /*@-sizeoftype@*/ 00973 if (!(entry->info.tag == RPMTAG_HEADERIMMUTABLE 00974 && entry->info.type == RPM_BIN_TYPE 00975 && entry->info.count == (rpmTagCount)REGION_TAG_COUNT)) 00976 { 00977 rc = RPMRC_NOTFOUND; 00978 goto exit; 00979 } 00980 /*@=sizeoftype@*/ 00981 00982 /* Is the offset within the data area? */ 00983 if (entry->info.offset >= (int) dl) { 00984 (void) snprintf(buf, sizeof(buf), 00985 _("region offset: BAD, tag %u type %u offset %d count %u"), 00986 (unsigned) entry->info.tag, (unsigned) entry->info.type, 00987 (int)entry->info.offset, (unsigned) entry->info.count); 00988 goto exit; 00989 } 00990 00991 /* Is there an immutable header region tag trailer? */ 00992 regionEnd = dataStart + entry->info.offset; 00993 /*@-sizeoftype@*/ 00994 (void) memcpy(info, regionEnd, REGION_TAG_COUNT); 00995 regionEnd += REGION_TAG_COUNT; 00996 00997 xx = headerVerifyInfo(1, dl, info, &entry->info, 1); 00998 if (xx != -1 || 00999 !(entry->info.tag == RPMTAG_HEADERIMMUTABLE 01000 && entry->info.type == RPM_BIN_TYPE 01001 && entry->info.count == (rpmTagCount)REGION_TAG_COUNT)) 01002 { 01003 (void) snprintf(buf, sizeof(buf), 01004 _("region trailer: BAD, tag %u type %u offset %d count %u"), 01005 (unsigned) entry->info.tag, (unsigned) entry->info.type, 01006 (int)entry->info.offset, (unsigned) entry->info.count); 01007 goto exit; 01008 } 01009 /*@=sizeoftype@*/ 01010 memset(info, 0, sizeof(*info)); 01011 01012 /* Is the no. of tags in the region less than the total no. of tags? */ 01013 ril = (rpmuint32_t) (entry->info.offset/sizeof(*pe)); 01014 if ((entry->info.offset % sizeof(*pe)) || ril > il) { 01015 (void) snprintf(buf, sizeof(buf), 01016 _("region size: BAD, ril(%u) > il(%u)"), (unsigned) ril, (unsigned)il); 01017 goto exit; 01018 } 01019 01020 /* Find a header-only digest/signature tag. */ 01021 for (i = ril; i < (unsigned) il; i++) { 01022 xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0); 01023 if (xx != -1) { 01024 (void) snprintf(buf, sizeof(buf), 01025 _("tag[%u]: BAD, tag %u type %u offset %d count %u"), 01026 (unsigned) i, (unsigned) entry->info.tag, (unsigned) entry->info.type, 01027 (int)entry->info.offset, (unsigned) entry->info.count); 01028 goto exit; 01029 } 01030 01031 switch (entry->info.tag) { 01032 case RPMTAG_SHA1HEADER: 01033 if (vsflags & RPMVSF_NOSHA1HEADER) 01034 /*@switchbreak@*/ break; 01035 blen = 0; 01036 for (b = dataStart + entry->info.offset; *b != '\0'; b++) { 01037 if (strchr("0123456789abcdefABCDEF", *b) == NULL) 01038 /*@innerbreak@*/ break; 01039 blen++; 01040 } 01041 if (entry->info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40) 01042 { 01043 (void) snprintf(buf, sizeof(buf), _("hdr SHA1: BAD, not hex")); 01044 goto exit; 01045 } 01046 if (info->tag == 0) { 01047 *info = entry->info; /* structure assignment */ 01048 siglen = blen + 1; 01049 } 01050 /*@switchbreak@*/ break; 01051 case RPMTAG_RSAHEADER: 01052 if (vsflags & RPMVSF_NORSAHEADER) 01053 /*@switchbreak@*/ break; 01054 if (entry->info.type != RPM_BIN_TYPE) { 01055 (void) snprintf(buf, sizeof(buf), _("hdr RSA: BAD, not binary")); 01056 goto exit; 01057 } 01058 *info = entry->info; /* structure assignment */ 01059 siglen = info->count; 01060 /*@switchbreak@*/ break; 01061 case RPMTAG_DSAHEADER: 01062 if (vsflags & RPMVSF_NODSAHEADER) 01063 /*@switchbreak@*/ break; 01064 if (entry->info.type != RPM_BIN_TYPE) { 01065 (void) snprintf(buf, sizeof(buf), _("hdr DSA: BAD, not binary")); 01066 goto exit; 01067 } 01068 *info = entry->info; /* structure assignment */ 01069 siglen = info->count; 01070 /*@switchbreak@*/ break; 01071 default: 01072 /*@switchbreak@*/ break; 01073 } 01074 } 01075 rc = RPMRC_NOTFOUND; 01076 01077 exit: 01078 /* Return determined RPMRC_OK/RPMRC_FAIL conditions. */ 01079 if (rc != RPMRC_NOTFOUND) { 01080 buf[sizeof(buf)-1] = '\0'; 01081 if (msg) *msg = xstrdup(buf); 01082 if (_pkgio_debug) 01083 fprintf(stderr, "--> headerCheck #1: rc %d \"%s\"\n", rc, (msg ? *msg: "")); 01084 return rc; 01085 } 01086 01087 /* If no header-only digest/signature, then do simple sanity check. */ 01088 if (info->tag == 0) { 01089 xx = (ril > 0 ? headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0) : -1); 01090 if (xx != -1) { 01091 (void) snprintf(buf, sizeof(buf), 01092 _("tag[%d]: BAD, tag %u type %u offset %d count %u"), 01093 xx+1, (unsigned) entry->info.tag, (unsigned) entry->info.type, 01094 (int)entry->info.offset, (unsigned) entry->info.count); 01095 rc = RPMRC_FAIL; 01096 } else { 01097 (void) snprintf(buf, sizeof(buf), "Header sanity check: OK"); 01098 rc = RPMRC_OK; 01099 } 01100 buf[sizeof(buf)-1] = '\0'; 01101 if (msg) *msg = xstrdup(buf); 01102 if (_pkgio_debug) 01103 fprintf(stderr, "--> headerCheck #2: rc %d \"%s\"\n", rc, (msg ? *msg: "")); 01104 return rc; 01105 } 01106 01107 /* Verify header-only digest/signature. */ 01108 assert(dig != NULL); 01109 dig->nbytes = 0; 01110 01111 sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen); 01112 { 01113 const void * osig = pgpGetSig(dig); 01114 /*@-modobserver -observertrans -dependenttrans @*/ /* FIX: pgpSetSig() lazy free. */ 01115 osig = _free(osig); 01116 /*@=modobserver =observertrans =dependenttrans @*/ 01117 (void) pgpSetSig(dig, info->tag, info->type, sig, info->count); 01118 } 01119 01120 switch (info->tag) { 01121 case RPMTAG_RSAHEADER: 01122 /* Parse the parameters from the OpenPGP packets that will be needed. */ 01123 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug())); 01124 if (dig->signature.version != (rpmuint8_t)3 01125 && dig->signature.version != (rpmuint8_t)4) 01126 { 01127 rpmlog(RPMLOG_ERR, 01128 _("skipping header with unverifiable V%u signature\n"), 01129 (unsigned) dig->signature.version); 01130 rc = RPMRC_FAIL; 01131 goto exit; 01132 } 01133 01134 ildl[0] = (rpmuint32_t) htonl(ril); 01135 ildl[1] = (rpmuint32_t) (regionEnd - dataStart); 01136 ildl[1] = (rpmuint32_t) htonl(ildl[1]); 01137 01138 op = pgpStatsAccumulator(dig, 10); /* RPMTS_OP_DIGEST */ 01139 (void) rpmswEnter(op, 0); 01140 dig->hdrctx = rpmDigestInit((pgpHashAlgo)dig->signature.hash_algo, RPMDIGEST_NONE); 01141 01142 b = NULL; nb = 0; 01143 (void) headerGetMagic(NULL, &b, &nb); 01144 if (b && nb > 0) { 01145 (void) rpmDigestUpdate(dig->hdrctx, b, nb); 01146 dig->nbytes += nb; 01147 } 01148 01149 b = (unsigned char *) ildl; 01150 nb = sizeof(ildl); 01151 (void) rpmDigestUpdate(dig->hdrctx, b, nb); 01152 dig->nbytes += nb; 01153 01154 b = (unsigned char *) pe; 01155 nb = (size_t) (htonl(ildl[0]) * sizeof(*pe)); 01156 (void) rpmDigestUpdate(dig->hdrctx, b, nb); 01157 dig->nbytes += nb; 01158 01159 b = (unsigned char *) dataStart; 01160 nb = (size_t) htonl(ildl[1]); 01161 (void) rpmDigestUpdate(dig->hdrctx, b, nb); 01162 dig->nbytes += nb; 01163 (void) rpmswExit(op, dig->nbytes); 01164 01165 break; 01166 case RPMTAG_DSAHEADER: 01167 /* Parse the parameters from the OpenPGP packets that will be needed. */ 01168 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug())); 01169 if (dig->signature.version != (rpmuint8_t)3 01170 && dig->signature.version != (rpmuint8_t)4) 01171 { 01172 rpmlog(RPMLOG_ERR, 01173 _("skipping header with unverifiable V%u signature\n"), 01174 (unsigned) dig->signature.version); 01175 rc = RPMRC_FAIL; 01176 goto exit; 01177 } 01178 /*@fallthrough@*/ 01179 case RPMTAG_SHA1HEADER: 01180 ildl[0] = (rpmuint32_t) htonl(ril); 01181 ildl[1] = (rpmuint32_t) (regionEnd - dataStart); 01182 ildl[1] = (rpmuint32_t) htonl(ildl[1]); 01183 01184 op = pgpStatsAccumulator(dig, 10); /* RPMTS_OP_DIGEST */ 01185 (void) rpmswEnter(op, 0); 01186 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE); 01187 01188 b = NULL; nb = 0; 01189 (void) headerGetMagic(NULL, &b, &nb); 01190 if (b && nb > 0) { 01191 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb); 01192 dig->nbytes += nb; 01193 } 01194 01195 b = (unsigned char *) ildl; 01196 nb = sizeof(ildl); 01197 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb); 01198 dig->nbytes += nb; 01199 01200 b = (unsigned char *) pe; 01201 nb = (size_t) (htonl(ildl[0]) * sizeof(*pe)); 01202 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb); 01203 dig->nbytes += nb; 01204 01205 b = (unsigned char *) dataStart; 01206 nb = (size_t) htonl(ildl[1]); 01207 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb); 01208 dig->nbytes += nb; 01209 (void) rpmswExit(op, dig->nbytes); 01210 01211 break; 01212 default: 01213 sig = _free(sig); 01214 break; 01215 } 01216 01217 buf[0] = '\0'; 01218 rc = rpmVerifySignature(dig, buf); 01219 01220 buf[sizeof(buf)-1] = '\0'; 01221 if (msg) *msg = xstrdup(buf); 01222 01223 if (_pkgio_debug) 01224 fprintf(stderr, "--> headerCheck #3: rc %d \"%s\"\n", rc, (msg ? *msg: "")); 01225 return rc; 01226 } 01227 01233 static size_t szHeader(/*@null@*/ const void * ptr) 01234 /*@*/ 01235 { 01236 rpmuint32_t p[4]; 01237 assert(ptr != NULL); 01238 memcpy(p, ptr, sizeof(p)); 01239 return (8 + 8 + 16 * ntohl(p[2]) + ntohl(p[3])); 01240 } 01241 01242 /*@-globuse@*/ 01250 static rpmRC ckHeader(/*@unused@*/ FD_t fd, const void * ptr, 01251 /*@unused@*/ /*@null@*/ const char ** msg) 01252 /*@globals fileSystem, internalState @*/ 01253 /*@modifies ptr, fileSystem, internalState @*/ 01254 { 01255 rpmRC rc = RPMRC_OK; 01256 Header h; 01257 01258 h = headerLoad((void *)ptr); 01259 if (h == NULL) 01260 rc = RPMRC_FAIL; 01261 (void)headerFree(h); 01262 h = NULL; 01263 01264 return rc; 01265 } 01266 01274 static rpmRC rpmReadHeader(FD_t fd, /*@null@*/ Header * hdrp, 01275 /*@null@*/ const char ** msg) 01276 /*@globals fileSystem, internalState @*/ 01277 /*@modifies fd, *hdrp, *msg, fileSystem, internalState @*/ 01278 { 01279 rpmxar xar = fdGetXAR(fd); 01280 pgpDig dig = pgpDigLink(fdGetDig(fd), "rpmReadHeader"); 01281 char buf[BUFSIZ]; 01282 rpmuint32_t block[4]; 01283 rpmuint32_t il; 01284 rpmuint32_t dl; 01285 rpmuint32_t * ei = NULL; 01286 size_t uc = 0; 01287 unsigned char * b; 01288 size_t startoff; 01289 size_t nb; 01290 Header h = NULL; 01291 const char * origin = NULL; 01292 rpmRC rc = RPMRC_FAIL; /* assume failure */ 01293 int xx; 01294 static int map = 1; 01295 01296 if (_pkgio_debug) 01297 fprintf(stderr, "--> rpmReadHeader(%p, %p, %p)\n", fd, hdrp, msg); 01298 01299 /* Create (if not already) a signature parameters container. */ 01300 if (dig == NULL) { 01301 dig = pgpDigNew(0); 01302 (void) fdSetDig(fd, dig); 01303 } 01304 01305 buf[0] = '\0'; 01306 01307 if (hdrp) 01308 *hdrp = NULL; 01309 01310 memset(block, 0, sizeof(block)); 01311 if (xar != NULL) { 01312 const char item[] = "Header"; 01313 if ((xx = rpmxarNext(xar)) != 0 || (xx = rpmxarPull(xar, item)) != 0) { 01314 (void) snprintf(buf, sizeof(buf), 01315 _("XAR file not found (or no XAR support)")); 01316 rc = RPMRC_NOTFOUND; 01317 goto exit; 01318 } 01319 } 01320 01321 startoff = fd->stats->ops[FDSTAT_READ].bytes; 01322 if ((xx = (int) timedRead(fd, (char *)block, sizeof(block))) != (int)sizeof(block)) { 01323 /* XXX Handle EOF's as RPMRC_NOTFOUND, not RPMRC_FAIL, returns. */ 01324 if (xx == 0) 01325 rc = RPMRC_NOTFOUND; 01326 else 01327 (void) snprintf(buf, sizeof(buf), 01328 _("hdr size(%u): BAD, read returned %d"), (unsigned)sizeof(block), xx); 01329 goto exit; 01330 } 01331 01332 b = NULL; 01333 nb = 0; 01334 (void) headerGetMagic(NULL, &b, &nb); 01335 if (memcmp(block, b, nb)) { 01336 unsigned char * x = (unsigned char *) block; 01337 /*@+charint@*/ 01338 (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]); 01339 /*@=charint@*/ 01340 goto exit; 01341 } 01342 01343 il = (rpmuint32_t)ntohl(block[2]); 01344 if (hdrchkTags(il)) { 01345 (void) snprintf(buf, sizeof(buf), 01346 _("hdr tags: BAD, no. of tags(%u) out of range"), (unsigned) il); 01347 01348 goto exit; 01349 } 01350 dl = (rpmuint32_t)ntohl(block[3]); 01351 if (hdrchkData(dl)) { 01352 (void) snprintf(buf, sizeof(buf), 01353 _("hdr data: BAD, no. of bytes(%u) out of range\n"), (unsigned) dl); 01354 goto exit; 01355 } 01356 01357 /*@-sizeoftype@*/ 01358 nb = (il * sizeof(struct entryInfo_s)) + dl; 01359 /*@=sizeoftype@*/ 01360 uc = sizeof(il) + sizeof(dl) + nb; 01361 if (map) { 01362 static const int prot = PROT_READ | PROT_WRITE; 01363 static const int flags = MAP_PRIVATE| MAP_ANONYMOUS; 01364 static const int fdno = -1; 01365 static const off_t off = 0; 01366 01367 ei = mmap(NULL, uc, prot, flags, fdno, off); 01368 if (ei == NULL || ei == (void *)-1) 01369 fprintf(stderr, 01370 "==> mmap(%p[%u], 0x%x, 0x%x, %d, 0x%x) error(%d): %s\n", 01371 NULL, uc, prot, flags, fdno, (unsigned)off, 01372 errno, strerror(errno)); 01373 } else { 01374 ei = (rpmuint32_t *) xmalloc(uc); 01375 } 01376 01377 if ((xx = (int) timedRead(fd, (char *)&ei[2], nb)) != (int) nb) { 01378 (void) snprintf(buf, sizeof(buf), 01379 _("hdr blob(%u): BAD, read returned %d"), (unsigned)nb, xx); 01380 goto exit; 01381 } 01382 ei[0] = block[2]; 01383 ei[1] = block[3]; 01384 01385 if (map) { 01386 if (mprotect(ei, uc, PROT_READ) != 0) 01387 fprintf(stderr, "==> mprotect(%p[%u],0x%x) error(%d): %s\n", 01388 ei, uc, PROT_READ, 01389 errno, strerror(errno)); 01390 } 01391 01392 /* Sanity check header tags */ 01393 rc = headerCheck(dig, ei, uc, msg); 01394 if (rc != RPMRC_OK) 01395 goto exit; 01396 01397 /* OK, blob looks sane, load the header. */ 01398 h = headerLoad(ei); 01399 if (h == NULL) { 01400 (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n")); 01401 goto exit; 01402 } 01403 if (map) { 01404 h->flags |= HEADERFLAG_MAPPED; 01405 h->flags |= HEADERFLAG_RDONLY; 01406 } else 01407 h->flags |= HEADERFLAG_ALLOCATED; 01408 ei = NULL; /* XXX will be freed with header */ 01409 01410 /* Save the opened path as the header origin. */ 01411 /* XXX TODO: push the Realpath() underneath fdGetOPath(). */ 01412 origin = fdGetOPath(fd); 01413 if (origin != NULL) { 01414 const char * lpath = NULL; 01415 int ut = urlPath(origin, &lpath); 01416 ut = ut; /* XXX keep gcc quiet. */ 01417 if (lpath && *lpath != '/') { 01418 char * rpath = Realpath(origin, NULL); 01419 (void) headerSetOrigin(h, rpath); 01420 rpath = _free(rpath); 01421 } else 01422 (void) headerSetOrigin(h, origin); 01423 } 01424 /*@-mods@*/ 01425 { struct stat * st = headerGetStatbuf(h); 01426 int saveno = errno; 01427 (void) Fstat(fd, st); 01428 errno = saveno; 01429 } 01430 /*@=mods@*/ 01431 (void) headerSetStartOff(h, (rpmuint32_t)startoff); 01432 (void) headerSetEndOff(h, fd->stats->ops[FDSTAT_READ].bytes); 01433 01434 exit: 01435 if (hdrp && h && rc == RPMRC_OK) 01436 *hdrp = headerLink(h); 01437 if (ei != NULL && uc > 0) { 01438 if (map) { 01439 if (munmap(ei, uc) != 0) 01440 fprintf(stderr, "==> munmap(%p[%u]) error(%d): %s\n", 01441 ei, uc, errno, strerror(errno)); 01442 ei = NULL; 01443 } else 01444 ei = _free(ei); 01445 } 01446 dig = pgpDigFree(dig, "rpmReadHeader"); 01447 (void)headerFree(h); 01448 h = NULL; 01449 01450 if (msg != NULL && *msg == NULL && buf[0] != '\0') { 01451 buf[sizeof(buf)-1] = '\0'; 01452 *msg = xstrdup(buf); 01453 } 01454 01455 if (_pkgio_debug) 01456 fprintf(stderr, "--> rpmReadHeader: rc %d \"%s\"\n", rc, (msg ? *msg: "")); 01457 return rc; 01458 } 01459 01467 static rpmRC rdHeader(FD_t fd, /*@out@*/ /*@null@*/ void * ptr, 01468 /*@null@*/ const char ** msg) 01469 /*@globals fileSystem, internalState @*/ 01470 /*@modifies fd, *ptr, *msg, fileSystem, internalState @*/ 01471 { 01472 Header * hdrp = ptr; 01473 /*@-compdef@*/ 01474 return rpmReadHeader(fd, hdrp, msg); 01475 /*@=compdef@*/ 01476 } 01477 01485 static rpmRC wrHeader(FD_t fd, void * ptr, 01486 /*@unused@*/ /*@null@*/ const char ** msg) 01487 /*@globals fileSystem, internalState @*/ 01488 /*@modifies fd, ptr, *msg, fileSystem, internalState @*/ 01489 { 01490 Header h = ptr; 01491 return rpmWriteHeader(fd, h, msg); 01492 } 01493 /*@=globuse@*/ 01494 01495 /*===============================================*/ 01496 01497 size_t rpmpkgSizeof(const char * fn, const void * ptr) 01498 { 01499 size_t len = 0; 01500 01501 if (!strcmp(fn, "Lead")) 01502 len = 96; /* RPMLEAD_SIZE */ 01503 else 01504 if (!strcmp(fn, "Signature")) { 01505 len = szHeader(ptr); 01506 len += ((8 - (len % 8)) % 8); /* padding */ 01507 } else 01508 if (!strcmp(fn, "Header")) 01509 len = szHeader(ptr); 01510 return len; 01511 } 01512 01513 rpmRC rpmpkgCheck(const char * fn, FD_t fd, const void * ptr, const char ** msg) 01514 { 01515 rpmRC rc = RPMRC_FAIL; 01516 01517 if (msg) 01518 *msg = NULL; 01519 01520 if (!strcmp(fn, "Header")) 01521 rc = ckHeader(fd, ptr, msg); 01522 return rc; 01523 } 01524 01525 rpmRC rpmpkgRead(const char * fn, FD_t fd, void * ptr, const char ** msg) 01526 { 01527 rpmRC rc = RPMRC_FAIL; 01528 01529 if (msg) 01530 *msg = NULL; 01531 01532 if (!strcmp(fn, "Lead")) 01533 rc = rdLead(fd, ptr, msg); 01534 else 01535 if (!strcmp(fn, "Signature")) 01536 rc = rdSignature(fd, ptr, msg); 01537 else 01538 if (!strcmp(fn, "Header")) 01539 rc = rdHeader(fd, ptr, msg); 01540 return rc; 01541 } 01542 01543 rpmRC rpmpkgWrite(const char * fn, FD_t fd, void * ptr, const char ** msg) 01544 { 01545 rpmRC rc = RPMRC_FAIL; 01546 01547 if (msg) 01548 *msg = NULL; 01549 01550 if (!strcmp(fn, "Lead")) 01551 rc = wrLead(fd, ptr, msg); 01552 else 01553 if (!strcmp(fn, "Signature")) 01554 rc = wrSignature(fd, ptr, msg); 01555 else 01556 if (!strcmp(fn, "Header")) 01557 rc = wrHeader(fd, ptr, msg); 01558 return rc; 01559 }