00001
00006 #include "system.h"
00007
00008 #include <rpmio_internal.h>
00009 #include <poptIO.h>
00010 #include <rpmbc.h>
00011 #include <rpmtag.h>
00012 #include <rpmtypes.h>
00013 #define _RPMEVR_INTERNAL
00014 #include <rpmevr.h>
00015 #include <rpmdb.h>
00016 #include <rpmxar.h>
00017 #include <pkgio.h>
00018 #include "signature.h"
00019
00020 #include <rpmts.h>
00021
00022 #include "rpmgi.h"
00023
00024 #include <rpmversion.h>
00025 #include <rpmcli.h>
00026
00027 #include "debug.h"
00028
00029
00030
00031
00032
00033
00034
00035 int _print_pkts = 0;
00036
00039 static int manageFile( FD_t *fdp,
00040 const char **fnp,
00041 int flags, int rc)
00042
00043
00044
00045 {
00046 const char *fn;
00047 FD_t fd;
00048
00049 if (fdp == NULL)
00050 return 1;
00051
00052
00053 if (*fdp && (fnp == NULL || *fnp == NULL)) {
00054 (void) Fclose(*fdp);
00055 *fdp = NULL;
00056 return 0;
00057 }
00058
00059
00060 if (*fdp == NULL && fnp != NULL && *fnp != NULL) {
00061 fd = Fopen(*fnp, ((flags & O_WRONLY) ? "w.fdio" : "r.fdio"));
00062 if (fd == NULL || Ferror(fd)) {
00063 rpmlog(RPMLOG_ERR, _("%s: open failed: %s\n"), *fnp,
00064 Fstrerror(fd));
00065 return 1;
00066 }
00067 *fdp = fd;
00068 return 0;
00069 }
00070
00071
00072 if (*fdp == NULL && (fnp == NULL || *fnp == NULL)) {
00073 fn = NULL;
00074 if (rpmTempFile(NULL, (fnp ? &fn : NULL), &fd)) {
00075 rpmlog(RPMLOG_ERR, _("rpmTempFile failed\n"));
00076 return 1;
00077 }
00078 if (fnp != NULL)
00079 *fnp = fn;
00080
00081 *fdp = fdLink(fd, "manageFile return");
00082 fd = fdFree(fd, "manageFile return");
00083
00084 return 0;
00085 }
00086
00087
00088 if (*fdp != NULL && fnp != NULL && *fnp != NULL)
00089 return 0;
00090
00091
00092 return 1;
00093 }
00094
00098 static int copyFile(FD_t *sfdp, const char **sfnp,
00099 FD_t *tfdp, const char **tfnp)
00100
00101
00102
00103
00104 {
00105 unsigned char buf[BUFSIZ];
00106 ssize_t count;
00107 int rc = 1;
00108
00109 if (manageFile(sfdp, sfnp, O_RDONLY, 0))
00110 goto exit;
00111 if (manageFile(tfdp, tfnp, O_WRONLY|O_CREAT|O_TRUNC, 0))
00112 goto exit;
00113
00114 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), *sfdp)) > 0)
00115 {
00116 if (Fwrite(buf, sizeof(buf[0]), count, *tfdp) != (size_t)count) {
00117 rpmlog(RPMLOG_ERR, _("%s: Fwrite failed: %s\n"), *tfnp,
00118 Fstrerror(*tfdp));
00119 goto exit;
00120 }
00121 }
00122 if (count < 0) {
00123 rpmlog(RPMLOG_ERR, _("%s: Fread failed: %s\n"), *sfnp, Fstrerror(*sfdp));
00124 goto exit;
00125 }
00126 if (Fflush(*tfdp) != 0) {
00127 rpmlog(RPMLOG_ERR, _("%s: Fflush failed: %s\n"), *tfnp,
00128 Fstrerror(*tfdp));
00129 goto exit;
00130 }
00131
00132 rc = 0;
00133
00134 exit:
00135 if (*sfdp) (void) manageFile(sfdp, NULL, 0, rc);
00136 if (*tfdp) (void) manageFile(tfdp, NULL, 0, rc);
00137 return rc;
00138 }
00139
00147 static int getSignid(Header sigh, rpmSigTag sigtag, unsigned char * signid)
00148
00149
00150 {
00151 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00152 int rc = 1;
00153 int xx;
00154
00155 he->tag = (rpmTag) sigtag;
00156 xx = headerGet(sigh, he, 0);
00157 if (xx && he->p.ptr != NULL) {
00158 pgpDig dig = pgpDigNew(0);
00159
00160 if (!pgpPrtPkts(he->p.ptr, he->c, dig, 0)) {
00161 memcpy(signid, dig->signature.signid, sizeof(dig->signature.signid));
00162 rc = 0;
00163 }
00164
00165 he->p.ptr = _free(he->p.ptr);
00166 dig = pgpDigFree(dig, "getSignid");
00167 }
00168 return rc;
00169 }
00170
00178 static int rpmReSign( rpmts ts,
00179 QVA_t qva, const char ** argv)
00180
00181
00182
00183
00184 {
00185 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00186 rpmgi gi = NULL;
00187 FD_t fd = NULL;
00188 FD_t ofd = NULL;
00189 struct rpmlead *lead = NULL;
00190 rpmSigTag sigtag;
00191 const char *sigtarget = NULL;
00192 char tmprpm[1024+1];
00193 Header sigh = NULL;
00194 const char * msg = NULL;
00195 int res = EXIT_FAILURE;
00196 int deleting = (qva->qva_mode == RPMSIGN_DEL_SIGNATURE);
00197 rpmRC rc;
00198 int xx;
00199 int i;
00200
00201 tmprpm[0] = '\0';
00202
00203 if (argv)
00204 {
00205 rpmuint32_t tag = (qva->qva_source == RPMQV_FTSWALK)
00206 ? RPMDBI_FTSWALK : RPMDBI_ARGLIST;
00207 rpmgiFlags _giFlags = RPMGI_NONE;
00208
00209 gi = rpmgiNew(ts, tag, NULL, 0);
00210
00211 if (rpmioFtsOpts == 0)
00212 rpmioFtsOpts = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT);
00213
00214 rc = rpmgiSetArgs(gi, argv, rpmioFtsOpts, (_giFlags|RPMGI_NOHEADER));
00215
00216 while (rpmgiNext(gi) == RPMRC_OK) {
00217 const char * fn = rpmgiHdrPath(gi);
00218 const char * tfn;
00219
00220 fprintf(stdout, "%s:\n", fn);
00221
00222
00223 if (manageFile(&fd, &fn, O_RDONLY, 0))
00224 goto exit;
00225
00226
00227 { const char item[] = "Lead";
00228 msg = NULL;
00229 rc = rpmpkgRead(item, fd, &lead, &msg);
00230 if (rc != RPMRC_OK) {
00231 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
00232 msg = _free(msg);
00233 goto exit;
00234 }
00235 msg = _free(msg);
00236 }
00237
00238 { const char item[] = "Signature";
00239 msg = NULL;
00240 rc = rpmpkgRead(item, fd, &sigh, &msg);
00241 switch (rc) {
00242 default:
00243 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item,
00244 (msg && *msg ? msg : ""));
00245 msg = _free(msg);
00246 goto exit;
00247 break;
00248 case RPMRC_OK:
00249 if (sigh == NULL) {
00250 rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), fn);
00251 goto exit;
00252 }
00253 break;
00254 }
00255 msg = _free(msg);
00256 }
00257
00258
00259
00260
00261 if (copyFile(&fd, &fn, &ofd, &sigtarget))
00262 goto exit;
00263
00264
00265
00266
00267
00268 he->tag = RPMTAG_HEADERSIGNATURES;
00269 xx = headerGet(sigh, he, 0);
00270 if (xx) {
00271 HE_t ohe = memset(alloca(sizeof(*ohe)), 0, sizeof(*ohe));
00272 HeaderIterator hi;
00273 Header oh;
00274 Header nh;
00275
00276 nh = headerNew();
00277 if (nh == NULL) {
00278 he->p.ptr = _free(he->p.ptr);
00279 goto exit;
00280 }
00281
00282 oh = headerCopyLoad(he->p.ptr);
00283 for (hi = headerInit(oh);
00284 headerNext(hi, ohe, 0);
00285 ohe->p.ptr = _free(ohe->p.ptr))
00286 {
00287 if (ohe->p.ptr) {
00288 xx = headerPut(nh, ohe, 0);
00289 }
00290 }
00291 hi = headerFini(hi);
00292 (void)headerFree(oh);
00293 oh = NULL;
00294
00295 (void)headerFree(sigh);
00296 sigh = NULL;
00297 sigh = headerLink(nh);
00298 (void)headerFree(nh);
00299 nh = NULL;
00300 }
00301
00302 if (sigh != NULL) {
00303
00304 he->tag = (rpmTag)RPMSIGTAG_LEMD5_1;
00305 xx = headerDel(sigh, he, 0);
00306 he->tag = (rpmTag)RPMSIGTAG_LEMD5_2;
00307 xx = headerDel(sigh, he, 0);
00308 he->tag = (rpmTag)RPMSIGTAG_BADSHA1_1;
00309 xx = headerDel(sigh, he, 0);
00310 he->tag = (rpmTag)RPMSIGTAG_BADSHA1_2;
00311 xx = headerDel(sigh, he, 0);
00312
00313
00314 { static const rpmuint32_t sigs[] =
00315 { RPMSIGTAG_SIZE, RPMSIGTAG_MD5, RPMSIGTAG_SHA1 };
00316 size_t nsigs = sizeof(sigs) / sizeof(sigs[0]);
00317 for (i = 0; i < (int)nsigs; i++) {
00318 he->tag = (rpmTag)sigs[i];
00319 xx = headerDel(sigh, he, 0);
00320 xx = rpmAddSignature(sigh, sigtarget, (rpmSigTag) he->tag, qva->passPhrase);
00321 if (xx)
00322 goto exit;
00323 }
00324 }
00325
00326 if (deleting) {
00327
00328 static const rpmuint32_t sigs[] =
00329 { RPMSIGTAG_GPG, RPMSIGTAG_PGP5, RPMSIGTAG_PGP,
00330 RPMSIGTAG_DSA, RPMSIGTAG_RSA };
00331 size_t nsigs = sizeof(sigs) / sizeof(sigs[0]);
00332 for (i = 0; i < (int)nsigs; i++) {
00333 he->tag = (rpmTag)sigs[i];
00334 xx = headerDel(sigh, he, 0);
00335 }
00336 } else {
00337 int addsig = 0;
00338 sigtag = RPMSIGTAG_GPG;
00339 addsig = 1;
00340
00341 if (addsig) {
00342 unsigned char oldsignid[8], newsignid[8];
00343
00344
00345 memset(oldsignid, 0, sizeof(oldsignid));
00346 xx = getSignid(sigh, sigtag, oldsignid);
00347
00348 switch (sigtag) {
00349 default:
00350 break;
00351 case RPMSIGTAG_DSA:
00352 he->tag = (rpmTag)RPMSIGTAG_GPG;
00353 xx = headerDel(sigh, he, 0);
00354 break;
00355 case RPMSIGTAG_RSA:
00356 he->tag = (rpmTag)RPMSIGTAG_PGP;
00357 xx = headerDel(sigh, he, 0);
00358 break;
00359 case RPMSIGTAG_GPG:
00360 he->tag = (rpmTag)RPMSIGTAG_PGP;
00361 xx = headerDel(sigh, he, 0);
00362 he->tag = (rpmTag)RPMSIGTAG_DSA;
00363 xx = headerDel(sigh, he, 0);
00364
00365 case RPMSIGTAG_PGP5:
00366 case RPMSIGTAG_PGP:
00367 he->tag = (rpmTag)RPMSIGTAG_RSA;
00368 xx = headerDel(sigh, he, 0);
00369 break;
00370 }
00371
00372 he->tag = (rpmTag)sigtag;
00373 xx = headerDel(sigh, he, 0);
00374 xx = rpmAddSignature(sigh, sigtarget, sigtag, qva->passPhrase);
00375 if (xx)
00376 goto exit;
00377
00378
00379 memset(newsignid, 0, sizeof(newsignid));
00380 if (memcmp(oldsignid, newsignid, sizeof(oldsignid))) {
00381
00382
00383 xx = getSignid(sigh, sigtag, newsignid);
00384
00385
00386 if (!memcmp(oldsignid, newsignid, sizeof(oldsignid))) {
00387
00388 rpmlog(RPMLOG_WARNING,
00389 _("%s: was already signed by key ID %s, skipping\n"),
00390 fn, pgpHexStr(newsignid+4, sizeof(newsignid)-4));
00391
00392
00393 xx = Unlink(sigtarget);
00394 sigtarget = _free(sigtarget);
00395 continue;
00396 }
00397 }
00398 }
00399 }
00400
00401
00402 sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES);
00403 if (sigh == NULL)
00404 goto exit;
00405 }
00406
00407
00408 (void) stpcpy( stpcpy(tmprpm, fn), ".XXXXXX");
00409
00410 #if defined(HAVE_MKSTEMP)
00411 (void) close(mkstemp(tmprpm));
00412 #else
00413 (void) mktemp(tmprpm);
00414 #endif
00415 tfn = tmprpm;
00416
00417 if (manageFile(&ofd, &tfn, O_WRONLY|O_CREAT|O_TRUNC, 0))
00418 goto exit;
00419
00420 { const char item[] = "Lead";
00421 rc = rpmpkgWrite(item, ofd, lead, NULL);
00422 if (rc != RPMRC_OK) {
00423 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", tfn, item, Fstrerror(ofd));
00424 goto exit;
00425 }
00426 }
00427
00428 { const char item[] = "Signature";
00429 rc = rpmpkgWrite(item, ofd, sigh, NULL);
00430 if (rc != RPMRC_OK) {
00431 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", tfn, item, Fstrerror(ofd));
00432 goto exit;
00433 }
00434 }
00435
00436
00437
00438 if (copyFile(&fd, &sigtarget, &ofd, &tfn))
00439 goto exit;
00440
00441
00442
00443
00444 xx = Unlink(fn);
00445 xx = Rename(tfn, fn);
00446 tmprpm[0] = '\0';
00447
00448
00449 xx = Unlink(sigtarget);
00450 sigtarget = _free(sigtarget);
00451 }
00452
00453 }
00454
00455 res = 0;
00456
00457 exit:
00458 if (fd) (void) manageFile(&fd, NULL, 0, res);
00459 if (ofd) (void) manageFile(&ofd, NULL, 0, res);
00460
00461 lead = _free(lead);
00462 (void)headerFree(sigh);
00463 sigh = NULL;
00464
00465 gi = rpmgiFree(gi);
00466
00467 if (sigtarget) {
00468 xx = Unlink(sigtarget);
00469 sigtarget = _free(sigtarget);
00470 }
00471 if (tmprpm[0] != '\0') {
00472 xx = Unlink(tmprpm);
00473 tmprpm[0] = '\0';
00474 }
00475
00476 return res;
00477 }
00478
00479 rpmRC rpmcliImportPubkey(const rpmts ts, const unsigned char * pkt, ssize_t pktlen)
00480 {
00481 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00482 static unsigned char zeros[] =
00483 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
00484 const char * afmt = "%{pubkeys:armor}";
00485 const char * group = "Public Keys";
00486 const char * license = "pubkey";
00487 const char * buildhost = "localhost";
00488 rpmuint32_t pflags = (RPMSENSE_KEYRING|RPMSENSE_EQUAL);
00489 rpmuint32_t zero = 0;
00490 pgpDig dig = NULL;
00491 pgpDigParams pubp = NULL;
00492 const char * d = NULL;
00493 const char * enc = NULL;
00494 const char * n = NULL;
00495 const char * u = NULL;
00496 const char * v = NULL;
00497 const char * r = NULL;
00498 const char * evr = NULL;
00499 Header h = NULL;
00500 rpmRC rc = RPMRC_FAIL;
00501 char * t;
00502 int xx;
00503
00504 if (pkt == NULL || pktlen <= 0)
00505 return RPMRC_FAIL;
00506 if (rpmtsOpenDB(ts, (O_RDWR|O_CREAT)))
00507 return RPMRC_FAIL;
00508
00509
00510 if ((enc = b64encode(pkt, pktlen)) == NULL)
00511 goto exit;
00512
00513
00514 dig = pgpDigNew(0);
00515
00516
00517 (void) pgpPrtPkts(pkt, pktlen, dig, 0);
00518 pubp = pgpGetPubkey(dig);
00519
00520 if (!memcmp(pubp->signid, zeros, sizeof(pubp->signid))
00521 || !memcmp(pubp->time, zeros, sizeof(pubp->time))
00522 || pubp->userid == NULL)
00523 goto exit;
00524
00525 v = t = xmalloc(16+1);
00526 t = stpcpy(t, pgpHexStr(pubp->signid, sizeof(pubp->signid)));
00527
00528 r = t = xmalloc(8+1);
00529 t = stpcpy(t, pgpHexStr(pubp->time, sizeof(pubp->time)));
00530
00531 n = t = xmalloc(sizeof("gpg()")+8);
00532 t = stpcpy( stpcpy( stpcpy(t, "gpg("), v+8), ")");
00533
00534
00535 u = t = xmalloc(sizeof("gpg()")+strlen(pubp->userid));
00536 t = stpcpy( stpcpy( stpcpy(t, "gpg("), pubp->userid), ")");
00537
00538
00539 evr = t = xmalloc(sizeof("4X:-")+strlen(v)+strlen(r));
00540 t = stpcpy(t, (pubp->version == 4 ? "4:" : "3:"));
00541 t = stpcpy( stpcpy( stpcpy(t, v), "-"), r);
00542
00543
00544
00545
00546 h = headerNew();
00547
00548 he->append = 1;
00549
00550 he->tag = RPMTAG_PUBKEYS;
00551 he->t = RPM_STRING_ARRAY_TYPE;
00552 he->p.argv = &enc;
00553 he->c = 1;
00554 xx = headerPut(h, he, 0);
00555
00556 he->append = 0;
00557
00558 d = headerSprintf(h, afmt, NULL, rpmHeaderFormats, NULL);
00559 if (d == NULL)
00560 goto exit;
00561
00562 he->t = RPM_STRING_TYPE;
00563 he->c = 1;
00564 he->tag = RPMTAG_NAME;
00565 he->p.str = xstrdup("gpg-pubkey");
00566 xx = headerPut(h, he, 0);
00567 he->p.ptr = _free(he->p.ptr);
00568 he->tag = RPMTAG_VERSION;
00569 he->p.str = v+8;
00570 xx = headerPut(h, he, 0);
00571 he->tag = RPMTAG_RELEASE;
00572 he->p.str = xstrdup(r);
00573 xx = headerPut(h, he, 0);
00574 he->p.ptr = _free(he->p.ptr);
00575
00576
00577 he->tag = RPMTAG_DESCRIPTION;
00578 he->p.str = xstrdup(d);
00579 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
00580 xx = headerAddI18NString(h, he->tag, he->p.ptr, "C");
00581 #else
00582 xx = headerPut(h, he, 0);
00583 #endif
00584 he->p.ptr = _free(he->p.ptr);
00585
00586 he->tag = RPMTAG_GROUP;
00587 he->p.str = xstrdup(group);
00588 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
00589 xx = headerAddI18NString(h, he->tag, he->p.ptr, "C");
00590 #else
00591 xx = headerPut(h, he, 0);
00592 #endif
00593 he->p.ptr = _free(he->p.ptr);
00594
00595 he->tag = RPMTAG_SUMMARY;
00596 he->p.str = xstrdup(u);
00597 #if defined(SUPPORT_IMPLICIT_TAG_DATA_TYPES)
00598 xx = headerAddI18NString(h, he->tag, he->p.ptr, "C");
00599 #else
00600 xx = headerPut(h, he, 0);
00601 #endif
00602 he->p.ptr = _free(he->p.ptr);
00603
00604 #ifdef NOTYET
00605
00606 he->tag = RPMTAG_ARCH;
00607 he->p.str = "pubkey";
00608 xx = headerPut(h, he, 0);
00609 he->tag = RPMTAG_OS;
00610 he->p.str = "pubkey";
00611 xx = headerPut(h, he, 0);
00612 #endif
00613
00614 he->tag = RPMTAG_LICENSE;
00615 he->p.str = xstrdup(license);
00616 xx = headerPut(h, he, 0);
00617 he->p.ptr = _free(he->p.ptr);
00618
00619 he->tag = RPMTAG_SIZE;
00620 he->t = RPM_UINT32_TYPE;
00621 he->p.ui32p = &zero;
00622 he->c = 1;
00623 xx = headerPut(h, he, 0);
00624
00625 he->append = 1;
00626
00627
00628 he->tag = RPMTAG_PROVIDENAME;
00629 he->t = RPM_STRING_ARRAY_TYPE;
00630 he->p.argv = &u;
00631 he->c = 1;
00632 xx = headerPut(h, he, 0);
00633 he->tag = RPMTAG_PROVIDEVERSION;
00634 he->t = RPM_STRING_ARRAY_TYPE;
00635 he->p.argv = &evr;
00636 he->c = 1;
00637 xx = headerPut(h, he, 0);
00638 he->tag = RPMTAG_PROVIDEFLAGS;
00639 he->t = RPM_UINT32_TYPE;
00640 he->p.ui32p = &pflags;
00641 he->c = 1;
00642 xx = headerPut(h, he, 0);
00643
00644
00645 he->tag = RPMTAG_PROVIDENAME;
00646 he->t = RPM_STRING_ARRAY_TYPE;
00647 he->p.argv = &n;
00648 he->c = 1;
00649 xx = headerPut(h, he, 0);
00650 he->tag = RPMTAG_PROVIDEVERSION;
00651 he->t = RPM_STRING_ARRAY_TYPE;
00652 he->p.argv = &evr;
00653 he->c = 1;
00654 xx = headerPut(h, he, 0);
00655 he->tag = RPMTAG_PROVIDEFLAGS;
00656 he->t = RPM_UINT32_TYPE;
00657 he->p.ui32p = &pflags;
00658 he->c = 1;
00659 xx = headerPut(h, he, 0);
00660
00661 he->append = 0;
00662
00663 he->tag = RPMTAG_RPMVERSION;
00664 he->t = RPM_STRING_TYPE;
00665 he->p.str = xstrdup(RPMVERSION);
00666 he->c = 1;
00667 xx = headerPut(h, he, 0);
00668 he->p.ptr = _free(he->p.ptr);
00669
00670
00671 he->tag = RPMTAG_BUILDHOST;
00672 he->t = RPM_STRING_TYPE;
00673 he->p.str = xstrdup(buildhost);
00674 he->c = 1;
00675 xx = headerPut(h, he, 0);
00676 he->p.ptr = _free(he->p.ptr);
00677
00678 { rpmuint32_t tid = rpmtsGetTid(ts);
00679 he->tag = RPMTAG_INSTALLTIME;
00680 he->t = RPM_UINT32_TYPE;
00681 he->p.ui32p = &tid;
00682 he->c = 1;
00683 xx = headerPut(h, he, 0);
00684
00685 he->tag = RPMTAG_BUILDTIME;
00686 he->t = RPM_UINT32_TYPE;
00687 he->p.ui32p = &tid;
00688 he->c = 1;
00689 xx = headerPut(h, he, 0);
00690 }
00691
00692 #ifdef NOTYET
00693
00694 he->tag = RPMTAG_SOURCERPM;
00695 he->t = RPM_STRING_TYPE;
00696 he->p.str = fn;
00697 he->c = 1;
00698 xx = headerPut(h, he, 0);
00699 #endif
00700
00701
00702 xx = rpmdbAdd(rpmtsGetRdb(ts), rpmtsGetTid(ts), h, NULL);
00703 if (xx != 0)
00704 goto exit;
00705 rc = RPMRC_OK;
00706
00707 exit:
00708
00709 (void)headerFree(h);
00710 h = NULL;
00711 dig = pgpDigFree(dig, "rpmcliImportPubkey");
00712 n = _free(n);
00713 u = _free(u);
00714 v = _free(v);
00715 r = _free(r);
00716 evr = _free(evr);
00717 enc = _free(enc);
00718 d = _free(d);
00719
00720 return rc;
00721 }
00722
00731 static int rpmcliImportPubkeys(const rpmts ts,
00732 QVA_t qva,
00733 const char ** argv)
00734
00735
00736
00737
00738 {
00739 const char * fn;
00740 rpmuint8_t * pkt = NULL;
00741 size_t pktlen = 0;
00742 char * t = NULL;
00743 int res = 0;
00744 rpmRC rpmrc;
00745 int rc;
00746
00747 if (argv == NULL) return res;
00748
00749 while ((fn = *argv++) != NULL) {
00750
00751 rpmtsClean(ts);
00752 pkt = _free(pkt);
00753 t = _free(t);
00754
00755
00756 if (fn[0] == '0' && fn[1] == 'x') {
00757 const char * s;
00758 int i;
00759 for (i = 0, s = fn+2; *s && isxdigit(*s); s++, i++)
00760 {};
00761 if (i == 8 || i == 16) {
00762 t = rpmExpand("%{_hkp_keyserver_query}", fn+2, NULL);
00763 if (t && *t != '%')
00764 fn = t;
00765 }
00766 }
00767
00768
00769 if ((rc = pgpReadPkts(fn, &pkt, &pktlen)) <= 0) {
00770 rpmlog(RPMLOG_ERR, _("%s: import read failed(%d).\n"), fn, rc);
00771 res++;
00772 continue;
00773 }
00774 if (rc != PGPARMOR_PUBKEY) {
00775 rpmlog(RPMLOG_ERR, _("%s: not an armored public key.\n"), fn);
00776 res++;
00777 continue;
00778 }
00779
00780
00781 if ((rpmrc = rpmcliImportPubkey(ts, pkt, pktlen)) != RPMRC_OK) {
00782 rpmlog(RPMLOG_ERR, _("%s: import failed.\n"), fn);
00783 res++;
00784 continue;
00785 }
00786
00787 }
00788
00789 rpmtsClean(ts);
00790 pkt = _free(pkt);
00791 t = _free(t);
00792 return res;
00793 }
00794
00798 static rpmRC readFile(FD_t fd, const char * fn)
00799
00800
00801 {
00802 rpmxar xar = fdGetXAR(fd);
00803 pgpDig dig = fdGetDig(fd);
00804 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00805 unsigned char buf[4*BUFSIZ];
00806 ssize_t count;
00807 rpmRC rc;
00808 int xx;
00809
00810 dig->nbytes = 0;
00811
00812
00813 { Header h = NULL;
00814 const char item[] = "Header";
00815 const char * msg = NULL;
00816 rc = rpmpkgRead(item, fd, &h, &msg);
00817 if (rc != RPMRC_OK) {
00818 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
00819 msg = _free(msg);
00820 goto exit;
00821 }
00822 msg = _free(msg);
00823
00824 dig->nbytes += headerSizeof(h);
00825
00826 if (headerIsEntry(h, RPMTAG_HEADERIMMUTABLE)) {
00827 unsigned char * hmagic = NULL;
00828 size_t nmagic = 0;
00829
00830 he->tag = RPMTAG_HEADERIMMUTABLE;
00831 xx = headerGet(h, he, 0);
00832 if (!xx || he->p.ptr == NULL) {
00833 (void)headerFree(h);
00834 h = NULL;
00835 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, _("headerGet failed"),
00836 _("failed to retrieve original header\n"));
00837 rc = RPMRC_FAIL;
00838 goto exit;
00839 }
00840 (void) headerGetMagic(NULL, &hmagic, &nmagic);
00841 dig->hdrsha1ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
00842 if (hmagic && nmagic > 0)
00843 (void) rpmDigestUpdate(dig->hdrsha1ctx, hmagic, nmagic);
00844 (void) rpmDigestUpdate(dig->hdrsha1ctx, he->p.ptr, he->c);
00845 dig->hdrctx = rpmDigestInit(dig->signature.hash_algo, RPMDIGEST_NONE);
00846 if (hmagic && nmagic > 0)
00847 (void) rpmDigestUpdate(dig->hdrctx, hmagic, nmagic);
00848 (void) rpmDigestUpdate(dig->hdrctx, he->p.ptr, he->c);
00849 he->p.ptr = _free(he->p.ptr);
00850 }
00851 (void)headerFree(h);
00852 h = NULL;
00853 }
00854
00855 if (xar != NULL) {
00856 const char item[] = "Payload";
00857 if ((xx = rpmxarNext(xar)) != 0 || (xx = rpmxarPull(xar, item)) != 0) {
00858 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item,
00859 _("XAR file not found (or no XAR support)"));
00860 rc = RPMRC_NOTFOUND;
00861 goto exit;
00862 }
00863 }
00864
00865
00866 while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), fd)) > 0)
00867 dig->nbytes += count;
00868 if (count < 0 || Ferror(fd)) {
00869 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, _("Fread failed"), Fstrerror(fd));
00870 rc = RPMRC_FAIL;
00871 goto exit;
00872 }
00873
00874
00875 fdStealDigest(fd, dig);
00876
00877 rc = RPMRC_OK;
00878
00879 exit:
00880 return rc;
00881 }
00882
00883 int rpmVerifySignatures(QVA_t qva, rpmts ts, void * _fd, const char * fn)
00884 {
00885 HE_t he = memset(alloca(sizeof(*he)), 0, sizeof(*he));
00886 HE_t she = memset(alloca(sizeof(*she)), 0, sizeof(*she));
00887
00888 FD_t fd = (FD_t)_fd;
00889
00890 char result[1024];
00891 char buf[8192], * b;
00892 char missingKeys[7164], * m;
00893 char untrustedKeys[7164], * u;
00894 pgpDig dig;
00895 pgpDigParams sigp;
00896 Header sigh = NULL;
00897 HeaderIterator hi = NULL;
00898 const char * msg = NULL;
00899 int res = 0;
00900 int xx;
00901 rpmRC rc, sigres;
00902 int failed;
00903 int nodigests = !(qva->qva_flags & VERIFY_DIGEST);
00904 int nosignatures = !(qva->qva_flags & VERIFY_SIGNATURE);
00905
00906 {
00907 { const char item[] = "Lead";
00908 msg = NULL;
00909
00910 rc = rpmpkgRead(item, fd, NULL, &msg);
00911
00912 if (rc != RPMRC_OK) {
00913 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item, msg);
00914 msg = _free(msg);
00915 res++;
00916 goto exit;
00917 }
00918 msg = _free(msg);
00919 }
00920
00921 { const char item[] = "Signature";
00922 msg = NULL;
00923
00924 rc = rpmpkgRead(item, fd, &sigh, &msg);
00925
00926 switch (rc) {
00927 default:
00928 rpmlog(RPMLOG_ERR, "%s: %s: %s\n", fn, item,
00929 (msg && *msg ? msg : ""));
00930 msg = _free(msg);
00931 res++;
00932 goto exit;
00933 break;
00934 case RPMRC_OK:
00935 if (sigh == NULL) {
00936 rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), fn);
00937 res++;
00938 goto exit;
00939 }
00940 break;
00941 }
00942 msg = _free(msg);
00943 }
00944
00945
00946 she->tag = 0;
00947 if (she->tag == 0 && !nosignatures) {
00948 if (headerIsEntry(sigh, (rpmTag) RPMSIGTAG_DSA))
00949 she->tag = (rpmTag) RPMSIGTAG_DSA;
00950 else if (headerIsEntry(sigh, (rpmTag) RPMSIGTAG_RSA))
00951 she->tag = (rpmTag) RPMSIGTAG_RSA;
00952 }
00953 if (she->tag == 0 && !nodigests) {
00954 if (headerIsEntry(sigh, (rpmTag) RPMSIGTAG_MD5))
00955 she->tag = (rpmTag) RPMSIGTAG_MD5;
00956 else if (headerIsEntry(sigh, (rpmTag) RPMSIGTAG_SHA1))
00957 she->tag = (rpmTag) RPMSIGTAG_SHA1;
00958 }
00959
00960 dig = rpmtsDig(ts);
00961
00962 (void) fdSetDig(fd, dig);
00963
00964 sigp = pgpGetSignature(dig);
00965
00966
00967 if ((rpmSigTag) she->tag == RPMSIGTAG_RSA) {
00968 he->tag = she->tag;
00969 xx = headerGet(sigh, he, 0);
00970 xx = pgpPrtPkts(he->p.ptr, he->c, dig, 0);
00971 he->p.ptr = _free(he->p.ptr);
00972 }
00973
00974
00975 if (headerIsEntry(sigh, (rpmTag)RPMSIGTAG_MD5))
00976 fdInitDigest(fd, PGPHASHALGO_MD5, 0);
00977
00978
00979
00980
00981 if (dig == NULL || sigp == NULL
00982 || readFile(fd, fn) != RPMRC_OK)
00983 {
00984 res++;
00985 goto exit;
00986 }
00987
00988
00989 failed = 0;
00990 b = buf; *b = '\0';
00991 m = missingKeys; *m = '\0';
00992 u = untrustedKeys; *u = '\0';
00993 sprintf(b, "%s:%c", fn, (rpmIsVerbose() ? '\n' : ' ') );
00994 b += strlen(b);
00995
00996 if (sigh != NULL)
00997 for (hi = headerInit(sigh);
00998 headerNext(hi, she, 0) != 0;
00999 she->p.ptr = _free(she->p.ptr))
01000 {
01001
01002 assert(she->p.ptr != NULL);
01003
01004
01005 pgpDigClean(dig);
01006
01007
01008 xx = pgpSetSig(dig, she->tag, she->t, she->p.ptr, she->c);
01009
01010
01011 switch ((rpmSigTag)she->tag) {
01012 case RPMSIGTAG_RSA:
01013 case RPMSIGTAG_DSA:
01014 if (nosignatures)
01015 continue;
01016 xx = pgpPrtPkts(she->p.ptr, she->c, dig,
01017 (_print_pkts & rpmIsDebug()));
01018
01019 if (sigp->version != 3 && sigp->version != 4) {
01020 rpmlog(RPMLOG_ERR,
01021 _("skipping package %s with unverifiable V%u signature\n"),
01022 fn, sigp->version);
01023 res++;
01024 goto exit;
01025 }
01026 break;
01027 case RPMSIGTAG_SHA1:
01028 if (nodigests)
01029 continue;
01030
01031 if (!nosignatures && (rpmSigTag)she->tag == RPMSIGTAG_DSA)
01032 continue;
01033 break;
01034 case RPMSIGTAG_MD5:
01035 if (nodigests)
01036 continue;
01037 break;
01038 default:
01039 continue;
01040 break;
01041 }
01042
01043 sigres = rpmVerifySignature(dig, result);
01044
01045 if (sigres) {
01046 failed = 1;
01047 if (rpmIsVerbose())
01048 b = stpcpy( stpcpy( stpcpy(b, " "), result), "\n");
01049 else
01050 switch ((rpmSigTag)she->tag) {
01051 case RPMSIGTAG_SIZE:
01052 b = stpcpy(b, "SIZE ");
01053 break;
01054 case RPMSIGTAG_SHA1:
01055 b = stpcpy(b, "SHA1 ");
01056 break;
01057 case RPMSIGTAG_MD5:
01058 b = stpcpy(b, "MD5 ");
01059 break;
01060 case RPMSIGTAG_RSA:
01061 b = stpcpy(b, "RSA ");
01062 break;
01063 case RPMSIGTAG_DSA:
01064 b = stpcpy(b, "(SHA1) DSA ");
01065 break;
01066 default:
01067 b = stpcpy(b, "?UnknownSignatureType? ");
01068 break;
01069 }
01070 } else {
01071 if (rpmIsVerbose())
01072 b = stpcpy( stpcpy( stpcpy(b, " "), result), "\n");
01073 else
01074 switch ((rpmSigTag)she->tag) {
01075 case RPMSIGTAG_SIZE:
01076 b = stpcpy(b, "size ");
01077 break;
01078 case RPMSIGTAG_SHA1:
01079 b = stpcpy(b, "sha1 ");
01080 break;
01081 case RPMSIGTAG_MD5:
01082 b = stpcpy(b, "md5 ");
01083 break;
01084 case RPMSIGTAG_RSA:
01085 b = stpcpy(b, "rsa ");
01086 break;
01087 case RPMSIGTAG_DSA:
01088 b = stpcpy(b, "(sha1) dsa ");
01089 break;
01090 default:
01091 b = stpcpy(b, "??? ");
01092 break;
01093 }
01094 }
01095 }
01096 hi = headerFini(hi);
01097
01098
01099 xx = pgpSetSig(dig, 0, 0, NULL, 0);
01100
01101
01102 res += failed;
01103
01104 if (failed) {
01105 if (rpmIsVerbose()) {
01106 rpmlog(RPMLOG_NOTICE, "%s", buf);
01107 } else {
01108 rpmlog(RPMLOG_NOTICE, "%s%s%s%s%s%s%s%s\n", buf,
01109 _("NOT_OK"),
01110 (missingKeys[0] != '\0') ? _(" (MISSING KEYS:") : "",
01111 missingKeys,
01112 (missingKeys[0] != '\0') ? _(") ") : "",
01113 (untrustedKeys[0] != '\0') ? _(" (UNTRUSTED KEYS:") : "",
01114 untrustedKeys,
01115 (untrustedKeys[0] != '\0') ? _(")") : "");
01116
01117 }
01118 } else {
01119 if (rpmIsVerbose()) {
01120 rpmlog(RPMLOG_NOTICE, "%s", buf);
01121 } else {
01122 rpmlog(RPMLOG_NOTICE, "%s%s%s%s%s%s%s%s\n", buf,
01123 _("OK"),
01124 (missingKeys[0] != '\0') ? _(" (MISSING KEYS:") : "",
01125 missingKeys,
01126 (missingKeys[0] != '\0') ? _(") ") : "",
01127 (untrustedKeys[0] != '\0') ? _(" (UNTRUSTED KEYS:") : "",
01128 untrustedKeys,
01129 (untrustedKeys[0] != '\0') ? _(")") : "");
01130 }
01131 }
01132
01133 }
01134
01135 exit:
01136 rpmtsCleanDig(ts);
01137 (void)headerFree(sigh);
01138 sigh = NULL;
01139 return res;
01140 }
01141
01142 int rpmcliSign(rpmts ts, QVA_t qva, const char ** argv)
01143
01144
01145 {
01146 int res = 0;
01147
01148 if (argv == NULL) return res;
01149
01150 switch (qva->qva_mode) {
01151 case RPMSIGN_CHK_SIGNATURE:
01152 break;
01153 case RPMSIGN_IMPORT_PUBKEY:
01154 return rpmcliImportPubkeys(ts, qva, argv);
01155 break;
01156 case RPMSIGN_NEW_SIGNATURE:
01157 case RPMSIGN_ADD_SIGNATURE:
01158 case RPMSIGN_DEL_SIGNATURE:
01159 return rpmReSign(ts, qva, argv);
01160 break;
01161 case RPMSIGN_NONE:
01162 default:
01163 return -1;
01164 break;
01165 }
01166
01167 {
01168
01169 int tag = (qva->qva_source == RPMQV_FTSWALK)
01170 ? RPMDBI_FTSWALK : RPMDBI_ARGLIST;
01171 rpmgi gi = rpmgiNew(ts, tag, NULL, 0);
01172 rpmgiFlags _giFlags = RPMGI_NONE;
01173 rpmRC rc;
01174
01175 if (rpmioFtsOpts == 0)
01176 rpmioFtsOpts = (FTS_COMFOLLOW | FTS_LOGICAL | FTS_NOSTAT);
01177 rc = rpmgiSetArgs(gi, argv, rpmioFtsOpts, (_giFlags|RPMGI_NOHEADER));
01178 while (rpmgiNext(gi) == RPMRC_OK) {
01179 const char * fn = rpmgiHdrPath(gi);
01180 FD_t fd;
01181 int xx;
01182
01183 fd = Fopen(fn, "r.fdio");
01184 if (fd == NULL || Ferror(fd)) {
01185 rpmlog(RPMLOG_ERR, _("%s: open failed: %s\n"),
01186 fn, Fstrerror(fd));
01187 res++;
01188 } else if (rpmVerifySignatures(qva, ts, fd, fn)) {
01189 res++;
01190 }
01191
01192 if (fd != NULL) {
01193 xx = Fclose(fd);
01194 }
01195 }
01196
01197 gi = rpmgiFree(gi);
01198
01199 }
01200
01201 return res;
01202 }