#include "system.h"
+#include <errno.h>
+#include <sys/wait.h>
+#include <popt.h>
+
#include <rpm/rpmlib.h> /* RPMSIGTAG & related */
#include <rpm/rpmpgp.h>
#include <rpm/rpmcli.h>
#include "debug.h"
+#if !defined(__GLIBC__) && !defined(__APPLE__)
+char ** environ = NULL;
+#endif
+
static int closeFile(FD_t *fdp)
{
if (fdp == NULL || *fdp == NULL)
return rc;
}
+/*
+ * NSS doesn't support everything GPG does. Basic tests to see if the
+ * generated signature is something we can use.
+ */
+static int validatePGPSig(pgpDigParams sigp)
+{
+ pgpPubkeyAlgo pa = sigp->pubkey_algo;
+ /* TODO: query from the implementation instead of hardwiring here */
+ if (pa != PGPPUBKEYALGO_DSA && pa != PGPPUBKEYALGO_RSA) {
+ rpmlog(RPMLOG_ERR, _("Unsupported PGP pubkey algorithm %d\n"),
+ sigp->pubkey_algo);
+ return 1;
+ }
+
+ if (rpmDigestLength(sigp->hash_algo) == 0) {
+ rpmlog(RPMLOG_ERR, _("Unsupported PGP hash algorithm %d\n"),
+ sigp->hash_algo);
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Generate GPG signature(s) for a header+payload file.
+ * @param file header+payload file name
+ * @retval *sigTagp signature tag
+ * @retval *pktp signature packet(s)
+ * @retval *pktlenp signature packet(s) length
+ * @param passPhrase private key pass phrase
+ * @return 0 on success, 1 on failure
+ */
+static int makeGPGSignature(const char * file, rpmSigTag * sigTagp,
+ uint8_t ** pktp, size_t * pktlenp,
+ const char * passPhrase)
+{
+ char * sigfile = NULL;
+ int pid, status;
+ int inpipe[2];
+ FILE * fpipe;
+ struct stat st;
+ const char * cmd;
+ char *const *av;
+ pgpDig dig = NULL;
+ pgpDigParams sigp = NULL;
+ int rc = 1; /* assume failure */
+
+ rasprintf(&sigfile, "%s.sig", file);
+
+ addMacro(NULL, "__plaintext_filename", NULL, file, -1);
+ addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
+
+ inpipe[0] = inpipe[1] = 0;
+ if (pipe(inpipe) < 0) {
+ rpmlog(RPMLOG_ERR, _("Couldn't create pipe for signing: %m"));
+ goto exit;
+ }
+
+ if (!(pid = fork())) {
+ const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
+
+ (void) dup2(inpipe[0], 3);
+ (void) close(inpipe[1]);
+
+ if (gpg_path && *gpg_path != '\0')
+ (void) setenv("GNUPGHOME", gpg_path, 1);
+ (void) setenv("LC_ALL", "C", 1);
+
+ unsetenv("MALLOC_CHECK_");
+ cmd = rpmExpand("%{?__gpg_sign_cmd}", NULL);
+ rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
+ if (!rc)
+ rc = execve(av[0], av+1, environ);
+
+ rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "gpg",
+ strerror(errno));
+ _exit(EXIT_FAILURE);
+ }
+
+ delMacro(NULL, "__plaintext_filename");
+ delMacro(NULL, "__signature_filename");
+
+ fpipe = fdopen(inpipe[1], "w");
+ (void) close(inpipe[0]);
+ if (fpipe) {
+ fprintf(fpipe, "%s\n", (passPhrase ? passPhrase : ""));
+ (void) fclose(fpipe);
+ }
+
+ (void) waitpid(pid, &status, 0);
+ if (!WIFEXITED(status) || WEXITSTATUS(status)) {
+ rpmlog(RPMLOG_ERR, _("gpg exec failed (%d)\n"), WEXITSTATUS(status));
+ goto exit;
+ }
+
+ if (stat(sigfile, &st)) {
+ /* GPG failed to write signature */
+ rpmlog(RPMLOG_ERR, _("gpg failed to write signature\n"));
+ goto exit;
+ }
+
+ *pktlenp = st.st_size;
+ rpmlog(RPMLOG_DEBUG, "GPG sig size: %zd\n", *pktlenp);
+ *pktp = xmalloc(*pktlenp);
+
+ { FD_t fd;
+
+ rc = 0;
+ fd = Fopen(sigfile, "r.ufdio");
+ if (fd != NULL && !Ferror(fd)) {
+ rc = Fread(*pktp, sizeof(**pktp), *pktlenp, fd);
+ (void) Fclose(fd);
+ }
+ if (rc != *pktlenp) {
+ *pktp = _free(*pktp);
+ rpmlog(RPMLOG_ERR, _("unable to read the signature\n"));
+ goto exit;
+ }
+ }
+
+ rpmlog(RPMLOG_DEBUG, "Got %zd bytes of GPG sig\n", *pktlenp);
+
+ /* Parse the signature, change signature tag as appropriate. */
+ dig = pgpNewDig();
+
+ (void) pgpPrtPkts(*pktp, *pktlenp, dig, 0);
+ sigp = &dig->signature;
+
+ switch (*sigTagp) {
+ case RPMSIGTAG_GPG:
+ /* XXX check MD5 hash too? */
+ if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA)
+ *sigTagp = RPMSIGTAG_PGP;
+ break;
+ case RPMSIGTAG_PGP5: /* XXX legacy */
+ case RPMSIGTAG_PGP:
+ if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA)
+ *sigTagp = RPMSIGTAG_GPG;
+ break;
+ case RPMSIGTAG_DSA:
+ /* XXX check MD5 hash too? */
+ if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA)
+ *sigTagp = RPMSIGTAG_RSA;
+ break;
+ case RPMSIGTAG_RSA:
+ if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA)
+ *sigTagp = RPMSIGTAG_DSA;
+ break;
+ default:
+ break;
+ }
+
+ rc = validatePGPSig(sigp);
+ dig = pgpFreeDig(dig);
+
+exit:
+ (void) unlink(sigfile);
+ free(sigfile);
+
+ return rc;
+}
+
+/**
+ * Generate header only signature(s) from a header+payload file.
+ * @param sigh signature header
+ * @param file header+payload file name
+ * @param sigTag type of signature(s) to add
+ * @param passPhrase private key pass phrase
+ * @return 0 on success, -1 on failure
+ */
+static int makeHDRSignature(Header sigh, const char * file, rpmSigTag sigTag,
+ const char * passPhrase)
+{
+ Header h = NULL;
+ FD_t fd = NULL;
+ uint8_t * pkt = NULL;
+ size_t pktlen;
+ char * fn = NULL;
+ int ret = -1; /* assume failure. */
+
+ switch (sigTag) {
+ case RPMSIGTAG_DSA:
+ case RPMSIGTAG_RSA:
+ fd = Fopen(file, "r.fdio");
+ if (fd == NULL || Ferror(fd))
+ goto exit;
+ h = headerRead(fd, HEADER_MAGIC_YES);
+ if (h == NULL)
+ goto exit;
+ (void) Fclose(fd);
+ fd = rpmMkTempFile(NULL, &fn);
+ if (fd == NULL || Ferror(fd))
+ goto exit;
+ if (headerWrite(fd, h, HEADER_MAGIC_YES))
+ goto exit;
+ (void) Fclose(fd); fd = NULL;
+ if (makeGPGSignature(fn, &sigTag, &pkt, &pktlen, passPhrase)
+ || !sighdrPut(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
+ goto exit;
+ ret = 0;
+ break;
+ default:
+ goto exit;
+ break;
+ }
+
+exit:
+ if (fn) {
+ (void) unlink(fn);
+ free(fn);
+ }
+ free(pkt);
+ h = headerFree(h);
+ if (fd != NULL) (void) Fclose(fd);
+ return ret;
+}
+
+int rpmGenSignature(Header sigh, const char * file, rpmSigTag sigTag,
+ const char * passPhrase)
+{
+ uint8_t * pkt = NULL;
+ size_t pktlen;
+ int ret = -1; /* assume failure. */
+
+ switch (sigTag) {
+ case RPMSIGTAG_PGP5: /* XXX legacy */
+ case RPMSIGTAG_PGP:
+ case RPMSIGTAG_GPG: {
+ rpmSigTag hdrtag;
+ if (makeGPGSignature(file, &sigTag, &pkt, &pktlen, passPhrase)
+ || !sighdrPut(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
+ break;
+ /* XXX Piggyback a header-only DSA/RSA signature as well. */
+ hdrtag = (sigTag == RPMSIGTAG_GPG) ? RPMSIGTAG_DSA : RPMSIGTAG_RSA;
+ ret = makeHDRSignature(sigh, file, hdrtag, passPhrase);
+ } break;
+ case RPMSIGTAG_RSA:
+ case RPMSIGTAG_DSA:
+ ret = makeHDRSignature(sigh, file, sigTag, passPhrase);
+ break;
+ default:
+ break;
+ }
+ free(pkt);
+
+ return ret;
+}
+
/**
* Retrieve signature from header tag
* @param sigh signature header
#include "system.h"
-#include <errno.h>
#include <inttypes.h>
-#include <sys/wait.h>
-#include <popt.h>
#include <rpm/rpmtypes.h>
-#include <rpm/rpmmacro.h> /* XXX for rpmExpand() */
#include <rpm/rpmstring.h>
#include <rpm/rpmfileutil.h>
#include <rpm/rpmlog.h>
#include "debug.h"
-#if !defined(__GLIBC__) && !defined(__APPLE__)
-char ** environ = NULL;
-#endif
-
/**
* Print package size.
* @todo rpmio: use fdSize rather than fstat(2) to get file size.
return headerFree(sigh);
}
-/*
- * NSS doesn't support everything GPG does. Basic tests to see if the
- * generated signature is something we can use.
- */
-static int validatePGPSig(pgpDigParams sigp)
-{
- pgpPubkeyAlgo pa = sigp->pubkey_algo;
- /* TODO: query from the implementation instead of hardwiring here */
- if (pa != PGPPUBKEYALGO_DSA && pa != PGPPUBKEYALGO_RSA) {
- rpmlog(RPMLOG_ERR, _("Unsupported PGP pubkey algorithm %d\n"),
- sigp->pubkey_algo);
- return 1;
- }
-
- if (rpmDigestLength(sigp->hash_algo) == 0) {
- rpmlog(RPMLOG_ERR, _("Unsupported PGP hash algorithm %d\n"),
- sigp->hash_algo);
- return 1;
- }
-
- return 0;
-}
-
-/**
- * Generate GPG signature(s) for a header+payload file.
- * @param file header+payload file name
- * @retval *sigTagp signature tag
- * @retval *pktp signature packet(s)
- * @retval *pktlenp signature packet(s) length
- * @param passPhrase private key pass phrase
- * @return 0 on success, 1 on failure
- */
-static int makeGPGSignature(const char * file, rpmSigTag * sigTagp,
- uint8_t ** pktp, size_t * pktlenp,
- const char * passPhrase)
-{
- char * sigfile = NULL;
- int pid, status;
- int inpipe[2];
- FILE * fpipe;
- struct stat st;
- const char * cmd;
- char *const *av;
- pgpDig dig = NULL;
- pgpDigParams sigp = NULL;
- int rc = 1; /* assume failure */
-
- rasprintf(&sigfile, "%s.sig", file);
-
- addMacro(NULL, "__plaintext_filename", NULL, file, -1);
- addMacro(NULL, "__signature_filename", NULL, sigfile, -1);
-
- inpipe[0] = inpipe[1] = 0;
- if (pipe(inpipe) < 0) {
- rpmlog(RPMLOG_ERR, _("Couldn't create pipe for signing: %m"));
- goto exit;
- }
-
- if (!(pid = fork())) {
- const char *gpg_path = rpmExpand("%{?_gpg_path}", NULL);
-
- (void) dup2(inpipe[0], 3);
- (void) close(inpipe[1]);
-
- if (gpg_path && *gpg_path != '\0')
- (void) setenv("GNUPGHOME", gpg_path, 1);
- (void) setenv("LC_ALL", "C", 1);
-
- unsetenv("MALLOC_CHECK_");
- cmd = rpmExpand("%{?__gpg_sign_cmd}", NULL);
- rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
- if (!rc)
- rc = execve(av[0], av+1, environ);
-
- rpmlog(RPMLOG_ERR, _("Could not exec %s: %s\n"), "gpg",
- strerror(errno));
- _exit(EXIT_FAILURE);
- }
-
- delMacro(NULL, "__plaintext_filename");
- delMacro(NULL, "__signature_filename");
-
- fpipe = fdopen(inpipe[1], "w");
- (void) close(inpipe[0]);
- if (fpipe) {
- fprintf(fpipe, "%s\n", (passPhrase ? passPhrase : ""));
- (void) fclose(fpipe);
- }
-
- (void) waitpid(pid, &status, 0);
- if (!WIFEXITED(status) || WEXITSTATUS(status)) {
- rpmlog(RPMLOG_ERR, _("gpg exec failed (%d)\n"), WEXITSTATUS(status));
- goto exit;
- }
-
- if (stat(sigfile, &st)) {
- /* GPG failed to write signature */
- rpmlog(RPMLOG_ERR, _("gpg failed to write signature\n"));
- goto exit;
- }
-
- *pktlenp = st.st_size;
- rpmlog(RPMLOG_DEBUG, "GPG sig size: %zd\n", *pktlenp);
- *pktp = xmalloc(*pktlenp);
-
- { FD_t fd;
-
- rc = 0;
- fd = Fopen(sigfile, "r.ufdio");
- if (fd != NULL && !Ferror(fd)) {
- rc = Fread(*pktp, sizeof(**pktp), *pktlenp, fd);
- (void) Fclose(fd);
- }
- if (rc != *pktlenp) {
- *pktp = _free(*pktp);
- rpmlog(RPMLOG_ERR, _("unable to read the signature\n"));
- goto exit;
- }
- }
-
- rpmlog(RPMLOG_DEBUG, "Got %zd bytes of GPG sig\n", *pktlenp);
-
- /* Parse the signature, change signature tag as appropriate. */
- dig = pgpNewDig();
-
- (void) pgpPrtPkts(*pktp, *pktlenp, dig, 0);
- sigp = &dig->signature;
-
- switch (*sigTagp) {
- case RPMSIGTAG_GPG:
- /* XXX check MD5 hash too? */
- if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA)
- *sigTagp = RPMSIGTAG_PGP;
- break;
- case RPMSIGTAG_PGP5: /* XXX legacy */
- case RPMSIGTAG_PGP:
- if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA)
- *sigTagp = RPMSIGTAG_GPG;
- break;
- case RPMSIGTAG_DSA:
- /* XXX check MD5 hash too? */
- if (sigp->pubkey_algo == PGPPUBKEYALGO_RSA)
- *sigTagp = RPMSIGTAG_RSA;
- break;
- case RPMSIGTAG_RSA:
- if (sigp->pubkey_algo == PGPPUBKEYALGO_DSA)
- *sigTagp = RPMSIGTAG_DSA;
- break;
- default:
- break;
- }
-
- rc = validatePGPSig(sigp);
- dig = pgpFreeDig(dig);
-
-exit:
- (void) unlink(sigfile);
- free(sigfile);
-
- return rc;
-}
-
-/**
- * Generate header only signature(s) from a header+payload file.
- * @param sigh signature header
- * @param file header+payload file name
- * @param sigTag type of signature(s) to add
- * @param passPhrase private key pass phrase
- * @return 0 on success, -1 on failure
- */
-static int makeHDRSignature(Header sigh, const char * file, rpmSigTag sigTag,
- const char * passPhrase)
-{
- Header h = NULL;
- FD_t fd = NULL;
- uint8_t * pkt = NULL;
- size_t pktlen;
- char * fn = NULL;
- int ret = -1; /* assume failure. */
-
- switch (sigTag) {
- case RPMSIGTAG_DSA:
- case RPMSIGTAG_RSA:
- fd = Fopen(file, "r.fdio");
- if (fd == NULL || Ferror(fd))
- goto exit;
- h = headerRead(fd, HEADER_MAGIC_YES);
- if (h == NULL)
- goto exit;
- (void) Fclose(fd);
- fd = rpmMkTempFile(NULL, &fn);
- if (fd == NULL || Ferror(fd))
- goto exit;
- if (headerWrite(fd, h, HEADER_MAGIC_YES))
- goto exit;
- (void) Fclose(fd); fd = NULL;
- if (makeGPGSignature(fn, &sigTag, &pkt, &pktlen, passPhrase)
- || !sighdrPut(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
- goto exit;
- ret = 0;
- break;
- default:
- goto exit;
- break;
- }
-
-exit:
- if (fn) {
- (void) unlink(fn);
- free(fn);
- }
- free(pkt);
- h = headerFree(h);
- if (fd != NULL) (void) Fclose(fd);
- return ret;
-}
-
-int rpmGenSignature(Header sigh, const char * file, rpmSigTag sigTag,
- const char * passPhrase)
-{
- uint8_t * pkt = NULL;
- size_t pktlen;
- int ret = -1; /* assume failure. */
-
- switch (sigTag) {
- case RPMSIGTAG_PGP5: /* XXX legacy */
- case RPMSIGTAG_PGP:
- case RPMSIGTAG_GPG: {
- rpmSigTag hdrtag;
- if (makeGPGSignature(file, &sigTag, &pkt, &pktlen, passPhrase)
- || !sighdrPut(sigh, sigTag, RPM_BIN_TYPE, pkt, pktlen))
- break;
- /* XXX Piggyback a header-only DSA/RSA signature as well. */
- hdrtag = (sigTag == RPMSIGTAG_GPG) ? RPMSIGTAG_DSA : RPMSIGTAG_RSA;
- ret = makeHDRSignature(sigh, file, hdrtag, passPhrase);
- } break;
- case RPMSIGTAG_RSA:
- case RPMSIGTAG_DSA:
- ret = makeHDRSignature(sigh, file, sigTag, passPhrase);
- break;
- default:
- break;
- }
- free(pkt);
-
- return ret;
-}
-
static int makeHDRDigest(Header sigh, const char * file, rpmSigTag sigTag)
{
Header h = NULL;