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