rpm
4.5
|
00001 00005 #include "system.h" 00006 00007 #include <netinet/in.h> 00008 00009 #include <rpmio_internal.h> 00010 #include <rpmlib.h> 00011 00012 #if defined(RPM_VENDOR_MANDRIVA) 00013 #define _RPMEVR_INTERNAL 00014 #include "rpmevr.h" 00015 #endif 00016 00017 #include "rpmts.h" 00018 #include "rpmevr.h" 00019 00020 #include "misc.h" /* XXX stripTrailingChar() */ 00021 #include "rpmlead.h" 00022 00023 #include "header_internal.h" /* XXX headerCheck */ 00024 #include "signature.h" 00025 #include "debug.h" 00026 00027 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s)) 00028 00029 /*@access pgpDig @*/ 00030 /*@access pgpDigParams @*/ 00031 /*@access Header @*/ /* XXX compared with NULL */ 00032 /*@access entryInfo @*/ /* XXX headerCheck */ 00033 /*@access indexEntry @*/ /* XXX headerCheck */ 00034 /*@access FD_t @*/ /* XXX stealing digests */ 00035 00036 /*@unchecked@*/ 00037 static int _print_pkts = 0; 00038 00039 /*@unchecked@*/ 00040 static unsigned int nkeyids_max = 256; 00041 /*@unchecked@*/ 00042 static unsigned int nkeyids = 0; 00043 /*@unchecked@*/ 00044 static unsigned int nextkeyid = 0; 00045 /*@unchecked@*/ /*@only@*/ /*@null@*/ 00046 static unsigned int * keyids; 00047 00048 /*@unchecked@*/ 00049 static unsigned char header_magic[8] = { 00050 0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00 00051 }; 00052 00056 /*@observer@*/ /*@unchecked@*/ 00057 static int typeAlign[16] = { 00058 1, 00059 1, 00060 1, 00061 2, 00062 4, 00063 8, 00064 1, 00065 1, 00066 1, 00067 1, 00068 0, 00069 0, 00070 0, 00071 0, 00072 0, 00073 0 00074 }; 00075 00080 #define hdrchkTags(_ntags) ((_ntags) & 0xffff0000) 00081 00085 #define hdrchkType(_type) ((_type) < RPM_MIN_TYPE || (_type) > RPM_MAX_TYPE) 00086 00091 #define hdrchkData(_nbytes) ((_nbytes) & 0xff000000) 00092 00096 #define hdrchkAlign(_type, _off) ((_off) & (typeAlign[_type]-1)) 00097 00101 #define hdrchkRange(_dl, _off) ((_off) < 0 || (_off) > (_dl)) 00102 00103 #if defined(RPM_VENDOR_MANDRIVA) 00104 /*@-boundsread@*/ 00105 static int dncmp(const void * a, const void * b) 00106 /*@*/ 00107 { 00108 const char *const * first = a; 00109 const char *const * second = b; 00110 return strcmp(*first, *second); 00111 } 00112 /*@=boundsread@*/ 00113 00114 /*@-bounds@*/ 00119 static void compressFilelist(Header h) 00120 /*@modifies h @*/ 00121 { 00122 HGE_t hge = (HGE_t)headerGetEntryMinMemory; 00123 HAE_t hae = (HAE_t)headerAddEntry; 00124 HRE_t hre = (HRE_t)headerRemoveEntry; 00125 HFD_t hfd = headerFreeData; 00126 char ** fileNames; 00127 const char ** dirNames; 00128 const char ** baseNames; 00129 int_32 * dirIndexes; 00130 rpmTagType fnt; 00131 int count; 00132 int i, xx; 00133 int dirIndex = -1; 00134 00135 /* 00136 * This assumes the file list is already sorted, and begins with a 00137 * single '/'. That assumption isn't critical, but it makes things go 00138 * a bit faster. 00139 */ 00140 00141 if (headerIsEntry(h, RPMTAG_DIRNAMES)) { 00142 xx = hre(h, RPMTAG_OLDFILENAMES); 00143 return; /* Already converted. */ 00144 } 00145 00146 if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (void **) &fileNames, &count)) 00147 return; /* no file list */ 00148 if (fileNames == NULL || count <= 0) 00149 return; 00150 00151 dirNames = alloca(sizeof(*dirNames) * count); /* worst case */ 00152 baseNames = alloca(sizeof(*dirNames) * count); 00153 dirIndexes = alloca(sizeof(*dirIndexes) * count); 00154 00155 if (fileNames[0][0] != '/') { 00156 /* HACK. Source RPM, so just do things differently */ 00157 dirIndex = 0; 00158 dirNames[dirIndex] = ""; 00159 for (i = 0; i < count; i++) { 00160 dirIndexes[i] = dirIndex; 00161 baseNames[i] = fileNames[i]; 00162 } 00163 goto exit; 00164 } 00165 00166 /*@-branchstate@*/ 00167 for (i = 0; i < count; i++) { 00168 const char ** needle; 00169 char savechar; 00170 char * baseName; 00171 int len; 00172 00173 if (fileNames[i] == NULL) /* XXX can't happen */ 00174 continue; 00175 baseName = strrchr(fileNames[i], '/') + 1; 00176 len = baseName - fileNames[i]; 00177 needle = dirNames; 00178 savechar = *baseName; 00179 *baseName = '\0'; 00180 /*@-compdef@*/ 00181 if (dirIndex < 0 || 00182 (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) { 00183 char *s = alloca(len + 1); 00184 memcpy(s, fileNames[i], len + 1); 00185 s[len] = '\0'; 00186 dirIndexes[i] = ++dirIndex; 00187 dirNames[dirIndex] = s; 00188 } else 00189 dirIndexes[i] = needle - dirNames; 00190 /*@=compdef@*/ 00191 00192 *baseName = savechar; 00193 baseNames[i] = baseName; 00194 } 00195 /*@=branchstate@*/ 00196 00197 exit: 00198 if (count > 0) { 00199 xx = hae(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count); 00200 xx = hae(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE, 00201 baseNames, count); 00202 xx = hae(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE, 00203 dirNames, dirIndex + 1); 00204 } 00205 00206 fileNames = hfd(fileNames, fnt); 00207 00208 xx = hre(h, RPMTAG_OLDFILENAMES); 00209 } 00210 /*@=bounds@*/ 00211 00212 00213 /* copied verbatim from build/pack.c */ 00214 static void providePackageNVR(Header h) 00215 /*@modifies h @*/ 00216 { 00217 HGE_t hge = (HGE_t)headerGetEntryMinMemory; 00218 HFD_t hfd = headerFreeData; 00219 const char *name, *version, *release; 00220 int_32 * epoch; 00221 const char *pEVR; 00222 char *p; 00223 int_32 pFlags = RPMSENSE_EQUAL; 00224 const char ** provides = NULL; 00225 const char ** providesEVR = NULL; 00226 rpmTagType pnt, pvt; 00227 int_32 * provideFlags = NULL; 00228 int providesCount; 00229 int i, xx; 00230 int bingo = 1; 00231 00232 /* Generate provides for this package name-version-release. */ 00233 xx = headerNVR(h, &name, &version, &release); 00234 if (!(name && version && release)) 00235 return; 00236 pEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1); 00237 *p = '\0'; 00238 if (hge(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) { 00239 sprintf(p, "%d:", *epoch); 00240 while (*p != '\0') 00241 p++; 00242 } 00243 (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release); 00244 00245 /* 00246 * Rpm prior to 3.0.3 does not have versioned provides. 00247 * If no provides at all are available, we can just add. 00248 */ 00249 if (!hge(h, RPMTAG_PROVIDENAME, &pnt, (void **) &provides, &providesCount)) 00250 goto exit; 00251 00252 /* 00253 * Otherwise, fill in entries on legacy packages. 00254 */ 00255 if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt, (void **) &providesEVR, NULL)) { 00256 for (i = 0; i < providesCount; i++) { 00257 char * vdummy = ""; 00258 int_32 fdummy = RPMSENSE_ANY; 00259 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE, 00260 &vdummy, 1); 00261 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE, 00262 &fdummy, 1); 00263 } 00264 goto exit; 00265 } 00266 00267 xx = hge(h, RPMTAG_PROVIDEFLAGS, NULL, (void **) &provideFlags, NULL); 00268 00269 /*@-nullderef@*/ /* LCL: providesEVR is not NULL */ 00270 if (provides && providesEVR && provideFlags) 00271 for (i = 0; i < providesCount; i++) { 00272 if (!(provides[i] && providesEVR[i])) 00273 continue; 00274 if (!(provideFlags[i] == RPMSENSE_EQUAL && 00275 !strcmp(name, provides[i]) && !strcmp(pEVR, providesEVR[i]))) 00276 continue; 00277 bingo = 0; 00278 break; 00279 } 00280 /*@=nullderef@*/ 00281 00282 exit: 00283 provides = hfd(provides, pnt); 00284 providesEVR = hfd(providesEVR, pvt); 00285 00286 if (bingo) { 00287 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE, 00288 &name, 1); 00289 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE, 00290 &pFlags, 1); 00291 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE, 00292 &pEVR, 1); 00293 } 00294 } 00295 00296 static void add_RPMTAG_SOURCERPM(Header h) 00297 { 00298 if (!headerIsEntry(h, RPMTAG_SOURCERPM) && !headerIsEntry(h, RPMTAG_SOURCEPACKAGE)) { 00299 /* we have no way to know if this is a srpm or an rpm with no SOURCERPM */ 00300 /* but since this is an old v3 rpm, we suppose it's not a srpm */ 00301 headerAddEntry(h, RPMTAG_SOURCERPM, RPM_STRING_TYPE, "\0", 1); 00302 } 00303 } 00304 00305 /* rpm v3 compatibility */ 00306 static void rpm3to4(Header h) { 00307 char * rpmversion; 00308 rpmTagType rpmversion_type; 00309 00310 (void) headerGetEntry(h, RPMTAG_RPMVERSION, NULL, (void **) &rpmversion, &rpmversion_type); 00311 00312 if ((!rpmversion) || rpmversion[0] < '4') { 00313 add_RPMTAG_SOURCERPM(h); 00314 providePackageNVR(h); 00315 compressFilelist(h); 00316 } 00317 headerFreeTag(h, (void *) rpmversion, rpmversion_type); 00318 return; 00319 } 00320 #endif 00321 00322 /*@-boundsread@*/ 00323 static int dncmp(const void * a, const void * b) 00324 /*@*/ 00325 { 00326 const char *const * first = a; 00327 const char *const * second = b; 00328 return strcmp(*first, *second); 00329 } 00330 /*@=boundsread@*/ 00331 00332 /*@-bounds@*/ 00337 static void compressFilelist(Header h) 00338 /*@modifies h @*/ 00339 { 00340 HGE_t hge = (HGE_t)headerGetEntryMinMemory; 00341 HAE_t hae = (HAE_t)headerAddEntry; 00342 HRE_t hre = (HRE_t)headerRemoveEntry; 00343 HFD_t hfd = headerFreeData; 00344 char ** fileNames; 00345 const char ** dirNames; 00346 const char ** baseNames; 00347 int_32 * dirIndexes; 00348 rpmTagType fnt; 00349 int count; 00350 int i, xx; 00351 int dirIndex = -1; 00352 00353 /* 00354 * This assumes the file list is already sorted, and begins with a 00355 * single '/'. That assumption isn't critical, but it makes things go 00356 * a bit faster. 00357 */ 00358 00359 if (headerIsEntry(h, RPMTAG_DIRNAMES)) { 00360 xx = hre(h, RPMTAG_OLDFILENAMES); 00361 return; /* Already converted. */ 00362 } 00363 00364 if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (void **) &fileNames, &count)) 00365 return; /* no file list */ 00366 if (fileNames == NULL || count <= 0) 00367 return; 00368 00369 dirNames = alloca(sizeof(*dirNames) * count); /* worst case */ 00370 baseNames = alloca(sizeof(*dirNames) * count); 00371 dirIndexes = alloca(sizeof(*dirIndexes) * count); 00372 00373 if (fileNames[0][0] != '/') { 00374 /* HACK. Source RPM, so just do things differently */ 00375 dirIndex = 0; 00376 dirNames[dirIndex] = ""; 00377 for (i = 0; i < count; i++) { 00378 dirIndexes[i] = dirIndex; 00379 baseNames[i] = fileNames[i]; 00380 } 00381 goto exit; 00382 } 00383 00384 /*@-branchstate@*/ 00385 for (i = 0; i < count; i++) { 00386 const char ** needle; 00387 char savechar; 00388 char * baseName; 00389 int len; 00390 00391 if (fileNames[i] == NULL) /* XXX can't happen */ 00392 continue; 00393 baseName = strrchr(fileNames[i], '/') + 1; 00394 len = baseName - fileNames[i]; 00395 needle = dirNames; 00396 savechar = *baseName; 00397 *baseName = '\0'; 00398 /*@-compdef@*/ 00399 if (dirIndex < 0 || 00400 (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) { 00401 char *s = alloca(len + 1); 00402 memcpy(s, fileNames[i], len + 1); 00403 s[len] = '\0'; 00404 dirIndexes[i] = ++dirIndex; 00405 dirNames[dirIndex] = s; 00406 } else 00407 dirIndexes[i] = needle - dirNames; 00408 /*@=compdef@*/ 00409 00410 *baseName = savechar; 00411 baseNames[i] = baseName; 00412 } 00413 /*@=branchstate@*/ 00414 00415 exit: 00416 if (count > 0) { 00417 xx = hae(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count); 00418 xx = hae(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE, 00419 baseNames, count); 00420 xx = hae(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE, 00421 dirNames, dirIndex + 1); 00422 } 00423 00424 fileNames = hfd(fileNames, fnt); 00425 00426 xx = hre(h, RPMTAG_OLDFILENAMES); 00427 } 00428 /*@=bounds@*/ 00429 00430 /* rpm v3 compatibility */ 00431 static void rpm3to4(Header h) { 00432 char * rpmversion; 00433 int_32 rpmversion_type; 00434 00435 (void) headerGetEntry(h, RPMTAG_RPMVERSION, NULL, (void **) &rpmversion, &rpmversion_type); 00436 00437 if ((!rpmversion) || rpmversion[0] < '4') { 00438 int *epoch; 00439 const char * name, *version, *release; 00440 const char *pEVR; 00441 char *p; 00442 int_32 pFlags = RPMSENSE_EQUAL; 00443 00444 if (headerNVR(h, &name, &version, &release) == 0) { 00445 pEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1); 00446 *p = '\0'; 00447 if (headerGetEntry(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) { 00448 sprintf(p, "%d:", *epoch); 00449 while (*p != '\0') 00450 p++; 00451 } 00452 (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release); 00453 00454 headerAddOrAppendEntry(h, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE, &name, 1); 00455 headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE, &pFlags, 1); 00456 headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE, &pEVR, 1); 00457 } 00458 compressFilelist(h); 00459 } 00460 headerFreeTag(h, (void *) rpmversion, rpmversion_type); 00461 return; 00462 } 00463 00464 void headerMergeLegacySigs(Header h, const Header sigh) 00465 { 00466 HFD_t hfd = (HFD_t) headerFreeData; 00467 HAE_t hae = (HAE_t) headerAddEntry; 00468 HeaderIterator hi; 00469 int_32 tag, type, count; 00470 const void * ptr; 00471 int xx; 00472 00473 for (hi = headerInitIterator(sigh); 00474 headerNextIterator(hi, &tag, &type, &ptr, &count); 00475 ptr = hfd(ptr, type)) 00476 { 00477 switch (tag) { 00478 /* XXX Translate legacy signature tag values. */ 00479 case RPMSIGTAG_SIZE: 00480 tag = RPMTAG_SIGSIZE; 00481 /*@switchbreak@*/ break; 00482 case RPMSIGTAG_LEMD5_1: 00483 tag = RPMTAG_SIGLEMD5_1; 00484 /*@switchbreak@*/ break; 00485 case RPMSIGTAG_PGP: 00486 tag = RPMTAG_SIGPGP; 00487 /*@switchbreak@*/ break; 00488 case RPMSIGTAG_LEMD5_2: 00489 tag = RPMTAG_SIGLEMD5_2; 00490 /*@switchbreak@*/ break; 00491 case RPMSIGTAG_MD5: 00492 tag = RPMTAG_SIGMD5; 00493 /*@switchbreak@*/ break; 00494 case RPMSIGTAG_GPG: 00495 tag = RPMTAG_SIGGPG; 00496 /*@switchbreak@*/ break; 00497 case RPMSIGTAG_PGP5: 00498 tag = RPMTAG_SIGPGP5; 00499 /*@switchbreak@*/ break; 00500 case RPMSIGTAG_PAYLOADSIZE: 00501 tag = RPMTAG_ARCHIVESIZE; 00502 /*@switchbreak@*/ break; 00503 case RPMSIGTAG_SHA1: 00504 case RPMSIGTAG_DSA: 00505 case RPMSIGTAG_RSA: 00506 default: 00507 if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE)) 00508 continue; 00509 /*@switchbreak@*/ break; 00510 } 00511 if (ptr == NULL) continue; /* XXX can't happen */ 00512 if (!headerIsEntry(h, tag)) { 00513 if (hdrchkType(type)) 00514 continue; 00515 if (count < 0 || hdrchkData(count)) 00516 continue; 00517 switch(type) { 00518 case RPM_NULL_TYPE: 00519 continue; 00520 /*@notreached@*/ /*@switchbreak@*/ break; 00521 case RPM_CHAR_TYPE: 00522 case RPM_INT8_TYPE: 00523 case RPM_INT16_TYPE: 00524 case RPM_INT32_TYPE: 00525 if (count != 1) 00526 continue; 00527 /*@switchbreak@*/ break; 00528 case RPM_STRING_TYPE: 00529 case RPM_BIN_TYPE: 00530 if (count >= 16*1024) 00531 continue; 00532 /*@switchbreak@*/ break; 00533 case RPM_STRING_ARRAY_TYPE: 00534 case RPM_I18NSTRING_TYPE: 00535 continue; 00536 /*@notreached@*/ /*@switchbreak@*/ break; 00537 } 00538 xx = hae(h, tag, type, ptr, count); 00539 } 00540 } 00541 hi = headerFreeIterator(hi); 00542 } 00543 00544 Header headerRegenSigHeader(const Header h, int noArchiveSize) 00545 { 00546 HFD_t hfd = (HFD_t) headerFreeData; 00547 Header sigh = rpmNewSignature(); 00548 HeaderIterator hi; 00549 int_32 tag, stag, type, count; 00550 const void * ptr; 00551 int xx; 00552 00553 for (hi = headerInitIterator(h); 00554 headerNextIterator(hi, &tag, &type, &ptr, &count); 00555 ptr = hfd(ptr, type)) 00556 { 00557 switch (tag) { 00558 /* XXX Translate legacy signature tag values. */ 00559 case RPMTAG_SIGSIZE: 00560 stag = RPMSIGTAG_SIZE; 00561 /*@switchbreak@*/ break; 00562 case RPMTAG_SIGLEMD5_1: 00563 stag = RPMSIGTAG_LEMD5_1; 00564 /*@switchbreak@*/ break; 00565 case RPMTAG_SIGPGP: 00566 stag = RPMSIGTAG_PGP; 00567 /*@switchbreak@*/ break; 00568 case RPMTAG_SIGLEMD5_2: 00569 stag = RPMSIGTAG_LEMD5_2; 00570 /*@switchbreak@*/ break; 00571 case RPMTAG_SIGMD5: 00572 stag = RPMSIGTAG_MD5; 00573 /*@switchbreak@*/ break; 00574 case RPMTAG_SIGGPG: 00575 stag = RPMSIGTAG_GPG; 00576 /*@switchbreak@*/ break; 00577 case RPMTAG_SIGPGP5: 00578 stag = RPMSIGTAG_PGP5; 00579 /*@switchbreak@*/ break; 00580 case RPMTAG_ARCHIVESIZE: 00581 /* XXX rpm-4.1 and later has archive size in signature header. */ 00582 if (noArchiveSize) 00583 continue; 00584 stag = RPMSIGTAG_PAYLOADSIZE; 00585 /*@switchbreak@*/ break; 00586 case RPMTAG_SHA1HEADER: 00587 case RPMTAG_DSAHEADER: 00588 case RPMTAG_RSAHEADER: 00589 default: 00590 if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE)) 00591 continue; 00592 stag = tag; 00593 /*@switchbreak@*/ break; 00594 } 00595 if (ptr == NULL) continue; /* XXX can't happen */ 00596 if (!headerIsEntry(sigh, stag)) 00597 xx = headerAddEntry(sigh, stag, type, ptr, count); 00598 } 00599 hi = headerFreeIterator(hi); 00600 return sigh; 00601 } 00602 00608 static int rpmtsStashKeyid(rpmts ts) 00609 /*@globals nextkeyid, nkeyids, keyids @*/ 00610 /*@modifies nextkeyid, nkeyids, keyids @*/ 00611 { 00612 const void * sig = rpmtsSig(ts); 00613 pgpDig dig = rpmtsDig(ts); 00614 pgpDigParams sigp = rpmtsSignature(ts); 00615 unsigned int keyid; 00616 int i; 00617 00618 if (sig == NULL || dig == NULL || sigp == NULL) 00619 return 0; 00620 00621 keyid = pgpGrab(sigp->signid+4, 4); 00622 if (keyid == 0) 00623 return 0; 00624 00625 if (keyids != NULL) 00626 for (i = 0; i < nkeyids; i++) { 00627 /*@-boundsread@*/ 00628 if (keyid == keyids[i]) 00629 return 1; 00630 /*@=boundsread@*/ 00631 } 00632 00633 if (nkeyids < nkeyids_max) { 00634 nkeyids++; 00635 keyids = xrealloc(keyids, nkeyids * sizeof(*keyids)); 00636 } 00637 /*@-boundswrite@*/ 00638 if (keyids) /* XXX can't happen */ 00639 keyids[nextkeyid] = keyid; 00640 /*@=boundswrite@*/ 00641 nextkeyid++; 00642 nextkeyid %= nkeyids_max; 00643 00644 return 0; 00645 } 00646 00647 int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate) 00648 { 00649 /*@-castexpose@*/ 00650 entryInfo pe = (entryInfo) pev; 00651 /*@=castexpose@*/ 00652 entryInfo info = iv; 00653 int i; 00654 00655 /*@-boundsread@*/ 00656 for (i = 0; i < il; i++) { 00657 info->tag = ntohl(pe[i].tag); 00658 info->type = ntohl(pe[i].type); 00659 info->offset = ntohl(pe[i].offset); 00660 if (negate) 00661 info->offset = -info->offset; 00662 info->count = ntohl(pe[i].count); 00663 00664 if (hdrchkType(info->type)) 00665 return i; 00666 if (hdrchkAlign(info->type, info->offset)) 00667 return i; 00668 if (!negate && hdrchkRange(dl, info->offset)) 00669 return i; 00670 if (hdrchkData(info->count)) 00671 return i; 00672 00673 } 00674 /*@=boundsread@*/ 00675 return -1; 00676 } 00677 00691 rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, const char ** msg) 00692 { 00693 pgpDig dig; 00694 unsigned char buf[8*BUFSIZ]; 00695 int_32 * ei = (int_32 *) uh; 00696 /*@-boundsread@*/ 00697 int_32 il = ntohl(ei[0]); 00698 int_32 dl = ntohl(ei[1]); 00699 /*@-castexpose@*/ 00700 entryInfo pe = (entryInfo) &ei[2]; 00701 /*@=castexpose@*/ 00702 /*@=boundsread@*/ 00703 int_32 ildl[2]; 00704 int_32 pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl; 00705 unsigned char * dataStart = (unsigned char *) (pe + il); 00706 indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry)); 00707 entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info)); 00708 const void * sig = NULL; 00709 const char * b; 00710 rpmVSFlags vsflags = rpmtsVSFlags(ts); 00711 int siglen = 0; 00712 int blen; 00713 size_t nb; 00714 int_32 ril = 0; 00715 unsigned char * regionEnd = NULL; 00716 rpmRC rc = RPMRC_FAIL; /* assume failure */ 00717 int xx; 00718 int i; 00719 static int hclvl; 00720 00721 hclvl++; 00722 /*@-boundswrite@*/ 00723 buf[0] = '\0'; 00724 /*@=boundswrite@*/ 00725 00726 /* Is the blob the right size? */ 00727 if (uc > 0 && pvlen != uc) { 00728 (void) snprintf(buf, sizeof(buf), 00729 _("blob size(%d): BAD, 8 + 16 * il(%d) + dl(%d)\n"), 00730 (int)uc, (int)il, (int)dl); 00731 goto exit; 00732 } 00733 00734 /* Check (and convert) the 1st tag element. */ 00735 xx = headerVerifyInfo(1, dl, pe, &entry->info, 0); 00736 if (xx != -1) { 00737 (void) snprintf(buf, sizeof(buf), 00738 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"), 00739 0, entry->info.tag, entry->info.type, 00740 entry->info.offset, entry->info.count); 00741 goto exit; 00742 } 00743 00744 /* Is there an immutable header region tag? */ 00745 /*@-sizeoftype@*/ 00746 if (!(entry->info.tag == RPMTAG_HEADERIMMUTABLE 00747 && entry->info.type == RPM_BIN_TYPE 00748 && entry->info.count == REGION_TAG_COUNT)) 00749 { 00750 rc = RPMRC_NOTFOUND; 00751 goto exit; 00752 } 00753 /*@=sizeoftype@*/ 00754 00755 /* Is the offset within the data area? */ 00756 if (entry->info.offset >= dl) { 00757 (void) snprintf(buf, sizeof(buf), 00758 _("region offset: BAD, tag %d type %d offset %d count %d\n"), 00759 entry->info.tag, entry->info.type, 00760 entry->info.offset, entry->info.count); 00761 goto exit; 00762 } 00763 00764 /* Is there an immutable header region tag trailer? */ 00765 regionEnd = dataStart + entry->info.offset; 00766 /*@-sizeoftype@*/ 00767 /*@-bounds@*/ 00768 (void) memcpy(info, regionEnd, REGION_TAG_COUNT); 00769 /*@=bounds@*/ 00770 regionEnd += REGION_TAG_COUNT; 00771 00772 xx = headerVerifyInfo(1, dl, info, &entry->info, 1); 00773 if (xx != -1 || 00774 !(entry->info.tag == RPMTAG_HEADERIMMUTABLE 00775 && entry->info.type == RPM_BIN_TYPE 00776 && entry->info.count == REGION_TAG_COUNT)) 00777 { 00778 (void) snprintf(buf, sizeof(buf), 00779 _("region trailer: BAD, tag %d type %d offset %d count %d\n"), 00780 entry->info.tag, entry->info.type, 00781 entry->info.offset, entry->info.count); 00782 goto exit; 00783 } 00784 /*@=sizeoftype@*/ 00785 /*@-boundswrite@*/ 00786 memset(info, 0, sizeof(*info)); 00787 /*@=boundswrite@*/ 00788 00789 /* Is the no. of tags in the region less than the total no. of tags? */ 00790 ril = entry->info.offset/sizeof(*pe); 00791 if ((entry->info.offset % sizeof(*pe)) || ril > il) { 00792 (void) snprintf(buf, sizeof(buf), 00793 _("region size: BAD, ril(%d) > il(%d)\n"), ril, il); 00794 goto exit; 00795 } 00796 00797 /* Find a header-only digest/signature tag. */ 00798 for (i = ril; i < il; i++) { 00799 xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0); 00800 if (xx != -1) { 00801 (void) snprintf(buf, sizeof(buf), 00802 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"), 00803 i, entry->info.tag, entry->info.type, 00804 entry->info.offset, entry->info.count); 00805 goto exit; 00806 } 00807 00808 switch (entry->info.tag) { 00809 case RPMTAG_SHA1HEADER: 00810 if (vsflags & RPMVSF_NOSHA1HEADER) 00811 /*@switchbreak@*/ break; 00812 blen = 0; 00813 /*@-boundsread@*/ 00814 for (b = dataStart + entry->info.offset; *b != '\0'; b++) { 00815 if (strchr("0123456789abcdefABCDEF", *b) == NULL) 00816 /*@innerbreak@*/ break; 00817 blen++; 00818 } 00819 if (entry->info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40) 00820 { 00821 (void) snprintf(buf, sizeof(buf), _("hdr SHA1: BAD, not hex\n")); 00822 goto exit; 00823 } 00824 /*@=boundsread@*/ 00825 if (info->tag == 0) { 00826 /*@-boundswrite@*/ 00827 *info = entry->info; /* structure assignment */ 00828 /*@=boundswrite@*/ 00829 siglen = blen + 1; 00830 } 00831 /*@switchbreak@*/ break; 00832 case RPMTAG_RSAHEADER: 00833 if (vsflags & RPMVSF_NORSAHEADER) 00834 /*@switchbreak@*/ break; 00835 if (entry->info.type != RPM_BIN_TYPE) { 00836 (void) snprintf(buf, sizeof(buf), _("hdr RSA: BAD, not binary\n")); 00837 goto exit; 00838 } 00839 /*@-boundswrite@*/ 00840 *info = entry->info; /* structure assignment */ 00841 /*@=boundswrite@*/ 00842 siglen = info->count; 00843 /*@switchbreak@*/ break; 00844 case RPMTAG_DSAHEADER: 00845 if (vsflags & RPMVSF_NODSAHEADER) 00846 /*@switchbreak@*/ break; 00847 if (entry->info.type != RPM_BIN_TYPE) { 00848 (void) snprintf(buf, sizeof(buf), _("hdr DSA: BAD, not binary\n")); 00849 goto exit; 00850 } 00851 /*@-boundswrite@*/ 00852 *info = entry->info; /* structure assignment */ 00853 /*@=boundswrite@*/ 00854 siglen = info->count; 00855 /*@switchbreak@*/ break; 00856 default: 00857 /*@switchbreak@*/ break; 00858 } 00859 } 00860 rc = RPMRC_NOTFOUND; 00861 00862 exit: 00863 /* Return determined RPMRC_OK/RPMRC_FAIL conditions. */ 00864 if (rc != RPMRC_NOTFOUND) { 00865 /*@-boundswrite@*/ 00866 buf[sizeof(buf)-1] = '\0'; 00867 if (msg) *msg = xstrdup(buf); 00868 /*@=boundswrite@*/ 00869 hclvl--; 00870 return rc; 00871 } 00872 00873 /* If no header-only digest/signature, then do simple sanity check. */ 00874 if (info->tag == 0) { 00875 verifyinfo_exit: 00876 xx = headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0); 00877 if (xx != -1) { 00878 (void) snprintf(buf, sizeof(buf), 00879 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"), 00880 xx+1, entry->info.tag, entry->info.type, 00881 entry->info.offset, entry->info.count); 00882 rc = RPMRC_FAIL; 00883 } else { 00884 (void) snprintf(buf, sizeof(buf), "Header sanity check: OK\n"); 00885 rc = RPMRC_OK; 00886 } 00887 /*@-boundswrite@*/ 00888 buf[sizeof(buf)-1] = '\0'; 00889 if (msg) *msg = xstrdup(buf); 00890 /*@=boundswrite@*/ 00891 hclvl--; 00892 return rc; 00893 } 00894 00895 /* Verify header-only digest/signature. */ 00896 dig = rpmtsDig(ts); 00897 if (dig == NULL) 00898 goto verifyinfo_exit; 00899 dig->nbytes = 0; 00900 00901 /*@-boundsread@*/ 00902 sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen); 00903 /*@=boundsread@*/ 00904 (void) rpmtsSetSig(ts, info->tag, info->type, sig, info->count); 00905 00906 switch (info->tag) { 00907 case RPMTAG_RSAHEADER: 00908 /* Parse the parameters from the OpenPGP packets that will be needed. */ 00909 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug())); 00910 if (dig->signature.version != 3 && dig->signature.version != 4) { 00911 rpmMessage(RPMMESS_ERROR, 00912 _("skipping header with unverifiable V%u signature\n"), 00913 dig->signature.version); 00914 rpmtsCleanDig(ts); 00915 rc = RPMRC_FAIL; 00916 goto exit; 00917 } 00918 00919 ildl[0] = htonl(ril); 00920 ildl[1] = (regionEnd - dataStart); 00921 ildl[1] = htonl(ildl[1]); 00922 00923 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0); 00924 dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE); 00925 00926 b = (unsigned char *) header_magic; 00927 nb = sizeof(header_magic); 00928 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb); 00929 dig->nbytes += nb; 00930 00931 b = (unsigned char *) ildl; 00932 nb = sizeof(ildl); 00933 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb); 00934 dig->nbytes += nb; 00935 00936 b = (unsigned char *) pe; 00937 nb = (htonl(ildl[0]) * sizeof(*pe)); 00938 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb); 00939 dig->nbytes += nb; 00940 00941 b = (unsigned char *) dataStart; 00942 nb = htonl(ildl[1]); 00943 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb); 00944 dig->nbytes += nb; 00945 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes); 00946 00947 break; 00948 case RPMTAG_DSAHEADER: 00949 /* Parse the parameters from the OpenPGP packets that will be needed. */ 00950 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug())); 00951 if (dig->signature.version != 3 && dig->signature.version != 4) { 00952 rpmMessage(RPMMESS_ERROR, 00953 _("skipping header with unverifiable V%u signature\n"), 00954 dig->signature.version); 00955 rpmtsCleanDig(ts); 00956 rc = RPMRC_FAIL; 00957 goto exit; 00958 } 00959 /*@fallthrough@*/ 00960 case RPMTAG_SHA1HEADER: 00961 /*@-boundswrite@*/ 00962 ildl[0] = htonl(ril); 00963 ildl[1] = (regionEnd - dataStart); 00964 ildl[1] = htonl(ildl[1]); 00965 /*@=boundswrite@*/ 00966 00967 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0); 00968 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE); 00969 00970 b = (unsigned char *) header_magic; 00971 nb = sizeof(header_magic); 00972 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb); 00973 dig->nbytes += nb; 00974 00975 b = (unsigned char *) ildl; 00976 nb = sizeof(ildl); 00977 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb); 00978 dig->nbytes += nb; 00979 00980 b = (unsigned char *) pe; 00981 nb = (htonl(ildl[0]) * sizeof(*pe)); 00982 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb); 00983 dig->nbytes += nb; 00984 00985 b = (unsigned char *) dataStart; 00986 nb = htonl(ildl[1]); 00987 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb); 00988 dig->nbytes += nb; 00989 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes); 00990 00991 break; 00992 default: 00993 sig = _free(sig); 00994 break; 00995 } 00996 00997 /*@-boundswrite@*/ 00998 buf[0] = '\0'; 00999 /*@=boundswrite@*/ 01000 rc = rpmVerifySignature(ts, buf); 01001 01002 /*@-boundswrite@*/ 01003 buf[sizeof(buf)-1] = '\0'; 01004 if (msg) *msg = xstrdup(buf); 01005 /*@=boundswrite@*/ 01006 01007 /* XXX headerCheck can recurse, free info only at top level. */ 01008 if (hclvl == 1) 01009 rpmtsCleanDig(ts); 01010 if (info->tag == RPMTAG_SHA1HEADER) 01011 sig = _free(sig); 01012 hclvl--; 01013 return rc; 01014 } 01015 01016 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, const char ** msg) 01017 { 01018 char buf[BUFSIZ]; 01019 int_32 block[4]; 01020 int_32 il; 01021 int_32 dl; 01022 int_32 * ei = NULL; 01023 size_t uc; 01024 size_t startoff; 01025 int_32 nb; 01026 Header h = NULL; 01027 const char * origin = NULL; 01028 rpmRC rc = RPMRC_FAIL; /* assume failure */ 01029 int xx; 01030 01031 /*@-boundswrite@*/ 01032 buf[0] = '\0'; 01033 01034 if (hdrp) 01035 *hdrp = NULL; 01036 if (msg) 01037 *msg = NULL; 01038 /*@=boundswrite@*/ 01039 01040 startoff = fd->stats->ops[FDSTAT_READ].bytes; 01041 memset(block, 0, sizeof(block)); 01042 if ((xx = timedRead(fd, (char *)block, sizeof(block))) != sizeof(block)) { 01043 (void) snprintf(buf, sizeof(buf), 01044 _("hdr size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx); 01045 goto exit; 01046 } 01047 if (memcmp(block, header_magic, sizeof(header_magic))) { 01048 (void) snprintf(buf, sizeof(buf), _("hdr magic: BAD\n")); 01049 goto exit; 01050 } 01051 /*@-boundsread@*/ 01052 il = ntohl(block[2]); 01053 /*@=boundsread@*/ 01054 if (hdrchkTags(il)) { 01055 (void) snprintf(buf, sizeof(buf), 01056 _("hdr tags: BAD, no. of tags(%d) out of range\n"), il); 01057 01058 goto exit; 01059 } 01060 /*@-boundsread@*/ 01061 dl = ntohl(block[3]); 01062 /*@=boundsread@*/ 01063 if (hdrchkData(dl)) { 01064 (void) snprintf(buf, sizeof(buf), 01065 _("hdr data: BAD, no. of bytes(%d) out of range\n"), dl); 01066 goto exit; 01067 } 01068 01069 /*@-sizeoftype@*/ 01070 nb = (il * sizeof(struct entryInfo_s)) + dl; 01071 /*@=sizeoftype@*/ 01072 uc = sizeof(il) + sizeof(dl) + nb; 01073 ei = xmalloc(uc); 01074 /*@-bounds@*/ 01075 ei[0] = block[2]; 01076 ei[1] = block[3]; 01077 if ((xx = timedRead(fd, (char *)&ei[2], nb)) != nb) { 01078 (void) snprintf(buf, sizeof(buf), 01079 _("hdr blob(%d): BAD, read returned %d\n"), nb, xx); 01080 goto exit; 01081 } 01082 /*@=bounds@*/ 01083 01084 /* Sanity check header tags */ 01085 rc = headerCheck(ts, ei, uc, msg); 01086 if (rc != RPMRC_OK) 01087 goto exit; 01088 01089 /* OK, blob looks sane, load the header. */ 01090 h = headerLoad(ei); 01091 if (h == NULL) { 01092 (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n")); 01093 goto exit; 01094 } 01095 h->flags |= HEADERFLAG_ALLOCATED; 01096 ei = NULL; /* XXX will be freed with header */ 01097 01098 /* Save the opened path as the header origin. */ 01099 origin = fdGetOPath(fd); 01100 if (origin != NULL) { 01101 const char * lpath = NULL; 01102 int ut = urlPath(origin, &lpath); 01103 ut = ut; /* XXX keep gcc quiet. */ 01104 if (lpath && *lpath != '/') { 01105 char * rpath = Realpath(origin, NULL); 01106 (void) headerSetOrigin(h, rpath); 01107 rpath = _free(rpath); 01108 } else 01109 (void) headerSetOrigin(h, origin); 01110 } 01111 { struct stat * st = headerGetStatbuf(h); 01112 int saveno = errno; 01113 (void) fstat(Fileno(fd), st); 01114 errno = saveno; 01115 } 01116 (void) headerSetStartOff(h, startoff); 01117 (void) headerSetEndOff(h, fd->stats->ops[FDSTAT_READ].bytes); 01118 01119 exit: 01120 /*@-boundswrite@*/ 01121 if (hdrp && h && rc == RPMRC_OK) 01122 *hdrp = headerLink(h); 01123 /*@=boundswrite@*/ 01124 ei = _free(ei); 01125 h = headerFree(h); 01126 01127 /*@-boundswrite@*/ 01128 if (msg != NULL && *msg == NULL && buf[0] != '\0') { 01129 buf[sizeof(buf)-1] = '\0'; 01130 *msg = xstrdup(buf); 01131 } 01132 /*@=boundswrite@*/ 01133 01134 return rc; 01135 } 01136 01137 /*@-bounds@*/ /* LCL: segfault */ 01138 rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp) 01139 { 01140 pgpDig dig; 01141 byte buf[8*BUFSIZ]; 01142 ssize_t count; 01143 struct rpmlead * l = alloca(sizeof(*l)); 01144 Header sigh = NULL; 01145 int_32 sigtag; 01146 int_32 sigtype; 01147 const void * sig; 01148 int_32 siglen; 01149 rpmtsOpX opx; 01150 size_t nb; 01151 Header h = NULL; 01152 const char * msg; 01153 rpmVSFlags vsflags; 01154 rpmRC rc = RPMRC_FAIL; /* assume failure */ 01155 rpmop opsave = memset(alloca(sizeof(*opsave)), 0, sizeof(*opsave)); 01156 int xx; 01157 int i; 01158 01159 if (hdrp) *hdrp = NULL; 01160 01161 #ifdef DYING 01162 { struct stat st; 01163 /*@-boundswrite@*/ 01164 memset(&st, 0, sizeof(st)); 01165 /*@=boundswrite@*/ 01166 (void) fstat(Fileno(fd), &st); 01167 /* if fd points to a socket, pipe, etc, st.st_size is *always* zero */ 01168 if (S_ISREG(st.st_mode) && st.st_size < sizeof(*l)) { 01169 rc = RPMRC_NOTFOUND; 01170 goto exit; 01171 } 01172 } 01173 #endif 01174 01175 /* Snapshot current I/O counters (cached persistent I/O reuses counters) */ 01176 (void) rpmswAdd(opsave, fdstat_op(fd, FDSTAT_READ)); 01177 01178 memset(l, 0, sizeof(*l)); 01179 rc = readLead(fd, l); 01180 if (rc != RPMRC_OK) 01181 goto exit; 01182 01183 switch (l->major) { 01184 case 1: 01185 rpmError(RPMERR_NEWPACKAGE, 01186 _("packaging version 1 is not supported by this version of RPM\n")); 01187 rc = RPMRC_NOTFOUND; 01188 goto exit; 01189 /*@notreached@*/ break; 01190 case 2: 01191 case 3: 01192 case 4: 01193 break; 01194 default: 01195 rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 " 01196 "is supported by this version of RPM\n")); 01197 rc = RPMRC_NOTFOUND; 01198 goto exit; 01199 /*@notreached@*/ break; 01200 } 01201 01202 /* Read the signature header. */ 01203 msg = NULL; 01204 rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg); 01205 switch (rc) { 01206 default: 01207 rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed: %s"), fn, 01208 (msg && *msg ? msg : "\n")); 01209 msg = _free(msg); 01210 goto exit; 01211 /*@notreached@*/ break; 01212 case RPMRC_OK: 01213 if (sigh == NULL) { 01214 rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn); 01215 rc = RPMRC_FAIL; 01216 goto exit; 01217 } 01218 break; 01219 } 01220 msg = _free(msg); 01221 01222 #define _chk(_mask) (sigtag == 0 && !(vsflags & (_mask))) 01223 01224 /* 01225 * Figger the most effective available signature. 01226 * Prefer signatures over digests, then header-only over header+payload. 01227 * DSA will be preferred over RSA if both exist because tested first. 01228 * Note that NEEDPAYLOAD prevents header+payload signatures and digests. 01229 */ 01230 sigtag = 0; 01231 opx = 0; 01232 vsflags = rpmtsVSFlags(ts); 01233 if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_DSA)) { 01234 sigtag = RPMSIGTAG_DSA; 01235 } else 01236 if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_RSA)) { 01237 sigtag = RPMSIGTAG_RSA; 01238 } else 01239 if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD) && 01240 headerIsEntry(sigh, RPMSIGTAG_GPG)) 01241 { 01242 sigtag = RPMSIGTAG_GPG; 01243 fdInitDigest(fd, PGPHASHALGO_SHA1, 0); 01244 opx = RPMTS_OP_SIGNATURE; 01245 } else 01246 if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD) && 01247 headerIsEntry(sigh, RPMSIGTAG_PGP)) 01248 { 01249 sigtag = RPMSIGTAG_PGP; 01250 fdInitDigest(fd, PGPHASHALGO_MD5, 0); 01251 opx = RPMTS_OP_SIGNATURE; 01252 } else 01253 if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, RPMSIGTAG_SHA1)) { 01254 sigtag = RPMSIGTAG_SHA1; 01255 } else 01256 if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) && 01257 headerIsEntry(sigh, RPMSIGTAG_MD5)) 01258 { 01259 sigtag = RPMSIGTAG_MD5; 01260 fdInitDigest(fd, PGPHASHALGO_MD5, 0); 01261 opx = RPMTS_OP_DIGEST; 01262 } 01263 01264 /* Read the metadata, computing digest(s) on the fly. */ 01265 h = NULL; 01266 msg = NULL; 01267 01268 /* XXX stats will include header i/o and setup overhead. */ 01269 /* XXX repackaged packages have appended tags, legacy dig/sig check fails */ 01270 if (opx > 0) 01271 (void) rpmswEnter(rpmtsOp(ts, opx), 0); 01272 /*@-type@*/ /* XXX arrow access of non-pointer (FDSTAT_t) */ 01273 nb = -fd->stats->ops[FDSTAT_READ].bytes; 01274 rc = rpmReadHeader(ts, fd, &h, &msg); 01275 nb += fd->stats->ops[FDSTAT_READ].bytes; 01276 /*@=type@*/ 01277 if (opx > 0) 01278 (void) rpmswExit(rpmtsOp(ts, opx), nb); 01279 01280 if (rc != RPMRC_OK || h == NULL) { 01281 rpmError(RPMERR_FREAD, _("%s: headerRead failed: %s"), fn, 01282 (msg && *msg ? msg : "\n")); 01283 msg = _free(msg); 01284 goto exit; 01285 } 01286 msg = _free(msg); 01287 01288 /* Any digests or signatures to check? */ 01289 if (sigtag == 0) { 01290 rc = RPMRC_OK; 01291 goto exit; 01292 } 01293 01294 dig = rpmtsDig(ts); 01295 if (dig == NULL) { 01296 rc = RPMRC_FAIL; 01297 goto exit; 01298 } 01299 dig->nbytes = 0; 01300 01301 /* Retrieve the tag parameters from the signature header. */ 01302 sig = NULL; 01303 xx = headerGetEntry(sigh, sigtag, &sigtype, (void **) &sig, &siglen); 01304 if (sig == NULL) { 01305 rc = RPMRC_FAIL; 01306 goto exit; 01307 } 01308 (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen); 01309 01310 switch (sigtag) { 01311 case RPMSIGTAG_RSA: 01312 /* Parse the parameters from the OpenPGP packets that will be needed. */ 01313 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug())); 01314 if (dig->signature.version != 3 && dig->signature.version != 4) { 01315 rpmMessage(RPMMESS_ERROR, 01316 _("skipping package %s with unverifiable V%u signature\n"), 01317 fn, dig->signature.version); 01318 rc = RPMRC_FAIL; 01319 goto exit; 01320 } 01321 { void * uh = NULL; 01322 int_32 uht; 01323 int_32 uhc; 01324 01325 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)) 01326 break; 01327 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0); 01328 dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE); 01329 (void) rpmDigestUpdate(dig->hdrmd5ctx, header_magic, sizeof(header_magic)); 01330 dig->nbytes += sizeof(header_magic); 01331 (void) rpmDigestUpdate(dig->hdrmd5ctx, uh, uhc); 01332 dig->nbytes += uhc; 01333 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes); 01334 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */ 01335 uh = headerFreeData(uh, uht); 01336 } break; 01337 case RPMSIGTAG_DSA: 01338 /* Parse the parameters from the OpenPGP packets that will be needed. */ 01339 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug())); 01340 if (dig->signature.version != 3 && dig->signature.version != 4) { 01341 rpmMessage(RPMMESS_ERROR, 01342 _("skipping package %s with unverifiable V%u signature\n"), 01343 fn, dig->signature.version); 01344 rc = RPMRC_FAIL; 01345 goto exit; 01346 } 01347 /*@fallthrough@*/ 01348 case RPMSIGTAG_SHA1: 01349 { void * uh = NULL; 01350 int_32 uht; 01351 int_32 uhc; 01352 01353 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)) 01354 break; 01355 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0); 01356 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE); 01357 (void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic)); 01358 dig->nbytes += sizeof(header_magic); 01359 (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc); 01360 dig->nbytes += uhc; 01361 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes); 01362 if (sigtag == RPMSIGTAG_SHA1) 01363 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */ 01364 uh = headerFreeData(uh, uht); 01365 } break; 01366 case RPMSIGTAG_GPG: 01367 case RPMSIGTAG_PGP5: /* XXX legacy */ 01368 case RPMSIGTAG_PGP: 01369 /* Parse the parameters from the OpenPGP packets that will be needed. */ 01370 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug())); 01371 01372 if (dig->signature.version != 3 && dig->signature.version != 4) { 01373 rpmMessage(RPMMESS_ERROR, 01374 _("skipping package %s with unverifiable V%u signature\n"), 01375 fn, dig->signature.version); 01376 rc = RPMRC_FAIL; 01377 goto exit; 01378 } 01379 /*@fallthrough@*/ 01380 case RPMSIGTAG_MD5: 01381 /* Legacy signatures need the compressed payload in the digest too. */ 01382 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0); 01383 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0) 01384 dig->nbytes += count; 01385 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes); 01386 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--; /* XXX one too many */ 01387 dig->nbytes += nb; /* XXX include size of header blob. */ 01388 if (count < 0) { 01389 rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"), 01390 fn, Fstrerror(fd)); 01391 rc = RPMRC_FAIL; 01392 goto exit; 01393 } 01394 01395 /* XXX Steal the digest-in-progress from the file handle. */ 01396 for (i = fd->ndigests - 1; i >= 0; i--) { 01397 FDDIGEST_t fddig = fd->digests + i; 01398 if (fddig->hashctx != NULL) 01399 switch (fddig->hashalgo) { 01400 case PGPHASHALGO_MD5: 01401 dig->md5ctx = fddig->hashctx; 01402 fddig->hashctx = NULL; 01403 /*@switchbreak@*/ break; 01404 case PGPHASHALGO_SHA1: 01405 case PGPHASHALGO_RIPEMD160: 01406 #if HAVE_BEECRYPT_API_H 01407 case PGPHASHALGO_SHA256: 01408 case PGPHASHALGO_SHA384: 01409 case PGPHASHALGO_SHA512: 01410 #endif 01411 dig->sha1ctx = fddig->hashctx; 01412 fddig->hashctx = NULL; 01413 /*@switchbreak@*/ break; 01414 default: 01415 /*@switchbreak@*/ break; 01416 } 01417 } 01418 break; 01419 } 01420 01423 /*@-boundswrite@*/ 01424 buf[0] = '\0'; 01425 /*@=boundswrite@*/ 01426 rc = rpmVerifySignature(ts, buf); 01427 switch (rc) { 01428 case RPMRC_OK: /* Signature is OK. */ 01429 rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf); 01430 break; 01431 case RPMRC_NOTTRUSTED: /* Signature is OK, but key is not trusted. */ 01432 case RPMRC_NOKEY: /* Public key is unavailable. */ 01433 /* XXX Print NOKEY/NOTTRUSTED warning only once. */ 01434 { int lvl = (rpmtsStashKeyid(ts) ? RPMMESS_DEBUG : RPMMESS_WARNING); 01435 rpmMessage(lvl, "%s: %s", fn, buf); 01436 } break; 01437 case RPMRC_NOTFOUND: /* Signature is unknown type. */ 01438 rpmMessage(RPMMESS_WARNING, "%s: %s", fn, buf); 01439 break; 01440 default: 01441 case RPMRC_FAIL: /* Signature does not verify. */ 01442 rpmMessage(RPMMESS_ERROR, "%s: %s", fn, buf); 01443 break; 01444 } 01445 01446 exit: 01447 if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) { 01448 01449 /* Append (and remap) signature tags to the metadata. */ 01450 headerMergeLegacySigs(h, sigh); 01451 01452 #if defined(RPM_VENDOR_MANDRIVA) 01453 rpm3to4(h); 01454 #endif 01455 01456 rpm3to4(h); 01457 01458 /* Bump reference count for return. */ 01459 /*@-boundswrite@*/ 01460 *hdrp = headerLink(h); 01461 /*@=boundswrite@*/ 01462 } 01463 h = headerFree(h); 01464 01465 /* Accumulate time reading package header. */ 01466 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_READHDR), 01467 fdstat_op(fd, FDSTAT_READ)); 01468 (void) rpmswSub(rpmtsOp(ts, RPMTS_OP_READHDR), 01469 opsave); 01470 01471 rpmtsCleanDig(ts); 01472 sigh = rpmFreeSignature(sigh); 01473 return rc; 01474 } 01475 /*@=bounds@*/