Main Page | Modules | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

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

Generated on Tue Jan 27 18:18:06 2009 for rpm by  doxygen 1.3.9.1