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