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