00001
00006 #include "system.h"
00007
00008 #include "rpmio_internal.h"
00009 #include <rpmcli.h>
00010
00011 #include "rpmdb.h"
00012
00013 #include "rpmts.h"
00014
00015 #include "rpmlead.h"
00016 #include "signature.h"
00017 #include "misc.h"
00018 #include "debug.h"
00019
00020
00021
00022
00023
00024
00025 int _print_pkts = 0;
00026
00029
00030 static int manageFile( FD_t *fdp,
00031 const char **fnp,
00032 int flags, int rc)
00033
00034
00035
00036 {
00037 const char *fn;
00038 FD_t fd;
00039
00040 if (fdp == NULL)
00041 return 1;
00042
00043
00044
00045 if (*fdp && (fnp == NULL || *fnp == NULL)) {
00046 (void) Fclose(*fdp);
00047 *fdp = NULL;
00048 return 0;
00049 }
00050
00051
00052 if (*fdp == NULL && fnp != NULL && *fnp != NULL) {
00053 fd = Fopen(*fnp, ((flags & O_WRONLY) ? "w.ufdio" : "r.ufdio"));
00054 if (fd == NULL || Ferror(fd)) {
00055 rpmError(RPMERR_OPEN, _("%s: open failed: %s\n"), *fnp,
00056 Fstrerror(fd));
00057 return 1;
00058 }
00059 *fdp = fd;
00060 return 0;
00061 }
00062
00063
00064 if (*fdp == NULL && (fnp == NULL || *fnp == NULL)) {
00065 fn = NULL;
00066 if (makeTempFile(NULL, (fnp ? &fn : NULL), &fd)) {
00067 rpmError(RPMERR_MAKETEMP, _("makeTempFile failed\n"));
00068 return 1;
00069 }
00070 if (fnp != NULL)
00071 *fnp = fn;
00072 *fdp = fdLink(fd, "manageFile return");
00073 fd = fdFree(fd, "manageFile return");
00074 return 0;
00075 }
00076
00077
00078
00079 if (*fdp != NULL && fnp != NULL && *fnp != NULL)
00080 return 0;
00081
00082
00083 return 1;
00084 }
00085
00086
00090
00091 static int copyFile(FD_t *sfdp, const char **sfnp,
00092 FD_t *tfdp, const char **tfnp)
00093
00094
00095
00096
00097 {
00098 unsigned char buf[BUFSIZ];
00099 ssize_t count;
00100 int rc = 1;
00101
00102 if (manageFile(sfdp, sfnp, O_RDONLY, 0))
00103 goto exit;
00104 if (manageFile(tfdp, tfnp, O_WRONLY|O_CREAT|O_TRUNC, 0))
00105 goto exit;
00106
00107 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), *sfdp)) > 0)
00108 {
00109 if (Fwrite(buf, sizeof(buf[0]), count, *tfdp) != count) {
00110 rpmError(RPMERR_FWRITE, _("%s: Fwrite failed: %s\n"), *tfnp,
00111 Fstrerror(*tfdp));
00112 goto exit;
00113 }
00114 }
00115 if (count < 0) {
00116 rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"), *sfnp, Fstrerror(*sfdp));
00117 goto exit;
00118 }
00119 if (Fflush(*tfdp) != 0) {
00120 rpmError(RPMERR_FWRITE, _("%s: Fflush failed: %s\n"), *tfnp,
00121 Fstrerror(*tfdp));
00122 }
00123
00124 rc = 0;
00125
00126 exit:
00127 if (*sfdp) (void) manageFile(sfdp, NULL, 0, rc);
00128 if (*tfdp) (void) manageFile(tfdp, NULL, 0, rc);
00129 return rc;
00130 }
00131
00132
00140 static int getSignid(Header sig, int sigtag, unsigned char * signid)
00141
00142
00143 {
00144 void * pkt = NULL;
00145 int_32 pkttyp = 0;
00146 int_32 pktlen = 0;
00147 int rc = 1;
00148
00149 if (headerGetEntry(sig, sigtag, &pkttyp, &pkt, &pktlen) && pkt != NULL) {
00150 pgpDig dig = pgpNewDig();
00151
00152 if (!pgpPrtPkts(pkt, pktlen, dig, 0)) {
00153
00154 memcpy(signid, dig->signature.signid, sizeof(dig->signature.signid));
00155
00156 rc = 0;
00157 }
00158
00159 dig = pgpFreeDig(dig);
00160 }
00161 pkt = headerFreeData(pkt, pkttyp);
00162 return rc;
00163 }
00164
00172 static int rpmReSign( rpmts ts,
00173 QVA_t qva, const char ** argv)
00174
00175
00176
00177
00178 {
00179 FD_t fd = NULL;
00180 FD_t ofd = NULL;
00181 struct rpmlead lead, *l = &lead;
00182 int_32 sigtag;
00183 const char *rpm, *trpm;
00184 const char *sigtarget = NULL;
00185 char tmprpm[1024+1];
00186 Header sigh = NULL;
00187 const char * msg;
00188 void * uh = NULL;
00189 int_32 uht, uhc;
00190 int res = EXIT_FAILURE;
00191 int deleting = (qva->qva_mode == RPMSIGN_DEL_SIGNATURE);
00192 rpmRC rc;
00193 int xx;
00194
00195 tmprpm[0] = '\0';
00196
00197
00198 if (argv)
00199 while ((rpm = *argv++) != NULL)
00200
00201 {
00202
00203 fprintf(stdout, "%s:\n", rpm);
00204
00205 if (manageFile(&fd, &rpm, O_RDONLY, 0))
00206 goto exit;
00207
00208
00209 memset(l, 0, sizeof(*l));
00210
00211 rc = readLead(fd, l);
00212 if (rc != RPMRC_OK) {
00213 rpmError(RPMERR_READLEAD, _("%s: not an rpm package\n"), rpm);
00214 goto exit;
00215 }
00216 switch (l->major) {
00217 case 1:
00218 rpmError(RPMERR_BADSIGTYPE, _("%s: Can't sign v1 packaging\n"), rpm);
00219 goto exit;
00220 break;
00221 case 2:
00222 rpmError(RPMERR_BADSIGTYPE, _("%s: Can't re-sign v2 packaging\n"), rpm);
00223 goto exit;
00224 break;
00225 default:
00226 break;
00227 }
00228
00229 msg = NULL;
00230 rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
00231 switch (rc) {
00232 default:
00233 rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed: %s"), rpm,
00234 (msg && *msg ? msg : "\n"));
00235 msg = _free(msg);
00236 goto exit;
00237 break;
00238 case RPMRC_OK:
00239 if (sigh == NULL) {
00240 rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), rpm);
00241 goto exit;
00242 }
00243 break;
00244 }
00245 msg = _free(msg);
00246
00247
00248
00249 if (copyFile(&fd, &rpm, &ofd, &sigtarget))
00250 goto exit;
00251
00252
00253
00254
00255 if (headerGetEntry(sigh, RPMTAG_HEADERSIGNATURES, &uht, &uh, &uhc)) {
00256 HeaderIterator hi;
00257 int_32 tag, type, count;
00258 hPTR_t ptr;
00259 Header oh;
00260 Header nh;
00261
00262 nh = headerNew();
00263 if (nh == NULL) {
00264 uh = headerFreeData(uh, uht);
00265 goto exit;
00266 }
00267
00268 oh = headerCopyLoad(uh);
00269 for (hi = headerInitIterator(oh);
00270 headerNextIterator(hi, &tag, &type, &ptr, &count);
00271 ptr = headerFreeData(ptr, type))
00272 {
00273 if (ptr)
00274 xx = headerAddEntry(nh, tag, type, ptr, count);
00275 }
00276 hi = headerFreeIterator(hi);
00277 oh = headerFree(oh);
00278
00279 sigh = headerFree(sigh);
00280 sigh = headerLink(nh);
00281 nh = headerFree(nh);
00282 }
00283
00284
00285 xx = headerRemoveEntry(sigh, RPMSIGTAG_LEMD5_1);
00286 xx = headerRemoveEntry(sigh, RPMSIGTAG_LEMD5_2);
00287 xx = headerRemoveEntry(sigh, RPMSIGTAG_BADSHA1_1);
00288 xx = headerRemoveEntry(sigh, RPMSIGTAG_BADSHA1_2);
00289
00290
00291 {
00292 enum rpmtagSignature const sigs[] = { RPMSIGTAG_SIZE,
00293 RPMSIGTAG_MD5,
00294 RPMSIGTAG_SHA1,
00295 };
00296 int i, nsigs = sizeof(sigs) / sizeof(enum rpmtagSignature);
00297 for (i = 0; i < nsigs; i++) {
00298 (void) headerRemoveEntry(sigh, sigs[i]);
00299 if (rpmAddSignature(sigh, sigtarget, sigs[i], qva->passPhrase))
00300 goto exit;
00301 }
00302 }
00303
00304 if (deleting) {
00305 xx = headerRemoveEntry(sigh, RPMSIGTAG_GPG);
00306 xx = headerRemoveEntry(sigh, RPMSIGTAG_DSA);
00307 xx = headerRemoveEntry(sigh, RPMSIGTAG_PGP5);
00308 xx = headerRemoveEntry(sigh, RPMSIGTAG_PGP);
00309 xx = headerRemoveEntry(sigh, RPMSIGTAG_RSA);
00310 } else
00311 if ((sigtag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0) {
00312 unsigned char oldsignid[8], newsignid[8];
00313
00314
00315 memset(oldsignid, 0, sizeof(oldsignid));
00316 xx = getSignid(sigh, sigtag, oldsignid);
00317
00318 switch (sigtag) {
00319 case RPMSIGTAG_DSA:
00320 xx = headerRemoveEntry(sigh, RPMSIGTAG_GPG);
00321 break;
00322 case RPMSIGTAG_RSA:
00323 xx = headerRemoveEntry(sigh, RPMSIGTAG_PGP);
00324 break;
00325 case RPMSIGTAG_GPG:
00326 xx = headerRemoveEntry(sigh, RPMSIGTAG_DSA);
00327
00328 case RPMSIGTAG_PGP5:
00329 case RPMSIGTAG_PGP:
00330 xx = headerRemoveEntry(sigh, RPMSIGTAG_RSA);
00331 break;
00332 }
00333
00334 xx = headerRemoveEntry(sigh, sigtag);
00335 if (rpmAddSignature(sigh, sigtarget, sigtag, qva->passPhrase)) {
00336 goto exit;
00337 }
00338
00339
00340 memset(newsignid, 0, sizeof(newsignid));
00341 if (memcmp(oldsignid, newsignid, sizeof(oldsignid))) {
00342
00343
00344 xx = getSignid(sigh, sigtag, newsignid);
00345
00346
00347 if (!memcmp(oldsignid, newsignid, sizeof(oldsignid))) {
00348
00349 rpmMessage(RPMMESS_WARNING,
00350 _("%s: was already signed by key ID %s, skipping\n"),
00351 rpm, pgpHexStr(newsignid+4, sizeof(newsignid)-4));
00352
00353
00354 xx = unlink(sigtarget);
00355 sigtarget = _free(sigtarget);
00356 continue;
00357 }
00358 }
00359 }
00360
00361
00362 sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES);
00363 if (sigh == NULL)
00364 goto exit;
00365
00366
00367
00368 strcpy(tmprpm, rpm);
00369 strcat(tmprpm, ".XXXXXX");
00370
00371 (void) mktemp(tmprpm);
00372 trpm = tmprpm;
00373
00374 if (manageFile(&ofd, &trpm, O_WRONLY|O_CREAT|O_TRUNC, 0))
00375 goto exit;
00376
00377 l->signature_type = RPMSIGTYPE_HEADERSIG;
00378 rc = writeLead(ofd, l);
00379 if (rc != RPMRC_OK) {
00380 rpmError(RPMERR_WRITELEAD, _("%s: writeLead failed: %s\n"), trpm,
00381 Fstrerror(ofd));
00382 goto exit;
00383 }
00384
00385 if (rpmWriteSignature(ofd, sigh)) {
00386 rpmError(RPMERR_SIGGEN, _("%s: rpmWriteSignature failed: %s\n"), trpm,
00387 Fstrerror(ofd));
00388 goto exit;
00389 }
00390
00391
00392
00393 if (copyFile(&fd, &sigtarget, &ofd, &trpm))
00394 goto exit;
00395
00396
00397
00398
00399 xx = unlink(rpm);
00400 xx = rename(trpm, rpm);
00401 tmprpm[0] = '\0';
00402
00403
00404 xx = unlink(sigtarget);
00405 sigtarget = _free(sigtarget);
00406 }
00407
00408
00409 res = 0;
00410
00411 exit:
00412 if (fd) (void) manageFile(&fd, NULL, 0, res);
00413 if (ofd) (void) manageFile(&ofd, NULL, 0, res);
00414
00415 sigh = rpmFreeSignature(sigh);
00416
00417 if (sigtarget) {
00418 xx = unlink(sigtarget);
00419 sigtarget = _free(sigtarget);
00420 }
00421 if (tmprpm[0] != '\0') {
00422 xx = unlink(tmprpm);
00423 tmprpm[0] = '\0';
00424 }
00425
00426 return res;
00427 }
00428
00429 rpmRC rpmcliImportPubkey(const rpmts ts, const unsigned char * pkt, ssize_t pktlen)
00430 {
00431 static unsigned char zeros[] =
00432 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
00433 const char * afmt = "%{pubkeys:armor}";
00434 const char * group = "Public Keys";
00435 const char * license = "pubkey";
00436 const char * buildhost = "localhost";
00437 int_32 pflags = (RPMSENSE_KEYRING|RPMSENSE_EQUAL);
00438 int_32 zero = 0;
00439 pgpDig dig = NULL;
00440 pgpDigParams pubp = NULL;
00441 const char * d = NULL;
00442 const char * enc = NULL;
00443 const char * n = NULL;
00444 const char * u = NULL;
00445 const char * v = NULL;
00446 const char * r = NULL;
00447 const char * evr = NULL;
00448 Header h = NULL;
00449 rpmRC rc = RPMRC_FAIL;
00450 char * t;
00451 int xx;
00452
00453 if (pkt == NULL || pktlen <= 0)
00454 return RPMRC_FAIL;
00455 if (rpmtsOpenDB(ts, (O_RDWR|O_CREAT)))
00456 return RPMRC_FAIL;
00457
00458 if ((enc = b64encode(pkt, pktlen, -1)) == NULL)
00459 goto exit;
00460
00461 dig = pgpNewDig();
00462
00463
00464 (void) pgpPrtPkts(pkt, pktlen, dig, 0);
00465 pubp = &dig->pubkey;
00466
00467 if (!memcmp(pubp->signid, zeros, sizeof(pubp->signid))
00468 || !memcmp(pubp->time, zeros, sizeof(pubp->time))
00469 || pubp->userid == NULL)
00470 goto exit;
00471
00472
00473 v = t = xmalloc(16+1);
00474 t = stpcpy(t, pgpHexStr(pubp->signid, sizeof(pubp->signid)));
00475
00476 r = t = xmalloc(8+1);
00477 t = stpcpy(t, pgpHexStr(pubp->time, sizeof(pubp->time)));
00478
00479 n = t = xmalloc(sizeof("gpg()")+8);
00480 t = stpcpy( stpcpy( stpcpy(t, "gpg("), v+8), ")");
00481
00482
00483 u = t = xmalloc(sizeof("gpg()")+strlen(pubp->userid));
00484 t = stpcpy( stpcpy( stpcpy(t, "gpg("), pubp->userid), ")");
00485
00486
00487 evr = t = xmalloc(sizeof("4X:-")+strlen(v)+strlen(r));
00488 t = stpcpy(t, (pubp->version == 4 ? "4:" : "3:"));
00489 t = stpcpy( stpcpy( stpcpy(t, v), "-"), r);
00490
00491
00492
00493
00494
00495 h = headerNew();
00496
00497 xx = headerAddOrAppendEntry(h, RPMTAG_PUBKEYS,
00498 RPM_STRING_ARRAY_TYPE, &enc, 1);
00499
00500 d = headerSprintf(h, afmt, rpmTagTable, rpmHeaderFormats, NULL);
00501 if (d == NULL)
00502 goto exit;
00503
00504 xx = headerAddEntry(h, RPMTAG_NAME, RPM_STRING_TYPE, "gpg-pubkey", 1);
00505 xx = headerAddEntry(h, RPMTAG_VERSION, RPM_STRING_TYPE, v+8, 1);
00506 xx = headerAddEntry(h, RPMTAG_RELEASE, RPM_STRING_TYPE, r, 1);
00507 xx = headerAddEntry(h, RPMTAG_DESCRIPTION, RPM_STRING_TYPE, d, 1);
00508 xx = headerAddEntry(h, RPMTAG_GROUP, RPM_STRING_TYPE, group, 1);
00509 xx = headerAddEntry(h, RPMTAG_LICENSE, RPM_STRING_TYPE, license, 1);
00510 xx = headerAddEntry(h, RPMTAG_SUMMARY, RPM_STRING_TYPE, u, 1);
00511
00512 xx = headerAddEntry(h, RPMTAG_SIZE, RPM_INT32_TYPE, &zero, 1);
00513
00514 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDENAME,
00515 RPM_STRING_ARRAY_TYPE, &u, 1);
00516 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION,
00517 RPM_STRING_ARRAY_TYPE, &evr, 1);
00518 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS,
00519 RPM_INT32_TYPE, &pflags, 1);
00520
00521 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDENAME,
00522 RPM_STRING_ARRAY_TYPE, &n, 1);
00523 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION,
00524 RPM_STRING_ARRAY_TYPE, &evr, 1);
00525 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS,
00526 RPM_INT32_TYPE, &pflags, 1);
00527
00528 xx = headerAddEntry(h, RPMTAG_RPMVERSION, RPM_STRING_TYPE, RPMVERSION, 1);
00529
00530
00531 xx = headerAddEntry(h, RPMTAG_BUILDHOST, RPM_STRING_TYPE, buildhost, 1);
00532 { int_32 tid = rpmtsGetTid(ts);
00533 xx = headerAddEntry(h, RPMTAG_INSTALLTIME, RPM_INT32_TYPE, &tid, 1);
00534
00535 xx = headerAddEntry(h, RPMTAG_BUILDTIME, RPM_INT32_TYPE, &tid, 1);
00536 }
00537
00538 #ifdef NOTYET
00539
00540 xx = headerAddEntry(h, RPMTAG_SOURCERPM, RPM_STRING_TYPE, fn, 1);
00541 #endif
00542
00543
00544 xx = rpmdbAdd(rpmtsGetRdb(ts), rpmtsGetTid(ts), h, NULL, NULL);
00545 if (xx != 0)
00546 goto exit;
00547 rc = RPMRC_OK;
00548
00549 exit:
00550
00551 h = headerFree(h);
00552 dig = pgpFreeDig(dig);
00553 n = _free(n);
00554 u = _free(u);
00555 v = _free(v);
00556 r = _free(r);
00557 evr = _free(evr);
00558 enc = _free(enc);
00559 d = _free(d);
00560
00561 return rc;
00562 }
00563
00572 static int rpmcliImportPubkeys(const rpmts ts,
00573 QVA_t qva,
00574 const char ** argv)
00575
00576
00577
00578
00579 {
00580 const char * fn;
00581 const unsigned char * pkt = NULL;
00582 ssize_t pktlen = 0;
00583 char * t = NULL;
00584 int res = 0;
00585 rpmRC rpmrc;
00586 int rc;
00587
00588 if (argv == NULL) return res;
00589
00590
00591
00592 while ((fn = *argv++) != NULL) {
00593
00594
00595 rpmtsClean(ts);
00596 pkt = _free(pkt);
00597 t = _free(t);
00598
00599
00600 if (fn[0] == '0' && fn[1] == 'x') {
00601 const char * s;
00602 int i;
00603 for (i = 0, s = fn+2; *s && isxdigit(*s); s++, i++)
00604 {};
00605 if (i == 8 || i == 16) {
00606 t = rpmExpand("%{_hkp_keyserver_query}", fn+2, NULL);
00607 if (t && *t != '%')
00608 fn = t;
00609 }
00610 }
00611
00612
00613 if ((rc = pgpReadPkts(fn, &pkt, &pktlen)) <= 0) {
00614 rpmError(RPMERR_IMPORT, _("%s: import read failed(%d).\n"), fn, rc);
00615 res++;
00616 continue;
00617 }
00618 if (rc != PGPARMOR_PUBKEY) {
00619 rpmError(RPMERR_IMPORT, _("%s: not an armored public key.\n"), fn);
00620 res++;
00621 continue;
00622 }
00623
00624
00625 if ((rpmrc = rpmcliImportPubkey(ts, pkt, pktlen)) != RPMRC_OK) {
00626 rpmError(RPMERR_IMPORT, _("%s: import failed.\n"), fn);
00627 res++;
00628 continue;
00629 }
00630
00631 }
00632
00633
00634 rpmtsClean(ts);
00635 pkt = _free(pkt);
00636 t = _free(t);
00637 return res;
00638 }
00639
00640
00641 static unsigned char header_magic[8] = {
00642 0x8e, 0xad, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00
00643 };
00644
00648 static int readFile(FD_t fd, const char * fn, pgpDig dig)
00649
00650
00651 {
00652 unsigned char buf[4*BUFSIZ];
00653 ssize_t count;
00654 int rc = 1;
00655 int i;
00656
00657 dig->nbytes = 0;
00658
00659
00660 { Header h = headerRead(fd, HEADER_MAGIC_YES);
00661 if (h == NULL) {
00662 rpmError(RPMERR_FREAD, _("%s: headerRead failed\n"), fn);
00663 goto exit;
00664 }
00665
00666 dig->nbytes += headerSizeof(h, HEADER_MAGIC_YES);
00667
00668 if (headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) {
00669 void * uh;
00670 int_32 uht, uhc;
00671
00672 if (!headerGetEntry(h, RPMTAG_HEADERIMMUTABLE, &uht, &uh, &uhc)
00673 || uh == NULL)
00674 {
00675 h = headerFree(h);
00676 rpmlog(RPMERR_FREAD,
00677 _("%s: Immutable header region could not be read. "
00678 "Corrupted package?\n"), fn);
00679 goto exit;
00680 }
00681 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00682 (void) rpmDigestUpdate(dig->hdrsha1ctx, header_magic, sizeof(header_magic));
00683 (void) rpmDigestUpdate(dig->hdrsha1ctx, uh, uhc);
00684 dig->hdrmd5ctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
00685 (void) rpmDigestUpdate(dig->hdrmd5ctx, header_magic, sizeof(header_magic));
00686 (void) rpmDigestUpdate(dig->hdrmd5ctx, uh, uhc);
00687 uh = headerFreeData(uh, uht);
00688 }
00689 h = headerFree(h);
00690 }
00691
00692
00693 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
00694 dig->nbytes += count;
00695 if (count < 0) {
00696 rpmError(RPMERR_FREAD, _("%s: Fread failed: %s\n"), fn, Fstrerror(fd));
00697 goto exit;
00698 }
00699
00700
00701 for (i = fd->ndigests - 1; i >= 0; i--) {
00702 FDDIGEST_t fddig = fd->digests + i;
00703 if (fddig->hashctx != NULL)
00704 switch (fddig->hashalgo) {
00705 case PGPHASHALGO_MD5:
00706 assert(dig->md5ctx == NULL);
00707 dig->md5ctx = fddig->hashctx;
00708 fddig->hashctx = NULL;
00709 break;
00710 case PGPHASHALGO_SHA1:
00711 case PGPHASHALGO_SHA256:
00712 case PGPHASHALGO_SHA384:
00713 case PGPHASHALGO_SHA512:
00714 assert(dig->sha1ctx == NULL);
00715 dig->sha1ctx = fddig->hashctx;
00716 fddig->hashctx = NULL;
00717 break;
00718 default:
00719 break;
00720 }
00721 }
00722
00723 rc = 0;
00724
00725 exit:
00726 return rc;
00727 }
00728
00729 int rpmVerifySignatures(QVA_t qva, rpmts ts, FD_t fd,
00730 const char * fn)
00731 {
00732 int res2, res3;
00733 struct rpmlead lead, *l = &lead;
00734 char result[1024];
00735 char buf[8192], * b;
00736 char missingKeys[7164], * m;
00737 char untrustedKeys[7164], * u;
00738 int_32 sigtag;
00739 int_32 sigtype;
00740 const void * sig;
00741 pgpDig dig;
00742 pgpDigParams sigp;
00743 int_32 siglen;
00744 Header sigh = NULL;
00745 HeaderIterator hi;
00746 const char * msg;
00747 int res = 0;
00748 int xx;
00749 rpmRC rc;
00750 int nodigests = !(qva->qva_flags & VERIFY_DIGEST);
00751 int nosignatures = !(qva->qva_flags & VERIFY_SIGNATURE);
00752
00753 {
00754
00755 memset(l, 0, sizeof(*l));
00756
00757 rc = readLead(fd, l);
00758 if (rc != RPMRC_OK) {
00759 rpmError(RPMERR_READLEAD, _("%s: not an rpm package\n"), fn);
00760 res++;
00761 goto exit;
00762 }
00763 switch (l->major) {
00764 case 1:
00765 rpmError(RPMERR_BADSIGTYPE, _("%s: No signature available (v1.0 RPM)\n"), fn);
00766 res++;
00767 goto exit;
00768 break;
00769 default:
00770 break;
00771 }
00772
00773 msg = NULL;
00774 rc = rpmReadSignature(fd, &sigh, l->signature_type, &msg);
00775 switch (rc) {
00776 default:
00777 rpmError(RPMERR_SIGGEN, _("%s: rpmReadSignature failed: %s"), fn,
00778 (msg && *msg ? msg : "\n"));
00779 msg = _free(msg);
00780 res++;
00781 goto exit;
00782 break;
00783 case RPMRC_OK:
00784 if (sigh == NULL) {
00785 rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), fn);
00786 res++;
00787 goto exit;
00788 }
00789 break;
00790 }
00791 msg = _free(msg);
00792
00793
00794 sigtag = 0;
00795 if (sigtag == 0 && !nosignatures) {
00796 if (headerIsEntry(sigh, RPMSIGTAG_DSA))
00797 sigtag = RPMSIGTAG_DSA;
00798 else if (headerIsEntry(sigh, RPMSIGTAG_RSA))
00799 sigtag = RPMSIGTAG_RSA;
00800 else if (headerIsEntry(sigh, RPMSIGTAG_GPG))
00801 sigtag = RPMSIGTAG_GPG;
00802 else if (headerIsEntry(sigh, RPMSIGTAG_PGP))
00803 sigtag = RPMSIGTAG_PGP;
00804 }
00805 if (sigtag == 0 && !nodigests) {
00806 if (headerIsEntry(sigh, RPMSIGTAG_MD5))
00807 sigtag = RPMSIGTAG_MD5;
00808 else if (headerIsEntry(sigh, RPMSIGTAG_SHA1))
00809 sigtag = RPMSIGTAG_SHA1;
00810 }
00811
00812 dig = rpmtsDig(ts);
00813 sigp = rpmtsSignature(ts);
00814
00815
00816 if (sigtag == RPMSIGTAG_RSA || sigtag == RPMSIGTAG_PGP) {
00817 xx = headerGetEntry(sigh, sigtag, &sigtype, &sig, &siglen);
00818 xx = pgpPrtPkts(sig, siglen, dig, 0);
00819 sig = headerFreeData(sig, sigtype);
00820
00821 if ((headerIsEntry(sigh, RPMSIGTAG_PGP)
00822 || headerIsEntry(sigh, RPMSIGTAG_PGP5))
00823 && dig->signature.hash_algo != PGPHASHALGO_MD5)
00824 fdInitDigest(fd, dig->signature.hash_algo, 0);
00825 }
00826
00827 if (headerIsEntry(sigh, RPMSIGTAG_PGP)
00828 || headerIsEntry(sigh, RPMSIGTAG_PGP5)
00829 || headerIsEntry(sigh, RPMSIGTAG_MD5))
00830 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00831 if (headerIsEntry(sigh, RPMSIGTAG_GPG))
00832 fdInitDigest(fd, PGPHASHALGO_SHA1, 0);
00833
00834
00835 if (dig == NULL || sigp == NULL || readFile(fd, fn, dig)) {
00836 res++;
00837 goto exit;
00838 }
00839
00840 res2 = 0;
00841 b = buf; *b = '\0';
00842 m = missingKeys; *m = '\0';
00843 u = untrustedKeys; *u = '\0';
00844 sprintf(b, "%s:%c", fn, (rpmIsVerbose() ? '\n' : ' ') );
00845 b += strlen(b);
00846
00847 for (hi = headerInitIterator(sigh);
00848 headerNextIterator(hi, &sigtag, &sigtype, &sig, &siglen) != 0;
00849 (void) rpmtsSetSig(ts, sigtag, sigtype, NULL, siglen))
00850 {
00851
00852 if (sig == NULL)
00853 continue;
00854
00855 (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
00856
00857
00858 pgpCleanDig(dig);
00859
00860 switch (sigtag) {
00861 case RPMSIGTAG_RSA:
00862 case RPMSIGTAG_DSA:
00863 case RPMSIGTAG_GPG:
00864 case RPMSIGTAG_PGP5:
00865 case RPMSIGTAG_PGP:
00866 if (nosignatures)
00867 continue;
00868 xx = pgpPrtPkts(sig, siglen, dig,
00869 (_print_pkts & rpmIsDebug()));
00870
00871 if (sigp->version != 3 && sigp->version != 4) {
00872 rpmError(RPMERR_SIGVFY,
00873 _("skipping package %s with unverifiable V%u signature\n"),
00874 fn, sigp->version);
00875 res++;
00876 goto exit;
00877 }
00878 break;
00879 case RPMSIGTAG_SHA1:
00880 if (nodigests)
00881 continue;
00882
00883 if (!nosignatures && sigtag == RPMSIGTAG_DSA)
00884 continue;
00885 break;
00886 case RPMSIGTAG_LEMD5_2:
00887 case RPMSIGTAG_LEMD5_1:
00888 case RPMSIGTAG_MD5:
00889 if (nodigests)
00890 continue;
00891
00892
00893
00894
00895 if (!nosignatures && sigtag == RPMSIGTAG_PGP)
00896 continue;
00897 break;
00898 default:
00899 continue;
00900 break;
00901 }
00902
00903 res3 = rpmVerifySignature(ts, result);
00904
00905
00906 if (res3) {
00907 if (rpmIsVerbose()) {
00908 b = stpcpy(b, " ");
00909 b = stpcpy(b, result);
00910 res2 = 1;
00911 } else {
00912 char *tempKey;
00913 switch (sigtag) {
00914 case RPMSIGTAG_SIZE:
00915 b = stpcpy(b, "SIZE ");
00916 res2 = 1;
00917 break;
00918 case RPMSIGTAG_SHA1:
00919 b = stpcpy(b, "SHA1 ");
00920 res2 = 1;
00921 break;
00922 case RPMSIGTAG_LEMD5_2:
00923 case RPMSIGTAG_LEMD5_1:
00924 case RPMSIGTAG_MD5:
00925 b = stpcpy(b, "MD5 ");
00926 res2 = 1;
00927 break;
00928 case RPMSIGTAG_RSA:
00929 b = stpcpy(b, "RSA ");
00930 res2 = 1;
00931 break;
00932 case RPMSIGTAG_PGP5:
00933 case RPMSIGTAG_PGP:
00934 switch (res3) {
00935 case RPMRC_NOKEY:
00936 res2 = 1;
00937
00938 case RPMRC_NOTTRUSTED:
00939 { int offset = 6;
00940 b = stpcpy(b, "(MD5) (PGP) ");
00941 tempKey = strstr(result, "ey ID");
00942 if (tempKey == NULL) {
00943 tempKey = strstr(result, "keyid:");
00944 offset = 9;
00945 }
00946 if (tempKey) {
00947 if (res3 == RPMRC_NOKEY) {
00948 m = stpcpy(m, " PGP#");
00949 m = stpncpy(m, tempKey + offset, 8);
00950 *m = '\0';
00951 } else {
00952 u = stpcpy(u, " PGP#");
00953 u = stpncpy(u, tempKey + offset, 8);
00954 *u = '\0';
00955 }
00956 }
00957 } break;
00958 default:
00959 b = stpcpy(b, "MD5 PGP ");
00960 res2 = 1;
00961 break;
00962 }
00963 break;
00964 case RPMSIGTAG_DSA:
00965 b = stpcpy(b, "(SHA1) DSA ");
00966 res2 = 1;
00967 break;
00968 case RPMSIGTAG_GPG:
00969
00970 switch (res3) {
00971 case RPMRC_NOKEY:
00972 b = stpcpy(b, "(GPG) ");
00973 m = stpcpy(m, " GPG#");
00974 tempKey = strstr(result, "ey ID");
00975 if (tempKey) {
00976 m = stpncpy(m, tempKey+6, 8);
00977 *m = '\0';
00978 }
00979 res2 = 1;
00980 break;
00981 default:
00982 b = stpcpy(b, "GPG ");
00983 res2 = 1;
00984 break;
00985 }
00986 break;
00987 default:
00988 b = stpcpy(b, "?UnknownSignatureType? ");
00989 res2 = 1;
00990 break;
00991 }
00992 }
00993 } else {
00994 if (rpmIsVerbose()) {
00995 b = stpcpy(b, " ");
00996 b = stpcpy(b, result);
00997 } else {
00998 switch (sigtag) {
00999 case RPMSIGTAG_SIZE:
01000 b = stpcpy(b, "size ");
01001 break;
01002 case RPMSIGTAG_SHA1:
01003 b = stpcpy(b, "sha1 ");
01004 break;
01005 case RPMSIGTAG_LEMD5_2:
01006 case RPMSIGTAG_LEMD5_1:
01007 case RPMSIGTAG_MD5:
01008 b = stpcpy(b, "md5 ");
01009 break;
01010 case RPMSIGTAG_RSA:
01011 b = stpcpy(b, "rsa ");
01012 break;
01013 case RPMSIGTAG_PGP5:
01014 case RPMSIGTAG_PGP:
01015 b = stpcpy(b, "(md5) pgp ");
01016 break;
01017 case RPMSIGTAG_DSA:
01018 b = stpcpy(b, "(sha1) dsa ");
01019 break;
01020 case RPMSIGTAG_GPG:
01021 b = stpcpy(b, "gpg ");
01022 break;
01023 default:
01024 b = stpcpy(b, "??? ");
01025 break;
01026 }
01027 }
01028 }
01029
01030 }
01031 hi = headerFreeIterator(hi);
01032
01033 res += res2;
01034
01035 if (res2) {
01036 if (rpmIsVerbose()) {
01037 rpmError(RPMERR_SIGVFY, "%s", buf);
01038 } else {
01039 rpmError(RPMERR_SIGVFY, "%s%s%s%s%s%s%s%s\n", buf,
01040 _("NOT OK"),
01041 (missingKeys[0] != '\0') ? _(" (MISSING KEYS:") : "",
01042 missingKeys,
01043 (missingKeys[0] != '\0') ? _(") ") : "",
01044 (untrustedKeys[0] != '\0') ? _(" (UNTRUSTED KEYS:") : "",
01045 untrustedKeys,
01046 (untrustedKeys[0] != '\0') ? _(")") : "");
01047
01048 }
01049 } else {
01050 if (rpmIsVerbose()) {
01051 rpmError(RPMERR_SIGVFY, "%s", buf);
01052 } else {
01053 rpmError(RPMERR_SIGVFY, "%s%s%s%s%s%s%s%s\n", buf,
01054 _("OK"),
01055 (missingKeys[0] != '\0') ? _(" (MISSING KEYS:") : "",
01056 missingKeys,
01057 (missingKeys[0] != '\0') ? _(") ") : "",
01058 (untrustedKeys[0] != '\0') ? _(" (UNTRUSTED KEYS:") : "",
01059 untrustedKeys,
01060 (untrustedKeys[0] != '\0') ? _(")") : "");
01061 }
01062 }
01063
01064 }
01065
01066 exit:
01067 sigh = rpmFreeSignature(sigh);
01068 rpmtsCleanDig(ts);
01069 return res;
01070 }
01071
01072 int rpmcliSign(rpmts ts, QVA_t qva, const char ** argv)
01073 {
01074 const char * arg;
01075 int res = 0;
01076 int xx;
01077
01078 if (argv == NULL) return res;
01079
01080 switch (qva->qva_mode) {
01081 case RPMSIGN_CHK_SIGNATURE:
01082 break;
01083 case RPMSIGN_IMPORT_PUBKEY:
01084 return rpmcliImportPubkeys(ts, qva, argv);
01085 break;
01086 case RPMSIGN_NEW_SIGNATURE:
01087 case RPMSIGN_ADD_SIGNATURE:
01088 case RPMSIGN_DEL_SIGNATURE:
01089 return rpmReSign(ts, qva, argv);
01090 break;
01091 case RPMSIGN_NONE:
01092 default:
01093 return -1;
01094 break;
01095 }
01096
01097 while ((arg = *argv++) != NULL) {
01098 FD_t fd;
01099
01100 fd = Fopen(arg, "r.ufdio");
01101 if (fd == NULL || Ferror(fd)) {
01102 rpmError(RPMERR_OPEN, _("%s: open failed: %s\n"),
01103 arg, Fstrerror(fd));
01104 res++;
01105 } else if (rpmVerifySignatures(qva, ts, fd, arg)) {
01106 res++;
01107 }
01108
01109 if (fd != NULL) xx = Fclose(fd);
01110 }
01111
01112 return res;
01113 }