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
00033 static int _print_pkts = 0;
00034
00035
00036 static unsigned int nkeyids_max = 256;
00037
00038 static unsigned int nkeyids = 0;
00039
00040 static unsigned int nextkeyid = 0;
00041
00042 static unsigned int * keyids;
00043
00044
00045 static unsigned char header_magic[8] = {
00046 0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
00047 };
00048
00052
00053 static int typeAlign[16] = {
00054 1,
00055 1,
00056 1,
00057 2,
00058 4,
00059 8,
00060 1,
00061 1,
00062 1,
00063 1,
00064 0,
00065 0,
00066 0,
00067 0,
00068 0,
00069 0
00070 };
00071
00076 #define hdrchkTags(_ntags) ((_ntags) & 0xffff0000)
00077
00081 #define hdrchkType(_type) ((_type) < RPM_MIN_TYPE || (_type) > RPM_MAX_TYPE)
00082
00087 #define hdrchkData(_nbytes) ((_nbytes) & 0xff000000)
00088
00092 #define hdrchkAlign(_type, _off) ((_off) & (typeAlign[_type]-1))
00093
00097 #define hdrchkRange(_dl, _off) ((_off) < 0 || (_off) > (_dl))
00098
00099 void headerMergeLegacySigs(Header h, const Header sigh)
00100 {
00101 HFD_t hfd = (HFD_t) headerFreeData;
00102 HAE_t hae = (HAE_t) headerAddEntry;
00103 HeaderIterator hi;
00104 int_32 tag, type, count;
00105 const void * ptr;
00106 int xx;
00107
00108 for (hi = headerInitIterator(sigh);
00109 headerNextIterator(hi, &tag, &type, &ptr, &count);
00110 ptr = hfd(ptr, type))
00111 {
00112 switch (tag) {
00113
00114 case RPMSIGTAG_SIZE:
00115 tag = RPMTAG_SIGSIZE;
00116 break;
00117 case RPMSIGTAG_LEMD5_1:
00118 tag = RPMTAG_SIGLEMD5_1;
00119 break;
00120 case RPMSIGTAG_PGP:
00121 tag = RPMTAG_SIGPGP;
00122 break;
00123 case RPMSIGTAG_LEMD5_2:
00124 tag = RPMTAG_SIGLEMD5_2;
00125 break;
00126 case RPMSIGTAG_MD5:
00127 tag = RPMTAG_SIGMD5;
00128 break;
00129 case RPMSIGTAG_GPG:
00130 tag = RPMTAG_SIGGPG;
00131 break;
00132 case RPMSIGTAG_PGP5:
00133 tag = RPMTAG_SIGPGP5;
00134 break;
00135 case RPMSIGTAG_PAYLOADSIZE:
00136 tag = RPMTAG_ARCHIVESIZE;
00137 break;
00138 case RPMSIGTAG_SHA1:
00139 case RPMSIGTAG_DSA:
00140 case RPMSIGTAG_RSA:
00141 default:
00142 if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
00143 continue;
00144 break;
00145 }
00146 if (ptr == NULL) continue;
00147 if (!headerIsEntry(h, tag)) {
00148 if (hdrchkType(type))
00149 continue;
00150 if (count < 0 || hdrchkData(count))
00151 continue;
00152 switch(type) {
00153 case RPM_NULL_TYPE:
00154 continue;
00155 break;
00156 case RPM_CHAR_TYPE:
00157 case RPM_INT8_TYPE:
00158 case RPM_INT16_TYPE:
00159 case RPM_INT32_TYPE:
00160 if (count != 1)
00161 continue;
00162 break;
00163 case RPM_STRING_TYPE:
00164 case RPM_BIN_TYPE:
00165 if (count >= 16*1024)
00166 continue;
00167 break;
00168 case RPM_STRING_ARRAY_TYPE:
00169 case RPM_I18NSTRING_TYPE:
00170 continue;
00171 break;
00172 }
00173 xx = hae(h, tag, type, ptr, count);
00174 }
00175 }
00176 hi = headerFreeIterator(hi);
00177 }
00178
00179 Header headerRegenSigHeader(const Header h, int noArchiveSize)
00180 {
00181 HFD_t hfd = (HFD_t) headerFreeData;
00182 Header sigh = rpmNewSignature();
00183 HeaderIterator hi;
00184 int_32 tag, stag, type, count;
00185 const void * ptr;
00186 int xx;
00187
00188 for (hi = headerInitIterator(h);
00189 headerNextIterator(hi, &tag, &type, &ptr, &count);
00190 ptr = hfd(ptr, type))
00191 {
00192 switch (tag) {
00193
00194 case RPMTAG_SIGSIZE:
00195 stag = RPMSIGTAG_SIZE;
00196 break;
00197 case RPMTAG_SIGLEMD5_1:
00198 stag = RPMSIGTAG_LEMD5_1;
00199 break;
00200 case RPMTAG_SIGPGP:
00201 stag = RPMSIGTAG_PGP;
00202 break;
00203 case RPMTAG_SIGLEMD5_2:
00204 stag = RPMSIGTAG_LEMD5_2;
00205 break;
00206 case RPMTAG_SIGMD5:
00207 stag = RPMSIGTAG_MD5;
00208 break;
00209 case RPMTAG_SIGGPG:
00210 stag = RPMSIGTAG_GPG;
00211 break;
00212 case RPMTAG_SIGPGP5:
00213 stag = RPMSIGTAG_PGP5;
00214 break;
00215 case RPMTAG_ARCHIVESIZE:
00216
00217 if (noArchiveSize)
00218 continue;
00219 stag = RPMSIGTAG_PAYLOADSIZE;
00220 break;
00221 case RPMTAG_SHA1HEADER:
00222 case RPMTAG_DSAHEADER:
00223 case RPMTAG_RSAHEADER:
00224 default:
00225 if (!(tag >= HEADER_SIGBASE && tag < HEADER_TAGBASE))
00226 continue;
00227 stag = tag;
00228 break;
00229 }
00230 if (ptr == NULL) continue;
00231 if (!headerIsEntry(sigh, stag))
00232 xx = headerAddEntry(sigh, stag, type, ptr, count);
00233 }
00234 hi = headerFreeIterator(hi);
00235 return sigh;
00236 }
00237
00243 static int rpmtsStashKeyid(rpmts ts)
00244
00245
00246 {
00247 const void * sig = rpmtsSig(ts);
00248 pgpDig dig = rpmtsDig(ts);
00249 pgpDigParams sigp = rpmtsSignature(ts);
00250 unsigned int keyid;
00251 int i;
00252
00253 if (sig == NULL || dig == NULL || sigp == NULL)
00254 return 0;
00255
00256 keyid = pgpGrab(sigp->signid+4, 4);
00257 if (keyid == 0)
00258 return 0;
00259
00260 if (keyids != NULL)
00261 for (i = 0; i < nkeyids; i++) {
00262
00263 if (keyid == keyids[i])
00264 return 1;
00265
00266 }
00267
00268 if (nkeyids < nkeyids_max) {
00269 nkeyids++;
00270 keyids = xrealloc(keyids, nkeyids * sizeof(*keyids));
00271 }
00272
00273 if (keyids)
00274 keyids[nextkeyid] = keyid;
00275
00276 nextkeyid++;
00277 nextkeyid %= nkeyids_max;
00278
00279 return 0;
00280 }
00281
00282 int headerVerifyInfo(int il, int dl, const void * pev, void * iv, int negate)
00283 {
00284
00285 entryInfo pe = (entryInfo) pev;
00286
00287 entryInfo info = iv;
00288 int i;
00289
00290
00291 for (i = 0; i < il; i++) {
00292 info->tag = ntohl(pe[i].tag);
00293 info->type = ntohl(pe[i].type);
00294 info->offset = ntohl(pe[i].offset);
00295 if (negate)
00296 info->offset = -info->offset;
00297 info->count = ntohl(pe[i].count);
00298
00299 if (hdrchkType(info->type))
00300 return i;
00301 if (hdrchkAlign(info->type, info->offset))
00302 return i;
00303 if (!negate && hdrchkRange(dl, info->offset))
00304 return i;
00305 if (hdrchkData(info->count))
00306 return i;
00307
00308 }
00309
00310 return -1;
00311 }
00312
00326 rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, const char ** msg)
00327 {
00328 pgpDig dig;
00329 unsigned char buf[8*BUFSIZ];
00330 int_32 * ei = (int_32 *) uh;
00331
00332 int_32 il = ntohl(ei[0]);
00333 int_32 dl = ntohl(ei[1]);
00334
00335 entryInfo pe = (entryInfo) &ei[2];
00336
00337
00338 int_32 ildl[2];
00339 int_32 pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl;
00340 unsigned char * dataStart = (unsigned char *) (pe + il);
00341 indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry));
00342 entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info));
00343 const void * sig = NULL;
00344 const char * b;
00345 rpmVSFlags vsflags = rpmtsVSFlags(ts);
00346 int siglen = 0;
00347 int blen;
00348 size_t nb;
00349 int_32 ril = 0;
00350 unsigned char * regionEnd = NULL;
00351 rpmRC rc = RPMRC_FAIL;
00352 int xx;
00353 int i;
00354
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 uc, il, 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 #ifdef NOTYET
00466 case RPMTAG_RSAHEADER:
00467 #endif
00468 case RPMTAG_DSAHEADER:
00469 if (vsflags & RPMVSF_NODSAHEADER)
00470 break;
00471 if (entry->info.type != RPM_BIN_TYPE) {
00472 (void) snprintf(buf, sizeof(buf), _("hdr DSA: BAD, not binary\n"));
00473 goto exit;
00474 }
00475
00476 *info = entry->info;
00477
00478 siglen = info->count;
00479 break;
00480 default:
00481 break;
00482 }
00483 }
00484 rc = RPMRC_NOTFOUND;
00485
00486 exit:
00487
00488 if (rc != RPMRC_NOTFOUND) {
00489
00490 buf[sizeof(buf)-1] = '\0';
00491 if (msg) *msg = xstrdup(buf);
00492
00493 return rc;
00494 }
00495
00496
00497 if (info->tag == 0) {
00498 verifyinfo_exit:
00499 xx = headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0);
00500 if (xx != -1) {
00501 (void) snprintf(buf, sizeof(buf),
00502 _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00503 xx+1, entry->info.tag, entry->info.type,
00504 entry->info.offset, entry->info.count);
00505 rc = RPMRC_FAIL;
00506 } else {
00507 (void) snprintf(buf, sizeof(buf), "Header sanity check: OK\n");
00508 rc = RPMRC_OK;
00509 }
00510
00511 buf[sizeof(buf)-1] = '\0';
00512 if (msg) *msg = xstrdup(buf);
00513
00514 return rc;
00515 }
00516
00517
00518 dig = rpmtsDig(ts);
00519 if (dig == NULL)
00520 goto verifyinfo_exit;
00521 dig->nbytes = 0;
00522
00523
00524 sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen);
00525
00526 (void) rpmtsSetSig(ts, info->tag, info->type, sig, info->count);
00527
00528 switch (info->tag) {
00529 #ifdef NOTYET
00530 case RPMTAG_RSAHEADER:
00531
00532 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00533
00534 if (dig->signature.version != 3) {
00535 rpmMessage(RPMMESS_WARNING,
00536 _("only V3 signatures can be verified, skipping V%u signature\n"),
00537 dig->signature.version);
00538 rpmtsCleanDig(ts);
00539 goto verifyinfo_exit;
00540 }
00541
00542 ildl[0] = htonl(ril);
00543 ildl[1] = (regionEnd - dataStart);
00544 ildl[1] = htonl(ildl[1]);
00545
00546 dig->hdrmd5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
00547
00548 b = (unsigned char *) header_magic;
00549 nb = sizeof(header_magic);
00550 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00551 dig->nbytes += nb;
00552
00553 b = (unsigned char *) ildl;
00554 nb = sizeof(ildl);
00555 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00556 dig->nbytes += nb;
00557
00558 b = (unsigned char *) pe;
00559 nb = (htonl(ildl[0]) * sizeof(*pe));
00560 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00561 dig->nbytes += nb;
00562
00563 b = (unsigned char *) dataStart;
00564 nb = htonl(ildl[1]);
00565 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00566 dig->nbytes += nb;
00567
00568 break;
00569 #endif
00570 case RPMTAG_DSAHEADER:
00571
00572 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00573
00574 if (dig->signature.version != 3) {
00575 rpmMessage(RPMMESS_WARNING,
00576 _("only V3 signatures can be verified, skipping V%u signature\n"),
00577 dig->signature.version);
00578 rpmtsCleanDig(ts);
00579 goto verifyinfo_exit;
00580 }
00581
00582 case RPMTAG_SHA1HEADER:
00583
00584 ildl[0] = htonl(ril);
00585 ildl[1] = (regionEnd - dataStart);
00586 ildl[1] = htonl(ildl[1]);
00587
00588
00589 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00590
00591 b = (unsigned char *) header_magic;
00592 nb = sizeof(header_magic);
00593 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00594 dig->nbytes += nb;
00595
00596 b = (unsigned char *) ildl;
00597 nb = sizeof(ildl);
00598 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00599 dig->nbytes += nb;
00600
00601 b = (unsigned char *) pe;
00602 nb = (htonl(ildl[0]) * sizeof(*pe));
00603 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00604 dig->nbytes += nb;
00605
00606 b = (unsigned char *) dataStart;
00607 nb = htonl(ildl[1]);
00608 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00609 dig->nbytes += nb;
00610
00611 break;
00612 default:
00613 break;
00614 }
00615
00616
00617 buf[0] = '\0';
00618
00619 rc = rpmVerifySignature(ts, buf);
00620
00621
00622 buf[sizeof(buf)-1] = '\0';
00623 if (msg) *msg = xstrdup(buf);
00624
00625
00626 rpmtsCleanDig(ts);
00627 return rc;
00628 }
00629
00630 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, const char ** msg)
00631 {
00632 char buf[BUFSIZ];
00633 int_32 block[4];
00634 int_32 il;
00635 int_32 dl;
00636 int_32 * ei = NULL;
00637 size_t uc;
00638 int_32 nb;
00639 Header h = NULL;
00640 rpmRC rc = RPMRC_FAIL;
00641 int xx;
00642
00643
00644 buf[0] = '\0';
00645
00646 if (hdrp)
00647 *hdrp = NULL;
00648 if (msg)
00649 *msg = NULL;
00650
00651
00652 memset(block, 0, sizeof(block));
00653 if ((xx = timedRead(fd, (char *)block, sizeof(block))) != sizeof(block)) {
00654 (void) snprintf(buf, sizeof(buf),
00655 _("hdr size(%d): BAD, read returned %d\n"), sizeof(block), xx);
00656 goto exit;
00657 }
00658 if (memcmp(block, header_magic, sizeof(header_magic))) {
00659 (void) snprintf(buf, sizeof(buf), _("hdr magic: BAD\n"));
00660 goto exit;
00661 }
00662
00663 il = ntohl(block[2]);
00664
00665 if (hdrchkTags(il)) {
00666 (void) snprintf(buf, sizeof(buf),
00667 _("hdr tags: BAD, no. of tags(%d) out of range\n"), il);
00668
00669 goto exit;
00670 }
00671
00672 dl = ntohl(block[3]);
00673
00674 if (hdrchkData(dl)) {
00675 (void) snprintf(buf, sizeof(buf),
00676 _("hdr data: BAD, no. of bytes(%d) out of range\n"), dl);
00677 goto exit;
00678 }
00679
00680
00681 nb = (il * sizeof(struct entryInfo_s)) + dl;
00682
00683 uc = sizeof(il) + sizeof(dl) + nb;
00684 ei = xmalloc(uc);
00685
00686 ei[0] = block[2];
00687 ei[1] = block[3];
00688 if ((xx = timedRead(fd, (char *)&ei[2], nb)) != nb) {
00689 (void) snprintf(buf, sizeof(buf),
00690 _("hdr blob(%d): BAD, read returned %d\n"), nb, xx);
00691 goto exit;
00692 }
00693
00694
00695
00696 rc = headerCheck(ts, ei, uc, msg);
00697 if (rc != RPMRC_OK)
00698 goto exit;
00699
00700
00701 h = headerLoad(ei);
00702 if (h == NULL) {
00703 (void) snprintf(buf, sizeof(buf), _("hdr load: BAD\n"));
00704 goto exit;
00705 }
00706 h->flags |= HEADERFLAG_ALLOCATED;
00707 ei = NULL;
00708
00709 exit:
00710
00711 if (hdrp && h && rc == RPMRC_OK)
00712 *hdrp = headerLink(h);
00713
00714 ei = _free(ei);
00715 h = headerFree(h);
00716
00717
00718 if (msg != NULL && *msg == NULL && buf[0] != '\0') {
00719 buf[sizeof(buf)-1] = '\0';
00720 *msg = xstrdup(buf);
00721 }
00722
00723
00724 return rc;
00725 }
00726
00727
00728 int rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
00729 {
00730 pgpDig dig;
00731 byte buf[8*BUFSIZ];
00732 ssize_t count;
00733 struct rpmlead * l = alloca(sizeof(*l));
00734 Header sigh = NULL;
00735 int_32 sigtag;
00736 int_32 sigtype;
00737 const void * sig;
00738 int_32 siglen;
00739 Header h = NULL;
00740 const char * msg;
00741 int hmagic;
00742 rpmVSFlags vsflags;
00743 rpmRC rc = RPMRC_FAIL;
00744 int xx;
00745 int i;
00746
00747 if (hdrp) *hdrp = NULL;
00748 { struct stat st;
00749
00750 memset(&st, 0, sizeof(st));
00751
00752 (void) fstat(Fileno(fd), &st);
00753
00754 if (S_ISREG(st.st_mode) && st.st_size < sizeof(*l))
00755 goto exit;
00756 }
00757
00758 memset(l, 0, sizeof(*l));
00759 rc = readLead(fd, l);
00760 if (rc != RPMRC_OK) {
00761 rc = RPMRC_NOTFOUND;
00762 goto exit;
00763 }
00764
00765 switch (l->major) {
00766 case 1:
00767 rpmError(RPMERR_NEWPACKAGE,
00768 _("packaging version 1 is not supported by this version of RPM\n"));
00769 goto exit;
00770 break;
00771 case 2:
00772 case 3:
00773 case 4:
00774 break;
00775 default:
00776 rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 "
00777 "is supported by this version of RPM\n"));
00778 goto exit;
00779 break;
00780 }
00781
00782
00783 msg = NULL;
00784 rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
00785 switch (rc) {
00786 default:
00787 rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed: %s"), fn,
00788 (msg && *msg ? msg : "\n"));
00789 msg = _free(msg);
00790 goto exit;
00791 break;
00792 case RPMRC_OK:
00793 if (sigh == NULL) {
00794 rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn);
00795 rc = RPMRC_FAIL;
00796 goto exit;
00797 }
00798 break;
00799 }
00800 msg = _free(msg);
00801
00802 #define _chk(_mask) (sigtag == 0 && !(vsflags & (_mask)))
00803
00804
00805 sigtag = 0;
00806 vsflags = rpmtsVSFlags(ts);
00807 #ifdef DYING
00808 if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_DSA))
00809 sigtag = RPMSIGTAG_DSA;
00810 if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_RSA))
00811 sigtag = RPMSIGTAG_RSA;
00812 #endif
00813 if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD) &&
00814 headerIsEntry(sigh, RPMSIGTAG_GPG))
00815 {
00816 sigtag = RPMSIGTAG_GPG;
00817 fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
00818 }
00819 if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD) &&
00820 headerIsEntry(sigh, RPMSIGTAG_PGP))
00821 {
00822 sigtag = RPMSIGTAG_PGP;
00823 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00824 }
00825 #ifdef DYING
00826 if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, RPMSIGTAG_SHA1))
00827 sigtag = RPMSIGTAG_SHA1;
00828 #endif
00829 if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
00830 headerIsEntry(sigh, RPMSIGTAG_MD5))
00831 {
00832 sigtag = RPMSIGTAG_MD5;
00833 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00834 }
00835
00836
00837 h = NULL;
00838 msg = NULL;
00839 rc = rpmReadHeader(ts, fd, &h, &msg);
00840 if (rc != RPMRC_OK || h == NULL) {
00841 rpmError(RPMERR_FREAD, _("%s: headerRead failed: %s"), fn,
00842 (msg && *msg ? msg : "\n"));
00843 msg = _free(msg);
00844 goto exit;
00845 }
00846 msg = _free(msg);
00847
00848
00849 if (sigtag == 0) {
00850 rc = RPMRC_OK;
00851 goto exit;
00852 }
00853
00854 dig = rpmtsDig(ts);
00855 if (dig == NULL) {
00856 rc = RPMRC_FAIL;
00857 goto exit;
00858 }
00859 dig->nbytes = 0;
00860
00861
00862 sig = NULL;
00863 xx = headerGetEntry(sigh, sigtag, &sigtype, (void **) &sig, &siglen);
00864 if (sig == NULL) {
00865 rc = RPMRC_FAIL;
00866 goto exit;
00867 }
00868 (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
00869
00870 switch (sigtag) {
00871 case RPMSIGTAG_RSA:
00872
00873 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00874
00875 if (dig->signature.version != 3) {
00876 rpmMessage(RPMMESS_WARNING,
00877 _("only V3 signatures can be verified, skipping V%u signature\n"),
00878 dig->signature.version);
00879 rc = RPMRC_OK;
00880 goto exit;
00881 }
00882 { void * uh = NULL;
00883 int_32 uht;
00884 int_32 uhc;
00885
00886 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
00887 break;
00888 dig->md5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
00889 (void) rpmDigestUpdate(dig->md5ctx, header_magic, sizeof(header_magic));
00890 dig->nbytes += sizeof(header_magic);
00891 (void) rpmDigestUpdate(dig->md5ctx, uh, uhc);
00892 dig->nbytes += uhc;
00893 uh = headerFreeData(uh, uht);
00894 } break;
00895 case RPMSIGTAG_DSA:
00896
00897 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00898
00899 if (dig->signature.version != 3) {
00900 rpmMessage(RPMMESS_WARNING,
00901 _("only V3 signatures can be verified, skipping V%u signature\n"),
00902 dig->signature.version);
00903 rc = RPMRC_OK;
00904 goto exit;
00905 }
00906
00907 case RPMSIGTAG_SHA1:
00908 { void * uh = NULL;
00909 int_32 uht;
00910 int_32 uhc;
00911
00912 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
00913 break;
00914 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00915 (void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic));
00916 dig->nbytes += sizeof(header_magic);
00917 (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
00918 dig->nbytes += uhc;
00919 uh = headerFreeData(uh, uht);
00920 } break;
00921 case RPMSIGTAG_GPG:
00922 case RPMSIGTAG_PGP5:
00923 case RPMSIGTAG_PGP:
00924
00925 xx = pgpPrtPkts(sig, siglen, dig,
00926 (_print_pkts & rpmIsDebug()));
00927
00928
00929 if (dig->signature.version != 3) {
00930 rpmMessage(RPMMESS_WARNING,
00931 _("only V3 signatures can be verified, skipping V%u signature\n"),
00932 dig->signature.version);
00933 rc = RPMRC_OK;
00934 goto exit;
00935 }
00936
00937 case RPMSIGTAG_MD5:
00938
00939 hmagic = ((l->major >= 3) ? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
00940 dig->nbytes += headerSizeof(h, hmagic);
00941 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
00942 dig->nbytes += count;
00943 if (count < 0) {
00944 rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
00945 fn, Fstrerror(fd));
00946 rc = RPMRC_FAIL;
00947 goto exit;
00948 }
00949 dig->nbytes += count;
00950
00951
00952 for (i = fd->ndigests - 1; i >= 0; i--) {
00953 FDDIGEST_t fddig = fd->digests + i;
00954 if (fddig->hashctx == NULL)
00955 continue;
00956 if (fddig->hashalgo == PGPHASHALGO_MD5) {
00957 dig->md5ctx = fddig->hashctx;
00958 fddig->hashctx = NULL;
00959 continue;
00960 }
00961 if (fddig->hashalgo == PGPHASHALGO_SHA1) {
00962 dig->sha1ctx = fddig->hashctx;
00963 fddig->hashctx = NULL;
00964 continue;
00965 }
00966 }
00967 break;
00968 }
00969
00972
00973 buf[0] = '\0';
00974
00975 rc = rpmVerifySignature(ts, buf);
00976 switch (rc) {
00977 case RPMRC_OK:
00978 rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
00979 break;
00980 case RPMRC_NOTTRUSTED:
00981 case RPMRC_NOKEY:
00982
00983 { int lvl = (rpmtsStashKeyid(ts) ? RPMMESS_DEBUG : RPMMESS_WARNING);
00984 rpmMessage(lvl, "%s: %s", fn, buf);
00985 } break;
00986 case RPMRC_NOTFOUND:
00987 rpmMessage(RPMMESS_WARNING, "%s: %s", fn, buf);
00988 break;
00989 default:
00990 case RPMRC_FAIL:
00991 rpmMessage(RPMMESS_ERROR, "%s: %s", fn, buf);
00992 break;
00993 }
00994
00995 exit:
00996 if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
00997
00998 legacyRetrofit(h, l);
00999
01000
01001 headerMergeLegacySigs(h, sigh);
01002
01003
01004
01005 *hdrp = headerLink(h);
01006
01007 }
01008 h = headerFree(h);
01009 rpmtsCleanDig(ts);
01010 sigh = rpmFreeSignature(sigh);
01011 return rc;
01012 }
01013