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