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 #ifdef NOTYET
00472 case RPMTAG_RSAHEADER:
00473 #endif
00474 case RPMTAG_DSAHEADER:
00475 if (vsflags & RPMVSF_NODSAHEADER)
00476 break;
00477 if (entry->info.type != RPM_BIN_TYPE) {
00478 (void) snprintf(buf, sizeof(buf), _("hdr DSA: BAD, not binary\n"));
00479 goto exit;
00480 }
00481
00482 *info = entry->info;
00483
00484 siglen = info->count;
00485 break;
00486 default:
00487 break;
00488 }
00489 }
00490 rc = RPMRC_NOTFOUND;
00491
00492 exit:
00493
00494 if (rc != RPMRC_NOTFOUND) {
00495
00496 buf[sizeof(buf)-1] = '\0';
00497 if (msg) *msg = xstrdup(buf);
00498
00499 hclvl--;
00500 return rc;
00501 }
00502
00503
00504 if (info->tag == 0) {
00505 verifyinfo_exit:
00506 xx = headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0);
00507 if (xx != -1) {
00508 (void) snprintf(buf, sizeof(buf),
00509 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00510 xx+1, entry->info.tag, entry->info.type,
00511 entry->info.offset, entry->info.count);
00512 rc = RPMRC_FAIL;
00513 } else {
00514 (void) snprintf(buf, sizeof(buf), "Header sanity check: OK\n");
00515 rc = RPMRC_OK;
00516 }
00517
00518 buf[sizeof(buf)-1] = '\0';
00519 if (msg) *msg = xstrdup(buf);
00520
00521 hclvl--;
00522 return rc;
00523 }
00524
00525
00526 dig = rpmtsDig(ts);
00527 if (dig == NULL)
00528 goto verifyinfo_exit;
00529 dig->nbytes = 0;
00530
00531
00532 sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen);
00533
00534 (void) rpmtsSetSig(ts, info->tag, info->type, sig, info->count);
00535
00536 switch (info->tag) {
00537 #ifdef NOTYET
00538 case RPMTAG_RSAHEADER:
00539
00540 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00541
00542 if (dig->signature.version != 3) {
00543 rpmMessage(RPMMESS_WARNING,
00544 _("only V3 signatures can be verified, skipping V%u signature\n"),
00545 dig->signature.version);
00546 rpmtsCleanDig(ts);
00547 goto verifyinfo_exit;
00548 }
00549
00550 ildl[0] = htonl(ril);
00551 ildl[1] = (regionEnd - dataStart);
00552 ildl[1] = htonl(ildl[1]);
00553
00554 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00555 dig->hdrmd5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
00556
00557 b = (unsigned char *) header_magic;
00558 nb = sizeof(header_magic);
00559 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00560 dig->nbytes += nb;
00561
00562 b = (unsigned char *) ildl;
00563 nb = sizeof(ildl);
00564 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00565 dig->nbytes += nb;
00566
00567 b = (unsigned char *) pe;
00568 nb = (htonl(ildl[0]) * sizeof(*pe));
00569 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00570 dig->nbytes += nb;
00571
00572 b = (unsigned char *) dataStart;
00573 nb = htonl(ildl[1]);
00574 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00575 dig->nbytes += nb;
00576 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00577
00578 break;
00579 #endif
00580 case RPMTAG_DSAHEADER:
00581
00582 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00583
00584 if (dig->signature.version != 3) {
00585 rpmMessage(RPMMESS_WARNING,
00586 _("only V3 signatures can be verified, skipping V%u signature\n"),
00587 dig->signature.version);
00588 rpmtsCleanDig(ts);
00589 goto verifyinfo_exit;
00590 }
00591
00592 case RPMTAG_SHA1HEADER:
00593
00594 ildl[0] = htonl(ril);
00595 ildl[1] = (regionEnd - dataStart);
00596 ildl[1] = htonl(ildl[1]);
00597
00598
00599 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00600 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00601
00602 b = (unsigned char *) header_magic;
00603 nb = sizeof(header_magic);
00604 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00605 dig->nbytes += nb;
00606
00607 b = (unsigned char *) ildl;
00608 nb = sizeof(ildl);
00609 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00610 dig->nbytes += nb;
00611
00612 b = (unsigned char *) pe;
00613 nb = (htonl(ildl[0]) * sizeof(*pe));
00614 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00615 dig->nbytes += nb;
00616
00617 b = (unsigned char *) dataStart;
00618 nb = htonl(ildl[1]);
00619 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00620 dig->nbytes += nb;
00621 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00622
00623 break;
00624 default:
00625 sig = _free(sig);
00626 break;
00627 }
00628
00629
00630 buf[0] = '\0';
00631
00632 rc = rpmVerifySignature(ts, buf);
00633
00634
00635 buf[sizeof(buf)-1] = '\0';
00636 if (msg) *msg = xstrdup(buf);
00637
00638
00639
00640 if (hclvl == 1)
00641 rpmtsCleanDig(ts);
00642 if (info->tag == RPMTAG_SHA1HEADER)
00643 sig = _free(sig);
00644 hclvl--;
00645 return rc;
00646 }
00647
00648 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, const char ** msg)
00649 {
00650 char buf[BUFSIZ];
00651 int_32 block[4];
00652 int_32 il;
00653 int_32 dl;
00654 int_32 * ei = NULL;
00655 size_t uc;
00656 int_32 nb;
00657 Header h = NULL;
00658 rpmRC rc = RPMRC_FAIL;
00659 int xx;
00660
00661
00662 buf[0] = '\0';
00663
00664 if (hdrp)
00665 *hdrp = NULL;
00666 if (msg)
00667 *msg = NULL;
00668
00669
00670 memset(block, 0, sizeof(block));
00671 if ((xx = timedRead(fd, (char *)block, sizeof(block))) != sizeof(block)) {
00672 (void) snprintf(buf, sizeof(buf),
00673 _("hdr size(%d): BAD, read returned %d\n"), (int)sizeof(block), xx);
00674 goto exit;
00675 }
00676 if (memcmp(block, header_magic, sizeof(header_magic))) {
00677 (void) snprintf(buf, sizeof(buf), _("hdr magic: BAD\n"));
00678 goto exit;
00679 }
00680
00681 il = ntohl(block[2]);
00682
00683 if (hdrchkTags(il)) {
00684 (void) snprintf(buf, sizeof(buf),
00685 _("hdr tags: BAD, no. of tags(%d) out of range\n"), il);
00686
00687 goto exit;
00688 }
00689
00690 dl = ntohl(block[3]);
00691
00692 if (hdrchkData(dl)) {
00693 (void) snprintf(buf, sizeof(buf),
00694 _("hdr data: BAD, no. of bytes(%d) out of range\n"), dl);
00695 goto exit;
00696 }
00697
00698
00699 nb = (il * sizeof(struct entryInfo_s)) + dl;
00700
00701 uc = sizeof(il) + sizeof(dl) + nb;
00702 ei = xmalloc(uc);
00703
00704 ei[0] = block[2];
00705 ei[1] = block[3];
00706 if ((xx = timedRead(fd, (char *)&ei[2], nb)) != nb) {
00707 (void) snprintf(buf, sizeof(buf),
00708 _("hdr blob(%d): BAD, read returned %d\n"), nb, xx);
00709 goto exit;
00710 }
00711
00712
00713
00714 rc = headerCheck(ts, ei, uc, msg);
00715 if (rc != RPMRC_OK)
00716 goto exit;
00717
00718
00719 h = headerLoad(ei);
00720 if (h == NULL) {
00721 (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n"));
00722 goto exit;
00723 }
00724 h->flags |= HEADERFLAG_ALLOCATED;
00725 ei = NULL;
00726
00727 exit:
00728
00729 if (hdrp && h && rc == RPMRC_OK)
00730 *hdrp = headerLink(h);
00731
00732 ei = _free(ei);
00733 h = headerFree(h);
00734
00735
00736 if (msg != NULL && *msg == NULL && buf[0] != '\0') {
00737 buf[sizeof(buf)-1] = '\0';
00738 *msg = xstrdup(buf);
00739 }
00740
00741
00742 return rc;
00743 }
00744
00745
00746 rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
00747 {
00748 pgpDig dig;
00749 byte buf[8*BUFSIZ];
00750 ssize_t count;
00751 struct rpmlead * l = alloca(sizeof(*l));
00752 Header sigh = NULL;
00753 int_32 sigtag;
00754 int_32 sigtype;
00755 const void * sig;
00756 int_32 siglen;
00757 Header h = NULL;
00758 const char * msg;
00759 int hmagic;
00760 rpmVSFlags vsflags;
00761 rpmRC rc = RPMRC_FAIL;
00762 int xx;
00763 int i;
00764
00765 if (hdrp) *hdrp = NULL;
00766
00767 #ifdef DYING
00768 { struct stat st;
00769
00770 memset(&st, 0, sizeof(st));
00771
00772 (void) fstat(Fileno(fd), &st);
00773
00774 if (S_ISREG(st.st_mode) && st.st_size < sizeof(*l)) {
00775 rc = RPMRC_NOTFOUND;
00776 goto exit;
00777 }
00778 }
00779 #endif
00780
00781 memset(l, 0, sizeof(*l));
00782 rc = readLead(fd, l);
00783 if (rc != RPMRC_OK)
00784 goto exit;
00785
00786 switch (l->major) {
00787 case 1:
00788 rpmError(RPMERR_NEWPACKAGE,
00789 _("packaging version 1 is not supported by this version of RPM\n"));
00790 rc = RPMRC_NOTFOUND;
00791 goto exit;
00792 break;
00793 case 2:
00794 case 3:
00795 case 4:
00796 break;
00797 default:
00798 rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 "
00799 "is supported by this version of RPM\n"));
00800 rc = RPMRC_NOTFOUND;
00801 goto exit;
00802 break;
00803 }
00804
00805
00806 msg = NULL;
00807 rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
00808 switch (rc) {
00809 default:
00810 rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed: %s"), fn,
00811 (msg && *msg ? msg : "\n"));
00812 msg = _free(msg);
00813 goto exit;
00814 break;
00815 case RPMRC_OK:
00816 if (sigh == NULL) {
00817 rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn);
00818 rc = RPMRC_FAIL;
00819 goto exit;
00820 }
00821 break;
00822 }
00823 msg = _free(msg);
00824
00825 #define _chk(_mask) (sigtag == 0 && !(vsflags & (_mask)))
00826
00827
00828 sigtag = 0;
00829 vsflags = rpmtsVSFlags(ts);
00830 #ifdef DYING
00831 if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_DSA))
00832 sigtag = RPMSIGTAG_DSA;
00833 if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_RSA))
00834 sigtag = RPMSIGTAG_RSA;
00835 #endif
00836 if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD) &&
00837 headerIsEntry(sigh, RPMSIGTAG_GPG))
00838 {
00839 sigtag = RPMSIGTAG_GPG;
00840 fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
00841 }
00842 if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD) &&
00843 headerIsEntry(sigh, RPMSIGTAG_PGP))
00844 {
00845 sigtag = RPMSIGTAG_PGP;
00846 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00847 }
00848 #ifdef DYING
00849 if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, RPMSIGTAG_SHA1))
00850 sigtag = RPMSIGTAG_SHA1;
00851 #endif
00852 if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
00853 headerIsEntry(sigh, RPMSIGTAG_MD5))
00854 {
00855 sigtag = RPMSIGTAG_MD5;
00856 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00857 }
00858
00859
00860 h = NULL;
00861 msg = NULL;
00862 rc = rpmReadHeader(ts, fd, &h, &msg);
00863 if (rc != RPMRC_OK || h == NULL) {
00864 rpmError(RPMERR_FREAD, _("%s: headerRead failed: %s"), fn,
00865 (msg && *msg ? msg : "\n"));
00866 msg = _free(msg);
00867 goto exit;
00868 }
00869 msg = _free(msg);
00870
00871
00872 if (sigtag == 0) {
00873 rc = RPMRC_OK;
00874 goto exit;
00875 }
00876
00877 dig = rpmtsDig(ts);
00878 if (dig == NULL) {
00879 rc = RPMRC_FAIL;
00880 goto exit;
00881 }
00882 dig->nbytes = 0;
00883
00884
00885 sig = NULL;
00886 xx = headerGetEntry(sigh, sigtag, &sigtype, (void **) &sig, &siglen);
00887 if (sig == NULL) {
00888 rc = RPMRC_FAIL;
00889 goto exit;
00890 }
00891 (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
00892
00893 switch (sigtag) {
00894 case RPMSIGTAG_RSA:
00895
00896 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00897
00898 if (dig->signature.version != 3) {
00899 rpmMessage(RPMMESS_WARNING,
00900 _("only V3 signatures can be verified, skipping V%u signature\n"),
00901 dig->signature.version);
00902 rc = RPMRC_OK;
00903 goto exit;
00904 }
00905 { void * uh = NULL;
00906 int_32 uht;
00907 int_32 uhc;
00908
00909 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
00910 break;
00911 dig->md5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
00912 (void) rpmDigestUpdate(dig->md5ctx, header_magic, sizeof(header_magic));
00913 dig->nbytes += sizeof(header_magic);
00914 (void) rpmDigestUpdate(dig->md5ctx, uh, uhc);
00915 dig->nbytes += uhc;
00916 uh = headerFreeData(uh, uht);
00917 } break;
00918 case RPMSIGTAG_DSA:
00919
00920 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00921
00922 if (dig->signature.version != 3) {
00923 rpmMessage(RPMMESS_WARNING,
00924 _("only V3 signatures can be verified, skipping V%u signature\n"),
00925 dig->signature.version);
00926 rc = RPMRC_OK;
00927 goto exit;
00928 }
00929
00930 case RPMSIGTAG_SHA1:
00931 { void * uh = NULL;
00932 int_32 uht;
00933 int_32 uhc;
00934
00935 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
00936 break;
00937 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00938 (void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic));
00939 dig->nbytes += sizeof(header_magic);
00940 (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
00941 dig->nbytes += uhc;
00942 uh = headerFreeData(uh, uht);
00943 } break;
00944 case RPMSIGTAG_GPG:
00945 case RPMSIGTAG_PGP5:
00946 case RPMSIGTAG_PGP:
00947
00948 xx = pgpPrtPkts(sig, siglen, dig,
00949 (_print_pkts & rpmIsDebug()));
00950
00951
00952 if (dig->signature.version != 3) {
00953 rpmMessage(RPMMESS_WARNING,
00954 _("only V3 signatures can be verified, skipping V%u signature\n"),
00955 dig->signature.version);
00956 rc = RPMRC_OK;
00957 goto exit;
00958 }
00959
00960 case RPMSIGTAG_MD5:
00961
00962 hmagic = ((l->major >= 3) ? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
00963 dig->nbytes += headerSizeof(h, hmagic);
00964 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
00965 dig->nbytes += count;
00966 if (count < 0) {
00967 rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
00968 fn, Fstrerror(fd));
00969 rc = RPMRC_FAIL;
00970 goto exit;
00971 }
00972 dig->nbytes += count;
00973
00974
00975 for (i = fd->ndigests - 1; i >= 0; i--) {
00976 FDDIGEST_t fddig = fd->digests + i;
00977 if (fddig->hashctx == NULL)
00978 continue;
00979 if (fddig->hashalgo == PGPHASHALGO_MD5) {
00980 dig->md5ctx = fddig->hashctx;
00981 fddig->hashctx = NULL;
00982 continue;
00983 }
00984 if (fddig->hashalgo == PGPHASHALGO_SHA1) {
00985 dig->sha1ctx = fddig->hashctx;
00986 fddig->hashctx = NULL;
00987 continue;
00988 }
00989 }
00990 break;
00991 }
00992
00995
00996 buf[0] = '\0';
00997
00998 rc = rpmVerifySignature(ts, buf);
00999 switch (rc) {
01000 case RPMRC_OK:
01001 rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
01002 break;
01003 case RPMRC_NOTTRUSTED:
01004 case RPMRC_NOKEY:
01005
01006 { int lvl = (rpmtsStashKeyid(ts) ? RPMMESS_DEBUG : RPMMESS_WARNING);
01007 rpmMessage(lvl, "%s: %s", fn, buf);
01008 } break;
01009 case RPMRC_NOTFOUND:
01010 rpmMessage(RPMMESS_WARNING, "%s: %s", fn, buf);
01011 break;
01012 default:
01013 case RPMRC_FAIL:
01014 rpmMessage(RPMMESS_ERROR, "%s: %s", fn, buf);
01015 break;
01016 }
01017
01018 exit:
01019 if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
01020
01021 legacyRetrofit(h, l);
01022
01023
01024 headerMergeLegacySigs(h, sigh);
01025
01026
01027
01028 *hdrp = headerLink(h);
01029
01030 }
01031 h = headerFree(h);
01032 rpmtsCleanDig(ts);
01033 sigh = rpmFreeSignature(sigh);
01034 return rc;
01035 }
01036