* gpg.sgml: Note that --throw-keyid is --throw-keyids. Note changes in
[gnupg.git] / sm / keylist.c
1 /* keylist.c
2  * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
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 "i18n.h"
37
38 struct list_external_parm_s {
39   FILE *fp;
40   int print_header;
41   int with_colons;
42   int with_chain;
43 };
44
45
46
47 static void
48 print_key_data (KsbaCert cert, FILE *fp)
49 {
50 #if 0  
51   int n = pk ? pubkey_get_npkey( pk->pubkey_algo ) : 0;
52   int i;
53
54   for(i=0; i < n; i++ ) 
55     {
56       fprintf (fp, "pkd:%d:%u:", i, mpi_get_nbits( pk->pkey[i] ) );
57       mpi_print(stdout, pk->pkey[i], 1 );
58       putchar(':');
59       putchar('\n');
60     }
61 #endif
62 }
63
64 static void
65 print_capabilities (KsbaCert cert, FILE *fp)
66 {
67   KsbaError err;
68   unsigned int use;
69
70   err = ksba_cert_get_key_usage (cert, &use);
71   if (err == KSBA_No_Data)
72     {
73       putc ('e', fp);
74       putc ('s', fp);
75       putc ('c', fp);
76       putc ('E', fp);
77       putc ('S', fp);
78       putc ('C', fp);
79       return;
80     }
81   if (err)
82     { 
83       log_error (_("error getting key usage information: %s\n"),
84                  ksba_strerror (err));
85       return;
86     } 
87
88   if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
89     putc ('e', fp);
90   if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
91     putc ('s', fp);
92   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
93     putc ('c', fp);
94   if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
95     putc ('E', fp);
96   if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
97     putc ('S', fp);
98   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
99     putc ('C', fp);
100 }
101
102
103 static void
104 print_time (time_t t, FILE *fp)
105 {
106   if (!t)
107     ;
108   else if ( t == (time_t)(-1) )
109     putc ('?', fp);
110   else
111     fprintf (fp, "%lu", (unsigned long)t);
112 }
113
114
115 /* return an allocated string with the email address extracted from a
116    DN */
117 static char *
118 email_kludge (const char *name)
119 {
120   const unsigned char *p;
121   unsigned char *buf;
122   int n;
123
124   if (strncmp (name, "1.2.840.113549.1.9.1=#", 22))
125     return NULL;
126   /* This looks pretty much like an email address in the subject's DN
127      we use this to add an additional user ID entry.  This way,
128      openSSL generated keys get a nicer and usable listing */
129   name += 22;    
130   for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++)
131     ;
132   if (*p != '#' || !n)
133     return NULL;
134   buf = xtrymalloc (n+3);
135   if (!buf)
136     return NULL; /* oops, out of core */
137   *buf = '<';
138   for (n=1, p=name; *p != '#'; p +=2, n++)
139     buf[n] = xtoi_2 (p);
140   buf[n++] = '>';
141   buf[n] = 0;
142   return buf;
143 }
144
145
146
147
148 /* List one certificate in colon mode */
149 static void
150 list_cert_colon (KsbaCert cert, FILE *fp, int have_secret)
151 {
152   int idx, trustletter = 0;
153   char *p;
154   KsbaSexp sexp;
155   char *fpr;
156
157   fputs (have_secret? "crs:":"crt:", fp);
158   trustletter = 0;
159 #if 0
160   if (is_not_valid (cert))
161     putc ('i', fp);
162   else if ( is_revoked (cert) )
163     putc ('r', fp);
164   else if ( has_expired (cert))
165     putcr ('e', fp);
166   else
167 #endif
168     {
169       trustletter = '?'; /*get_validity_info ( pk, NULL );*/
170       putc (trustletter, fp);
171     }
172
173   fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
174   fprintf (fp, ":%u:%d:%s:",
175            /*keylen_of_cert (cert)*/1024,
176            /* pubkey_algo_of_cert (cert)*/1,
177            fpr+24);
178
179   /* we assume --fixed-list-mode for gpgsm */
180   print_time ( ksba_cert_get_validity (cert, 0), fp);
181   putc (':', fp);
182   print_time ( ksba_cert_get_validity (cert, 1), fp);
183   putc (':', fp);
184   /* field 8, serial number: */
185   if ((sexp = ksba_cert_get_serial (cert)))
186     {
187       int len;
188       const unsigned char *s = sexp;
189       
190       if (*s == '(')
191         {
192           s++;
193           for (len=0; *s && *s != ':' && digitp (s); s++)
194             len = len*10 + atoi_1 (s);
195           if (*s == ':')
196             for (s++; len; len--, s++)
197               fprintf (fp,"%02X", *s);
198         }
199       xfree (sexp);
200     }
201   putc (':', fp);
202   /* field 9, ownertrust - not used here */
203   putc (':', fp);
204   /* field 10, old user ID - we use it here for the issuer DN */
205   if ((p = ksba_cert_get_issuer (cert,0)))
206     {
207       print_sanitized_string (fp, p, ':');
208       xfree (p);
209     }
210   putc (':', fp);
211   /* field 11, signature class - not used */ 
212   putc (':', fp);
213   /* field 12, capabilities: */ 
214   print_capabilities (cert, fp);
215   putc (':', fp);
216   putc ('\n', fp);
217
218   /* FPR record */
219   fprintf (fp, "fpr:::::::::%s:::", fpr);
220   xfree (fpr); fpr = NULL;
221   /* print chaining ID (field 13)*/
222   {
223     KsbaCert next;
224     
225     if (!gpgsm_walk_cert_chain (cert, &next))
226       {
227         p = gpgsm_get_fingerprint_hexstring (next, GCRY_MD_SHA1);
228         fputs (p, fp);
229         xfree (p);
230         ksba_cert_release (next);
231       }
232   }
233   putc (':', fp);
234   putc ('\n', fp);
235
236
237   if (opt.with_key_data)
238     {
239       if ( (p = gpgsm_get_keygrip_hexstring (cert)))
240         {
241           fprintf (fp, "grp:::::::::%s:\n", p);
242           xfree (p);
243         }
244       print_key_data (cert, fp);
245     }
246
247   for (idx=0; (p = ksba_cert_get_subject (cert,idx)); idx++)
248     {
249       fprintf (fp, "uid:%c::::::::", trustletter);
250       print_sanitized_string (fp, p, ':');
251       putc (':', fp);
252       putc (':', fp);
253       putc ('\n', fp);
254       if (!idx)
255         {
256           /* It would be better to get the faked email address from
257              the keydb.  But as long as we don't have a way to pass
258              the meta data back, we just check it the same way as the
259              code used to create the keybox meta data does */
260           char *pp = email_kludge (p);
261           if (pp)
262             {
263               fprintf (fp, "uid:%c::::::::", trustletter);
264               print_sanitized_string (fp, pp, ':');
265               putc (':', fp);
266               putc (':', fp);
267               putc ('\n', fp);
268               xfree (pp);
269             }
270         }
271       xfree (p);
272     }
273 }
274
275
276 /* List one certificate in standard mode */
277 static void
278 list_cert_std (KsbaCert cert, FILE *fp, int have_secret)
279 {
280   KsbaError kerr;
281   KsbaSexp sexp;
282   char *dn;
283   time_t t;
284   int idx;
285   int is_ca, chainlen;
286   unsigned int kusage;
287   char *string, *p;
288
289   sexp = ksba_cert_get_serial (cert);
290   fputs ("Serial number: ", fp);
291   gpgsm_print_serial (fp, sexp);
292   ksba_free (sexp);
293   putc ('\n', fp);
294
295   dn = ksba_cert_get_issuer (cert, 0);
296   fputs ("       Issuer: ", fp);
297   gpgsm_print_name (fp, dn);
298   ksba_free (dn);
299   putc ('\n', fp);
300   for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
301     {
302       fputs ("          aka: ", fp);
303       gpgsm_print_name (fp, dn);
304       ksba_free (dn);
305       putc ('\n', fp);
306     }
307
308   dn = ksba_cert_get_subject (cert, 0);
309   fputs ("      Subject: ", fp);
310   gpgsm_print_name (fp, dn);
311   ksba_free (dn);
312   putc ('\n', fp);
313   for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
314     {
315       fputs ("          aka: ", fp);
316       gpgsm_print_name (fp, dn);
317       ksba_free (dn);
318       putc ('\n', fp);
319     }
320
321   t = ksba_cert_get_validity (cert, 0);
322   fputs ("     validity: ", fp);
323   gpgsm_print_time (fp, t);
324   fputs (" through ", fp);
325   t = ksba_cert_get_validity (cert, 1);
326   gpgsm_print_time (fp, t);
327   putc ('\n', fp);
328
329   kerr = ksba_cert_get_key_usage (cert, &kusage);
330   if (kerr != KSBA_No_Data)
331     {
332       fputs ("    key usage:", fp);
333       if (kerr)
334         fprintf (fp, " [error: %s]", ksba_strerror (kerr));
335       else
336         {
337           if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
338             fputs (" digitalSignature", fp);
339           if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))  
340             fputs (" nonRepudiation", fp);
341           if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT)) 
342             fputs (" keyEncipherment", fp);
343           if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
344             fputs (" dataEncipherment", fp);
345           if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))    
346             fputs (" keyAgreement", fp);
347           if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
348             fputs (" certSign", fp);
349           if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))  
350             fputs (" crlSign", fp);
351           if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
352             fputs (" encipherOnly", fp);
353           if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))  
354             fputs (" decipherOnly", fp);
355         }
356       putc ('\n', fp);
357     }
358
359   kerr = ksba_cert_get_cert_policies (cert, &string);
360   if (kerr != KSBA_No_Data)
361     {
362       fputs ("     policies: ", fp);
363       if (kerr)
364         fprintf (fp, "[error: %s]", ksba_strerror (kerr));
365       else
366         {
367           for (p=string; *p; p++)
368             {
369               if (*p == '\n')
370                 *p = ',';
371             }
372           print_sanitized_string (fp, string, 0);
373           xfree (string);
374         }
375       putc ('\n', fp);
376     }
377
378   kerr = ksba_cert_is_ca (cert, &is_ca, &chainlen);
379   if (kerr || is_ca)
380     {
381       fputs (" chain length: ", fp);
382       if (kerr)
383         fprintf (fp, "[error: %s]", ksba_strerror (kerr));
384       else if (chainlen == -1)
385         fputs ("unlimited", fp);
386       else
387         fprintf (fp, "%d", chainlen);
388       putc ('\n', fp);
389     }
390
391
392   dn = gpgsm_get_fingerprint_string (cert, 0);
393   fprintf (fp, "  fingerprint: %s\n", dn?dn:"error");
394   xfree (dn);
395 }
396
397 /* Same as standard mode mode list all certifying certts too */
398 static void
399 list_cert_chain (KsbaCert cert, FILE *fp)
400 {
401   KsbaCert next = NULL;
402
403   list_cert_std (cert, fp, 0);
404   ksba_cert_ref (cert);
405   while (!gpgsm_walk_cert_chain (cert, &next))
406     {
407       ksba_cert_release (cert);
408       fputs ("Certified by\n", fp);
409       list_cert_std (next, fp, 0);
410       cert = next;
411     }
412   ksba_cert_release (cert);
413   putc ('\n', fp);
414 }
415
416
417 \f
418 /* List all internal keys or just the key given as NAMES.
419  */
420 static void
421 list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
422 {
423   KEYDB_HANDLE hd;
424   KEYDB_SEARCH_DESC *desc = NULL;
425   STRLIST sl;
426   int ndesc;
427   KsbaCert cert = NULL;
428   int rc=0;
429   const char *lastresname, *resname;
430   int have_secret;
431
432   hd = keydb_new (0);
433   if (!hd)
434     {
435       log_error ("keydb_new failed\n");
436       goto leave;
437     }
438
439   if (!names)
440     ndesc = 1;
441   else
442     {
443       for (sl=names, ndesc=0; sl; sl = sl->next, ndesc++) 
444         ;
445     }
446
447   desc = xtrycalloc (ndesc, sizeof *desc);
448   if (!ndesc)
449     {
450       log_error ("out of core\n");
451       goto leave;
452     }
453
454   if (!names)
455     desc[0].mode = KEYDB_SEARCH_MODE_FIRST;
456   else 
457     {
458       for (ndesc=0, sl=names; sl; sl = sl->next) 
459         {
460           rc = keydb_classify_name (sl->d, desc+ndesc);
461           if (rc)
462             {
463               log_error ("key `%s' not found: %s\n",
464                          sl->d, gpg_strerror (rc));
465               rc = 0;
466             }
467           else
468             ndesc++;
469         }
470       
471     }
472
473   /* it would be nice to see which of the given users did actually
474      match one in the keyring.  To implement this we need to have a
475      found flag for each entry in desc and to set this we must check
476      all those entries after a match to mark all matched one -
477      currently we stop at the first match.  To do this we need an
478      extra flag to enable this feature so */
479
480   lastresname = NULL;
481   while (!(rc = keydb_search (hd, desc, ndesc)))
482     {
483       if (!names) 
484         desc[0].mode = KEYDB_SEARCH_MODE_NEXT;
485
486       rc = keydb_get_cert (hd, &cert);
487       if (rc) 
488         {
489           log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
490           goto leave;
491         }
492       
493       resname = keydb_get_resource_name (hd);
494       
495       if (lastresname != resname ) 
496         {
497           int i;
498           
499           if (ctrl->no_server)
500             {
501               fprintf (fp, "%s\n", resname );
502               for (i=strlen(resname); i; i-- )
503                 putchar('-');
504               putc ('\n', fp);
505               lastresname = resname;
506             }
507         }
508
509       have_secret = 0;
510       if (mode)
511         {
512           char *p = gpgsm_get_keygrip_hexstring (cert);
513           if (p)
514             {
515               if (!gpgsm_agent_havekey (p))
516                 have_secret = 1;
517               xfree (p);
518             }
519         }
520
521       if (!mode
522           || ((mode & 1) && !have_secret)
523           || ((mode & 2) && have_secret)  )
524         {
525           if (ctrl->with_colons)
526             list_cert_colon (cert, fp, have_secret);
527           else if (ctrl->with_chain)
528             list_cert_chain (cert, fp);
529           else
530             {
531               list_cert_std (cert, fp, have_secret);
532               putc ('\n', fp);
533             }
534         }
535       ksba_cert_release (cert); 
536       cert = NULL;
537     }
538   if (rc && rc != -1)
539     log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
540   
541  leave:
542   ksba_cert_release (cert);
543   xfree (desc);
544   keydb_release (hd);
545 }
546
547
548
549 static void
550 list_external_cb (void *cb_value, KsbaCert cert)
551 {
552   struct list_external_parm_s *parm = cb_value;
553
554   if (keydb_store_cert (cert, 1, NULL))
555     log_error ("error storing certificate as ephemeral\n");
556
557   if (parm->print_header)
558     {
559       const char *resname = "[external keys]";
560       int i;
561
562       fprintf (parm->fp, "%s\n", resname );
563       for (i=strlen(resname); i; i-- )
564         putchar('-');
565       putc ('\n', parm->fp);
566       parm->print_header = 0;
567     }
568
569   if (parm->with_colons)
570     list_cert_colon (cert, parm->fp, 0);
571   else if (parm->with_chain)
572     list_cert_chain (cert, parm->fp);
573   else
574     {
575       list_cert_std (cert, parm->fp, 0);
576       putc ('\n', parm->fp);
577     }
578 }
579
580
581 /* List external keys similar to internal one.  Note: mode does not
582    make sense here because it would be unwise to list external secret
583    keys */
584 static void
585 list_external_keys (CTRL ctrl, STRLIST names, FILE *fp)
586 {
587   int rc;
588   struct list_external_parm_s parm;
589
590   parm.fp = fp;
591   parm.print_header = ctrl->no_server;
592   parm.with_colons = ctrl->with_colons;
593   parm.with_chain = ctrl->with_chain;
594
595   rc = gpgsm_dirmngr_lookup (ctrl, names, list_external_cb, &parm);
596   if (rc)
597     log_error ("listing external keys failed: %s\n", gpg_strerror (rc));
598 }
599
600 /* List all keys or just the key given as NAMES.
601    MODE controls the operation mode: 
602     Bit 0-2:
603       0 = list all public keys but don't flag secret ones
604       1 = list only public keys
605       2 = list only secret keys
606       3 = list secret and public keys
607     Bit 6: list internal keys
608     Bit 7: list external keys
609  */
610 void
611 gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
612 {
613   if ((mode & (1<<6)))
614       list_internal_keys (ctrl, names, fp, (mode & 3));
615   if ((mode & (1<<7)))
616       list_external_keys (ctrl, names, fp); 
617 }