diff options
Diffstat (limited to 'rpmsign.c')
-rw-r--r-- | rpmsign.c | 168 |
1 files changed, 97 insertions, 71 deletions
@@ -1,6 +1,7 @@ #include "system.h" #include <errno.h> #include <sys/wait.h> +#include <termios.h> #include <popt.h> #include <rpm/rpmcli.h> @@ -8,17 +9,21 @@ #include "cliutils.h" #include "debug.h" -#if !defined(__GLIBC__) && !defined(__APPLE__) -char ** environ = NULL; -#endif - enum modes { + MODE_NONE = 0, MODE_ADDSIGN = (1 << 0), MODE_RESIGN = (1 << 1), MODE_DELSIGN = (1 << 2), }; -static int mode = 0; +static int mode = MODE_NONE; + +#ifdef WITH_IMAEVM +static int signfiles = 0, fskpass = 0; +static char * fileSigningKey = NULL; +#endif + +static struct rpmSignArgs sargs = {NULL, 0, 0}; static struct poptOption signOptsTable[] = { { "addsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_ADDSIGN, @@ -27,6 +32,15 @@ static struct poptOption signOptsTable[] = { N_("sign package(s) (identical to --addsign)"), NULL }, { "delsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_DELSIGN, N_("delete package signatures"), NULL }, +#ifdef WITH_IMAEVM + { "signfiles", '\0', POPT_ARG_NONE, &signfiles, 0, + N_("sign package(s) files"), NULL}, + { "fskpath", '\0', POPT_ARG_STRING, &fileSigningKey, 0, + N_("use file signing key <key>"), + N_("<key>") }, + { "fskpass", '\0', POPT_ARG_NONE, &fskpass, 0, + N_("prompt for file signing key password"), NULL}, +#endif POPT_TABLEEND }; @@ -41,67 +55,46 @@ static struct poptOption optionsTable[] = { POPT_TABLEEND }; -static int checkPassPhrase(const char * passPhrase) +#ifdef WITH_IMAEVM +static char *get_fskpass(void) { - 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); + struct termios flags, tmp_flags; + int passlen = 64; + char *password = xmalloc(passlen); + char *pwd = NULL; + + tcgetattr(fileno(stdin), &flags); + tmp_flags = flags; + tmp_flags.c_lflag &= ~ECHO; + tmp_flags.c_lflag |= ECHONL; + + if (tcsetattr(fileno(stdin), TCSANOW, &tmp_flags) != 0) { + perror("tcsetattr"); + goto exit; } - xx = close(passPhrasePipe[0]); - xx = write(passPhrasePipe[1], passPhrase, strlen(passPhrase)); - xx = write(passPhrasePipe[1], "\n", 1); - xx = close(passPhrasePipe[1]); + printf("PEM password: "); + pwd = fgets(password, passlen, stdin); - (void) waitpid(pid, &status, 0); + if (tcsetattr(fileno(stdin), TCSANOW, &flags) != 0) { + perror("tcsetattr"); + pwd = NULL; + goto exit; + } - return ((WIFEXITED(status) && WEXITSTATUS(status) == 0)) ? 0 : 1; +exit: + if (pwd) + pwd[strlen(pwd) - 1] = '\0'; /* remove newline */ + else + free(password); + return pwd; } +#endif /* TODO: permit overriding macro setup on the command line */ -static int doSign(poptContext optCon) +static int doSign(poptContext optCon, struct rpmSignArgs *sargs) { int rc = EXIT_FAILURE; - char * passPhrase = NULL; char * name = rpmExpand("%{?_gpg_name}", NULL); if (rstreq(name, "")) { @@ -109,22 +102,42 @@ static int doSign(poptContext optCon) goto exit; } - /* XXX FIXME: eliminate obsolete getpass() usage */ - passPhrase = getpass(_("Enter pass phrase: ")); - passPhrase = (passPhrase != NULL) ? rstrdup(passPhrase) : NULL; - if (checkPassPhrase(passPhrase) == 0) { - const char *arg; - fprintf(stderr, _("Pass phrase is good.\n")); - rc = 0; - while ((arg = poptGetArg(optCon)) != NULL) { - rc += rpmPkgSign(arg, NULL, passPhrase); +#ifdef WITH_IMAEVM + if (fileSigningKey) { + rpmPushMacro(NULL, "_file_signing_key", NULL, fileSigningKey, RMIL_GLOBAL); + } + + if (signfiles) { + char *fileSigningKeyPassword = NULL; + char *key = rpmExpand("%{?_file_signing_key}", NULL); + if (rstreq(key, "")) { + fprintf(stderr, _("You must set \"%%_file_signing_key\" in your macro file or on the command line with --fskpath\n")); + goto exit; } - } else { - fprintf(stderr, _("Pass phrase check failed or gpg key expired\n")); + + if (fskpass) { + fileSigningKeyPassword = get_fskpass(); + } + + if (fileSigningKeyPassword) { + rpmPushMacro(NULL, "_file_signing_key_password", NULL, + fileSigningKeyPassword, RMIL_CMDLINE); + memset(fileSigningKeyPassword, 0, strlen(fileSigningKeyPassword)); + free(fileSigningKeyPassword); + } + + sargs->signfiles = 1; + free(key); + } +#endif + + const char *arg; + rc = 0; + while ((arg = poptGetArg(optCon)) != NULL) { + rc += rpmPkgSign(arg, sargs); } exit: - free(passPhrase); free(name); return rc; } @@ -132,9 +145,13 @@ exit: int main(int argc, char *argv[]) { int ec = EXIT_FAILURE; - poptContext optCon = rpmcliInit(argc, argv, optionsTable); + poptContext optCon = NULL; const char *arg; + xsetprogname(argv[0]); /* Portability call -- see system.h */ + + optCon = rpmcliInit(argc, argv, optionsTable); + if (argc <= 1) { printUsage(optCon, stderr, 0); goto exit; @@ -144,17 +161,26 @@ int main(int argc, char *argv[]) argerror(_("no arguments given")); } +#ifdef WITH_IMAEVM + if (fileSigningKey && !signfiles) { + argerror(_("--fskpath may only be specified when signing files")); + } +#endif + switch (mode) { case MODE_ADDSIGN: case MODE_RESIGN: - ec = doSign(optCon); + ec = doSign(optCon, &sargs); break; case MODE_DELSIGN: ec = 0; while ((arg = poptGetArg(optCon)) != NULL) { - ec += rpmPkgDelSign(arg); + ec += rpmPkgDelSign(arg, &sargs); } break; + case MODE_NONE: + printUsage(optCon, stderr, 0); + break; default: argerror(_("only one major mode may be specified")); break; |