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 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 entryInfo pe = (entryInfo) pev;
00284 entryInfo info = iv;
00285 int i;
00286
00287
00288 for (i = 0; i < il; i++) {
00289 info->tag = ntohl(pe[i].tag);
00290 info->type = ntohl(pe[i].type);
00291 info->offset = ntohl(pe[i].offset);
00292 if (negate)
00293 info->offset = -info->offset;
00294 info->count = ntohl(pe[i].count);
00295
00296 if (hdrchkType(info->type))
00297 return i;
00298 if (hdrchkAlign(info->type, info->offset))
00299 return i;
00300 if (!negate && hdrchkRange(dl, info->offset))
00301 return i;
00302 if (hdrchkData(info->count))
00303 return i;
00304
00305 }
00306
00307 return -1;
00308 }
00309
00323 rpmRC headerCheck(rpmts ts, const void * uh, size_t uc, const char ** msg)
00324 {
00325 pgpDig dig;
00326 unsigned char buf[8*BUFSIZ];
00327 int_32 * ei = (int_32 *) uh;
00328
00329 int_32 il = ntohl(ei[0]);
00330 int_32 dl = ntohl(ei[1]);
00331
00332 entryInfo pe = (entryInfo) &ei[2];
00333
00334
00335 int_32 ildl[2];
00336 int_32 pvlen = sizeof(ildl) + (il * sizeof(*pe)) + dl;
00337 unsigned char * dataStart = (unsigned char *) (pe + il);
00338 indexEntry entry = memset(alloca(sizeof(*entry)), 0, sizeof(*entry));
00339 entryInfo info = memset(alloca(sizeof(*info)), 0, sizeof(*info));
00340 const void * sig = NULL;
00341 const char * b;
00342 rpmVSFlags vsflags = rpmtsVSFlags(ts);
00343 int siglen = 0;
00344 int blen;
00345 size_t nb;
00346 int_32 ril = 0;
00347 unsigned char * end = NULL;
00348 rpmRC rc = RPMRC_FAIL;
00349 int xx;
00350 int i;
00351
00352 buf[0] = '\0';
00353
00354
00355 if (uc > 0 && pvlen != uc) {
00356 sprintf(buf, _("blob size(%d): BAD, 8 + 16 * il(%d) + dl(%d)\n"),
00357 uc, il, dl);
00358 goto exit;
00359 }
00360
00361
00362 xx = headerVerifyInfo(1, dl, pe, &entry->info, 0);
00363 if (xx != -1) {
00364 sprintf(buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00365 0, entry->info.tag, entry->info.type,
00366 entry->info.offset, entry->info.count);
00367 goto exit;
00368 }
00369
00370
00371
00372 if (!(entry->info.tag == RPMTAG_HEADERIMMUTABLE
00373 && entry->info.type == RPM_BIN_TYPE
00374 && entry->info.count == REGION_TAG_COUNT))
00375 {
00376 rc = RPMRC_NOTFOUND;
00377 goto exit;
00378 }
00379
00380
00381
00382 end = dataStart + entry->info.offset;
00383
00384 (void) memcpy(info, end, entry->info.count);
00385
00386 end += entry->info.count;
00387
00388
00389 xx = headerVerifyInfo(1, dl, info, &entry->info, 1);
00390 if (xx != -1 ||
00391 !(entry->info.tag == RPMTAG_HEADERIMMUTABLE
00392 && entry->info.type == RPM_BIN_TYPE
00393 && entry->info.count == REGION_TAG_COUNT))
00394 {
00395 sprintf(buf,
00396 _("region trailer: BAD, tag %d type %d offset %d count %d\n"),
00397 entry->info.tag, entry->info.type,
00398 entry->info.offset, entry->info.count);
00399 goto exit;
00400 }
00401
00402
00403 memset(info, 0, sizeof(*info));
00404
00405
00406
00407 ril = entry->info.offset/sizeof(*pe);
00408 if (ril > il) {
00409 sprintf(buf, _("region size: BAD, ril(%d) > il(%d)\n"), ril, il);
00410 goto exit;
00411 }
00412
00413
00414 for (i = ril; i < il; i++) {
00415 xx = headerVerifyInfo(1, dl, pe+i, &entry->info, 0);
00416 if (xx != -1) {
00417 sprintf(buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00418 i, entry->info.tag, entry->info.type,
00419 entry->info.offset, entry->info.count);
00420 goto exit;
00421 }
00422
00423 switch (entry->info.tag) {
00424 case RPMTAG_SHA1HEADER:
00425 if (vsflags & RPMVSF_NOSHA1HEADER)
00426 break;
00427 blen = 0;
00428
00429 for (b = dataStart + entry->info.offset; *b != '\0'; b++) {
00430 if (strchr("0123456789abcdefABCDEF", *b) == NULL)
00431 break;
00432 blen++;
00433 }
00434 if (entry->info.type != RPM_STRING_TYPE || *b != '\0' || blen != 40)
00435 goto exit;
00436
00437 if (info->tag == 0) {
00438
00439 *info = entry->info;
00440
00441 siglen = blen + 1;
00442 }
00443 break;
00444 #ifdef NOTYET
00445 case RPMTAG_RSAHEADER:
00446 #endif
00447 case RPMTAG_DSAHEADER:
00448 if (vsflags & RPMVSF_NODSAHEADER)
00449 break;
00450 if (entry->info.type != RPM_BIN_TYPE)
00451 goto exit;
00452
00453 *info = entry->info;
00454
00455 siglen = info->count;
00456 break;
00457 default:
00458 break;
00459 }
00460 }
00461 rc = RPMRC_NOTFOUND;
00462
00463 exit:
00464
00465 if (rc != RPMRC_NOTFOUND) {
00466 if (msg) *msg = xstrdup(buf);
00467 return rc;
00468 }
00469
00470
00471 if (info->tag == 0) {
00472 verifyinfo_exit:
00473 xx = headerVerifyInfo(ril-1, dl, pe+1, &entry->info, 0);
00474 if (xx != -1) {
00475 sprintf(buf, _("tag[%d]: BAD, tag %d type %d offset %d count %d\n"),
00476 xx+1, entry->info.tag, entry->info.type,
00477 entry->info.offset, entry->info.count);
00478 rc = RPMRC_FAIL;
00479 } else {
00480 sprintf(buf, "Header sanity check: OK\n");
00481 rc = RPMRC_OK;
00482 }
00483 if (msg) *msg = xstrdup(buf);
00484 return rc;
00485 }
00486
00487
00488 dig = rpmtsDig(ts);
00489 if (dig == NULL)
00490 goto verifyinfo_exit;
00491 dig->nbytes = 0;
00492
00493
00494 sig = memcpy(xmalloc(siglen), dataStart + info->offset, siglen);
00495
00496 (void) rpmtsSetSig(ts, info->tag, info->type, sig, info->count);
00497
00498 switch (info->tag) {
00499 #ifdef NOTYET
00500 case RPMTAG_RSAHEADER:
00501
00502 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00503
00504 if (dig->signature.version != 3) {
00505 rpmMessage(RPMMESS_WARNING,
00506 _("only V3 signatures can be verified, skipping V%u signature\n"),
00507 dig->signature.version);
00508 rpmtsCleanDig(ts);
00509 goto verifyinfo_exit;
00510 }
00511
00512 ildl[0] = htonl(ril);
00513 ildl[1] = (end - dataStart);
00514 ildl[1] = htonl(ildl[1]);
00515
00516 dig->hdrmd5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
00517
00518 b = (unsigned char *) header_magic;
00519 nb = sizeof(header_magic);
00520 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00521 dig->nbytes += nb;
00522
00523 b = (unsigned char *) ildl;
00524 nb = sizeof(ildl);
00525 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00526 dig->nbytes += nb;
00527
00528 b = (unsigned char *) pe;
00529 nb = (htonl(ildl[0]) * sizeof(*pe));
00530 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00531 dig->nbytes += nb;
00532
00533 b = (unsigned char *) dataStart;
00534 nb = htonl(ildl[1]);
00535 (void) rpmDigestUpdate(dig->hdrmd5ctx, b, nb);
00536 dig->nbytes += nb;
00537
00538 break;
00539 #endif
00540 case RPMTAG_DSAHEADER:
00541
00542 xx = pgpPrtPkts(sig, info->count, dig, (_print_pkts & rpmIsDebug()));
00543
00544 if (dig->signature.version != 3) {
00545 rpmMessage(RPMMESS_WARNING,
00546 _("only V3 signatures can be verified, skipping V%u signature\n"),
00547 dig->signature.version);
00548 rpmtsCleanDig(ts);
00549 goto verifyinfo_exit;
00550 }
00551
00552 case RPMTAG_SHA1HEADER:
00553
00554 ildl[0] = htonl(ril);
00555 ildl[1] = (end - dataStart);
00556 ildl[1] = htonl(ildl[1]);
00557
00558
00559 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00560
00561 b = (unsigned char *) header_magic;
00562 nb = sizeof(header_magic);
00563 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00564 dig->nbytes += nb;
00565
00566 b = (unsigned char *) ildl;
00567 nb = sizeof(ildl);
00568 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00569 dig->nbytes += nb;
00570
00571 b = (unsigned char *) pe;
00572 nb = (htonl(ildl[0]) * sizeof(*pe));
00573 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00574 dig->nbytes += nb;
00575
00576 b = (unsigned char *) dataStart;
00577 nb = htonl(ildl[1]);
00578 (void) rpmDigestUpdate(dig->hdrsha1ctx, b, nb);
00579 dig->nbytes += nb;
00580
00581 break;
00582 default:
00583 break;
00584 }
00585
00586
00587 buf[0] = '\0';
00588
00589 rc = rpmVerifySignature(ts, buf);
00590
00591
00592 if (msg != NULL)
00593 *msg = xstrdup(buf);
00594
00595
00596 rpmtsCleanDig(ts);
00597 return rc;
00598 }
00599
00600 rpmRC rpmReadHeader(rpmts ts, FD_t fd, Header *hdrp, const char ** msg)
00601 {
00602 int_32 block[4];
00603 int_32 il;
00604 int_32 dl;
00605 int_32 * ei = NULL;
00606 size_t uc;
00607 int_32 nb;
00608 Header h = NULL;
00609 rpmRC rc = RPMRC_FAIL;
00610
00611 if (hdrp)
00612 *hdrp = NULL;
00613
00614 if (timedRead(fd, (char *)block, sizeof(block)) != sizeof(block))
00615 goto exit;
00616 if (memcmp(block, header_magic, sizeof(header_magic)))
00617 goto exit;
00618 il = ntohl(block[2]);
00619 if (hdrchkTags(il))
00620 goto exit;
00621 dl = ntohl(block[3]);
00622 if (hdrchkData(dl))
00623 goto exit;
00624
00625 nb = (il * sizeof(struct entryInfo_s)) + dl;
00626 uc = sizeof(il) + sizeof(dl) + nb;
00627 ei = xmalloc(uc);
00628 ei[0] = block[2];
00629 ei[1] = block[3];
00630 if (timedRead(fd, (char *)&ei[2], nb) != nb)
00631 goto exit;
00632
00633
00634 rc = headerCheck(ts, ei, uc, msg);
00635 if (rc != RPMRC_OK)
00636 goto exit;
00637
00638
00639 h = headerLoad(ei);
00640 if (h == NULL)
00641 goto exit;
00642 h->flags |= HEADERFLAG_ALLOCATED;
00643 ei = NULL;
00644
00645 exit:
00646 if (rc == RPMRC_OK && hdrp && h)
00647 *hdrp = headerLink(h);
00648 ei = _free(ei);
00649 h = headerFree(h);
00650 return rc;
00651 }
00652
00653 int rpmReadPackageFile(rpmts ts, FD_t fd, const char * fn, Header * hdrp)
00654 {
00655 pgpDig dig;
00656 byte buf[8*BUFSIZ];
00657 ssize_t count;
00658 struct rpmlead * l = alloca(sizeof(*l));
00659 Header sigh = NULL;
00660 int_32 sigtag;
00661 int_32 sigtype;
00662 const void * sig;
00663 int_32 siglen;
00664 Header h = NULL;
00665 const char * msg;
00666 int hmagic;
00667 rpmVSFlags vsflags;
00668 rpmRC rc = RPMRC_FAIL;
00669 int xx;
00670 int i;
00671
00672 if (hdrp) *hdrp = NULL;
00673 { struct stat st;
00674
00675 memset(&st, 0, sizeof(st));
00676
00677 (void) fstat(Fileno(fd), &st);
00678
00679 if (S_ISREG(st.st_mode) && st.st_size < sizeof(*l))
00680 goto exit;
00681 }
00682
00683 memset(l, 0, sizeof(*l));
00684 rc = readLead(fd, l);
00685 if (rc != RPMRC_OK) {
00686 rc = RPMRC_NOTFOUND;
00687 goto exit;
00688 }
00689
00690 switch (l->major) {
00691 case 1:
00692 rpmError(RPMERR_NEWPACKAGE,
00693 _("packaging version 1 is not supported by this version of RPM\n"));
00694 goto exit;
00695 break;
00696 case 2:
00697 case 3:
00698 case 4:
00699 break;
00700 default:
00701 rpmError(RPMERR_NEWPACKAGE, _("only packaging with major numbers <= 4 "
00702 "is supported by this version of RPM\n"));
00703 goto exit;
00704 break;
00705 }
00706
00707
00708 rc = rpmReadSignature(fd, &sigh, l->signature_type);
00709 switch (rc) {
00710 default:
00711 rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed\n"), fn);
00712 goto exit;
00713 break;
00714 case RPMRC_OK:
00715 if (sigh == NULL) {
00716 rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn);
00717 rc = RPMRC_FAIL;
00718 goto exit;
00719 }
00720 break;
00721 }
00722
00723 #define _chk(_mask) (sigtag == 0 && !(vsflags & (_mask)))
00724
00725
00726 sigtag = 0;
00727 vsflags = rpmtsVSFlags(ts);
00728 #ifdef DYING
00729 if (_chk(RPMVSF_NODSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_DSA))
00730 sigtag = RPMSIGTAG_DSA;
00731 if (_chk(RPMVSF_NORSAHEADER) && headerIsEntry(sigh, RPMSIGTAG_RSA))
00732 sigtag = RPMSIGTAG_RSA;
00733 #endif
00734 if (_chk(RPMVSF_NODSA|RPMVSF_NEEDPAYLOAD) &&
00735 headerIsEntry(sigh, RPMSIGTAG_GPG))
00736 {
00737 sigtag = RPMSIGTAG_GPG;
00738 fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
00739 }
00740 if (_chk(RPMVSF_NORSA|RPMVSF_NEEDPAYLOAD) &&
00741 headerIsEntry(sigh, RPMSIGTAG_PGP))
00742 {
00743 sigtag = RPMSIGTAG_PGP;
00744 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00745 }
00746 #ifdef DYING
00747 if (_chk(RPMVSF_NOSHA1HEADER) && headerIsEntry(sigh, RPMSIGTAG_SHA1))
00748 sigtag = RPMSIGTAG_SHA1;
00749 #endif
00750 if (_chk(RPMVSF_NOMD5|RPMVSF_NEEDPAYLOAD) &&
00751 headerIsEntry(sigh, RPMSIGTAG_MD5))
00752 {
00753 sigtag = RPMSIGTAG_MD5;
00754 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00755 }
00756
00757
00758 h = NULL;
00759 msg = NULL;
00760 rc = rpmReadHeader(ts, fd, &h, &msg);
00761 if (rc != RPMRC_OK || h == NULL) {
00762 rpmError(RPMERR_FREAD, _("%s: headerRead failed: %s"), fn,
00763 (msg && *msg ? msg : "\n"));
00764 msg = _free(msg);
00765 goto exit;
00766 }
00767 msg = _free(msg);
00768
00769
00770 if (sigtag == 0) {
00771 rc = RPMRC_OK;
00772 goto exit;
00773 }
00774
00775 dig = rpmtsDig(ts);
00776 if (dig == NULL) {
00777 rc = RPMRC_FAIL;
00778 goto exit;
00779 }
00780 dig->nbytes = 0;
00781
00782
00783 sig = NULL;
00784 xx = headerGetEntry(sigh, sigtag, &sigtype, (void **) &sig, &siglen);
00785 if (sig == NULL) {
00786 rc = RPMRC_FAIL;
00787 goto exit;
00788 }
00789 (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
00790
00791 switch (sigtag) {
00792 case RPMSIGTAG_RSA:
00793
00794 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00795
00796 if (dig->signature.version != 3) {
00797 rpmMessage(RPMMESS_WARNING,
00798 _("only V3 signatures can be verified, skipping V%u signature\n"),
00799 dig->signature.version);
00800 rc = RPMRC_OK;
00801 goto exit;
00802 }
00803 { void * uh = NULL;
00804 int_32 uht;
00805 int_32 uhc;
00806
00807 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
00808 break;
00809 dig->md5ctx = rpmDigestInit(PGPHASHALGO_MD5, RPMDIGEST_NONE);
00810 (void) rpmDigestUpdate(dig->md5ctx, header_magic, sizeof(header_magic));
00811 dig->nbytes += sizeof(header_magic);
00812 (void) rpmDigestUpdate(dig->md5ctx, uh, uhc);
00813 dig->nbytes += uhc;
00814 uh = headerFreeData(uh, uht);
00815 } break;
00816 case RPMSIGTAG_DSA:
00817
00818 xx = pgpPrtPkts(sig, siglen, dig, (_print_pkts & rpmIsDebug()));
00819
00820 if (dig->signature.version != 3) {
00821 rpmMessage(RPMMESS_WARNING,
00822 _("only V3 signatures can be verified, skipping V%u signature\n"),
00823 dig->signature.version);
00824 rc = RPMRC_OK;
00825 goto exit;
00826 }
00827
00828 case RPMSIGTAG_SHA1:
00829 { void * uh = NULL;
00830 int_32 uht;
00831 int_32 uhc;
00832
00833 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc))
00834 break;
00835 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00836 (void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic));
00837 dig->nbytes += sizeof(header_magic);
00838 (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
00839 dig->nbytes += uhc;
00840 uh = headerFreeData(uh, uht);
00841 } break;
00842 case RPMSIGTAG_GPG:
00843 case RPMSIGTAG_PGP5:
00844 case RPMSIGTAG_PGP:
00845
00846 xx = pgpPrtPkts(sig, siglen, dig,
00847 (_print_pkts & rpmIsDebug()));
00848
00849
00850 if (dig->signature.version != 3) {
00851 rpmMessage(RPMMESS_WARNING,
00852 _("only V3 signatures can be verified, skipping V%u signature\n"),
00853 dig->signature.version);
00854 rc = RPMRC_OK;
00855 goto exit;
00856 }
00857
00858 case RPMSIGTAG_MD5:
00859
00860 hmagic = ((l->major >= 3) ? HEADER_MAGIC_YES : HEADER_MAGIC_NO);
00861 dig->nbytes += headerSizeof(h, hmagic);
00862 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
00863 dig->nbytes += count;
00864 if (count < 0) {
00865 rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"),
00866 fn, Fstrerror(fd));
00867 rc = RPMRC_FAIL;
00868 goto exit;
00869 }
00870 dig->nbytes += count;
00871
00872
00873 for (i = fd->ndigests - 1; i >= 0; i--) {
00874 FDDIGEST_t fddig = fd->digests + i;
00875 if (fddig->hashctx == NULL)
00876 continue;
00877 if (fddig->hashalgo == PGPHASHALGO_MD5) {
00878 dig->md5ctx = fddig->hashctx;
00879 fddig->hashctx = NULL;
00880 continue;
00881 }
00882 if (fddig->hashalgo == PGPHASHALGO_SHA1) {
00883 dig->sha1ctx = fddig->hashctx;
00884 fddig->hashctx = NULL;
00885 continue;
00886 }
00887 }
00888 break;
00889 }
00890
00893
00894 buf[0] = '\0';
00895
00896 rc = rpmVerifySignature(ts, buf);
00897 switch (rc) {
00898 case RPMRC_OK:
00899 rpmMessage(RPMMESS_DEBUG, "%s: %s", fn, buf);
00900 break;
00901 case RPMRC_NOTTRUSTED:
00902 case RPMRC_NOKEY:
00903
00904 { int lvl = (rpmtsStashKeyid(ts) ? RPMMESS_DEBUG : RPMMESS_WARNING);
00905 rpmMessage(lvl, "%s: %s", fn, buf);
00906 } break;
00907 case RPMRC_NOTFOUND:
00908 rpmMessage(RPMMESS_WARNING, "%s: %s", fn, buf);
00909 break;
00910 default:
00911 case RPMRC_FAIL:
00912 rpmMessage(RPMMESS_ERROR, "%s: %s", fn, buf);
00913 break;
00914 }
00915
00916 exit:
00917 if (rc != RPMRC_FAIL && h != NULL && hdrp != NULL) {
00918
00919 legacyRetrofit(h, l);
00920
00921
00922 headerMergeLegacySigs(h, sigh);
00923
00924
00925
00926 *hdrp = headerLink(h);
00927
00928 }
00929 h = headerFree(h);
00930 rpmtsCleanDig(ts);
00931 sigh = rpmFreeSignature(sigh);
00932 return rc;
00933 }