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_WARNING,
00545 _("only V3 and V4 signatures can be verified, skipping V%u signature\n"),
00546 dig->signature.version);
00547 rpmtsCleanDig(ts);
00548 goto verifyinfo_exit;
00549 }
00550
00551 ildl[0] = htonl(ril);
00552 ildl[1] = (regionEnd - dataStart);
00553 ildl[1] = htonl(ildl[1]);
00554
00555 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00556 dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
00557
00558 b = (unsigned char *) header_magic;
00559 nb = sizeof(header_magic);
00560 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00561 dig->nbytes += nb;
00562
00563 b = (unsigned char *) ildl;
00564 nb = sizeof(ildl);
00565 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00566 dig->nbytes += nb;
00567
00568 b = (unsigned char *) pe;
00569 nb = (htonl(ildl[0]) * sizeof(*pe));
00570 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00571 dig->nbytes += nb;
00572
00573 b = (unsigned char *) dataStart;
00574 nb = htonl(ildl[1]);
00575 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00576 dig->nbytes += nb;
00577 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00578
00579 break;
00580 case RPMTAG_DSAHEADER:
00581
00582 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00583 if (dig->signature.version != 3 && dig->signature.version != 4) {
00584 rpmMessage(RPMMESS_WARNING,
00585 _("only V3 and V4 signatures can be verified, skipping V%u signature\n"),
00586 dig->signature.version);
00587 rpmtsCleanDig(ts);
00588 goto verifyinfo_exit;
00589 }
00590
00591 case RPMTAG_SHA1HEADER:
00592
00593 ildl[0] = htonl(ril);
00594 ildl[1] = (regionEnd - dataStart);
00595 ildl[1] = htonl(ildl[1]);
00596
00597
00598 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00599 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00600
00601 b = (unsigned char *) header_magic;
00602 nb = sizeof(header_magic);
00603 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00604 dig->nbytes += nb;
00605
00606 b = (unsigned char *) ildl;
00607 nb = sizeof(ildl);
00608 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00609 dig->nbytes += nb;
00610
00611 b = (unsigned char *) pe;
00612 nb = (htonl(ildl[0]) * sizeof(*pe));
00613 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00614 dig->nbytes += nb;
00615
00616 b = (unsigned char *) dataStart;
00617 nb = htonl(ildl[1]);
00618 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00619 dig->nbytes += nb;
00620 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00621
00622 break;
00623 default:
00624 sig = _free(sig);
00625 break;
00626 }
00627
00628
00629 buf[0] = '\0';
00630
00631 rc = rpmVerifySignature(ts, buf);
00632
00633
00634 buf[sizeof(buf)-1] = '\0';
00635 if (msg) *msg = xstrdup(buf);
00636
00637
00638
00639 if (hclvl == 1)
00640 rpmtsCleanDig(ts);
00641 if (info->tag == RPMTAG_SHA1HEADER)
00642 sig = _free(sig);
00643 hclvl--;
00644 return rc;
00645 }
00646
00647 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, const char ** msg)
00648 {
00649 char buf[BUFSIZ];
00650 int_32 block[4];
00651 int_32 il;
00652 int_32 dl;
00653 int_32 * ei = NULL;
00654 size_t uc;
00655 int_32 nb;
00656 Header h = NULL;
00657 const char * origin = 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
00728 origin = fdGetOPath(fd);
00729 if (origin != NULL)
00730 (void) headerSetOrigin(h, origin);
00731
00732 exit:
00733
00734 if (hdrp && h && rc == RPMRC_OK)
00735 *hdrp = headerLink(h);
00736
00737 ei = _free(ei);
00738 h = headerFree(h);
00739
00740
00741 if (msg != NULL && *msg == NULL && buf[0] != '\0') {
00742 buf[sizeof(buf)-1] = '\0';
00743 *msg = xstrdup(buf);
00744 }
00745
00746
00747 return rc;
00748 }
00749
00750
00751 rpmRC rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
00752 {
00753 pgpDig dig;
00754 byte buf[8*BUFSIZ];
00755 ssize_t count;
00756 struct rpmlead * l = alloca(sizeof(*l));
00757 Header sigh = NULL;
00758 int_32 sigtag;
00759 int_32 sigtype;
00760 const void * sig;
00761 int_32 siglen;
00762 rpmtsOpX opx;
00763 size_t nb;
00764 Header h = NULL;
00765 const char * msg;
00766 rpmVSFlags vsflags;
00767 rpmRC rc = RPMRC_FAIL;
00768 rpmop opsave = memset(alloca(sizeof(*opsave)), 0, sizeof(*opsave));
00769 int xx;
00770 int i;
00771
00772 if (hdrp) *hdrp = NULL;
00773
00774 #ifdef DYING
00775 { struct stat st;
00776
00777 memset(&st, 0, sizeof(st));
00778
00779 (void) fstat(Fileno(fd), &st);
00780
00781 if (S_ISREG(st.st_mode) && st.st_size < sizeof(*l)) {
00782 rc = RPMRC_NOTFOUND;
00783 goto exit;
00784 }
00785 }
00786 #endif
00787
00788
00789 (void) rpmswAdd(opsave, fdstat_op(fd, FDSTAT_READ));
00790
00791 memset(l, 0, sizeof(*l));
00792 rc = readLead(fd, l);
00793 if (rc != RPMRC_OK)
00794 goto exit;
00795
00796 switch (l->major) {
00797 case 1:
00798 rpmError(RPMERR_NEWPACKAGE,
00799 _("packaging version 1 is not supported by this version of RPM\n"));
00800 rc = RPMRC_NOTFOUND;
00801 goto exit;
00802 break;
00803 case 2:
00804 case 3:
00805 case 4:
00806 break;
00807 default:
00808 rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 "
00809 "is supported by this version of RPM\n"));
00810 rc = RPMRC_NOTFOUND;
00811 goto exit;
00812 break;
00813 }
00814
00815
00816 msg = NULL;
00817 rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
00818 switch (rc) {
00819 default:
00820 rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed: %s"), fn,
00821 (msg && *msg ? msg : "\n"));
00822 msg = _free(msg);
00823 goto exit;
00824 break;
00825 case RPMRC_OK:
00826 if (sigh == NULL) {
00827 rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn);
00828 rc = RPMRC_FAIL;
00829 goto exit;
00830 }
00831 break;
00832 }
00833 msg = _free(msg);
00834
00835 #define _chk(_mask) (sigtag == 0 && !(vsflags & (_mask)))
00836
00837
00838
00839
00840
00841
00842
00843 sigtag = 0;
00844 opx = 0;
00845 vsflags = rpmtsVSFlags(ts);
00846 if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_DSA)) {
00847 sigtag = RPMSIGTAG_DSA;
00848 } else
00849 if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_RSA)) {
00850 sigtag = RPMSIGTAG_RSA;
00851 } else
00852 if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD) &&
00853 headerIsEntry(sigh, RPMSIGTAG_GPG))
00854 {
00855 sigtag = RPMSIGTAG_GPG;
00856 fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
00857 opx = RPMTS_OP_SIGNATURE;
00858 } else
00859 if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD) &&
00860 headerIsEntry(sigh, RPMSIGTAG_PGP))
00861 {
00862 sigtag = RPMSIGTAG_PGP;
00863 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00864 opx = RPMTS_OP_SIGNATURE;
00865 } else
00866 if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, RPMSIGTAG_SHA1)) {
00867 sigtag = RPMSIGTAG_SHA1;
00868 } else
00869 if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
00870 headerIsEntry(sigh, RPMSIGTAG_MD5))
00871 {
00872 sigtag = RPMSIGTAG_MD5;
00873 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00874 opx = RPMTS_OP_DIGEST;
00875 }
00876
00877
00878 h = NULL;
00879 msg = NULL;
00880
00881
00882
00883 if (opx > 0)
00884 (void) rpmswEnter(rpmtsOp(ts, opx), 0);
00885
00886 nb = -fd->stats->ops[FDSTAT_READ].bytes;
00887 rc = rpmReadHeader(ts, fd, &h, &msg);
00888 nb += fd->stats->ops[FDSTAT_READ].bytes;
00889
00890 if (opx > 0)
00891 (void) rpmswExit(rpmtsOp(ts, opx), nb);
00892
00893 if (rc != RPMRC_OK || h == NULL) {
00894 rpmError(RPMERR_FREAD, _("%s: headerRead failed: %s"), fn,
00895 (msg && *msg ? msg : "\n"));
00896 msg = _free(msg);
00897 goto exit;
00898 }
00899 msg = _free(msg);
00900
00901
00902 if (sigtag == 0) {
00903 rc = RPMRC_OK;
00904 goto exit;
00905 }
00906
00907 dig = rpmtsDig(ts);
00908 if (dig == NULL) {
00909 rc = RPMRC_FAIL;
00910 goto exit;
00911 }
00912 dig->nbytes = 0;
00913
00914
00915 sig = NULL;
00916 xx = headerGetEntry(sigh, sigtag, &sigtype, (void **) &sig, &siglen);
00917 if (sig == NULL) {
00918 rc = RPMRC_FAIL;
00919 goto exit;
00920 }
00921 (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
00922
00923 switch (sigtag) {
00924 case RPMSIGTAG_RSA:
00925
00926 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00927 if (dig->signature.version != 3 && dig->signature.version != 4) {
00928 rpmMessage(RPMMESS_WARNING,
00929 _("only V3 and V4 signatures can be verified, skipping V%u signature\n"),
00930 dig->signature.version);
00931 rc = RPMRC_OK;
00932 goto exit;
00933 }
00934 { void * uh = NULL;
00935 int_32 uht;
00936 int_32 uhc;
00937
00938 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
00939 break;
00940 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00941 dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
00942 (void) rpmDigestUpdate(dig->hdrmd5ctx, header_magic, sizeof(header_magic));
00943 dig->nbytes += sizeof(header_magic);
00944 (void) rpmDigestUpdate(dig->hdrmd5ctx, uh, uhc);
00945 dig->nbytes += uhc;
00946 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00947 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;
00948 uh = headerFreeData(uh, uht);
00949 } break;
00950 case RPMSIGTAG_DSA:
00951
00952 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00953 if (dig->signature.version != 3 && dig->signature.version != 4) {
00954 rpmMessage(RPMMESS_WARNING,
00955 _("only V3 and V4 signatures can be verified, skipping V%u signature\n"),
00956 dig->signature.version);
00957 rc = RPMRC_OK;
00958 goto exit;
00959 }
00960
00961 case RPMSIGTAG_SHA1:
00962 { void * uh = NULL;
00963 int_32 uht;
00964 int_32 uhc;
00965
00966 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
00967 break;
00968 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00969 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00970 (void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic));
00971 dig->nbytes += sizeof(header_magic);
00972 (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
00973 dig->nbytes += uhc;
00974 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00975 if (sigtag == RPMSIGTAG_SHA1)
00976 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;
00977 uh = headerFreeData(uh, uht);
00978 } break;
00979 case RPMSIGTAG_GPG:
00980 case RPMSIGTAG_PGP5:
00981 case RPMSIGTAG_PGP:
00982
00983 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00984
00985 if (dig->signature.version != 3 && dig->signature.version != 4) {
00986 rpmMessage(RPMMESS_WARNING,
00987 _("only V3 and V4 signatures can be verified, skipping V%u signature\n"),
00988 dig->signature.version);
00989 rc = RPMRC_OK;
00990 goto exit;
00991 }
00992
00993 case RPMSIGTAG_MD5:
00994
00995 (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_DIGEST), 0);
00996 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
00997 dig->nbytes += count;
00998 (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_DIGEST), dig->nbytes);
00999 rpmtsOp(ts, RPMTS_OP_DIGEST)->count--;
01000 dig->nbytes += nb;
01001 if (count < 0) {
01002 rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
01003 fn, Fstrerror(fd));
01004 rc = RPMRC_FAIL;
01005 goto exit;
01006 }
01007
01008
01009 for (i = fd->ndigests - 1; i >= 0; i--) {
01010 FDDIGEST_t fddig = fd->digests + i;
01011 if (fddig->hashctx != NULL)
01012 switch (fddig->hashalgo) {
01013 case PGPHASHALGO_MD5:
01014 dig->md5ctx = fddig->hashctx;
01015 fddig->hashctx = NULL;
01016 break;
01017 case PGPHASHALGO_SHA1:
01018 case PGPHASHALGO_RIPEMD160:
01019 #if HAVE_BEECRYPT_API_H
01020 case PGPHASHALGO_SHA256:
01021 case PGPHASHALGO_SHA384:
01022 case PGPHASHALGO_SHA512:
01023 #endif
01024 dig->sha1ctx = fddig->hashctx;
01025 fddig->hashctx = NULL;
01026 break;
01027 default:
01028 break;
01029 }
01030 }
01031 break;
01032 }
01033
01036
01037 buf[0] = '\0';
01038
01039 rc = rpmVerifySignature(ts, buf);
01040 switch (rc) {
01041 case RPMRC_OK:
01042 rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
01043 break;
01044 case RPMRC_NOTTRUSTED:
01045 case RPMRC_NOKEY:
01046
01047 { int lvl = (rpmtsStashKeyid(ts) ? RPMMESS_DEBUG : RPMMESS_WARNING);
01048 rpmMessage(lvl, "%s: %s", fn, buf);
01049 } break;
01050 case RPMRC_NOTFOUND:
01051 rpmMessage(RPMMESS_WARNING, "%s: %s", fn, buf);
01052 break;
01053 default:
01054 case RPMRC_FAIL:
01055 rpmMessage(RPMMESS_ERROR, "%s: %s", fn, buf);
01056 break;
01057 }
01058
01059 exit:
01060 if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
01061
01062
01063 headerMergeLegacySigs(h, sigh);
01064
01065
01066
01067 *hdrp = headerLink(h);
01068
01069 }
01070 h = headerFree(h);
01071
01072
01073 (void) rpmswAdd(rpmtsOp(ts, RPMTS_OP_READHDR),
01074 fdstat_op(fd, FDSTAT_READ));
01075 (void) rpmswSub(rpmtsOp(ts, RPMTS_OP_READHDR),
01076 opsave);
01077
01078 rpmtsCleanDig(ts);
01079 sigh = rpmFreeSignature(sigh);
01080 return rc;
01081 }
01082