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

Generated on Mon Aug 3 15:24:59 2009 for rpm by  doxygen 1.4.4