Update error handling to match gpg-error in CVS.
[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 #include "i18n.h"
36
37 struct list_external_parm_s {
38   FILE *fp;
39   int print_header;
40   int with_colons;
41   int with_chain;
42 };
43
44
45
46 static void
47 print_key_data (KsbaCert cert, FILE *fp)
48 {
49 #if 0  
50   int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
51   int i;
52
53   for(i=0; i < n; i++ ) 
54     {
55       fprintf (fp, "pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) );
56       mpi_print(stdout, pk->pkey[i], 1 );
57       putchar(':');
58       putchar('\n');
59     }
60 #endif
61 }
62
63 static void
64 print_capabilities (KsbaCert cert, FILE *fp)
65 {
66   KsbaError err;
67   unsigned int use;
68
69   err = ksba_cert_get_key_usage (cert, &use);
70   if (err == KSBA_No_Data)
71     {
72       putc ('e', fp);
73       putc ('s', fp);
74       putc ('c', fp);
75       putc ('E', fp);
76       putc ('S', fp);
77       putc ('C', fp);
78       return;
79     }
80   if (err)
81     { 
82       log_error (_("error getting key usage information: %s\n"),
83                  ksba_strerror (err));
84       return;
85     } 
86
87   if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
88     putc ('e', fp);
89   if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
90     putc ('s', fp);
91   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
92     putc ('c', fp);
93   if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
94     putc ('E', fp);
95   if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
96     putc ('S', fp);
97   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
98     putc ('C', fp);
99 }
100
101
102 static void
103 print_time (time_t t, FILE *fp)
104 {
105   if (!t)
106     ;
107   else if ( t == (time_t)(-1) )
108     putc ('?', fp);
109   else
110     fprintf (fp, "%lu", (unsigned long)t);
111 }
112
113
114 /* return an allocated string with the email address extracted from a
115    DN */
116 static char *
117 email_kludge (const char *name)
118 {
119   const unsigned char *p;
120   unsigned char *buf;
121   int n;
122
123   if (strncmp (name, "1.2.840.113549.1.9.1=#", 22))
124     return NULL;
125   /* This looks pretty much like an email address in the subject's DN
126      we use this to add an additional user ID entry.  This way,
127      openSSL generated keys get a nicer and usable listing */
128   name += 22;    
129   for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++)
130     ;
131   if (*p != '#' || !n)
132     return NULL;
133   buf = xtrymalloc (n+3);
134   if (!buf)
135     return NULL; /* oops, out of core */
136   *buf = '<';
137   for (n=1, p=name; *p != '#'; p +=2, n++)
138     buf[n] = xtoi_2 (p);
139   buf[n++] = '>';
140   buf[n] = 0;
141   return buf;
142 }
143
144
145
146
147 /* List one certificate in colon mode */
148 static void
149 list_cert_colon (KsbaCert cert, FILE *fp, int have_secret)
150 {
151   int idx, trustletter = 0;
152   char *p;
153   KsbaSexp sexp;
154   char *fpr;
155
156   fputs (have_secret? "crs:":"crt:", fp);
157   trustletter = 0;
158 #if 0
159   if (is_not_valid (cert))
160     putc ('i', fp);
161   else if ( is_revoked (cert) )
162     putc ('r', fp);
163   else if ( has_expired (cert))
164     putcr ('e', fp);
165   else
166 #endif
167     {
168       trustletter = '?'; /*get_validity_info ( pk, NULL );*/
169       putc (trustletter, fp);
170     }
171
172   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
173   fprintf (fp, ":%u:%d:%s:",
174            /*keylen_of_cert (cert)*/1024,
175            /* pubkey_algo_of_cert (cert)*/1,
176            fpr+24);
177
178   /* we assume --fixed-list-mode for gpgsm */
179   print_time ( ksba_cert_get_validity (cert, 0), fp);
180   putc (':', fp);
181   print_time ( ksba_cert_get_validity (cert, 1), fp);
182   putc (':', fp);
183   /* field 8, serial number: */
184   if ((sexp = ksba_cert_get_serial (cert)))
185     {
186       int len;
187       const unsigned char *s = sexp;
188       
189       if (*s == '(')
190         {
191           s++;
192           for (len=0; *s && *s != ':' && digitp (s); s++)
193             len = len*10 + atoi_1 (s);
194           if (*s == ':')
195             for (s++; len; len--, s++)
196               fprintf (fp,"%02X", *s);
197         }
198       xfree (sexp);
199     }
200   putc (':', fp);
201   /* field 9, ownertrust - not used here */
202   putc (':', fp);
203   /* field 10, old user ID - we use it here for the issuer DN */
204   if ((p = ksba_cert_get_issuer (cert,0)))
205     {
206       print_sanitized_string (fp, p, ':');
207       xfree (p);
208     }
209   putc (':', fp);
210   /* field 11, signature class - not used */ 
211   putc (':', fp);
212   /* field 12, capabilities: */ 
213   print_capabilities (cert, fp);
214   putc (':', fp);
215   putc ('\n', fp);
216
217   /* FPR record */
218   fprintf (fp, "fpr:::::::::%s:::", fpr);
219   xfree (fpr); fpr = NULL;
220   /* print chaining ID (field 13)*/
221   {
222     KsbaCert next;
223     
224     if (!gpgsm_walk_cert_chain (cert, &next))
225       {
226         p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1);
227         fputs (p, fp);
228         xfree (p);
229         ksba_cert_release (next);
230       }
231   }
232   putc (':', fp);
233   putc ('\n', fp);
234
235
236   if (opt.with_key_data)
237     {
238       if ( (p = gpgsm_get_keygrip_hexstring (cert)))
239         {
240           fprintf (fp, "grp:::::::::%s:\n", p);
241           xfree (p);
242         }
243       print_key_data (cert, fp);
244     }
245
246   for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++)
247     {
248       fprintf (fp, "uid:%c::::::::", trustletter);
249       print_sanitized_string (fp, p, ':');
250       putc (':', fp);
251       putc (':', fp);
252       putc ('\n', fp);
253       if (!idx)
254         {
255           /* It would be better to get the faked email address from
256              the keydb.  But as long as we don't have a way to pass
257              the meta data back, we just check it the same way as the
258              code used to create the keybox meta data does */
259           char *pp = email_kludge (p);
260           if (pp)
261             {
262               fprintf (fp, "uid:%c::::::::", trustletter);
263               print_sanitized_string (fp, pp, ':');
264               putc (':', fp);
265               putc (':', fp);
266               putc ('\n', fp);
267               xfree (pp);
268             }
269         }
270       xfree (p);
271     }
272 }
273
274
275 /* List one certificate in standard mode */
276 static void
277 list_cert_std (KsbaCert cert, FILE *fp, int have_secret)
278 {
279   KsbaError kerr;
280   KsbaSexp sexp;
281   char *dn;
282   time_t t;
283   int idx;
284   int is_ca, chainlen;
285   unsigned int kusage;
286   char *string, *p;
287
288   sexp = ksba_cert_get_serial (cert);
289   fputs ("Serial number: ", fp);
290   gpgsm_print_serial (fp, sexp);
291   ksba_free (sexp);
292   putc ('\n', fp);
293
294   dn = ksba_cert_get_issuer (cert, 0);
295   fputs ("       Issuer: ", fp);
296   gpgsm_print_name (fp, dn);
297   ksba_free (dn);
298   putc ('\n', fp);
299   for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
300     {
301       fputs ("          aka: ", fp);
302       gpgsm_print_name (fp, dn);
303       ksba_free (dn);
304       putc ('\n', fp);
305     }
306
307   dn = ksba_cert_get_subject (cert, 0);
308   fputs ("      Subject: ", fp);
309   gpgsm_print_name (fp, dn);
310   ksba_free (dn);
311   putc ('\n', fp);
312   for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
313     {
314       fputs ("          aka: ", fp);
315       gpgsm_print_name (fp, dn);
316       ksba_free (dn);
317       putc ('\n', fp);
318     }
319
320   t = ksba_cert_get_validity (cert, 0);
321   fputs ("     validity: ", fp);
322   gpgsm_print_time (fp, t);
323   fputs (" through ", fp);
324   t = ksba_cert_get_validity (cert, 1);
325   gpgsm_print_time (fp, t);
326   putc ('\n', fp);
327
328   kerr = ksba_cert_get_key_usage (cert, &kusage);
329   if (kerr != KSBA_No_Data)
330     {
331       fputs ("    key usage:", fp);
332       if (kerr)
333         fprintf (fp, " [error: %s]", ksba_strerror (kerr));
334       else
335         {
336           if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
337             fputs (" digitalSignature", fp);
338           if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))  
339             fputs (" nonRepudiation", fp);
340           if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT)) 
341             fputs (" keyEncipherment", fp);
342           if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
343             fputs (" dataEncipherment", fp);
344           if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))    
345             fputs (" keyAgreement", fp);
346           if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
347             fputs (" certSign", fp);
348           if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))  
349             fputs (" crlSign", fp);
350           if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
351             fputs (" encipherOnly", fp);
352           if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))  
353             fputs (" decipherOnly", fp);
354         }
355       putc ('\n', fp);
356     }
357
358   kerr = ksba_cert_get_cert_policies (cert, &string);
359   if (kerr != KSBA_No_Data)
360     {
361       fputs ("     policies: ", fp);
362       if (kerr)
363         fprintf (fp, "[error: %s]", ksba_strerror (kerr));
364       else
365         {
366           for (p=string; *p; p++)
367             {
368               if (*p == '\n')
369                 *p = ',';
370             }
371           print_sanitized_string (fp, string, 0);
372           xfree (string);
373         }
374       putc ('\n', fp);
375     }
376
377   kerr = ksba_cert_is_ca (cert, &is_ca, &chainlen);
378   if (kerr || is_ca)
379     {
380       fputs (" chain length: ", fp);
381       if (kerr)
382         fprintf (fp, "[error: %s]", ksba_strerror (kerr));
383       else if (chainlen == -1)
384         fputs ("unlimited", fp);
385       else
386         fprintf (fp, "%d", chainlen);
387       putc ('\n', fp);
388     }
389
390
391   dn = gpgsm_get_fingerprint_string (cert, 0);
392   fprintf (fp, "  fingerprint: %s\n", dn?dn:"error");
393   xfree (dn);
394 }
395
396 /* Same as standard mode mode list all certifying certts too */
397 static void
398 list_cert_chain (KsbaCert cert, FILE *fp)
399 {
400   KsbaCert next = NULL;
401
402   list_cert_std (cert, fp, 0);
403   ksba_cert_ref (cert);
404   while (!gpgsm_walk_cert_chain (cert, &next))
405     {
406       ksba_cert_release (cert);
407       fputs ("Certified by\n", fp);
408       list_cert_std (next, fp, 0);
409       cert = next;
410     }
411   ksba_cert_release (cert);
412   putc ('\n', fp);
413 }
414
415
416 \f
417 /* List all internal keys or just the key given as NAMES.
418  */
419 static void
420 list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
421 {
422   KEYDB_HANDLE hd;
423   KEYDB_SEARCH_DESC *desc = NULL;
424   STRLIST sl;
425   int ndesc;
426   KsbaCert cert = NULL;
427   int rc=0;
428   const char *lastresname, *resname;
429   int have_secret;
430
431   hd = keydb_new (0);
432   if (!hd)
433     {
434       log_error ("keydb_new failed\n");
435       goto leave;
436     }
437
438   if (!names)
439     ndesc = 1;
440   else
441     {
442       for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) 
443         ;
444     }
445
446   desc = xtrycalloc (ndesc, sizeof *desc);
447   if (!ndesc)
448     {
449       log_error ("out of core\n");
450       goto leave;
451     }
452
453   if (!names)
454     desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
455   else 
456     {
457       for (ndesc=0, sl=names; sl; sl = sl->next) 
458         {
459           rc = keydb_classify_name (sl->d, desc+ndesc);
460           if (rc)
461             {
462               log_error ("key `%s' not found: %s\n",
463                          sl->d, gnupg_strerror (rc));
464               rc = 0;
465             }
466           else
467             ndesc++;
468         }
469       
470     }
471
472   /* it would be nice to see which of the given users did actually
473      match one in the keyring.  To implement this we need to have a
474      found flag for each entry in desc and to set this we must check
475      all those entries after a match to mark all matched one -
476      currently we stop at the first match.  To do this we need an
477      extra flag to enable this feature so */
478
479   lastresname = NULL;
480   while (!(rc = keydb_search (hd, desc, ndesc)))
481     {
482       if (!names) 
483         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
484
485       rc = keydb_get_cert (hd, &cert);
486       if (rc) 
487         {
488           log_error ("keydb_get_cert failed: %s\n", gnupg_strerror (rc));
489           goto leave;
490         }
491       
492       resname = keydb_get_resource_name (hd);
493       
494       if (lastresname != resname ) 
495         {
496           int i;
497           
498           if (ctrl->no_server)
499             {
500               fprintf (fp, "%s\n", resname );
501               for (i=strlen(resname); i; i-- )
502                 putchar('-');
503               putc ('\n', fp);
504               lastresname = resname;
505             }
506         }
507
508       have_secret = 0;
509       if (mode)
510         {
511           char *p = gpgsm_get_keygrip_hexstring (cert);
512           if (p)
513             {
514               if (!gpgsm_agent_havekey (p))
515                 have_secret = 1;
516               xfree (p);
517             }
518         }
519
520       if (!mode
521           || ((mode & 1) && !have_secret)
522           || ((mode & 2) && have_secret)  )
523         {
524           if (ctrl->with_colons)
525             list_cert_colon (cert, fp, have_secret);
526           else if (ctrl->with_chain)
527             list_cert_chain (cert, fp);
528           else
529             {
530               list_cert_std (cert, fp, have_secret);
531               putc ('\n', fp);
532             }
533         }
534       ksba_cert_release (cert); 
535       cert = NULL;
536     }
537   if (rc && rc != -1)
538     log_error ("keydb_search failed: %s\n", gnupg_strerror (rc));
539   
540  leave:
541   ksba_cert_release (cert);
542   xfree (desc);
543   keydb_release (hd);
544 }
545
546
547
548 static void
549 list_external_cb (void *cb_value, KsbaCert cert)
550 {
551   struct list_external_parm_s *parm = cb_value;
552
553   if (keydb_store_cert (cert, 1, NULL))
554     log_error ("error storing certificate as ephemeral\n");
555
556   if (parm->print_header)
557     {
558       const char *resname = "[external keys]";
559       int i;
560
561       fprintf (parm->fp, "%s\n", resname );
562       for (i=strlen(resname); i; i-- )
563         putchar('-');
564       putc ('\n', parm->fp);
565       parm->print_header = 0;
566     }
567
568   if (parm->with_colons)
569     list_cert_colon (cert, parm->fp, 0);
570   else if (parm->with_chain)
571     list_cert_chain (cert, parm->fp);
572   else
573     {
574       list_cert_std (cert, parm->fp, 0);
575       putc ('\n', parm->fp);
576     }
577 }
578
579
580 /* List external keys similar to internal one.  Note: mode does not
581    make sense here because it would be unwise to list external secret
582    keys */
583 static void
584 list_external_keys (CTRL ctrl, STRLIST names, FILE *fp)
585 {
586   int rc;
587   struct list_external_parm_s parm;
588
589   parm.fp = fp;
590   parm.print_header = ctrl->no_server;
591   parm.with_colons = ctrl->with_colons;
592   parm.with_chain = ctrl->with_chain;
593
594   rc = gpgsm_dirmngr_lookup (ctrl, names, list_external_cb, &parm);
595   if (rc)
596     log_error ("listing external keys failed: %s\n", gnupg_strerror (rc));
597 }
598
599 /* List all keys or just the key given as NAMES.
600    MODE controls the operation mode: 
601     Bit 0-2:
602       0 = list all public keys but don't flag secret ones
603       1 = list only public keys
604       2 = list only secret keys
605       3 = list secret and public keys
606     Bit 6: list internal keys
607     Bit 7: list external keys
608  */
609 void
610 gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
611 {
612   if ((mode & (1<<6)))
613       list_internal_keys (ctrl, names, fp, (mode & 3));
614   if ((mode & (1<<7)))
615       list_external_keys (ctrl, names, fp); 
616 }