From: Panu Matilainen Date: Fri, 3 Sep 2010 11:40:18 +0000 (+0300) Subject: Add a brand new rpmsign utility for package signing X-Git-Tag: tznext/4.11.0.1.tizen20130304~1738 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=df0b760e7e54b6714d9a52abbd2e33a44cd42d41;p=tools%2Flibrpm-tizen.git Add a brand new rpmsign utility for package signing - Signing (and deleting) are different from everything else in rpm in that it needs very little of rpm's facilities. For example access to the rpmdb is not needed at all. Splitting this to a separate, small utility allows various possibilities, like severely limiting its access from SELinux POV, control of signature generation with cli arguments (the main rpm executable is already overcrowded with options). It's also the first step to allow reasonably splitting rpm signing to a separate package; not everybody needs to sign packages, yet signing support needs to drag in GPG and whatnot. - Reimplement / refactor various librpm signature generation helpers into somewhat saner internal versions. --- diff --git a/Makefile.am b/Makefile.am index dfee933..4dae4a3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -78,7 +78,7 @@ pkginclude_HEADERS += build/rpmspec.h rpmbindir = `echo $(bindir) | $(SED) -e s,usr/bin,bin,` rpmbin_PROGRAMS = rpm -bin_PROGRAMS = rpm2cpio rpmbuild +bin_PROGRAMS = rpm2cpio rpmbuild rpmsign rpmlibexec_PROGRAMS = rpmconfig_SCRIPTS = find-provides find-requires mkinstalldirs \ @@ -98,6 +98,12 @@ rpm_LDADD = libcliutils.la rpm_LDADD += build/librpmbuild.la lib/librpm.la rpmio/librpmio.la rpm_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ +rpmsign_SOURCES = rpmsign.c debug.h system.h +rpmsign_CPPFLAGS = $(AM_CPPFLAGS) +rpmsign_LDADD = libcliutils.la +rpmsign_LDADD += lib/librpm.la rpmio/librpmio.la +rpmsign_LDADD += @WITH_NSS_LIB@ @WITH_POPT_LIB@ @WITH_ZLIB_LIB@ + rpmbuild_SOURCES = rpmbuild.c debug.h system.h rpmbuild_CPPFLAGS = $(AM_CPPFLAGS) rpmbuild_LDADD = libcliutils.la @@ -191,8 +197,6 @@ install-exec-hook: @LN_S@ ../../bin/rpm $(DESTDIR)$(bindir)/rpmquery rm -f $(DESTDIR)$(bindir)/rpmverify @LN_S@ ../../bin/rpm $(DESTDIR)$(bindir)/rpmverify - rm -f $(DESTDIR)$(bindir)/rpmsign - @LN_S@ ../../bin/rpm $(DESTDIR)$(bindir)/rpmsign rm -f $(DESTDIR)$(bindir)/rpmdb @LN_S@ ../../bin/rpm $(DESTDIR)$(bindir)/rpmdb @@ -206,7 +210,6 @@ install-data-local: # XXX to appease distcheck we need to remove "stuff" here... uninstall-local: @rm -f $(DESTDIR)$(bindir)/rpmquery - @rm -f $(DESTDIR)$(bindir)/rpmsign @rm -f $(DESTDIR)$(bindir)/rpmverify @rm -f $(DESTDIR)$(bindir)/rpmdb @rm -rf $(DESTDIR)$(rpmconfigdir)/platform/ diff --git a/po/POTFILES.in b/po/POTFILES.in index 7ea6694..c1f28b0 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -6,6 +6,7 @@ cliutils.c rpm2cpio.c rpmqv.c rpmbuild.c +rpmsign.c build/build.c build/expression.c build/files.c diff --git a/rpmsign.c b/rpmsign.c new file mode 100644 index 0000000..61e753e --- /dev/null +++ b/rpmsign.c @@ -0,0 +1,187 @@ +#include "system.h" +#include +#include + +#include +#include +#include "cliutils.h" +#include "debug.h" + +#if !defined(__GLIBC__) && !defined(__APPLE__) +char ** environ = NULL; +#endif + +enum modes { + MODE_ADDSIGN = (1 << 0), + MODE_RESIGN = (1 << 1), + MODE_DELSIGN = (1 << 2), +}; + +static int mode = 0; + +static struct poptOption optionsTable[] = { + { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0, + N_("Common options for all rpm modes and executables:"), NULL }, + { "addsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_ADDSIGN, + N_("sign package(s)"), NULL }, + { "resign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_RESIGN, + N_("sign package(s) (identical to --addsign)"), NULL }, + { "delsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_DELSIGN, + N_("delete package signatures"), NULL }, + + POPT_AUTOALIAS + POPT_AUTOHELP + POPT_TABLEEND +}; + +static rpmSigTag lookupSignatureType(void) +{ + rpmSigTag rc = 0; + + char *name = rpmExpand("%{?_signature}", NULL); + if (!(name && *name != '\0')) + rc = 0; + else if (!rstrcasecmp(name, "none")) + rc = 0; + else if (!rstrcasecmp(name, "pgp")) + rc = RPMSIGTAG_PGP; + else if (!rstrcasecmp(name, "pgp5")) /* XXX legacy */ + rc = RPMSIGTAG_PGP; + else if (!rstrcasecmp(name, "gpg")) + rc = RPMSIGTAG_GPG; + else + rc = -1; /* Invalid %_signature spec in macro file */ + + name = _free(name); + return rc; +} + +static int checkPassPhrase(const char * passPhrase) +{ + int passPhrasePipe[2]; + int pid, status; + int rc; + int xx; + + if (passPhrase == NULL) + return -1; + + passPhrasePipe[0] = passPhrasePipe[1] = 0; + xx = pipe(passPhrasePipe); + if (!(pid = fork())) { + char * cmd, * gpg_path; + char *const *av; + int fdno; + + xx = close(STDIN_FILENO); + xx = close(STDOUT_FILENO); + xx = close(passPhrasePipe[1]); + if ((fdno = open("/dev/null", O_RDONLY)) != STDIN_FILENO) { + xx = dup2(fdno, STDIN_FILENO); + xx = close(fdno); + } + if ((fdno = open("/dev/null", O_WRONLY)) != STDOUT_FILENO) { + xx = dup2(fdno, STDOUT_FILENO); + xx = close(fdno); + } + xx = dup2(passPhrasePipe[0], 3); + + unsetenv("MALLOC_CHECK_"); + gpg_path = rpmExpand("%{?_gpg_path}", NULL); + + if (!rstreq(gpg_path, "")) + setenv("GNUPGHOME", gpg_path, 1); + + cmd = rpmExpand("%{?__gpg_check_password_cmd}", NULL); + rc = poptParseArgvString(cmd, NULL, (const char ***)&av); + if (!rc) + rc = execve(av[0], av+1, environ); + + fprintf(stderr, _("Could not exec %s: %s\n"), "gpg", + strerror(errno)); + _exit(EXIT_FAILURE); + } + + xx = close(passPhrasePipe[0]); + xx = write(passPhrasePipe[1], passPhrase, strlen(passPhrase)); + xx = write(passPhrasePipe[1], "\n", 1); + xx = close(passPhrasePipe[1]); + + (void) waitpid(pid, &status, 0); + + return ((WIFEXITED(status) && WEXITSTATUS(status) == 0)) ? 0 : 1; +} + +/* TODO: permit overriding macro setup on the command line */ +static int doSign(ARGV_const_t args) +{ + int rc = EXIT_FAILURE; + int sigTag = lookupSignatureType(); + char * passPhrase = NULL; + char * name = rpmExpand("%{?_gpg_name}", NULL); + + if (rstreq(name, "")) { + fprintf(stderr, _("You must set \"%%_gpg_name\" in your macro file\n")); + goto exit; + } + + switch (sigTag) { + case RPMSIGTAG_PGP: + case RPMSIGTAG_GPG: + case RPMSIGTAG_DSA: + case RPMSIGTAG_RSA: + break; + default: + fprintf(stderr, _("Invalid %%_signature spec in macro file.\n")); + goto exit; + break; + } + + /* XXX FIXME: eliminate obsolete getpass() usage */ + passPhrase = getpass(_("Enter pass phrase: ")); + passPhrase = (passPhrase != NULL) ? rstrdup(passPhrase) : NULL; + if (checkPassPhrase(passPhrase) == 0) { + fprintf(stderr, _("Pass phrase is good.\n")); + rc = rpmcliSign(args, 0, sigTag, passPhrase); + } else { + fprintf(stderr, _("Pass phrase check failed\n")); + } + +exit: + free(name); + return rc; +} + +int main(int argc, char *argv[]) +{ + int ec = EXIT_FAILURE; + poptContext optCon = rpmcliInit(argc, argv, optionsTable); + ARGV_const_t args = NULL; + + if (argc <= 1) { + printUsage(optCon, stderr, 0); + goto exit; + } + + args = (ARGV_const_t) poptGetArgs(optCon); + if (args == NULL) { + argerror(_("no arguments given")); + } + + switch (mode) { + case MODE_ADDSIGN: + case MODE_RESIGN: + ec = doSign(args); + break; + case MODE_DELSIGN: + ec = rpmcliSign(args, 1, 0, NULL); + break; + default: + argerror(_("only one major mode may be specified")); + break; + } + +exit: + rpmcliFini(optCon); + return ec; +}