00001
00005 #include "system.h"
00006
00007 #include <netinet/in.h>
00008
00009 #include <rpmio_internal.h>
00010 #include <rpmlib.h>
00011
00012 #include "rpmts.h"
00013 #include "rpmevr.h"
00014
00015 #include "misc.h"
00016 #include "rpmlead.h"
00017
00018 #include "header_internal.h"
00019 #include "signature.h"
00020 #include "debug.h"
00021
00022 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 static int _print_pkts = 0;
00033
00034
00035 static unsigned int nkeyids_max = 256;
00036
00037 static unsigned int nkeyids = 0;
00038
00039 static unsigned int nextkeyid = 0;
00040
00041 static unsigned int * keyids;
00042
00043
00044 static unsigned char header_magic[8] = {
00045 0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
00046 };
00047
00051
00052 static int typeAlign[16] = {
00053 1,
00054 1,
00055 1,
00056 2,
00057 4,
00058 8,
00059 1,
00060 1,
00061 1,
00062 1,
00063 0,
00064 0,
00065 0,
00066 0,
00067 0,
00068 0
00069 };
00070
00075 #define hdrchkTags(_ntags) ((_ntags) & 0xffff0000)
00076
00080 #define hdrchkType(_type) ((_type) < RPM_MIN_TYPE || (_type) > RPM_MAX_TYPE)
00081
00086 #define hdrchkData(_nbytes) ((_nbytes) & 0xff000000)
00087
00091 #define hdrchkAlign(_type, _off) ((_off) & (typeAlign[_type]-1))
00092
00096 #define hdrchkRange(_dl, _off) ((_off) < 0 || (_off) > (_dl))
00097
00098
00099 static int dncmp(const void * a, const void * b)
00100
00101 {
00102 const char *const * first = a;
00103 const char *const * second = b;
00104 return strcmp(*first, *second);
00105 }
00106
00107
00108
00113 static void compressFilelist(Header h)
00114
00115 {
00116 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
00117 HAE_t hae = (HAE_t)headerAddEntry;
00118 HRE_t hre = (HRE_t)headerRemoveEntry;
00119 HFD_t hfd = headerFreeData;
00120 char ** fileNames;
00121 const char ** dirNames;
00122 const char ** baseNames;
00123 int_32 * dirIndexes;
00124 rpmTagType fnt;
00125 int count;
00126 int i, xx;
00127 int dirIndex = -1;
00128
00129
00130
00131
00132
00133
00134
00135 if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
00136 xx = hre(h, RPMTAG_OLDFILENAMES);
00137 return;
00138 }
00139
00140 if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (void **) &fileNames, &count))
00141 return;
00142 if (fileNames == NULL || count <= 0)
00143 return;
00144
00145 dirNames = alloca(sizeof(*dirNames) * count);
00146 baseNames = alloca(sizeof(*dirNames) * count);
00147 dirIndexes = alloca(sizeof(*dirIndexes) * count);
00148
00149 if (fileNames[0][0] != '/') {
00150
00151 dirIndex = 0;
00152 dirNames[dirIndex] = "";
00153 for (i = 0; i < count; i++) {
00154 dirIndexes[i] = dirIndex;
00155 baseNames[i] = fileNames[i];
00156 }
00157 goto exit;
00158 }
00159
00160
00161 for (i = 0; i < count; i++) {
00162 const char ** needle;
00163 char savechar;
00164 char * baseName;
00165 int len;
00166
00167 if (fileNames[i] == NULL)
00168 continue;
00169 baseName = strrchr(fileNames[i], '/') + 1;
00170 len = baseName - fileNames[i];
00171 needle = dirNames;
00172 savechar = *baseName;
00173 *baseName = '\0';
00174
00175 if (dirIndex < 0 ||
00176 (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
00177 char *s = alloca(len + 1);
00178 memcpy(s, fileNames[i], len + 1);
00179 s[len] = '\0';
00180 dirIndexes[i] = ++dirIndex;
00181 dirNames[dirIndex] = s;
00182 } else
00183 dirIndexes[i] = needle - dirNames;
00184
00185
00186 *baseName = savechar;
00187 baseNames[i] = baseName;
00188 }
00189
00190
00191 exit:
00192 if (count > 0) {
00193 xx = hae(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
00194 xx = hae(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
00195 baseNames, count);
00196 xx = hae(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
00197 dirNames, dirIndex + 1);
00198 }
00199
00200 fileNames = hfd(fileNames, fnt);
00201
00202 xx = hre(h, RPMTAG_OLDFILENAMES);
00203 }
00204
00205
00206
00207 static void rpm3to4(Header h) {
00208 char * rpmversion;
00209 int_32 rpmversion_type;
00210
00211 (void) headerGetEntry(h, RPMTAG_RPMVERSION, NULL, (void **) &rpmversion, &rpmversion_type);
00212
00213 if ((!rpmversion) || rpmversion[0] < '4') {
00214 int *epoch;
00215 const char * name, *version, *release;
00216 const char *pEVR;
00217 char *p;
00218 int_32 pFlags = RPMSENSE_EQUAL;
00219
00220 if (headerNVR(h, &name, &version, &release) == 0) {
00221 pEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1);
00222 *p = '\0';
00223 if (headerGetEntry(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
00224 sprintf(p, "%d:", *epoch);
00225 while (*p != '\0')
00226 p++;
00227 }
00228 (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release);
00229
00230 headerAddOrAppendEntry(h, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE, &name, 1);
00231 headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE, &pFlags, 1);
00232 headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE, &pEVR, 1);
00233 }
00234 compressFilelist(h);
00235 }
00236 headerFreeTag(h, (void *) rpmversion, rpmversion_type);
00237 return;
00238 }
00239
00240 void headerMergeLegacySigs(Header h, const Header sigh)
00241 {
00242 HFD_t hfd = (HFD_t) headerFreeData;
00243 HAE_t hae = (HAE_t) headerAddEntry;
00244 HeaderIterator hi;
00245 int_32 tag, type, count;
00246 const void * ptr;
00247 int xx;
00248
00249 for (hi = headerInitIterator(sigh);
00250 headerNextIterator(hi, &tag, &type, &ptr, &count);
00251 ptr = hfd(ptr, type))
00252 {
00253 switch (tag) {
00254
00255 case RPMSIGTAG_SIZE:
00256 tag = RPMTAG_SIGSIZE;
00257 break;
00258 case RPMSIGTAG_LEMD5_1:
00259 tag = RPMTAG_SIGLEMD5_1;
00260 break;
00261 case RPMSIGTAG_PGP:
00262 tag = RPMTAG_SIGPGP;
00263 break;
00264 case RPMSIGTAG_LEMD5_2:
00265 tag = RPMTAG_SIGLEMD5_2;
00266 break;
00267 case RPMSIGTAG_MD5:
00268 tag = RPMTAG_SIGMD5;
00269 break;
00270 case RPMSIGTAG_GPG:
00271 tag = RPMTAG_SIGGPG;
00272 break;
00273 case RPMSIGTAG_PGP5:
00274 tag = RPMTAG_SIGPGP5;
00275 break;
00276 case RPMSIGTAG_PAYLOADSIZE:
00277 tag = RPMTAG_ARCHIVESIZE;
00278 break;
00279 case RPMSIGTAG_SHA1:
00280 case RPMSIGTAG_DSA:
00281 case RPMSIGTAG_RSA:
00282 default:
00283 if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
00284 continue;
00285 break;
00286 }
00287 if (ptr == NULL) continue;
00288 if (!headerIsEntry(h, tag)) {
00289 if (hdrchkType(type))
00290 continue;
00291 if (count < 0 || hdrchkData(count))
00292 continue;
00293 switch(type) {
00294 case RPM_NULL_TYPE:
00295 continue;
00296 break;
00297 case RPM_CHAR_TYPE:
00298 case RPM_INT8_TYPE:
00299 case RPM_INT16_TYPE:
00300 case RPM_INT32_TYPE:
00301 if (count != 1)
00302 continue;
00303 break;
00304 case RPM_STRING_TYPE:
00305 case RPM_BIN_TYPE:
00306 if (count >= 16*1024)
00307 continue;
00308 break;
00309 case RPM_STRING_ARRAY_TYPE:
00310 case RPM_I18NSTRING_TYPE:
00311 continue;
00312 break;
00313 }
00314 xx = hae(h, tag, type, ptr, count);
00315 }
00316 }
00317 hi = headerFreeIterator(hi);
00318 }
00319
00320 Header headerRegenSigHeader(const Header h, int noArchiveSize)
00321 {
00322 HFD_t hfd = (HFD_t) headerFreeData;
00323 Header sigh = rpmNewSignature();
00324 HeaderIterator hi;
00325 int_32 tag, stag, type, count;
00326 const void * ptr;
00327 int xx;
00328
00329 for (hi = headerInitIterator(h);
00330 headerNextIterator(hi, &tag, &type, &ptr, &count);
00331 ptr = hfd(ptr, type))
00332 {
00333 switch (tag) {
00334
00335 case RPMTAG_SIGSIZE:
00336 stag = RPMSIGTAG_SIZE;
00337 break;
00338 case RPMTAG_SIGLEMD5_1:
00339 stag = RPMSIGTAG_LEMD5_1;
00340 break;
00341 case RPMTAG_SIGPGP:
00342 stag = RPMSIGTAG_PGP;
00343 break;
00344 case RPMTAG_SIGLEMD5_2:
00345 stag = RPMSIGTAG_LEMD5_2;
00346 break;
00347 case RPMTAG_SIGMD5:
00348 stag = RPMSIGTAG_MD5;
00349 break;
00350 case RPMTAG_SIGGPG:
00351 stag = RPMSIGTAG_GPG;
00352 break;
00353 case RPMTAG_SIGPGP5:
00354 stag = RPMSIGTAG_PGP5;
00355 break;
00356 case RPMTAG_ARCHIVESIZE:
00357
00358 if (noArchiveSize)
00359 continue;
00360 stag = RPMSIGTAG_PAYLOADSIZE;
00361 break;
00362 case RPMTAG_SHA1HEADER:
00363 case RPMTAG_DSAHEADER:
00364 case RPMTAG_RSAHEADER:
00365 default:
00366 if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
00367 continue;
00368 stag = tag;
00369 break;
00370 }
00371 if (ptr == NULL) continue;
00372 if (!headerIsEntry(sigh, stag))
00373 xx = headerAddEntry(sigh, stag, type, ptr, count);
00374 }
00375 hi = headerFreeIterator(hi);
00376 return sigh;
00377 }
00378
00384 static int rpmtsStashKeyid(rpmts ts)
00385
00386
00387 {
00388 const void * sig = rpmtsSig(ts);
00389 pgpDig dig = rpmtsDig(ts);
00390 pgpDigParams sigp = rpmtsSignature(ts);
00391 unsigned int keyid;
00392 int i;
00393
00394 if (sig == NULL || dig == NULL || sigp == NULL)
00395 return 0;
00396
00397 keyid = pgpGrab(sigp->signid+4, 4);
00398 if (keyid == 0)
00399 return 0;
00400
00401 if (keyids != NULL)
00402 for (i = 0; i < nkeyids; i++) {
00403
00404 if (keyid == keyids[i])
00405 return 1;
00406
00407 }
00408
00409 if (nkeyids < nkeyids_max) {
00410 nkeyids++;
00411 keyids = xrealloc(keyids, nkeyids * sizeof(*keyids));
00412 }
00413
00414 if (keyids)
00415 keyids[nextkeyid] = keyid;
00416
00417 nextkeyid++;
00418 nextkeyid %= nkeyids_max;
00419
00420 return 0;
00421 }
00422
00423 int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate)
00424 {
00425
00426 entryInfo pe = (entryInfo) pev;
00427
00428 entryInfo info = iv;
00429 int i;
00430
00431
00432 for (i = 0; i < il; i++) {
00433 info->tag = ntohl(pe[i].tag);
00434 info->type = ntohl(pe[i].type);
00435 info->offset = ntohl(pe[i].offset);
00436 if (negate)
00437 info->offset = -info->offset;
00438 info->count = ntohl(pe[i].count);
00439
00440 if (hdrchkType(info->type))
00441 return i;
00442 if (hdrchkAlign(info->type, info->offset))
00443 return i;
00444 if (!negate && hdrchkRange(dl, info->offset))
00445 return i;
00446 if (hdrchkData(info->count))
00447 return i;
00448
00449 }
00450
00451 return -1;
00452 }
00453
00467 rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, const char ** msg)
00468 {
00469 pgpDig dig;
00470 unsigned char buf[8*BUFSIZ];
00471 int_32 * ei = (int_32 *) uh;
00472
00473 int_32 il = ntohl(ei[0]);
00474 int_32 dl = ntohl(ei[1]);
00475
00476 entryInfo pe = (entryInfo) &ei[2];
00477
00478
00479 int_32 ildl[2];
00480 int_32 pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl;
00481 unsigned char * dataStart = (unsigned char *) (pe + il);
00482 indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry));
00483 entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info));
00484 const void * sig = NULL;
00485 const char * b;
00486 rpmVSFlags vsflags = rpmtsVSFlags(ts);
00487 int siglen = 0;
00488 int blen;
00489 size_t nb;
00490 int_32 ril = 0;
00491 unsigned char * regionEnd = NULL;
00492 rpmRC rc = RPMRC_FAIL;
00493 int xx;
00494 int i;
00495 static int hclvl;
00496
00497 hclvl++;
00498
00499 buf[0] = '\0';
00500
00501
00502
00503 if (uc > 0 && pvlen != uc) {
00504 (void) snprintf(buf, sizeof(buf),
00505 _("blob size(%d): BAD, 8 + 16 * il(%d) + dl(%d)\n"),
00506 (int)uc, (int)il, (int)dl);
00507 goto exit;
00508 }
00509
00510
00511 xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
00512 if (xx != -1) {
00513 (void) snprintf(buf, sizeof(buf),
00514 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00515 0, entry->info.tag, entry->info.type,
00516 entry->info.offset, entry->info.count);
00517 goto exit;
00518 }
00519
00520
00521
00522 if (!(entry->info.tag == RPMTAG_HEADERIMMUTABLE
00523 && entry->info.type == RPM_BIN_TYPE
00524 && entry->info.count == REGION_TAG_COUNT))
00525 {
00526 rc = RPMRC_NOTFOUND;
00527 goto exit;
00528 }
00529
00530
00531
00532 if (entry->info.offset >= dl) {
00533 (void) snprintf(buf, sizeof(buf),
00534 _("region offset: BAD, tag %d type %d offset %d count %d\n"),
00535 entry->info.tag, entry->info.type,
00536 entry->info.offset, entry->info.count);
00537 goto exit;
00538 }
00539
00540
00541 regionEnd = dataStart + entry->info.offset;
00542
00543
00544 (void) memcpy(info, regionEnd, REGION_TAG_COUNT);
00545
00546 regionEnd += REGION_TAG_COUNT;
00547
00548 xx = headerVerifyInfo(1, dl, info, &entry->info, 1);
00549 if (xx != -1 ||
00550 !(entry->info.tag == RPMTAG_HEADERIMMUTABLE
00551 && entry->info.type == RPM_BIN_TYPE
00552 && entry->info.count == REGION_TAG_COUNT))
00553 {
00554 (void) snprintf(buf, sizeof(buf),
00555 _("region trailer: BAD, tag %d type %d offset %d count %d\n"),
00556 entry->info.tag, entry->info.type,
00557 entry->info.offset, entry->info.count);
00558 goto exit;
00559 }
00560
00561
00562 memset(info, 0, sizeof(*info));
00563
00564
00565
00566 ril = entry->info.offset/sizeof(*pe);
00567 if ((entry->info.offset % sizeof(*pe)) || ril > il) {
00568 (void) snprintf(buf, sizeof(buf),
00569 _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
00570 goto exit;
00571 }
00572
00573
00574 for (i = ril; i < il; i++) {
00575 xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0);
00576 if (xx != -1) {
00577 (void) snprintf(buf, sizeof(buf),
00578 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00579 i, entry->info.tag, entry->info.type,
00580 entry->info.offset, entry->info.count);
00581 goto exit;
00582 }
00583
00584 switch (entry->info.tag) {
00585 case RPMTAG_SHA1HEADER:
00586 if (vsflags & RPMVSF_NOSHA1HEADER)
00587 break;
00588 blen = 0;
00589
00590 for (b = dataStart + entry->info.offset; *b != '\0'; b++) {
00591 if (strchr("0123456789abcdefABCDEF", *b) == NULL)
00592 break;
00593 blen++;
00594 }
00595 if (entry->info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40)
00596 {
00597 (void) snprintf(buf, sizeof(buf), _("hdr SHA1: BAD, not hex\n"));
00598 goto exit;
00599 }
00600
00601 if (info->tag == 0) {
00602
00603 *info = entry->info;
00604
00605 siglen = blen + 1;
00606 }
00607 break;
00608 case RPMTAG_RSAHEADER:
00609 if (vsflags & RPMVSF_NORSAHEADER)
00610 break;
00611 if (entry->info.type != RPM_BIN_TYPE) {
00612 (void) snprintf(buf, sizeof(buf), _("hdr RSA: BAD, not binary\n"));
00613 goto exit;
00614 }
00615
00616 *info = entry->info;
00617
00618 siglen = info->count;
00619 break;
00620 case RPMTAG_DSAHEADER:
00621 if (vsflags & RPMVSF_NODSAHEADER)
00622 break;
00623 if (entry->info.type != RPM_BIN_TYPE) {
00624 (void) snprintf(buf, sizeof(buf), _("hdr DSA: BAD, not binary\n"));
00625 goto exit;
00626 }
00627
00628 *info = entry->info;
00629
00630 siglen = info->count;
00631 break;
00632 default:
00633 break;
00634 }
00635 }
00636 rc = RPMRC_NOTFOUND;
00637
00638 exit:
00639
00640 if (rc != RPMRC_NOTFOUND) {
00641
00642 buf[sizeof(buf)-1] = '\0';
00643 if (msg) *msg = xstrdup(buf);
00644
00645 hclvl--;
00646 return rc;
00647 }
00648
00649
00650 if (info->tag == 0) {
00651 verifyinfo_exit:
00652 xx = headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0);
00653 if (xx != -1) {
00654 (void) snprintf(buf, sizeof(buf),
00655 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00656 xx+1, entry->info.tag, entry->info.type,
00657 entry->info.offset, entry->info.count);
00658 rc = RPMRC_FAIL;
00659 } else {
00660 (void) snprintf(buf, sizeof(buf), "Header sanity check: OK\n");
00661 rc = RPMRC_OK;
00662 }
00663
00664 buf[sizeof(buf)-1] = '\0';
00665 if (msg) *msg = xstrdup(buf);
00666
00667 hclvl--;
00668 return rc;
00669 }
00670
00671
00672 dig = rpmtsDig(ts);
00673 if (dig == NULL)
00674 goto verifyinfo_exit;
00675 dig->nbytes = 0;
00676
00677
00678 sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen);
00679
00680 (void) rpmtsSetSig(ts, info->tag, info->type, sig, info->count);
00681
00682 switch (info->tag) {
00683 case RPMTAG_RSAHEADER:
00684
00685 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00686 if (dig->signature.version != 3 && dig->signature.version != 4) {
00687 rpmMessage(RPMMESS_WARNING,
00688 _("only V3 and V4 signatures can be verified, skipping V%u signature\n"),
00689 dig->signature.version);
00690 rpmtsCleanDig(ts);
00691 goto verifyinfo_exit;
00692 }
00693
00694 ildl[0] = htonl(ril);
00695 ildl[1] = (regionEnd - dataStart);
00696 ildl[1] = htonl(ildl[1]);
00697
00698 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00699 dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
00700
00701 b = (unsigned char *) header_magic;
00702 nb = sizeof(header_magic);
00703 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00704 dig->nbytes += nb;
00705
00706 b = (unsigned char *) ildl;
00707 nb = sizeof(ildl);
00708 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00709 dig->nbytes += nb;
00710
00711 b = (unsigned char *) pe;
00712 nb = (htonl(ildl[0]) * sizeof(*pe));
00713 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00714 dig->nbytes += nb;
00715
00716 b = (unsigned char *) dataStart;
00717 nb = htonl(ildl[1]);
00718 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00719 dig->nbytes += nb;
00720 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00721
00722 break;
00723 case RPMTAG_DSAHEADER:
00724
00725 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00726 if (dig->signature.version != 3 && dig->signature.version != 4) {
00727 rpmMessage(RPMMESS_WARNING,
00728 _("only V3 and V4 signatures can be verified, skipping V%u signature\n"),
00729 dig->signature.version);
00730 rpmtsCleanDig(ts);
00731 goto verifyinfo_exit;
00732 }
00733
00734 case RPMTAG_SHA1HEADER:
00735
00736 ildl[0] = htonl(ril);
00737 ildl[1] = (regionEnd - dataStart);
00738 ildl[1] = htonl(ildl[1]);
00739
00740
00741 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00742 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00743
00744 b = (unsigned char *) header_magic;
00745 nb = sizeof(header_magic);
00746 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00747 dig->nbytes += nb;
00748
00749 b = (unsigned char *) ildl;
00750 nb = sizeof(ildl);
00751 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00752 dig->nbytes += nb;
00753
00754 b = (unsigned char *) pe;
00755 nb = (htonl(ildl[0]) * sizeof(*pe));
00756 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00757 dig->nbytes += nb;
00758
00759 b = (unsigned char *) dataStart;
00760 nb = htonl(ildl[1]);
00761 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00762 dig->nbytes += nb;
00763 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00764
00765 break;
00766 default:
00767 sig = _free(sig);
00768 break;
00769 }
00770
00771
00772 buf[0] = '\0';
00773
00774 rc = rpmVerifySignature(ts, buf);
00775
00776
00777 buf[sizeof(buf)-1] = '\0';
00778 if (msg) *msg = xstrdup(buf);
00779
00780
00781
00782 if (hclvl == 1)
00783 rpmtsCleanDig(ts);
00784 if (info->tag == RPMTAG_SHA1HEADER)
00785 sig = _free(sig);
00786 hclvl--;
00787 return rc;
00788 }
00789
00790 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, const char ** msg)
00791 {
00792 char buf[BUFSIZ];
00793 int_32 block[4];
00794 int_32 il;
00795 int_32 dl;
00796 int_32 * ei = NULL;
00797 size_t uc;
00798 int_32 nb;
00799 Header h = NULL;
00800 const char * origin = NULL;
00801 rpmRC rc = RPMRC_FAIL;
00802 int xx;
00803
00804
00805 buf[0] = '\0';
00806
00807 if (hdrp)
00808 *hdrp = NULL;
00809 if (msg)
00810 *msg = NULL;
00811
00812
00813 memset(block, 0, sizeof(block));
00814 if ((xx = timedRead(fd, (char *)block, sizeof(block))) != sizeof(block)) {
00815 (void) snprintf(buf, sizeof(buf),
00816 _("hdr size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx);
00817 goto exit;
00818 }
00819 if (memcmp(block, header_magic, sizeof(header_magic))) {
00820 (void) snprintf(buf, sizeof(buf), _("hdr magic: BAD\n"));
00821 goto exit;
00822 }
00823
00824 il = ntohl(block[2]);
00825
00826 if (hdrchkTags(il)) {
00827 (void) snprintf(buf, sizeof(buf),
00828 _("hdr tags: BAD, no. of tags(%d) out of range\n"), il);
00829
00830 goto exit;
00831 }
00832
00833 dl = ntohl(block[3]);
00834
00835 if (hdrchkData(dl)) {
00836 (void) snprintf(buf, sizeof(buf),
00837 _("hdr data: BAD, no. of bytes(%d) out of range\n"), dl);
00838 goto exit;
00839 }
00840
00841
00842 nb = (il * sizeof(struct entryInfo_s)) + dl;
00843
00844 uc = sizeof(il) + sizeof(dl) + nb;
00845 ei = xmalloc(uc);
00846
00847 ei[0] = block[2];
00848 ei[1] = block[3];
00849 if ((xx = timedRead(fd, (char *)&ei[2], nb)) != nb) {
00850 (void) snprintf(buf, sizeof(buf),
00851 _("hdr blob(%d): BAD, read returned %d\n"), nb, xx);
00852 goto exit;
00853 }
00854
00855
00856
00857 rc = headerCheck(ts, ei, uc, msg);
00858 if (rc != RPMRC_OK)
00859 goto exit;
00860
00861
00862 h = headerLoad(ei);
00863 if (h == NULL) {
00864 (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n"));
00865 goto exit;
00866 }
00867 h->flags |= HEADERFLAG_ALLOCATED;
00868 ei = NULL;
00869
00870
00871 origin = fdGetOPath(fd);
00872 if (origin != NULL)
00873 (void) headerSetOrigin(h, origin);
00874
00875 exit:
00876
00877 if (hdrp && h && rc == RPMRC_OK)
00878 *hdrp = headerLink(h);
00879
00880 ei = _free(ei);
00881 h = headerFree(h);
00882
00883
00884 if (msg != NULL && *msg == NULL && buf[0] != '\0') {
00885 buf[sizeof(buf)-1] = '\0';
00886 *msg = xstrdup(buf);
00887 }
00888
00889
00890 return rc;
00891 }
00892
00893
00894 rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
00895 {
00896 pgpDig dig;
00897 byte buf[8*BUFSIZ];
00898 ssize_t count;
00899 struct rpmlead * l = alloca(sizeof(*l));
00900 Header sigh = NULL;
00901 int_32 sigtag;
00902 int_32 sigtype;
00903 const void * sig;
00904 int_32 siglen;
00905 rpmtsOpX opx;
00906 size_t nb;
00907 Header h = NULL;
00908 const char * msg;
00909 rpmVSFlags vsflags;
00910 rpmRC rc = RPMRC_FAIL;
00911 rpmop opsave = memset(alloca(sizeof(*opsave)), 0, sizeof(*opsave));
00912 int xx;
00913 int i;
00914
00915 if (hdrp) *hdrp = NULL;
00916
00917 #ifdef DYING
00918 { struct stat st;
00919
00920 memset(&st, 0, sizeof(st));
00921
00922 (void) fstat(Fileno(fd), &st);
00923
00924 if (S_ISREG(st.st_mode) && st.st_size < sizeof(*l)) {
00925 rc = RPMRC_NOTFOUND;
00926 goto exit;
00927 }
00928 }
00929 #endif
00930
00931
00932 (void) rpmswAdd(opsave, fdstat_op(fd, FDSTAT_READ));
00933
00934 memset(l, 0, sizeof(*l));
00935 rc = readLead(fd, l);
00936 if (rc != RPMRC_OK)
00937 goto exit;
00938
00939 switch (l->major) {
00940 case 1:
00941 rpmError(RPMERR_NEWPACKAGE,
00942 _("packaging version 1 is not supported by this version of RPM\n"));
00943 rc = RPMRC_NOTFOUND;
00944 goto exit;
00945 break;
00946 case 2:
00947 case 3:
00948 case 4:
00949 break;
00950 default:
00951 rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 "
00952 "is supported by this version of RPM\n"));
00953 rc = RPMRC_NOTFOUND;
00954 goto exit;
00955 break;
00956 }
00957
00958
00959 msg = NULL;
00960 rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
00961 switch (rc) {
00962 default:
00963 rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed: %s"), fn,
00964 (msg && *msg ? msg : "\n"));
00965 msg = _free(msg);
00966 goto exit;
00967 break;
00968 case RPMRC_OK:
00969 if (sigh == NULL) {
00970 rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn);
00971 rc = RPMRC_FAIL;
00972 goto exit;
00973 }
00974 break;
00975 }
00976 msg = _free(msg);
00977
00978 #define _chk(_mask) (sigtag == 0 && !(vsflags & (_mask)))
00979
00980
00981
00982
00983
00984
00985
00986 sigtag = 0;
00987 opx = 0;
00988 vsflags = rpmtsVSFlags(ts);
00989 if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_DSA)) {
00990 sigtag = RPMSIGTAG_DSA;
00991 } else
00992 if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_RSA)) {
00993 sigtag = RPMSIGTAG_RSA;
00994 } else
00995 if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD) &&
00996 headerIsEntry(sigh, RPMSIGTAG_GPG))
00997 {
00998 sigtag = RPMSIGTAG_GPG;
00999 fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
01000 opx = RPMTS_OP_SIGNATURE;
01001 } else
01002 if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD) &&
01003 headerIsEntry(sigh, RPMSIGTAG_PGP))
01004 {
01005 sigtag = RPMSIGTAG_PGP;
01006 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
01007 opx = RPMTS_OP_SIGNATURE;
01008 } else
01009 if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, RPMSIGTAG_SHA1)) {
01010 sigtag = RPMSIGTAG_SHA1;
01011 } else
01012 if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
01013 headerIsEntry(sigh, RPMSIGTAG_MD5))
01014 {
01015 sigtag = RPMSIGTAG_MD5;
01016 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
01017 opx = RPMTS_OP_DIGEST;
01018 }
01019
01020
01021 h = NULL;
01022 msg = NULL;
01023
01024
01025
01026 if (opx > 0)
01027 (void) rpmswEnter(rpmtsOp(ts, opx), 0);
01028
01029 nb = -fd->stats->ops[FDSTAT_READ].bytes;
01030 rc = rpmReadHeader(ts, fd, &h, &msg);
01031 nb += fd->stats->ops[FDSTAT_READ].bytes;
01032
01033 if (opx > 0)
01034 (void) rpmswExit(rpmtsOp(ts, opx), nb);
01035
01036 if (rc != RPMRC_OK || h == NULL) {
01037 rpmError(RPMERR_FREAD, _("%s: headerRead failed: %s"), fn,
01038 (msg && *msg ? msg : "\n"));
01039 msg = _free(msg);
01040 goto exit;
01041 }
01042 msg = _free(msg);
01043
01044
01045 if (sigtag == 0) {
01046 rc = RPMRC_OK;
01047 goto exit;
01048 }
01049
01050 dig = rpmtsDig(ts);
01051 if (dig == NULL) {
01052 rc = RPMRC_FAIL;
01053 goto exit;
01054 }
01055 dig->nbytes = 0;
01056
01057
01058 sig = NULL;
01059 xx = headerGetEntry(sigh, sigtag, &sigtype, (void **) &sig, &siglen);
01060 if (sig == NULL) {
01061 rc = RPMRC_FAIL;
01062 goto exit;
01063 }
01064 (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
01065
01066 switch (sigtag) {
01067 case RPMSIGTAG_RSA:
01068
01069 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
01070 if (dig->signature.version != 3 && dig->signature.version != 4) {
01071 rpmMessage(RPMMESS_WARNING,
01072 _("only V3 and V4 signatures can be verified, skipping V%u signature\n"),
01073 dig->signature.version);
01074 rc = RPMRC_OK;
01075 goto exit;
01076 }
01077 { void * uh = NULL;
01078 int_32 uht;
01079 int_32 uhc;
01080
01081 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
01082 break;
01083 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
01084 dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
01085 (void) rpmDigestUpdate(dig->hdrmd5ctx, header_magic, sizeof(header_magic));
01086 dig->nbytes += sizeof(header_magic);
01087 (void) rpmDigestUpdate(dig->hdrmd5ctx, uh, uhc);
01088 dig->nbytes += uhc;
01089 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
01090 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;
01091 uh = headerFreeData(uh, uht);
01092 } break;
01093 case RPMSIGTAG_DSA:
01094
01095 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
01096 if (dig->signature.version != 3 && dig->signature.version != 4) {
01097 rpmMessage(RPMMESS_WARNING,
01098 _("only V3 and V4 signatures can be verified, skipping V%u signature\n"),
01099 dig->signature.version);
01100 rc = RPMRC_OK;
01101 goto exit;
01102 }
01103
01104 case RPMSIGTAG_SHA1:
01105 { void * uh = NULL;
01106 int_32 uht;
01107 int_32 uhc;
01108
01109 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
01110 break;
01111 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
01112 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
01113 (void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic));
01114 dig->nbytes += sizeof(header_magic);
01115 (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
01116 dig->nbytes += uhc;
01117 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
01118 if (sigtag == RPMSIGTAG_SHA1)
01119 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;
01120 uh = headerFreeData(uh, uht);
01121 } break;
01122 case RPMSIGTAG_GPG:
01123 case RPMSIGTAG_PGP5:
01124 case RPMSIGTAG_PGP:
01125
01126 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
01127
01128 if (dig->signature.version != 3 && dig->signature.version != 4) {
01129 rpmMessage(RPMMESS_WARNING,
01130 _("only V3 and V4 signatures can be verified, skipping V%u signature\n"),
01131 dig->signature.version);
01132 rc = RPMRC_OK;
01133 goto exit;
01134 }
01135
01136 case RPMSIGTAG_MD5:
01137
01138 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
01139 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
01140 dig->nbytes += count;
01141 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
01142 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;
01143 dig->nbytes += nb;
01144 if (count < 0) {
01145 rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
01146 fn, Fstrerror(fd));
01147 rc = RPMRC_FAIL;
01148 goto exit;
01149 }
01150
01151
01152 for (i = fd->ndigests - 1; i >= 0; i--) {
01153 FDDIGEST_t fddig = fd->digests + i;
01154 if (fddig->hashctx != NULL)
01155 switch (fddig->hashalgo) {
01156 case PGPHASHALGO_MD5:
01157 dig->md5ctx = fddig->hashctx;
01158 fddig->hashctx = NULL;
01159 break;
01160 case PGPHASHALGO_SHA1:
01161 case PGPHASHALGO_RIPEMD160:
01162 #if HAVE_BEECRYPT_API_H
01163 case PGPHASHALGO_SHA256:
01164 case PGPHASHALGO_SHA384:
01165 case PGPHASHALGO_SHA512:
01166 #endif
01167 dig->sha1ctx = fddig->hashctx;
01168 fddig->hashctx = NULL;
01169 break;
01170 default:
01171 break;
01172 }
01173 }
01174 break;
01175 }
01176
01179
01180 buf[0] = '\0';
01181
01182 rc = rpmVerifySignature(ts, buf);
01183 switch (rc) {
01184 case RPMRC_OK:
01185 rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
01186 break;
01187 case RPMRC_NOTTRUSTED:
01188 case RPMRC_NOKEY:
01189
01190 { int lvl = (rpmtsStashKeyid(ts) ? RPMMESS_DEBUG : RPMMESS_WARNING);
01191 rpmMessage(lvl, "%s: %s", fn, buf);
01192 } break;
01193 case RPMRC_NOTFOUND:
01194 rpmMessage(RPMMESS_WARNING, "%s: %s", fn, buf);
01195 break;
01196 default:
01197 case RPMRC_FAIL:
01198 rpmMessage(RPMMESS_ERROR, "%s: %s", fn, buf);
01199 break;
01200 }
01201
01202 exit:
01203 if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
01204
01205
01206 headerMergeLegacySigs(h, sigh);
01207
01208 rpm3to4(h);
01209
01210
01211
01212 *hdrp = headerLink(h);
01213
01214 }
01215 h = headerFree(h);
01216
01217
01218 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_READHDR),
01219 fdstat_op(fd, FDSTAT_READ));
01220 (void) rpmswSub(rpmtsOp(ts, RPMTS_OP_READHDR),
01221 opsave);
01222
01223 rpmtsCleanDig(ts);
01224 sigh = rpmFreeSignature(sigh);
01225 return rc;
01226 }
01227