Line data Source code
1 : /* card-util.c - Utility functions for the OpenPGP card.
2 : * Copyright (C) 2003-2005, 2009 Free Software Foundation, Inc.
3 : * Copyright (C) 2003-2005, 2009 Werner Koch
4 : *
5 : * This file is part of GnuPG.
6 : *
7 : * GnuPG is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU General Public License as published by
9 : * the Free Software Foundation; either version 3 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * GnuPG is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU General Public License
18 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <config.h>
22 : #include <stdio.h>
23 : #include <stdlib.h>
24 : #include <string.h>
25 : #include <errno.h>
26 : #ifdef HAVE_LIBREADLINE
27 : # define GNUPG_LIBREADLINE_H_INCLUDED
28 : # include <readline/readline.h>
29 : #endif /*HAVE_LIBREADLINE*/
30 :
31 : #if GNUPG_MAJOR_VERSION != 1
32 : # include "gpg.h"
33 : #endif /*GNUPG_MAJOR_VERSION != 1*/
34 : #include "util.h"
35 : #include "i18n.h"
36 : #include "ttyio.h"
37 : #include "status.h"
38 : #include "options.h"
39 : #include "main.h"
40 : #include "keyserver-internal.h"
41 :
42 : #if GNUPG_MAJOR_VERSION == 1
43 : # include "cardglue.h"
44 : #else /*GNUPG_MAJOR_VERSION!=1*/
45 : # include "call-agent.h"
46 : #endif /*GNUPG_MAJOR_VERSION!=1*/
47 :
48 : #define CONTROL_D ('D' - 'A' + 1)
49 :
50 :
51 : static void
52 0 : write_sc_op_status (gpg_error_t err)
53 : {
54 0 : switch (gpg_err_code (err))
55 : {
56 : case 0:
57 0 : write_status (STATUS_SC_OP_SUCCESS);
58 0 : break;
59 : #if GNUPG_MAJOR_VERSION != 1
60 : case GPG_ERR_CANCELED:
61 : case GPG_ERR_FULLY_CANCELED:
62 0 : write_status_text (STATUS_SC_OP_FAILURE, "1");
63 0 : break;
64 : case GPG_ERR_BAD_PIN:
65 0 : write_status_text (STATUS_SC_OP_FAILURE, "2");
66 0 : break;
67 : default:
68 0 : write_status (STATUS_SC_OP_FAILURE);
69 0 : break;
70 : #endif /* GNUPG_MAJOR_VERSION != 1 */
71 : }
72 0 : }
73 :
74 :
75 : /* Change the PIN of a an OpenPGP card. This is an interactive
76 : function. */
77 : void
78 0 : change_pin (int unblock_v2, int allow_admin)
79 : {
80 : struct agent_card_info_s info;
81 : int rc;
82 :
83 0 : rc = agent_scd_learn (&info, 0);
84 0 : if (rc)
85 : {
86 0 : log_error (_("OpenPGP card not available: %s\n"),
87 : gpg_strerror (rc));
88 0 : return;
89 : }
90 :
91 0 : log_info (_("OpenPGP card no. %s detected\n"),
92 0 : info.serialno? info.serialno : "[none]");
93 :
94 0 : agent_clear_pin_cache (info.serialno);
95 :
96 0 : if (opt.batch)
97 : {
98 0 : agent_release_card_info (&info);
99 0 : log_error (_("can't do this in batch mode\n"));
100 0 : return;
101 : }
102 :
103 :
104 0 : if (unblock_v2)
105 : {
106 0 : if (!info.is_v2)
107 0 : log_error (_("This command is only available for version 2 cards\n"));
108 0 : else if (!info.chvretry[1])
109 0 : log_error (_("Reset Code not or not anymore available\n"));
110 : else
111 : {
112 0 : rc = agent_scd_change_pin (2, info.serialno);
113 0 : write_sc_op_status (rc);
114 0 : if (rc)
115 0 : tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
116 : else
117 0 : tty_printf ("PIN changed.\n");
118 : }
119 : }
120 0 : else if (!allow_admin)
121 : {
122 0 : rc = agent_scd_change_pin (1, info.serialno);
123 0 : write_sc_op_status (rc);
124 0 : if (rc)
125 0 : tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
126 : else
127 0 : tty_printf ("PIN changed.\n");
128 : }
129 : else
130 : for (;;)
131 : {
132 : char *answer;
133 :
134 0 : tty_printf ("\n");
135 0 : tty_printf ("1 - change PIN\n"
136 : "2 - unblock PIN\n"
137 : "3 - change Admin PIN\n"
138 : "4 - set the Reset Code\n"
139 : "Q - quit\n");
140 0 : tty_printf ("\n");
141 :
142 0 : answer = cpr_get("cardutil.change_pin.menu",_("Your selection? "));
143 0 : cpr_kill_prompt();
144 0 : if (strlen (answer) != 1)
145 0 : continue;
146 :
147 0 : if (*answer == '1')
148 : {
149 : /* Change PIN. */
150 0 : rc = agent_scd_change_pin (1, info.serialno);
151 0 : write_sc_op_status (rc);
152 0 : if (rc)
153 0 : tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
154 : else
155 0 : tty_printf ("PIN changed.\n");
156 : }
157 0 : else if (*answer == '2')
158 : {
159 : /* Unblock PIN. */
160 0 : rc = agent_scd_change_pin (101, info.serialno);
161 0 : write_sc_op_status (rc);
162 0 : if (rc)
163 0 : tty_printf ("Error unblocking the PIN: %s\n", gpg_strerror (rc));
164 : else
165 0 : tty_printf ("PIN unblocked and new PIN set.\n");
166 : }
167 0 : else if (*answer == '3')
168 : {
169 : /* Change Admin PIN. */
170 0 : rc = agent_scd_change_pin (3, info.serialno);
171 0 : write_sc_op_status (rc);
172 0 : if (rc)
173 0 : tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
174 : else
175 0 : tty_printf ("PIN changed.\n");
176 : }
177 0 : else if (*answer == '4')
178 : {
179 : /* Set a new Reset Code. */
180 0 : rc = agent_scd_change_pin (102, info.serialno);
181 0 : write_sc_op_status (rc);
182 0 : if (rc)
183 0 : tty_printf ("Error setting the Reset Code: %s\n",
184 : gpg_strerror (rc));
185 : else
186 0 : tty_printf ("Reset Code set.\n");
187 : }
188 0 : else if (*answer == 'q' || *answer == 'Q')
189 : {
190 : break;
191 : }
192 0 : }
193 :
194 0 : agent_release_card_info (&info);
195 : }
196 :
197 : static const char *
198 0 : get_manufacturer (unsigned int no)
199 : {
200 : /* Note: Make sure that there is no colon or linefeed in the string. */
201 0 : switch (no)
202 : {
203 0 : case 0x0001: return "PPC Card Systems";
204 0 : case 0x0002: return "Prism";
205 0 : case 0x0003: return "OpenFortress";
206 0 : case 0x0004: return "Wewid";
207 0 : case 0x0005: return "ZeitControl";
208 0 : case 0x0006: return "Yubico";
209 0 : case 0x0007: return "OpenKMS";
210 0 : case 0x0008: return "LogoEmail";
211 0 : case 0x0009: return "Fidesmo";
212 0 : case 0x000A: return "Dangerous Things";
213 :
214 0 : case 0x002A: return "Magrathea";
215 :
216 0 : case 0x1337: return "Warsaw Hackerspace";
217 0 : case 0x2342: return "warpzone"; /* hackerspace Muenster. */
218 0 : case 0xF517: return "FSIJ";
219 :
220 : /* 0x0000 and 0xFFFF are defined as test cards per spec,
221 : 0xFF00 to 0xFFFE are assigned for use with randomly created
222 : serial numbers. */
223 : case 0x0000:
224 0 : case 0xffff: return "test card";
225 0 : default: return (no & 0xff00) == 0xff00? "unmanaged S/N range":"unknown";
226 : }
227 : }
228 :
229 :
230 : static void
231 0 : print_sha1_fpr (estream_t fp, const unsigned char *fpr)
232 : {
233 : int i;
234 :
235 0 : if (fpr)
236 : {
237 0 : for (i=0; i < 20 ; i+=2, fpr += 2 )
238 : {
239 0 : if (i == 10 )
240 0 : tty_fprintf (fp, " ");
241 0 : tty_fprintf (fp, " %02X%02X", *fpr, fpr[1]);
242 : }
243 : }
244 : else
245 0 : tty_fprintf (fp, " [none]");
246 0 : tty_fprintf (fp, "\n");
247 0 : }
248 :
249 :
250 : static void
251 0 : print_sha1_fpr_colon (estream_t fp, const unsigned char *fpr)
252 : {
253 : int i;
254 :
255 0 : if (fpr)
256 : {
257 0 : for (i=0; i < 20 ; i++, fpr++)
258 0 : es_fprintf (fp, "%02X", *fpr);
259 : }
260 0 : es_putc (':', fp);
261 0 : }
262 :
263 :
264 : static void
265 0 : print_name (estream_t fp, const char *text, const char *name)
266 : {
267 0 : tty_fprintf (fp, "%s", text);
268 :
269 : /* FIXME: tty_printf_utf8_string2 eats everything after and
270 : including an @ - e.g. when printing an url. */
271 0 : if (name && *name)
272 : {
273 0 : if (fp)
274 0 : print_utf8_buffer2 (fp, name, strlen (name), '\n');
275 : else
276 0 : tty_print_utf8_string2 (NULL, name, strlen (name), 0);
277 : }
278 : else
279 0 : tty_fprintf (fp, _("[not set]"));
280 0 : tty_fprintf (fp, "\n");
281 0 : }
282 :
283 : static void
284 0 : print_isoname (estream_t fp, const char *text,
285 : const char *tag, const char *name)
286 : {
287 0 : if (opt.with_colons)
288 0 : es_fprintf (fp, "%s:", tag);
289 : else
290 0 : tty_fprintf (fp, "%s", text);
291 :
292 0 : if (name && *name)
293 0 : {
294 0 : char *p, *given, *buf = xstrdup (name);
295 :
296 0 : given = strstr (buf, "<<");
297 0 : for (p=buf; *p; p++)
298 0 : if (*p == '<')
299 0 : *p = ' ';
300 0 : if (given && given[2])
301 : {
302 0 : *given = 0;
303 0 : given += 2;
304 0 : if (opt.with_colons)
305 0 : es_write_sanitized (fp, given, strlen (given), ":", NULL);
306 0 : else if (fp)
307 0 : print_utf8_buffer2 (fp, given, strlen (given), '\n');
308 : else
309 0 : tty_print_utf8_string2 (NULL, given, strlen (given), 0);
310 :
311 0 : if (opt.with_colons)
312 0 : es_putc (':', fp);
313 0 : else if (*buf)
314 0 : tty_fprintf (fp, " ");
315 : }
316 :
317 0 : if (opt.with_colons)
318 0 : es_write_sanitized (fp, buf, strlen (buf), ":", NULL);
319 0 : else if (fp)
320 0 : print_utf8_buffer2 (fp, buf, strlen (buf), '\n');
321 : else
322 0 : tty_print_utf8_string2 (NULL, buf, strlen (buf), 0);
323 0 : xfree (buf);
324 : }
325 : else
326 : {
327 0 : if (opt.with_colons)
328 0 : es_putc (':', fp);
329 : else
330 0 : tty_fprintf (fp, _("[not set]"));
331 : }
332 :
333 0 : if (opt.with_colons)
334 0 : es_fputs (":\n", fp);
335 : else
336 0 : tty_fprintf (fp, "\n");
337 0 : }
338 :
339 : /* Return true if the SHA1 fingerprint FPR consists only of zeroes. */
340 : static int
341 0 : fpr_is_zero (const char *fpr)
342 : {
343 : int i;
344 :
345 0 : for (i=0; i < 20 && !fpr[i]; i++)
346 : ;
347 0 : return (i == 20);
348 : }
349 :
350 :
351 : /* Return true if the SHA1 fingerprint FPR consists only of 0xFF. */
352 : static int
353 0 : fpr_is_ff (const char *fpr)
354 : {
355 : int i;
356 :
357 0 : for (i=0; i < 20 && fpr[i] == '\xff'; i++)
358 : ;
359 0 : return (i == 20);
360 : }
361 :
362 :
363 : /* Print all available information about the current card. */
364 : void
365 0 : card_status (estream_t fp, char *serialno, size_t serialnobuflen)
366 : {
367 : struct agent_card_info_s info;
368 0 : PKT_public_key *pk = xcalloc (1, sizeof *pk);
369 0 : kbnode_t keyblock = NULL;
370 : int rc;
371 : unsigned int uval;
372 : const unsigned char *thefpr;
373 : int i;
374 :
375 0 : if (serialno && serialnobuflen)
376 0 : *serialno = 0;
377 :
378 0 : rc = agent_scd_learn (&info, 0);
379 0 : if (rc)
380 : {
381 0 : if (opt.with_colons)
382 0 : es_fputs ("AID:::\n", fp);
383 0 : log_error (_("OpenPGP card not available: %s\n"), gpg_strerror (rc));
384 0 : xfree (pk);
385 0 : return;
386 : }
387 :
388 0 : if (opt.with_colons)
389 0 : es_fprintf (fp, "Reader:%s:", info.reader? info.reader : "");
390 : else
391 0 : tty_fprintf (fp, "Reader ...........: %s\n",
392 0 : info.reader? info.reader : "[none]");
393 0 : if (opt.with_colons)
394 0 : es_fprintf (fp, "AID:%s:", info.serialno? info.serialno : "");
395 : else
396 0 : tty_fprintf (fp, "Application ID ...: %s\n",
397 0 : info.serialno? info.serialno : "[none]");
398 0 : if (!info.serialno || strncmp (info.serialno, "D27600012401", 12)
399 0 : || strlen (info.serialno) != 32 )
400 : {
401 0 : if (info.apptype && !strcmp (info.apptype, "NKS"))
402 : {
403 0 : if (opt.with_colons)
404 0 : es_fputs ("netkey-card:\n", fp);
405 0 : log_info ("this is a NetKey card\n");
406 : }
407 0 : else if (info.apptype && !strcmp (info.apptype, "DINSIG"))
408 : {
409 0 : if (opt.with_colons)
410 0 : es_fputs ("dinsig-card:\n", fp);
411 0 : log_info ("this is a DINSIG compliant card\n");
412 : }
413 0 : else if (info.apptype && !strcmp (info.apptype, "P15"))
414 : {
415 0 : if (opt.with_colons)
416 0 : es_fputs ("pkcs15-card:\n", fp);
417 0 : log_info ("this is a PKCS#15 compliant card\n");
418 : }
419 0 : else if (info.apptype && !strcmp (info.apptype, "GELDKARTE"))
420 : {
421 0 : if (opt.with_colons)
422 0 : es_fputs ("geldkarte-card:\n", fp);
423 0 : log_info ("this is a Geldkarte compliant card\n");
424 : }
425 : else
426 : {
427 0 : if (opt.with_colons)
428 0 : es_fputs ("unknown:\n", fp);
429 : }
430 0 : log_info ("not an OpenPGP card\n");
431 0 : agent_release_card_info (&info);
432 0 : xfree (pk);
433 0 : return;
434 : }
435 :
436 0 : if (!serialno)
437 : ;
438 0 : else if (strlen (serialno)+1 > serialnobuflen)
439 0 : log_error ("serial number longer than expected\n");
440 : else
441 0 : strcpy (serialno, info.serialno);
442 :
443 0 : if (opt.with_colons)
444 0 : es_fputs ("openpgp-card:\n", fp);
445 :
446 :
447 0 : if (opt.with_colons)
448 : {
449 0 : es_fprintf (fp, "version:%.4s:\n", info.serialno+12);
450 0 : uval = xtoi_2(info.serialno+16)*256 + xtoi_2 (info.serialno+18);
451 0 : es_fprintf (fp, "vendor:%04x:%s:\n", uval, get_manufacturer (uval));
452 0 : es_fprintf (fp, "serial:%.8s:\n", info.serialno+20);
453 :
454 0 : print_isoname (fp, "Name of cardholder: ", "name", info.disp_name);
455 :
456 0 : es_fputs ("lang:", fp);
457 0 : if (info.disp_lang)
458 0 : es_write_sanitized (fp, info.disp_lang, strlen (info.disp_lang),
459 : ":", NULL);
460 0 : es_fputs (":\n", fp);
461 :
462 0 : es_fprintf (fp, "sex:%c:\n", (info.disp_sex == 1? 'm':
463 0 : info.disp_sex == 2? 'f' : 'u'));
464 :
465 0 : es_fputs ("url:", fp);
466 0 : if (info.pubkey_url)
467 0 : es_write_sanitized (fp, info.pubkey_url, strlen (info.pubkey_url),
468 : ":", NULL);
469 0 : es_fputs (":\n", fp);
470 :
471 0 : es_fputs ("login:", fp);
472 0 : if (info.login_data)
473 0 : es_write_sanitized (fp, info.login_data, strlen (info.login_data),
474 : ":", NULL);
475 0 : es_fputs (":\n", fp);
476 :
477 0 : es_fprintf (fp, "forcepin:%d:::\n", !info.chv1_cached);
478 0 : for (i=0; i < DIM (info.key_attr); i++)
479 0 : if (info.key_attr[0].algo == PUBKEY_ALGO_RSA)
480 0 : es_fprintf (fp, "keyattr:%d:%d:%u:\n", i+1,
481 : info.key_attr[i].algo, info.key_attr[i].nbits);
482 0 : else if (info.key_attr[i].algo == PUBKEY_ALGO_ECDH
483 0 : || info.key_attr[i].algo == PUBKEY_ALGO_ECDSA
484 0 : || info.key_attr[i].algo == PUBKEY_ALGO_EDDSA)
485 0 : es_fprintf (fp, "keyattr:%d:%d:%s:\n", i+1,
486 : info.key_attr[i].algo, info.key_attr[i].curve);
487 0 : es_fprintf (fp, "maxpinlen:%d:%d:%d:\n",
488 : info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]);
489 0 : es_fprintf (fp, "pinretry:%d:%d:%d:\n",
490 : info.chvretry[0], info.chvretry[1], info.chvretry[2]);
491 0 : es_fprintf (fp, "sigcount:%lu:::\n", info.sig_counter);
492 :
493 0 : for (i=0; i < 4; i++)
494 : {
495 0 : if (info.private_do[i])
496 : {
497 0 : es_fprintf (fp, "private_do:%d:", i+1);
498 0 : es_write_sanitized (fp, info.private_do[i],
499 0 : strlen (info.private_do[i]), ":", NULL);
500 0 : es_fputs (":\n", fp);
501 : }
502 : }
503 :
504 0 : es_fputs ("cafpr:", fp);
505 0 : print_sha1_fpr_colon (fp, info.cafpr1valid? info.cafpr1:NULL);
506 0 : print_sha1_fpr_colon (fp, info.cafpr2valid? info.cafpr2:NULL);
507 0 : print_sha1_fpr_colon (fp, info.cafpr3valid? info.cafpr3:NULL);
508 0 : es_putc ('\n', fp);
509 0 : es_fputs ("fpr:", fp);
510 0 : print_sha1_fpr_colon (fp, info.fpr1valid? info.fpr1:NULL);
511 0 : print_sha1_fpr_colon (fp, info.fpr2valid? info.fpr2:NULL);
512 0 : print_sha1_fpr_colon (fp, info.fpr3valid? info.fpr3:NULL);
513 0 : es_putc ('\n', fp);
514 0 : es_fprintf (fp, "fprtime:%lu:%lu:%lu:\n",
515 0 : (unsigned long)info.fpr1time, (unsigned long)info.fpr2time,
516 0 : (unsigned long)info.fpr3time);
517 : }
518 : else
519 : {
520 0 : tty_fprintf (fp, "Version ..........: %.1s%c.%.1s%c\n",
521 0 : info.serialno[12] == '0'?"":info.serialno+12,
522 0 : info.serialno[13],
523 0 : info.serialno[14] == '0'?"":info.serialno+14,
524 0 : info.serialno[15]);
525 0 : tty_fprintf (fp, "Manufacturer .....: %s\n",
526 0 : get_manufacturer (xtoi_2(info.serialno+16)*256
527 0 : + xtoi_2 (info.serialno+18)));
528 0 : tty_fprintf (fp, "Serial number ....: %.8s\n", info.serialno+20);
529 :
530 0 : print_isoname (fp, "Name of cardholder: ", "name", info.disp_name);
531 0 : print_name (fp, "Language prefs ...: ", info.disp_lang);
532 0 : tty_fprintf (fp, "Sex ..............: %s\n",
533 0 : info.disp_sex == 1? _("male"):
534 0 : info.disp_sex == 2? _("female") : _("unspecified"));
535 0 : print_name (fp, "URL of public key : ", info.pubkey_url);
536 0 : print_name (fp, "Login data .......: ", info.login_data);
537 0 : if (info.private_do[0])
538 0 : print_name (fp, "Private DO 1 .....: ", info.private_do[0]);
539 0 : if (info.private_do[1])
540 0 : print_name (fp, "Private DO 2 .....: ", info.private_do[1]);
541 0 : if (info.private_do[2])
542 0 : print_name (fp, "Private DO 3 .....: ", info.private_do[2]);
543 0 : if (info.private_do[3])
544 0 : print_name (fp, "Private DO 4 .....: ", info.private_do[3]);
545 0 : if (info.cafpr1valid)
546 : {
547 0 : tty_fprintf (fp, "CA fingerprint %d .:", 1);
548 0 : print_sha1_fpr (fp, info.cafpr1);
549 : }
550 0 : if (info.cafpr2valid)
551 : {
552 0 : tty_fprintf (fp, "CA fingerprint %d .:", 2);
553 0 : print_sha1_fpr (fp, info.cafpr2);
554 : }
555 0 : if (info.cafpr3valid)
556 : {
557 0 : tty_fprintf (fp, "CA fingerprint %d .:", 3);
558 0 : print_sha1_fpr (fp, info.cafpr3);
559 : }
560 0 : tty_fprintf (fp, "Signature PIN ....: %s\n",
561 0 : info.chv1_cached? _("not forced"): _("forced"));
562 0 : if (info.key_attr[0].algo)
563 : {
564 0 : tty_fprintf (fp, "Key attributes ...:");
565 0 : for (i=0; i < DIM (info.key_attr); i++)
566 0 : if (info.key_attr[i].algo == PUBKEY_ALGO_RSA)
567 0 : tty_fprintf (fp, " rsa%u", info.key_attr[i].nbits);
568 0 : else if (info.key_attr[i].algo == PUBKEY_ALGO_ECDH
569 0 : || info.key_attr[i].algo == PUBKEY_ALGO_ECDSA
570 0 : || info.key_attr[i].algo == PUBKEY_ALGO_EDDSA)
571 0 : tty_fprintf (fp, " %s", info.key_attr[i].curve);
572 0 : tty_fprintf (fp, "\n");
573 : }
574 0 : tty_fprintf (fp, "Max. PIN lengths .: %d %d %d\n",
575 : info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]);
576 0 : tty_fprintf (fp, "PIN retry counter : %d %d %d\n",
577 : info.chvretry[0], info.chvretry[1], info.chvretry[2]);
578 0 : tty_fprintf (fp, "Signature counter : %lu\n", info.sig_counter);
579 0 : tty_fprintf (fp, "Signature key ....:");
580 0 : print_sha1_fpr (fp, info.fpr1valid? info.fpr1:NULL);
581 0 : if (info.fpr1valid && info.fpr1time)
582 0 : tty_fprintf (fp, " created ....: %s\n",
583 : isotimestamp (info.fpr1time));
584 0 : tty_fprintf (fp, "Encryption key....:");
585 0 : print_sha1_fpr (fp, info.fpr2valid? info.fpr2:NULL);
586 0 : if (info.fpr2valid && info.fpr2time)
587 0 : tty_fprintf (fp, " created ....: %s\n",
588 : isotimestamp (info.fpr2time));
589 0 : tty_fprintf (fp, "Authentication key:");
590 0 : print_sha1_fpr (fp, info.fpr3valid? info.fpr3:NULL);
591 0 : if (info.fpr3valid && info.fpr3time)
592 0 : tty_fprintf (fp, " created ....: %s\n",
593 : isotimestamp (info.fpr3time));
594 0 : tty_fprintf (fp, "General key info..: ");
595 :
596 0 : thefpr = (info.fpr1valid? info.fpr1 : info.fpr2valid? info.fpr2 :
597 0 : info.fpr3valid? info.fpr3 : NULL);
598 : /* If the fingerprint is all 0xff, the key has no asssociated
599 : OpenPGP certificate. */
600 0 : if ( thefpr && !fpr_is_ff (thefpr)
601 0 : && !get_pubkey_byfprint (pk, &keyblock, thefpr, 20))
602 : {
603 0 : print_pubkey_info (fp, pk);
604 0 : if (keyblock)
605 0 : print_card_key_info (fp, keyblock);
606 : }
607 : else
608 0 : tty_fprintf (fp, "[none]\n");
609 : }
610 :
611 0 : release_kbnode (keyblock);
612 0 : free_public_key (pk);
613 0 : agent_release_card_info (&info);
614 : }
615 :
616 :
617 : static char *
618 0 : get_one_name (const char *prompt1, const char *prompt2)
619 : {
620 : char *name;
621 : int i;
622 :
623 : for (;;)
624 : {
625 0 : name = cpr_get (prompt1, prompt2);
626 0 : if (!name)
627 0 : return NULL;
628 0 : trim_spaces (name);
629 0 : cpr_kill_prompt ();
630 0 : for (i=0; name[i] && name[i] >= ' ' && name[i] <= 126; i++)
631 : ;
632 :
633 : /* The name must be in Latin-1 and not UTF-8 - lacking the code
634 : to ensure this we restrict it to ASCII. */
635 0 : if (name[i])
636 0 : tty_printf (_("Error: Only plain ASCII is currently allowed.\n"));
637 0 : else if (strchr (name, '<'))
638 0 : tty_printf (_("Error: The \"<\" character may not be used.\n"));
639 0 : else if (strstr (name, " "))
640 0 : tty_printf (_("Error: Double spaces are not allowed.\n"));
641 : else
642 0 : return name;
643 0 : xfree (name);
644 0 : }
645 : }
646 :
647 :
648 :
649 : static int
650 0 : change_name (void)
651 : {
652 0 : char *surname = NULL, *givenname = NULL;
653 : char *isoname, *p;
654 : int rc;
655 :
656 0 : surname = get_one_name ("keygen.smartcard.surname",
657 0 : _("Cardholder's surname: "));
658 0 : givenname = get_one_name ("keygen.smartcard.givenname",
659 0 : _("Cardholder's given name: "));
660 0 : if (!surname || !givenname || (!*surname && !*givenname))
661 : {
662 0 : xfree (surname);
663 0 : xfree (givenname);
664 0 : return -1; /*canceled*/
665 : }
666 :
667 0 : isoname = xmalloc ( strlen (surname) + 2 + strlen (givenname) + 1);
668 0 : strcpy (stpcpy (stpcpy (isoname, surname), "<<"), givenname);
669 0 : xfree (surname);
670 0 : xfree (givenname);
671 0 : for (p=isoname; *p; p++)
672 0 : if (*p == ' ')
673 0 : *p = '<';
674 :
675 0 : if (strlen (isoname) > 39 )
676 : {
677 0 : tty_printf (_("Error: Combined name too long "
678 : "(limit is %d characters).\n"), 39);
679 0 : xfree (isoname);
680 0 : return -1;
681 : }
682 :
683 0 : rc = agent_scd_setattr ("DISP-NAME", isoname, strlen (isoname), NULL );
684 0 : if (rc)
685 0 : log_error ("error setting Name: %s\n", gpg_strerror (rc));
686 :
687 0 : xfree (isoname);
688 0 : return rc;
689 : }
690 :
691 :
692 : static int
693 0 : change_url (void)
694 : {
695 : char *url;
696 : int rc;
697 :
698 0 : url = cpr_get ("cardedit.change_url", _("URL to retrieve public key: "));
699 0 : if (!url)
700 0 : return -1;
701 0 : trim_spaces (url);
702 0 : cpr_kill_prompt ();
703 :
704 0 : if (strlen (url) > 254 )
705 : {
706 0 : tty_printf (_("Error: URL too long "
707 : "(limit is %d characters).\n"), 254);
708 0 : xfree (url);
709 0 : return -1;
710 : }
711 :
712 0 : rc = agent_scd_setattr ("PUBKEY-URL", url, strlen (url), NULL );
713 0 : if (rc)
714 0 : log_error ("error setting URL: %s\n", gpg_strerror (rc));
715 0 : xfree (url);
716 0 : write_sc_op_status (rc);
717 0 : return rc;
718 : }
719 :
720 :
721 : /* Fetch the key from the URL given on the card or try to get it from
722 : the default keyserver. */
723 : static int
724 0 : fetch_url (ctrl_t ctrl)
725 : {
726 : int rc;
727 : struct agent_card_info_s info;
728 :
729 0 : memset(&info,0,sizeof(info));
730 :
731 0 : rc=agent_scd_getattr("PUBKEY-URL",&info);
732 0 : if(rc)
733 0 : log_error("error retrieving URL from card: %s\n",gpg_strerror(rc));
734 : else
735 : {
736 0 : rc=agent_scd_getattr("KEY-FPR",&info);
737 0 : if(rc)
738 0 : log_error("error retrieving key fingerprint from card: %s\n",
739 : gpg_strerror(rc));
740 0 : else if (info.pubkey_url && *info.pubkey_url)
741 0 : {
742 0 : strlist_t sl = NULL;
743 :
744 0 : add_to_strlist (&sl, info.pubkey_url);
745 0 : rc = keyserver_fetch (ctrl, sl);
746 0 : free_strlist (sl);
747 : }
748 0 : else if (info.fpr1valid)
749 : {
750 0 : rc = keyserver_import_fprint (ctrl, info.fpr1, 20, opt.keyserver);
751 : }
752 : }
753 :
754 0 : return rc;
755 : }
756 :
757 :
758 : /* Read data from file FNAME up to MAXLEN characters. On error return
759 : -1 and store NULL at R_BUFFER; on success return the number of
760 : bytes read and store the address of a newly allocated buffer at
761 : R_BUFFER. */
762 : static int
763 0 : get_data_from_file (const char *fname, size_t maxlen, char **r_buffer)
764 : {
765 : estream_t fp;
766 : char *data;
767 : int n;
768 :
769 0 : *r_buffer = NULL;
770 :
771 0 : fp = es_fopen (fname, "rb");
772 : #if GNUPG_MAJOR_VERSION == 1
773 : if (fp && is_secured_file (fileno (fp)))
774 : {
775 : fclose (fp);
776 : fp = NULL;
777 : errno = EPERM;
778 : }
779 : #endif
780 0 : if (!fp)
781 : {
782 0 : tty_printf (_("can't open '%s': %s\n"), fname, strerror (errno));
783 0 : return -1;
784 : }
785 :
786 0 : data = xtrymalloc (maxlen? maxlen:1);
787 0 : if (!data)
788 : {
789 0 : tty_printf (_("error allocating enough memory: %s\n"), strerror (errno));
790 0 : es_fclose (fp);
791 0 : return -1;
792 : }
793 :
794 0 : if (maxlen)
795 0 : n = es_fread (data, 1, maxlen, fp);
796 : else
797 0 : n = 0;
798 0 : es_fclose (fp);
799 0 : if (n < 0)
800 : {
801 0 : tty_printf (_("error reading '%s': %s\n"), fname, strerror (errno));
802 0 : xfree (data);
803 0 : return -1;
804 : }
805 0 : *r_buffer = data;
806 0 : return n;
807 : }
808 :
809 :
810 : /* Write LENGTH bytes from BUFFER to file FNAME. Return 0 on
811 : success. */
812 : static int
813 0 : put_data_to_file (const char *fname, const void *buffer, size_t length)
814 : {
815 : estream_t fp;
816 :
817 0 : fp = es_fopen (fname, "wb");
818 : #if GNUPG_MAJOR_VERSION == 1
819 : if (fp && is_secured_file (fileno (fp)))
820 : {
821 : fclose (fp);
822 : fp = NULL;
823 : errno = EPERM;
824 : }
825 : #endif
826 0 : if (!fp)
827 : {
828 0 : tty_printf (_("can't create '%s': %s\n"), fname, strerror (errno));
829 0 : return -1;
830 : }
831 :
832 0 : if (length && es_fwrite (buffer, length, 1, fp) != 1)
833 : {
834 0 : tty_printf (_("error writing '%s': %s\n"), fname, strerror (errno));
835 0 : es_fclose (fp);
836 0 : return -1;
837 : }
838 0 : es_fclose (fp);
839 0 : return 0;
840 : }
841 :
842 :
843 : static int
844 0 : change_login (const char *args)
845 : {
846 : char *data;
847 : int n;
848 : int rc;
849 :
850 0 : if (args && *args == '<') /* Read it from a file */
851 : {
852 0 : for (args++; spacep (args); args++)
853 : ;
854 0 : n = get_data_from_file (args, 254, &data);
855 0 : if (n < 0)
856 0 : return -1;
857 : }
858 : else
859 : {
860 0 : data = cpr_get ("cardedit.change_login",
861 0 : _("Login data (account name): "));
862 0 : if (!data)
863 0 : return -1;
864 0 : trim_spaces (data);
865 0 : cpr_kill_prompt ();
866 0 : n = strlen (data);
867 : }
868 :
869 0 : if (n > 254 )
870 : {
871 0 : tty_printf (_("Error: Login data too long "
872 : "(limit is %d characters).\n"), 254);
873 0 : xfree (data);
874 0 : return -1;
875 : }
876 :
877 0 : rc = agent_scd_setattr ("LOGIN-DATA", data, n, NULL );
878 0 : if (rc)
879 0 : log_error ("error setting login data: %s\n", gpg_strerror (rc));
880 0 : xfree (data);
881 0 : write_sc_op_status (rc);
882 0 : return rc;
883 : }
884 :
885 : static int
886 0 : change_private_do (const char *args, int nr)
887 : {
888 0 : char do_name[] = "PRIVATE-DO-X";
889 : char *data;
890 : int n;
891 : int rc;
892 :
893 0 : log_assert (nr >= 1 && nr <= 4);
894 0 : do_name[11] = '0' + nr;
895 :
896 0 : if (args && (args = strchr (args, '<'))) /* Read it from a file */
897 : {
898 0 : for (args++; spacep (args); args++)
899 : ;
900 0 : n = get_data_from_file (args, 254, &data);
901 0 : if (n < 0)
902 0 : return -1;
903 : }
904 : else
905 : {
906 0 : data = cpr_get ("cardedit.change_private_do",
907 0 : _("Private DO data: "));
908 0 : if (!data)
909 0 : return -1;
910 0 : trim_spaces (data);
911 0 : cpr_kill_prompt ();
912 0 : n = strlen (data);
913 : }
914 :
915 0 : if (n > 254 )
916 : {
917 0 : tty_printf (_("Error: Private DO too long "
918 : "(limit is %d characters).\n"), 254);
919 0 : xfree (data);
920 0 : return -1;
921 : }
922 :
923 0 : rc = agent_scd_setattr (do_name, data, n, NULL );
924 0 : if (rc)
925 0 : log_error ("error setting private DO: %s\n", gpg_strerror (rc));
926 0 : xfree (data);
927 0 : write_sc_op_status (rc);
928 0 : return rc;
929 : }
930 :
931 :
932 : static int
933 0 : change_cert (const char *args)
934 : {
935 : char *data;
936 : int n;
937 : int rc;
938 :
939 0 : if (args && *args == '<') /* Read it from a file */
940 : {
941 0 : for (args++; spacep (args); args++)
942 : ;
943 0 : n = get_data_from_file (args, 16384, &data);
944 0 : if (n < 0)
945 0 : return -1;
946 : }
947 : else
948 : {
949 0 : tty_printf ("usage error: redirection to file required\n");
950 0 : return -1;
951 : }
952 :
953 0 : rc = agent_scd_writecert ("OPENPGP.3", data, n);
954 0 : if (rc)
955 0 : log_error ("error writing certificate to card: %s\n", gpg_strerror (rc));
956 0 : xfree (data);
957 0 : write_sc_op_status (rc);
958 0 : return rc;
959 : }
960 :
961 :
962 : static int
963 0 : read_cert (const char *args)
964 : {
965 : const char *fname;
966 : void *buffer;
967 : size_t length;
968 : int rc;
969 :
970 0 : if (args && *args == '>') /* Write it to a file */
971 : {
972 0 : for (args++; spacep (args); args++)
973 : ;
974 0 : fname = args;
975 : }
976 : else
977 : {
978 0 : tty_printf ("usage error: redirection to file required\n");
979 0 : return -1;
980 : }
981 :
982 0 : rc = agent_scd_readcert ("OPENPGP.3", &buffer, &length);
983 0 : if (rc)
984 0 : log_error ("error reading certificate from card: %s\n", gpg_strerror (rc));
985 : else
986 0 : rc = put_data_to_file (fname, buffer, length);
987 0 : xfree (buffer);
988 0 : write_sc_op_status (rc);
989 0 : return rc;
990 : }
991 :
992 :
993 : static int
994 0 : change_lang (void)
995 : {
996 : char *data, *p;
997 : int rc;
998 :
999 0 : data = cpr_get ("cardedit.change_lang",
1000 0 : _("Language preferences: "));
1001 0 : if (!data)
1002 0 : return -1;
1003 0 : trim_spaces (data);
1004 0 : cpr_kill_prompt ();
1005 :
1006 0 : if (strlen (data) > 8 || (strlen (data) & 1))
1007 : {
1008 0 : tty_printf (_("Error: invalid length of preference string.\n"));
1009 0 : xfree (data);
1010 0 : return -1;
1011 : }
1012 :
1013 0 : for (p=data; *p && *p >= 'a' && *p <= 'z'; p++)
1014 : ;
1015 0 : if (*p)
1016 : {
1017 0 : tty_printf (_("Error: invalid characters in preference string.\n"));
1018 0 : xfree (data);
1019 0 : return -1;
1020 : }
1021 :
1022 0 : rc = agent_scd_setattr ("DISP-LANG", data, strlen (data), NULL );
1023 0 : if (rc)
1024 0 : log_error ("error setting lang: %s\n", gpg_strerror (rc));
1025 0 : xfree (data);
1026 0 : write_sc_op_status (rc);
1027 0 : return rc;
1028 : }
1029 :
1030 :
1031 : static int
1032 0 : change_sex (void)
1033 : {
1034 : char *data;
1035 : const char *str;
1036 : int rc;
1037 :
1038 0 : data = cpr_get ("cardedit.change_sex",
1039 0 : _("Sex ((M)ale, (F)emale or space): "));
1040 0 : if (!data)
1041 0 : return -1;
1042 0 : trim_spaces (data);
1043 0 : cpr_kill_prompt ();
1044 :
1045 0 : if (!*data)
1046 0 : str = "9";
1047 0 : else if ((*data == 'M' || *data == 'm') && !data[1])
1048 0 : str = "1";
1049 0 : else if ((*data == 'F' || *data == 'f') && !data[1])
1050 0 : str = "2";
1051 : else
1052 : {
1053 0 : tty_printf (_("Error: invalid response.\n"));
1054 0 : xfree (data);
1055 0 : return -1;
1056 : }
1057 :
1058 0 : rc = agent_scd_setattr ("DISP-SEX", str, 1, NULL );
1059 0 : if (rc)
1060 0 : log_error ("error setting sex: %s\n", gpg_strerror (rc));
1061 0 : xfree (data);
1062 0 : write_sc_op_status (rc);
1063 0 : return rc;
1064 : }
1065 :
1066 :
1067 : static int
1068 0 : change_cafpr (int fprno)
1069 : {
1070 : char *data;
1071 : const char *s;
1072 : int i, c, rc;
1073 : unsigned char fpr[20];
1074 :
1075 0 : data = cpr_get ("cardedit.change_cafpr", _("CA fingerprint: "));
1076 0 : if (!data)
1077 0 : return -1;
1078 0 : trim_spaces (data);
1079 0 : cpr_kill_prompt ();
1080 :
1081 0 : for (i=0, s=data; i < 20 && *s; )
1082 : {
1083 0 : while (spacep(s))
1084 0 : s++;
1085 0 : if (*s == ':')
1086 0 : s++;
1087 0 : while (spacep(s))
1088 0 : s++;
1089 0 : c = hextobyte (s);
1090 0 : if (c == -1)
1091 0 : break;
1092 0 : fpr[i++] = c;
1093 0 : s += 2;
1094 : }
1095 0 : xfree (data);
1096 0 : if (i != 20 || *s)
1097 : {
1098 0 : tty_printf (_("Error: invalid formatted fingerprint.\n"));
1099 0 : return -1;
1100 : }
1101 :
1102 0 : rc = agent_scd_setattr (fprno==1?"CA-FPR-1":
1103 : fprno==2?"CA-FPR-2":
1104 : fprno==3?"CA-FPR-3":"x", fpr, 20, NULL );
1105 0 : if (rc)
1106 0 : log_error ("error setting cafpr: %s\n", gpg_strerror (rc));
1107 0 : write_sc_op_status (rc);
1108 0 : return rc;
1109 : }
1110 :
1111 :
1112 :
1113 : static void
1114 0 : toggle_forcesig (void)
1115 : {
1116 : struct agent_card_info_s info;
1117 : int rc;
1118 : int newstate;
1119 :
1120 0 : memset (&info, 0, sizeof info);
1121 0 : rc = agent_scd_getattr ("CHV-STATUS", &info);
1122 0 : if (rc)
1123 : {
1124 0 : log_error ("error getting current status: %s\n", gpg_strerror (rc));
1125 0 : return;
1126 : }
1127 0 : newstate = !info.chv1_cached;
1128 0 : agent_release_card_info (&info);
1129 :
1130 0 : rc = agent_scd_setattr ("CHV-STATUS-1", newstate? "\x01":"", 1, NULL);
1131 0 : if (rc)
1132 0 : log_error ("error toggling signature PIN flag: %s\n", gpg_strerror (rc));
1133 0 : write_sc_op_status (rc);
1134 : }
1135 :
1136 :
1137 : /* Helper for the key generation/edit functions. */
1138 : static int
1139 0 : get_info_for_key_operation (struct agent_card_info_s *info)
1140 : {
1141 : int rc;
1142 :
1143 0 : memset (info, 0, sizeof *info);
1144 0 : rc = agent_scd_getattr ("SERIALNO", info);
1145 0 : if (rc || !info->serialno || strncmp (info->serialno, "D27600012401", 12)
1146 0 : || strlen (info->serialno) != 32 )
1147 : {
1148 0 : log_error (_("key operation not possible: %s\n"),
1149 0 : rc ? gpg_strerror (rc) : _("not an OpenPGP card"));
1150 0 : return rc? rc: -1;
1151 : }
1152 0 : rc = agent_scd_getattr ("KEY-FPR", info);
1153 0 : if (!rc)
1154 0 : rc = agent_scd_getattr ("CHV-STATUS", info);
1155 0 : if (!rc)
1156 0 : rc = agent_scd_getattr ("DISP-NAME", info);
1157 0 : if (!rc)
1158 0 : rc = agent_scd_getattr ("EXTCAP", info);
1159 0 : if (!rc)
1160 0 : rc = agent_scd_getattr ("KEY-ATTR", info);
1161 0 : if (rc)
1162 0 : log_error (_("error getting current key info: %s\n"), gpg_strerror (rc));
1163 0 : return rc;
1164 : }
1165 :
1166 :
1167 : /* Helper for the key generation/edit functions. */
1168 : static int
1169 0 : check_pin_for_key_operation (struct agent_card_info_s *info, int *forced_chv1)
1170 : {
1171 0 : int rc = 0;
1172 :
1173 0 : agent_clear_pin_cache (info->serialno);
1174 :
1175 0 : *forced_chv1 = !info->chv1_cached;
1176 0 : if (*forced_chv1)
1177 : { /* Switch off the forced mode so that during key generation we
1178 : don't get bothered with PIN queries for each
1179 : self-signature. */
1180 0 : rc = agent_scd_setattr ("CHV-STATUS-1", "\x01", 1, info->serialno);
1181 0 : if (rc)
1182 : {
1183 0 : log_error ("error clearing forced signature PIN flag: %s\n",
1184 : gpg_strerror (rc));
1185 0 : *forced_chv1 = 0;
1186 : }
1187 : }
1188 :
1189 0 : if (!rc)
1190 : {
1191 : /* Check the PIN now, so that we won't get asked later for each
1192 : binding signature. */
1193 0 : rc = agent_scd_checkpin (info->serialno);
1194 0 : if (rc)
1195 : {
1196 0 : log_error ("error checking the PIN: %s\n", gpg_strerror (rc));
1197 0 : write_sc_op_status (rc);
1198 : }
1199 : }
1200 0 : return rc;
1201 : }
1202 :
1203 : /* Helper for the key generation/edit functions. */
1204 : static void
1205 0 : restore_forced_chv1 (int *forced_chv1)
1206 : {
1207 : int rc;
1208 :
1209 0 : if (*forced_chv1)
1210 : { /* Switch back to forced state. */
1211 0 : rc = agent_scd_setattr ("CHV-STATUS-1", "", 1, NULL);
1212 0 : if (rc)
1213 : {
1214 0 : log_error ("error setting forced signature PIN flag: %s\n",
1215 : gpg_strerror (rc));
1216 : }
1217 : }
1218 0 : }
1219 :
1220 :
1221 : /* Helper for the key generation/edit functions. */
1222 : static void
1223 0 : show_card_key_info (struct agent_card_info_s *info)
1224 : {
1225 0 : tty_fprintf (NULL, "Signature key ....:");
1226 0 : print_sha1_fpr (NULL, info->fpr1valid? info->fpr1:NULL);
1227 0 : tty_fprintf (NULL, "Encryption key....:");
1228 0 : print_sha1_fpr (NULL, info->fpr2valid? info->fpr2:NULL);
1229 0 : tty_fprintf (NULL, "Authentication key:");
1230 0 : print_sha1_fpr (NULL, info->fpr3valid? info->fpr3:NULL);
1231 0 : tty_printf ("\n");
1232 0 : }
1233 :
1234 :
1235 : /* Helper for the key generation/edit functions. */
1236 : static int
1237 0 : replace_existing_key_p (struct agent_card_info_s *info, int keyno)
1238 : {
1239 0 : log_assert (keyno >= 0 && keyno <= 3);
1240 :
1241 0 : if ((keyno == 1 && info->fpr1valid)
1242 0 : || (keyno == 2 && info->fpr2valid)
1243 0 : || (keyno == 3 && info->fpr3valid))
1244 : {
1245 0 : tty_printf ("\n");
1246 0 : log_info ("WARNING: such a key has already been stored on the card!\n");
1247 0 : tty_printf ("\n");
1248 0 : if ( !cpr_get_answer_is_yes( "cardedit.genkeys.replace_key",
1249 0 : _("Replace existing key? (y/N) ")))
1250 0 : return -1;
1251 0 : return 1;
1252 : }
1253 0 : return 0;
1254 : }
1255 :
1256 :
1257 : static void
1258 0 : show_keysize_warning (void)
1259 : {
1260 : static int shown;
1261 :
1262 0 : if (shown)
1263 0 : return;
1264 0 : shown = 1;
1265 0 : tty_printf
1266 0 : (_("Note: There is no guarantee that the card "
1267 : "supports the requested size.\n"
1268 : " If the key generation does not succeed, "
1269 : "please check the\n"
1270 : " documentation of your card to see what "
1271 : "sizes are allowed.\n"));
1272 : }
1273 :
1274 :
1275 : /* Ask for the size of a card key. NBITS is the current size
1276 : configured for the card. KEYNO is the number of the key used to
1277 : select the prompt. Returns 0 to use the default size (i.e. NBITS)
1278 : or the selected size. */
1279 : static unsigned int
1280 0 : ask_card_keysize (int keyno, unsigned int nbits)
1281 : {
1282 0 : unsigned int min_nbits = 1024;
1283 0 : unsigned int max_nbits = 4096;
1284 : char *prompt, *answer;
1285 : unsigned int req_nbits;
1286 :
1287 : for (;;)
1288 : {
1289 0 : prompt = xasprintf
1290 : (keyno == 0?
1291 : _("What keysize do you want for the Signature key? (%u) "):
1292 : keyno == 1?
1293 : _("What keysize do you want for the Encryption key? (%u) "):
1294 : _("What keysize do you want for the Authentication key? (%u) "),
1295 : nbits);
1296 0 : answer = cpr_get ("cardedit.genkeys.size", prompt);
1297 0 : cpr_kill_prompt ();
1298 0 : req_nbits = *answer? atoi (answer): nbits;
1299 0 : xfree (prompt);
1300 0 : xfree (answer);
1301 :
1302 0 : if (req_nbits != nbits && (req_nbits % 32) )
1303 : {
1304 0 : req_nbits = ((req_nbits + 31) / 32) * 32;
1305 0 : tty_printf (_("rounded up to %u bits\n"), req_nbits);
1306 : }
1307 :
1308 0 : if (req_nbits == nbits)
1309 0 : return 0; /* Use default. */
1310 :
1311 0 : if (req_nbits < min_nbits || req_nbits > max_nbits)
1312 : {
1313 0 : tty_printf (_("%s keysizes must be in the range %u-%u\n"),
1314 : "RSA", min_nbits, max_nbits);
1315 : }
1316 : else
1317 : {
1318 0 : tty_printf (_("The card will now be re-configured "
1319 : "to generate a key of %u bits\n"), req_nbits);
1320 0 : show_keysize_warning ();
1321 0 : return req_nbits;
1322 : }
1323 0 : }
1324 : }
1325 :
1326 :
1327 : /* Change the size of key KEYNO (0..2) to NBITS and show an error
1328 : message if that fails. */
1329 : static gpg_error_t
1330 0 : do_change_keysize (int keyno, unsigned int nbits)
1331 : {
1332 : gpg_error_t err;
1333 : char args[100];
1334 :
1335 0 : snprintf (args, sizeof args, "--force %d 1 rsa%u", keyno+1, nbits);
1336 0 : err = agent_scd_setattr ("KEY-ATTR", args, strlen (args), NULL);
1337 0 : if (err)
1338 0 : log_error (_("error changing size of key %d to %u bits: %s\n"),
1339 : keyno+1, nbits, gpg_strerror (err));
1340 0 : return err;
1341 : }
1342 :
1343 :
1344 : static void
1345 0 : generate_card_keys (ctrl_t ctrl)
1346 : {
1347 : struct agent_card_info_s info;
1348 : int forced_chv1;
1349 : int want_backup;
1350 : int keyno;
1351 :
1352 0 : if (get_info_for_key_operation (&info))
1353 0 : return;
1354 :
1355 0 : if (info.extcap.ki)
1356 : {
1357 : char *answer;
1358 :
1359 : /* FIXME: Should be something like cpr_get_bool so that a status
1360 : GET_BOOL will be emitted. */
1361 0 : answer = cpr_get ("cardedit.genkeys.backup_enc",
1362 0 : _("Make off-card backup of encryption key? (Y/n) "));
1363 :
1364 0 : want_backup = answer_is_yes_no_default (answer, 1/*(default to Yes)*/);
1365 0 : cpr_kill_prompt ();
1366 0 : xfree (answer);
1367 : }
1368 : else
1369 0 : want_backup = 0;
1370 :
1371 0 : if ( (info.fpr1valid && !fpr_is_zero (info.fpr1))
1372 0 : || (info.fpr2valid && !fpr_is_zero (info.fpr2))
1373 0 : || (info.fpr3valid && !fpr_is_zero (info.fpr3)))
1374 : {
1375 0 : tty_printf ("\n");
1376 0 : log_info (_("Note: keys are already stored on the card!\n"));
1377 0 : tty_printf ("\n");
1378 0 : if ( !cpr_get_answer_is_yes ("cardedit.genkeys.replace_keys",
1379 0 : _("Replace existing keys? (y/N) ")))
1380 : {
1381 0 : agent_release_card_info (&info);
1382 0 : return;
1383 : }
1384 : }
1385 :
1386 : /* If no displayed name has been set, we assume that this is a fresh
1387 : card and print a hint about the default PINs. */
1388 0 : if (!info.disp_name || !*info.disp_name)
1389 : {
1390 0 : tty_printf ("\n");
1391 0 : tty_printf (_("Please note that the factory settings of the PINs are\n"
1392 : " PIN = '%s' Admin PIN = '%s'\n"
1393 : "You should change them using the command --change-pin\n"),
1394 : "123456", "12345678");
1395 0 : tty_printf ("\n");
1396 : }
1397 :
1398 0 : if (check_pin_for_key_operation (&info, &forced_chv1))
1399 0 : goto leave;
1400 :
1401 : /* If the cards features changeable key attributes, we ask for the
1402 : key size. */
1403 0 : if (info.is_v2 && info.extcap.aac)
1404 : {
1405 : unsigned int nbits;
1406 :
1407 0 : for (keyno = 0; keyno < DIM (info.key_attr); keyno++)
1408 : {
1409 0 : nbits = ask_card_keysize (keyno, info.key_attr[keyno].nbits);
1410 0 : if (nbits && do_change_keysize (keyno, nbits))
1411 : {
1412 : /* Error: Better read the default key size again. */
1413 0 : agent_release_card_info (&info);
1414 0 : if (get_info_for_key_operation (&info))
1415 0 : goto leave;
1416 : /* Ask again for this key size. */
1417 0 : keyno--;
1418 : }
1419 : }
1420 : /* Note that INFO has not be synced. However we will only use
1421 : the serialnumber and thus it won't harm. */
1422 : }
1423 :
1424 0 : generate_keypair (ctrl, 1, NULL, info.serialno, want_backup);
1425 :
1426 : leave:
1427 0 : agent_release_card_info (&info);
1428 0 : restore_forced_chv1 (&forced_chv1);
1429 : }
1430 :
1431 :
1432 : /* This function is used by the key edit menu to generate an arbitrary
1433 : subkey. */
1434 : gpg_error_t
1435 0 : card_generate_subkey (KBNODE pub_keyblock)
1436 : {
1437 : gpg_error_t err;
1438 : struct agent_card_info_s info;
1439 0 : int forced_chv1 = 0;
1440 : int keyno;
1441 :
1442 0 : err = get_info_for_key_operation (&info);
1443 0 : if (err)
1444 0 : return err;
1445 :
1446 0 : show_card_key_info (&info);
1447 :
1448 0 : tty_printf (_("Please select the type of key to generate:\n"));
1449 :
1450 0 : tty_printf (_(" (1) Signature key\n"));
1451 0 : tty_printf (_(" (2) Encryption key\n"));
1452 0 : tty_printf (_(" (3) Authentication key\n"));
1453 :
1454 : for (;;)
1455 : {
1456 0 : char *answer = cpr_get ("cardedit.genkeys.subkeytype",
1457 0 : _("Your selection? "));
1458 0 : cpr_kill_prompt();
1459 0 : if (*answer == CONTROL_D)
1460 : {
1461 0 : xfree (answer);
1462 0 : err = gpg_error (GPG_ERR_CANCELED);
1463 0 : goto leave;
1464 : }
1465 0 : keyno = *answer? atoi(answer): 0;
1466 0 : xfree(answer);
1467 0 : if (keyno >= 1 && keyno <= 3)
1468 0 : break; /* Okay. */
1469 0 : tty_printf(_("Invalid selection.\n"));
1470 0 : }
1471 :
1472 0 : if (replace_existing_key_p (&info, keyno) < 0)
1473 : {
1474 0 : err = gpg_error (GPG_ERR_CANCELED);
1475 0 : goto leave;
1476 : }
1477 :
1478 0 : err = check_pin_for_key_operation (&info, &forced_chv1);
1479 0 : if (err)
1480 0 : goto leave;
1481 :
1482 : /* If the cards features changeable key attributes, we ask for the
1483 : key size. */
1484 0 : if (info.is_v2 && info.extcap.aac)
1485 : {
1486 : unsigned int nbits;
1487 :
1488 : ask_again:
1489 0 : nbits = ask_card_keysize (keyno-1, info.key_attr[keyno-1].nbits);
1490 0 : if (nbits && do_change_keysize (keyno-1, nbits))
1491 : {
1492 : /* Error: Better read the default key size again. */
1493 0 : agent_release_card_info (&info);
1494 0 : err = get_info_for_key_operation (&info);
1495 0 : if (err)
1496 0 : goto leave;
1497 0 : goto ask_again;
1498 : }
1499 : /* Note that INFO has not be synced. However we will only use
1500 : the serialnumber and thus it won't harm. */
1501 : }
1502 :
1503 0 : err = generate_card_subkeypair (pub_keyblock, keyno, info.serialno);
1504 :
1505 : leave:
1506 0 : agent_release_card_info (&info);
1507 0 : restore_forced_chv1 (&forced_chv1);
1508 0 : return err;
1509 : }
1510 :
1511 :
1512 : /* Store the key at NODE into the smartcard and modify NODE to
1513 : carry the serialno stuff instead of the actual secret key
1514 : parameters. USE is the usage for that key; 0 means any
1515 : usage. */
1516 : int
1517 0 : card_store_subkey (KBNODE node, int use)
1518 : {
1519 : struct agent_card_info_s info;
1520 0 : int okay = 0;
1521 : unsigned int nbits;
1522 : int allow_keyno[3];
1523 : int keyno;
1524 : PKT_public_key *pk;
1525 : gpg_error_t err;
1526 : char *hexgrip;
1527 : int rc;
1528 : gnupg_isotime_t timebuf;
1529 :
1530 0 : log_assert (node->pkt->pkttype == PKT_PUBLIC_KEY
1531 : || node->pkt->pkttype == PKT_PUBLIC_SUBKEY);
1532 :
1533 0 : pk = node->pkt->pkt.public_key;
1534 :
1535 0 : if (get_info_for_key_operation (&info))
1536 0 : return 0;
1537 :
1538 0 : if (!info.extcap.ki)
1539 : {
1540 0 : tty_printf ("The card does not support the import of keys\n");
1541 0 : tty_printf ("\n");
1542 0 : goto leave;
1543 : }
1544 :
1545 0 : nbits = nbits_from_pk (pk);
1546 :
1547 0 : if (!info.is_v2 && nbits != 1024)
1548 : {
1549 0 : tty_printf ("You may only store a 1024 bit RSA key on the card\n");
1550 0 : tty_printf ("\n");
1551 0 : goto leave;
1552 : }
1553 :
1554 0 : allow_keyno[0] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_CERT)));
1555 0 : allow_keyno[1] = (!use || (use & (PUBKEY_USAGE_ENC)));
1556 0 : allow_keyno[2] = (!use || (use & (PUBKEY_USAGE_SIG|PUBKEY_USAGE_AUTH)));
1557 :
1558 0 : tty_printf (_("Please select where to store the key:\n"));
1559 :
1560 0 : if (allow_keyno[0])
1561 0 : tty_printf (_(" (1) Signature key\n"));
1562 0 : if (allow_keyno[1])
1563 0 : tty_printf (_(" (2) Encryption key\n"));
1564 0 : if (allow_keyno[2])
1565 0 : tty_printf (_(" (3) Authentication key\n"));
1566 :
1567 : for (;;)
1568 : {
1569 0 : char *answer = cpr_get ("cardedit.genkeys.storekeytype",
1570 0 : _("Your selection? "));
1571 0 : cpr_kill_prompt();
1572 0 : if (*answer == CONTROL_D || !*answer)
1573 : {
1574 0 : xfree (answer);
1575 0 : goto leave;
1576 : }
1577 0 : keyno = *answer? atoi(answer): 0;
1578 0 : xfree(answer);
1579 0 : if (keyno >= 1 && keyno <= 3 && allow_keyno[keyno-1])
1580 : {
1581 0 : if (info.is_v2 && !info.extcap.aac
1582 0 : && info.key_attr[keyno-1].nbits != nbits)
1583 : {
1584 0 : tty_printf ("Key does not match the card's capability.\n");
1585 : }
1586 : else
1587 : break; /* Okay. */
1588 : }
1589 : else
1590 0 : tty_printf(_("Invalid selection.\n"));
1591 0 : }
1592 :
1593 0 : if ((rc = replace_existing_key_p (&info, keyno)) < 0)
1594 0 : goto leave;
1595 :
1596 0 : err = hexkeygrip_from_pk (pk, &hexgrip);
1597 0 : if (err)
1598 0 : goto leave;
1599 :
1600 0 : epoch2isotime (timebuf, (time_t)pk->timestamp);
1601 0 : rc = agent_keytocard (hexgrip, keyno, rc, info.serialno, timebuf);
1602 :
1603 0 : if (rc)
1604 0 : log_error (_("KEYTOCARD failed: %s\n"), gpg_strerror (rc));
1605 : else
1606 0 : okay = 1;
1607 0 : xfree (hexgrip);
1608 :
1609 : leave:
1610 0 : agent_release_card_info (&info);
1611 0 : return okay;
1612 : }
1613 :
1614 :
1615 :
1616 : /* Direct sending of an hex encoded APDU with error printing. */
1617 : static gpg_error_t
1618 0 : send_apdu (const char *hexapdu, const char *desc, unsigned int ignore)
1619 : {
1620 : gpg_error_t err;
1621 : unsigned int sw;
1622 :
1623 0 : err = agent_scd_apdu (hexapdu, &sw);
1624 0 : if (err)
1625 0 : tty_printf ("sending card command %s failed: %s\n", desc,
1626 : gpg_strerror (err));
1627 0 : else if (!hexapdu || !strcmp (hexapdu, "undefined"))
1628 : ;
1629 0 : else if (ignore == 0xffff)
1630 : ; /* Ignore all status words. */
1631 0 : else if (sw != 0x9000)
1632 : {
1633 0 : switch (sw)
1634 : {
1635 0 : case 0x6285: err = gpg_error (GPG_ERR_OBJ_TERM_STATE); break;
1636 0 : case 0x6982: err = gpg_error (GPG_ERR_BAD_PIN); break;
1637 0 : case 0x6985: err = gpg_error (GPG_ERR_USE_CONDITIONS); break;
1638 0 : default: err = gpg_error (GPG_ERR_CARD);
1639 : }
1640 0 : if (!(ignore && ignore == sw))
1641 0 : tty_printf ("card command %s failed: %s (0x%04x)\n", desc,
1642 : gpg_strerror (err), sw);
1643 : }
1644 0 : return err;
1645 : }
1646 :
1647 :
1648 : /* Do a factory reset after confirmation. */
1649 : static void
1650 0 : factory_reset (void)
1651 : {
1652 : struct agent_card_info_s info;
1653 : gpg_error_t err;
1654 0 : char *answer = NULL;
1655 0 : int termstate = 0;
1656 : int i;
1657 :
1658 : /* The code below basically does the same what this
1659 : gpg-connect-agent script does:
1660 :
1661 : scd reset
1662 : scd serialno undefined
1663 : scd apdu 00 A4 04 00 06 D2 76 00 01 24 01
1664 : scd apdu 00 20 00 81 08 40 40 40 40 40 40 40 40
1665 : scd apdu 00 20 00 81 08 40 40 40 40 40 40 40 40
1666 : scd apdu 00 20 00 81 08 40 40 40 40 40 40 40 40
1667 : scd apdu 00 20 00 81 08 40 40 40 40 40 40 40 40
1668 : scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
1669 : scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
1670 : scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
1671 : scd apdu 00 20 00 83 08 40 40 40 40 40 40 40 40
1672 : scd apdu 00 e6 00 00
1673 : scd reset
1674 : scd serialno undefined
1675 : scd apdu 00 A4 04 00 06 D2 76 00 01 24 01
1676 : scd apdu 00 44 00 00
1677 : /echo Card has been reset to factory defaults
1678 :
1679 : but tries to find out something about the card first.
1680 : */
1681 :
1682 0 : err = agent_scd_learn (&info, 0);
1683 0 : if (gpg_err_code (err) == GPG_ERR_OBJ_TERM_STATE
1684 0 : && gpg_err_source (err) == GPG_ERR_SOURCE_SCD)
1685 0 : termstate = 1;
1686 0 : else if (err)
1687 : {
1688 0 : log_error (_("OpenPGP card not available: %s\n"), gpg_strerror (err));
1689 0 : return;
1690 : }
1691 :
1692 0 : if (!termstate)
1693 : {
1694 0 : log_info (_("OpenPGP card no. %s detected\n"),
1695 0 : info.serialno? info.serialno : "[none]");
1696 0 : if (!(info.status_indicator == 3 || info.status_indicator == 5))
1697 : {
1698 : /* Note: We won't see status-indicator 3 here because it is not
1699 : possible to select a card application in termination state. */
1700 0 : log_error (_("This command is not supported by this card\n"));
1701 0 : goto leave;
1702 : }
1703 :
1704 0 : tty_printf ("\n");
1705 0 : log_info (_("Note: This command destroys all keys stored on the card!\n"));
1706 0 : tty_printf ("\n");
1707 0 : if (!cpr_get_answer_is_yes ("cardedit.factory-reset.proceed",
1708 0 : _("Continue? (y/N) ")))
1709 0 : goto leave;
1710 :
1711 :
1712 0 : answer = cpr_get ("cardedit.factory-reset.really",
1713 0 : _("Really do a factory reset? (enter \"yes\") "));
1714 0 : cpr_kill_prompt ();
1715 0 : trim_spaces (answer);
1716 0 : if (strcmp (answer, "yes"))
1717 0 : goto leave;
1718 :
1719 : /* We need to select a card application before we can send APDUs
1720 : to the card without scdaemon doing anything on its own. */
1721 0 : err = send_apdu (NULL, "RESET", 0);
1722 0 : if (err)
1723 0 : goto leave;
1724 0 : err = send_apdu ("undefined", "dummy select ", 0);
1725 0 : if (err)
1726 0 : goto leave;
1727 :
1728 : /* Select the OpenPGP application. */
1729 0 : err = send_apdu ("00A4040006D27600012401", "SELECT AID", 0);
1730 0 : if (err)
1731 0 : goto leave;
1732 :
1733 : /* Do some dummy verifies with wrong PINs to set the retry
1734 : counter to zero. We can't easily use the card version 2.1
1735 : feature of presenting the admin PIN to allow the terminate
1736 : command because there is no machinery in scdaemon to catch
1737 : the verify command and ask for the PIN when the "APDU"
1738 : command is used. */
1739 0 : for (i=0; i < 4; i++)
1740 0 : send_apdu ("00200081084040404040404040", "VERIFY", 0xffff);
1741 0 : for (i=0; i < 4; i++)
1742 0 : send_apdu ("00200083084040404040404040", "VERIFY", 0xffff);
1743 :
1744 : /* Send terminate datafile command. */
1745 0 : err = send_apdu ("00e60000", "TERMINATE DF", 0x6985);
1746 0 : if (err)
1747 0 : goto leave;
1748 : }
1749 :
1750 : /* The card is in termination state - reset and select again. */
1751 0 : err = send_apdu (NULL, "RESET", 0);
1752 0 : if (err)
1753 0 : goto leave;
1754 0 : err = send_apdu ("undefined", "dummy select", 0);
1755 0 : if (err)
1756 0 : goto leave;
1757 :
1758 : /* Select the OpenPGP application. (no error checking here). */
1759 0 : send_apdu ("00A4040006D27600012401", "SELECT AID", 0xffff);
1760 :
1761 : /* Send activate datafile command. This is used without
1762 : confirmation if the card is already in termination state. */
1763 0 : err = send_apdu ("00440000", "ACTIVATE DF", 0);
1764 0 : if (err)
1765 0 : goto leave;
1766 :
1767 : /* Finally we reset the card reader once more. */
1768 0 : err = send_apdu (NULL, "RESET", 0);
1769 0 : if (err)
1770 0 : goto leave;
1771 :
1772 : leave:
1773 0 : xfree (answer);
1774 0 : agent_release_card_info (&info);
1775 : }
1776 :
1777 :
1778 :
1779 : /* Data used by the command parser. This needs to be outside of the
1780 : function scope to allow readline based command completion. */
1781 : enum cmdids
1782 : {
1783 : cmdNOP = 0,
1784 : cmdQUIT, cmdADMIN, cmdHELP, cmdLIST, cmdDEBUG, cmdVERIFY,
1785 : cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR,
1786 : cmdFORCESIG, cmdGENERATE, cmdPASSWD, cmdPRIVATEDO, cmdWRITECERT,
1787 : cmdREADCERT, cmdUNBLOCK, cmdFACTORYRESET,
1788 : cmdINVCMD
1789 : };
1790 :
1791 : static struct
1792 : {
1793 : const char *name;
1794 : enum cmdids id;
1795 : int admin_only;
1796 : const char *desc;
1797 : } cmds[] =
1798 : {
1799 : { "quit" , cmdQUIT , 0, N_("quit this menu")},
1800 : { "q" , cmdQUIT , 0, NULL },
1801 : { "admin" , cmdADMIN , 0, N_("show admin commands")},
1802 : { "help" , cmdHELP , 0, N_("show this help")},
1803 : { "?" , cmdHELP , 0, NULL },
1804 : { "list" , cmdLIST , 0, N_("list all available data")},
1805 : { "l" , cmdLIST , 0, NULL },
1806 : { "debug" , cmdDEBUG , 0, NULL },
1807 : { "name" , cmdNAME , 1, N_("change card holder's name")},
1808 : { "url" , cmdURL , 1, N_("change URL to retrieve key")},
1809 : { "fetch" , cmdFETCH , 0, N_("fetch the key specified in the card URL")},
1810 : { "login" , cmdLOGIN , 1, N_("change the login name")},
1811 : { "lang" , cmdLANG , 1, N_("change the language preferences")},
1812 : { "sex" , cmdSEX , 1, N_("change card holder's sex")},
1813 : { "cafpr" , cmdCAFPR , 1, N_("change a CA fingerprint")},
1814 : { "forcesig", cmdFORCESIG, 1, N_("toggle the signature force PIN flag")},
1815 : { "generate", cmdGENERATE, 1, N_("generate new keys")},
1816 : { "passwd" , cmdPASSWD, 0, N_("menu to change or unblock the PIN")},
1817 : { "verify" , cmdVERIFY, 0, N_("verify the PIN and list all data")},
1818 : { "unblock" , cmdUNBLOCK,0, N_("unblock the PIN using a Reset Code") },
1819 : { "factory-reset", cmdFACTORYRESET, 1, N_("destroy all keys and data")},
1820 : /* Note, that we do not announce these command yet. */
1821 : { "privatedo", cmdPRIVATEDO, 0, NULL },
1822 : { "readcert", cmdREADCERT, 0, NULL },
1823 : { "writecert", cmdWRITECERT, 1, NULL },
1824 : { NULL, cmdINVCMD, 0, NULL }
1825 : };
1826 :
1827 :
1828 : #ifdef HAVE_LIBREADLINE
1829 :
1830 : /* These two functions are used by readline for command completion. */
1831 :
1832 : static char *
1833 0 : command_generator(const char *text,int state)
1834 : {
1835 : static int list_index,len;
1836 : const char *name;
1837 :
1838 : /* If this is a new word to complete, initialize now. This includes
1839 : saving the length of TEXT for efficiency, and initializing the
1840 : index variable to 0. */
1841 0 : if(!state)
1842 : {
1843 0 : list_index=0;
1844 0 : len=strlen(text);
1845 : }
1846 :
1847 : /* Return the next partial match */
1848 0 : while((name=cmds[list_index].name))
1849 : {
1850 : /* Only complete commands that have help text */
1851 0 : if(cmds[list_index++].desc && strncmp(name,text,len)==0)
1852 0 : return strdup(name);
1853 : }
1854 :
1855 0 : return NULL;
1856 : }
1857 :
1858 : static char **
1859 0 : card_edit_completion(const char *text, int start, int end)
1860 : {
1861 : (void)end;
1862 : /* If we are at the start of a line, we try and command-complete.
1863 : If not, just do nothing for now. */
1864 :
1865 0 : if(start==0)
1866 0 : return rl_completion_matches(text,command_generator);
1867 :
1868 0 : rl_attempted_completion_over=1;
1869 :
1870 0 : return NULL;
1871 : }
1872 : #endif /*HAVE_LIBREADLINE*/
1873 :
1874 : /* Menu to edit all user changeable values on an OpenPGP card. Only
1875 : Key creation is not handled here. */
1876 : void
1877 0 : card_edit (ctrl_t ctrl, strlist_t commands)
1878 : {
1879 0 : enum cmdids cmd = cmdNOP;
1880 0 : int have_commands = !!commands;
1881 0 : int redisplay = 1;
1882 0 : char *answer = NULL;
1883 0 : int allow_admin=0;
1884 : char serialnobuf[50];
1885 :
1886 :
1887 0 : if (opt.command_fd != -1)
1888 : ;
1889 0 : else if (opt.batch && !have_commands)
1890 : {
1891 0 : log_error(_("can't do this in batch mode\n"));
1892 0 : goto leave;
1893 : }
1894 :
1895 : for (;;)
1896 : {
1897 : int arg_number;
1898 0 : const char *arg_string = "";
1899 0 : const char *arg_rest = "";
1900 : char *p;
1901 : int i;
1902 : int cmd_admin_only;
1903 :
1904 0 : tty_printf("\n");
1905 0 : if (redisplay )
1906 : {
1907 0 : if (opt.with_colons)
1908 : {
1909 0 : card_status (es_stdout, serialnobuf, DIM (serialnobuf));
1910 0 : fflush (stdout);
1911 : }
1912 : else
1913 : {
1914 0 : card_status (NULL, serialnobuf, DIM (serialnobuf));
1915 0 : tty_printf("\n");
1916 : }
1917 0 : redisplay = 0;
1918 : }
1919 :
1920 : do
1921 : {
1922 0 : xfree (answer);
1923 0 : if (have_commands)
1924 : {
1925 0 : if (commands)
1926 : {
1927 0 : answer = xstrdup (commands->d);
1928 0 : commands = commands->next;
1929 : }
1930 0 : else if (opt.batch)
1931 : {
1932 0 : answer = xstrdup ("quit");
1933 : }
1934 : else
1935 0 : have_commands = 0;
1936 : }
1937 :
1938 0 : if (!have_commands)
1939 : {
1940 0 : tty_enable_completion (card_edit_completion);
1941 0 : answer = cpr_get_no_help("cardedit.prompt", _("gpg/card> "));
1942 0 : cpr_kill_prompt();
1943 0 : tty_disable_completion ();
1944 : }
1945 0 : trim_spaces(answer);
1946 : }
1947 0 : while ( *answer == '#' );
1948 :
1949 0 : arg_number = 0; /* Yes, here is the init which egcc complains about */
1950 0 : cmd_admin_only = 0;
1951 0 : if (!*answer)
1952 0 : cmd = cmdLIST; /* Default to the list command */
1953 0 : else if (*answer == CONTROL_D)
1954 0 : cmd = cmdQUIT;
1955 : else
1956 : {
1957 0 : if ((p=strchr (answer,' ')))
1958 : {
1959 0 : *p++ = 0;
1960 0 : trim_spaces (answer);
1961 0 : trim_spaces (p);
1962 0 : arg_number = atoi(p);
1963 0 : arg_string = p;
1964 0 : arg_rest = p;
1965 0 : while (digitp (arg_rest))
1966 0 : arg_rest++;
1967 0 : while (spacep (arg_rest))
1968 0 : arg_rest++;
1969 : }
1970 :
1971 0 : for (i=0; cmds[i].name; i++ )
1972 0 : if (!ascii_strcasecmp (answer, cmds[i].name ))
1973 0 : break;
1974 :
1975 0 : cmd = cmds[i].id;
1976 0 : cmd_admin_only = cmds[i].admin_only;
1977 : }
1978 :
1979 0 : if (!allow_admin && cmd_admin_only)
1980 : {
1981 0 : tty_printf ("\n");
1982 0 : tty_printf (_("Admin-only command\n"));
1983 0 : continue;
1984 : }
1985 :
1986 0 : switch (cmd)
1987 : {
1988 : case cmdHELP:
1989 0 : for (i=0; cmds[i].name; i++ )
1990 0 : if(cmds[i].desc
1991 0 : && (!cmds[i].admin_only || (cmds[i].admin_only && allow_admin)))
1992 0 : tty_printf("%-14s %s\n", cmds[i].name, _(cmds[i].desc) );
1993 0 : break;
1994 :
1995 : case cmdADMIN:
1996 0 : if ( !strcmp (arg_string, "on") )
1997 0 : allow_admin = 1;
1998 0 : else if ( !strcmp (arg_string, "off") )
1999 0 : allow_admin = 0;
2000 0 : else if ( !strcmp (arg_string, "verify") )
2001 : {
2002 : /* Force verification of the Admin Command. However,
2003 : this is only done if the retry counter is at initial
2004 : state. */
2005 0 : char *tmp = xmalloc (strlen (serialnobuf) + 6 + 1);
2006 0 : strcpy (stpcpy (tmp, serialnobuf), "[CHV3]");
2007 0 : allow_admin = !agent_scd_checkpin (tmp);
2008 0 : xfree (tmp);
2009 : }
2010 : else /* Toggle. */
2011 0 : allow_admin=!allow_admin;
2012 0 : if(allow_admin)
2013 0 : tty_printf(_("Admin commands are allowed\n"));
2014 : else
2015 0 : tty_printf(_("Admin commands are not allowed\n"));
2016 0 : break;
2017 :
2018 : case cmdVERIFY:
2019 0 : agent_scd_checkpin (serialnobuf);
2020 0 : redisplay = 1;
2021 0 : break;
2022 :
2023 : case cmdLIST:
2024 0 : redisplay = 1;
2025 0 : break;
2026 :
2027 : case cmdNAME:
2028 0 : change_name ();
2029 0 : break;
2030 :
2031 : case cmdURL:
2032 0 : change_url ();
2033 0 : break;
2034 :
2035 : case cmdFETCH:
2036 0 : fetch_url (ctrl);
2037 0 : break;
2038 :
2039 : case cmdLOGIN:
2040 0 : change_login (arg_string);
2041 0 : break;
2042 :
2043 : case cmdLANG:
2044 0 : change_lang ();
2045 0 : break;
2046 :
2047 : case cmdSEX:
2048 0 : change_sex ();
2049 0 : break;
2050 :
2051 : case cmdCAFPR:
2052 0 : if ( arg_number < 1 || arg_number > 3 )
2053 0 : tty_printf ("usage: cafpr N\n"
2054 : " 1 <= N <= 3\n");
2055 : else
2056 0 : change_cafpr (arg_number);
2057 0 : break;
2058 :
2059 : case cmdPRIVATEDO:
2060 0 : if ( arg_number < 1 || arg_number > 4 )
2061 0 : tty_printf ("usage: privatedo N\n"
2062 : " 1 <= N <= 4\n");
2063 : else
2064 0 : change_private_do (arg_string, arg_number);
2065 0 : break;
2066 :
2067 : case cmdWRITECERT:
2068 0 : if ( arg_number != 3 )
2069 0 : tty_printf ("usage: writecert 3 < FILE\n");
2070 : else
2071 0 : change_cert (arg_rest);
2072 0 : break;
2073 :
2074 : case cmdREADCERT:
2075 0 : if ( arg_number != 3 )
2076 0 : tty_printf ("usage: readcert 3 > FILE\n");
2077 : else
2078 0 : read_cert (arg_rest);
2079 0 : break;
2080 :
2081 : case cmdFORCESIG:
2082 0 : toggle_forcesig ();
2083 0 : break;
2084 :
2085 : case cmdGENERATE:
2086 0 : generate_card_keys (ctrl);
2087 0 : break;
2088 :
2089 : case cmdPASSWD:
2090 0 : change_pin (0, allow_admin);
2091 0 : break;
2092 :
2093 : case cmdUNBLOCK:
2094 0 : change_pin (1, allow_admin);
2095 0 : break;
2096 :
2097 : case cmdFACTORYRESET:
2098 0 : factory_reset ();
2099 0 : break;
2100 :
2101 : case cmdQUIT:
2102 0 : goto leave;
2103 :
2104 : case cmdNOP:
2105 0 : break;
2106 :
2107 : case cmdINVCMD:
2108 : default:
2109 0 : tty_printf ("\n");
2110 0 : tty_printf (_("Invalid command (try \"help\")\n"));
2111 0 : break;
2112 : } /* End command switch. */
2113 0 : } /* End of main menu loop. */
2114 :
2115 : leave:
2116 0 : xfree (answer);
2117 0 : }
|