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 (!negate && 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
00380 if (!(entry->info.tag == RPMTAG_HEADERIMMUTABLE
00381 && entry->info.type == RPM_BIN_TYPE
00382 && entry->info.count == REGION_TAG_COUNT))
00383 {
00384 rc = RPMRC_NOTFOUND;
00385 goto exit;
00386 }
00387
00388
00389
00390 if (entry->info.offset >= dl) {
00391 (void) snprintf(buf, sizeof(buf),
00392 _("region offset: BAD, tag %d type %d offset %d count %d\n"),
00393 entry->info.tag, entry->info.type,
00394 entry->info.offset, entry->info.count);
00395 goto exit;
00396 }
00397
00398
00399 regionEnd = dataStart + entry->info.offset;
00400
00401
00402 (void) memcpy(info, regionEnd, REGION_TAG_COUNT);
00403
00404 regionEnd += REGION_TAG_COUNT;
00405
00406 xx = headerVerifyInfo(1, dl, info, &entry->info, 1);
00407 if (xx != -1 ||
00408 !(entry->info.tag == RPMTAG_HEADERIMMUTABLE
00409 && entry->info.type == RPM_BIN_TYPE
00410 && entry->info.count == REGION_TAG_COUNT))
00411 {
00412 (void) snprintf(buf, sizeof(buf),
00413 _("region trailer: BAD, tag %d type %d offset %d count %d\n"),
00414 entry->info.tag, entry->info.type,
00415 entry->info.offset, entry->info.count);
00416 goto exit;
00417 }
00418
00419
00420 memset(info, 0, sizeof(*info));
00421
00422
00423
00424 ril = entry->info.offset/sizeof(*pe);
00425 if ((entry->info.offset % sizeof(*pe)) || ril > il) {
00426 (void) snprintf(buf, sizeof(buf),
00427 _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
00428 goto exit;
00429 }
00430
00431
00432 for (i = ril; i < il; i++) {
00433 xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0);
00434 if (xx != -1) {
00435 (void) snprintf(buf, sizeof(buf),
00436 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00437 i, entry->info.tag, entry->info.type,
00438 entry->info.offset, entry->info.count);
00439 goto exit;
00440 }
00441
00442 switch (entry->info.tag) {
00443 case RPMTAG_SHA1HEADER:
00444 if (vsflags & RPMVSF_NOSHA1HEADER)
00445 break;
00446 blen = 0;
00447
00448 for (b = dataStart + entry->info.offset; *b != '\0'; b++) {
00449 if (strchr("0123456789abcdefABCDEF", *b) == NULL)
00450 break;
00451 blen++;
00452 }
00453 if (entry->info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40)
00454 {
00455 (void) snprintf(buf, sizeof(buf), _("hdr SHA1: BAD, not hex\n"));
00456 goto exit;
00457 }
00458
00459 if (info->tag == 0) {
00460
00461 *info = entry->info;
00462
00463 siglen = blen + 1;
00464 }
00465 break;
00466 case RPMTAG_RSAHEADER:
00467 if (vsflags & RPMVSF_NORSAHEADER)
00468 break;
00469 if (entry->info.type != RPM_BIN_TYPE) {
00470 (void) snprintf(buf, sizeof(buf), _("hdr RSA: BAD, not binary\n"));
00471 goto exit;
00472 }
00473
00474 *info = entry->info;
00475
00476 siglen = info->count;
00477 break;
00478 case RPMTAG_DSAHEADER:
00479 if (vsflags & RPMVSF_NODSAHEADER)
00480 break;
00481 if (entry->info.type != RPM_BIN_TYPE) {
00482 (void) snprintf(buf, sizeof(buf), _("hdr DSA: BAD, not binary\n"));
00483 goto exit;
00484 }
00485
00486 *info = entry->info;
00487
00488 siglen = info->count;
00489 break;
00490 default:
00491 break;
00492 }
00493 }
00494 rc = RPMRC_NOTFOUND;
00495
00496 exit:
00497
00498 if (rc != RPMRC_NOTFOUND) {
00499
00500 buf[sizeof(buf)-1] = '\0';
00501 if (msg) *msg = xstrdup(buf);
00502
00503 hclvl--;
00504 return rc;
00505 }
00506
00507
00508 if (info->tag == 0) {
00509 verifyinfo_exit:
00510 xx = headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0);
00511 if (xx != -1) {
00512 (void) snprintf(buf, sizeof(buf),
00513 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00514 xx+1, entry->info.tag, entry->info.type,
00515 entry->info.offset, entry->info.count);
00516 rc = RPMRC_FAIL;
00517 } else {
00518 (void) snprintf(buf, sizeof(buf), "Header sanity check: OK\n");
00519 rc = RPMRC_OK;
00520 }
00521
00522 buf[sizeof(buf)-1] = '\0';
00523 if (msg) *msg = xstrdup(buf);
00524
00525 hclvl--;
00526 return rc;
00527 }
00528
00529
00530 dig = rpmtsDig(ts);
00531 if (dig == NULL)
00532 goto verifyinfo_exit;
00533 dig->nbytes = 0;
00534
00535
00536 sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen);
00537
00538 (void) rpmtsSetSig(ts, info->tag, info->type, sig, info->count);
00539
00540 switch (info->tag) {
00541 case RPMTAG_RSAHEADER:
00542
00543 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00544 if (dig->signature.version != 3 && dig->signature.version != 4) {
00545 rpmMessage(RPMMESS_ERROR,
00546 _("skipping header with unverifiable V%u signature\n"),
00547 dig->signature.version);
00548 rpmtsCleanDig(ts);
00549 rc = RPMRC_FAIL;
00550 goto exit;
00551 }
00552
00553 ildl[0] = htonl(ril);
00554 ildl[1] = (regionEnd - dataStart);
00555 ildl[1] = htonl(ildl[1]);
00556
00557 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00558 dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
00559
00560 b = (unsigned char *) header_magic;
00561 nb = sizeof(header_magic);
00562 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00563 dig->nbytes += nb;
00564
00565 b = (unsigned char *) ildl;
00566 nb = sizeof(ildl);
00567 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00568 dig->nbytes += nb;
00569
00570 b = (unsigned char *) pe;
00571 nb = (htonl(ildl[0]) * sizeof(*pe));
00572 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00573 dig->nbytes += nb;
00574
00575 b = (unsigned char *) dataStart;
00576 nb = htonl(ildl[1]);
00577 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00578 dig->nbytes += nb;
00579 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00580
00581 break;
00582 case RPMTAG_DSAHEADER:
00583
00584 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00585 if (dig->signature.version != 3 && dig->signature.version != 4) {
00586 rpmMessage(RPMMESS_ERROR,
00587 _("skipping header with unverifiable V%u signature\n"),
00588 dig->signature.version);
00589 rpmtsCleanDig(ts);
00590 rc = RPMRC_FAIL;
00591 goto exit;
00592 }
00593
00594 case RPMTAG_SHA1HEADER:
00595
00596 ildl[0] = htonl(ril);
00597 ildl[1] = (regionEnd - dataStart);
00598 ildl[1] = htonl(ildl[1]);
00599
00600
00601 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00602 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00603
00604 b = (unsigned char *) header_magic;
00605 nb = sizeof(header_magic);
00606 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00607 dig->nbytes += nb;
00608
00609 b = (unsigned char *) ildl;
00610 nb = sizeof(ildl);
00611 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00612 dig->nbytes += nb;
00613
00614 b = (unsigned char *) pe;
00615 nb = (htonl(ildl[0]) * sizeof(*pe));
00616 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00617 dig->nbytes += nb;
00618
00619 b = (unsigned char *) dataStart;
00620 nb = htonl(ildl[1]);
00621 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00622 dig->nbytes += nb;
00623 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00624
00625 break;
00626 default:
00627 sig = _free(sig);
00628 break;
00629 }
00630
00631
00632 buf[0] = '\0';
00633
00634 rc = rpmVerifySignature(ts, buf);
00635
00636
00637 buf[sizeof(buf)-1] = '\0';
00638 if (msg) *msg = xstrdup(buf);
00639
00640
00641
00642 if (hclvl == 1)
00643 rpmtsCleanDig(ts);
00644 if (info->tag == RPMTAG_SHA1HEADER)
00645 sig = _free(sig);
00646 hclvl--;
00647 return rc;
00648 }
00649
00650 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, const char ** msg)
00651 {
00652 char buf[BUFSIZ];
00653 int_32 block[4];
00654 int_32 il;
00655 int_32 dl;
00656 int_32 * ei = NULL;
00657 size_t uc;
00658 int_32 nb;
00659 Header h = NULL;
00660 rpmRC rc = RPMRC_FAIL;
00661 int xx;
00662
00663
00664 buf[0] = '\0';
00665
00666 if (hdrp)
00667 *hdrp = NULL;
00668 if (msg)
00669 *msg = NULL;
00670
00671
00672 memset(block, 0, sizeof(block));
00673 if ((xx = timedRead(fd, (char *)block, sizeof(block))) != sizeof(block)) {
00674 (void) snprintf(buf, sizeof(buf),
00675 _("hdr size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx);
00676 goto exit;
00677 }
00678 if (memcmp(block, header_magic, sizeof(header_magic))) {
00679 (void) snprintf(buf, sizeof(buf), _("hdr magic: BAD\n"));
00680 goto exit;
00681 }
00682
00683 il = ntohl(block[2]);
00684
00685 if (hdrchkTags(il)) {
00686 (void) snprintf(buf, sizeof(buf),
00687 _("hdr tags: BAD, no. of tags(%d) out of range\n"), il);
00688
00689 goto exit;
00690 }
00691
00692 dl = ntohl(block[3]);
00693
00694 if (hdrchkData(dl)) {
00695 (void) snprintf(buf, sizeof(buf),
00696 _("hdr data: BAD, no. of bytes(%d) out of range\n"), dl);
00697 goto exit;
00698 }
00699
00700
00701 nb = (il * sizeof(struct entryInfo_s)) + dl;
00702
00703 uc = sizeof(il) + sizeof(dl) + nb;
00704 ei = xmalloc(uc);
00705
00706 ei[0] = block[2];
00707 ei[1] = block[3];
00708 if ((xx = timedRead(fd, (char *)&ei[2], nb)) != nb) {
00709 (void) snprintf(buf, sizeof(buf),
00710 _("hdr blob(%d): BAD, read returned %d\n"), nb, xx);
00711 goto exit;
00712 }
00713
00714
00715
00716 rc = headerCheck(ts, ei, uc, msg);
00717 if (rc != RPMRC_OK)
00718 goto exit;
00719
00720
00721 h = headerLoad(ei);
00722 if (h == NULL) {
00723 (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n"));
00724 goto exit;
00725 }
00726 h->flags |= HEADERFLAG_ALLOCATED;
00727 ei = NULL;
00728
00729 exit:
00730
00731 if (hdrp && h && rc == RPMRC_OK)
00732 *hdrp = headerLink(h);
00733
00734 ei = _free(ei);
00735 h = headerFree(h);
00736
00737
00738 if (msg != NULL && *msg == NULL && buf[0] != '\0') {
00739 buf[sizeof(buf)-1] = '\0';
00740 *msg = xstrdup(buf);
00741 }
00742
00743
00744 return rc;
00745 }
00746
00747
00748 rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
00749 {
00750 pgpDig dig;
00751 byte buf[8*BUFSIZ];
00752 ssize_t count;
00753 struct rpmlead * l = alloca(sizeof(*l));
00754 Header sigh = NULL;
00755 int_32 sigtag;
00756 int_32 sigtype;
00757 const void * sig;
00758 int_32 siglen;
00759 rpmtsOpX opx;
00760 size_t nb;
00761 Header h = NULL;
00762 const char * msg;
00763 rpmVSFlags vsflags;
00764 rpmRC rc = RPMRC_FAIL;
00765 int xx;
00766 int i;
00767
00768 if (hdrp) *hdrp = NULL;
00769
00770 #ifdef DYING
00771 { struct stat st;
00772
00773 memset(&st, 0, sizeof(st));
00774
00775 (void) fstat(Fileno(fd), &st);
00776
00777 if (S_ISREG(st.st_mode) && st.st_size < sizeof(*l)) {
00778 rc = RPMRC_NOTFOUND;
00779 goto exit;
00780 }
00781 }
00782 #endif
00783
00784 memset(l, 0, sizeof(*l));
00785 rc = readLead(fd, l);
00786 if (rc != RPMRC_OK)
00787 goto exit;
00788
00789 switch (l->major) {
00790 case 1:
00791 rpmError(RPMERR_NEWPACKAGE,
00792 _("packaging version 1 is not supported by this version of RPM\n"));
00793 rc = RPMRC_NOTFOUND;
00794 goto exit;
00795 break;
00796 case 2:
00797 case 3:
00798 case 4:
00799 break;
00800 default:
00801 rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 "
00802 "is supported by this version of RPM\n"));
00803 rc = RPMRC_NOTFOUND;
00804 goto exit;
00805 break;
00806 }
00807
00808
00809 msg = NULL;
00810 rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
00811 switch (rc) {
00812 default:
00813 rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed: %s"), fn,
00814 (msg && *msg ? msg : "\n"));
00815 msg = _free(msg);
00816 goto exit;
00817 break;
00818 case RPMRC_OK:
00819 if (sigh == NULL) {
00820 rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn);
00821 rc = RPMRC_FAIL;
00822 goto exit;
00823 }
00824 break;
00825 }
00826 msg = _free(msg);
00827
00828 #define _chk(_mask) (sigtag == 0 && !(vsflags & (_mask)))
00829
00830
00831
00832
00833
00834
00835
00836 sigtag = 0;
00837 opx = 0;
00838 vsflags = rpmtsVSFlags(ts);
00839 if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_DSA)) {
00840 sigtag = RPMSIGTAG_DSA;
00841 } else
00842 if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_RSA)) {
00843 sigtag = RPMSIGTAG_RSA;
00844 } else
00845 if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD) &&
00846 headerIsEntry(sigh, RPMSIGTAG_GPG))
00847 {
00848 sigtag = RPMSIGTAG_GPG;
00849 fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
00850 opx = RPMTS_OP_SIGNATURE;
00851 } else
00852 if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD) &&
00853 headerIsEntry(sigh, RPMSIGTAG_PGP))
00854 {
00855 sigtag = RPMSIGTAG_PGP;
00856 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00857 opx = RPMTS_OP_SIGNATURE;
00858 } else
00859 if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, RPMSIGTAG_SHA1)) {
00860 sigtag = RPMSIGTAG_SHA1;
00861 } else
00862 if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
00863 headerIsEntry(sigh, RPMSIGTAG_MD5))
00864 {
00865 sigtag = RPMSIGTAG_MD5;
00866 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00867 opx = RPMTS_OP_DIGEST;
00868 }
00869
00870
00871 h = NULL;
00872 msg = NULL;
00873
00874
00875
00876 if (opx > 0)
00877 (void) rpmswEnter(rpmtsOp(ts, opx), 0);
00878
00879 nb = -fd->stats->ops[FDSTAT_READ].bytes;
00880 rc = rpmReadHeader(ts, fd, &h, &msg);
00881 nb += fd->stats->ops[FDSTAT_READ].bytes;
00882
00883 if (opx > 0)
00884 (void) rpmswExit(rpmtsOp(ts, opx), nb);
00885
00886 if (rc != RPMRC_OK || h == NULL) {
00887 rpmError(RPMERR_FREAD, _("%s: headerRead failed: %s"), fn,
00888 (msg && *msg ? msg : "\n"));
00889 msg = _free(msg);
00890 goto exit;
00891 }
00892 msg = _free(msg);
00893
00894
00895 if (sigtag == 0) {
00896 rc = RPMRC_OK;
00897 goto exit;
00898 }
00899
00900 dig = rpmtsDig(ts);
00901 if (dig == NULL) {
00902 rc = RPMRC_FAIL;
00903 goto exit;
00904 }
00905 dig->nbytes = 0;
00906
00907
00908 sig = NULL;
00909 xx = headerGetEntry(sigh, sigtag, &sigtype, (void **) &sig, &siglen);
00910 if (sig == NULL) {
00911 rc = RPMRC_FAIL;
00912 goto exit;
00913 }
00914 (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
00915
00916 switch (sigtag) {
00917 case RPMSIGTAG_RSA:
00918
00919 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00920 if (dig->signature.version != 3 && dig->signature.version != 4) {
00921 rpmMessage(RPMMESS_ERROR,
00922 _("skipping package %s with unverifiable V%u signature\n"),
00923 fn, dig->signature.version);
00924 rc = RPMRC_FAIL;
00925 goto exit;
00926 }
00927 { void * uh = NULL;
00928 int_32 uht;
00929 int_32 uhc;
00930
00931 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
00932 break;
00933 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00934 dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
00935 (void) rpmDigestUpdate(dig->hdrmd5ctx, header_magic, sizeof(header_magic));
00936 dig->nbytes += sizeof(header_magic);
00937 (void) rpmDigestUpdate(dig->hdrmd5ctx, uh, uhc);
00938 dig->nbytes += uhc;
00939 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00940 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;
00941 uh = headerFreeData(uh, uht);
00942 } break;
00943 case RPMSIGTAG_DSA:
00944
00945 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00946 if (dig->signature.version != 3 && dig->signature.version != 4) {
00947 rpmMessage(RPMMESS_ERROR,
00948 _("skipping package %s with unverifiable V%u signature\n"),
00949 fn, dig->signature.version);
00950 rc = RPMRC_FAIL;
00951 goto exit;
00952 }
00953
00954 case RPMSIGTAG_SHA1:
00955 { void * uh = NULL;
00956 int_32 uht;
00957 int_32 uhc;
00958
00959 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
00960 break;
00961 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00962 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00963 (void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic));
00964 dig->nbytes += sizeof(header_magic);
00965 (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
00966 dig->nbytes += uhc;
00967 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00968 if (sigtag == RPMSIGTAG_SHA1)
00969 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;
00970 uh = headerFreeData(uh, uht);
00971 } break;
00972 case RPMSIGTAG_GPG:
00973 case RPMSIGTAG_PGP5:
00974 case RPMSIGTAG_PGP:
00975
00976 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00977
00978 if (dig->signature.version != 3 && dig->signature.version != 4) {
00979 rpmMessage(RPMMESS_ERROR,
00980 _("skipping package %s with unverifiable V%u signature\n"),
00981 fn, dig->signature.version);
00982 rc = RPMRC_FAIL;
00983 goto exit;
00984 }
00985
00986 case RPMSIGTAG_MD5:
00987
00988 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00989 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
00990 dig->nbytes += count;
00991 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00992 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;
00993 dig->nbytes += nb;
00994 if (count < 0) {
00995 rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
00996 fn, Fstrerror(fd));
00997 rc = RPMRC_FAIL;
00998 goto exit;
00999 }
01000
01001
01002 for (i = fd->ndigests - 1; i >= 0; i--) {
01003 FDDIGEST_t fddig = fd->digests + i;
01004 if (fddig->hashctx != NULL)
01005 switch (fddig->hashalgo) {
01006 case PGPHASHALGO_MD5:
01007 dig->md5ctx = fddig->hashctx;
01008 fddig->hashctx = NULL;
01009 break;
01010 case PGPHASHALGO_SHA1:
01011 #if HAVE_BEECRYPT_API_H
01012 case PGPHASHALGO_SHA256:
01013 case PGPHASHALGO_SHA384:
01014 case PGPHASHALGO_SHA512:
01015 #endif
01016 dig->sha1ctx = fddig->hashctx;
01017 fddig->hashctx = NULL;
01018 break;
01019 default:
01020 break;
01021 }
01022 }
01023 break;
01024 }
01025
01028
01029 buf[0] = '\0';
01030
01031 rc = rpmVerifySignature(ts, buf);
01032 switch (rc) {
01033 case RPMRC_OK:
01034 rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
01035 break;
01036 case RPMRC_NOTTRUSTED:
01037 case RPMRC_NOKEY:
01038
01039 { int lvl = (rpmtsStashKeyid(ts) ? RPMMESS_DEBUG : RPMMESS_WARNING);
01040 rpmMessage(lvl, "%s: %s", fn, buf);
01041 } break;
01042 case RPMRC_NOTFOUND:
01043 rpmMessage(RPMMESS_WARNING, "%s: %s", fn, buf);
01044 break;
01045 default:
01046 case RPMRC_FAIL:
01047 rpmMessage(RPMMESS_ERROR, "%s: %s", fn, buf);
01048 break;
01049 }
01050
01051 exit:
01052 if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
01053
01054 legacyRetrofit(h, l);
01055
01056
01057 headerMergeLegacySigs(h, sigh);
01058
01059
01060
01061 *hdrp = headerLink(h);
01062
01063 }
01064 h = headerFree(h);
01065 rpmtsCleanDig(ts);
01066 sigh = rpmFreeSignature(sigh);
01067 return rc;
01068 }
01069
01075 rpmRC headerCheckPayloadFormat(Header h) {
01076 rpmRC rc = RPMRC_FAIL;
01077 int xx;
01078 const char *payloadfmt = NULL;
01079
01080 xx = headerGetEntry(h, RPMTAG_PAYLOADFORMAT, NULL,
01081 (void **)&payloadfmt, NULL);
01082
01083
01084
01085
01086 if (!payloadfmt)
01087 return RPMRC_OK;
01088
01089 if (payloadfmt && strncmp(payloadfmt, "cpio", strlen("cpio")) == 0) {
01090 rc = RPMRC_OK;
01091 } else {
01092 const char *nevra = hGetNEVRA(h, NULL);
01093 if (payloadfmt && strncmp(payloadfmt, "drpm", strlen("drpm")) == 0) {
01094 rpmMessage(RPMMESS_ERROR,
01095 _("%s is a Delta RPM and cannot be directly installed\n"),
01096 nevra);
01097 } else {
01098 rpmMessage(RPMMESS_ERROR,
01099 _("Unsupported payload (%s) in package %s\n"),
01100 payloadfmt ? payloadfmt : "none", nevra);
01101 }
01102 nevra = _free(nevra);
01103 }
01104 return rc;
01105 }
01106
01107
01108