Add macro %isu_package to generate ISU Package
[platform/upstream/rpm.git] / rpmsign.c
1 #include "system.h"
2 #include <errno.h>
3 #include <sys/wait.h>
4
5 #include <popt.h>
6 #include <rpm/rpmcli.h>
7 #include <rpm/rpmsign.h>
8 #include "cliutils.h"
9 #include "debug.h"
10
11 #if !defined(__GLIBC__) && !defined(__APPLE__)
12 char ** environ = NULL;
13 #endif
14
15 enum modes {
16     MODE_ADDSIGN = (1 << 0),
17     MODE_RESIGN  = (1 << 1),
18     MODE_DELSIGN = (1 << 2),
19 };
20
21 static int mode = 0;
22
23 static struct poptOption signOptsTable[] = {
24     { "addsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_ADDSIGN,
25         N_("sign package(s)"), NULL },
26     { "resign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_RESIGN,
27         N_("sign package(s) (identical to --addsign)"), NULL },
28     { "delsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_DELSIGN,
29         N_("delete package signatures"), NULL },
30     POPT_TABLEEND
31 };
32
33 static struct poptOption optionsTable[] = {
34     { NULL, '\0', POPT_ARG_INCLUDE_TABLE, signOptsTable, 0,
35         N_("Signature options:"), NULL },
36     { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
37         N_("Common options for all rpm modes and executables:"), NULL },
38
39     POPT_AUTOALIAS
40     POPT_AUTOHELP
41     POPT_TABLEEND
42 };
43
44 static int checkPassPhrase(const char * passPhrase)
45 {
46     int passPhrasePipe[2];
47     int pid, status;
48     int rc;
49     int xx;
50
51     if (passPhrase == NULL)
52         return -1;
53
54     passPhrasePipe[0] = passPhrasePipe[1] = 0;
55     xx = pipe(passPhrasePipe);
56     if (!(pid = fork())) {
57         char * cmd, * gpg_path;
58         char *const *av;
59         int fdno;
60
61         xx = close(STDIN_FILENO);
62         xx = close(STDOUT_FILENO);
63         xx = close(passPhrasePipe[1]);
64         if ((fdno = open("/dev/null", O_RDONLY)) != STDIN_FILENO) {
65             xx = dup2(fdno, STDIN_FILENO);
66             xx = close(fdno);
67         }
68         if ((fdno = open("/dev/null", O_WRONLY)) != STDOUT_FILENO) {
69             xx = dup2(fdno, STDOUT_FILENO);
70             xx = close(fdno);
71         }
72         xx = dup2(passPhrasePipe[0], 3);
73
74         unsetenv("MALLOC_CHECK_");
75         gpg_path = rpmExpand("%{?_gpg_path}", NULL);
76
77         if (!rstreq(gpg_path, ""))
78             setenv("GNUPGHOME", gpg_path, 1);
79         
80         cmd = rpmExpand("%{?__gpg_check_password_cmd}", NULL);
81         rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
82         if (!rc)
83             rc = execve(av[0], av+1, environ);
84
85         fprintf(stderr, _("Could not exec %s: %s\n"), "gpg",
86                     strerror(errno));
87         _exit(EXIT_FAILURE);
88     }
89
90     xx = close(passPhrasePipe[0]);
91     xx = write(passPhrasePipe[1], passPhrase, strlen(passPhrase));
92     xx = write(passPhrasePipe[1], "\n", 1);
93     xx = close(passPhrasePipe[1]);
94
95     (void) waitpid(pid, &status, 0);
96
97     return ((WIFEXITED(status) && WEXITSTATUS(status) == 0)) ? 0 : 1;
98 }
99
100 /* TODO: permit overriding macro setup on the command line */
101 static int doSign(poptContext optCon)
102 {
103     int rc = EXIT_FAILURE;
104     char * passPhrase = NULL;
105     char * name = rpmExpand("%{?_gpg_name}", NULL);
106
107     if (rstreq(name, "")) {
108         fprintf(stderr, _("You must set \"%%_gpg_name\" in your macro file\n"));
109         goto exit;
110     }
111
112     /* XXX FIXME: eliminate obsolete getpass() usage */
113     passPhrase = getpass(_("Enter pass phrase: "));
114     passPhrase = (passPhrase != NULL) ? rstrdup(passPhrase) : NULL;
115     if (checkPassPhrase(passPhrase) == 0) {
116         const char *arg;
117         fprintf(stderr, _("Pass phrase is good.\n"));
118         rc = 0;
119         while ((arg = poptGetArg(optCon)) != NULL) {
120             rc += rpmPkgSign(arg, NULL, passPhrase);
121         }
122     } else {
123         fprintf(stderr, _("Pass phrase check failed or gpg key expired\n"));
124     }
125
126 exit:
127     free(passPhrase);
128     free(name);
129     return rc;
130 }
131
132 int main(int argc, char *argv[])
133 {
134     int ec = EXIT_FAILURE;
135     poptContext optCon = rpmcliInit(argc, argv, optionsTable);
136     const char *arg;
137     
138     if (argc <= 1) {
139         printUsage(optCon, stderr, 0);
140         goto exit;
141     }
142
143     if (poptPeekArg(optCon) == NULL) {
144         argerror(_("no arguments given"));
145     }
146
147     switch (mode) {
148     case MODE_ADDSIGN:
149     case MODE_RESIGN:
150         ec = doSign(optCon);
151         break;
152     case MODE_DELSIGN:
153         ec = 0;
154         while ((arg = poptGetArg(optCon)) != NULL) {
155             ec += rpmPkgDelSign(arg);
156         }
157         break;
158     default:
159         argerror(_("only one major mode may be specified"));
160         break;
161     }
162
163 exit:
164     rpmcliFini(optCon);
165     return ec;
166 }