rpm 5.2.1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

lib/rpmchecksig.c
Go to the documentation of this file.

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