Move password repetition from gpg to gpg-agent.
[gnupg.git] / sm / certreqgen-ui.c
blob3dc948f0b1950898145b36fe3f8446e49f321c98
1 /* certreqgen-ui.c - Simple user interface for certreqgen.c
2 * Copyright (C) 2007 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <time.h>
27 #include <assert.h>
29 #include "gpgsm.h"
30 #include <gcrypt.h>
32 #include "i18n.h"
33 #include "ttyio.h"
34 #include "membuf.h"
37 /* Prompt for lines and append them to MB. */
38 static void
39 ask_mb_lines (membuf_t *mb, const char *prefix)
41 char *answer = NULL;
43 do
45 xfree (answer);
46 answer = tty_get ("> ");
47 tty_kill_prompt ();
48 trim_spaces (answer);
49 if (*answer)
51 put_membuf_str (mb, prefix);
52 put_membuf_str (mb, answer);
53 put_membuf (mb, "\n", 1);
56 while (*answer);
57 xfree (answer);
60 /* Helper to store stuff in a membuf. */
61 void
62 store_key_value_lf (membuf_t *mb, const char *key, const char *value)
64 put_membuf_str (mb, key);
65 put_membuf_str (mb, value);
66 put_membuf (mb, "\n", 1);
69 /* Helper tp store a membuf create by mb_ask_lines into MB. Returns
70 -1 on error. */
71 int
72 store_mb_lines (membuf_t *mb, membuf_t *lines)
74 char *p;
76 if (get_membuf_len (lines))
78 put_membuf (lines, "", 1);
79 p = get_membuf (lines, NULL);
80 if (!p)
81 return -1;
82 put_membuf_str (mb, p);
83 xfree (p);
85 return 0;
89 /* This function is used to create a certificate request from the
90 command line. In the past the similar gpgsm-gencert.sh script has
91 been used for it; however that scripts requires a full Unix shell
92 and thus is not suitable for the Windows port. So here is the
93 re-implementation. */
94 void
95 gpgsm_gencertreq_tty (ctrl_t ctrl, FILE *output_fp)
97 gpg_error_t err;
98 char *answer;
99 int selection;
100 estream_t fp = NULL;
101 int method;
102 char *keytype;
103 char *keygrip = NULL;
104 unsigned int nbits;
105 int minbits = 1024;
106 int maxbits = 4096;
107 int defbits = 2048;
108 const char *keyusage;
109 char *subject_name;
110 membuf_t mb_email, mb_dns, mb_uri, mb_result;
111 char *result = NULL;
112 int i;
113 const char *s, *s2;
115 init_membuf (&mb_email, 100);
116 init_membuf (&mb_dns, 100);
117 init_membuf (&mb_uri, 100);
118 init_membuf (&mb_result, 512);
120 /* Get the type of the key. */
121 tty_printf (_("Please select what kind of key you want:\n"));
122 tty_printf (_(" (%d) RSA\n"), 1 );
123 tty_printf (_(" (%d) Existing key\n"), 2 );
124 tty_printf (_(" (%d) Existing key from card\n"), 3 );
128 answer = tty_get (_("Your selection? "));
129 tty_kill_prompt ();
130 selection = *answer? atoi (answer): 1;
131 xfree (answer);
133 while (!(selection >= 1 && selection <= 3));
134 method = selection;
136 /* Get size of the key. */
137 if (method == 1)
139 keytype = xstrdup ("RSA");
140 for (;;)
142 answer = tty_getf (_("What keysize do you want? (%u) "), defbits);
143 tty_kill_prompt ();
144 nbits = *answer? atoi (answer): defbits;
145 xfree (answer);
146 if (nbits < minbits || nbits > maxbits)
147 tty_printf(_("%s keysizes must be in the range %u-%u\n"),
148 "RSA", minbits, maxbits);
149 else
150 break; /* Okay. */
152 tty_printf (_("Requested keysize is %u bits\n"), nbits);
153 /* We round it up so that it better matches the word size. */
154 if (( nbits % 64))
156 nbits = ((nbits + 63) / 64) * 64;
157 tty_printf (_("rounded up to %u bits\n"), nbits);
160 else if (method == 2)
162 tty_printf ("Not yet supported; "
163 "use the gpgsm-gencert.sh script instead\n");
164 keytype = xstrdup ("RSA");
165 nbits = defbits; /* We need a dummy value. */
167 else /* method == 3 */
169 tty_printf ("Not yet supported; "
170 "use the gpgsm-gencert.sh script instead\n");
171 keytype = xstrdup ("card:foobar");
172 nbits = defbits; /* We need a dummy value. */
175 /* Ask for the key usage. */
176 tty_printf (_("Possible actions for a %s key:\n"), "RSA");
177 tty_printf (_(" (%d) sign, encrypt\n"), 1 );
178 tty_printf (_(" (%d) sign\n"), 2 );
179 tty_printf (_(" (%d) encrypt\n"), 3 );
182 answer = tty_get (_("Your selection? "));
183 tty_kill_prompt ();
184 selection = *answer? atoi (answer): 1;
185 xfree (answer);
186 switch (selection)
188 case 1: keyusage = "sign, encrypt"; break;
189 case 2: keyusage = "sign"; break;
190 case 3: keyusage = "encrypt"; break;
191 default: keyusage = NULL; break;
194 while (!keyusage);
196 /* Get the subject name. */
197 answer = NULL;
200 size_t erroff, errlen;
202 xfree (answer);
203 answer = tty_get (_("Enter the X.509 subject name: "));
204 tty_kill_prompt ();
205 trim_spaces (answer);
206 if (!*answer)
207 tty_printf (_("No subject name given\n"));
208 else if ( (err = ksba_dn_teststr (answer, 0, &erroff, &errlen)) )
210 if (gpg_err_code (err) == GPG_ERR_UNKNOWN_NAME)
211 tty_printf (_("Invalid subject name label `%.*s'\n"),
212 (int)errlen, answer+erroff);
213 else
215 /* TRANSLATORS: The 22 in the second string is the
216 length of the first string up to the "%s". Please
217 adjust it do the length of your translation. The
218 second string is merely passed to atoi so you can
219 drop everything after the number. */
220 tty_printf (_("Invalid subject name `%s'\n"), answer);
221 tty_printf ("%*s^\n",
222 atoi (_("22 translator: see "
223 "certreg-ui.c:gpgsm_gencertreq_tty"))
224 + (int)erroff, "");
226 *answer = 0;
229 while (!*answer);
230 subject_name = answer;
231 answer = NULL;
233 /* Get the email addresses. */
234 tty_printf (_("Enter email addresses"));
235 tty_printf (_(" (end with an empty line):\n"));
236 ask_mb_lines (&mb_email, "Name-Email: ");
238 /* DNS names. */
239 tty_printf (_("Enter DNS names"));
240 tty_printf (_(" (optional; end with an empty line):\n"));
241 ask_mb_lines (&mb_email, "Name-DNS: ");
243 /* URIs. */
244 tty_printf (_("Enter URIs"));
245 tty_printf (_(" (optional; end with an empty line):\n"));
246 ask_mb_lines (&mb_email, "Name-URI: ");
249 /* Put it all together. */
250 store_key_value_lf (&mb_result, "Key-Type: ", keytype);
252 char numbuf[30];
253 snprintf (numbuf, sizeof numbuf, "%u", nbits);
254 store_key_value_lf (&mb_result, "Key-Length: ", numbuf);
256 store_key_value_lf (&mb_result, "Key-Usage: ", keyusage);
257 store_key_value_lf (&mb_result, "Name-DN: ", subject_name);
258 if (keygrip)
259 store_key_value_lf (&mb_result, "Key-Grip: ", keygrip);
260 if (store_mb_lines (&mb_result, &mb_email))
261 goto mem_error;
262 if (store_mb_lines (&mb_result, &mb_dns))
263 goto mem_error;
264 if (store_mb_lines (&mb_result, &mb_uri))
265 goto mem_error;
266 put_membuf (&mb_result, "", 1);
267 result = get_membuf (&mb_result, NULL);
268 if (!result)
269 goto mem_error;
271 tty_printf (_("Parameters to be used for the certificate request:\n"));
272 for (s=result; (s2 = strchr (s, '\n')); s = s2+1, i++)
273 tty_printf (" %.*s\n", (int)(s2-s), s);
274 tty_printf ("\n");
277 if (!tty_get_answer_is_yes ("Really create request? (y/N) "))
278 goto leave;
280 /* Now create a parameter file and generate the key. */
281 fp = es_fopenmem (0, "w+");
282 if (!fp)
284 log_error (_("error creating temporary file: %s\n"), strerror (errno));
285 goto leave;
287 es_fputs (result, fp);
288 es_rewind (fp);
289 tty_printf (_("Now creating certificate request. "
290 "This may take a while ...\n"));
292 int save_pem = ctrl->create_pem;
293 ctrl->create_pem = 1; /* Force creation of PEM. */
294 err = gpgsm_genkey (ctrl, fp, output_fp);
295 ctrl->create_pem = save_pem;
297 if (!err)
298 tty_printf (_("Ready. You should now send this request to your CA.\n"));
301 goto leave;
302 mem_error:
303 log_error (_("resource problem: out of core\n"));
304 leave:
305 es_fclose (fp);
306 xfree (keytype);
307 xfree (subject_name);
308 xfree (keygrip);
309 xfree (get_membuf (&mb_email, NULL));
310 xfree (get_membuf (&mb_dns, NULL));
311 xfree (get_membuf (&mb_uri, NULL));
312 xfree (get_membuf (&mb_result, NULL));
313 xfree (result);