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