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