* gpgsm.c: New option --force-crl-refresh.
[gnupg.git] / sm / keylist.c
1 /* keylist.c
2  * Copyright (C) 1998, 1999, 2000, 2001, 2003,
3  *               2004 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <unistd.h> 
28 #include <time.h>
29 #include <assert.h>
30
31 #include "gpgsm.h"
32
33 #include <gcrypt.h>
34 #include <ksba.h>
35
36 #include "keydb.h"
37 #include "../kbx/keybox.h" /* for KEYBOX_FLAG_* */
38 #include "i18n.h"
39
40 struct list_external_parm_s {
41   ctrl_t ctrl;
42   FILE *fp;
43   int print_header;
44   int with_colons;
45   int with_chain;
46 };
47
48
49 /* This table is to map Extended Key Usage OIDs to human readable
50    names.  */
51 struct {
52   const char *oid;
53   const char *name;
54 } key_purpose_map[] = {
55   { "1.3.6.1.5.5.7.3.1",  "serverAuth" },
56   { "1.3.6.1.5.5.7.3.2",  "clientAuth" },          
57   { "1.3.6.1.5.5.7.3.3",  "codeSigning" },      
58   { "1.3.6.1.5.5.7.3.4",  "emailProtection" },     
59   { "1.3.6.1.5.5.7.3.5",  "ipsecEndSystem" }, 
60   { "1.3.6.1.5.5.7.3.6",  "ipsecTunnel" },  
61   { "1.3.6.1.5.5.7.3.7",  "ipsecUser" },     
62   { "1.3.6.1.5.5.7.3.8",  "timeStamping" },       
63   { "1.3.6.1.5.5.7.3.9",  "ocspSigning" },    
64   { "1.3.6.1.5.5.7.3.10", "dvcs" },      
65   { "1.3.6.1.5.5.7.3.11", "sbgpCertAAServerAuth" },
66   { "1.3.6.1.5.5.7.3.13", "eapOverPPP" },
67   { "1.3.6.1.5.5.7.3.14", "wlanSSID" },       
68   { NULL, NULL }
69 };
70
71
72 static void
73 print_key_data (ksba_cert_t cert, FILE *fp)
74 {
75 #if 0  
76   int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
77   int i;
78
79   for(i=0; i < n; i++ ) 
80     {
81       fprintf (fp, "pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) );
82       mpi_print(stdout, pk->pkey[i], 1 );
83       putchar(':');
84       putchar('\n');
85     }
86 #endif
87 }
88
89 static void
90 print_capabilities (ksba_cert_t cert, FILE *fp)
91 {
92   gpg_error_t err;
93   unsigned int use;
94
95   err = ksba_cert_get_key_usage (cert, &use);
96   if (gpg_err_code (err) == GPG_ERR_NO_DATA)
97     {
98       putc ('e', fp);
99       putc ('s', fp);
100       putc ('c', fp);
101       putc ('E', fp);
102       putc ('S', fp);
103       putc ('C', fp);
104       return;
105     }
106   if (err)
107     { 
108       log_error (_("error getting key usage information: %s\n"),
109                  gpg_strerror (err));
110       return;
111     } 
112
113   if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
114     putc ('e', fp);
115   if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
116     putc ('s', fp);
117   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
118     putc ('c', fp);
119   if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
120     putc ('E', fp);
121   if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
122     putc ('S', fp);
123   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
124     putc ('C', fp);
125 }
126
127
128 static void
129 print_time (gnupg_isotime_t t, FILE *fp)
130 {
131   if (!t || !*t)
132     ;
133   else 
134     fputs (t, fp);
135 }
136
137
138 /* return an allocated string with the email address extracted from a
139    DN */
140 static char *
141 email_kludge (const char *name)
142 {
143   const unsigned char *p;
144   unsigned char *buf;
145   int n;
146
147   if (strncmp (name, "1.2.840.113549.1.9.1=#", 22))
148     return NULL;
149   /* This looks pretty much like an email address in the subject's DN
150      we use this to add an additional user ID entry.  This way,
151      openSSL generated keys get a nicer and usable listing */
152   name += 22;    
153   for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++)
154     ;
155   if (*p != '#' || !n)
156     return NULL;
157   buf = xtrymalloc (n+3);
158   if (!buf)
159     return NULL; /* oops, out of core */
160   *buf = '<';
161   for (n=1, p=name; *p != '#'; p +=2, n++)
162     buf[n] = xtoi_2 (p);
163   buf[n++] = '>';
164   buf[n] = 0;
165   return buf;
166 }
167
168
169
170
171 /* List one certificate in colon mode */
172 static void
173 list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
174                  FILE *fp, int have_secret)
175 {
176   int idx;
177   char truststring[2];
178   char *p;
179   ksba_sexp_t sexp;
180   char *fpr;
181   ksba_isotime_t t;
182   gpg_error_t valerr;
183
184   if (ctrl->with_validation)
185     valerr = gpgsm_validate_chain (ctrl, cert, NULL, 1, NULL, 0);
186   else
187     valerr = 0;
188
189   fputs (have_secret? "crs:":"crt:", fp);
190   truststring[0] = 0;
191   truststring[1] = 0;
192   if ((validity & VALIDITY_REVOKED)
193       || gpg_err_code (valerr) == GPG_ERR_CERT_REVOKED)
194     *truststring = 'r';
195   else if (gpg_err_code (valerr) == GPG_ERR_CERT_EXPIRED)
196     *truststring = 'e';
197   else if (valerr)
198     *truststring = 'i';
199   else 
200     {
201       /* Lets also check whether the certificate under question
202          expired.  This is merely a hack until we found a proper way
203          to store the expiration flag in the keybox. */
204       ksba_isotime_t current_time, not_after;
205   
206       gnupg_get_isotime (current_time);
207       if (!opt.ignore_expiration
208           && !ksba_cert_get_validity (cert, 1, not_after)
209           && *not_after && strcmp (current_time, not_after) > 0 )
210         *truststring = 'e';
211     }
212   
213   if (*truststring)
214     fputs (truststring, fp);
215
216   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
217   fprintf (fp, ":%u:%d:%s:",
218            /*keylen_of_cert (cert)*/1024,
219            /* pubkey_algo_of_cert (cert)*/1,
220            fpr+24);
221
222   /* We assume --fixed-list-mode for gpgsm */
223   ksba_cert_get_validity (cert, 0, t);
224   print_time (t, fp);
225   putc (':', fp);
226   ksba_cert_get_validity (cert, 1, t);
227   print_time ( t, fp);
228   putc (':', fp);
229   /* Field 8, serial number: */
230   if ((sexp = ksba_cert_get_serial (cert)))
231     {
232       int len;
233       const unsigned char *s = sexp;
234       
235       if (*s == '(')
236         {
237           s++;
238           for (len=0; *s && *s != ':' && digitp (s); s++)
239             len = len*10 + atoi_1 (s);
240           if (*s == ':')
241             for (s++; len; len--, s++)
242               fprintf (fp,"%02X", *s);
243         }
244       xfree (sexp);
245     }
246   putc (':', fp);
247   /* Field 9, ownertrust - not used here */
248   putc (':', fp);
249   /* field 10, old user ID - we use it here for the issuer DN */
250   if ((p = ksba_cert_get_issuer (cert,0)))
251     {
252       print_sanitized_string (fp, p, ':');
253       xfree (p);
254     }
255   putc (':', fp);
256   /* Field 11, signature class - not used */ 
257   putc (':', fp);
258   /* Field 12, capabilities: */ 
259   print_capabilities (cert, fp);
260   putc (':', fp);
261   putc ('\n', fp);
262
263   /* FPR record */
264   fprintf (fp, "fpr:::::::::%s:::", fpr);
265   /* Print chaining ID (field 13)*/
266   {
267     ksba_cert_t next;
268     int rc;
269     
270     rc = gpgsm_walk_cert_chain (cert, &next);
271     if (!rc) /* We known the issuer's certificate. */
272       {
273         p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1);
274         fputs (p, fp);
275         xfree (p);
276         ksba_cert_release (next);
277       }
278     else if (rc == -1)  /* We reached the root certificate. */
279       {
280         fputs (fpr, fp);
281       }
282   }
283   putc (':', fp);
284   putc ('\n', fp);
285   xfree (fpr); fpr = NULL;
286
287
288   if (opt.with_key_data)
289     {
290       if ( (p = gpgsm_get_keygrip_hexstring (cert)))
291         {
292           fprintf (fp, "grp:::::::::%s:\n", p);
293           xfree (p);
294         }
295       print_key_data (cert, fp);
296     }
297
298   for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++)
299     {
300       fprintf (fp, "uid:%s::::::::", truststring);
301       print_sanitized_string (fp, p, ':');
302       putc (':', fp);
303       putc (':', fp);
304       putc ('\n', fp);
305       if (!idx)
306         {
307           /* It would be better to get the faked email address from
308              the keydb.  But as long as we don't have a way to pass
309              the meta data back, we just check it the same way as the
310              code used to create the keybox meta data does */
311           char *pp = email_kludge (p);
312           if (pp)
313             {
314               fprintf (fp, "uid:%s::::::::", truststring);
315               print_sanitized_string (fp, pp, ':');
316               putc (':', fp);
317               putc (':', fp);
318               putc ('\n', fp);
319               xfree (pp);
320             }
321         }
322       xfree (p);
323     }
324 }
325
326
327 /* List one certificate in standard mode */
328 static void
329 list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret,
330                int with_validation)
331 {
332   gpg_error_t err;
333   ksba_sexp_t sexp;
334   char *dn;
335   ksba_isotime_t t;
336   int idx, i;
337   int is_ca, chainlen;
338   unsigned int kusage;
339   char *string, *p, *pend;
340
341   sexp = ksba_cert_get_serial (cert);
342   fputs ("Serial number: ", fp);
343   gpgsm_print_serial (fp, sexp);
344   ksba_free (sexp);
345   putc ('\n', fp);
346
347   dn = ksba_cert_get_issuer (cert, 0);
348   fputs ("       Issuer: ", fp);
349   gpgsm_print_name (fp, dn);
350   ksba_free (dn);
351   putc ('\n', fp);
352   for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
353     {
354       fputs ("          aka: ", fp);
355       gpgsm_print_name (fp, dn);
356       ksba_free (dn);
357       putc ('\n', fp);
358     }
359
360   dn = ksba_cert_get_subject (cert, 0);
361   fputs ("      Subject: ", fp);
362   gpgsm_print_name (fp, dn);
363   ksba_free (dn);
364   putc ('\n', fp);
365   for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
366     {
367       fputs ("          aka: ", fp);
368       gpgsm_print_name (fp, dn);
369       ksba_free (dn);
370       putc ('\n', fp);
371     }
372
373   ksba_cert_get_validity (cert, 0, t);
374   fputs ("     validity: ", fp);
375   gpgsm_print_time (fp, t);
376   fputs (" through ", fp);
377   ksba_cert_get_validity (cert, 1, t);
378   gpgsm_print_time (fp, t);
379   putc ('\n', fp);
380
381   err = ksba_cert_get_key_usage (cert, &kusage);
382   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
383     {
384       fputs ("    key usage:", fp);
385       if (err)
386         fprintf (fp, " [error: %s]", gpg_strerror (err));
387       else
388         {
389           if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
390             fputs (" digitalSignature", fp);
391           if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))  
392             fputs (" nonRepudiation", fp);
393           if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT)) 
394             fputs (" keyEncipherment", fp);
395           if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
396             fputs (" dataEncipherment", fp);
397           if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))    
398             fputs (" keyAgreement", fp);
399           if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
400             fputs (" certSign", fp);
401           if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))  
402             fputs (" crlSign", fp);
403           if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
404             fputs (" encipherOnly", fp);
405           if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))  
406             fputs (" decipherOnly", fp);
407         }
408       putc ('\n', fp);
409     }
410
411   err = ksba_cert_get_ext_key_usages (cert, &string);
412   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
413     { 
414       fputs ("ext key usage: ", fp);
415       if (err)
416         fprintf (fp, "[error: %s]", gpg_strerror (err));
417       else
418         {
419           p = string;
420           while (p && (pend=strchr (p, ':')))
421             {
422               *pend++ = 0;
423               for (i=0; key_purpose_map[i].oid; i++)
424                 if ( !strcmp (key_purpose_map[i].oid, p) )
425                   break;
426               fputs (key_purpose_map[i].oid?key_purpose_map[i].name:p, fp);
427               p = pend;
428               if (*p != 'C')
429                 fputs (" (suggested)", fp);
430               if ((p = strchr (p, '\n')))
431                 {
432                   p++;
433                   fputs (", ", fp);
434                 }
435             }
436           xfree (string);
437         }
438       putc ('\n', fp);
439     }
440
441   err = ksba_cert_get_cert_policies (cert, &string);
442   if (gpg_err_code (err) != GPG_ERR_NO_DATA)
443     {
444       fputs ("     policies: ", fp);
445       if (err)
446         fprintf (fp, "[error: %s]", gpg_strerror (err));
447       else
448         {
449           for (p=string; *p; p++)
450             {
451               if (*p == '\n')
452                 *p = ',';
453             }
454           print_sanitized_string (fp, string, 0);
455           xfree (string);
456         }
457       putc ('\n', fp);
458     }
459
460   err = ksba_cert_is_ca (cert, &is_ca, &chainlen);
461   if (err || is_ca)
462     {
463       fputs (" chain length: ", fp);
464       if (err)
465         fprintf (fp, "[error: %s]", gpg_strerror (err));
466       else if (chainlen == -1)
467         fputs ("unlimited", fp);
468       else
469         fprintf (fp, "%d", chainlen);
470       putc ('\n', fp);
471     }
472
473   if (opt.with_md5_fingerprint)
474     {
475       dn = gpgsm_get_fingerprint_string (cert, GCRY_MD_MD5);
476       fprintf (fp, "      md5 fpr: %s\n", dn?dn:"error");
477       xfree (dn);
478     }
479
480   dn = gpgsm_get_fingerprint_string (cert, 0);
481   fprintf (fp, "  fingerprint: %s\n", dn?dn:"error");
482   xfree (dn);
483
484   if (with_validation)
485     {
486       err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp, 0);
487       if (!err)
488         fprintf (fp, "  [certificate is good]\n");
489       else
490         fprintf (fp, "  [certificate is bad: %s]\n", gpg_strerror (err));
491     }
492 }
493
494
495 /* Same as standard mode mode list all certifying certs too. */
496 static void
497 list_cert_chain (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int with_validation)
498 {
499   ksba_cert_t next = NULL;
500
501   list_cert_std (ctrl, cert, fp, 0, with_validation);
502   ksba_cert_ref (cert);
503   while (!gpgsm_walk_cert_chain (cert, &next))
504     {
505       ksba_cert_release (cert);
506       fputs ("Certified by\n", fp);
507       list_cert_std (ctrl, next, fp, 0, with_validation);
508       cert = next;
509     }
510   ksba_cert_release (cert);
511   putc ('\n', fp);
512 }
513
514
515 \f
516 /* List all internal keys or just the key given as NAMES.
517  */
518 static gpg_error_t
519 list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
520 {
521   KEYDB_HANDLE hd;
522   KEYDB_SEARCH_DESC *desc = NULL;
523   STRLIST sl;
524   int ndesc;
525   ksba_cert_t cert = NULL;
526   gpg_error_t rc = 0;
527   const char *lastresname, *resname;
528   int have_secret;
529
530   hd = keydb_new (0);
531   if (!hd)
532     {
533       log_error ("keydb_new failed\n");
534       rc = gpg_error (GPG_ERR_GENERAL);
535       goto leave;
536     }
537
538   if (!names)
539     ndesc = 1;
540   else
541     {
542       for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) 
543         ;
544     }
545
546   desc = xtrycalloc (ndesc, sizeof *desc);
547   if (!ndesc)
548     {
549       rc = gpg_error_from_errno (errno);
550       log_error ("out of core\n");
551       goto leave;
552     }
553
554   if (!names)
555     desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
556   else 
557     {
558       for (ndesc=0, sl=names; sl; sl = sl->next) 
559         {
560           rc = keydb_classify_name (sl->d, desc+ndesc);
561           if (rc)
562             {
563               log_error ("key `%s' not found: %s\n",
564                          sl->d, gpg_strerror (rc));
565               rc = 0;
566             }
567           else
568             ndesc++;
569         }
570       
571     }
572
573   /* It would be nice to see which of the given users did actually
574      match one in the keyring.  To implement this we need to have a
575      found flag for each entry in desc and to set this we must check
576      all those entries after a match to mark all matched one -
577      currently we stop at the first match.  To do this we need an
578      extra flag to enable this feature so */
579
580   lastresname = NULL;
581   while (!(rc = keydb_search (hd, desc, ndesc)))
582     {
583       unsigned int validity;
584
585       if (!names) 
586         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
587
588       rc = keydb_get_flags (hd, KEYBOX_FLAG_VALIDITY, 0, &validity);
589       if (rc)
590         {
591           log_error ("keydb_get_flags failed: %s\n", gpg_strerror (rc));
592           goto leave;
593         }
594       rc = keydb_get_cert (hd, &cert);
595       if (rc) 
596         {
597           log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
598           goto leave;
599         }
600       
601       resname = keydb_get_resource_name (hd);
602       
603       if (lastresname != resname ) 
604         {
605           int i;
606           
607           if (ctrl->no_server)
608             {
609               fprintf (fp, "%s\n", resname );
610               for (i=strlen(resname); i; i-- )
611                 putchar('-');
612               putc ('\n', fp);
613               lastresname = resname;
614             }
615         }
616
617       have_secret = 0;
618       if (mode)
619         {
620           char *p = gpgsm_get_keygrip_hexstring (cert);
621           if (p)
622             {
623               rc = gpgsm_agent_havekey (p);
624               if (!rc)
625                 have_secret = 1;
626               else if ( gpg_err_code (rc) != GPG_ERR_NO_SECKEY)
627                 goto leave;
628               rc = 0;
629               xfree (p);
630             }
631         }
632
633       if (!mode
634           || ((mode & 1) && !have_secret)
635           || ((mode & 2) && have_secret)  )
636         {
637           if (ctrl->with_colons)
638             list_cert_colon (ctrl, cert, validity, fp, have_secret);
639           else if (ctrl->with_chain)
640             list_cert_chain (ctrl, cert, fp, ctrl->with_validation);
641           else
642             {
643               list_cert_std (ctrl, cert, fp, have_secret,
644                              ctrl->with_validation);
645               putc ('\n', fp);
646             }
647         }
648       ksba_cert_release (cert); 
649       cert = NULL;
650     }
651   if (gpg_err_code (rc) == GPG_ERR_EOF || rc == -1 )
652     rc = 0;
653   if (rc)
654     log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
655   
656  leave:
657   ksba_cert_release (cert);
658   xfree (desc);
659   keydb_release (hd);
660   return rc;
661 }
662
663
664
665 static void
666 list_external_cb (void *cb_value, ksba_cert_t cert)
667 {
668   struct list_external_parm_s *parm = cb_value;
669
670   if (keydb_store_cert (cert, 1, NULL))
671     log_error ("error storing certificate as ephemeral\n");
672
673   if (parm->print_header)
674     {
675       const char *resname = "[external keys]";
676       int i;
677
678       fprintf (parm->fp, "%s\n", resname );
679       for (i=strlen(resname); i; i-- )
680         putchar('-');
681       putc ('\n', parm->fp);
682       parm->print_header = 0;
683     }
684
685   if (parm->with_colons)
686     list_cert_colon (parm->ctrl, cert, 0, parm->fp, 0);
687   else if (parm->with_chain)
688     list_cert_chain (parm->ctrl, cert, parm->fp, 0);
689   else
690     {
691       list_cert_std (parm->ctrl, cert, parm->fp, 0, 0);
692       putc ('\n', parm->fp);
693     }
694 }
695
696
697 /* List external keys similar to internal one.  Note: mode does not
698    make sense here because it would be unwise to list external secret
699    keys */
700 static gpg_error_t
701 list_external_keys (CTRL ctrl, STRLIST names, FILE *fp)
702 {
703   int rc;
704   struct list_external_parm_s parm;
705
706   parm.fp = fp;
707   parm.ctrl = ctrl,
708   parm.print_header = ctrl->no_server;
709   parm.with_colons = ctrl->with_colons;
710   parm.with_chain = ctrl->with_chain;
711
712   rc = gpgsm_dirmngr_lookup (ctrl, names, list_external_cb, &parm);
713   if (rc)
714     log_error ("listing external keys failed: %s\n", gpg_strerror (rc));
715   return rc;
716 }
717
718 /* List all keys or just the key given as NAMES.
719    MODE controls the operation mode: 
720     Bit 0-2:
721       0 = list all public keys but don't flag secret ones
722       1 = list only public keys
723       2 = list only secret keys
724       3 = list secret and public keys
725     Bit 6: list internal keys
726     Bit 7: list external keys
727  */
728 gpg_error_t
729 gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
730 {
731   gpg_error_t err = 0;
732
733   if ((mode & (1<<6)))
734     err = list_internal_keys (ctrl, names, fp, (mode & 3));
735   if (!err && (mode & (1<<7)))
736     err = list_external_keys (ctrl, names, fp); 
737   return err;
738 }