kbx/
[gnupg.git] / sm / keylist.c
1 /* keylist.c - Print certificates in various formats.
2  * Copyright (C) 1998, 1999, 2000, 2001, 2003,
3  *               2004, 2005 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
20  * USA.
21  */
22
23 #include <config.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <unistd.h> 
29 #include <time.h>
30 #include <assert.h>
31
32 #include "gpgsm.h"
33
34 #include <gcrypt.h>
35 #include <ksba.h>
36
37 #include "keydb.h"
38 #include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */
39 #include "i18n.h"
40
41 struct list_external_parm_s 
42 {
43   ctrl_t ctrl;
44   estream_t fp;
45   int print_header;
46   int with_colons;
47   int with_chain;
48   int raw_mode;
49 };
50
51
52 /* This table is to map Extended Key Usage OIDs to human readable
53    names.  */
54 struct
55 {
56   const char *oid;
57   const char *name;
58 } key_purpose_map[] = {
59   { "1.3.6.1.5.5.7.3.1",  "serverAuth" },
60   { "1.3.6.1.5.5.7.3.2",  "clientAuth" },          
61   { "1.3.6.1.5.5.7.3.3",  "codeSigning" },      
62   { "1.3.6.1.5.5.7.3.4",  "emailProtection" },     
63   { "1.3.6.1.5.5.7.3.5",  "ipsecEndSystem" }, 
64   { "1.3.6.1.5.5.7.3.6",  "ipsecTunnel" },  
65   { "1.3.6.1.5.5.7.3.7",  "ipsecUser" },     
66   { "1.3.6.1.5.5.7.3.8",  "timeStamping" },       
67   { "1.3.6.1.5.5.7.3.9",  "ocspSigning" },    
68   { "1.3.6.1.5.5.7.3.10", "dvcs" },      
69   { "1.3.6.1.5.5.7.3.11", "sbgpCertAAServerAuth" },
70   { "1.3.6.1.5.5.7.3.13", "eapOverPPP" },
71   { "1.3.6.1.5.5.7.3.14", "wlanSSID" },       
72
73   { "2.16.840.1.113730.4.1", "serverGatedCrypto.ns" }, /* Netscape. */
74   { "1.3.6.1.4.1.311.10.3.3", "serverGatedCrypto.ms"}, /* Microsoft. */
75
76   { "1.3.6.1.5.5.7.48.1.5", "ocspNoCheck" },
77
78   { NULL, NULL }
79 };
80
81
82 /* A table mapping OIDs to a descriptive string. */
83 static struct 
84 {
85   char *oid;
86   char *name;
87   unsigned int flag;
88 } oidtranstbl[] = {
89
90   /* Algorithms. */
91   { "1.2.840.10040.4.1", "dsa" },
92   { "1.2.840.10040.4.3", "dsaWithSha1" },
93
94   { "1.2.840.113549.1.1.1", "rsaEncryption" },
95   { "1.2.840.113549.1.1.2", "md2WithRSAEncryption" },
96   { "1.2.840.113549.1.1.3", "md4WithRSAEncryption" },
97   { "1.2.840.113549.1.1.4", "md5WithRSAEncryption" },
98   { "1.2.840.113549.1.1.5", "sha1WithRSAEncryption" },
99   { "1.2.840.113549.1.1.7", "rsaOAEP" },
100   { "1.2.840.113549.1.1.8", "rsaOAEP-MGF" },
101   { "1.2.840.113549.1.1.9", "rsaOAEP-pSpecified" },
102   { "1.2.840.113549.1.1.10", "rsaPSS" },
103   { "1.2.840.113549.1.1.11", "sha256WithRSAEncryption" },
104   { "1.2.840.113549.1.1.12", "sha384WithRSAEncryption" },
105   { "1.2.840.113549.1.1.13", "sha512WithRSAEncryption" },
106
107   { "1.3.14.3.2.26", "sha1" },
108   { "1.3.14.3.2.29",  "sha-1WithRSAEncryption" },
109   { "1.3.36.3.3.1.2", "rsaSignatureWithripemd160" },
110
111
112   /* Telesec extensions. */
113   { "0.2.262.1.10.12.0", "certExtensionLiabilityLimitationExt" },
114   { "0.2.262.1.10.12.1", "telesecCertIdExt" },
115   { "0.2.262.1.10.12.2", "telesecPolicyIdentifier" },
116   { "0.2.262.1.10.12.3", "telesecPolicyQualifierID" },
117   { "0.2.262.1.10.12.4", "telesecCRLFilteredExt" },
118   { "0.2.262.1.10.12.5", "telesecCRLFilterExt"},
119   { "0.2.262.1.10.12.6", "telesecNamingAuthorityExt" },
120
121   /* PKIX private extensions. */
122   { "1.3.6.1.5.5.7.1.1", "authorityInfoAccess" },
123   { "1.3.6.1.5.5.7.1.2", "biometricInfo" },
124   { "1.3.6.1.5.5.7.1.3", "qcStatements" },
125   { "1.3.6.1.5.5.7.1.4", "acAuditIdentity" },
126   { "1.3.6.1.5.5.7.1.5", "acTargeting" },
127   { "1.3.6.1.5.5.7.1.6", "acAaControls" },
128   { "1.3.6.1.5.5.7.1.7", "sbgp-ipAddrBlock" },
129   { "1.3.6.1.5.5.7.1.8", "sbgp-autonomousSysNum" },
130   { "1.3.6.1.5.5.7.1.9", "sbgp-routerIdentifier" },
131   { "1.3.6.1.5.5.7.1.10", "acProxying" },
132   { "1.3.6.1.5.5.7.1.11", "subjectInfoAccess" },
133
134   { "1.3.6.1.5.5.7.48.1", "ocsp" },
135   { "1.3.6.1.5.5.7.48.2", "caIssuers" },
136   { "1.3.6.1.5.5.7.48.3", "timeStamping" },
137   { "1.3.6.1.5.5.7.48.5", "caRepository" },
138
139   /* X.509 id-ce */
140   { "2.5.29.14", "subjectKeyIdentifier", 1},
141   { "2.5.29.15", "keyUsage", 1 },
142   { "2.5.29.16", "privateKeyUsagePeriod" },
143   { "2.5.29.17", "subjectAltName", 1 },
144   { "2.5.29.18", "issuerAltName", 1 },
145   { "2.5.29.19", "basicConstraints", 1},
146   { "2.5.29.20", "cRLNumber" },
147   { "2.5.29.21", "cRLReason" },
148   { "2.5.29.22", "expirationDate" },
149   { "2.5.29.23", "instructionCode" }, 
150   { "2.5.29.24", "invalidityDate" },
151   { "2.5.29.27", "deltaCRLIndicator" },
152   { "2.5.29.28", "issuingDistributionPoint" },
153   { "2.5.29.29", "certificateIssuer" },
154   { "2.5.29.30", "nameConstraints" },
155   { "2.5.29.31", "cRLDistributionPoints", 1 },
156   { "2.5.29.32", "certificatePolicies", 1 },
157   { "2.5.29.32.0", "anyPolicy" },
158   { "2.5.29.33", "policyMappings" },
159   { "2.5.29.35", "authorityKeyIdentifier", 1 },
160   { "2.5.29.36", "policyConstraints" },
161   { "2.5.29.37", "extKeyUsage", 1 },
162   { "2.5.29.46", "freshestCRL" },
163   { "2.5.29.54", "inhibitAnyPolicy" },
164
165   /* Netscape certificate extensions. */
166   { "2.16.840.1.113730.1.1", "netscape-cert-type" },
167   { "2.16.840.1.113730.1.2", "netscape-base-url" },
168   { "2.16.840.1.113730.1.3", "netscape-revocation-url" },
169   { "2.16.840.1.113730.1.4", "netscape-ca-revocation-url" },
170   { "2.16.840.1.113730.1.7", "netscape-cert-renewal-url" },
171   { "2.16.840.1.113730.1.8", "netscape-ca-policy-url" },
172   { "2.16.840.1.113730.1.9", "netscape-homePage-url" },
173   { "2.16.840.1.113730.1.10", "netscape-entitylogo" },
174   { "2.16.840.1.113730.1.11", "netscape-userPicture" },
175   { "2.16.840.1.113730.1.12", "netscape-ssl-server-name" },
176   { "2.16.840.1.113730.1.13", "netscape-comment" },
177
178   /* GnuPG extensions */
179   { "1.3.6.1.4.1.11591.2.1.1", "pkaAddress" },
180
181   { NULL }
182 };
183
184
185 /* Return the description for OID; if no description is available 
186    NULL is returned. */
187 static const char *
188 get_oid_desc (const char *oid, unsigned int *flag)
189 {
190   int i;
191
192   if (oid)
193     for (i=0; oidtranstbl[i].oid; i++)
194       if (!strcmp (oidtranstbl[i].oid, oid))
195         {
196           if (flag)
197             *flag = oidtranstbl[i].flag;
198           return oidtranstbl[i].name;
199         }
200   if (flag)
201     *flag = 0;
202   return NULL;
203 }
204
205
206 static void
207 print_key_data (ksba_cert_t cert, estream_t fp)
208 {
209 #if 0  
210   int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
211   int i;
212
213   for(i=0; i < n; i++ ) 
214     {
215       es_fprintf (fp, "pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) );
216       mpi_print(stdout, pk->pkey[i], 1 );
217       putchar(':');
218       putchar('\n');
219     }
220 #endif
221 }
222
223 static void
224 print_capabilities (ksba_cert_t cert, estream_t fp)
225 {
226   gpg_error_t err;
227   unsigned int use;
228   size_t buflen;
229   char buffer[1];
230
231   err = ksba_cert_get_user_data (cert, "is_qualified", 
232                                  &buffer, sizeof (buffer), &buflen);
233   if (!err && buflen)
234     {
235       if (*buffer)
236         es_putc ('q', fp);
237     }    
238   else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
239     ; /* Don't know - will not get marked as 'q' */
240   else
241     log_debug ("get_user_data(is_qualified) failed: %s\n",
242                gpg_strerror (err)); 
243
244   err = ksba_cert_get_key_usage (cert, &use);
245   if (gpg_err_code (err) == GPG_ERR_NO_DATA
246       || gpg_err_code (err) == GPG_ERR_NO_VALUE)
247     {
248       es_putc ('e', fp);
249       es_putc ('s', fp);
250       es_putc ('c', fp);
251       es_putc ('E', fp);
252       es_putc ('S', fp);
253       es_putc ('C', fp);
254       return;
255     }
256   if (err)
257     { 
258       log_error (_("error getting key usage information: %s\n"),
259                  gpg_strerror (err));
260       return;
261     } 
262
263   if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
264     es_putc ('e', fp);
265   if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
266     es_putc ('s', fp);
267   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
268     es_putc ('c', fp);
269   if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
270     es_putc ('E', fp);
271   if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
272     es_putc ('S', fp);
273   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
274     es_putc ('C', fp);
275 }
276
277
278 static void
279 print_time (gnupg_isotime_t t, estream_t fp)
280 {
281   if (!t || !*t)
282     ;
283   else 
284     es_fputs (t, fp);
285 }
286
287
288 /* Return an allocated string with the email address extracted from a
289    DN */
290 static char *
291 email_kludge (const char *name)
292 {
293   const char *p, *string;
294   unsigned char *buf;
295   int n;
296
297   string = name;
298   for (;;)
299     {
300       p = strstr (string, "1.2.840.113549.1.9.1=#");
301       if (!p)
302         return NULL;
303       if (p == name || (p > string+1 && p[-1] == ',' && p[-2] != '\\'))
304         {
305           name = p + 22;
306           break;
307         }
308       string = p + 22;
309     }
310
311
312   /* This looks pretty much like an email address in the subject's DN
313      we use this to add an additional user ID entry.  This way,
314      openSSL generated keys get a nicer and usable listing */
315   for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++)
316     ;
317   if (!n)
318     return NULL;
319   buf = xtrymalloc (n+3);
320   if (!buf)
321     return NULL; /* oops, out of core */
322   *buf = '<';
323   for (n=1, p=name; hexdigitp (p); p +=2, n++)
324     buf[n] = xtoi_2 (p);
325   buf[n++] = '>';
326   buf[n] = 0;
327   return (char*)buf;
328 }
329
330
331
332
333 /* List one certificate in colon mode */
334 static void
335 list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
336                  estream_t fp, int have_secret)
337 {
338   int rc;
339   int idx;
340   char truststring[2];
341   char *p;
342   ksba_sexp_t sexp;
343   char *fpr;
344   ksba_isotime_t t;
345   gpg_error_t valerr;
346   int algo;
347   unsigned int nbits;
348   const char *chain_id;
349   char *chain_id_buffer = NULL;
350   int is_root = 0;
351
352   if (ctrl->with_validation)
353     valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL, 0);
354   else
355     valerr = 0;
356
357
358   /* We need to get the fingerprint and the chaining ID in advance. */
359   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
360   {
361     ksba_cert_t next;
362
363     rc = gpgsm_walk_cert_chain (cert, &next);
364     if (!rc) /* We known the issuer's certificate. */
365       {
366         p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1);
367         chain_id_buffer = p;
368         chain_id = chain_id_buffer;
369         ksba_cert_release (next);
370       }
371     else if (rc == -1)  /* We have reached the root certificate. */
372       {
373         chain_id = fpr;
374         is_root = 1;
375       }
376     else
377       chain_id = NULL;
378   }
379
380
381   es_fputs (have_secret? "crs:":"crt:", fp);
382
383   /* Note: We can't use multiple flags, like "ei", because the
384      validation check does only return one error.  */
385   truststring[0] = 0;
386   truststring[1] = 0;
387   if ((validity & VALIDITY_REVOKED)
388       || gpg_err_code (valerr) == GPG_ERR_CERT_REVOKED)
389     *truststring = 'r';
390   else if (gpg_err_code (valerr) == GPG_ERR_CERT_EXPIRED)
391     *truststring = 'e';
392   else 
393     {
394       /* Lets also check whether the certificate under question
395          expired.  This is merely a hack until we found a proper way
396          to store the expiration flag in the keybox. */
397       ksba_isotime_t current_time, not_after;
398   
399       gnupg_get_isotime (current_time);
400       if (!opt.ignore_expiration
401           && !ksba_cert_get_validity (cert, 1, not_after)
402           && *not_after && strcmp (current_time, not_after) > 0 )
403         *truststring = 'e';
404       else if (valerr)
405         *truststring = 'i';
406     }
407
408   /* If we have no truststring yet (i.e. the certificate might be
409      good) and this is a root certificate, we ask the agent whether
410      this is a trusted root certificate. */
411   if (!*truststring && is_root)
412     {
413       struct rootca_flags_s dummy_flags;
414
415       rc = gpgsm_agent_istrusted (ctrl, cert, &dummy_flags);
416       if (!rc)
417         *truststring = 'u';  /* Yes, we trust this one (ultimately). */
418       else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
419         *truststring = 'n';  /* No, we do not trust this one. */
420       /* (in case of an error we can't tell anything.) */
421     }
422   
423   if (*truststring)
424     es_fputs (truststring, fp);
425
426   algo = gpgsm_get_key_algo_info (cert, &nbits);
427   es_fprintf (fp, ":%u:%d:%s:", nbits, algo, fpr+24);
428
429   /* We assume --fixed-list-mode for gpgsm */
430   ksba_cert_get_validity (cert, 0, t);
431   print_time (t, fp);
432   es_putc (':', fp);
433   ksba_cert_get_validity (cert, 1, t);
434   print_time ( t, fp);
435   es_putc (':', fp);
436   /* Field 8, serial number: */
437   if ((sexp = ksba_cert_get_serial (cert)))
438     {
439       int len;
440       const unsigned char *s = sexp;
441       
442       if (*s == '(')
443         {
444           s++;
445           for (len=0; *s && *s != ':' && digitp (s); s++)
446             len = len*10 + atoi_1 (s);
447           if (*s == ':')
448             for (s++; len; len--, s++)
449               es_fprintf (fp,"%02X", *s);
450         }
451       xfree (sexp);
452     }
453   es_putc (':', fp);
454   /* Field 9, ownertrust - not used here */
455   es_putc (':', fp);
456   /* field 10, old user ID - we use it here for the issuer DN */
457   if ((p = ksba_cert_get_issuer (cert,0)))
458     {
459       es_write_sanitized (fp, p, strlen (p), ":", NULL);
460       xfree (p);
461     }
462   es_putc (':', fp);
463   /* Field 11, signature class - not used */ 
464   es_putc (':', fp);
465   /* Field 12, capabilities: */ 
466   print_capabilities (cert, fp);
467   es_putc (':', fp);
468   es_putc ('\n', fp);
469
470   /* FPR record */
471   es_fprintf (fp, "fpr:::::::::%s:::", fpr);
472   /* Print chaining ID (field 13)*/
473   if (chain_id)
474     es_fputs (chain_id, fp);
475   es_putc (':', fp);
476   es_putc ('\n', fp);
477   xfree (fpr); fpr = NULL; chain_id = NULL;
478   xfree (chain_id_buffer); chain_id_buffer = NULL;
479
480   if (opt.with_key_data)
481     {
482       if ( (p = gpgsm_get_keygrip_hexstring (cert)))
483         {
484           es_fprintf (fp, "grp:::::::::%s:\n", p);
485           xfree (p);
486         }
487       print_key_data (cert, fp);
488     }
489
490   for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++)
491     {
492       es_fprintf (fp, "uid:%s::::::::", truststring);
493       es_write_sanitized (fp, p, strlen (p), ":", NULL);
494       es_putc (':', fp);
495       es_putc (':', fp);
496       es_putc ('\n', fp);
497       if (!idx)
498         {
499           /* It would be better to get the faked email address from
500              the keydb.  But as long as we don't have a way to pass
501              the meta data back, we just check it the same way as the
502              code used to create the keybox meta data does */
503           char *pp = email_kludge (p);
504           if (pp)
505             {
506               es_fprintf (fp, "uid:%s::::::::", truststring);
507               es_write_sanitized (fp, pp, strlen (pp), ":", NULL);
508               es_putc (':', fp);
509               es_putc (':', fp);
510               es_putc ('\n', fp);
511               xfree (pp);
512             }
513         }
514       xfree (p);
515     }
516 }
517
518
519 static void
520 print_name_raw (estream_t fp, const char *string)
521 {
522   if (!string)
523     es_fputs ("[error]", fp);
524   else
525     es_write_sanitized (fp, string, strlen (string), NULL, NULL);
526 }
527
528 static void
529 print_names_raw (estream_t fp, int indent, ksba_name_t name)
530 {
531   int idx;
532   const char *s;
533   int indent_all;
534
535   if ((indent_all = (indent < 0)))
536     indent = - indent;
537
538   if (!name)
539     {
540       es_fputs ("none\n", fp);
541       return;
542     }
543   
544   for (idx=0; (s = ksba_name_enum (name, idx)); idx++)
545     {
546       char *p = ksba_name_get_uri (name, idx);
547       es_fprintf (fp, "%*s", idx||indent_all?indent:0, "");
548       es_write_sanitized (fp, p?p:s, strlen (p?p:s), NULL, NULL);
549       es_putc ('\n', fp);
550       xfree (p);
551     }
552 }
553
554
555 /* List one certificate in raw mode useful to have a closer look at
556    the certificate.  This one does no beautification and only minimal
557    output sanitation.  It is mainly useful for debugging. */
558 static void
559 list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd,
560                ksba_cert_t cert, estream_t fp, int have_secret,
561                int with_validation)
562 {
563   gpg_error_t err;
564   size_t off, len;
565   ksba_sexp_t sexp, keyid;
566   char *dn;
567   ksba_isotime_t t;
568   int idx, i;
569   int is_ca, chainlen;
570   unsigned int kusage;
571   char *string, *p, *pend;
572   const char *oid, *s;
573   ksba_name_t name, name2;
574   unsigned int reason;
575
576   sexp = ksba_cert_get_serial (cert);
577   es_fputs ("Serial number: ", fp);
578   gpgsm_print_serial (fp, sexp);
579   ksba_free (sexp);
580   es_putc ('\n', fp);
581
582   dn = ksba_cert_get_issuer (cert, 0);
583   es_fputs ("       Issuer: ", fp);
584   print_name_raw (fp, dn);
585   ksba_free (dn);
586   es_putc ('\n', fp);
587   for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
588     {
589       es_fputs ("          aka: ", fp);
590       print_name_raw (fp, dn);
591       ksba_free (dn);
592       es_putc ('\n', fp);
593     }
594
595   dn = ksba_cert_get_subject (cert, 0);
596   es_fputs ("      Subject: ", fp);
597   print_name_raw (fp, dn);
598   ksba_free (dn);
599   es_putc ('\n', fp);
600   for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
601     {
602       es_fputs ("          aka: ", fp);
603       print_name_raw (fp, dn);
604       ksba_free (dn);
605       es_putc ('\n', fp);
606     }
607
608   dn = gpgsm_get_fingerprint_string (cert, 0);
609   es_fprintf (fp, "     sha1_fpr: %s\n", dn?dn:"error");
610   xfree (dn);
611
612   dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5);
613   es_fprintf (fp, "      md5_fpr: %s\n", dn?dn:"error");
614   xfree (dn);
615
616   dn = gpgsm_get_certid (cert);
617   es_fprintf (fp, "       certid: %s\n", dn?dn:"error");
618   xfree (dn);
619
620   dn = gpgsm_get_keygrip_hexstring (cert);
621   es_fprintf (fp, "      keygrip: %s\n", dn?dn:"error");
622   xfree (dn);
623
624   ksba_cert_get_validity (cert, 0, t);
625   es_fputs ("    notBefore: ", fp);
626   gpgsm_print_time (fp, t);
627   es_putc ('\n', fp);
628   es_fputs ("     notAfter: ", fp);
629   ksba_cert_get_validity (cert, 1, t);
630   gpgsm_print_time (fp, t);
631   es_putc ('\n', fp);
632
633   oid = ksba_cert_get_digest_algo (cert);
634   s = get_oid_desc (oid, NULL);
635   es_fprintf (fp, "     hashAlgo: %s%s%s%s\n", oid, s?" (":"",s?s:"",s?")":"");
636
637   {
638     const char *algoname;
639     unsigned int nbits;
640
641     algoname = gcry_pk_algo_name (gpgsm_get_key_algo_info (cert, &nbits));
642     es_fprintf (fp, "      keyType: %u bit %s\n",
643                 nbits, algoname? algoname:"?");
644   }
645
646   /* subjectKeyIdentifier */
647   es_fputs ("    subjKeyId: ", fp);
648   err = ksba_cert_get_subj_key_id (cert, NULL, &keyid);
649   if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA
650       || gpg_err_code (err) == GPG_ERR_NO_VALUE)
651     {
652       if (gpg_err_code (err) == GPG_ERR_NO_DATA
653           || gpg_err_code (err) == GPG_ERR_NO_VALUE)
654         es_fputs ("[none]\n", fp);
655       else
656         {
657           gpgsm_print_serial (fp, keyid);
658           ksba_free (keyid);
659           es_putc ('\n', fp);
660         }
661     }
662   else
663     es_fputs ("[?]\n", fp);
664
665
666   /* authorityKeyIdentifier */
667   es_fputs ("    authKeyId: ", fp);
668   err = ksba_cert_get_auth_key_id (cert, &keyid, &name, &sexp);
669   if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA
670       || gpg_err_code (err) == GPG_ERR_NO_VALUE)
671     {
672       if (gpg_err_code (err) == GPG_ERR_NO_DATA || !name
673           || gpg_err_code (err) == GPG_ERR_NO_VALUE)
674         es_fputs ("[none]\n", fp);
675       else
676         {
677           gpgsm_print_serial (fp, sexp);
678           ksba_free (sexp);
679           es_putc ('\n', fp);
680           print_names_raw (fp, -15, name);
681           ksba_name_release (name);
682         }
683       if (keyid)
684         {
685           es_fputs (" authKeyId.ki: ", fp);
686           gpgsm_print_serial (fp, keyid);
687           ksba_free (keyid);
688           es_putc ('\n', fp);
689         }
690     }
691   else
692     es_fputs ("[?]\n", fp);
693
694   es_fputs ("     keyUsage:", fp);
695   err = ksba_cert_get_key_usage (cert, &kusage);
696   if (gpg_err_code (err) != GPG_ERR_NO_DATA
697       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
698     {
699       if (err)
700         es_fprintf (fp, " [error: %s]", gpg_strerror (err));
701       else
702         {
703           if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
704             es_fputs (" digitalSignature", fp);
705           if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))  
706             es_fputs (" nonRepudiation", fp);
707           if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT)) 
708             es_fputs (" keyEncipherment", fp);
709           if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
710             es_fputs (" dataEncipherment", fp);
711           if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))    
712             es_fputs (" keyAgreement", fp);
713           if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
714             es_fputs (" certSign", fp);
715           if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))  
716             es_fputs (" crlSign", fp);
717           if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
718             es_fputs (" encipherOnly", fp);
719           if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))  
720             es_fputs (" decipherOnly", fp);
721         }
722       es_putc ('\n', fp);
723     }
724   else
725     es_fputs (" [none]\n", fp);
726
727   es_fputs ("  extKeyUsage: ", fp);
728   err = ksba_cert_get_ext_key_usages (cert, &string);
729   if (gpg_err_code (err) != GPG_ERR_NO_DATA
730       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
731     { 
732       if (err)
733         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
734       else
735         {
736           p = string;
737           while (p && (pend=strchr (p, ':')))
738             {
739               *pend++ = 0;
740               for (i=0; key_purpose_map[i].oid; i++)
741                 if ( !strcmp (key_purpose_map[i].oid, p) )
742                   break;
743               es_fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
744               p = pend;
745               if (*p != 'C')
746                 es_fputs (" (suggested)", fp);
747               if ((p = strchr (p, '\n')))
748                 {
749                   p++;
750                   es_fputs ("\n               ", fp);
751                 }
752             }
753           xfree (string);
754         }
755       es_putc ('\n', fp);
756     }
757   else
758     es_fputs ("[none]\n", fp);
759
760
761   es_fputs ("     policies: ", fp);
762   err = ksba_cert_get_cert_policies (cert, &string);
763   if (gpg_err_code (err) != GPG_ERR_NO_DATA
764       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
765     {
766       if (err)
767         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
768       else
769         {
770           p = string;
771           while (p && (pend=strchr (p, ':')))
772             {
773               *pend++ = 0;
774               for (i=0; key_purpose_map[i].oid; i++)
775                 if ( !strcmp (key_purpose_map[i].oid, p) )
776                   break;
777               es_fputs (p, fp);
778               p = pend;
779               if (*p == 'C')
780                 es_fputs (" (critical)", fp);
781               if ((p = strchr (p, '\n')))
782                 {
783                   p++;
784                   es_fputs ("\n               ", fp);
785                 }
786             }
787           xfree (string);
788         }
789       es_putc ('\n', fp);
790     }
791   else
792     es_fputs ("[none]\n", fp);
793
794   es_fputs ("  chainLength: ", fp);
795   err = ksba_cert_is_ca (cert, &is_ca, &chainlen);
796   if (err || is_ca)
797     {
798       if (gpg_err_code (err) == GPG_ERR_NO_VALUE )
799         es_fprintf (fp, "[none]");
800       else if (err)
801         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
802       else if (chainlen == -1)
803         es_fputs ("unlimited", fp);
804       else
805         es_fprintf (fp, "%d", chainlen);
806       es_putc ('\n', fp);
807     }
808   else
809     es_fputs ("not a CA\n", fp);
810
811
812   /* CRL distribution point */
813   for (idx=0; !(err=ksba_cert_get_crl_dist_point (cert, idx, &name, &name2,
814                                                   &reason)) ;idx++)
815     {
816       es_fputs ("        crlDP: ", fp);
817       print_names_raw (fp, 15, name);
818       if (reason)
819         {
820           es_fputs ("               reason: ", fp);
821           if ( (reason & KSBA_CRLREASON_UNSPECIFIED))
822             es_fputs (" unused", fp);
823           if ( (reason & KSBA_CRLREASON_KEY_COMPROMISE))
824             es_fputs (" keyCompromise", fp);
825           if ( (reason & KSBA_CRLREASON_CA_COMPROMISE))
826             es_fputs (" caCompromise", fp);
827           if ( (reason & KSBA_CRLREASON_AFFILIATION_CHANGED))
828             es_fputs (" affiliationChanged", fp);
829           if ( (reason & KSBA_CRLREASON_SUPERSEDED))
830             es_fputs (" superseded", fp);
831           if ( (reason & KSBA_CRLREASON_CESSATION_OF_OPERATION))
832             es_fputs (" cessationOfOperation", fp);
833           if ( (reason & KSBA_CRLREASON_CERTIFICATE_HOLD))
834             es_fputs (" certificateHold", fp);
835           es_putc ('\n', fp);
836         }
837       es_fputs ("               issuer: ", fp);
838       print_names_raw (fp, 23, name2);
839       ksba_name_release (name);
840       ksba_name_release (name2);
841     }
842   if (err && gpg_err_code (err) != GPG_ERR_EOF
843       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
844     es_fputs ("        crlDP: [error]\n", fp);
845   else if (!idx)
846     es_fputs ("        crlDP: [none]\n", fp);
847
848
849   /* authorityInfoAccess. */
850   for (idx=0; !(err=ksba_cert_get_authority_info_access (cert, idx, &string,
851                                                          &name)); idx++)
852     {
853       es_fputs ("     authInfo: ", fp);
854       s = get_oid_desc (string, NULL);
855       es_fprintf (fp, "%s%s%s%s\n", string, s?" (":"", s?s:"", s?")":"");
856       print_names_raw (fp, -15, name);
857       ksba_name_release (name);
858       ksba_free (string);
859     }
860   if (err && gpg_err_code (err) != GPG_ERR_EOF
861       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
862     es_fputs ("     authInfo: [error]\n", fp);
863   else if (!idx)
864     es_fputs ("     authInfo: [none]\n", fp);
865
866   /* subjectInfoAccess. */
867   for (idx=0; !(err=ksba_cert_get_subject_info_access (cert, idx, &string,
868                                                          &name)); idx++)
869     {
870       es_fputs ("  subjectInfo: ", fp);
871       s = get_oid_desc (string, NULL);
872       es_fprintf (fp, "%s%s%s%s\n", string, s?" (":"", s?s:"", s?")":"");
873       print_names_raw (fp, -15, name);
874       ksba_name_release (name);
875       ksba_free (string);
876     }
877   if (err && gpg_err_code (err) != GPG_ERR_EOF
878       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
879     es_fputs ("     subjInfo: [error]\n", fp);
880   else if (!idx)
881     es_fputs ("     subjInfo: [none]\n", fp);
882
883
884   for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
885                                              &oid, &i, &off, &len));idx++)
886     {
887       unsigned int flag;
888
889       s = get_oid_desc (oid, &flag);
890
891       if (!(flag & 1))
892         es_fprintf (fp, "     %s: %s%s%s%s  [%d octets]\n",
893                  i? "critExtn":"    extn",
894                  oid, s?" (":"", s?s:"", s?")":"", (int)len);
895     }
896
897
898   if (with_validation)
899     {
900       err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp, 0);
901       if (!err)
902         es_fprintf (fp, "  [certificate is good]\n");
903       else
904         es_fprintf (fp, "  [certificate is bad: %s]\n", gpg_strerror (err));
905     }
906
907   if (opt.with_ephemeral_keys && hd)
908     {
909       unsigned int blobflags;
910
911       err = keydb_get_flags (hd, KEYBOX_FLAG_BLOB, 0, &blobflags);
912       if (err)
913         es_fprintf (fp, "  [error getting keyflags: %s]\n",gpg_strerror (err));
914       else if ((blobflags & KEYBOX_FLAG_BLOB_EPHEMERAL))
915         es_fprintf (fp, "  [stored as ephemeral]\n");
916     }
917
918 }
919
920
921
922
923 /* List one certificate in standard mode */
924 static void
925 list_cert_std (ctrl_t ctrl, ksba_cert_t cert, estream_t fp, int have_secret,
926                int with_validation)
927 {
928   gpg_error_t err;
929   ksba_sexp_t sexp;
930   char *dn;
931   ksba_isotime_t t;
932   int idx, i;
933   int is_ca, chainlen;
934   unsigned int kusage;
935   char *string, *p, *pend;
936
937   sexp = ksba_cert_get_serial (cert);
938   es_fputs ("Serial number: ", fp);
939   gpgsm_print_serial (fp, sexp);
940   ksba_free (sexp);
941   es_putc ('\n', fp);
942
943   dn = ksba_cert_get_issuer (cert, 0);
944   es_fputs ("       Issuer: ", fp);
945   gpgsm_es_print_name (fp, dn);
946   ksba_free (dn);
947   es_putc ('\n', fp);
948   for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
949     {
950       es_fputs ("          aka: ", fp);
951       gpgsm_es_print_name (fp, dn);
952       ksba_free (dn);
953       es_putc ('\n', fp);
954     }
955
956   dn = ksba_cert_get_subject (cert, 0);
957   es_fputs ("      Subject: ", fp);
958   gpgsm_es_print_name (fp, dn);
959   ksba_free (dn);
960   es_putc ('\n', fp);
961   for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
962     {
963       es_fputs ("          aka: ", fp);
964       gpgsm_es_print_name (fp, dn);
965       ksba_free (dn);
966       es_putc ('\n', fp);
967     }
968
969   ksba_cert_get_validity (cert, 0, t);
970   es_fputs ("     validity: ", fp);
971   gpgsm_print_time (fp, t);
972   es_fputs (" through ", fp);
973   ksba_cert_get_validity (cert, 1, t);
974   gpgsm_print_time (fp, t);
975   es_putc ('\n', fp);
976
977
978   {
979     const char *algoname;
980     unsigned int nbits;
981
982     algoname = gcry_pk_algo_name (gpgsm_get_key_algo_info (cert, &nbits));
983     es_fprintf (fp, "     key type: %u bit %s\n",
984                 nbits, algoname? algoname:"?");
985   }
986
987
988   err = ksba_cert_get_key_usage (cert, &kusage);
989   if (gpg_err_code (err) != GPG_ERR_NO_DATA
990       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
991     {
992       es_fputs ("    key usage:", fp);
993       if (err)
994         es_fprintf (fp, " [error: %s]", gpg_strerror (err));
995       else
996         {
997           if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
998             es_fputs (" digitalSignature", fp);
999           if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))  
1000             es_fputs (" nonRepudiation", fp);
1001           if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT)) 
1002             es_fputs (" keyEncipherment", fp);
1003           if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
1004             es_fputs (" dataEncipherment", fp);
1005           if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))    
1006             es_fputs (" keyAgreement", fp);
1007           if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
1008             es_fputs (" certSign", fp);
1009           if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))  
1010             es_fputs (" crlSign", fp);
1011           if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
1012             es_fputs (" encipherOnly", fp);
1013           if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))  
1014             es_fputs (" decipherOnly", fp);
1015         }
1016       es_putc ('\n', fp);
1017     }
1018
1019   err = ksba_cert_get_ext_key_usages (cert, &string);
1020   if (gpg_err_code (err) != GPG_ERR_NO_DATA
1021       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
1022     { 
1023       es_fputs ("ext key usage: ", fp);
1024       if (err)
1025         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
1026       else
1027         {
1028           p = string;
1029           while (p && (pend=strchr (p, ':')))
1030             {
1031               *pend++ = 0;
1032               for (i=0; key_purpose_map[i].oid; i++)
1033                 if ( !strcmp (key_purpose_map[i].oid, p) )
1034                   break;
1035               es_fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
1036               p = pend;
1037               if (*p != 'C')
1038                 es_fputs (" (suggested)", fp);
1039               if ((p = strchr (p, '\n')))
1040                 {
1041                   p++;
1042                   es_fputs (", ", fp);
1043                 }
1044             }
1045           xfree (string);
1046         }
1047       es_putc ('\n', fp);
1048     }
1049
1050   err = ksba_cert_get_cert_policies (cert, &string);
1051   if (gpg_err_code (err) != GPG_ERR_NO_DATA
1052       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
1053     {
1054       es_fputs ("     policies: ", fp);
1055       if (err)
1056         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
1057       else
1058         {
1059           for (p=string; *p; p++)
1060             {
1061               if (*p == '\n')
1062                 *p = ',';
1063             }
1064           es_write_sanitized (fp, string, strlen (string), NULL, NULL);
1065           xfree (string);
1066         }
1067       es_putc ('\n', fp);
1068     }
1069
1070   err = ksba_cert_is_ca (cert, &is_ca, &chainlen);
1071   if (err || is_ca)
1072     {
1073       es_fputs (" chain length: ", fp);
1074       if (gpg_err_code (err) == GPG_ERR_NO_VALUE )
1075         es_fprintf (fp, "none");
1076       else if (err)
1077         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
1078       else if (chainlen == -1)
1079         es_fputs ("unlimited", fp);
1080       else
1081         es_fprintf (fp, "%d", chainlen);
1082       es_putc ('\n', fp);
1083     }
1084
1085   if (opt.with_md5_fingerprint)
1086     {
1087       dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5);
1088       es_fprintf (fp, "      md5 fpr: %s\n", dn?dn:"error");
1089       xfree (dn);
1090     }
1091
1092   dn = gpgsm_get_fingerprint_string (cert, 0);
1093   es_fprintf (fp, "  fingerprint: %s\n", dn?dn:"error");
1094   xfree (dn);
1095
1096
1097
1098   if (with_validation)
1099     {
1100       gpg_error_t tmperr;
1101       size_t buflen;
1102       char buffer[1];
1103       
1104       err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp, 0);
1105       tmperr = ksba_cert_get_user_data (cert, "is_qualified", 
1106                                         &buffer, sizeof (buffer), &buflen);
1107       if (!tmperr && buflen)
1108         {
1109           if (*buffer)
1110             es_fputs ("  [qualified]\n", fp);
1111         }    
1112       else if (gpg_err_code (tmperr) == GPG_ERR_NOT_FOUND)
1113         ; /* Don't know - will not get marked as 'q' */
1114       else
1115         log_debug ("get_user_data(is_qualified) failed: %s\n",
1116                    gpg_strerror (tmperr)); 
1117
1118       if (!err)
1119         es_fprintf (fp, "  [certificate is good]\n");
1120       else
1121         es_fprintf (fp, "  [certificate is bad: %s]\n", gpg_strerror (err));
1122     }
1123 }
1124
1125
1126 /* Same as standard mode mode list all certifying certs too. */
1127 static void
1128 list_cert_chain (ctrl_t ctrl, KEYDB_HANDLE hd,
1129                  ksba_cert_t cert, int raw_mode,
1130                  estream_t fp, int with_validation)
1131 {
1132   ksba_cert_t next = NULL;
1133
1134   if (raw_mode)
1135     list_cert_raw (ctrl, hd, cert, fp, 0, with_validation);
1136   else
1137     list_cert_std (ctrl, cert, fp, 0, with_validation);
1138   ksba_cert_ref (cert);
1139   while (!gpgsm_walk_cert_chain (cert, &next))
1140     {
1141       ksba_cert_release (cert);
1142       es_fputs ("Certified by\n", fp);
1143       if (raw_mode)
1144         list_cert_raw (ctrl, hd, next, fp, 0, with_validation);
1145       else
1146         list_cert_std (ctrl, next, fp, 0, with_validation);
1147       cert = next;
1148     }
1149   ksba_cert_release (cert);
1150   es_putc ('\n', fp);
1151 }
1152
1153
1154 \f
1155 /* List all internal keys or just the keys given as NAMES.  MODE is a
1156    bit vector to specify what keys are to be included; see
1157    gpgsm_list_keys (below) for details.  If RAW_MODE is true, the raw
1158    output mode will be used instead of the standard beautified one.
1159  */
1160 static gpg_error_t
1161 list_internal_keys (ctrl_t ctrl, strlist_t names, estream_t fp,
1162                     unsigned int mode, int raw_mode)
1163 {
1164   KEYDB_HANDLE hd;
1165   KEYDB_SEARCH_DESC *desc = NULL;
1166   strlist_t sl;
1167   int ndesc;
1168   ksba_cert_t cert = NULL;
1169   gpg_error_t rc = 0;
1170   const char *lastresname, *resname;
1171   int have_secret;
1172
1173   hd = keydb_new (0);
1174   if (!hd)
1175     {
1176       log_error ("keydb_new failed\n");
1177       rc = gpg_error (GPG_ERR_GENERAL);
1178       goto leave;
1179     }
1180
1181   if (!names)
1182     ndesc = 1;
1183   else
1184     {
1185       for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) 
1186         ;
1187     }
1188
1189   desc = xtrycalloc (ndesc, sizeof *desc);
1190   if (!ndesc)
1191     {
1192       rc = gpg_error_from_syserror ();
1193       log_error ("out of core\n");
1194       goto leave;
1195     }
1196
1197   if (!names)
1198     desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
1199   else 
1200     {
1201       for (ndesc=0, sl=names; sl; sl = sl->next) 
1202         {
1203           rc = keydb_classify_name (sl->d, desc+ndesc);
1204           if (rc)
1205             {
1206               log_error ("key `%s' not found: %s\n",
1207                          sl->d, gpg_strerror (rc));
1208               rc = 0;
1209             }
1210           else
1211             ndesc++;
1212         }
1213       
1214     }
1215
1216   if (opt.with_ephemeral_keys)
1217     keydb_set_ephemeral (hd, 1);
1218
1219   /* It would be nice to see which of the given users did actually
1220      match one in the keyring.  To implement this we need to have a
1221      found flag for each entry in desc and to set this we must check
1222      all those entries after a match to mark all matched one -
1223      currently we stop at the first match.  To do this we need an
1224      extra flag to enable this feature so */
1225
1226   lastresname = NULL;
1227   while (!(rc = keydb_search (hd, desc, ndesc)))
1228     {
1229       unsigned int validity;
1230
1231       if (!names) 
1232         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
1233
1234       rc = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &validity);
1235       if (rc)
1236         {
1237           log_error ("keydb_get_flags failed: %s\n", gpg_strerror (rc));
1238           goto leave;
1239         }
1240       rc = keydb_get_cert (hd, &cert);
1241       if (rc) 
1242         {
1243           log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
1244           goto leave;
1245         }
1246       
1247       resname = keydb_get_resource_name (hd);
1248       
1249       if (lastresname != resname ) 
1250         {
1251           int i;
1252           
1253           if (ctrl->no_server)
1254             {
1255               es_fprintf (fp, "%s\n", resname );
1256               for (i=strlen(resname); i; i-- )
1257                 es_putc ('-', fp);
1258               es_putc ('\n', fp);
1259               lastresname = resname;
1260             }
1261         }
1262
1263       have_secret = 0;
1264       if (mode)
1265         {
1266           char *p = gpgsm_get_keygrip_hexstring (cert);
1267           if (p)
1268             {
1269               rc = gpgsm_agent_havekey (ctrl, p); 
1270              if (!rc)
1271                 have_secret = 1;
1272               else if ( gpg_err_code (rc) != GPG_ERR_NO_SECKEY)
1273                 goto leave;
1274               rc = 0;
1275               xfree (p);
1276             }
1277         }
1278
1279       if (!mode
1280           || ((mode & 1) && !have_secret)
1281           || ((mode & 2) && have_secret)  )
1282         {
1283           if (ctrl->with_colons)
1284             list_cert_colon (ctrl, cert, validity, fp, have_secret);
1285           else if (ctrl->with_chain)
1286             list_cert_chain (ctrl, hd, cert,
1287                              raw_mode, fp, ctrl->with_validation);
1288           else
1289             {
1290               if (raw_mode)
1291                 list_cert_raw (ctrl, hd, cert, fp, have_secret,
1292                                ctrl->with_validation);
1293               else
1294                 list_cert_std (ctrl, cert, fp, have_secret,
1295                                ctrl->with_validation);
1296               es_putc ('\n', fp);
1297             }
1298         }
1299       ksba_cert_release (cert); 
1300       cert = NULL;
1301     }
1302   if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1 )
1303     rc = 0;
1304   if (rc)
1305     log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
1306   
1307  leave:
1308   ksba_cert_release (cert);
1309   xfree (desc);
1310   keydb_release (hd);
1311   return rc;
1312 }
1313
1314
1315
1316 static void
1317 list_external_cb (void *cb_value, ksba_cert_t cert)
1318 {
1319   struct list_external_parm_s *parm = cb_value;
1320
1321   if (keydb_store_cert (cert, 1, NULL))
1322     log_error ("error storing certificate as ephemeral\n");
1323
1324   if (parm->print_header)
1325     {
1326       const char *resname = "[external keys]";
1327       int i;
1328
1329       es_fprintf (parm->fp, "%s\n", resname );
1330       for (i=strlen(resname); i; i-- )
1331         es_putc('-', parm->fp);
1332       es_putc ('\n', parm->fp);
1333       parm->print_header = 0;
1334     }
1335
1336   if (parm->with_colons)
1337     list_cert_colon (parm->ctrl, cert, 0, parm->fp, 0);
1338   else if (parm->with_chain)
1339     list_cert_chain (parm->ctrl, NULL, cert, parm->raw_mode, parm->fp, 0);
1340   else
1341     {
1342       if (parm->raw_mode)
1343         list_cert_raw (parm->ctrl, NULL, cert, parm->fp, 0, 0);
1344       else
1345         list_cert_std (parm->ctrl, cert, parm->fp, 0, 0);
1346       es_putc ('\n', parm->fp);
1347     }
1348 }
1349
1350
1351 /* List external keys similar to internal one.  Note: mode does not
1352    make sense here because it would be unwise to list external secret
1353    keys */
1354 static gpg_error_t
1355 list_external_keys (ctrl_t ctrl, strlist_t names, estream_t fp, int raw_mode)
1356 {
1357   int rc;
1358   struct list_external_parm_s parm;
1359
1360   parm.fp = fp;
1361   parm.ctrl = ctrl,
1362   parm.print_header = ctrl->no_server;
1363   parm.with_colons = ctrl->with_colons;
1364   parm.with_chain = ctrl->with_chain;
1365   parm.raw_mode  = raw_mode;
1366
1367   rc = gpgsm_dirmngr_lookup (ctrl, names, list_external_cb, &parm);
1368   if (rc)
1369     log_error ("listing external keys failed: %s\n", gpg_strerror (rc));
1370   return rc;
1371 }
1372
1373 /* List all keys or just the key given as NAMES.
1374    MODE controls the operation mode: 
1375     Bit 0-2:
1376       0 = list all public keys but don't flag secret ones
1377       1 = list only public keys
1378       2 = list only secret keys
1379       3 = list secret and public keys
1380     Bit 6: list internal keys
1381     Bit 7: list external keys
1382     Bit 8: Do a raw format dump.
1383  */
1384 gpg_error_t
1385 gpgsm_list_keys (ctrl_t ctrl, strlist_t names, estream_t fp,
1386                  unsigned int mode)
1387 {
1388   gpg_error_t err = 0;
1389
1390   if ((mode & (1<<6)))
1391     err = list_internal_keys (ctrl, names, fp, (mode & 3), (mode&256));
1392   if (!err && (mode & (1<<7)))
1393     err = list_external_keys (ctrl, names, fp, (mode&256)); 
1394   return err;
1395 }