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

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

Generated on Tue Sep 17 15:59:51 2002 for rpm by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002