* keylist.c (list_cert_colon): Fixed listing of crt record; the
[gnupg.git] / sm / keylist.c
1 /* keylist.c
2  * Copyright (C) 1998, 1999, 2000, 2001 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 <unistd.h> 
27 #include <time.h>
28 #include <assert.h>
29
30 #include <gcrypt.h>
31 #include <ksba.h>
32
33 #include "gpgsm.h"
34 #include "keydb.h"
35
36
37
38
39 static void
40 print_key_data (KsbaCert cert, FILE *fp)
41 {
42 #if 0  
43   int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
44   int i;
45
46   for(i=0; i < n; i++ ) 
47     {
48       fprintf (fp, "pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) );
49       mpi_print(stdout, pk->pkey[i], 1 );
50       putchar(':');
51       putchar('\n');
52     }
53 #endif
54 }
55
56 static void
57 print_capabilities (KsbaCert cert, FILE *fp)
58 {
59   putc ('e', fp);
60   putc ('s', fp);
61   putc ('c', fp);
62   putc ('E', fp);
63   putc ('S', fp);
64   putc ('C', fp);
65 }
66
67
68 static void
69 print_time (time_t t, FILE *fp)
70 {
71   if (!t)
72     ;
73   else if ( t == (time_t)(-1) )
74     putc ('?', fp);
75   else
76     fprintf (fp, "%lu", (unsigned long)t);
77 }
78
79
80 /* return an allocated string with the email address extracted from a
81    DN */
82 static char *
83 email_kludge (const char *name)
84 {
85   const unsigned char *p;
86   unsigned char *buf;
87   int n;
88
89   if (strncmp (name, "1.2.840.113549.1.9.1=#", 22))
90     return NULL;
91   /* This looks pretty much like an email address in the subject's DN
92      we use this to add an additional user ID entry.  This way,
93      openSSL generated keys get a nicer and usable listing */
94   name += 22;    
95   for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++)
96     ;
97   if (*p != '#' || !n)
98     return NULL;
99   buf = xtrymalloc (n+3);
100   if (!buf)
101     return NULL; /* oops, out of core */
102   *buf = '<';
103   for (n=1, p=name; *p != '#'; p +=2, n++)
104     buf[n] = xtoi_2 (p);
105   buf[n++] = '>';
106   buf[n] = 0;
107   return buf;
108 }
109
110
111
112
113 /* List one certificate in colon mode */
114 static void
115 list_cert_colon (KsbaCert cert, FILE *fp, int have_secret)
116 {
117   int idx, trustletter = 0;
118   char *p;
119   KsbaSexp sexp;
120
121   fputs (have_secret? "crs:":"crt:", fp);
122   trustletter = 0;
123 #if 0
124   if (is_not_valid (cert))
125     putc ('i', fp);
126   else if ( is_revoked (cert) )
127     putc ('r', fp);
128   else if ( has_expired (cert))
129     putcr ('e', fp);
130   else
131 #endif
132     {
133       trustletter = '?'; /*get_validity_info ( pk, NULL );*/
134       putc (trustletter, fp);
135     }
136
137   fprintf (fp, ":%u:%d::",
138            /*keylen_of_cert (cert)*/1024,
139            /* pubkey_algo_of_cert (cert)*/1);
140
141   /* we assume --fixed-list-mode for gpgsm */
142   print_time ( ksba_cert_get_validity (cert, 0), fp);
143   putc (':', fp);
144   print_time ( ksba_cert_get_validity (cert, 1), fp);
145   putc (':', fp);
146   /* field 8, serial number: */
147   if ((sexp = ksba_cert_get_serial (cert)))
148     {
149       int len;
150       const unsigned char *s = sexp;
151       
152       if (*s == '(')
153         {
154           s++;
155           for (len=0; *s && *s != ':' && digitp (s); s++)
156             len = len*10 + atoi_1 (s);
157           if (*s == ':')
158             for (s++; len; len--, s++)
159               fprintf (fp,"%02X", *s);
160         }
161       xfree (sexp);
162     }
163   putc (':', fp);
164   /* field 9, ownertrust - not used here */
165   putc (':', fp);
166   /* field 10, old user ID - we use it here for the issuer DN */
167   if ((p = ksba_cert_get_issuer (cert,0)))
168     {
169       print_sanitized_string (fp, p, ':');
170       xfree (p);
171     }
172   putc (':', fp);
173   /* field 11, signature class - not used */ 
174   putc (':', fp);
175   /* field 12, capabilities: */ 
176   print_capabilities (cert, fp);
177   putc (':', fp);
178   putc ('\n', fp);
179
180   /* FPR record */
181   p = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
182   fprintf (fp, "fpr:::::::::%s:::", p);
183   xfree (p);
184   /* print chaining ID (field 13)*/
185   {
186     KsbaCert next;
187     
188     if (!gpgsm_walk_cert_chain (cert, &next))
189       {
190         p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1);
191         fputs (p, fp);
192         xfree (p);
193         ksba_cert_release (next);
194       }
195   }
196   putc (':', fp);
197   putc ('\n', fp);
198
199
200   if (opt.with_key_data)
201     {
202       if ( (p = gpgsm_get_keygrip_hexstring (cert)))
203         {
204           fprintf (fp, "grp:::::::::%s:\n", p);
205           xfree (p);
206         }
207       print_key_data (cert, fp);
208     }
209
210   for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++)
211     {
212       fprintf (fp, "uid:%c::::::::", trustletter);
213       print_sanitized_string (fp, p, ':');
214       putc (':', fp);
215       putc (':', fp);
216       putc ('\n', fp);
217       if (!idx)
218         {
219           /* It would be better to get the faked email address from
220              the keydb.  But as long as we don't have a way to pass
221              the meta data back, we just check it the same way as the
222              code used to create the keybox meta data does */
223           char *pp = email_kludge (p);
224           if (pp)
225             {
226               fprintf (fp, "uid:%c::::::::", trustletter);
227               print_sanitized_string (fp, pp, ':');
228               putc (':', fp);
229               putc (':', fp);
230               putc ('\n', fp);
231               xfree (pp);
232             }
233         }
234       xfree (p);
235     }
236 }
237
238
239
240 \f
241 /* List all keys or just the key given as NAMES.
242    MODE controls the operation mode: 
243       0 = list all public keys but don't flag secret ones
244       1 = list only public keys
245       2 = list only secret keys
246       3 = list secret and public keys
247  */
248 void
249 gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
250 {
251   KEYDB_HANDLE hd;
252   KEYDB_SEARCH_DESC *desc = NULL;
253   STRLIST sl;
254   int ndesc;
255   KsbaCert cert = NULL;
256   int rc=0;
257   const char *lastresname, *resname;
258   int have_secret;
259
260   hd = keydb_new (0);
261   if (!hd)
262     {
263       log_error ("keydb_new failed\n");
264       goto leave;
265     }
266
267   if (!names)
268     ndesc = 1;
269   else
270     {
271       for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) 
272         ;
273     }
274
275   desc = xtrycalloc (ndesc, sizeof *desc);
276   if (!ndesc)
277     {
278       log_error ("out of core\n");
279       goto leave;
280     }
281
282   if (!names)
283     desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
284   else 
285     {
286       for (ndesc=0, sl=names; sl; sl = sl->next) 
287         {
288           rc = keydb_classify_name (sl->d, desc+ndesc);
289           if (rc)
290             {
291               log_error ("key `%s' not found: %s\n",
292                          sl->d, gnupg_strerror (rc));
293               rc = 0;
294             }
295           else
296             ndesc++;
297         }
298       
299     }
300
301   /* it would be nice to see which of the given users did actually
302      match one in the keyring.  To implement this we need to have a
303      found flag for each entry in desc and to set this we must check
304      all those entries after a match to mark all matched one -
305      currently we stop at the first match.  To do this we need an
306      extra flag to enable this feature so */
307
308   lastresname = NULL;
309   while (!(rc = keydb_search (hd, desc, ndesc)))
310     {
311       if (!names) 
312         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
313
314       rc = keydb_get_cert (hd, &cert);
315       if (rc) 
316         {
317           log_error ("keydb_get_cert failed: %s\n", gnupg_strerror (rc));
318           goto leave;
319         }
320       
321       resname = keydb_get_resource_name (hd);
322       
323       if (lastresname != resname ) 
324         {
325           int i;
326           
327           if (ctrl->no_server)
328             {
329               fprintf (fp, "%s\n", resname );
330               for (i=strlen(resname); i; i-- )
331                 putchar('-');
332               putc ('\n', fp);
333               lastresname = resname;
334             }
335         }
336
337       have_secret = 0;
338       if (mode)
339         {
340           char *p = gpgsm_get_keygrip_hexstring (cert);
341           if (p)
342             {
343               if (!gpgsm_agent_havekey (p))
344                 have_secret = 1;
345               xfree (p);
346             }
347         }
348
349       if (!mode
350           || ((mode & 1) && !have_secret)
351           || ((mode & 2) && have_secret)  )
352         {
353           if (ctrl->with_colons)
354             list_cert_colon (cert, fp, have_secret);
355           else
356             list_cert_colon (cert, fp, have_secret);
357         }
358       ksba_cert_release (cert); 
359       cert = NULL;
360     }
361   if (rc && rc != -1)
362     log_error ("keydb_search failed: %s\n", gnupg_strerror (rc));
363   
364  leave:
365   ksba_cert_release (cert);
366   xfree (desc);
367   keydb_release (hd);
368 }
369
370
371