rpm  4.11.1-rc1
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 }