Split package signing out of rpmchecksig.c
authorPanu Matilainen <pmatilai@redhat.com>
Fri, 3 Sep 2010 08:11:55 +0000 (11:11 +0300)
committerPanu Matilainen <pmatilai@redhat.com>
Fri, 3 Sep 2010 08:11:55 +0000 (11:11 +0300)
- No functional changes, supposedly

lib/Makefile.am
lib/rpmchecksig.c
lib/rpmgensig.c [new file with mode: 0644]
po/POTFILES.in

index d34588e..65536ca 100644 (file)
@@ -34,7 +34,7 @@ librpm_la_SOURCES = \
        verify.c rpmlock.c rpmlock.h misc.h \
        rpmscript.h rpmscript.c legacy.c merge.c \
        rpmliblua.c rpmliblua.h rpmchroot.c rpmchroot.h \
-       rpmplugins.c rpmplugins.h
+       rpmplugins.c rpmplugins.h rpmgensig.c
 
 librpm_la_LDFLAGS = -version-info 1:0:0
 
index e308aee..25679a5 100644 (file)
 
 int _print_pkts = 0;
 
-static int closeFile(FD_t *fdp)
-{
-    if (fdp == NULL || *fdp == NULL)
-       return 1;
-
-    /* close and reset *fdp to NULL */
-    (void) Fclose(*fdp);
-    *fdp = NULL;
-    return 0;
-}
-
-/**
- */
-static int manageFile(FD_t *fdp, const char *fn, int flags)
-{
-    FD_t fd;
-
-    if (fdp == NULL || fn == NULL)     /* programmer error */
-       return 1;
-
-    /* open a file and set *fdp */
-    if (*fdp == NULL && fn != NULL) {
-       fd = Fopen(fn, (flags & O_ACCMODE) == O_WRONLY ? "w.ufdio" : "r.ufdio");
-       if (fd == NULL || Ferror(fd)) {
-           rpmlog(RPMLOG_ERR, _("%s: open failed: %s\n"), fn,
-               Fstrerror(fd));
-           return 1;
-       }
-       *fdp = fd;
-       return 0;
-    }
-
-    /* no operation */
-    if (*fdp != NULL && fn != NULL)
-       return 0;
-
-    /* XXX never reached */
-    return 1;
-}
-
-/**
- * Copy header+payload, calculating digest(s) on the fly.
- */
-static int copyFile(FD_t *sfdp, const char *sfnp,
-               FD_t *tfdp, const char *tfnp)
-{
-    unsigned char buf[BUFSIZ];
-    ssize_t count;
-    int rc = 1;
-
-    if (manageFile(sfdp, sfnp, O_RDONLY))
-       goto exit;
-    if (manageFile(tfdp, tfnp, O_WRONLY|O_CREAT|O_TRUNC))
-       goto exit;
-
-    while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), *sfdp)) > 0)
-    {
-       if (Fwrite(buf, sizeof(buf[0]), count, *tfdp) != count) {
-           rpmlog(RPMLOG_ERR, _("%s: Fwrite failed: %s\n"), tfnp,
-               Fstrerror(*tfdp));
-           goto exit;
-       }
-    }
-    if (count < 0) {
-       rpmlog(RPMLOG_ERR, _("%s: Fread failed: %s\n"), sfnp, Fstrerror(*sfdp));
-       goto exit;
-    }
-    if (Fflush(*tfdp) != 0) {
-       rpmlog(RPMLOG_ERR, _("%s: Fflush failed: %s\n"), tfnp,
-           Fstrerror(*tfdp));
-    }
-
-    rc = 0;
-
-exit:
-    if (*sfdp) (void) closeFile(sfdp);
-    if (*tfdp) (void) closeFile(tfdp);
-    return rc;
-}
-
-/**
- * Retrieve signer fingerprint from an OpenPGP signature tag.
- * @param sig          signature header
- * @param sigtag       signature tag
- * @retval signid      signer fingerprint
- * @return             0 on success
- */
-static int getSignid(Header sig, rpmSigTag sigtag, pgpKeyID_t signid)
-{
-    struct rpmtd_s pkt;
-    int rc = 1;
-
-    if (headerGet(sig, sigtag, &pkt, HEADERGET_DEFAULT) && pkt.data != NULL) {
-       pgpDig dig = pgpNewDig();
-
-       if (!pgpPrtPkts(pkt.data, pkt.count, dig, 0)) {
-           memcpy(signid, dig->signature.signid, sizeof(dig->signature.signid));
-           rc = 0;
-       }
-     
-       dig = pgpFreeDig(dig);
-       rpmtdFreeData(&pkt);
-    }
-    return rc;
-}
-
-/** \ingroup rpmcli
- * Create/modify elements in signature header.
- * @param ts           transaction set
- * @param qva          mode flags and parameters
- * @param argv         array of package file names (NULL terminated)
- * @return             0 on success, -1 on error
- */
-static int rpmReSign(rpmts ts, QVA_t qva, ARGV_const_t argv)
-{
-    FD_t fd = NULL;
-    FD_t ofd = NULL;
-    rpmlead lead;
-    rpmSigTag sigtag;
-    const char *rpm;
-    char *sigtarget = NULL, *trpm = NULL;
-    Header sigh = NULL;
-    char * msg;
-    int res = -1; /* assume failure */
-    int deleting = (qva->qva_mode == RPMSIGN_DEL_SIGNATURE);
-    int xx;
-    
-    if (argv)
-    while ((rpm = *argv++) != NULL)
-    {
-       rpmRC rc;
-       struct rpmtd_s utd;
-
-       fprintf(stdout, "%s:\n", rpm);
-
-       if (manageFile(&fd, rpm, O_RDONLY))
-           goto exit;
-
-       lead = rpmLeadNew();
-
-       if ((rc = rpmLeadRead(fd, lead)) == RPMRC_OK) {
-           const char *lmsg = NULL;
-           rc = rpmLeadCheck(lead, &lmsg);
-           if (rc != RPMRC_OK) 
-               rpmlog(RPMLOG_ERR, "%s: %s\n", rpm, lmsg);
-       }
-
-       if (rc != RPMRC_OK) {
-           lead = rpmLeadFree(lead);
-           goto exit;
-       }
-
-       msg = NULL;
-       rc = rpmReadSignature(fd, &sigh, RPMSIGTYPE_HEADERSIG, &msg);
-       switch (rc) {
-       default:
-           rpmlog(RPMLOG_ERR, _("%s: rpmReadSignature failed: %s"), rpm,
-                       (msg && *msg ? msg : "\n"));
-           msg = _free(msg);
-           goto exit;
-           break;
-       case RPMRC_OK:
-           if (sigh == NULL) {
-               rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), rpm);
-               goto exit;
-           }
-           break;
-       }
-       msg = _free(msg);
-
-       /* ASSERT: ofd == NULL && sigtarget == NULL */
-       ofd = rpmMkTempFile(NULL, &sigtarget);
-       if (ofd == NULL || Ferror(ofd)) {
-           rpmlog(RPMLOG_ERR, _("rpmMkTemp failed\n"));
-           goto exit;
-       }
-       /* Write the header and archive to a temp file */
-       if (copyFile(&fd, rpm, &ofd, sigtarget))
-           goto exit;
-       /* Both fd and ofd are now closed. sigtarget contains tempfile name. */
-       /* ASSERT: fd == NULL && ofd == NULL */
-
-       /* Dump the immutable region (if present). */
-       if (headerGet(sigh, RPMTAG_HEADERSIGNATURES, &utd, HEADERGET_DEFAULT)) {
-           struct rpmtd_s copytd;
-           Header nh = headerNew();
-           Header oh = headerCopyLoad(utd.data);
-           HeaderIterator hi = headerInitIterator(oh);
-           while (headerNext(hi, &copytd)) {
-               if (copytd.data)
-                   xx = headerPut(nh, &copytd, HEADERPUT_DEFAULT);
-               rpmtdFreeData(&copytd);
-           }
-           hi = headerFreeIterator(hi);
-           oh = headerFree(oh);
-
-           sigh = headerFree(sigh);
-           sigh = headerLink(nh);
-           nh = headerFree(nh);
-       }
-
-       /* Eliminate broken digest values. */
-       xx = headerDel(sigh, RPMSIGTAG_BADSHA1_1);
-       xx = headerDel(sigh, RPMSIGTAG_BADSHA1_2);
-
-       /* Toss and recalculate header+payload size and digests. */
-       {
-           rpmSigTag const sigs[] = {  RPMSIGTAG_SIZE, 
-                                       RPMSIGTAG_MD5,
-                                       RPMSIGTAG_SHA1,
-                                    };
-           int nsigs = sizeof(sigs) / sizeof(rpmSigTag);
-           for (int i = 0; i < nsigs; i++) {
-               (void) headerDel(sigh, sigs[i]);
-               if (rpmAddSignature(sigh, sigtarget, sigs[i], qva->passPhrase))
-                   goto exit;
-           }
-       }
-
-       if (deleting) { /* Nuke all the signature tags. */
-           xx = headerDel(sigh, RPMSIGTAG_GPG);
-           xx = headerDel(sigh, RPMSIGTAG_DSA);
-           xx = headerDel(sigh, RPMSIGTAG_PGP5);
-           xx = headerDel(sigh, RPMSIGTAG_PGP);
-           xx = headerDel(sigh, RPMSIGTAG_RSA);
-       } else          /* If gpg/pgp is configured, replace the signature. */
-       if ((sigtag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0) {
-           pgpKeyID_t oldsignid, newsignid;
-
-           /* Grab the old signature fingerprint (if any) */
-           memset(oldsignid, 0, sizeof(oldsignid));
-           xx = getSignid(sigh, sigtag, oldsignid);
-
-           switch (sigtag) {
-           case RPMSIGTAG_DSA:
-               xx = headerDel(sigh, RPMSIGTAG_GPG);
-               break;
-           case RPMSIGTAG_RSA:
-               xx = headerDel(sigh, RPMSIGTAG_PGP);
-               break;
-           case RPMSIGTAG_GPG:
-               xx = headerDel(sigh, RPMSIGTAG_DSA);
-           case RPMSIGTAG_PGP5:
-           case RPMSIGTAG_PGP:
-               xx = headerDel(sigh, RPMSIGTAG_RSA);
-               break;
-           default:
-               break;
-           }
-
-           xx = headerDel(sigh, sigtag);
-           if (rpmAddSignature(sigh, sigtarget, sigtag, qva->passPhrase)) {
-               goto exit;
-           }
-
-           /* If package was previously signed, check for same signer. */
-           memset(newsignid, 0, sizeof(newsignid));
-           if (memcmp(oldsignid, newsignid, sizeof(oldsignid))) {
-
-               /* Grab the new signature fingerprint */
-               xx = getSignid(sigh, sigtag, newsignid);
-
-               /* If same signer, skip resigning the package. */
-               if (!memcmp(oldsignid, newsignid, sizeof(oldsignid))) {
-
-                   char *signid = pgpHexStr(newsignid+4, sizeof(newsignid)-4);
-                   rpmlog(RPMLOG_WARNING,
-                       _("%s: was already signed by key ID %s, skipping\n"),
-                       rpm, signid);
-                   free(signid);
-
-                   /* Clean up intermediate target */
-                   xx = unlink(sigtarget);
-                   sigtarget = _free(sigtarget);
-                   continue;
-               }
-           }
-       }
-
-       /* Reallocate the signature into one contiguous region. */
-       sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES);
-       if (sigh == NULL)       /* XXX can't happen */
-           goto exit;
-
-       rasprintf(&trpm, "%s.XXXXXX", rpm);
-       ofd = rpmMkTemp(trpm);
-       if (ofd == NULL || Ferror(ofd)) {
-           rpmlog(RPMLOG_ERR, _("rpmMkTemp failed\n"));
-           goto exit;
-       }
-
-       /* Write the lead/signature of the output rpm */
-       rc = rpmLeadWrite(ofd, lead);
-       lead = rpmLeadFree(lead);
-       if (rc != RPMRC_OK) {
-           rpmlog(RPMLOG_ERR, _("%s: writeLead failed: %s\n"), trpm,
-               Fstrerror(ofd));
-           goto exit;
-       }
-
-       if (rpmWriteSignature(ofd, sigh)) {
-           rpmlog(RPMLOG_ERR, _("%s: rpmWriteSignature failed: %s\n"), trpm,
-               Fstrerror(ofd));
-           goto exit;
-       }
-
-       /* Append the header and archive from the temp file */
-       /* ASSERT: fd == NULL && ofd != NULL */
-       if (copyFile(&fd, sigtarget, &ofd, trpm))
-           goto exit;
-       /* Both fd and ofd are now closed. */
-       /* ASSERT: fd == NULL && ofd == NULL */
-
-       /* Move final target into place, restore file permissions. */
-       {
-           struct stat st;
-           xx = stat(rpm, &st);
-           xx = unlink(rpm);
-           xx = rename(trpm, rpm);
-           xx = chmod(rpm, st.st_mode);
-       }
-       trpm = _free(trpm);
-
-       /* Clean up intermediate target */
-       xx = unlink(sigtarget);
-       sigtarget = _free(sigtarget);
-    }
-
-    res = 0;
-
-exit:
-    if (fd)    (void) closeFile(&fd);
-    if (ofd)   (void) closeFile(&ofd);
-
-    sigh = rpmFreeSignature(sigh);
-
-    if (sigtarget) {
-       xx = unlink(sigtarget);
-       sigtarget = _free(sigtarget);
-    }
-    if (trpm) {
-       (void) unlink(trpm);
-       free(trpm);
-    }
-
-    return res;
-}
-
 static int doImport(rpmts ts, const char *fn, char *buf, ssize_t blen)
 {
     char const * const pgpmark = "-----BEGIN PGP ";
@@ -808,27 +460,3 @@ int rpmcliVerifySignatures(rpmts ts, QVA_t qva, ARGV_const_t argv)
     rpmKeyringFree(keyring);
     return res;
 }
-
-int rpmcliSign(rpmts ts, QVA_t qva, ARGV_const_t argv)
-{
-
-    if (argv == NULL) return -1;
-
-    switch (qva->qva_mode) {
-    case RPMSIGN_CHK_SIGNATURE:
-       return rpmcliVerifySignatures(ts, qva, argv);
-       break;
-    case RPMSIGN_IMPORT_PUBKEY:
-       return rpmcliImportPubkeys(ts, argv);
-       break;
-    case RPMSIGN_NEW_SIGNATURE:
-    case RPMSIGN_ADD_SIGNATURE:
-    case RPMSIGN_DEL_SIGNATURE:
-       return rpmReSign(ts, qva, argv);
-       break;
-    default:
-       break;
-    }
-
-    return -1;
-}
diff --git a/lib/rpmgensig.c b/lib/rpmgensig.c
new file mode 100644 (file)
index 0000000..9d07c51
--- /dev/null
@@ -0,0 +1,390 @@
+/** \ingroup rpmcli
+ * \file lib/rpmchecksig.c
+ * Verify the signature of a package.
+ */
+
+#include "system.h"
+
+#include <rpm/rpmlib.h>                        /* RPMSIGTAG & related */
+#include <rpm/rpmpgp.h>
+#include <rpm/rpmcli.h>
+#include <rpm/rpmfileutil.h>   /* rpmMkTemp() */
+#include <rpm/rpmlog.h>
+#include <rpm/rpmstring.h>
+
+#include "rpmio/digest.h"
+#include "lib/rpmlead.h"
+#include "lib/signature.h"
+
+#include "debug.h"
+
+static int closeFile(FD_t *fdp)
+{
+    if (fdp == NULL || *fdp == NULL)
+       return 1;
+
+    /* close and reset *fdp to NULL */
+    (void) Fclose(*fdp);
+    *fdp = NULL;
+    return 0;
+}
+
+/**
+ */
+static int manageFile(FD_t *fdp, const char *fn, int flags)
+{
+    FD_t fd;
+
+    if (fdp == NULL || fn == NULL)     /* programmer error */
+       return 1;
+
+    /* open a file and set *fdp */
+    if (*fdp == NULL && fn != NULL) {
+       fd = Fopen(fn, (flags & O_ACCMODE) == O_WRONLY ? "w.ufdio" : "r.ufdio");
+       if (fd == NULL || Ferror(fd)) {
+           rpmlog(RPMLOG_ERR, _("%s: open failed: %s\n"), fn,
+               Fstrerror(fd));
+           return 1;
+       }
+       *fdp = fd;
+       return 0;
+    }
+
+    /* no operation */
+    if (*fdp != NULL && fn != NULL)
+       return 0;
+
+    /* XXX never reached */
+    return 1;
+}
+
+/**
+ * Copy header+payload, calculating digest(s) on the fly.
+ */
+static int copyFile(FD_t *sfdp, const char *sfnp,
+               FD_t *tfdp, const char *tfnp)
+{
+    unsigned char buf[BUFSIZ];
+    ssize_t count;
+    int rc = 1;
+
+    if (manageFile(sfdp, sfnp, O_RDONLY))
+       goto exit;
+    if (manageFile(tfdp, tfnp, O_WRONLY|O_CREAT|O_TRUNC))
+       goto exit;
+
+    while ((count = Fread(buf, sizeof(buf[0]), sizeof(buf), *sfdp)) > 0)
+    {
+       if (Fwrite(buf, sizeof(buf[0]), count, *tfdp) != count) {
+           rpmlog(RPMLOG_ERR, _("%s: Fwrite failed: %s\n"), tfnp,
+               Fstrerror(*tfdp));
+           goto exit;
+       }
+    }
+    if (count < 0) {
+       rpmlog(RPMLOG_ERR, _("%s: Fread failed: %s\n"), sfnp, Fstrerror(*sfdp));
+       goto exit;
+    }
+    if (Fflush(*tfdp) != 0) {
+       rpmlog(RPMLOG_ERR, _("%s: Fflush failed: %s\n"), tfnp,
+           Fstrerror(*tfdp));
+    }
+
+    rc = 0;
+
+exit:
+    if (*sfdp) (void) closeFile(sfdp);
+    if (*tfdp) (void) closeFile(tfdp);
+    return rc;
+}
+
+/**
+ * Retrieve signer fingerprint from an OpenPGP signature tag.
+ * @param sig          signature header
+ * @param sigtag       signature tag
+ * @retval signid      signer fingerprint
+ * @return             0 on success
+ */
+static int getSignid(Header sig, rpmSigTag sigtag, pgpKeyID_t signid)
+{
+    struct rpmtd_s pkt;
+    int rc = 1;
+
+    if (headerGet(sig, sigtag, &pkt, HEADERGET_DEFAULT) && pkt.data != NULL) {
+       pgpDig dig = pgpNewDig();
+
+       if (!pgpPrtPkts(pkt.data, pkt.count, dig, 0)) {
+           memcpy(signid, dig->signature.signid, sizeof(dig->signature.signid));
+           rc = 0;
+       }
+     
+       dig = pgpFreeDig(dig);
+       rpmtdFreeData(&pkt);
+    }
+    return rc;
+}
+
+/** \ingroup rpmcli
+ * Create/modify elements in signature header.
+ * @param ts           transaction set
+ * @param qva          mode flags and parameters
+ * @param argv         array of package file names (NULL terminated)
+ * @return             0 on success, -1 on error
+ */
+static int rpmReSign(rpmts ts, QVA_t qva, ARGV_const_t argv)
+{
+    FD_t fd = NULL;
+    FD_t ofd = NULL;
+    rpmlead lead;
+    rpmSigTag sigtag;
+    const char *rpm;
+    char *sigtarget = NULL, *trpm = NULL;
+    Header sigh = NULL;
+    char * msg;
+    int res = -1; /* assume failure */
+    int deleting = (qva->qva_mode == RPMSIGN_DEL_SIGNATURE);
+    int xx;
+    
+    if (argv)
+    while ((rpm = *argv++) != NULL)
+    {
+       rpmRC rc;
+       struct rpmtd_s utd;
+
+       fprintf(stdout, "%s:\n", rpm);
+
+       if (manageFile(&fd, rpm, O_RDONLY))
+           goto exit;
+
+       lead = rpmLeadNew();
+
+       if ((rc = rpmLeadRead(fd, lead)) == RPMRC_OK) {
+           const char *lmsg = NULL;
+           rc = rpmLeadCheck(lead, &lmsg);
+           if (rc != RPMRC_OK) 
+               rpmlog(RPMLOG_ERR, "%s: %s\n", rpm, lmsg);
+       }
+
+       if (rc != RPMRC_OK) {
+           lead = rpmLeadFree(lead);
+           goto exit;
+       }
+
+       msg = NULL;
+       rc = rpmReadSignature(fd, &sigh, RPMSIGTYPE_HEADERSIG, &msg);
+       switch (rc) {
+       default:
+           rpmlog(RPMLOG_ERR, _("%s: rpmReadSignature failed: %s"), rpm,
+                       (msg && *msg ? msg : "\n"));
+           msg = _free(msg);
+           goto exit;
+           break;
+       case RPMRC_OK:
+           if (sigh == NULL) {
+               rpmlog(RPMLOG_ERR, _("%s: No signature available\n"), rpm);
+               goto exit;
+           }
+           break;
+       }
+       msg = _free(msg);
+
+       /* ASSERT: ofd == NULL && sigtarget == NULL */
+       ofd = rpmMkTempFile(NULL, &sigtarget);
+       if (ofd == NULL || Ferror(ofd)) {
+           rpmlog(RPMLOG_ERR, _("rpmMkTemp failed\n"));
+           goto exit;
+       }
+       /* Write the header and archive to a temp file */
+       if (copyFile(&fd, rpm, &ofd, sigtarget))
+           goto exit;
+       /* Both fd and ofd are now closed. sigtarget contains tempfile name. */
+       /* ASSERT: fd == NULL && ofd == NULL */
+
+       /* Dump the immutable region (if present). */
+       if (headerGet(sigh, RPMTAG_HEADERSIGNATURES, &utd, HEADERGET_DEFAULT)) {
+           struct rpmtd_s copytd;
+           Header nh = headerNew();
+           Header oh = headerCopyLoad(utd.data);
+           HeaderIterator hi = headerInitIterator(oh);
+           while (headerNext(hi, &copytd)) {
+               if (copytd.data)
+                   xx = headerPut(nh, &copytd, HEADERPUT_DEFAULT);
+               rpmtdFreeData(&copytd);
+           }
+           hi = headerFreeIterator(hi);
+           oh = headerFree(oh);
+
+           sigh = headerFree(sigh);
+           sigh = headerLink(nh);
+           nh = headerFree(nh);
+       }
+
+       /* Eliminate broken digest values. */
+       xx = headerDel(sigh, RPMSIGTAG_BADSHA1_1);
+       xx = headerDel(sigh, RPMSIGTAG_BADSHA1_2);
+
+       /* Toss and recalculate header+payload size and digests. */
+       {
+           rpmSigTag const sigs[] = {  RPMSIGTAG_SIZE, 
+                                       RPMSIGTAG_MD5,
+                                       RPMSIGTAG_SHA1,
+                                    };
+           int nsigs = sizeof(sigs) / sizeof(rpmSigTag);
+           for (int i = 0; i < nsigs; i++) {
+               (void) headerDel(sigh, sigs[i]);
+               if (rpmAddSignature(sigh, sigtarget, sigs[i], qva->passPhrase))
+                   goto exit;
+           }
+       }
+
+       if (deleting) { /* Nuke all the signature tags. */
+           xx = headerDel(sigh, RPMSIGTAG_GPG);
+           xx = headerDel(sigh, RPMSIGTAG_DSA);
+           xx = headerDel(sigh, RPMSIGTAG_PGP5);
+           xx = headerDel(sigh, RPMSIGTAG_PGP);
+           xx = headerDel(sigh, RPMSIGTAG_RSA);
+       } else          /* If gpg/pgp is configured, replace the signature. */
+       if ((sigtag = rpmLookupSignatureType(RPMLOOKUPSIG_QUERY)) > 0) {
+           pgpKeyID_t oldsignid, newsignid;
+
+           /* Grab the old signature fingerprint (if any) */
+           memset(oldsignid, 0, sizeof(oldsignid));
+           xx = getSignid(sigh, sigtag, oldsignid);
+
+           switch (sigtag) {
+           case RPMSIGTAG_DSA:
+               xx = headerDel(sigh, RPMSIGTAG_GPG);
+               break;
+           case RPMSIGTAG_RSA:
+               xx = headerDel(sigh, RPMSIGTAG_PGP);
+               break;
+           case RPMSIGTAG_GPG:
+               xx = headerDel(sigh, RPMSIGTAG_DSA);
+           case RPMSIGTAG_PGP5:
+           case RPMSIGTAG_PGP:
+               xx = headerDel(sigh, RPMSIGTAG_RSA);
+               break;
+           default:
+               break;
+           }
+
+           xx = headerDel(sigh, sigtag);
+           if (rpmAddSignature(sigh, sigtarget, sigtag, qva->passPhrase)) {
+               goto exit;
+           }
+
+           /* If package was previously signed, check for same signer. */
+           memset(newsignid, 0, sizeof(newsignid));
+           if (memcmp(oldsignid, newsignid, sizeof(oldsignid))) {
+
+               /* Grab the new signature fingerprint */
+               xx = getSignid(sigh, sigtag, newsignid);
+
+               /* If same signer, skip resigning the package. */
+               if (!memcmp(oldsignid, newsignid, sizeof(oldsignid))) {
+
+                   char *signid = pgpHexStr(newsignid+4, sizeof(newsignid)-4);
+                   rpmlog(RPMLOG_WARNING,
+                       _("%s: was already signed by key ID %s, skipping\n"),
+                       rpm, signid);
+                   free(signid);
+
+                   /* Clean up intermediate target */
+                   xx = unlink(sigtarget);
+                   sigtarget = _free(sigtarget);
+                   continue;
+               }
+           }
+       }
+
+       /* Reallocate the signature into one contiguous region. */
+       sigh = headerReload(sigh, RPMTAG_HEADERSIGNATURES);
+       if (sigh == NULL)       /* XXX can't happen */
+           goto exit;
+
+       rasprintf(&trpm, "%s.XXXXXX", rpm);
+       ofd = rpmMkTemp(trpm);
+       if (ofd == NULL || Ferror(ofd)) {
+           rpmlog(RPMLOG_ERR, _("rpmMkTemp failed\n"));
+           goto exit;
+       }
+
+       /* Write the lead/signature of the output rpm */
+       rc = rpmLeadWrite(ofd, lead);
+       lead = rpmLeadFree(lead);
+       if (rc != RPMRC_OK) {
+           rpmlog(RPMLOG_ERR, _("%s: writeLead failed: %s\n"), trpm,
+               Fstrerror(ofd));
+           goto exit;
+       }
+
+       if (rpmWriteSignature(ofd, sigh)) {
+           rpmlog(RPMLOG_ERR, _("%s: rpmWriteSignature failed: %s\n"), trpm,
+               Fstrerror(ofd));
+           goto exit;
+       }
+
+       /* Append the header and archive from the temp file */
+       /* ASSERT: fd == NULL && ofd != NULL */
+       if (copyFile(&fd, sigtarget, &ofd, trpm))
+           goto exit;
+       /* Both fd and ofd are now closed. */
+       /* ASSERT: fd == NULL && ofd == NULL */
+
+       /* Move final target into place, restore file permissions. */
+       {
+           struct stat st;
+           xx = stat(rpm, &st);
+           xx = unlink(rpm);
+           xx = rename(trpm, rpm);
+           xx = chmod(rpm, st.st_mode);
+       }
+       trpm = _free(trpm);
+
+       /* Clean up intermediate target */
+       xx = unlink(sigtarget);
+       sigtarget = _free(sigtarget);
+    }
+
+    res = 0;
+
+exit:
+    if (fd)    (void) closeFile(&fd);
+    if (ofd)   (void) closeFile(&ofd);
+
+    sigh = rpmFreeSignature(sigh);
+
+    if (sigtarget) {
+       xx = unlink(sigtarget);
+       sigtarget = _free(sigtarget);
+    }
+    if (trpm) {
+       (void) unlink(trpm);
+       free(trpm);
+    }
+
+    return res;
+}
+
+int rpmcliSign(rpmts ts, QVA_t qva, ARGV_const_t argv)
+{
+    if (argv == NULL) return -1;
+
+    switch (qva->qva_mode) {
+    case RPMSIGN_CHK_SIGNATURE:
+       return rpmcliVerifySignatures(ts, qva, argv);
+       break;
+    case RPMSIGN_IMPORT_PUBKEY:
+       return rpmcliImportPubkeys(ts, argv);
+       break;
+    case RPMSIGN_NEW_SIGNATURE:
+    case RPMSIGN_ADD_SIGNATURE:
+    case RPMSIGN_DEL_SIGNATURE:
+       return rpmReSign(ts, qva, argv);
+       break;
+    default:
+       break;
+    }
+
+    return -1;
+}
index 4514708..7ea6694 100644 (file)
@@ -45,6 +45,7 @@ lib/rpmchecksig.c
 lib/rpmchroot.c
 lib/rpmds.c
 lib/rpmfi.c
+lib/rpmgensig.c
 lib/rpmgi.c
 lib/rpminstall.c
 lib/rpmlead.c