rpm: rpmsign.c Source File

rpm 4.11.1-rc1

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

rpmsign.c
Go to the documentation of this file.
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 = -1;
49 int xx;
50
51 if (passPhrase == NULL)
52 return -1;
53
54 passPhrasePipe[0] = passPhrasePipe[1] = 0;
55 if (pipe(passPhrasePipe))
56 return -1;
57
58 pid = fork();
59 if (pid < 0) {
60 close(passPhrasePipe[0]);
61 close(passPhrasePipe[1]);
62 return -1;
63 }
64
65 if (pid == 0) {
66 char * cmd, * gpg_path;
67 char *const *av;
68 int fdno;
69
70 close(STDIN_FILENO);
71 close(STDOUT_FILENO);
72 close(passPhrasePipe[1]);
73 if ((fdno = open("/dev/null", O_RDONLY)) != STDIN_FILENO) {
74 xx = dup2(fdno, STDIN_FILENO);
75 close(fdno);
76 }
77 if ((fdno = open("/dev/null", O_WRONLY)) != STDOUT_FILENO) {
78 xx = dup2(fdno, STDOUT_FILENO);
79 close(fdno);
80 }
81 xx = dup2(passPhrasePipe[0], 3);
82
83 unsetenv("MALLOC_CHECK_");
84 gpg_path = rpmExpand("%{?_gpg_path}", NULL);
85
86 if (!rstreq(gpg_path, ""))
87 setenv("GNUPGHOME", gpg_path, 1);
88
89 cmd = rpmExpand("%{?__gpg_check_password_cmd}", NULL);
90 rc = poptParseArgvString(cmd, NULL, (const char ***)&av);
91 if (xx >= 0 && rc == 0) {
92 rc = execve(av[0], av+1, environ);
93 fprintf(stderr, _("Could not exec %s: %s\n"), "gpg",
94 strerror(errno));
95 }
96 _exit(EXIT_FAILURE);
97 }
98
99 close(passPhrasePipe[0]);
100 xx = write(passPhrasePipe[1], passPhrase, strlen(passPhrase));
101 xx = write(passPhrasePipe[1], "\n", 1);
102 close(passPhrasePipe[1]);
103
104 if (xx >= 0 && waitpid(pid, &status, 0) >= 0)
105 rc = (WIFEXITED(status) && WEXITSTATUS(status) == 0) ? 0 : 1;
106
107 return rc;
108 }
109
110 /* TODO: permit overriding macro setup on the command line */
111 static int doSign(poptContext optCon)
112 {
113 int rc = EXIT_FAILURE;
114 char * passPhrase = NULL;
115 char * name = rpmExpand("%{?_gpg_name}", NULL);
116
117 if (rstreq(name, "")) {
118 fprintf(stderr, _("You must set \"%%_gpg_name\" in your macro file\n"));
119 goto exit;
120 }
121
122 /* XXX FIXME: eliminate obsolete getpass() usage */
123 passPhrase = getpass(_("Enter pass phrase: "));
124 passPhrase = (passPhrase != NULL) ? rstrdup(passPhrase) : NULL;
125 if (checkPassPhrase(passPhrase) == 0) {
126 const char *arg;
127 fprintf(stderr, _("Pass phrase is good.\n"));
128 rc = 0;
129 while ((arg = poptGetArg(optCon)) != NULL) {
130 rc += rpmPkgSign(arg, NULL, passPhrase);
131 }
132 } else {
133 fprintf(stderr, _("Pass phrase check failed or gpg key expired\n"));
134 }
135
136 exit:
137 free(passPhrase);
138 free(name);
139 return rc;
140 }
141
142 int main(int argc, char *argv[])
143 {
144 int ec = EXIT_FAILURE;
145 poptContext optCon = rpmcliInit(argc, argv, optionsTable);
146 const char *arg;
147
148 if (argc <= 1) {
149 printUsage(optCon, stderr, 0);
150 goto exit;
151 }
152
153 if (poptPeekArg(optCon) == NULL) {
154 argerror(_("no arguments given"));
155 }
156
157 switch (mode) {
158 case MODE_ADDSIGN:
159 case MODE_RESIGN:
160 ec = doSign(optCon);
161 break;
162 case MODE_DELSIGN:
163 ec = 0;
164 while ((arg = poptGetArg(optCon)) != NULL) {
165 ec += rpmPkgDelSign(arg);
166 }
167 break;
168 default:
169 argerror(_("only one major mode may be specified"));
170 break;
171 }
172
173 exit:
174 rpmcliFini(optCon);
175 return ec;
176 }