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