Preparing for a release
[gnupg.git] / sm / keylist.c
1 /* keylist.c
2  * Copyright (C) 1998, 1999, 2000, 2001, 2003,
3  *               2004 Free Software Foundation, Inc.
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 2 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, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <unistd.h> 
28 #include <time.h>
29 #include <assert.h>
30
31 #include "gpgsm.h"
32
33 #include <gcrypt.h>
34 #include <ksba.h>
35
36 #include "keydb.h"
37 #include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */
38 #include "i18n.h"
39
40 struct list_external_parm_s {
41   ctrl_t ctrl;
42   FILE *fp;
43   int print_header;
44   int with_colons;
45   int with_chain;
46 };
47
48
49 /* This table is to map Extended Key Usage OIDs to human readable
50    names.  */
51 struct {
52   const char *oid;
53   const char *name;
54 } key_purpose_map[] = {
55   { "1.3.6.1.5.5.7.3.1",  "serverAuth" },
56   { "1.3.6.1.5.5.7.3.2",  "clientAuth" },          
57   { "1.3.6.1.5.5.7.3.3",  "codeSigning" },      
58   { "1.3.6.1.5.5.7.3.4",  "emailProtection" },     
59   { "1.3.6.1.5.5.7.3.5",  "ipsecEndSystem" }, 
60   { "1.3.6.1.5.5.7.3.6",  "ipsecTunnel" },  
61   { "1.3.6.1.5.5.7.3.7",  "ipsecUser" },     
62   { "1.3.6.1.5.5.7.3.8",  "timeStamping" },       
63   { "1.3.6.1.5.5.7.3.9",  "ocspSigning" },    
64   { "1.3.6.1.5.5.7.3.10", "dvcs" },      
65   { "1.3.6.1.5.5.7.3.11", "sbgpCertAAServerAuth" },
66   { "1.3.6.1.5.5.7.3.13", "eapOverPPP" },
67   { "1.3.6.1.5.5.7.3.14", "wlanSSID" },       
68   { NULL, NULL }
69 };
70
71
72 static void
73 print_key_data (ksba_cert_t cert, FILE *fp)
74 {
75 #if 0  
76   int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
77   int i;
78
79   for(i=0; i < n; i++ ) 
80     {
81       fprintf (fp, "pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) );
82       mpi_print(stdout, pk->pkey[i], 1 );
83       putchar(':');
84       putchar('\n');
85     }
86 #endif
87 }
88
89 static void
90 print_capabilities (ksba_cert_t cert, FILE *fp)
91 {
92   gpg_error_t err;
93   unsigned int use;
94
95   err = ksba_cert_get_key_usage (cert, &use);
96   if (gpg_err_code (err) == GPG_ERR_NO_DATA)
97     {
98       putc ('e', fp);
99       putc ('s', fp);
100       putc ('c', fp);
101       putc ('E', fp);
102       putc ('S', fp);
103       putc ('C', fp);
104       return;
105     }
106   if (err)
107     { 
108       log_error (_("error getting key usage information: %s\n"),
109                  gpg_strerror (err));
110       return;
111     } 
112
113   if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
114     putc ('e', fp);
115   if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
116     putc ('s', fp);
117   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
118     putc ('c', fp);
119   if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
120     putc ('E', fp);
121   if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
122     putc ('S', fp);
123   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
124     putc ('C', fp);
125 }
126
127
128 static void
129 print_time (gnupg_isotime_t t, FILE *fp)
130 {
131   if (!t || !*t)
132     ;
133   else 
134     fputs (t, fp);
135 }
136
137
138 /* return an allocated string with the email address extracted from a
139    DN */
140 static char *
141 email_kludge (const char *name)
142 {
143   const unsigned char *p;
144   unsigned char *buf;
145   int n;
146
147   if (strncmp (name, "1.2.840.113549.1.9.1=#", 22))
148     return NULL;
149   /* This looks pretty much like an email address in the subject's DN
150      we use this to add an additional user ID entry.  This way,
151      openSSL generated keys get a nicer and usable listing */
152   name += 22;    
153   for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++)
154     ;
155   if (*p != '#' || !n)
156     return NULL;
157   buf = xtrymalloc (n+3);
158   if (!buf)
159     return NULL; /* oops, out of core */
160   *buf = '<';
161   for (n=1, p=name; *p != '#'; p +=2, n++)
162     buf[n] = xtoi_2 (p);
163   buf[n++] = '>';
164   buf[n] = 0;
165   return buf;
166 }
167
168
169
170
171 /* List one certificate in colon mode */
172 static void
173 list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
174                  FILE *fp, int have_secret)
175 {
176   int idx;
177   char truststring[2];
178   char *p;
179   ksba_sexp_t sexp;
180   char *fpr;
181   ksba_isotime_t t;
182   gpg_error_t valerr;
183
184   if (ctrl->with_validation)
185     valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL);
186   else
187     valerr = 0;
188
189   fputs (have_secret? "crs:":"crt:", fp);
190   truststring[0] = 0;
191   truststring[1] = 0;
192   if ((validity & VALIDITY_REVOKED)
193       || gpg_err_code (valerr) == GPG_ERR_CERT_REVOKED)
194     *truststring = 'r';
195   else if (gpg_err_code (valerr) == GPG_ERR_CERT_EXPIRED)
196     *truststring = 'e';
197   else if (valerr)
198     *truststring = 'i';
199   
200   if (*truststring)
201     fputs (truststring, fp);
202
203   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
204   fprintf (fp, ":%u:%d:%s:",
205            /*keylen_of_cert (cert)*/1024,
206            /* pubkey_algo_of_cert (cert)*/1,
207            fpr+24);
208
209   /* we assume --fixed-list-mode for gpgsm */
210   ksba_cert_get_validity (cert, 0, t);
211   print_time (t, fp);
212   putc (':', fp);
213   ksba_cert_get_validity (cert, 1, t);
214   print_time ( t, fp);
215   putc (':', fp);
216   /* field 8, serial number: */
217   if ((sexp = ksba_cert_get_serial (cert)))
218     {
219       int len;
220       const unsigned char *s = sexp;
221       
222       if (*s == '(')
223         {
224           s++;
225           for (len=0; *s && *s != ':' && digitp (s); s++)
226             len = len*10 + atoi_1 (s);
227           if (*s == ':')
228             for (s++; len; len--, s++)
229               fprintf (fp,"%02X", *s);
230         }
231       xfree (sexp);
232     }
233   putc (':', fp);
234   /* field 9, ownertrust - not used here */
235   putc (':', fp);
236   /* field 10, old user ID - we use it here for the issuer DN */
237   if ((p = ksba_cert_get_issuer (cert,0)))
238     {
239       print_sanitized_string (fp, p, ':');
240       xfree (p);
241     }
242   putc (':', fp);
243   /* field 11, signature class - not used */ 
244   putc (':', fp);
245   /* field 12, capabilities: */ 
246   print_capabilities (cert, fp);
247   putc (':', fp);
248   putc ('\n', fp);
249
250   /* FPR record */
251   fprintf (fp, "fpr:::::::::%s:::", fpr);
252   /* print chaining ID (field 13)*/
253   {
254     ksba_cert_t next;
255     int rc;
256     
257     rc = gpgsm_walk_cert_chain (cert, &next);
258     if (!rc) /* We known the issuer's certificate. */
259       {
260         p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1);
261         fputs (p, fp);
262         xfree (p);
263         ksba_cert_release (next);
264       }
265     else if (rc == -1)  /* We reached the root certificate. */
266       {
267         fputs (fpr, fp);
268       }
269   }
270   putc (':', fp);
271   putc ('\n', fp);
272   xfree (fpr); fpr = NULL;
273
274
275   if (opt.with_key_data)
276     {
277       if ( (p = gpgsm_get_keygrip_hexstring (cert)))
278         {
279           fprintf (fp, "grp:::::::::%s:\n", p);
280           xfree (p);
281         }
282       print_key_data (cert, fp);
283     }
284
285   for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++)
286     {
287       fprintf (fp, "uid:%s::::::::", truststring);
288       print_sanitized_string (fp, p, ':');
289       putc (':', fp);
290       putc (':', fp);
291       putc ('\n', fp);
292       if (!idx)
293         {
294           /* It would be better to get the faked email address from
295              the keydb.  But as long as we don't have a way to pass
296              the meta data back, we just check it the same way as the
297              code used to create the keybox meta data does */
298           char *pp = email_kludge (p);
299           if (pp)
300             {
301               fprintf (fp, "uid:%s::::::::", truststring);
302               print_sanitized_string (fp, pp, ':');
303               putc (':', fp);
304               putc (':', fp);
305               putc ('\n', fp);
306               xfree (pp);
307             }
308         }
309       xfree (p);
310     }
311 }
312
313
314 /* List one certificate in standard mode */
315 static void
316 list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret,
317                int with_validation)
318 {
319   gpg_error_t err;
320   ksba_sexp_t sexp;
321   char *dn;
322   ksba_isotime_t t;
323   int idx, i;
324   int is_ca, chainlen;
325   unsigned int kusage;
326   char *string, *p, *pend;
327
328   sexp = ksba_cert_get_serial (cert);
329   fputs ("Serial number: ", fp);
330   gpgsm_print_serial (fp, sexp);
331   ksba_free (sexp);
332   putc ('\n', fp);
333
334   dn = ksba_cert_get_issuer (cert, 0);
335   fputs ("       Issuer: ", fp);
336   gpgsm_print_name (fp, dn);
337   ksba_free (dn);
338   putc ('\n', fp);
339   for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
340     {
341       fputs ("          aka: ", fp);
342       gpgsm_print_name (fp, dn);
343       ksba_free (dn);
344       putc ('\n', fp);
345     }
346
347   dn = ksba_cert_get_subject (cert, 0);
348   fputs ("      Subject: ", fp);
349   gpgsm_print_name (fp, dn);
350   ksba_free (dn);
351   putc ('\n', fp);
352   for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
353     {
354       fputs ("          aka: ", fp);
355       gpgsm_print_name (fp, dn);
356       ksba_free (dn);
357       putc ('\n', fp);
358     }
359
360   ksba_cert_get_validity (cert, 0, t);
361   fputs ("     validity: ", fp);
362   gpgsm_print_time (fp, t);
363   fputs (" through ", fp);
364   ksba_cert_get_validity (cert, 1, t);
365   gpgsm_print_time (fp, t);
366   putc ('\n', fp);
367
368   err = ksba_cert_get_key_usage (cert, &kusage);
369   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
370     {
371       fputs ("    key usage:", fp);
372       if (err)
373         fprintf (fp, " [error: %s]", gpg_strerror (err));
374       else
375         {
376           if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
377             fputs (" digitalSignature", fp);
378           if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))  
379             fputs (" nonRepudiation", fp);
380           if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT)) 
381             fputs (" keyEncipherment", fp);
382           if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
383             fputs (" dataEncipherment", fp);
384           if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))    
385             fputs (" keyAgreement", fp);
386           if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
387             fputs (" certSign", fp);
388           if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))  
389             fputs (" crlSign", fp);
390           if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
391             fputs (" encipherOnly", fp);
392           if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))  
393             fputs (" decipherOnly", fp);
394         }
395       putc ('\n', fp);
396     }
397
398   err = ksba_cert_get_ext_key_usages (cert, &string);
399   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
400     { 
401       fputs ("ext key usage: ", fp);
402       if (err)
403         fprintf (fp, "[error: %s]", gpg_strerror (err));
404       else
405         {
406           p = string;
407           while (p && (pend=strchr (p, ':')))
408             {
409               *pend++ = 0;
410               for (i=0; key_purpose_map[i].oid; i++)
411                 if ( !strcmp (key_purpose_map[i].oid, p) )
412                   break;
413               fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
414               p = pend;
415               if (*p != 'C')
416                 fputs (" (suggested)", fp);
417               if ((p = strchr (p, '\n')))
418                 {
419                   p++;
420                   fputs (", ", fp);
421                 }
422             }
423           xfree (string);
424         }
425       putc ('\n', fp);
426     }
427
428   err = ksba_cert_get_cert_policies (cert, &string);
429   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
430     {
431       fputs ("     policies: ", fp);
432       if (err)
433         fprintf (fp, "[error: %s]", gpg_strerror (err));
434       else
435         {
436           for (p=string; *p; p++)
437             {
438               if (*p == '\n')
439                 *p = ',';
440             }
441           print_sanitized_string (fp, string, 0);
442           xfree (string);
443         }
444       putc ('\n', fp);
445     }
446
447   err = ksba_cert_is_ca (cert, &is_ca, &chainlen);
448   if (err || is_ca)
449     {
450       fputs (" chain length: ", fp);
451       if (err)
452         fprintf (fp, "[error: %s]", gpg_strerror (err));
453       else if (chainlen == -1)
454         fputs ("unlimited", fp);
455       else
456         fprintf (fp, "%d", chainlen);
457       putc ('\n', fp);
458     }
459
460   if (opt.with_md5_fingerprint)
461     {
462       dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5);
463       fprintf (fp, "      md5 fpr: %s\n", dn?dn:"error");
464       xfree (dn);
465     }
466
467   dn = gpgsm_get_fingerprint_string (cert, 0);
468   fprintf (fp, "  fingerprint: %s\n", dn?dn:"error");
469   xfree (dn);
470
471   if (with_validation)
472     {
473       err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp);
474       if (!err)
475         fprintf (fp, "  [certificate is good]\n");
476       else
477         fprintf (fp, "  [certificate is bad: %s]\n", gpg_strerror (err));
478     }
479 }
480
481
482 /* Same as standard mode mode list all certifying certs too. */
483 static void
484 list_cert_chain (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int with_validation)
485 {
486   ksba_cert_t next = NULL;
487
488   list_cert_std (ctrl, cert, fp, 0, with_validation);
489   ksba_cert_ref (cert);
490   while (!gpgsm_walk_cert_chain (cert, &next))
491     {
492       ksba_cert_release (cert);
493       fputs ("Certified by\n", fp);
494       list_cert_std (ctrl, next, fp, 0, with_validation);
495       cert = next;
496     }
497   ksba_cert_release (cert);
498   putc ('\n', fp);
499 }
500
501
502 \f
503 /* List all internal keys or just the key given as NAMES.
504  */
505 static gpg_error_t
506 list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
507 {
508   KEYDB_HANDLE hd;
509   KEYDB_SEARCH_DESC *desc = NULL;
510   STRLIST sl;
511   int ndesc;
512   ksba_cert_t cert = NULL;
513   gpg_error_t rc = 0;
514   const char *lastresname, *resname;
515   int have_secret;
516
517   hd = keydb_new (0);
518   if (!hd)
519     {
520       log_error ("keydb_new failed\n");
521       rc = gpg_error (GPG_ERR_GENERAL);
522       goto leave;
523     }
524
525   if (!names)
526     ndesc = 1;
527   else
528     {
529       for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) 
530         ;
531     }
532
533   desc = xtrycalloc (ndesc, sizeof *desc);
534   if (!ndesc)
535     {
536       rc = gpg_error_from_errno (errno);
537       log_error ("out of core\n");
538       goto leave;
539     }
540
541   if (!names)
542     desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
543   else 
544     {
545       for (ndesc=0, sl=names; sl; sl = sl->next) 
546         {
547           rc = keydb_classify_name (sl->d, desc+ndesc);
548           if (rc)
549             {
550               log_error ("key `%s' not found: %s\n",
551                          sl->d, gpg_strerror (rc));
552               rc = 0;
553             }
554           else
555             ndesc++;
556         }
557       
558     }
559
560   /* It would be nice to see which of the given users did actually
561      match one in the keyring.  To implement this we need to have a
562      found flag for each entry in desc and to set this we must check
563      all those entries after a match to mark all matched one -
564      currently we stop at the first match.  To do this we need an
565      extra flag to enable this feature so */
566
567   lastresname = NULL;
568   while (!(rc = keydb_search (hd, desc, ndesc)))
569     {
570       unsigned int validity;
571
572       if (!names) 
573         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
574
575       rc = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &validity);
576       if (rc)
577         {
578           log_error ("keydb_get_flags failed: %s\n", gpg_strerror (rc));
579           goto leave;
580         }
581       rc = keydb_get_cert (hd, &cert);
582       if (rc) 
583         {
584           log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
585           goto leave;
586         }
587       
588       resname = keydb_get_resource_name (hd);
589       
590       if (lastresname != resname ) 
591         {
592           int i;
593           
594           if (ctrl->no_server)
595             {
596               fprintf (fp, "%s\n", resname );
597               for (i=strlen(resname); i; i-- )
598                 putchar('-');
599               putc ('\n', fp);
600               lastresname = resname;
601             }
602         }
603
604       have_secret = 0;
605       if (mode)
606         {
607           char *p = gpgsm_get_keygrip_hexstring (cert);
608           if (p)
609             {
610               rc = gpgsm_agent_havekey (p);
611               if (!rc)
612                 have_secret = 1;
613               else if ( gpg_err_code (rc) != GPG_ERR_NO_SECKEY)
614                 goto leave;
615               rc = 0;
616               xfree (p);
617             }
618         }
619
620       if (!mode
621           || ((mode & 1) && !have_secret)
622           || ((mode & 2) && have_secret)  )
623         {
624           if (ctrl->with_colons)
625             list_cert_colon (ctrl, cert, validity, fp, have_secret);
626           else if (ctrl->with_chain)
627             list_cert_chain (ctrl, cert, fp, ctrl->with_validation);
628           else
629             {
630               list_cert_std (ctrl, cert, fp, have_secret,
631                              ctrl->with_validation);
632               putc ('\n', fp);
633             }
634         }
635       ksba_cert_release (cert); 
636       cert = NULL;
637     }
638   if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1 )
639     rc = 0;
640   if (rc)
641     log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
642   
643  leave:
644   ksba_cert_release (cert);
645   xfree (desc);
646   keydb_release (hd);
647   return rc;
648 }
649
650
651
652 static void
653 list_external_cb (void *cb_value, ksba_cert_t cert)
654 {
655   struct list_external_parm_s *parm = cb_value;
656
657   if (keydb_store_cert (cert, 1, NULL))
658     log_error ("error storing certificate as ephemeral\n");
659
660   if (parm->print_header)
661     {
662       const char *resname = "[external keys]";
663       int i;
664
665       fprintf (parm->fp, "%s\n", resname );
666       for (i=strlen(resname); i; i-- )
667         putchar('-');
668       putc ('\n', parm->fp);
669       parm->print_header = 0;
670     }
671
672   if (parm->with_colons)
673     list_cert_colon (parm->ctrl, cert, 0, parm->fp, 0);
674   else if (parm->with_chain)
675     list_cert_chain (parm->ctrl, cert, parm->fp, 0);
676   else
677     {
678       list_cert_std (parm->ctrl, cert, parm->fp, 0, 0);
679       putc ('\n', parm->fp);
680     }
681 }
682
683
684 /* List external keys similar to internal one.  Note: mode does not
685    make sense here because it would be unwise to list external secret
686    keys */
687 static gpg_error_t
688 list_external_keys (CTRL ctrl, STRLIST names, FILE *fp)
689 {
690   int rc;
691   struct list_external_parm_s parm;
692
693   parm.fp = fp;
694   parm.ctrl = ctrl,
695   parm.print_header = ctrl->no_server;
696   parm.with_colons = ctrl->with_colons;
697   parm.with_chain = ctrl->with_chain;
698
699   rc = gpgsm_dirmngr_lookup (ctrl, names, list_external_cb, &parm);
700   if (rc)
701     log_error ("listing external keys failed: %s\n", gpg_strerror (rc));
702   return rc;
703 }
704
705 /* List all keys or just the key given as NAMES.
706    MODE controls the operation mode: 
707     Bit 0-2:
708       0 = list all public keys but don't flag secret ones
709       1 = list only public keys
710       2 = list only secret keys
711       3 = list secret and public keys
712     Bit 6: list internal keys
713     Bit 7: list external keys
714  */
715 gpg_error_t
716 gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
717 {
718   gpg_error_t err = 0;
719
720   if ((mode & (1<<6)))
721     err = list_internal_keys (ctrl, names, fp, (mode & 3));
722   if (!err && (mode & (1<<7)))
723     err = list_external_keys (ctrl, names, fp); 
724   return err;
725 }