(main): New commands --dump-keys, --dump-external-keys,
[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   int raw_mode;
47 };
48
49
50 /* This table is to map Extended Key Usage OIDs to human readable
51    names.  */
52 struct {
53   const char *oid;
54   const char *name;
55 } key_purpose_map[] = {
56   { "1.3.6.1.5.5.7.3.1",  "serverAuth" },
57   { "1.3.6.1.5.5.7.3.2",  "clientAuth" },          
58   { "1.3.6.1.5.5.7.3.3",  "codeSigning" },      
59   { "1.3.6.1.5.5.7.3.4",  "emailProtection" },     
60   { "1.3.6.1.5.5.7.3.5",  "ipsecEndSystem" }, 
61   { "1.3.6.1.5.5.7.3.6",  "ipsecTunnel" },  
62   { "1.3.6.1.5.5.7.3.7",  "ipsecUser" },     
63   { "1.3.6.1.5.5.7.3.8",  "timeStamping" },       
64   { "1.3.6.1.5.5.7.3.9",  "ocspSigning" },    
65   { "1.3.6.1.5.5.7.3.10", "dvcs" },      
66   { "1.3.6.1.5.5.7.3.11", "sbgpCertAAServerAuth" },
67   { "1.3.6.1.5.5.7.3.13", "eapOverPPP" },
68   { "1.3.6.1.5.5.7.3.14", "wlanSSID" },       
69   { NULL, NULL }
70 };
71
72
73 static void
74 print_key_data (ksba_cert_t cert, FILE *fp)
75 {
76 #if 0  
77   int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
78   int i;
79
80   for(i=0; i < n; i++ ) 
81     {
82       fprintf (fp, "pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) );
83       mpi_print(stdout, pk->pkey[i], 1 );
84       putchar(':');
85       putchar('\n');
86     }
87 #endif
88 }
89
90 static void
91 print_capabilities (ksba_cert_t cert, FILE *fp)
92 {
93   gpg_error_t err;
94   unsigned int use;
95
96   err = ksba_cert_get_key_usage (cert, &use);
97   if (gpg_err_code (err) == GPG_ERR_NO_DATA)
98     {
99       putc ('e', fp);
100       putc ('s', fp);
101       putc ('c', fp);
102       putc ('E', fp);
103       putc ('S', fp);
104       putc ('C', fp);
105       return;
106     }
107   if (err)
108     { 
109       log_error (_("error getting key usage information: %s\n"),
110                  gpg_strerror (err));
111       return;
112     } 
113
114   if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
115     putc ('e', fp);
116   if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
117     putc ('s', fp);
118   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
119     putc ('c', fp);
120   if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
121     putc ('E', fp);
122   if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
123     putc ('S', fp);
124   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
125     putc ('C', fp);
126 }
127
128
129 static void
130 print_time (gnupg_isotime_t t, FILE *fp)
131 {
132   if (!t || !*t)
133     ;
134   else 
135     fputs (t, fp);
136 }
137
138
139 /* return an allocated string with the email address extracted from a
140    DN */
141 static char *
142 email_kludge (const char *name)
143 {
144   const unsigned char *p;
145   unsigned char *buf;
146   int n;
147
148   if (strncmp (name, "1.2.840.113549.1.9.1=#", 22))
149     return NULL;
150   /* This looks pretty much like an email address in the subject's DN
151      we use this to add an additional user ID entry.  This way,
152      openSSL generated keys get a nicer and usable listing */
153   name += 22;    
154   for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++)
155     ;
156   if (*p != '#' || !n)
157     return NULL;
158   buf = xtrymalloc (n+3);
159   if (!buf)
160     return NULL; /* oops, out of core */
161   *buf = '<';
162   for (n=1, p=name; *p != '#'; p +=2, n++)
163     buf[n] = xtoi_2 (p);
164   buf[n++] = '>';
165   buf[n] = 0;
166   return buf;
167 }
168
169
170
171
172 /* List one certificate in colon mode */
173 static void
174 list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
175                  FILE *fp, int have_secret)
176 {
177   int idx;
178   char truststring[2];
179   char *p;
180   ksba_sexp_t sexp;
181   char *fpr;
182   ksba_isotime_t t;
183   gpg_error_t valerr;
184
185   if (ctrl->with_validation)
186     valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL, 0);
187   else
188     valerr = 0;
189
190   fputs (have_secret? "crs:":"crt:", fp);
191   truststring[0] = 0;
192   truststring[1] = 0;
193   if ((validity & VALIDITY_REVOKED)
194       || gpg_err_code (valerr) == GPG_ERR_CERT_REVOKED)
195     *truststring = 'r';
196   else if (gpg_err_code (valerr) == GPG_ERR_CERT_EXPIRED)
197     *truststring = 'e';
198   else if (valerr)
199     *truststring = 'i';
200   else 
201     {
202       /* Lets also check whether the certificate under question
203          expired.  This is merely a hack until we found a proper way
204          to store the expiration flag in the keybox. */
205       ksba_isotime_t current_time, not_after;
206   
207       gnupg_get_isotime (current_time);
208       if (!opt.ignore_expiration
209           && !ksba_cert_get_validity (cert, 1, not_after)
210           && *not_after && strcmp (current_time, not_after) > 0 )
211         *truststring = 'e';
212     }
213   
214   if (*truststring)
215     fputs (truststring, fp);
216
217   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
218   fprintf (fp, ":%u:%d:%s:",
219            /*keylen_of_cert (cert)*/1024,
220            /* pubkey_algo_of_cert (cert)*/1,
221            fpr+24);
222
223   /* We assume --fixed-list-mode for gpgsm */
224   ksba_cert_get_validity (cert, 0, t);
225   print_time (t, fp);
226   putc (':', fp);
227   ksba_cert_get_validity (cert, 1, t);
228   print_time ( t, fp);
229   putc (':', fp);
230   /* Field 8, serial number: */
231   if ((sexp = ksba_cert_get_serial (cert)))
232     {
233       int len;
234       const unsigned char *s = sexp;
235       
236       if (*s == '(')
237         {
238           s++;
239           for (len=0; *s && *s != ':' && digitp (s); s++)
240             len = len*10 + atoi_1 (s);
241           if (*s == ':')
242             for (s++; len; len--, s++)
243               fprintf (fp,"%02X", *s);
244         }
245       xfree (sexp);
246     }
247   putc (':', fp);
248   /* Field 9, ownertrust - not used here */
249   putc (':', fp);
250   /* field 10, old user ID - we use it here for the issuer DN */
251   if ((p = ksba_cert_get_issuer (cert,0)))
252     {
253       print_sanitized_string (fp, p, ':');
254       xfree (p);
255     }
256   putc (':', fp);
257   /* Field 11, signature class - not used */ 
258   putc (':', fp);
259   /* Field 12, capabilities: */ 
260   print_capabilities (cert, fp);
261   putc (':', fp);
262   putc ('\n', fp);
263
264   /* FPR record */
265   fprintf (fp, "fpr:::::::::%s:::", fpr);
266   /* Print chaining ID (field 13)*/
267   {
268     ksba_cert_t next;
269     int rc;
270     
271     rc = gpgsm_walk_cert_chain (cert, &next);
272     if (!rc) /* We known the issuer's certificate. */
273       {
274         p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1);
275         fputs (p, fp);
276         xfree (p);
277         ksba_cert_release (next);
278       }
279     else if (rc == -1)  /* We reached the root certificate. */
280       {
281         fputs (fpr, fp);
282       }
283   }
284   putc (':', fp);
285   putc ('\n', fp);
286   xfree (fpr); fpr = NULL;
287
288
289   if (opt.with_key_data)
290     {
291       if ( (p = gpgsm_get_keygrip_hexstring (cert)))
292         {
293           fprintf (fp, "grp:::::::::%s:\n", p);
294           xfree (p);
295         }
296       print_key_data (cert, fp);
297     }
298
299   for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++)
300     {
301       fprintf (fp, "uid:%s::::::::", truststring);
302       print_sanitized_string (fp, p, ':');
303       putc (':', fp);
304       putc (':', fp);
305       putc ('\n', fp);
306       if (!idx)
307         {
308           /* It would be better to get the faked email address from
309              the keydb.  But as long as we don't have a way to pass
310              the meta data back, we just check it the same way as the
311              code used to create the keybox meta data does */
312           char *pp = email_kludge (p);
313           if (pp)
314             {
315               fprintf (fp, "uid:%s::::::::", truststring);
316               print_sanitized_string (fp, pp, ':');
317               putc (':', fp);
318               putc (':', fp);
319               putc ('\n', fp);
320               xfree (pp);
321             }
322         }
323       xfree (p);
324     }
325 }
326
327
328 /* List one certificate in raw mode useful to have a closer look at
329    the certificate.  This one does not beautification and only minimal
330    output sanitation.  It is mainly useful for debugging. */
331 static void
332 list_cert_raw (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret,
333                int with_validation)
334 {
335   gpg_error_t err;
336   ksba_sexp_t sexp;
337   char *dn;
338   ksba_isotime_t t;
339   int idx, i;
340   int is_ca, chainlen;
341   unsigned int kusage;
342   char *string, *p, *pend;
343
344   sexp = ksba_cert_get_serial (cert);
345   fputs ("Serial number: ", fp);
346   gpgsm_print_serial (fp, sexp);
347   ksba_free (sexp);
348   putc ('\n', fp);
349
350   dn = ksba_cert_get_issuer (cert, 0);
351   fputs ("       Issuer: ", fp);
352   gpgsm_print_name (fp, dn);
353   ksba_free (dn);
354   putc ('\n', fp);
355   for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
356     {
357       fputs ("          aka: ", fp);
358       gpgsm_print_name (fp, dn);
359       ksba_free (dn);
360       putc ('\n', fp);
361     }
362
363   dn = ksba_cert_get_subject (cert, 0);
364   fputs ("      Subject: ", fp);
365   gpgsm_print_name (fp, dn);
366   ksba_free (dn);
367   putc ('\n', fp);
368   for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
369     {
370       fputs ("          aka: ", fp);
371       gpgsm_print_name (fp, dn);
372       ksba_free (dn);
373       putc ('\n', fp);
374     }
375
376   ksba_cert_get_validity (cert, 0, t);
377   fputs ("     validity: ", fp);
378   gpgsm_print_time (fp, t);
379   fputs (" through ", fp);
380   ksba_cert_get_validity (cert, 1, t);
381   gpgsm_print_time (fp, t);
382   putc ('\n', fp);
383
384   err = ksba_cert_get_key_usage (cert, &kusage);
385   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
386     {
387       fputs ("    key usage:", fp);
388       if (err)
389         fprintf (fp, " [error: %s]", gpg_strerror (err));
390       else
391         {
392           if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
393             fputs (" digitalSignature", fp);
394           if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))  
395             fputs (" nonRepudiation", fp);
396           if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT)) 
397             fputs (" keyEncipherment", fp);
398           if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
399             fputs (" dataEncipherment", fp);
400           if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))    
401             fputs (" keyAgreement", fp);
402           if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
403             fputs (" certSign", fp);
404           if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))  
405             fputs (" crlSign", fp);
406           if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
407             fputs (" encipherOnly", fp);
408           if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))  
409             fputs (" decipherOnly", fp);
410         }
411       putc ('\n', fp);
412     }
413
414   err = ksba_cert_get_ext_key_usages (cert, &string);
415   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
416     { 
417       fputs ("ext key usage: ", fp);
418       if (err)
419         fprintf (fp, "[error: %s]", gpg_strerror (err));
420       else
421         {
422           p = string;
423           while (p && (pend=strchr (p, ':')))
424             {
425               *pend++ = 0;
426               for (i=0; key_purpose_map[i].oid; i++)
427                 if ( !strcmp (key_purpose_map[i].oid, p) )
428                   break;
429               fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
430               p = pend;
431               if (*p != 'C')
432                 fputs (" (suggested)", fp);
433               if ((p = strchr (p, '\n')))
434                 {
435                   p++;
436                   fputs (", ", fp);
437                 }
438             }
439           xfree (string);
440         }
441       putc ('\n', fp);
442     }
443
444   err = ksba_cert_get_cert_policies (cert, &string);
445   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
446     {
447       fputs ("     policies: ", fp);
448       if (err)
449         fprintf (fp, "[error: %s]", gpg_strerror (err));
450       else
451         {
452           for (p=string; *p; p++)
453             {
454               if (*p == '\n')
455                 *p = ',';
456             }
457           print_sanitized_string (fp, string, 0);
458           xfree (string);
459         }
460       putc ('\n', fp);
461     }
462
463   err = ksba_cert_is_ca (cert, &is_ca, &chainlen);
464   if (err || is_ca)
465     {
466       fputs (" chain length: ", fp);
467       if (err)
468         fprintf (fp, "[error: %s]", gpg_strerror (err));
469       else if (chainlen == -1)
470         fputs ("unlimited", fp);
471       else
472         fprintf (fp, "%d", chainlen);
473       putc ('\n', fp);
474     }
475
476   dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5);
477   fprintf (fp, "      md5 fpr: %s\n", dn?dn:"error");
478   xfree (dn);
479
480   dn = gpgsm_get_fingerprint_string (cert, 0);
481   fprintf (fp, "  fingerprint: %s\n", dn?dn:"error");
482   xfree (dn);
483
484   if (with_validation)
485     {
486       err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp, 0);
487       if (!err)
488         fprintf (fp, "  [certificate is good]\n");
489       else
490         fprintf (fp, "  [certificate is bad: %s]\n", gpg_strerror (err));
491     }
492 }
493
494
495
496
497 /* List one certificate in standard mode */
498 static void
499 list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret,
500                int with_validation)
501 {
502   gpg_error_t err;
503   ksba_sexp_t sexp;
504   char *dn;
505   ksba_isotime_t t;
506   int idx, i;
507   int is_ca, chainlen;
508   unsigned int kusage;
509   char *string, *p, *pend;
510
511   sexp = ksba_cert_get_serial (cert);
512   fputs ("Serial number: ", fp);
513   gpgsm_print_serial (fp, sexp);
514   ksba_free (sexp);
515   putc ('\n', fp);
516
517   dn = ksba_cert_get_issuer (cert, 0);
518   fputs ("       Issuer: ", fp);
519   gpgsm_print_name (fp, dn);
520   ksba_free (dn);
521   putc ('\n', fp);
522   for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
523     {
524       fputs ("          aka: ", fp);
525       gpgsm_print_name (fp, dn);
526       ksba_free (dn);
527       putc ('\n', fp);
528     }
529
530   dn = ksba_cert_get_subject (cert, 0);
531   fputs ("      Subject: ", fp);
532   gpgsm_print_name (fp, dn);
533   ksba_free (dn);
534   putc ('\n', fp);
535   for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
536     {
537       fputs ("          aka: ", fp);
538       gpgsm_print_name (fp, dn);
539       ksba_free (dn);
540       putc ('\n', fp);
541     }
542
543   ksba_cert_get_validity (cert, 0, t);
544   fputs ("     validity: ", fp);
545   gpgsm_print_time (fp, t);
546   fputs (" through ", fp);
547   ksba_cert_get_validity (cert, 1, t);
548   gpgsm_print_time (fp, t);
549   putc ('\n', fp);
550
551   err = ksba_cert_get_key_usage (cert, &kusage);
552   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
553     {
554       fputs ("    key usage:", fp);
555       if (err)
556         fprintf (fp, " [error: %s]", gpg_strerror (err));
557       else
558         {
559           if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
560             fputs (" digitalSignature", fp);
561           if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))  
562             fputs (" nonRepudiation", fp);
563           if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT)) 
564             fputs (" keyEncipherment", fp);
565           if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
566             fputs (" dataEncipherment", fp);
567           if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))    
568             fputs (" keyAgreement", fp);
569           if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
570             fputs (" certSign", fp);
571           if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))  
572             fputs (" crlSign", fp);
573           if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
574             fputs (" encipherOnly", fp);
575           if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))  
576             fputs (" decipherOnly", fp);
577         }
578       putc ('\n', fp);
579     }
580
581   err = ksba_cert_get_ext_key_usages (cert, &string);
582   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
583     { 
584       fputs ("ext key usage: ", fp);
585       if (err)
586         fprintf (fp, "[error: %s]", gpg_strerror (err));
587       else
588         {
589           p = string;
590           while (p && (pend=strchr (p, ':')))
591             {
592               *pend++ = 0;
593               for (i=0; key_purpose_map[i].oid; i++)
594                 if ( !strcmp (key_purpose_map[i].oid, p) )
595                   break;
596               fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
597               p = pend;
598               if (*p != 'C')
599                 fputs (" (suggested)", fp);
600               if ((p = strchr (p, '\n')))
601                 {
602                   p++;
603                   fputs (", ", fp);
604                 }
605             }
606           xfree (string);
607         }
608       putc ('\n', fp);
609     }
610
611   err = ksba_cert_get_cert_policies (cert, &string);
612   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
613     {
614       fputs ("     policies: ", fp);
615       if (err)
616         fprintf (fp, "[error: %s]", gpg_strerror (err));
617       else
618         {
619           for (p=string; *p; p++)
620             {
621               if (*p == '\n')
622                 *p = ',';
623             }
624           print_sanitized_string (fp, string, 0);
625           xfree (string);
626         }
627       putc ('\n', fp);
628     }
629
630   err = ksba_cert_is_ca (cert, &is_ca, &chainlen);
631   if (err || is_ca)
632     {
633       fputs (" chain length: ", fp);
634       if (err)
635         fprintf (fp, "[error: %s]", gpg_strerror (err));
636       else if (chainlen == -1)
637         fputs ("unlimited", fp);
638       else
639         fprintf (fp, "%d", chainlen);
640       putc ('\n', fp);
641     }
642
643   if (opt.with_md5_fingerprint)
644     {
645       dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5);
646       fprintf (fp, "      md5 fpr: %s\n", dn?dn:"error");
647       xfree (dn);
648     }
649
650   dn = gpgsm_get_fingerprint_string (cert, 0);
651   fprintf (fp, "  fingerprint: %s\n", dn?dn:"error");
652   xfree (dn);
653
654   if (with_validation)
655     {
656       err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp, 0);
657       if (!err)
658         fprintf (fp, "  [certificate is good]\n");
659       else
660         fprintf (fp, "  [certificate is bad: %s]\n", gpg_strerror (err));
661     }
662 }
663
664
665 /* Same as standard mode mode list all certifying certs too. */
666 static void
667 list_cert_chain (ctrl_t ctrl, ksba_cert_t cert, int raw_mode,
668                  FILE *fp, int with_validation)
669 {
670   ksba_cert_t next = NULL;
671
672   if (raw_mode)
673     list_cert_raw (ctrl, cert, fp, 0, with_validation);
674   else
675     list_cert_std (ctrl, cert, fp, 0, with_validation);
676   ksba_cert_ref (cert);
677   while (!gpgsm_walk_cert_chain (cert, &next))
678     {
679       ksba_cert_release (cert);
680       fputs ("Certified by\n", fp);
681       if (raw_mode)
682         list_cert_raw (ctrl, next, fp, 0, with_validation);
683       else
684         list_cert_std (ctrl, next, fp, 0, with_validation);
685       cert = next;
686     }
687   ksba_cert_release (cert);
688   putc ('\n', fp);
689 }
690
691
692 \f
693 /* List all internal keys or just the keys given as NAMES.  MODE is a
694    bit vector to specify what keys are to be included; see
695    gpgsm_list_keys (below) for details.  If RAW_MODE is true, the raw
696    output mode will be used intead of the standard beautified one.
697  */
698 static gpg_error_t
699 list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp,
700                     unsigned int mode, int raw_mode)
701 {
702   KEYDB_HANDLE hd;
703   KEYDB_SEARCH_DESC *desc = NULL;
704   STRLIST sl;
705   int ndesc;
706   ksba_cert_t cert = NULL;
707   gpg_error_t rc = 0;
708   const char *lastresname, *resname;
709   int have_secret;
710
711   hd = keydb_new (0);
712   if (!hd)
713     {
714       log_error ("keydb_new failed\n");
715       rc = gpg_error (GPG_ERR_GENERAL);
716       goto leave;
717     }
718
719   if (!names)
720     ndesc = 1;
721   else
722     {
723       for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) 
724         ;
725     }
726
727   desc = xtrycalloc (ndesc, sizeof *desc);
728   if (!ndesc)
729     {
730       rc = gpg_error_from_errno (errno);
731       log_error ("out of core\n");
732       goto leave;
733     }
734
735   if (!names)
736     desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
737   else 
738     {
739       for (ndesc=0, sl=names; sl; sl = sl->next) 
740         {
741           rc = keydb_classify_name (sl->d, desc+ndesc);
742           if (rc)
743             {
744               log_error ("key `%s' not found: %s\n",
745                          sl->d, gpg_strerror (rc));
746               rc = 0;
747             }
748           else
749             ndesc++;
750         }
751       
752     }
753
754   /* It would be nice to see which of the given users did actually
755      match one in the keyring.  To implement this we need to have a
756      found flag for each entry in desc and to set this we must check
757      all those entries after a match to mark all matched one -
758      currently we stop at the first match.  To do this we need an
759      extra flag to enable this feature so */
760
761   lastresname = NULL;
762   while (!(rc = keydb_search (hd, desc, ndesc)))
763     {
764       unsigned int validity;
765
766       if (!names) 
767         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
768
769       rc = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &validity);
770       if (rc)
771         {
772           log_error ("keydb_get_flags failed: %s\n", gpg_strerror (rc));
773           goto leave;
774         }
775       rc = keydb_get_cert (hd, &cert);
776       if (rc) 
777         {
778           log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
779           goto leave;
780         }
781       
782       resname = keydb_get_resource_name (hd);
783       
784       if (lastresname != resname ) 
785         {
786           int i;
787           
788           if (ctrl->no_server)
789             {
790               fprintf (fp, "%s\n", resname );
791               for (i=strlen(resname); i; i-- )
792                 putchar('-');
793               putc ('\n', fp);
794               lastresname = resname;
795             }
796         }
797
798       have_secret = 0;
799       if (mode)
800         {
801           char *p = gpgsm_get_keygrip_hexstring (cert);
802           if (p)
803             {
804               rc = gpgsm_agent_havekey (p);
805               if (!rc)
806                 have_secret = 1;
807               else if ( gpg_err_code (rc) != GPG_ERR_NO_SECKEY)
808                 goto leave;
809               rc = 0;
810               xfree (p);
811             }
812         }
813
814       if (!mode
815           || ((mode & 1) && !have_secret)
816           || ((mode & 2) && have_secret)  )
817         {
818           if (ctrl->with_colons)
819             list_cert_colon (ctrl, cert, validity, fp, have_secret);
820           else if (ctrl->with_chain)
821             list_cert_chain (ctrl, cert, raw_mode, fp, ctrl->with_validation);
822           else
823             {
824               if (raw_mode)
825                 list_cert_raw (ctrl, cert, fp, have_secret,
826                                ctrl->with_validation);
827               else
828                 list_cert_std (ctrl, cert, fp, have_secret,
829                                ctrl->with_validation);
830               putc ('\n', fp);
831             }
832         }
833       ksba_cert_release (cert); 
834       cert = NULL;
835     }
836   if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1 )
837     rc = 0;
838   if (rc)
839     log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
840   
841  leave:
842   ksba_cert_release (cert);
843   xfree (desc);
844   keydb_release (hd);
845   return rc;
846 }
847
848
849
850 static void
851 list_external_cb (void *cb_value, ksba_cert_t cert)
852 {
853   struct list_external_parm_s *parm = cb_value;
854
855   if (keydb_store_cert (cert, 1, NULL))
856     log_error ("error storing certificate as ephemeral\n");
857
858   if (parm->print_header)
859     {
860       const char *resname = "[external keys]";
861       int i;
862
863       fprintf (parm->fp, "%s\n", resname );
864       for (i=strlen(resname); i; i-- )
865         putchar('-');
866       putc ('\n', parm->fp);
867       parm->print_header = 0;
868     }
869
870   if (parm->with_colons)
871     list_cert_colon (parm->ctrl, cert, 0, parm->fp, 0);
872   else if (parm->with_chain)
873     list_cert_chain (parm->ctrl, cert, parm->raw_mode, parm->fp, 0);
874   else
875     {
876       if (parm->raw_mode)
877         list_cert_raw (parm->ctrl, cert, parm->fp, 0, 0);
878       else
879         list_cert_std (parm->ctrl, cert, parm->fp, 0, 0);
880       putc ('\n', parm->fp);
881     }
882 }
883
884
885 /* List external keys similar to internal one.  Note: mode does not
886    make sense here because it would be unwise to list external secret
887    keys */
888 static gpg_error_t
889 list_external_keys (CTRL ctrl, STRLIST names, FILE *fp, int raw_mode)
890 {
891   int rc;
892   struct list_external_parm_s parm;
893
894   parm.fp = fp;
895   parm.ctrl = ctrl,
896   parm.print_header = ctrl->no_server;
897   parm.with_colons = ctrl->with_colons;
898   parm.with_chain = ctrl->with_chain;
899   parm.raw_mode  = raw_mode;
900
901   rc = gpgsm_dirmngr_lookup (ctrl, names, list_external_cb, &parm);
902   if (rc)
903     log_error ("listing external keys failed: %s\n", gpg_strerror (rc));
904   return rc;
905 }
906
907 /* List all keys or just the key given as NAMES.
908    MODE controls the operation mode: 
909     Bit 0-2:
910       0 = list all public keys but don't flag secret ones
911       1 = list only public keys
912       2 = list only secret keys
913       3 = list secret and public keys
914     Bit 6: list internal keys
915     Bit 7: list external keys
916     Bit 8: Do a raw format dump.
917  */
918 gpg_error_t
919 gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
920 {
921   gpg_error_t err = 0;
922
923   if ((mode & (1<<6)))
924     err = list_internal_keys (ctrl, names, fp, (mode & 3), (mode&256));
925   if (!err && (mode & (1<<7)))
926     err = list_external_keys (ctrl, names, fp, (mode&256)); 
927   return err;
928 }