* keylist.c (list_internal_keys): Return error codes.
[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   xfree (fpr); fpr = NULL;
253   /* print chaining ID (field 13)*/
254   {
255     ksba_cert_t next;
256     
257     if (!gpgsm_walk_cert_chain (cert, &next))
258       {
259         p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1);
260         fputs (p, fp);
261         xfree (p);
262         ksba_cert_release (next);
263       }
264   }
265   putc (':', fp);
266   putc ('\n', fp);
267
268
269   if (opt.with_key_data)
270     {
271       if ( (p = gpgsm_get_keygrip_hexstring (cert)))
272         {
273           fprintf (fp, "grp:::::::::%s:\n", p);
274           xfree (p);
275         }
276       print_key_data (cert, fp);
277     }
278
279   for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++)
280     {
281       fprintf (fp, "uid:%s::::::::", truststring);
282       print_sanitized_string (fp, p, ':');
283       putc (':', fp);
284       putc (':', fp);
285       putc ('\n', fp);
286       if (!idx)
287         {
288           /* It would be better to get the faked email address from
289              the keydb.  But as long as we don't have a way to pass
290              the meta data back, we just check it the same way as the
291              code used to create the keybox meta data does */
292           char *pp = email_kludge (p);
293           if (pp)
294             {
295               fprintf (fp, "uid:%s::::::::", truststring);
296               print_sanitized_string (fp, pp, ':');
297               putc (':', fp);
298               putc (':', fp);
299               putc ('\n', fp);
300               xfree (pp);
301             }
302         }
303       xfree (p);
304     }
305 }
306
307
308 /* List one certificate in standard mode */
309 static void
310 list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret,
311                int with_validation)
312 {
313   gpg_error_t err;
314   ksba_sexp_t sexp;
315   char *dn;
316   ksba_isotime_t t;
317   int idx, i;
318   int is_ca, chainlen;
319   unsigned int kusage;
320   char *string, *p, *pend;
321
322   sexp = ksba_cert_get_serial (cert);
323   fputs ("Serial number: ", fp);
324   gpgsm_print_serial (fp, sexp);
325   ksba_free (sexp);
326   putc ('\n', fp);
327
328   dn = ksba_cert_get_issuer (cert, 0);
329   fputs ("       Issuer: ", fp);
330   gpgsm_print_name (fp, dn);
331   ksba_free (dn);
332   putc ('\n', fp);
333   for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
334     {
335       fputs ("          aka: ", fp);
336       gpgsm_print_name (fp, dn);
337       ksba_free (dn);
338       putc ('\n', fp);
339     }
340
341   dn = ksba_cert_get_subject (cert, 0);
342   fputs ("      Subject: ", fp);
343   gpgsm_print_name (fp, dn);
344   ksba_free (dn);
345   putc ('\n', fp);
346   for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
347     {
348       fputs ("          aka: ", fp);
349       gpgsm_print_name (fp, dn);
350       ksba_free (dn);
351       putc ('\n', fp);
352     }
353
354   ksba_cert_get_validity (cert, 0, t);
355   fputs ("     validity: ", fp);
356   gpgsm_print_time (fp, t);
357   fputs (" through ", fp);
358   ksba_cert_get_validity (cert, 1, t);
359   gpgsm_print_time (fp, t);
360   putc ('\n', fp);
361
362   err = ksba_cert_get_key_usage (cert, &kusage);
363   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
364     {
365       fputs ("    key usage:", fp);
366       if (err)
367         fprintf (fp, " [error: %s]", gpg_strerror (err));
368       else
369         {
370           if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
371             fputs (" digitalSignature", fp);
372           if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))  
373             fputs (" nonRepudiation", fp);
374           if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT)) 
375             fputs (" keyEncipherment", fp);
376           if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
377             fputs (" dataEncipherment", fp);
378           if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))    
379             fputs (" keyAgreement", fp);
380           if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
381             fputs (" certSign", fp);
382           if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))  
383             fputs (" crlSign", fp);
384           if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
385             fputs (" encipherOnly", fp);
386           if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))  
387             fputs (" decipherOnly", fp);
388         }
389       putc ('\n', fp);
390     }
391
392   err = ksba_cert_get_ext_key_usages (cert, &string);
393   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
394     { 
395       fputs ("ext key usage: ", fp);
396       if (err)
397         fprintf (fp, "[error: %s]", gpg_strerror (err));
398       else
399         {
400           p = string;
401           while (p && (pend=strchr (p, ':')))
402             {
403               *pend++ = 0;
404               for (i=0; key_purpose_map[i].oid; i++)
405                 if ( !strcmp (key_purpose_map[i].oid, p) )
406                   break;
407               fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
408               p = pend;
409               if (*p != 'C')
410                 fputs (" (suggested)", fp);
411               if ((p = strchr (p, '\n')))
412                 {
413                   p++;
414                   fputs (", ", fp);
415                 }
416             }
417           xfree (string);
418         }
419       putc ('\n', fp);
420     }
421
422   err = ksba_cert_get_cert_policies (cert, &string);
423   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
424     {
425       fputs ("     policies: ", fp);
426       if (err)
427         fprintf (fp, "[error: %s]", gpg_strerror (err));
428       else
429         {
430           for (p=string; *p; p++)
431             {
432               if (*p == '\n')
433                 *p = ',';
434             }
435           print_sanitized_string (fp, string, 0);
436           xfree (string);
437         }
438       putc ('\n', fp);
439     }
440
441   err = ksba_cert_is_ca (cert, &is_ca, &chainlen);
442   if (err || is_ca)
443     {
444       fputs (" chain length: ", fp);
445       if (err)
446         fprintf (fp, "[error: %s]", gpg_strerror (err));
447       else if (chainlen == -1)
448         fputs ("unlimited", fp);
449       else
450         fprintf (fp, "%d", chainlen);
451       putc ('\n', fp);
452     }
453
454   if (opt.with_md5_fingerprint)
455     {
456       dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5);
457       fprintf (fp, "      md5 fpr: %s\n", dn?dn:"error");
458       xfree (dn);
459     }
460
461   dn = gpgsm_get_fingerprint_string (cert, 0);
462   fprintf (fp, "  fingerprint: %s\n", dn?dn:"error");
463   xfree (dn);
464
465   if (with_validation)
466     {
467       err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp);
468       if (!err)
469         fprintf (fp, "  [certificate is good]\n");
470       else
471         fprintf (fp, "  [certificate is bad: %s]\n", gpg_strerror (err));
472     }
473 }
474
475
476 /* Same as standard mode mode list all certifying certs too. */
477 static void
478 list_cert_chain (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int with_validation)
479 {
480   ksba_cert_t next = NULL;
481
482   list_cert_std (ctrl, cert, fp, 0, with_validation);
483   ksba_cert_ref (cert);
484   while (!gpgsm_walk_cert_chain (cert, &next))
485     {
486       ksba_cert_release (cert);
487       fputs ("Certified by\n", fp);
488       list_cert_std (ctrl, next, fp, 0, with_validation);
489       cert = next;
490     }
491   ksba_cert_release (cert);
492   putc ('\n', fp);
493 }
494
495
496 \f
497 /* List all internal keys or just the key given as NAMES.
498  */
499 static gpg_error_t
500 list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
501 {
502   KEYDB_HANDLE hd;
503   KEYDB_SEARCH_DESC *desc = NULL;
504   STRLIST sl;
505   int ndesc;
506   ksba_cert_t cert = NULL;
507   gpg_error_t rc = 0;
508   const char *lastresname, *resname;
509   int have_secret;
510
511   hd = keydb_new (0);
512   if (!hd)
513     {
514       log_error ("keydb_new failed\n");
515       rc = gpg_error (GPG_ERR_GENERAL);
516       goto leave;
517     }
518
519   if (!names)
520     ndesc = 1;
521   else
522     {
523       for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) 
524         ;
525     }
526
527   desc = xtrycalloc (ndesc, sizeof *desc);
528   if (!ndesc)
529     {
530       rc = gpg_error_from_errno (errno);
531       log_error ("out of core\n");
532       goto leave;
533     }
534
535   if (!names)
536     desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
537   else 
538     {
539       for (ndesc=0, sl=names; sl; sl = sl->next) 
540         {
541           rc = keydb_classify_name (sl->d, desc+ndesc);
542           if (rc)
543             {
544               log_error ("key `%s' not found: %s\n",
545                          sl->d, gpg_strerror (rc));
546               rc = 0;
547             }
548           else
549             ndesc++;
550         }
551       
552     }
553
554   /* It would be nice to see which of the given users did actually
555      match one in the keyring.  To implement this we need to have a
556      found flag for each entry in desc and to set this we must check
557      all those entries after a match to mark all matched one -
558      currently we stop at the first match.  To do this we need an
559      extra flag to enable this feature so */
560
561   lastresname = NULL;
562   while (!(rc = keydb_search (hd, desc, ndesc)))
563     {
564       unsigned int validity;
565
566       if (!names) 
567         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
568
569       rc = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &validity);
570       if (rc)
571         {
572           log_error ("keydb_get_flags failed: %s\n", gpg_strerror (rc));
573           goto leave;
574         }
575       rc = keydb_get_cert (hd, &cert);
576       if (rc) 
577         {
578           log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
579           goto leave;
580         }
581       
582       resname = keydb_get_resource_name (hd);
583       
584       if (lastresname != resname ) 
585         {
586           int i;
587           
588           if (ctrl->no_server)
589             {
590               fprintf (fp, "%s\n", resname );
591               for (i=strlen(resname); i; i-- )
592                 putchar('-');
593               putc ('\n', fp);
594               lastresname = resname;
595             }
596         }
597
598       have_secret = 0;
599       if (mode)
600         {
601           char *p = gpgsm_get_keygrip_hexstring (cert);
602           if (p)
603             {
604               rc = gpgsm_agent_havekey (p);
605               if (!rc)
606                 have_secret = 1;
607               else if ( gpg_err_code (rc) != GPG_ERR_NO_SECKEY)
608                 goto leave;
609               rc = 0;
610               xfree (p);
611             }
612         }
613
614       if (!mode
615           || ((mode & 1) && !have_secret)
616           || ((mode & 2) && have_secret)  )
617         {
618           if (ctrl->with_colons)
619             list_cert_colon (ctrl, cert, validity, fp, have_secret);
620           else if (ctrl->with_chain)
621             list_cert_chain (ctrl, cert, fp, ctrl->with_validation);
622           else
623             {
624               list_cert_std (ctrl, cert, fp, have_secret,
625                              ctrl->with_validation);
626               putc ('\n', fp);
627             }
628         }
629       ksba_cert_release (cert); 
630       cert = NULL;
631     }
632   if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1 )
633     rc = 0;
634   if (rc)
635     log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
636   
637  leave:
638   ksba_cert_release (cert);
639   xfree (desc);
640   keydb_release (hd);
641   return rc;
642 }
643
644
645
646 static void
647 list_external_cb (void *cb_value, ksba_cert_t cert)
648 {
649   struct list_external_parm_s *parm = cb_value;
650
651   if (keydb_store_cert (cert, 1, NULL))
652     log_error ("error storing certificate as ephemeral\n");
653
654   if (parm->print_header)
655     {
656       const char *resname = "[external keys]";
657       int i;
658
659       fprintf (parm->fp, "%s\n", resname );
660       for (i=strlen(resname); i; i-- )
661         putchar('-');
662       putc ('\n', parm->fp);
663       parm->print_header = 0;
664     }
665
666   if (parm->with_colons)
667     list_cert_colon (parm->ctrl, cert, 0, parm->fp, 0);
668   else if (parm->with_chain)
669     list_cert_chain (parm->ctrl, cert, parm->fp, 0);
670   else
671     {
672       list_cert_std (parm->ctrl, cert, parm->fp, 0, 0);
673       putc ('\n', parm->fp);
674     }
675 }
676
677
678 /* List external keys similar to internal one.  Note: mode does not
679    make sense here because it would be unwise to list external secret
680    keys */
681 static gpg_error_t
682 list_external_keys (CTRL ctrl, STRLIST names, FILE *fp)
683 {
684   int rc;
685   struct list_external_parm_s parm;
686
687   parm.fp = fp;
688   parm.ctrl = ctrl,
689   parm.print_header = ctrl->no_server;
690   parm.with_colons = ctrl->with_colons;
691   parm.with_chain = ctrl->with_chain;
692
693   rc = gpgsm_dirmngr_lookup (ctrl, names, list_external_cb, &parm);
694   if (rc)
695     log_error ("listing external keys failed: %s\n", gpg_strerror (rc));
696   return rc;
697 }
698
699 /* List all keys or just the key given as NAMES.
700    MODE controls the operation mode: 
701     Bit 0-2:
702       0 = list all public keys but don't flag secret ones
703       1 = list only public keys
704       2 = list only secret keys
705       3 = list secret and public keys
706     Bit 6: list internal keys
707     Bit 7: list external keys
708  */
709 gpg_error_t
710 gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
711 {
712   gpg_error_t err = 0;
713
714   if ((mode & (1<<6)))
715     err = list_internal_keys (ctrl, names, fp, (mode & 3));
716   if (!err && (mode & (1<<7)))
717     err = list_external_keys (ctrl, names, fp); 
718   return err;
719 }