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
00014 #include "misc.h"
00015 #include "legacy.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 void headerMergeLegacySigs(Header h, const Header sigh)
00099 {
00100 HFD_t hfd = (HFD_t) headerFreeData;
00101 HAE_t hae = (HAE_t) headerAddEntry;
00102 HeaderIterator hi;
00103 int_32 tag, type, count;
00104 const void * ptr;
00105 int xx;
00106
00107 for (hi = headerInitIterator(sigh);
00108 headerNextIterator(hi, &tag, &type, &ptr, &count);
00109 ptr = hfd(ptr, type))
00110 {
00111 switch (tag) {
00112
00113 case RPMSIGTAG_SIZE:
00114 tag = RPMTAG_SIGSIZE;
00115 break;
00116 case RPMSIGTAG_LEMD5_1:
00117 tag = RPMTAG_SIGLEMD5_1;
00118 break;
00119 case RPMSIGTAG_PGP:
00120 tag = RPMTAG_SIGPGP;
00121 break;
00122 case RPMSIGTAG_LEMD5_2:
00123 tag = RPMTAG_SIGLEMD5_2;
00124 break;
00125 case RPMSIGTAG_MD5:
00126 tag = RPMTAG_SIGMD5;
00127 break;
00128 case RPMSIGTAG_GPG:
00129 tag = RPMTAG_SIGGPG;
00130 break;
00131 case RPMSIGTAG_PGP5:
00132 tag = RPMTAG_SIGPGP5;
00133 break;
00134 case RPMSIGTAG_PAYLOADSIZE:
00135 tag = RPMTAG_ARCHIVESIZE;
00136 break;
00137 case RPMSIGTAG_SHA1:
00138 case RPMSIGTAG_DSA:
00139 case RPMSIGTAG_RSA:
00140 default:
00141 if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
00142 continue;
00143 break;
00144 }
00145 if (ptr == NULL) continue;
00146 if (!headerIsEntry(h, tag)) {
00147 if (hdrchkType(type))
00148 continue;
00149 if (count < 0 || hdrchkData(count))
00150 continue;
00151 switch(type) {
00152 case RPM_NULL_TYPE:
00153 continue;
00154 break;
00155 case RPM_CHAR_TYPE:
00156 case RPM_INT8_TYPE:
00157 case RPM_INT16_TYPE:
00158 case RPM_INT32_TYPE:
00159 if (count != 1)
00160 continue;
00161 break;
00162 case RPM_STRING_TYPE:
00163 case RPM_BIN_TYPE:
00164 if (count >= 16*1024)
00165 continue;
00166 break;
00167 case RPM_STRING_ARRAY_TYPE:
00168 case RPM_I18NSTRING_TYPE:
00169 continue;
00170 break;
00171 }
00172 xx = hae(h, tag, type, ptr, count);
00173 }
00174 }
00175 hi = headerFreeIterator(hi);
00176 }
00177
00178 Header headerRegenSigHeader(const Header h, int noArchiveSize)
00179 {
00180 HFD_t hfd = (HFD_t) headerFreeData;
00181 Header sigh = rpmNewSignature();
00182 HeaderIterator hi;
00183 int_32 tag, stag, type, count;
00184 const void * ptr;
00185 int xx;
00186
00187 for (hi = headerInitIterator(h);
00188 headerNextIterator(hi, &tag, &type, &ptr, &count);
00189 ptr = hfd(ptr, type))
00190 {
00191 switch (tag) {
00192
00193 case RPMTAG_SIGSIZE:
00194 stag = RPMSIGTAG_SIZE;
00195 break;
00196 case RPMTAG_SIGLEMD5_1:
00197 stag = RPMSIGTAG_LEMD5_1;
00198 break;
00199 case RPMTAG_SIGPGP:
00200 stag = RPMSIGTAG_PGP;
00201 break;
00202 case RPMTAG_SIGLEMD5_2:
00203 stag = RPMSIGTAG_LEMD5_2;
00204 break;
00205 case RPMTAG_SIGMD5:
00206 stag = RPMSIGTAG_MD5;
00207 break;
00208 case RPMTAG_SIGGPG:
00209 stag = RPMSIGTAG_GPG;
00210 break;
00211 case RPMTAG_SIGPGP5:
00212 stag = RPMSIGTAG_PGP5;
00213 break;
00214 case RPMTAG_ARCHIVESIZE:
00215
00216 if (noArchiveSize)
00217 continue;
00218 stag = RPMSIGTAG_PAYLOADSIZE;
00219 break;
00220 case RPMTAG_SHA1HEADER:
00221 case RPMTAG_DSAHEADER:
00222 case RPMTAG_RSAHEADER:
00223 default:
00224 if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
00225 continue;
00226 stag = tag;
00227 break;
00228 }
00229 if (ptr == NULL) continue;
00230 if (!headerIsEntry(sigh, stag))
00231 xx = headerAddEntry(sigh, stag, type, ptr, count);
00232 }
00233 hi = headerFreeIterator(hi);
00234 return sigh;
00235 }
00236
00242 static int rpmtsStashKeyid(rpmts ts)
00243
00244
00245 {
00246 const void * sig = rpmtsSig(ts);
00247 pgpDig dig = rpmtsDig(ts);
00248 pgpDigParams sigp = rpmtsSignature(ts);
00249 unsigned int keyid;
00250 int i;
00251
00252 if (sig == NULL || dig == NULL || sigp == NULL)
00253 return 0;
00254
00255 keyid = pgpGrab(sigp->signid+4, 4);
00256 if (keyid == 0)
00257 return 0;
00258
00259 if (keyids != NULL)
00260 for (i = 0; i < nkeyids; i++) {
00261
00262 if (keyid == keyids[i])
00263 return 1;
00264
00265 }
00266
00267 if (nkeyids < nkeyids_max) {
00268 nkeyids++;
00269 keyids = xrealloc(keyids, nkeyids * sizeof(*keyids));
00270 }
00271
00272 if (keyids)
00273 keyids[nextkeyid] = keyid;
00274
00275 nextkeyid++;
00276 nextkeyid %= nkeyids_max;
00277
00278 return 0;
00279 }
00280
00281 int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate)
00282 {
00283
00284 entryInfo pe = (entryInfo) pev;
00285
00286 entryInfo info = iv;
00287 int i;
00288
00289
00290 for (i = 0; i < il; i++) {
00291 info->tag = ntohl(pe[i].tag);
00292 info->type = ntohl(pe[i].type);
00293 info->offset = ntohl(pe[i].offset);
00294 if (negate)
00295 info->offset = -info->offset;
00296 info->count = ntohl(pe[i].count);
00297
00298 if (hdrchkType(info->type))
00299 return i;
00300 if (hdrchkAlign(info->type, info->offset))
00301 return i;
00302 if (hdrchkRange(dl, info->offset))
00303 return i;
00304 if (hdrchkData(info->count))
00305 return i;
00306
00307 }
00308
00309 return -1;
00310 }
00311
00325 rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, const char ** msg)
00326 {
00327 pgpDig dig;
00328 unsigned char buf[8*BUFSIZ];
00329 int_32 * ei = (int_32 *) uh;
00330
00331 int_32 il = ntohl(ei[0]);
00332 int_32 dl = ntohl(ei[1]);
00333
00334 entryInfo pe = (entryInfo) &ei[2];
00335
00336
00337 int_32 ildl[2];
00338 int_32 pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl;
00339 unsigned char * dataStart = (unsigned char *) (pe + il);
00340 indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry));
00341 entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info));
00342 const void * sig = NULL;
00343 const char * b;
00344 rpmVSFlags vsflags = rpmtsVSFlags(ts);
00345 int siglen = 0;
00346 int blen;
00347 size_t nb;
00348 int_32 ril = 0;
00349 unsigned char * regionEnd = NULL;
00350 rpmRC rc = RPMRC_FAIL;
00351 int xx;
00352 int i;
00353 static int hclvl;
00354
00355 hclvl++;
00356
00357 buf[0] = '\0';
00358
00359
00360
00361 if (uc > 0 && pvlen != uc) {
00362 (void) snprintf(buf, sizeof(buf),
00363 _("blob size(%d): BAD, 8 + 16 * il(%d) + dl(%d)\n"),
00364 (int)uc, (int)il, (int)dl);
00365 goto exit;
00366 }
00367
00368
00369 xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
00370 if (xx != -1) {
00371 (void) snprintf(buf, sizeof(buf),
00372 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00373 0, entry->info.tag, entry->info.type,
00374 entry->info.offset, entry->info.count);
00375 goto exit;
00376 }
00377
00378
00379 if (!(entry->info.tag == RPMTAG_HEADERIMMUTABLE)) {
00380 rc = RPMRC_NOTFOUND;
00381 goto exit;
00382 }
00383
00384
00385 if (!(entry->info.type == REGION_TAG_TYPE &&
00386 entry->info.count == REGION_TAG_COUNT)) {
00387 (void) snprintf(buf, sizeof(buf),
00388 _("region tag: BAD, tag %d type %d offset %d count %d\n"),
00389 entry->info.tag, entry->info.type,
00390 entry->info.offset, entry->info.count);
00391 goto exit;
00392 }
00393
00394
00395 if (entry->info.offset + REGION_TAG_COUNT > dl) {
00396 (void) snprintf(buf, sizeof(buf),
00397 _("region offset: BAD, tag %d type %d offset %d count %d\n"),
00398 entry->info.tag, entry->info.type,
00399 entry->info.offset, entry->info.count);
00400 goto exit;
00401 }
00402
00403
00404 regionEnd = dataStart + entry->info.offset;
00405
00406
00407 (void) memcpy(info, regionEnd, REGION_TAG_COUNT);
00408
00409 regionEnd += REGION_TAG_COUNT;
00410
00411 xx = headerVerifyInfo(1, il * sizeof(*pe), info, &entry->info, 1);
00412 if (xx != -1 ||
00413 !(entry->info.tag == RPMTAG_HEADERIMMUTABLE
00414 && entry->info.type == REGION_TAG_TYPE
00415 && entry->info.count == REGION_TAG_COUNT))
00416 {
00417 (void) snprintf(buf, sizeof(buf),
00418 _("region trailer: BAD, tag %d type %d offset %d count %d\n"),
00419 entry->info.tag, entry->info.type,
00420 entry->info.offset, entry->info.count);
00421 goto exit;
00422 }
00423
00424
00425 memset(info, 0, sizeof(*info));
00426
00427
00428
00429 ril = entry->info.offset/sizeof(*pe);
00430 if ((entry->info.offset % sizeof(*pe)) || ril > il) {
00431 (void) snprintf(buf, sizeof(buf),
00432 _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
00433 goto exit;
00434 }
00435
00436
00437 for (i = ril; i < il; i++) {
00438 xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0);
00439 if (xx != -1) {
00440 (void) snprintf(buf, sizeof(buf),
00441 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00442 i, entry->info.tag, entry->info.type,
00443 entry->info.offset, entry->info.count);
00444 goto exit;
00445 }
00446
00447 switch (entry->info.tag) {
00448 case RPMTAG_SHA1HEADER:
00449 if (vsflags & RPMVSF_NOSHA1HEADER)
00450 break;
00451 blen = 0;
00452
00453 for (b = dataStart + entry->info.offset; *b != '\0'; b++) {
00454 if (strchr("0123456789abcdefABCDEF", *b) == NULL)
00455 break;
00456 blen++;
00457 }
00458 if (entry->info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40)
00459 {
00460 (void) snprintf(buf, sizeof(buf), _("hdr SHA1: BAD, not hex\n"));
00461 goto exit;
00462 }
00463
00464 if (info->tag == 0) {
00465
00466 *info = entry->info;
00467
00468 siglen = blen + 1;
00469 }
00470 break;
00471 case RPMTAG_RSAHEADER:
00472 if (vsflags & RPMVSF_NORSAHEADER)
00473 break;
00474 if (entry->info.type != RPM_BIN_TYPE) {
00475 (void) snprintf(buf, sizeof(buf), _("hdr RSA: BAD, not binary\n"));
00476 goto exit;
00477 }
00478
00479 *info = entry->info;
00480
00481 siglen = info->count;
00482 break;
00483 case RPMTAG_DSAHEADER:
00484 if (vsflags & RPMVSF_NODSAHEADER)
00485 break;
00486 if (entry->info.type != RPM_BIN_TYPE) {
00487 (void) snprintf(buf, sizeof(buf), _("hdr DSA: BAD, not binary\n"));
00488 goto exit;
00489 }
00490
00491 *info = entry->info;
00492
00493 siglen = info->count;
00494 break;
00495 default:
00496 break;
00497 }
00498 }
00499 rc = RPMRC_NOTFOUND;
00500
00501 exit:
00502
00503 if (rc != RPMRC_NOTFOUND) {
00504
00505 buf[sizeof(buf)-1] = '\0';
00506 if (msg) *msg = xstrdup(buf);
00507
00508 hclvl--;
00509 return rc;
00510 }
00511
00512
00513 if (info->tag == 0) {
00514 verifyinfo_exit:
00515 xx = headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0);
00516 if (xx != -1) {
00517 (void) snprintf(buf, sizeof(buf),
00518 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00519 xx+1, entry->info.tag, entry->info.type,
00520 entry->info.offset, entry->info.count);
00521 rc = RPMRC_FAIL;
00522 } else {
00523 (void) snprintf(buf, sizeof(buf), "Header sanity check: OK\n");
00524 rc = RPMRC_OK;
00525 }
00526
00527 buf[sizeof(buf)-1] = '\0';
00528 if (msg) *msg = xstrdup(buf);
00529
00530 hclvl--;
00531 return rc;
00532 }
00533
00534
00535 dig = rpmtsDig(ts);
00536 if (dig == NULL)
00537 goto verifyinfo_exit;
00538 dig->nbytes = 0;
00539
00540
00541 sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen);
00542
00543 (void) rpmtsSetSig(ts, info->tag, info->type, sig, info->count);
00544
00545 switch (info->tag) {
00546 case RPMTAG_RSAHEADER:
00547
00548 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00549 if (dig->signature.version != 3 && dig->signature.version != 4) {
00550 rpmMessage(RPMMESS_ERROR,
00551 _("skipping header with unverifiable V%u signature\n"),
00552 dig->signature.version);
00553 rpmtsCleanDig(ts);
00554 rc = RPMRC_FAIL;
00555 goto exit;
00556 }
00557
00558 ildl[0] = htonl(ril);
00559 ildl[1] = (regionEnd - dataStart);
00560 ildl[1] = htonl(ildl[1]);
00561
00562 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00563 dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
00564
00565 b = (unsigned char *) header_magic;
00566 nb = sizeof(header_magic);
00567 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00568 dig->nbytes += nb;
00569
00570 b = (unsigned char *) ildl;
00571 nb = sizeof(ildl);
00572 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00573 dig->nbytes += nb;
00574
00575 b = (unsigned char *) pe;
00576 nb = (htonl(ildl[0]) * sizeof(*pe));
00577 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00578 dig->nbytes += nb;
00579
00580 b = (unsigned char *) dataStart;
00581 nb = htonl(ildl[1]);
00582 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00583 dig->nbytes += nb;
00584 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00585
00586 break;
00587 case RPMTAG_DSAHEADER:
00588
00589 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00590 if (dig->signature.version != 3 && dig->signature.version != 4) {
00591 rpmMessage(RPMMESS_ERROR,
00592 _("skipping header with unverifiable V%u signature\n"),
00593 dig->signature.version);
00594 rpmtsCleanDig(ts);
00595 rc = RPMRC_FAIL;
00596 goto exit;
00597 }
00598
00599 case RPMTAG_SHA1HEADER:
00600
00601 ildl[0] = htonl(ril);
00602 ildl[1] = (regionEnd - dataStart);
00603 ildl[1] = htonl(ildl[1]);
00604
00605
00606 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00607 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00608
00609 b = (unsigned char *) header_magic;
00610 nb = sizeof(header_magic);
00611 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00612 dig->nbytes += nb;
00613
00614 b = (unsigned char *) ildl;
00615 nb = sizeof(ildl);
00616 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00617 dig->nbytes += nb;
00618
00619 b = (unsigned char *) pe;
00620 nb = (htonl(ildl[0]) * sizeof(*pe));
00621 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00622 dig->nbytes += nb;
00623
00624 b = (unsigned char *) dataStart;
00625 nb = htonl(ildl[1]);
00626 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00627 dig->nbytes += nb;
00628 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00629
00630 break;
00631 default:
00632 sig = _free(sig);
00633 break;
00634 }
00635
00636
00637 buf[0] = '\0';
00638
00639 rc = rpmVerifySignature(ts, buf);
00640
00641
00642 buf[sizeof(buf)-1] = '\0';
00643 if (msg) *msg = xstrdup(buf);
00644
00645
00646
00647 if (hclvl == 1)
00648 rpmtsCleanDig(ts);
00649 if (info->tag == RPMTAG_SHA1HEADER)
00650 sig = _free(sig);
00651 hclvl--;
00652 return rc;
00653 }
00654
00655 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, const char ** msg)
00656 {
00657 char buf[BUFSIZ];
00658 int_32 block[4];
00659 int_32 il;
00660 int_32 dl;
00661 int_32 * ei = NULL;
00662 size_t uc;
00663 int_32 nb;
00664 Header h = NULL;
00665 rpmRC rc = RPMRC_FAIL;
00666 int xx;
00667
00668
00669 buf[0] = '\0';
00670
00671 if (hdrp)
00672 *hdrp = NULL;
00673 if (msg)
00674 *msg = NULL;
00675
00676
00677 memset(block, 0, sizeof(block));
00678 if ((xx = timedRead(fd, (char *)block, sizeof(block))) != sizeof(block)) {
00679 (void) snprintf(buf, sizeof(buf),
00680 _("hdr size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx);
00681 goto exit;
00682 }
00683 if (memcmp(block, header_magic, sizeof(header_magic))) {
00684 (void) snprintf(buf, sizeof(buf), _("hdr magic: BAD\n"));
00685 goto exit;
00686 }
00687
00688 il = ntohl(block[2]);
00689
00690 if (hdrchkTags(il)) {
00691 (void) snprintf(buf, sizeof(buf),
00692 _("hdr tags: BAD, no. of tags(%d) out of range\n"), il);
00693
00694 goto exit;
00695 }
00696
00697 dl = ntohl(block[3]);
00698
00699 if (hdrchkData(dl)) {
00700 (void) snprintf(buf, sizeof(buf),
00701 _("hdr data: BAD, no. of bytes(%d) out of range\n"), dl);
00702 goto exit;
00703 }
00704
00705
00706 nb = (il * sizeof(struct entryInfo_s)) + dl;
00707
00708 uc = sizeof(il) + sizeof(dl) + nb;
00709 ei = xmalloc(uc);
00710
00711 ei[0] = block[2];
00712 ei[1] = block[3];
00713 if ((xx = timedRead(fd, (char *)&ei[2], nb)) != nb) {
00714 (void) snprintf(buf, sizeof(buf),
00715 _("hdr blob(%d): BAD, read returned %d\n"), nb, xx);
00716 goto exit;
00717 }
00718
00719
00720
00721 rc = headerCheck(ts, ei, uc, msg);
00722 if (rc != RPMRC_OK)
00723 goto exit;
00724
00725
00726 h = headerLoad(ei);
00727 if (h == NULL) {
00728 (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n"));
00729 goto exit;
00730 }
00731 h->flags |= HEADERFLAG_ALLOCATED;
00732 ei = NULL;
00733
00734 exit:
00735
00736 if (hdrp && h && rc == RPMRC_OK)
00737 *hdrp = headerLink(h);
00738
00739 ei = _free(ei);
00740 h = headerFree(h);
00741
00742
00743 if (msg != NULL && *msg == NULL && buf[0] != '\0') {
00744 buf[sizeof(buf)-1] = '\0';
00745 *msg = xstrdup(buf);
00746 }
00747
00748
00749 return rc;
00750 }
00751
00752
00753 rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
00754 {
00755 pgpDig dig;
00756 byte buf[8*BUFSIZ];
00757 ssize_t count;
00758 struct rpmlead * l = alloca(sizeof(*l));
00759 Header sigh = NULL;
00760 int_32 sigtag;
00761 int_32 sigtype;
00762 const void * sig;
00763 int_32 siglen;
00764 rpmtsOpX opx;
00765 size_t nb;
00766 Header h = NULL;
00767 const char * msg;
00768 rpmVSFlags vsflags;
00769 rpmRC rc = RPMRC_FAIL;
00770 int xx;
00771 int i;
00772
00773 if (hdrp) *hdrp = NULL;
00774
00775 #ifdef DYING
00776 { struct stat st;
00777
00778 memset(&st, 0, sizeof(st));
00779
00780 (void) fstat(Fileno(fd), &st);
00781
00782 if (S_ISREG(st.st_mode) && st.st_size < sizeof(*l)) {
00783 rc = RPMRC_NOTFOUND;
00784 goto exit;
00785 }
00786 }
00787 #endif
00788
00789 memset(l, 0, sizeof(*l));
00790 rc = readLead(fd, l);
00791 if (rc != RPMRC_OK)
00792 goto exit;
00793
00794 switch (l->major) {
00795 case 1:
00796 rpmError(RPMERR_NEWPACKAGE,
00797 _("packaging version 1 is not supported by this version of RPM\n"));
00798 rc = RPMRC_NOTFOUND;
00799 goto exit;
00800 break;
00801 case 2:
00802 case 3:
00803 case 4:
00804 break;
00805 default:
00806 rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 "
00807 "is supported by this version of RPM\n"));
00808 rc = RPMRC_NOTFOUND;
00809 goto exit;
00810 break;
00811 }
00812
00813
00814 msg = NULL;
00815 rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
00816 switch (rc) {
00817 default:
00818 rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed: %s"), fn,
00819 (msg && *msg ? msg : "\n"));
00820 msg = _free(msg);
00821 goto exit;
00822 break;
00823 case RPMRC_OK:
00824 if (sigh == NULL) {
00825 rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn);
00826 rc = RPMRC_FAIL;
00827 goto exit;
00828 }
00829 break;
00830 }
00831 msg = _free(msg);
00832
00833 #define _chk(_mask) (sigtag == 0 && !(vsflags & (_mask)))
00834
00835
00836
00837
00838
00839
00840
00841 sigtag = 0;
00842 opx = 0;
00843 vsflags = rpmtsVSFlags(ts);
00844 if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_DSA)) {
00845 sigtag = RPMSIGTAG_DSA;
00846 } else
00847 if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_RSA)) {
00848 sigtag = RPMSIGTAG_RSA;
00849 } else
00850 if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD) &&
00851 headerIsEntry(sigh, RPMSIGTAG_GPG))
00852 {
00853 sigtag = RPMSIGTAG_GPG;
00854 fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
00855 opx = RPMTS_OP_SIGNATURE;
00856 } else
00857 if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD) &&
00858 headerIsEntry(sigh, RPMSIGTAG_PGP))
00859 {
00860 sigtag = RPMSIGTAG_PGP;
00861 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00862 opx = RPMTS_OP_SIGNATURE;
00863 } else
00864 if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, RPMSIGTAG_SHA1)) {
00865 sigtag = RPMSIGTAG_SHA1;
00866 } else
00867 if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
00868 headerIsEntry(sigh, RPMSIGTAG_MD5))
00869 {
00870 sigtag = RPMSIGTAG_MD5;
00871 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00872 opx = RPMTS_OP_DIGEST;
00873 }
00874
00875
00876 h = NULL;
00877 msg = NULL;
00878
00879
00880
00881 if (opx > 0)
00882 (void) rpmswEnter(rpmtsOp(ts, opx), 0);
00883
00884 nb = -fd->stats->ops[FDSTAT_READ].bytes;
00885 rc = rpmReadHeader(ts, fd, &h, &msg);
00886 nb += fd->stats->ops[FDSTAT_READ].bytes;
00887
00888 if (opx > 0)
00889 (void) rpmswExit(rpmtsOp(ts, opx), nb);
00890
00891 if (rc != RPMRC_OK || h == NULL) {
00892 rpmError(RPMERR_FREAD, _("%s: headerRead failed: %s"), fn,
00893 (msg && *msg ? msg : "\n"));
00894 msg = _free(msg);
00895 goto exit;
00896 }
00897 msg = _free(msg);
00898
00899
00900 if (sigtag == 0) {
00901 rc = RPMRC_OK;
00902 goto exit;
00903 }
00904
00905 dig = rpmtsDig(ts);
00906 if (dig == NULL) {
00907 rc = RPMRC_FAIL;
00908 goto exit;
00909 }
00910 dig->nbytes = 0;
00911
00912
00913 sig = NULL;
00914 xx = headerGetEntry(sigh, sigtag, &sigtype, (void **) &sig, &siglen);
00915 if (sig == NULL) {
00916 rc = RPMRC_FAIL;
00917 goto exit;
00918 }
00919 (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
00920
00921 switch (sigtag) {
00922 case RPMSIGTAG_RSA:
00923
00924 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00925 if (dig->signature.version != 3 && dig->signature.version != 4) {
00926 rpmMessage(RPMMESS_ERROR,
00927 _("skipping package %s with unverifiable V%u signature\n"),
00928 fn, dig->signature.version);
00929 rc = RPMRC_FAIL;
00930 goto exit;
00931 }
00932 { void * uh = NULL;
00933 int_32 uht;
00934 int_32 uhc;
00935
00936 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
00937 break;
00938 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00939 dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
00940 (void) rpmDigestUpdate(dig->hdrmd5ctx, header_magic, sizeof(header_magic));
00941 dig->nbytes += sizeof(header_magic);
00942 (void) rpmDigestUpdate(dig->hdrmd5ctx, uh, uhc);
00943 dig->nbytes += uhc;
00944 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00945 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;
00946 uh = headerFreeData(uh, uht);
00947 } break;
00948 case RPMSIGTAG_DSA:
00949
00950 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00951 if (dig->signature.version != 3 && dig->signature.version != 4) {
00952 rpmMessage(RPMMESS_ERROR,
00953 _("skipping package %s with unverifiable V%u signature\n"),
00954 fn, dig->signature.version);
00955 rc = RPMRC_FAIL;
00956 goto exit;
00957 }
00958
00959 case RPMSIGTAG_SHA1:
00960 { void * uh = NULL;
00961 int_32 uht;
00962 int_32 uhc;
00963
00964 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
00965 break;
00966 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00967 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00968 (void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic));
00969 dig->nbytes += sizeof(header_magic);
00970 (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
00971 dig->nbytes += uhc;
00972 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00973 if (sigtag == RPMSIGTAG_SHA1)
00974 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;
00975 uh = headerFreeData(uh, uht);
00976 } break;
00977 case RPMSIGTAG_GPG:
00978 case RPMSIGTAG_PGP5:
00979 case RPMSIGTAG_PGP:
00980
00981 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00982
00983 if (dig->signature.version != 3 && dig->signature.version != 4) {
00984 rpmMessage(RPMMESS_ERROR,
00985 _("skipping package %s with unverifiable V%u signature\n"),
00986 fn, dig->signature.version);
00987 rc = RPMRC_FAIL;
00988 goto exit;
00989 }
00990
00991 case RPMSIGTAG_MD5:
00992
00993 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00994 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
00995 dig->nbytes += count;
00996 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00997 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;
00998 dig->nbytes += nb;
00999 if (count < 0) {
01000 rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
01001 fn, Fstrerror(fd));
01002 rc = RPMRC_FAIL;
01003 goto exit;
01004 }
01005
01006
01007 for (i = fd->ndigests - 1; i >= 0; i--) {
01008 FDDIGEST_t fddig = fd->digests + i;
01009 if (fddig->hashctx != NULL)
01010 switch (fddig->hashalgo) {
01011 case PGPHASHALGO_MD5:
01012 dig->md5ctx = fddig->hashctx;
01013 fddig->hashctx = NULL;
01014 break;
01015 case PGPHASHALGO_SHA1:
01016 case PGPHASHALGO_SHA256:
01017 case PGPHASHALGO_SHA384:
01018 case PGPHASHALGO_SHA512:
01019 dig->sha1ctx = fddig->hashctx;
01020 fddig->hashctx = NULL;
01021 break;
01022 default:
01023 break;
01024 }
01025 }
01026 break;
01027 }
01028
01031
01032 buf[0] = '\0';
01033
01034 rc = rpmVerifySignature(ts, buf);
01035 switch (rc) {
01036 case RPMRC_OK:
01037 rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
01038 break;
01039 case RPMRC_NOTTRUSTED:
01040 case RPMRC_NOKEY:
01041
01042 { int lvl = (rpmtsStashKeyid(ts) ? RPMMESS_DEBUG : RPMMESS_WARNING);
01043 rpmMessage(lvl, "%s: %s", fn, buf);
01044 } break;
01045 case RPMRC_NOTFOUND:
01046 rpmMessage(RPMMESS_WARNING, "%s: %s", fn, buf);
01047 break;
01048 default:
01049 case RPMRC_FAIL:
01050 rpmMessage(RPMMESS_ERROR, "%s: %s", fn, buf);
01051 break;
01052 }
01053
01054 exit:
01055 if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
01056
01057 legacyRetrofit(h, l);
01058
01059
01060 headerMergeLegacySigs(h, sigh);
01061
01062
01063
01064 *hdrp = headerLink(h);
01065
01066 }
01067 h = headerFree(h);
01068 rpmtsCleanDig(ts);
01069 sigh = rpmFreeSignature(sigh);
01070 return rc;
01071 }
01072
01078 rpmRC headerCheckPayloadFormat(Header h) {
01079 rpmRC rc = RPMRC_FAIL;
01080 int xx;
01081 const char *payloadfmt = NULL;
01082
01083 xx = headerGetEntry(h, RPMTAG_PAYLOADFORMAT, NULL,
01084 (void **)&payloadfmt, NULL);
01085
01086
01087
01088
01089 if (!payloadfmt)
01090 return RPMRC_OK;
01091
01092 if (payloadfmt && strncmp(payloadfmt, "cpio", strlen("cpio")) == 0) {
01093 rc = RPMRC_OK;
01094 } else {
01095 const char *nevra = hGetNEVRA(h, NULL);
01096 if (payloadfmt && strncmp(payloadfmt, "drpm", strlen("drpm")) == 0) {
01097 rpmMessage(RPMMESS_ERROR,
01098 _("%s is a Delta RPM and cannot be directly installed\n"),
01099 nevra);
01100 } else {
01101 rpmMessage(RPMMESS_ERROR,
01102 _("Unsupported payload (%s) in package %s\n"),
01103 payloadfmt ? payloadfmt : "none", nevra);
01104 }
01105 nevra = _free(nevra);
01106 }
01107 return rc;
01108 }
01109
01110
01111