#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; }