* card-util.c (fetch_url, card_edit): Use the pubkey URL stored on the
[gnupg.git] / g10 / card-util.c
1 /* card-util.c - Utility functions for the OpenPGP card.
2  *      Copyright (C) 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
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 2 of the License, or
9  * (at your option) any later version.
10  *
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.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27
28 #if GNUPG_MAJOR_VERSION != 1
29 #include "gpg.h"
30 #endif
31 #include "util.h"
32 #include "i18n.h"
33 #include "ttyio.h"
34 #include "status.h"
35 #include "options.h"
36 #include "main.h"
37 #include "keyserver-internal.h"
38 #if GNUPG_MAJOR_VERSION == 1
39 #include "cardglue.h"
40 #else
41 #include "call-agent.h"
42 #endif
43
44 #define CONTROL_D ('D' - 'A' + 1)
45
46
47 /* Change the PIN of a an OpenPGP card.  This is an interactive
48    function. */
49 void
50 change_pin (int chvno)
51 {
52   struct agent_card_info_s info;
53   int rc;
54
55   rc = agent_learn (&info);
56   if (rc)
57     {
58       log_error (_("OpenPGP card not available: %s\n"),
59                   gpg_strerror (rc));
60       return;
61     }
62   
63   log_info (_("OpenPGP card no. %s detected\n"),
64               info.serialno? info.serialno : "[none]");
65
66   agent_release_card_info (&info);
67
68   if (opt.batch)
69     {
70       log_error (_("sorry, can't do this in batch mode\n"));
71       return;
72     }
73
74   for (;;)
75     {
76       char *answer;
77
78       tty_printf ("\n");
79       tty_printf ("1 - change PIN\n"
80                   "2 - unblock PIN\n"
81                   "3 - change Admin PIN\n"
82                   "Q - quit\n");
83       tty_printf ("\n");
84
85       answer = cpr_get("cardutil.change_pin.menu",_("Your selection? "));
86       cpr_kill_prompt();
87       if (strlen (answer) != 1)
88         continue;
89
90       rc = 0;
91       if (*answer == '1')
92         {
93           rc = agent_scd_change_pin (1);
94           if (rc)
95             tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
96           else
97             tty_printf ("PIN changed.\n");
98         }
99       else if (*answer == '2')
100         {
101           rc = agent_scd_change_pin (101);
102           if (rc)
103             tty_printf ("Error unblocking the PIN: %s\n", gpg_strerror (rc));
104           else
105             tty_printf ("PIN unblocked and new PIN set.\n");
106         }
107       else if (*answer == '3')
108         {
109           rc = agent_scd_change_pin (3);
110           if (rc)
111             tty_printf ("Error changing the PIN: %s\n", gpg_strerror (rc));
112           else
113             tty_printf ("PIN changed.\n");
114         }
115       else if (*answer == 'q' || *answer == 'Q')
116         {
117           break;
118         }
119     }
120 }
121
122 static const char *
123 get_manufacturer (unsigned int no)
124 {
125   /* Note:  Make sure that there is no colon or linefeed in the string. */
126   switch (no)
127     {
128     case 0:
129     case 0xffff: return "test card";
130     case 0x0001: return "PPC Card Systems";
131     default: return "unknown";
132     }
133 }
134
135
136 static void
137 print_sha1_fpr (FILE *fp, const unsigned char *fpr)
138 {
139   int i;
140
141   if (fpr)
142     {
143       for (i=0; i < 20 ; i+=2, fpr += 2 )
144         {
145           if (i == 10 )
146             tty_fprintf (fp, " ");
147           tty_fprintf (fp, " %02X%02X", *fpr, fpr[1]);
148         }
149     }
150   else
151     tty_fprintf (fp, " [none]");
152   tty_fprintf (fp, "\n");
153 }
154
155
156 static void
157 print_sha1_fpr_colon (FILE *fp, const unsigned char *fpr)
158 {
159   int i;
160
161   if (fpr)
162     {
163       for (i=0; i < 20 ; i++, fpr++)
164         fprintf (fp, "%02X", *fpr);
165     }
166   putc (':', fp);
167 }
168
169
170 static void
171 print_name (FILE *fp, const char *text, const char *name)
172 {
173   tty_fprintf (fp, "%s", text);
174
175   /* FIXME: tty_printf_utf8_string2 eats everything after and
176      including an @ - e.g. when printing an url. */
177   if (name && *name)
178     {
179       if (fp)
180         print_utf8_string2 (fp, name, strlen (name), '\n');
181       else
182         tty_print_utf8_string2 (name, strlen (name), 0);
183     }
184   else
185     tty_fprintf (fp, _("[not set]"));
186   tty_fprintf (fp, "\n");
187 }
188
189 static void
190 print_isoname (FILE *fp, const char *text, const char *tag, const char *name)
191 {
192   if (opt.with_colons)
193     fprintf (fp, "%s:", tag);
194   else
195     tty_fprintf (fp, "%s", text);
196
197   if (name && *name)
198     {
199       char *p, *given, *buf = xstrdup (name);
200
201       given = strstr (buf, "<<");
202       for (p=buf; *p; p++)
203         if (*p == '<')
204           *p = ' ';
205       if (given && given[2])
206         {
207           *given = 0;
208           given += 2;
209           if (opt.with_colons)
210             print_string (fp, given, strlen (given), ':');
211           else if (fp)
212             print_utf8_string2 (fp, given, strlen (given), '\n');
213           else
214             tty_print_utf8_string2 (given, strlen (given), 0);
215
216           if (opt.with_colons)
217             putc (':', fp);
218           else if (*buf)
219             tty_fprintf (fp, " ");
220         }
221
222       if (opt.with_colons)
223         print_string (fp, buf, strlen (buf), ':');
224       else if (fp)
225         print_utf8_string2 (fp, buf, strlen (buf), '\n');
226       else
227         tty_print_utf8_string2 (buf, strlen (buf), 0);
228       xfree (buf);
229     }
230   else
231     {
232       if (opt.with_colons)
233         putc (':', fp);
234       else
235         tty_fprintf (fp, _("[not set]"));
236     }
237
238   if (opt.with_colons)
239     fputs (":\n", fp);
240   else
241     tty_fprintf (fp, "\n");
242 }
243
244 /* Return true if the SHA1 fingerprint FPR consists only of zeroes. */
245 static int
246 fpr_is_zero (const char *fpr)
247 {
248   int i;
249
250   for (i=0; i < 20 && !fpr[i]; i++)
251     ;
252   return (i == 20);
253 }
254
255
256 /* Print all available information about the current card. */
257 void
258 card_status (FILE *fp, char *serialno, size_t serialnobuflen)
259 {
260   struct agent_card_info_s info;
261   PKT_public_key *pk = xcalloc (1, sizeof *pk);
262   int rc;
263   unsigned int uval;
264
265   if (serialno && serialnobuflen)
266     *serialno = 0;
267
268   rc = agent_learn (&info);
269   if (rc)
270     {
271       if (opt.with_colons)
272         fputs ("AID:::\n", fp);
273       log_error (_("OpenPGP card not available: %s\n"),
274                   gpg_strerror (rc));
275       xfree (pk);
276       return;
277     }
278
279   if (opt.with_colons)
280     fprintf (fp, "AID:%s:", info.serialno? info.serialno : "");
281   else
282     tty_fprintf (fp, "Application ID ...: %s\n",
283                  info.serialno? info.serialno : "[none]");
284   if (!info.serialno || strncmp (info.serialno, "D27600012401", 12) 
285       || strlen (info.serialno) != 32 )
286     {
287       if (opt.with_colons)
288         fputs ("unknown:\n", fp);
289       log_info ("not an OpenPGP card\n");
290       agent_release_card_info (&info);
291       xfree (pk);
292       return;
293     }
294
295   if (!serialno)
296     ;
297   else if (strlen (serialno)+1 > serialnobuflen)
298     log_error ("serial number longer than expected\n");
299   else 
300     strcpy (serialno, info.serialno);
301
302   if (opt.with_colons)
303     fputs ("openpgp-card:\n", fp);
304
305
306   if (opt.with_colons)
307     {
308       fprintf (fp, "version:%.4s:\n", info.serialno+12);
309       uval = xtoi_2(info.serialno+16)*256 + xtoi_2 (info.serialno+18);
310       fprintf (fp, "vendor:%04x:%s:\n", uval, get_manufacturer (uval));
311       fprintf (fp, "serial:%.8s:\n", info.serialno+20);
312       
313       print_isoname (fp, "Name of cardholder: ", "name", info.disp_name);
314
315       fputs ("lang:", fp);
316       if (info.disp_lang)
317         print_string (fp, info.disp_lang, strlen (info.disp_lang), ':');
318       fputs (":\n", fp);
319
320       fprintf (fp, "sex:%c:\n", (info.disp_sex == 1? 'm':
321                                  info.disp_sex == 2? 'f' : 'u'));
322
323       fputs ("url:", fp);
324       if (info.pubkey_url)
325         print_string (fp, info.pubkey_url, strlen (info.pubkey_url), ':');
326       fputs (":\n", fp);
327
328       fputs ("login:", fp);
329       if (info.login_data)
330         print_string (fp, info.login_data, strlen (info.login_data), ':');
331       fputs (":\n", fp);
332
333       fprintf (fp, "forcepin:%d:::\n", !info.chv1_cached);
334       fprintf (fp, "maxpinlen:%d:%d:%d:\n",
335                    info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]);
336       fprintf (fp, "pinretry:%d:%d:%d:\n",
337                    info.chvretry[0], info.chvretry[1], info.chvretry[2]);
338       fprintf (fp, "sigcount:%lu:::\n", info.sig_counter);
339
340       fputs ("cafpr:", fp);
341       print_sha1_fpr_colon (fp, info.cafpr1valid? info.cafpr1:NULL);
342       print_sha1_fpr_colon (fp, info.cafpr2valid? info.cafpr2:NULL);
343       print_sha1_fpr_colon (fp, info.cafpr3valid? info.cafpr3:NULL);
344       putc ('\n', fp);
345       fputs ("fpr:", fp);
346       print_sha1_fpr_colon (fp, info.fpr1valid? info.fpr1:NULL);
347       print_sha1_fpr_colon (fp, info.fpr2valid? info.fpr2:NULL);
348       print_sha1_fpr_colon (fp, info.fpr3valid? info.fpr3:NULL);
349       putc ('\n', fp);
350
351     }
352   else 
353     {
354       tty_fprintf (fp, "Version ..........: %.1s%c.%.1s%c\n",
355                    info.serialno[12] == '0'?"":info.serialno+12,
356                    info.serialno[13],
357                    info.serialno[14] == '0'?"":info.serialno+14,
358                    info.serialno[15]);
359       tty_fprintf (fp, "Manufacturer .....: %s\n", 
360                    get_manufacturer (xtoi_2(info.serialno+16)*256
361                                      + xtoi_2 (info.serialno+18)));
362       tty_fprintf (fp, "Serial number ....: %.8s\n", info.serialno+20);
363       
364       print_isoname (fp, "Name of cardholder: ", "name", info.disp_name);
365       print_name (fp, "Language prefs ...: ", info.disp_lang);
366       tty_fprintf (fp,    "Sex ..............: %s\n",
367                    info.disp_sex == 1? _("male"):
368                    info.disp_sex == 2? _("female") : _("unspecified"));
369       print_name (fp, "URL of public key : ", info.pubkey_url);
370       print_name (fp, "Login data .......: ", info.login_data);
371       if (info.cafpr1valid)
372         {
373           tty_fprintf (fp, "CA fingerprint %d .:", 1);
374           print_sha1_fpr (fp, info.cafpr1);
375         }
376       if (info.cafpr2valid)
377         {
378           tty_fprintf (fp, "CA fingerprint %d .:", 2);
379           print_sha1_fpr (fp, info.cafpr2);
380         }
381       if (info.cafpr3valid)
382         {
383           tty_fprintf (fp, "CA fingerprint %d .:", 3);
384           print_sha1_fpr (fp, info.cafpr3);
385         }
386       tty_fprintf (fp,    "Signature PIN ....: %s\n",
387                    info.chv1_cached? _("not forced"): _("forced"));
388       tty_fprintf (fp,    "Max. PIN lengths .: %d %d %d\n",
389                    info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]);
390       tty_fprintf (fp,    "PIN retry counter : %d %d %d\n",
391                    info.chvretry[0], info.chvretry[1], info.chvretry[2]);
392       tty_fprintf (fp,    "Signature counter : %lu\n", info.sig_counter);
393       tty_fprintf (fp, "Signature key ....:");
394       print_sha1_fpr (fp, info.fpr1valid? info.fpr1:NULL);
395       tty_fprintf (fp, "Encryption key....:");
396       print_sha1_fpr (fp, info.fpr2valid? info.fpr2:NULL);
397       tty_fprintf (fp, "Authentication key:");
398       print_sha1_fpr (fp, info.fpr3valid? info.fpr3:NULL);
399       tty_fprintf (fp, "General key info..: "); 
400       if (info.fpr1valid && !get_pubkey_byfprint (pk, info.fpr1, 20))
401         print_pubkey_info (fp, pk);
402       else
403         tty_fprintf (fp, "[none]\n");
404     }
405       
406   free_public_key (pk);
407   agent_release_card_info (&info);
408 }
409
410
411 static char *
412 get_one_name (const char *prompt1, const char *prompt2)
413 {
414   char *name;
415   int i;
416
417   for (;;)
418     {
419       name = cpr_get (prompt1, prompt2);
420       if (!name)
421         return NULL;
422       trim_spaces (name);
423       cpr_kill_prompt ();
424       for (i=0; name[i] && name[i] >= ' ' && name[i] <= 126; i++)
425         ;
426
427       /* The name must be in Latin-1 and not UTF-8 - lacking the code
428          to ensure this we restrict it to ASCII. */
429       if (name[i])
430         tty_printf (_("Error: Only plain ASCII is currently allowed.\n"));
431       else if (strchr (name, '<'))
432         tty_printf (_("Error: The \"<\" character may not be used.\n"));
433       else if (strstr (name, "  "))
434         tty_printf (_("Error: Double spaces are not allowed.\n"));    
435       else
436         return name;
437       xfree (name);
438     }
439 }
440
441
442
443 static int
444 change_name (void)
445 {
446   char *surname = NULL, *givenname = NULL;
447   char *isoname, *p;
448   int rc;
449
450   surname = get_one_name ("keygen.smartcard.surname",
451                                     _("Cardholder's surname: "));
452   givenname = get_one_name ("keygen.smartcard.givenname",
453                                        _("Cardholder's given name: "));
454   if (!surname || !givenname || (!*surname && !*givenname))
455     {
456       xfree (surname);
457       xfree (givenname);
458       return -1; /*canceled*/
459     }
460
461   isoname = xmalloc ( strlen (surname) + 2 + strlen (givenname) + 1);
462   strcpy (stpcpy (stpcpy (isoname, surname), "<<"), givenname);
463   xfree (surname);
464   xfree (givenname);
465   for (p=isoname; *p; p++)
466     if (*p == ' ')
467       *p = '<';
468
469   if (strlen (isoname) > 39 )
470     {
471       tty_printf (_("Error: Combined name too long "
472                     "(limit is %d characters).\n"), 39);    
473       xfree (isoname);
474       return -1;
475     }
476
477   log_debug ("setting Name to `%s'\n", isoname);
478   rc = agent_scd_setattr ("DISP-NAME", isoname, strlen (isoname) );
479   if (rc)
480     log_error ("error setting Name: %s\n", gpg_strerror (rc));
481
482   xfree (isoname);
483   return rc;
484 }
485
486
487 static int
488 change_url (void)
489 {
490   char *url;
491   int rc;
492
493   url = cpr_get ("cardedit.change_url", _("URL to retrieve public key: "));
494   if (!url)
495     return -1;
496   trim_spaces (url);
497   cpr_kill_prompt ();
498
499   if (strlen (url) > 254 )
500     {
501       tty_printf (_("Error: URL too long "
502                     "(limit is %d characters).\n"), 254);    
503       xfree (url);
504       return -1;
505     }
506
507   rc = agent_scd_setattr ("PUBKEY-URL", url, strlen (url) );
508   if (rc)
509     log_error ("error setting URL: %s\n", gpg_strerror (rc));
510   xfree (url);
511   return rc;
512 }
513
514 static int
515 fetch_url(void)
516 {
517   int rc;
518   struct agent_card_info_s info;
519
520   memset(&info,0,sizeof(info));
521
522   rc=agent_scd_getattr("PUBKEY-URL",&info);
523   if(rc)
524     log_error("error retrieving URL from card: %s\n",gpg_strerror(rc));
525   else if(info.pubkey_url)
526     {
527       struct keyserver_spec *spec=NULL;
528
529       rc=agent_scd_getattr("KEY-FPR",&info);
530       if(rc)
531         log_error("error retrieving key fingerprint from card: %s\n",
532                   gpg_strerror(rc));
533       else
534         {
535           spec=parse_keyserver_uri(info.pubkey_url,0,NULL,0);
536           if(spec && info.fpr1valid)
537             {
538               /* This is not perfectly right.  Currently, all card
539                  fingerprints are 20 digits, but what about
540                  fingerprints for a future v5 key?  We should get the
541                  length from somewhere lower in the code.  In any
542                  event, the fpr/keyid is not meaningful for straight
543                  HTTP fetches, but using it allows the card to point
544                  to HKP and LDAP servers as well. */
545               rc=keyserver_import_fprint(info.fpr1,20,spec);
546               free_keyserver_spec(spec);
547             }
548         }
549     }
550   else
551     log_error("no URL set on card\n");
552
553   return rc;
554 }
555
556
557 static int
558 change_login (const char *args)
559 {
560   char *data;
561   int n;
562   int rc;
563
564   if (args && *args == '<')  /* Read it from a file */
565     {
566       FILE *fp;
567
568       for (args++; spacep (args); args++)
569         ;
570       fp = fopen (args, "rb");
571       if (!fp)
572         {
573           tty_printf ("can't open `%s': %s\n", args, strerror (errno));
574           return -1;
575         }
576       data = xmalloc (254);
577       n = fread (data, 1, 254, fp);
578       fclose (fp);
579       if (n < 0)
580         {
581           tty_printf ("error reading `%s': %s\n", args, strerror (errno));
582           xfree (data);
583           return -1;
584         }
585     }
586   else
587     {
588       data = cpr_get ("cardedit.change_login",
589                       _("Login data (account name): "));
590       if (!data)
591         return -1;
592       trim_spaces (data);
593       cpr_kill_prompt ();
594       n = strlen (data);
595     }
596
597   if (n > 254 )
598     {
599       tty_printf (_("Error: Login data too long "
600                     "(limit is %d characters).\n"), 254);    
601       xfree (data);
602       return -1;
603     }
604
605   rc = agent_scd_setattr ("LOGIN-DATA", data, n );
606   if (rc)
607     log_error ("error setting login data: %s\n", gpg_strerror (rc));
608   xfree (data);
609   return rc;
610 }
611
612 static int
613 change_lang (void)
614 {
615   char *data, *p;
616   int rc;
617
618   data = cpr_get ("cardedit.change_lang",
619                   _("Language preferences: "));
620   if (!data)
621     return -1;
622   trim_spaces (data);
623   cpr_kill_prompt ();
624
625   if (strlen (data) > 8 || (strlen (data) & 1))
626     {
627       tty_printf (_("Error: invalid length of preference string.\n"));
628       xfree (data);
629       return -1;
630     }
631
632   for (p=data; *p && *p >= 'a' && *p <= 'z'; p++)
633     ;
634   if (*p)
635     {
636       tty_printf (_("Error: invalid characters in preference string.\n"));
637       xfree (data);
638       return -1;
639     }
640
641   rc = agent_scd_setattr ("DISP-LANG", data, strlen (data) );
642   if (rc)
643     log_error ("error setting lang: %s\n", gpg_strerror (rc));
644   xfree (data);
645   return rc;
646 }
647
648
649 static int
650 change_sex (void)
651 {
652   char *data;
653   const char *str;
654   int rc;
655
656   data = cpr_get ("cardedit.change_sex",
657                   _("Sex ((M)ale, (F)emale or space): "));
658   if (!data)
659     return -1;
660   trim_spaces (data);
661   cpr_kill_prompt ();
662
663   if (!*data)
664     str = "9";
665   else if ((*data == 'M' || *data == 'm') && !data[1])
666     str = "1";
667   else if ((*data == 'F' || *data == 'f') && !data[1])
668     str = "2";
669   else 
670     {
671       tty_printf (_("Error: invalid response.\n"));
672       xfree (data);
673       return -1;
674     }
675      
676   rc = agent_scd_setattr ("DISP-SEX", str, 1 );
677   if (rc)
678     log_error ("error setting sex: %s\n", gpg_strerror (rc));
679   xfree (data);
680   return rc;
681 }
682
683
684 static int
685 change_cafpr (int fprno)
686 {
687   char *data;
688   const char *s;
689   int i, c, rc;
690   unsigned char fpr[20];
691
692   data = cpr_get ("cardedit.change_cafpr", _("CA fingerprint: "));
693   if (!data)
694     return -1;
695   trim_spaces (data);
696   cpr_kill_prompt ();
697
698   for (i=0, s=data; i < 20 && *s; )
699     {
700       while (spacep(s))
701         s++;
702       if (*s == ':')
703         s++;
704       while (spacep(s))
705         s++;
706       c = hextobyte (s);
707       if (c == -1)
708         break;
709       fpr[i++] = c;
710       s += 2;
711     }
712   xfree (data);
713   if (i != 20 || *s)
714     {
715       tty_printf (_("Error: invalid formatted fingerprint.\n"));
716       return -1;
717     }
718
719   rc = agent_scd_setattr (fprno==1?"CA-FPR-1":
720                           fprno==2?"CA-FPR-2":
721                           fprno==3?"CA-FPR-3":"x", fpr, 20 );
722   if (rc)
723     log_error ("error setting cafpr: %s\n", gpg_strerror (rc));
724   return rc;
725 }
726
727
728
729 static void
730 toggle_forcesig (void)
731 {
732   struct agent_card_info_s info;
733   int rc;
734   int newstate;
735
736   memset (&info, 0, sizeof info);
737   rc = agent_scd_getattr ("CHV-STATUS", &info);
738   if (rc)
739     {
740       log_error ("error getting current status: %s\n", gpg_strerror (rc));
741       return;
742     }
743   newstate = !info.chv1_cached;
744   agent_release_card_info (&info);
745
746   rc = agent_scd_setattr ("CHV-STATUS-1", newstate? "\x01":"", 1);
747   if (rc)
748     log_error ("error toggling signature PIN flag: %s\n", gpg_strerror (rc));
749 }
750
751
752 static void
753 generate_card_keys (const char *serialno)
754 {
755   struct agent_card_info_s info;
756   int rc;
757   int forced_chv1;
758
759   memset (&info, 0, sizeof info);
760   rc = agent_scd_getattr ("KEY-FPR", &info);
761   if (!rc)
762     rc = agent_scd_getattr ("SERIALNO", &info);
763   if (!rc)
764     rc = agent_scd_getattr ("CHV-STATUS", &info);
765   if (!rc)
766     rc = agent_scd_getattr ("DISP-NAME", &info);
767   if (rc)
768     {
769       log_error ("error getting current key info: %s\n", gpg_strerror (rc));
770       return;
771     }
772   if ( (info.fpr1valid && !fpr_is_zero (info.fpr1))
773        || (info.fpr2valid && !fpr_is_zero (info.fpr2))
774        || (info.fpr3valid && !fpr_is_zero (info.fpr3)))
775     {
776       tty_printf ("\n");
777       log_info ("NOTE: keys are already stored on the card!\n");
778       tty_printf ("\n");
779       if ( !cpr_get_answer_is_yes( "cardedit.genkeys.replace_keys",
780                                   _("Replace existing keys? ")))
781         {
782           agent_release_card_info (&info);
783           return;
784         }
785     }
786   else if (!info.disp_name || !*info.disp_name)
787     {
788       tty_printf ("\n");
789       tty_printf (_("Please note that the factory settings of the PINs are\n"
790                     "   PIN = \"%s\"     Admin PIN = \"%s\"\n"
791                     "You should change them using the command --change-pin\n"),
792                   "123456", "12345678");
793       tty_printf ("\n");
794     }
795
796   forced_chv1 = !info.chv1_cached;
797   if (forced_chv1)
798     { /* Switch of the forced mode so that during key generation we
799          don't get bothered with PIN queries for each
800          self-signature. */
801       rc = agent_scd_setattr ("CHV-STATUS-1", "\x01", 1);
802       if (rc)
803         {
804           log_error ("error clearing forced signature PIN flag: %s\n",
805                      gpg_strerror (rc));
806           return;
807         }
808     }
809
810   /* Check the PIN now, so that we won't get asked later for each
811      binding signature. */
812   rc = agent_scd_checkpin (serialno);
813   if (rc)
814     log_error ("error checking the PIN: %s\n", gpg_strerror (rc));
815   else
816     generate_keypair (NULL, info.serialno);
817
818   agent_release_card_info (&info);
819   if (forced_chv1)
820     { /* Switch back to forced state. */
821       rc = agent_scd_setattr ("CHV-STATUS-1", "", 1);
822       if (rc)
823         {
824           log_error ("error setting forced signature PIN flag: %s\n",
825                      gpg_strerror (rc));
826           return;
827         }
828     }
829 }
830
831 /* Menu to edit all user changeable values on an OpenPGP card.  Only
832    Key creation is not handled here. */
833 void
834 card_edit (STRLIST commands)
835 {
836   enum cmdids {
837     cmdNOP = 0,
838     cmdQUIT, cmdHELP, cmdLIST, cmdDEBUG,
839     cmdNAME, cmdURL, cmdFETCH, cmdLOGIN, cmdLANG, cmdSEX, cmdCAFPR,
840     cmdFORCESIG, cmdGENERATE, cmdPASSWD,
841     cmdINVCMD
842   };
843
844   static struct {
845     const char *name;
846     enum cmdids id;
847     const char *desc;
848   } cmds[] = {
849     { N_("quit")  , cmdQUIT  , N_("quit this menu") },
850     { N_("q")     , cmdQUIT  , NULL   },
851     { N_("help")  , cmdHELP  , N_("show this help") },
852     {    "?"      , cmdHELP  , NULL   },
853     { N_("list")  , cmdLIST  , N_("list all available data") },
854     { N_("l")     , cmdLIST  , NULL   },
855     { N_("debug") , cmdDEBUG , NULL },
856     { N_("name")  , cmdNAME  , N_("change card holder's name") },
857     { N_("url")   , cmdURL   , N_("change URL to retrieve key") },
858     { N_("fetch") , cmdFETCH , N_("fetch the key specified in the card URL") },
859     { N_("login") , cmdLOGIN , N_("change the login name") },
860     { N_("lang")  , cmdLANG  , N_("change the language preferences") },
861     { N_("sex")   , cmdSEX   , N_("change card holder's sex") },
862     { N_("cafpr"),  cmdCAFPR,  N_("change a CA fingerprint") },
863     { N_("forcesig"),
864                   cmdFORCESIG, N_("toggle the signature force PIN flag") },
865     { N_("generate"),
866                   cmdGENERATE, N_("generate new keys") },
867     { N_("passwd"), cmdPASSWD, N_("menu to change or unblock the PIN") },
868     { NULL, cmdINVCMD } 
869   };
870  
871   enum cmdids cmd = cmdNOP;
872   int have_commands = !!commands;
873   int redisplay = 1;
874   char *answer = NULL;
875   int did_checkpin = 0;
876   char serialnobuf[50];
877
878
879   if (opt.command_fd != -1)
880     ;
881   else if (opt.batch && !have_commands)
882     {
883       log_error(_("can't do that in batchmode\n"));
884       goto leave;
885     }
886
887   for (;;)
888     {
889       int arg_number;
890       const char *arg_string = "";
891       char *p;
892       int i;
893       
894       tty_printf("\n");
895       if (redisplay )
896         {
897           if (opt.with_colons)
898             {
899               card_status (stdout, serialnobuf, DIM (serialnobuf));
900               fflush (stdout);
901             }
902           else
903             {
904               card_status (NULL, serialnobuf, DIM (serialnobuf));
905               tty_printf("\n");
906             }
907           redisplay = 0;
908         }
909
910       do
911         {
912           xfree (answer);
913           if (have_commands)
914             {
915               if (commands)
916                 {
917                   answer = xstrdup (commands->d);
918                   commands = commands->next;
919                 }
920               else if (opt.batch)
921                 {
922                   answer = xstrdup ("quit");
923                 }
924               else
925                 have_commands = 0;
926             }
927
928             if (!have_commands)
929               {
930                 answer = cpr_get_no_help("cardedit.prompt", _("Command> "));
931                 cpr_kill_prompt();
932             }
933             trim_spaces(answer);
934         }
935       while( *answer == '#' );
936
937       arg_number = 0; /* Yes, here is the init which egcc complains about */
938       if (!*answer)
939         cmd = cmdLIST; /* Default to the list command */
940       else if (*answer == CONTROL_D)
941         cmd = cmdQUIT;
942       else {
943         if ((p=strchr (answer,' ')))
944           {
945             *p++ = 0;
946             trim_spaces (answer);
947             trim_spaces (p);
948             arg_number = atoi(p);
949             arg_string = p;
950           }
951
952         for (i=0; cmds[i].name; i++ )
953           if (!ascii_strcasecmp (answer, cmds[i].name ))
954             break;
955
956         cmd = cmds[i].id;
957       }
958       
959
960       switch (cmd)
961         {
962         case cmdHELP:
963           for (i=0; cmds[i].name; i++ )
964             if (cmds[i].desc)
965               tty_printf("%-10s %s\n", cmds[i].name, _(cmds[i].desc) );
966           break;
967
968         case cmdLIST:
969           redisplay = 1;
970           break;
971
972         case cmdNAME:
973           change_name ();
974           break;
975
976         case cmdURL:
977           change_url ();
978           break;
979
980         case cmdFETCH:
981           fetch_url();
982           break;
983
984         case cmdLOGIN:
985           change_login (arg_string);
986           break;
987
988         case cmdLANG:
989           change_lang ();
990           break;
991
992         case cmdSEX:
993           change_sex ();
994           break;
995
996         case cmdCAFPR:
997           if ( arg_number < 1 || arg_number > 3 )
998             tty_printf ("usage: cafpr N\n"
999                         "       1 <= N <= 3\n");
1000           else
1001             change_cafpr (arg_number);
1002           break;
1003
1004         case cmdFORCESIG:
1005           toggle_forcesig ();
1006           break;
1007
1008         case cmdGENERATE:
1009           generate_card_keys (serialnobuf);
1010           break;
1011
1012         case cmdPASSWD:
1013           change_pin (0);
1014           did_checkpin = 0; /* Need to reset it of course. */
1015           break;
1016
1017         case cmdQUIT:
1018           goto leave;
1019
1020         case cmdNOP:
1021           break;
1022
1023         case cmdINVCMD:
1024         default:
1025           tty_printf ("\n");
1026           tty_printf (_("Invalid command  (try \"help\")\n"));
1027           break;
1028         } /* End command switch. */
1029     } /* End of main menu loop. */
1030
1031  leave:
1032   xfree (answer);
1033 }
1034