Changed to GPLv3.
[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   { NULL }
180 };
181
182
183 /* Return the description for OID; if no description is available 
184    NULL is returned. */
185 static const char *
186 get_oid_desc (const char *oid, unsigned int *flag)
187 {
188   int i;
189
190   if (oid)
191     for (i=0; oidtranstbl[i].oid; i++)
192       if (!strcmp (oidtranstbl[i].oid, oid))
193         {
194           if (flag)
195             *flag = oidtranstbl[i].flag;
196           return oidtranstbl[i].name;
197         }
198   if (flag)
199     *flag = 0;
200   return NULL;
201 }
202
203
204 static void
205 print_key_data (ksba_cert_t cert, estream_t fp)
206 {
207 #if 0  
208   int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
209   int i;
210
211   for(i=0; i < n; i++ ) 
212     {
213       es_fprintf (fp, "pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) );
214       mpi_print(stdout, pk->pkey[i], 1 );
215       putchar(':');
216       putchar('\n');
217     }
218 #endif
219 }
220
221 static void
222 print_capabilities (ksba_cert_t cert, estream_t fp)
223 {
224   gpg_error_t err;
225   unsigned int use;
226   size_t buflen;
227   char buffer[1];
228
229   err = ksba_cert_get_user_data (cert, "is_qualified", 
230                                  &buffer, sizeof (buffer), &buflen);
231   if (!err && buflen)
232     {
233       if (*buffer)
234         es_putc ('q', fp);
235     }    
236   else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
237     ; /* Don't know - will not get marked as 'q' */
238   else
239     log_debug ("get_user_data(is_qualified) failed: %s\n",
240                gpg_strerror (err)); 
241
242   err = ksba_cert_get_key_usage (cert, &use);
243   if (gpg_err_code (err) == GPG_ERR_NO_DATA)
244     {
245       es_putc ('e', fp);
246       es_putc ('s', fp);
247       es_putc ('c', fp);
248       es_putc ('E', fp);
249       es_putc ('S', fp);
250       es_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     es_putc ('e', fp);
262   if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
263     es_putc ('s', fp);
264   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
265     es_putc ('c', fp);
266   if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
267     es_putc ('E', fp);
268   if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
269     es_putc ('S', fp);
270   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
271     es_putc ('C', fp);
272 }
273
274
275 static void
276 print_time (gnupg_isotime_t t, estream_t fp)
277 {
278   if (!t || !*t)
279     ;
280   else 
281     es_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                  estream_t 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   es_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     es_fputs (truststring, fp);
422
423   algo = gpgsm_get_key_algo_info (cert, &nbits);
424   es_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   es_putc (':', fp);
430   ksba_cert_get_validity (cert, 1, t);
431   print_time ( t, fp);
432   es_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               es_fprintf (fp,"%02X", *s);
447         }
448       xfree (sexp);
449     }
450   es_putc (':', fp);
451   /* Field 9, ownertrust - not used here */
452   es_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       es_write_sanitized (fp, p, strlen (p), ":", NULL);
457       xfree (p);
458     }
459   es_putc (':', fp);
460   /* Field 11, signature class - not used */ 
461   es_putc (':', fp);
462   /* Field 12, capabilities: */ 
463   print_capabilities (cert, fp);
464   es_putc (':', fp);
465   es_putc ('\n', fp);
466
467   /* FPR record */
468   es_fprintf (fp, "fpr:::::::::%s:::", fpr);
469   /* Print chaining ID (field 13)*/
470   if (chain_id)
471     es_fputs (chain_id, fp);
472   es_putc (':', fp);
473   es_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           es_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       es_fprintf (fp, "uid:%s::::::::", truststring);
490       es_write_sanitized (fp, p, strlen (p), ":", NULL);
491       es_putc (':', fp);
492       es_putc (':', fp);
493       es_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               es_fprintf (fp, "uid:%s::::::::", truststring);
504               es_write_sanitized (fp, pp, strlen (pp), ":", NULL);
505               es_putc (':', fp);
506               es_putc (':', fp);
507               es_putc ('\n', fp);
508               xfree (pp);
509             }
510         }
511       xfree (p);
512     }
513 }
514
515
516 static void
517 print_name_raw (estream_t fp, const char *string)
518 {
519   if (!string)
520     es_fputs ("[error]", fp);
521   else
522     es_write_sanitized (fp, string, strlen (string), NULL, NULL);
523 }
524
525 static void
526 print_names_raw (estream_t 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       es_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       es_fprintf (fp, "%*s", idx||indent_all?indent:0, "");
545       es_write_sanitized (fp, p?p:s, strlen (p?p:s), NULL, NULL);
546       es_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, estream_t 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   es_fputs ("Serial number: ", fp);
575   gpgsm_print_serial (fp, sexp);
576   ksba_free (sexp);
577   es_putc ('\n', fp);
578
579   dn = ksba_cert_get_issuer (cert, 0);
580   es_fputs ("       Issuer: ", fp);
581   print_name_raw (fp, dn);
582   ksba_free (dn);
583   es_putc ('\n', fp);
584   for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
585     {
586       es_fputs ("          aka: ", fp);
587       print_name_raw (fp, dn);
588       ksba_free (dn);
589       es_putc ('\n', fp);
590     }
591
592   dn = ksba_cert_get_subject (cert, 0);
593   es_fputs ("      Subject: ", fp);
594   print_name_raw (fp, dn);
595   ksba_free (dn);
596   es_putc ('\n', fp);
597   for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
598     {
599       es_fputs ("          aka: ", fp);
600       print_name_raw (fp, dn);
601       ksba_free (dn);
602       es_putc ('\n', fp);
603     }
604
605   dn = gpgsm_get_fingerprint_string (cert, 0);
606   es_fprintf (fp, "     sha1_fpr: %s\n", dn?dn:"error");
607   xfree (dn);
608
609   dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5);
610   es_fprintf (fp, "      md5_fpr: %s\n", dn?dn:"error");
611   xfree (dn);
612
613   dn = gpgsm_get_certid (cert);
614   es_fprintf (fp, "       certid: %s\n", dn?dn:"error");
615   xfree (dn);
616
617   dn = gpgsm_get_keygrip_hexstring (cert);
618   es_fprintf (fp, "      keygrip: %s\n", dn?dn:"error");
619   xfree (dn);
620
621   ksba_cert_get_validity (cert, 0, t);
622   es_fputs ("    notBefore: ", fp);
623   gpgsm_print_time (fp, t);
624   es_putc ('\n', fp);
625   es_fputs ("     notAfter: ", fp);
626   ksba_cert_get_validity (cert, 1, t);
627   gpgsm_print_time (fp, t);
628   es_putc ('\n', fp);
629
630   oid = ksba_cert_get_digest_algo (cert);
631   s = get_oid_desc (oid, NULL);
632   es_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     es_fprintf (fp, "      keyType: %u bit %s\n",
640                 nbits, algoname? algoname:"?");
641   }
642
643   /* subjectKeyIdentifier */
644   es_fputs ("    subjKeyId: ", fp);
645   err = ksba_cert_get_subj_key_id (cert, NULL, &keyid);
646   if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA)
647     {
648       if (gpg_err_code (err) == GPG_ERR_NO_DATA)
649         es_fputs ("[none]\n", fp);
650       else
651         {
652           gpgsm_print_serial (fp, keyid);
653           ksba_free (keyid);
654           es_putc ('\n', fp);
655         }
656     }
657   else
658     es_fputs ("[?]\n", fp);
659
660
661   /* authorityKeyIdentifier */
662   es_fputs ("    authKeyId: ", fp);
663   err = ksba_cert_get_auth_key_id (cert, &keyid, &name, &sexp);
664   if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA)
665     {
666       if (gpg_err_code (err) == GPG_ERR_NO_DATA || !name)
667         es_fputs ("[none]\n", fp);
668       else
669         {
670           gpgsm_print_serial (fp, sexp);
671           ksba_free (sexp);
672           es_putc ('\n', fp);
673           print_names_raw (fp, -15, name);
674           ksba_name_release (name);
675         }
676       if (keyid)
677         {
678           es_fputs (" authKeyId.ki: ", fp);
679           gpgsm_print_serial (fp, keyid);
680           ksba_free (keyid);
681           es_putc ('\n', fp);
682         }
683     }
684   else
685     es_fputs ("[?]\n", fp);
686
687   es_fputs ("     keyUsage:", fp);
688   err = ksba_cert_get_key_usage (cert, &kusage);
689   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
690     {
691       if (err)
692         es_fprintf (fp, " [error: %s]", gpg_strerror (err));
693       else
694         {
695           if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
696             es_fputs (" digitalSignature", fp);
697           if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))  
698             es_fputs (" nonRepudiation", fp);
699           if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT)) 
700             es_fputs (" keyEncipherment", fp);
701           if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
702             es_fputs (" dataEncipherment", fp);
703           if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))    
704             es_fputs (" keyAgreement", fp);
705           if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
706             es_fputs (" certSign", fp);
707           if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))  
708             es_fputs (" crlSign", fp);
709           if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
710             es_fputs (" encipherOnly", fp);
711           if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))  
712             es_fputs (" decipherOnly", fp);
713         }
714       es_putc ('\n', fp);
715     }
716   else
717     es_fputs (" [none]\n", fp);
718
719   es_fputs ("  extKeyUsage: ", fp);
720   err = ksba_cert_get_ext_key_usages (cert, &string);
721   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
722     { 
723       if (err)
724         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
725       else
726         {
727           p = string;
728           while (p && (pend=strchr (p, ':')))
729             {
730               *pend++ = 0;
731               for (i=0; key_purpose_map[i].oid; i++)
732                 if ( !strcmp (key_purpose_map[i].oid, p) )
733                   break;
734               es_fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
735               p = pend;
736               if (*p != 'C')
737                 es_fputs (" (suggested)", fp);
738               if ((p = strchr (p, '\n')))
739                 {
740                   p++;
741                   es_fputs ("\n               ", fp);
742                 }
743             }
744           xfree (string);
745         }
746       es_putc ('\n', fp);
747     }
748   else
749     es_fputs ("[none]\n", fp);
750
751
752   es_fputs ("     policies: ", fp);
753   err = ksba_cert_get_cert_policies (cert, &string);
754   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
755     {
756       if (err)
757         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
758       else
759         {
760           p = string;
761           while (p && (pend=strchr (p, ':')))
762             {
763               *pend++ = 0;
764               for (i=0; key_purpose_map[i].oid; i++)
765                 if ( !strcmp (key_purpose_map[i].oid, p) )
766                   break;
767               es_fputs (p, fp);
768               p = pend;
769               if (*p == 'C')
770                 es_fputs (" (critical)", fp);
771               if ((p = strchr (p, '\n')))
772                 {
773                   p++;
774                   es_fputs ("\n               ", fp);
775                 }
776             }
777           xfree (string);
778         }
779       es_putc ('\n', fp);
780     }
781   else
782     es_fputs ("[none]\n", fp);
783
784   es_fputs ("  chainLength: ", fp);
785   err = ksba_cert_is_ca (cert, &is_ca, &chainlen);
786   if (err || is_ca)
787     {
788       if (gpg_err_code (err) == GPG_ERR_NO_VALUE )
789         es_fprintf (fp, "[none]");
790       else if (err)
791         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
792       else if (chainlen == -1)
793         es_fputs ("unlimited", fp);
794       else
795         es_fprintf (fp, "%d", chainlen);
796       es_putc ('\n', fp);
797     }
798   else
799     es_fputs ("not a CA\n", fp);
800
801
802   /* CRL distribution point */
803   for (idx=0; !(err=ksba_cert_get_crl_dist_point (cert, idx, &name, &name2,
804                                                   &reason)) ;idx++)
805     {
806       es_fputs ("        crlDP: ", fp);
807       print_names_raw (fp, 15, name);
808       if (reason)
809         {
810           es_fputs ("               reason: ", fp);
811           if ( (reason & KSBA_CRLREASON_UNSPECIFIED))
812             es_fputs (" unused", fp);
813           if ( (reason & KSBA_CRLREASON_KEY_COMPROMISE))
814             es_fputs (" keyCompromise", fp);
815           if ( (reason & KSBA_CRLREASON_CA_COMPROMISE))
816             es_fputs (" caCompromise", fp);
817           if ( (reason & KSBA_CRLREASON_AFFILIATION_CHANGED))
818             es_fputs (" affiliationChanged", fp);
819           if ( (reason & KSBA_CRLREASON_SUPERSEDED))
820             es_fputs (" superseded", fp);
821           if ( (reason & KSBA_CRLREASON_CESSATION_OF_OPERATION))
822             es_fputs (" cessationOfOperation", fp);
823           if ( (reason & KSBA_CRLREASON_CERTIFICATE_HOLD))
824             es_fputs (" certificateHold", fp);
825           es_putc ('\n', fp);
826         }
827       es_fputs ("               issuer: ", fp);
828       print_names_raw (fp, 23, name2);
829       ksba_name_release (name);
830       ksba_name_release (name2);
831     }
832   if (err && gpg_err_code (err) != GPG_ERR_EOF
833       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
834     es_fputs ("        crlDP: [error]\n", fp);
835   else if (!idx)
836     es_fputs ("        crlDP: [none]\n", fp);
837
838
839   /* authorityInfoAccess. */
840   for (idx=0; !(err=ksba_cert_get_authority_info_access (cert, idx, &string,
841                                                          &name)); idx++)
842     {
843       es_fputs ("     authInfo: ", fp);
844       s = get_oid_desc (string, NULL);
845       es_fprintf (fp, "%s%s%s%s\n", string, s?" (":"", s?s:"", s?")":"");
846       print_names_raw (fp, -15, name);
847       ksba_name_release (name);
848       ksba_free (string);
849     }
850   if (err && gpg_err_code (err) != GPG_ERR_EOF
851       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
852     es_fputs ("     authInfo: [error]\n", fp);
853   else if (!idx)
854     es_fputs ("     authInfo: [none]\n", fp);
855
856   /* subjectInfoAccess. */
857   for (idx=0; !(err=ksba_cert_get_subject_info_access (cert, idx, &string,
858                                                          &name)); idx++)
859     {
860       es_fputs ("  subjectInfo: ", fp);
861       s = get_oid_desc (string, NULL);
862       es_fprintf (fp, "%s%s%s%s\n", string, s?" (":"", s?s:"", s?")":"");
863       print_names_raw (fp, -15, name);
864       ksba_name_release (name);
865       ksba_free (string);
866     }
867   if (err && gpg_err_code (err) != GPG_ERR_EOF
868       && gpg_err_code (err) != GPG_ERR_NO_VALUE)
869     es_fputs ("     subjInfo: [error]\n", fp);
870   else if (!idx)
871     es_fputs ("     subjInfo: [none]\n", fp);
872
873
874   for (idx=0; !(err=ksba_cert_get_extension (cert, idx,
875                                              &oid, &i, &off, &len));idx++)
876     {
877       unsigned int flag;
878
879       s = get_oid_desc (oid, &flag);
880
881       if (!(flag & 1))
882         es_fprintf (fp, "     %s: %s%s%s%s  [%d octets]\n",
883                  i? "critExtn":"    extn",
884                  oid, s?" (":"", s?s:"", s?")":"", (int)len);
885     }
886
887
888   if (with_validation)
889     {
890       err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp, 0);
891       if (!err)
892         es_fprintf (fp, "  [certificate is good]\n");
893       else
894         es_fprintf (fp, "  [certificate is bad: %s]\n", gpg_strerror (err));
895     }
896
897   if (opt.with_ephemeral_keys && hd)
898     {
899       unsigned int blobflags;
900
901       err = keydb_get_flags (hd, KEYBOX_FLAG_BLOB, 0, &blobflags);
902       if (err)
903         es_fprintf (fp, "  [error getting keyflags: %s]\n",gpg_strerror (err));
904       else if ((blobflags & KEYBOX_FLAG_BLOB_EPHEMERAL))
905         es_fprintf (fp, "  [stored as ephemeral]\n");
906     }
907
908 }
909
910
911
912
913 /* List one certificate in standard mode */
914 static void
915 list_cert_std (ctrl_t ctrl, ksba_cert_t cert, estream_t fp, int have_secret,
916                int with_validation)
917 {
918   gpg_error_t err;
919   ksba_sexp_t sexp;
920   char *dn;
921   ksba_isotime_t t;
922   int idx, i;
923   int is_ca, chainlen;
924   unsigned int kusage;
925   char *string, *p, *pend;
926
927   sexp = ksba_cert_get_serial (cert);
928   es_fputs ("Serial number: ", fp);
929   gpgsm_print_serial (fp, sexp);
930   ksba_free (sexp);
931   es_putc ('\n', fp);
932
933   dn = ksba_cert_get_issuer (cert, 0);
934   es_fputs ("       Issuer: ", fp);
935   gpgsm_es_print_name (fp, dn);
936   ksba_free (dn);
937   es_putc ('\n', fp);
938   for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
939     {
940       es_fputs ("          aka: ", fp);
941       gpgsm_es_print_name (fp, dn);
942       ksba_free (dn);
943       es_putc ('\n', fp);
944     }
945
946   dn = ksba_cert_get_subject (cert, 0);
947   es_fputs ("      Subject: ", fp);
948   gpgsm_es_print_name (fp, dn);
949   ksba_free (dn);
950   es_putc ('\n', fp);
951   for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
952     {
953       es_fputs ("          aka: ", fp);
954       gpgsm_es_print_name (fp, dn);
955       ksba_free (dn);
956       es_putc ('\n', fp);
957     }
958
959   ksba_cert_get_validity (cert, 0, t);
960   es_fputs ("     validity: ", fp);
961   gpgsm_print_time (fp, t);
962   es_fputs (" through ", fp);
963   ksba_cert_get_validity (cert, 1, t);
964   gpgsm_print_time (fp, t);
965   es_putc ('\n', fp);
966
967
968   {
969     const char *algoname;
970     unsigned int nbits;
971
972     algoname = gcry_pk_algo_name (gpgsm_get_key_algo_info (cert, &nbits));
973     es_fprintf (fp, "     key type: %u bit %s\n",
974                 nbits, algoname? algoname:"?");
975   }
976
977
978   err = ksba_cert_get_key_usage (cert, &kusage);
979   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
980     {
981       es_fputs ("    key usage:", fp);
982       if (err)
983         es_fprintf (fp, " [error: %s]", gpg_strerror (err));
984       else
985         {
986           if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
987             es_fputs (" digitalSignature", fp);
988           if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))  
989             es_fputs (" nonRepudiation", fp);
990           if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT)) 
991             es_fputs (" keyEncipherment", fp);
992           if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
993             es_fputs (" dataEncipherment", fp);
994           if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))    
995             es_fputs (" keyAgreement", fp);
996           if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
997             es_fputs (" certSign", fp);
998           if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))  
999             es_fputs (" crlSign", fp);
1000           if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
1001             es_fputs (" encipherOnly", fp);
1002           if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))  
1003             es_fputs (" decipherOnly", fp);
1004         }
1005       es_putc ('\n', fp);
1006     }
1007
1008   err = ksba_cert_get_ext_key_usages (cert, &string);
1009   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
1010     { 
1011       es_fputs ("ext key usage: ", fp);
1012       if (err)
1013         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
1014       else
1015         {
1016           p = string;
1017           while (p && (pend=strchr (p, ':')))
1018             {
1019               *pend++ = 0;
1020               for (i=0; key_purpose_map[i].oid; i++)
1021                 if ( !strcmp (key_purpose_map[i].oid, p) )
1022                   break;
1023               es_fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
1024               p = pend;
1025               if (*p != 'C')
1026                 es_fputs (" (suggested)", fp);
1027               if ((p = strchr (p, '\n')))
1028                 {
1029                   p++;
1030                   es_fputs (", ", fp);
1031                 }
1032             }
1033           xfree (string);
1034         }
1035       es_putc ('\n', fp);
1036     }
1037
1038   err = ksba_cert_get_cert_policies (cert, &string);
1039   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
1040     {
1041       es_fputs ("     policies: ", fp);
1042       if (err)
1043         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
1044       else
1045         {
1046           for (p=string; *p; p++)
1047             {
1048               if (*p == '\n')
1049                 *p = ',';
1050             }
1051           es_write_sanitized (fp, string, strlen (string), NULL, NULL);
1052           xfree (string);
1053         }
1054       es_putc ('\n', fp);
1055     }
1056
1057   err = ksba_cert_is_ca (cert, &is_ca, &chainlen);
1058   if (err || is_ca)
1059     {
1060       es_fputs (" chain length: ", fp);
1061       if (gpg_err_code (err) == GPG_ERR_NO_VALUE )
1062         es_fprintf (fp, "none");
1063       else if (err)
1064         es_fprintf (fp, "[error: %s]", gpg_strerror (err));
1065       else if (chainlen == -1)
1066         es_fputs ("unlimited", fp);
1067       else
1068         es_fprintf (fp, "%d", chainlen);
1069       es_putc ('\n', fp);
1070     }
1071
1072   if (opt.with_md5_fingerprint)
1073     {
1074       dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5);
1075       es_fprintf (fp, "      md5 fpr: %s\n", dn?dn:"error");
1076       xfree (dn);
1077     }
1078
1079   dn = gpgsm_get_fingerprint_string (cert, 0);
1080   es_fprintf (fp, "  fingerprint: %s\n", dn?dn:"error");
1081   xfree (dn);
1082
1083
1084
1085   if (with_validation)
1086     {
1087       gpg_error_t tmperr;
1088       size_t buflen;
1089       char buffer[1];
1090       
1091       err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp, 0);
1092       tmperr = ksba_cert_get_user_data (cert, "is_qualified", 
1093                                         &buffer, sizeof (buffer), &buflen);
1094       if (!tmperr && buflen)
1095         {
1096           if (*buffer)
1097             es_fputs ("  [qualified]\n", fp);
1098         }    
1099       else if (gpg_err_code (tmperr) == GPG_ERR_NOT_FOUND)
1100         ; /* Don't know - will not get marked as 'q' */
1101       else
1102         log_debug ("get_user_data(is_qualified) failed: %s\n",
1103                    gpg_strerror (tmperr)); 
1104
1105       if (!err)
1106         es_fprintf (fp, "  [certificate is good]\n");
1107       else
1108         es_fprintf (fp, "  [certificate is bad: %s]\n", gpg_strerror (err));
1109     }
1110 }
1111
1112
1113 /* Same as standard mode mode list all certifying certs too. */
1114 static void
1115 list_cert_chain (ctrl_t ctrl, KEYDB_HANDLE hd,
1116                  ksba_cert_t cert, int raw_mode,
1117                  estream_t fp, int with_validation)
1118 {
1119   ksba_cert_t next = NULL;
1120
1121   if (raw_mode)
1122     list_cert_raw (ctrl, hd, cert, fp, 0, with_validation);
1123   else
1124     list_cert_std (ctrl, cert, fp, 0, with_validation);
1125   ksba_cert_ref (cert);
1126   while (!gpgsm_walk_cert_chain (cert, &next))
1127     {
1128       ksba_cert_release (cert);
1129       es_fputs ("Certified by\n", fp);
1130       if (raw_mode)
1131         list_cert_raw (ctrl, hd, next, fp, 0, with_validation);
1132       else
1133         list_cert_std (ctrl, next, fp, 0, with_validation);
1134       cert = next;
1135     }
1136   ksba_cert_release (cert);
1137   es_putc ('\n', fp);
1138 }
1139
1140
1141 \f
1142 /* List all internal keys or just the keys given as NAMES.  MODE is a
1143    bit vector to specify what keys are to be included; see
1144    gpgsm_list_keys (below) for details.  If RAW_MODE is true, the raw
1145    output mode will be used instead of the standard beautified one.
1146  */
1147 static gpg_error_t
1148 list_internal_keys (ctrl_t ctrl, strlist_t names, estream_t fp,
1149                     unsigned int mode, int raw_mode)
1150 {
1151   KEYDB_HANDLE hd;
1152   KEYDB_SEARCH_DESC *desc = NULL;
1153   strlist_t sl;
1154   int ndesc;
1155   ksba_cert_t cert = NULL;
1156   gpg_error_t rc = 0;
1157   const char *lastresname, *resname;
1158   int have_secret;
1159
1160   hd = keydb_new (0);
1161   if (!hd)
1162     {
1163       log_error ("keydb_new failed\n");
1164       rc = gpg_error (GPG_ERR_GENERAL);
1165       goto leave;
1166     }
1167
1168   if (!names)
1169     ndesc = 1;
1170   else
1171     {
1172       for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) 
1173         ;
1174     }
1175
1176   desc = xtrycalloc (ndesc, sizeof *desc);
1177   if (!ndesc)
1178     {
1179       rc = gpg_error_from_syserror ();
1180       log_error ("out of core\n");
1181       goto leave;
1182     }
1183
1184   if (!names)
1185     desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
1186   else 
1187     {
1188       for (ndesc=0, sl=names; sl; sl = sl->next) 
1189         {
1190           rc = keydb_classify_name (sl->d, desc+ndesc);
1191           if (rc)
1192             {
1193               log_error ("key `%s' not found: %s\n",
1194                          sl->d, gpg_strerror (rc));
1195               rc = 0;
1196             }
1197           else
1198             ndesc++;
1199         }
1200       
1201     }
1202
1203   if (opt.with_ephemeral_keys)
1204     keydb_set_ephemeral (hd, 1);
1205
1206   /* It would be nice to see which of the given users did actually
1207      match one in the keyring.  To implement this we need to have a
1208      found flag for each entry in desc and to set this we must check
1209      all those entries after a match to mark all matched one -
1210      currently we stop at the first match.  To do this we need an
1211      extra flag to enable this feature so */
1212
1213   lastresname = NULL;
1214   while (!(rc = keydb_search (hd, desc, ndesc)))
1215     {
1216       unsigned int validity;
1217
1218       if (!names) 
1219         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
1220
1221       rc = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &validity);
1222       if (rc)
1223         {
1224           log_error ("keydb_get_flags failed: %s\n", gpg_strerror (rc));
1225           goto leave;
1226         }
1227       rc = keydb_get_cert (hd, &cert);
1228       if (rc) 
1229         {
1230           log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
1231           goto leave;
1232         }
1233       
1234       resname = keydb_get_resource_name (hd);
1235       
1236       if (lastresname != resname ) 
1237         {
1238           int i;
1239           
1240           if (ctrl->no_server)
1241             {
1242               es_fprintf (fp, "%s\n", resname );
1243               for (i=strlen(resname); i; i-- )
1244                 es_putc ('-', fp);
1245               es_putc ('\n', fp);
1246               lastresname = resname;
1247             }
1248         }
1249
1250       have_secret = 0;
1251       if (mode)
1252         {
1253           char *p = gpgsm_get_keygrip_hexstring (cert);
1254           if (p)
1255             {
1256               rc = gpgsm_agent_havekey (ctrl, p); 
1257              if (!rc)
1258                 have_secret = 1;
1259               else if ( gpg_err_code (rc) != GPG_ERR_NO_SECKEY)
1260                 goto leave;
1261               rc = 0;
1262               xfree (p);
1263             }
1264         }
1265
1266       if (!mode
1267           || ((mode & 1) && !have_secret)
1268           || ((mode & 2) && have_secret)  )
1269         {
1270           if (ctrl->with_colons)
1271             list_cert_colon (ctrl, cert, validity, fp, have_secret);
1272           else if (ctrl->with_chain)
1273             list_cert_chain (ctrl, hd, cert,
1274                              raw_mode, fp, ctrl->with_validation);
1275           else
1276             {
1277               if (raw_mode)
1278                 list_cert_raw (ctrl, hd, cert, fp, have_secret,
1279                                ctrl->with_validation);
1280               else
1281                 list_cert_std (ctrl, cert, fp, have_secret,
1282                                ctrl->with_validation);
1283               es_putc ('\n', fp);
1284             }
1285         }
1286       ksba_cert_release (cert); 
1287       cert = NULL;
1288     }
1289   if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1 )
1290     rc = 0;
1291   if (rc)
1292     log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
1293   
1294  leave:
1295   ksba_cert_release (cert);
1296   xfree (desc);
1297   keydb_release (hd);
1298   return rc;
1299 }
1300
1301
1302
1303 static void
1304 list_external_cb (void *cb_value, ksba_cert_t cert)
1305 {
1306   struct list_external_parm_s *parm = cb_value;
1307
1308   if (keydb_store_cert (cert, 1, NULL))
1309     log_error ("error storing certificate as ephemeral\n");
1310
1311   if (parm->print_header)
1312     {
1313       const char *resname = "[external keys]";
1314       int i;
1315
1316       es_fprintf (parm->fp, "%s\n", resname );
1317       for (i=strlen(resname); i; i-- )
1318         es_putc('-', parm->fp);
1319       es_putc ('\n', parm->fp);
1320       parm->print_header = 0;
1321     }
1322
1323   if (parm->with_colons)
1324     list_cert_colon (parm->ctrl, cert, 0, parm->fp, 0);
1325   else if (parm->with_chain)
1326     list_cert_chain (parm->ctrl, NULL, cert, parm->raw_mode, parm->fp, 0);
1327   else
1328     {
1329       if (parm->raw_mode)
1330         list_cert_raw (parm->ctrl, NULL, cert, parm->fp, 0, 0);
1331       else
1332         list_cert_std (parm->ctrl, cert, parm->fp, 0, 0);
1333       es_putc ('\n', parm->fp);
1334     }
1335 }
1336
1337
1338 /* List external keys similar to internal one.  Note: mode does not
1339    make sense here because it would be unwise to list external secret
1340    keys */
1341 static gpg_error_t
1342 list_external_keys (ctrl_t ctrl, strlist_t names, estream_t fp, int raw_mode)
1343 {
1344   int rc;
1345   struct list_external_parm_s parm;
1346
1347   parm.fp = fp;
1348   parm.ctrl = ctrl,
1349   parm.print_header = ctrl->no_server;
1350   parm.with_colons = ctrl->with_colons;
1351   parm.with_chain = ctrl->with_chain;
1352   parm.raw_mode  = raw_mode;
1353
1354   rc = gpgsm_dirmngr_lookup (ctrl, names, list_external_cb, &parm);
1355   if (rc)
1356     log_error ("listing external keys failed: %s\n", gpg_strerror (rc));
1357   return rc;
1358 }
1359
1360 /* List all keys or just the key given as NAMES.
1361    MODE controls the operation mode: 
1362     Bit 0-2:
1363       0 = list all public keys but don't flag secret ones
1364       1 = list only public keys
1365       2 = list only secret keys
1366       3 = list secret and public keys
1367     Bit 6: list internal keys
1368     Bit 7: list external keys
1369     Bit 8: Do a raw format dump.
1370  */
1371 gpg_error_t
1372 gpgsm_list_keys (ctrl_t ctrl, strlist_t names, estream_t fp,
1373                  unsigned int mode)
1374 {
1375   gpg_error_t err = 0;
1376
1377   if ((mode & (1<<6)))
1378     err = list_internal_keys (ctrl, names, fp, (mode & 3), (mode&256));
1379   if (!err && (mode & (1<<7)))
1380     err = list_external_keys (ctrl, names, fp, (mode&256)); 
1381   return err;
1382 }