Add macro %isu_package to generate ISU Package
[platform/upstream/rpm.git] / rpmsign.c
index 2e0a72a..ae86f66 100644 (file)
--- a/rpmsign.c
+++ b/rpmsign.c
@@ -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\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;