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