Handle config.guess and config.sub with DOS EOLs
[platform/upstream/rpm.git] / rpmsign.c
1 #include "system.h"
2 #include <errno.h>
3 #include <sys/wait.h>
4 #include <termios.h>
5
6 #include <popt.h>
7 #include <rpm/rpmcli.h>
8 #include <rpm/rpmsign.h>
9 #include "cliutils.h"
10 #include "debug.h"
11
12 enum modes {
13     MODE_NONE    = 0,
14     MODE_ADDSIGN = (1 << 0),
15     MODE_RESIGN  = (1 << 1),
16     MODE_DELSIGN = (1 << 2),
17 };
18
19 static int mode = MODE_NONE;
20
21 #ifdef WITH_IMAEVM
22 static int signfiles = 0, fskpass = 0;
23 static char * fileSigningKey = NULL;
24 #endif
25
26 static struct rpmSignArgs sargs = {NULL, 0, 0};
27
28 static struct poptOption signOptsTable[] = {
29     { "addsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_ADDSIGN,
30         N_("sign package(s)"), NULL },
31     { "resign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_RESIGN,
32         N_("sign package(s) (identical to --addsign)"), NULL },
33     { "delsign", '\0', (POPT_ARG_VAL|POPT_ARGFLAG_OR), &mode, MODE_DELSIGN,
34         N_("delete package signatures"), NULL },
35 #ifdef WITH_IMAEVM
36     { "signfiles", '\0', POPT_ARG_NONE, &signfiles, 0,
37         N_("sign package(s) files"), NULL},
38     { "fskpath", '\0', POPT_ARG_STRING, &fileSigningKey, 0,
39         N_("use file signing key <key>"),
40         N_("<key>") },
41     { "fskpass", '\0', POPT_ARG_NONE, &fskpass, 0,
42         N_("prompt for file signing key password"), NULL},
43 #endif
44     POPT_TABLEEND
45 };
46
47 static struct poptOption optionsTable[] = {
48     { NULL, '\0', POPT_ARG_INCLUDE_TABLE, signOptsTable, 0,
49         N_("Signature options:"), NULL },
50     { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmcliAllPoptTable, 0,
51         N_("Common options for all rpm modes and executables:"), NULL },
52
53     POPT_AUTOALIAS
54     POPT_AUTOHELP
55     POPT_TABLEEND
56 };
57
58 #ifdef WITH_IMAEVM
59 static char *get_fskpass(void)
60 {
61     struct termios flags, tmp_flags;
62     int passlen = 64;
63     char *password = xmalloc(passlen);
64     char *pwd = NULL;
65
66     tcgetattr(fileno(stdin), &flags);
67     tmp_flags = flags;
68     tmp_flags.c_lflag &= ~ECHO;
69     tmp_flags.c_lflag |= ECHONL;
70
71     if (tcsetattr(fileno(stdin), TCSANOW, &tmp_flags) != 0) {
72         perror("tcsetattr");
73         goto exit;
74     }
75
76     printf("PEM password: ");
77     pwd = fgets(password, passlen, stdin);
78
79     if (tcsetattr(fileno(stdin), TCSANOW, &flags) != 0) {
80         perror("tcsetattr");
81         pwd = NULL;
82         goto exit;
83     }
84
85 exit:
86     if (pwd)
87         pwd[strlen(pwd) - 1] = '\0';  /* remove newline */
88     else
89         free(password);
90     return pwd;
91 }
92 #endif
93
94 /* TODO: permit overriding macro setup on the command line */
95 static int doSign(poptContext optCon, struct rpmSignArgs *sargs)
96 {
97     int rc = EXIT_FAILURE;
98     char * name = rpmExpand("%{?_gpg_name}", NULL);
99
100     if (rstreq(name, "")) {
101         fprintf(stderr, _("You must set \"%%_gpg_name\" in your macro file\n"));
102         goto exit;
103     }
104
105 #ifdef WITH_IMAEVM
106     if (fileSigningKey) {
107         rpmPushMacro(NULL, "_file_signing_key", NULL, fileSigningKey, RMIL_GLOBAL);
108     }
109
110     if (signfiles) {
111         char *fileSigningKeyPassword = NULL;
112         char *key = rpmExpand("%{?_file_signing_key}", NULL);
113         if (rstreq(key, "")) {
114             fprintf(stderr, _("You must set \"%%_file_signing_key\" in your macro file or on the command line with --fskpath\n"));
115             goto exit;
116         }
117
118         if (fskpass) {
119             fileSigningKeyPassword = get_fskpass();
120         }
121
122         if (fileSigningKeyPassword) {
123             rpmPushMacro(NULL, "_file_signing_key_password", NULL,
124                         fileSigningKeyPassword, RMIL_CMDLINE);
125             memset(fileSigningKeyPassword, 0, strlen(fileSigningKeyPassword));
126             free(fileSigningKeyPassword);
127         }
128
129         sargs->signfiles = 1;
130         free(key);
131     }
132 #endif
133
134     const char *arg;
135     rc = 0;
136     while ((arg = poptGetArg(optCon)) != NULL) {
137         rc += rpmPkgSign(arg, sargs);
138     }
139
140 exit:
141     free(name);
142     return rc;
143 }
144
145 int main(int argc, char *argv[])
146 {
147     int ec = EXIT_FAILURE;
148     poptContext optCon = NULL;
149     const char *arg;
150     
151     xsetprogname(argv[0]); /* Portability call -- see system.h */
152
153     optCon = rpmcliInit(argc, argv, optionsTable);
154
155     if (argc <= 1) {
156         printUsage(optCon, stderr, 0);
157         goto exit;
158     }
159
160     if (poptPeekArg(optCon) == NULL) {
161         argerror(_("no arguments given"));
162     }
163
164 #ifdef WITH_IMAEVM
165     if (fileSigningKey && !signfiles) {
166         argerror(_("--fskpath may only be specified when signing files"));
167     }
168 #endif
169
170     switch (mode) {
171     case MODE_ADDSIGN:
172     case MODE_RESIGN:
173         ec = doSign(optCon, &sargs);
174         break;
175     case MODE_DELSIGN:
176         ec = 0;
177         while ((arg = poptGetArg(optCon)) != NULL) {
178             ec += rpmPkgDelSign(arg, &sargs);
179         }
180         break;
181     case MODE_NONE:
182         printUsage(optCon, stderr, 0);
183         break;
184     default:
185         argerror(_("only one major mode may be specified"));
186         break;
187     }
188
189 exit:
190     rpmcliFini(optCon);
191     return ec;
192 }