lib/rpmchecksig.c

Go to the documentation of this file.
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"       /* XXX for makeTempFile() */
00018 #include "debug.h"
00019 
00020 /*@access FD_t @*/              /* XXX stealing digests */
00021 /*@access pgpDig @*/
00022 /*@access pgpDigParams @*/
00023 
00024 /*@unchecked@*/
00025 int _print_pkts = 0;
00026 
00029 /*@-boundsread@*/
00030 static int manageFile(/*@out@*/ FD_t *fdp,
00031                 /*@null@*/ /*@out@*/ const char **fnp,
00032                 int flags, /*@unused@*/ int rc)
00033         /*@globals rpmGlobalMacroContext, h_errno, fileSystem, internalState @*/
00034         /*@modifies *fdp, *fnp, rpmGlobalMacroContext,
00035                 fileSystem, internalState @*/
00036 {
00037     const char *fn;
00038     FD_t fd;
00039 
00040     if (fdp == NULL)    /* programmer error */
00041         return 1;
00042 
00043 /*@-boundswrite@*/
00044     /* close and reset *fdp to NULL */
00045     if (*fdp && (fnp == NULL || *fnp == NULL)) {
00046         (void) Fclose(*fdp);
00047         *fdp = NULL;
00048         return 0;
00049     }
00050 
00051     /* open a file and set *fdp */
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     /* open a temp file */
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 /*@=boundswrite@*/
00077 
00078     /* no operation */
00079     if (*fdp != NULL && fnp != NULL && *fnp != NULL)
00080         return 0;
00081 
00082     /* XXX never reached */
00083     return 1;
00084 }
00085 /*@=boundsread@*/
00086 
00090 /*@-boundsread@*/
00091 static int copyFile(FD_t *sfdp, const char **sfnp,
00092                 FD_t *tfdp, const char **tfnp)
00093         /*@globals rpmGlobalMacroContext, h_errno,
00094                 fileSystem, internalState @*/
00095         /*@modifies *sfdp, *sfnp, *tfdp, *tfnp, rpmGlobalMacroContext,
00096                 fileSystem, internalState @*/
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 /*@=boundsread@*/
00128 
00136 static int getSignid(Header sig, int sigtag, unsigned char * signid)
00137         /*@globals fileSystem, internalState @*/
00138         /*@modifies *signid, fileSystem, internalState @*/
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 /*@-bounds@*/
00150             memcpy(signid, dig->signature.signid, sizeof(dig->signature.signid));
00151 /*@=bounds@*/
00152             rc = 0;
00153         }
00154      
00155         dig = pgpFreeDig(dig);
00156     }
00157     pkt = headerFreeData(pkt, pkttyp);
00158     return rc;
00159 }
00160 
00168 static int rpmReSign(/*@unused@*/ rpmts ts,
00169                 QVA_t qva, const char ** argv)
00170         /*@globals rpmGlobalMacroContext, h_errno,
00171                 fileSystem, internalState @*/
00172         /*@modifies rpmGlobalMacroContext,
00173                 fileSystem, internalState @*/
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     /*@-branchstate@*/
00193 /*@-boundsread@*/
00194     if (argv)
00195     while ((rpm = *argv++) != NULL)
00196 /*@=boundsread@*/
00197     {
00198 
00199         fprintf(stdout, "%s:\n", rpm);
00200 
00201         if (manageFile(&fd, &rpm, O_RDONLY, 0))
00202             goto exit;
00203 
00204 /*@-boundswrite@*/
00205         memset(l, 0, sizeof(*l));
00206 /*@=boundswrite@*/
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             /*@notreached@*/ /*@switchbreak@*/ break;
00217         case 2:
00218             rpmError(RPMERR_BADSIGTYPE, _("%s: Can't re-sign v2 packaging\n"), rpm);
00219             goto exit;
00220             /*@notreached@*/ /*@switchbreak@*/ break;
00221         default:
00222             /*@switchbreak@*/ 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             /*@notreached@*/ /*@switchbreak@*/ break;
00234         case RPMRC_OK:
00235             if (sigh == NULL) {
00236                 rpmError(RPMERR_SIGGEN, _("%s: No signature available\n"), rpm);
00237                 goto exit;
00238             }
00239             /*@switchbreak@*/ break;
00240         }
00241         msg = _free(msg);
00242 
00243         /* Write the header and archive to a temp file */
00244         /* ASSERT: ofd == NULL && sigtarget == NULL */
00245         if (copyFile(&fd, &rpm, &ofd, &sigtarget))
00246             goto exit;
00247         /* Both fd and ofd are now closed. sigtarget contains tempfile name. */
00248         /* ASSERT: fd == NULL && ofd == NULL */
00249 
00250         /* Dump the immutable region (if present). */
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         /* Eliminate broken digest values. */
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         /* Toss and recalculate header+payload size and digests. */
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) { /* Nuke all the signature tags. */
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          /* If gpg/pgp is configured, replace the signature. */
00301         if ((sigtag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0) {
00302             unsigned char oldsignid[8], newsignid[8];
00303 
00304             /* Grab the old signature fingerprint (if any) */
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                 /*@switchbreak@*/ break;
00312             case RPMSIGTAG_RSA:
00313                 xx = headerRemoveEntry(sigh, RPMSIGTAG_PGP);
00314                 /*@switchbreak@*/ break;
00315             case RPMSIGTAG_GPG:
00316                 xx = headerRemoveEntry(sigh, RPMSIGTAG_DSA);
00317                 /*@fallthrough@*/
00318             case RPMSIGTAG_PGP5:
00319             case RPMSIGTAG_PGP:
00320                 xx = headerRemoveEntry(sigh, RPMSIGTAG_RSA);
00321                 /*@switchbreak@*/ break;
00322             }
00323 
00324             xx = headerRemoveEntry(sigh, sigtag);
00325             xx = rpmAddSignature(sigh, sigtarget, sigtag, qva->passPhrase);
00326 
00327             /* If package was previously signed, check for same signer. */
00328             memset(newsignid, 0, sizeof(newsignid));
00329             if (memcmp(oldsignid, newsignid, sizeof(oldsignid))) {
00330 
00331                 /* Grab the new signature fingerprint */
00332                 xx = getSignid(sigh, sigtag, newsignid);
00333 
00334                 /* If same signer, skip resigning the package. */
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                     /* Clean up intermediate target */
00342                     xx = unlink(sigtarget);
00343                     sigtarget = _free(sigtarget);
00344                     continue;
00345                 }
00346             }
00347         }
00348 
00349         /* Reallocate the signature into one contiguous region. */
00350         sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES);
00351         if (sigh == NULL)       /* XXX can't happen */
00352             goto exit;
00353 
00354         /* Write the lead/signature of the output rpm */
00355 /*@-boundswrite@*/
00356         strcpy(tmprpm, rpm);
00357         strcat(tmprpm, ".XXXXXX");
00358 /*@=boundswrite@*/
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         /* Append the header and archive from the temp file */
00380         /* ASSERT: fd == NULL && ofd != NULL */
00381         if (copyFile(&fd, &sigtarget, &ofd, &trpm))
00382             goto exit;
00383         /* Both fd and ofd are now closed. */
00384         /* ASSERT: fd == NULL && ofd == NULL */
00385 
00386         /* Move final target into place. */
00387         xx = unlink(rpm);
00388         xx = rename(trpm, rpm);
00389         tmprpm[0] = '\0';
00390 
00391         /* Clean up intermediate target */
00392         xx = unlink(sigtarget);
00393         sigtarget = _free(sigtarget);
00394     }
00395     /*@=branchstate@*/
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;              /* assume failure */
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     /* Build header elements. */
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 /*@-boundswrite@*/
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     /*@-nullpass@*/ /* FIX: pubp->userid may be NULL */
00471     u = t = xmalloc(sizeof("gpg()")+strlen(pubp->userid));
00472     t = stpcpy( stpcpy( stpcpy(t, "gpg("), pubp->userid), ")");
00473     /*@=nullpass@*/
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 /*@=boundswrite@*/
00479 
00480     /* Check for pre-existing header. */
00481 
00482     /* Build pubkey header. */
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     /* XXX W2DO: tag value inheirited from parent? */
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         /* XXX W2DO: tag value inheirited from parent? */
00523         xx = headerAddEntry(h, RPMTAG_BUILDTIME, RPM_INT32_TYPE, &tid, 1);
00524     }
00525 
00526 #ifdef  NOTYET
00527     /* XXX W2DO: tag value inheirited from parent? */
00528     xx = headerAddEntry(h, RPMTAG_SOURCERPM, RPM_STRING_TYPE, fn, 1);
00529 #endif
00530 
00531     /* Add header to database. */
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     /* Clean up. */
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                 /*@unused@*/ QVA_t qva,
00562                 /*@null@*/ const char ** argv)
00563         /*@globals RPMVERSION, rpmGlobalMacroContext, h_errno,
00564                 fileSystem, internalState @*/
00565         /*@modifies ts, rpmGlobalMacroContext,
00566                 fileSystem, internalState @*/
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     /*@-branchstate@*/
00579 /*@-boundsread@*/
00580     while ((fn = *argv++) != NULL) {
00581 /*@=boundsread@*/
00582 
00583         rpmtsClean(ts);
00584         pkt = _free(pkt);
00585         t = _free(t);
00586 
00587         /* If arg looks like a keyid, then attempt keyserver retrieve. */
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         /* Read pgp packet. */
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         /* Import pubkey packet(s). */
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     /*@=branchstate@*/
00621     
00622 rpmtsClean(ts);
00623     pkt = _free(pkt);
00624     t = _free(t);
00625     return res;
00626 }
00627 
00628 /*@unchecked@*/
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         /*@globals fileSystem, internalState @*/
00638         /*@modifies fd, *dig, fileSystem, internalState @*/
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     /* Read the header from the package. */
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     /* Read the payload from the package. */
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     /* XXX Steal the digest-in-progress from the file handle. */
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             /*@switchbreak@*/ 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             /*@switchbreak@*/ break;
00706         default:
00707             /*@switchbreak@*/ 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 /*@-boundswrite@*/
00743         memset(l, 0, sizeof(*l));
00744 /*@=boundswrite@*/
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             /*@notreached@*/ /*@switchbreak@*/ break;
00757         default:
00758             /*@switchbreak@*/ 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             /*@notreached@*/ /*@switchbreak@*/ 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             /*@switchbreak@*/ break;
00778         }
00779         msg = _free(msg);
00780 
00781         /* Grab a hint of what needs doing to avoid duplication. */
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;        /* XXX never happens */
00798         }
00799 
00800         dig = rpmtsDig(ts);
00801         sigp = rpmtsSignature(ts);
00802 
00803         /* XXX RSA needs the hash_algo, so decode early. */
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             /* XXX assume same hash_algo in header-only and header+payload */
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         /* Read the file, generating digest(s) on the fly. */
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) /* XXX can't happen */
00841                 continue;
00842 
00843             (void) rpmtsSetSig(ts, sigtag, sigtype, sig, siglen);
00844 
00845             /* Clean up parameters from previous sigtag. */
00846             pgpCleanDig(dig);
00847 
00848             switch (sigtag) {
00849             case RPMSIGTAG_RSA:
00850             case RPMSIGTAG_DSA:
00851             case RPMSIGTAG_GPG:
00852             case RPMSIGTAG_PGP5:        /* XXX legacy */
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                 /*@switchbreak@*/ break;
00866             case RPMSIGTAG_SHA1:
00867                 if (nodigests)
00868                      continue;
00869                 /* XXX Don't bother with header sha1 if header dsa. */
00870                 if (!nosignatures && sigtag == RPMSIGTAG_DSA)
00871                     continue;
00872                 /*@switchbreak@*/ break;
00873             case RPMSIGTAG_LEMD5_2:
00874             case RPMSIGTAG_LEMD5_1:
00875             case RPMSIGTAG_MD5:
00876                 if (nodigests)
00877                      continue;
00878                 /*
00879                  * Don't bother with md5 if pgp, as RSA/MD5 is more reliable
00880                  * than the -- now unsupported -- legacy md5 breakage.
00881                  */
00882                 if (!nosignatures && sigtag == RPMSIGTAG_PGP)
00883                     continue;
00884                 /*@switchbreak@*/ break;
00885             default:
00886                 continue;
00887                 /*@notreached@*/ /*@switchbreak@*/ break;
00888             }
00889 
00890             res3 = rpmVerifySignature(ts, result);
00891 
00892 /*@-bounds@*/
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                         /*@switchbreak@*/ break;
00905                     case RPMSIGTAG_SHA1:
00906                         b = stpcpy(b, "SHA1 ");
00907                         res2 = 1;
00908                         /*@switchbreak@*/ break;
00909                     case RPMSIGTAG_LEMD5_2:
00910                     case RPMSIGTAG_LEMD5_1:
00911                     case RPMSIGTAG_MD5:
00912                         b = stpcpy(b, "MD5 ");
00913                         res2 = 1;
00914                         /*@switchbreak@*/ break;
00915                     case RPMSIGTAG_RSA:
00916                         b = stpcpy(b, "RSA ");
00917                         res2 = 1;
00918                         /*@switchbreak@*/ break;
00919                     case RPMSIGTAG_PGP5:        /* XXX legacy */
00920                     case RPMSIGTAG_PGP:
00921                         switch (res3) {
00922                         case RPMRC_NOKEY:
00923                             res2 = 1;
00924                             /*@fallthrough@*/
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                         }   /*@innerbreak@*/ break;
00945                         default:
00946                             b = stpcpy(b, "MD5 PGP ");
00947                             res2 = 1;
00948                             /*@innerbreak@*/ break;
00949                         }
00950                         /*@switchbreak@*/ break;
00951                     case RPMSIGTAG_DSA:
00952                         b = stpcpy(b, "(SHA1) DSA ");
00953                         res2 = 1;
00954                         /*@switchbreak@*/ break;
00955                     case RPMSIGTAG_GPG:
00956                         /* Do not consider this a failure */
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                             /*@innerbreak@*/ break;
00968                         default:
00969                             b = stpcpy(b, "GPG ");
00970                             res2 = 1;
00971                             /*@innerbreak@*/ break;
00972                         }
00973                         /*@switchbreak@*/ break;
00974                     default:
00975                         b = stpcpy(b, "?UnknownSignatureType? ");
00976                         res2 = 1;
00977                         /*@switchbreak@*/ 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                         /*@switchbreak@*/ break;
00989                     case RPMSIGTAG_SHA1:
00990                         b = stpcpy(b, "sha1 ");
00991                         /*@switchbreak@*/ break;
00992                     case RPMSIGTAG_LEMD5_2:
00993                     case RPMSIGTAG_LEMD5_1:
00994                     case RPMSIGTAG_MD5:
00995                         b = stpcpy(b, "md5 ");
00996                         /*@switchbreak@*/ break;
00997                     case RPMSIGTAG_RSA:
00998                         b = stpcpy(b, "rsa ");
00999                         /*@switchbreak@*/ break;
01000                     case RPMSIGTAG_PGP5:        /* XXX legacy */
01001                     case RPMSIGTAG_PGP:
01002                         b = stpcpy(b, "(md5) pgp ");
01003                         /*@switchbreak@*/ break;
01004                     case RPMSIGTAG_DSA:
01005                         b = stpcpy(b, "(sha1) dsa ");
01006                         /*@switchbreak@*/ break;
01007                     case RPMSIGTAG_GPG:
01008                         b = stpcpy(b, "gpg ");
01009                         /*@switchbreak@*/ break;
01010                     default:
01011                         b = stpcpy(b, "??? ");
01012                         /*@switchbreak@*/ break;
01013                     }
01014                 }
01015             }
01016 /*@=bounds@*/
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         /*@notreached@*/ break;
01073     case RPMSIGN_NEW_SIGNATURE:
01074     case RPMSIGN_ADD_SIGNATURE:
01075     case RPMSIGN_DEL_SIGNATURE:
01076         return rpmReSign(ts, qva, argv);
01077         /*@notreached@*/ break;
01078     case RPMSIGN_NONE:
01079     default:
01080         return -1;
01081         /*@notreached@*/ 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 }

Generated on Wed Jan 28 12:45:24 2009 for rpm by  doxygen 1.4.7