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