* g10.c: New command --card-status.
[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 #include "gpg.h"
29 #include "util.h"
30 #include "i18n.h"
31 #include "ttyio.h"
32 #include "status.h"
33 #include "options.h"
34 #include "main.h"
35 #include "call-agent.h"
36
37
38 /* Change the PIN of a an OpenPGP card.  This is an interactive
39    function. */
40 void
41 change_pin (int chvno)
42 {
43   struct agent_card_info_s info;
44   int rc;
45   int reset_mode = 0;
46
47   rc = agent_learn (&info);
48   if (rc)
49     {
50       log_error (_("OpenPGP card not available: %s\n"),
51                   gpg_strerror (rc));
52       return;
53     }
54   
55   log_info (_("OpenPGP card no. %s detected\n"),
56               info.serialno? info.serialno : "[none]");
57
58   agent_release_card_info (&info);
59
60   if (opt.batch)
61     {
62       log_error (_("sorry, can't do this in batch mode\n"));
63       return;
64     }
65
66   for (;;)
67     {
68       char *answer;
69
70       tty_printf ("\n");
71       tty_printf ("1 - change signature PIN\n"
72                   "2 - change decryption and authentication PIN\n"
73                   "3 - change Admin's PIN\n"
74                   "R - toggle reset retry counter mode\n"
75                   "Q - quit\n");
76       tty_printf ("\n");
77       if (reset_mode)
78         {
79           tty_printf ("Reset Retry Counter mode active\n");
80           tty_printf ("\n");
81         }
82
83       answer = cpr_get("cardutil.change_pin.menu",_("Your selection? "));
84       cpr_kill_prompt();
85       if (strlen (answer) != 1)
86         continue;
87
88       rc = 0;
89       if (reset_mode && *answer == '3')
90         {
91           tty_printf ("Sorry, reset of the Admin PIN's retry counter "
92                       "is not possible.\n");
93         }
94       else if (*answer == '1'  || *answer == '2' || *answer == '3')
95         {
96           rc = agent_scd_change_pin (*answer - '0' + (reset_mode?100:0));
97           if (rc)
98             tty_printf ("Error changing/resetting the PIN: %s\n",
99                         gpg_strerror (rc));
100           else
101             tty_printf ("New PIN successfully set.\n");
102         }
103       else if (*answer == 'r' || *answer == 'R')
104         {
105           reset_mode = !reset_mode;
106         }
107       else if (*answer == 'q' || *answer == 'Q')
108         {
109           break;
110         }
111     }
112
113 }
114
115 static const char *
116 get_manufacturer (unsigned int no)
117 {
118   switch (no)
119     {
120     case 0:
121     case 0xffff: return "test card";
122     case 0x0001: return "PPC Card Systems";
123     default: return "unknown";
124     }
125 }
126
127
128 static void
129 print_sha1_fpr (FILE *fp, const unsigned char *fpr)
130 {
131   int i;
132
133   if (fpr)
134     {
135       for (i=0; i < 20 ; i+=2, fpr += 2 )
136         {
137           if (i == 10 )
138             putc (' ', fp);
139           fprintf (fp, " %02X%02X", *fpr, fpr[1]);
140         }
141     }
142   else
143     fputs (" [none]", fp);
144   putc ('\n', fp);
145 }
146
147
148 static void
149 print_name (FILE *fp, const char *text, const char *name)
150 {
151   fputs (text, fp);
152
153   if (name && *name)
154     print_utf8_string2 (fp, name, strlen (name), '\n');
155   else
156     fputs (_("[not set]"), fp);
157   putc ('\n', fp);
158 }
159
160 static void
161 print_isoname (FILE *fp, const char *text, const char *name)
162 {
163   fputs (text, fp);
164
165   if (name && *name)
166     {
167       char *p, *given, *buf = xstrdup (name);
168
169       given = strstr (buf, "<<");
170       for (p=buf; *p; p++)
171         if (*p == '<')
172           *p = ' ';
173       if (given && given[2])
174         {
175           *given = 0;
176           given += 2;
177           print_utf8_string2 (fp, given, strlen (given), '\n');
178           if (*buf)
179             putc (' ', fp);
180         }
181       print_utf8_string2 (fp, buf, strlen (buf), '\n');
182       xfree (buf);
183     }
184   else
185     fputs (_("[not set]"), fp);
186   putc ('\n', fp);
187 }
188
189
190 /* Print all available information about the current card. */
191 void
192 card_status (FILE *fp)
193 {
194   struct agent_card_info_s info;
195   PKT_public_key *pk = xcalloc (1, sizeof *pk);
196   int rc;
197
198   rc = agent_learn (&info);
199   if (rc)
200     {
201       log_error (_("OpenPGP card not available: %s\n"),
202                   gpg_strerror (rc));
203       return;
204     }
205   
206   fprintf (fp, "Application ID ...: %s\n",
207          info.serialno? info.serialno : "[none]");
208   if (!info.serialno || strncmp (info.serialno, "D27600012401", 12) 
209       || strlen (info.serialno) != 32 )
210     {
211       log_info ("not an OpenPGP card\n");
212       agent_release_card_info (&info);
213     }
214   fprintf (fp, "Version ..........: %.1s%c.%.1s%c\n",
215            info.serialno[12] == '0'?"":info.serialno+12,
216            info.serialno[13],
217            info.serialno[14] == '0'?"":info.serialno+14,
218            info.serialno[15]);
219   fprintf (fp, "Manufacturer .....: %s\n", 
220            get_manufacturer (xtoi_2(info.serialno+16)*256
221                              + xtoi_2 (info.serialno+18)));
222   fprintf (fp, "Serial number ....: %.8s\n", info.serialno+20);
223   
224   print_isoname (fp, "Name of cardholder: ", info.disp_name);
225   print_name (fp, "Language prefs ...: ", info.disp_lang);
226   fprintf (fp,    "Sex ..............: %s\n", info.disp_sex == 1? _("male"):
227            info.disp_sex == 2? _("female") : _("unspecified"));
228   print_name (fp, "URL of public key : ", info.pubkey_url);
229   print_name (fp, "Login data .......: ", info.login_data);
230   fprintf (fp,    "Signature PIN ....: %s\n",
231            info.chv1_cached? _("cached"): _("not cached"));
232   fprintf (fp,    "Max. PIN lengths .: %d %d %d\n",
233            info.chvmaxlen[0], info.chvmaxlen[1], info.chvmaxlen[2]);
234   fprintf (fp,    "PIN retry counter : %d %d %d\n",
235            info.chvretry[0], info.chvretry[1], info.chvretry[2]);
236   fputs ("Signature key ....:", fp);
237   print_sha1_fpr (fp, info.fpr1valid? info.fpr1:NULL);
238   fputs ("Encryption key....:", fp);
239   print_sha1_fpr (fp, info.fpr2valid? info.fpr2:NULL);
240   fputs ("Authentication key:", fp);
241   print_sha1_fpr (fp, info.fpr3valid? info.fpr3:NULL);
242   fputs ("General key info..: ", fp); 
243   if (info.fpr1valid && !get_pubkey_byfprint (pk, info.fpr1, 20))
244     print_pubkey_info (fp, pk);
245   else
246     fputs ("[none]\n", fp);
247   fprintf (fp,    "Signature counter : %lu\n", info.sig_counter);
248   
249   free_public_key (pk);
250   agent_release_card_info (&info);
251 }
252
253
254
255
256
257
258
259
260
261