* gpgsm.c (main): Set the prefixes for assuan logging.
[gnupg.git] / sm / keylist.c
index b53b10f..7b7402f 100644 (file)
@@ -1,5 +1,5 @@
 /* keylist.c
- * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
 #include <time.h>
 #include <assert.h>
 
+#include "gpgsm.h"
+
 #include <gcrypt.h>
 #include <ksba.h>
 
-#include "gpgsm.h"
 #include "keydb.h"
 #include "i18n.h"
 
@@ -38,6 +39,7 @@ struct list_external_parm_s {
   FILE *fp;
   int print_header;
   int with_colons;
+  int with_chain;
 };
 
 
@@ -66,7 +68,7 @@ print_capabilities (KsbaCert cert, FILE *fp)
   unsigned int use;
 
   err = ksba_cert_get_key_usage (cert, &use);
-  if (err == KSBA_No_Data)
+  if (gpg_err_code (err) == GPG_ERR_NO_DATA)
     {
       putc ('e', fp);
       putc ('s', fp);
@@ -79,19 +81,19 @@ print_capabilities (KsbaCert cert, FILE *fp)
   if (err)
     { 
       log_error (_("error getting key usage information: %s\n"),
-                 ksba_strerror (err));
+                 gpg_strerror (err));
       return;
     } 
 
-  if ((use & KSBA_KEYUSAGE_KEY_ENCIPHERMENT))
+  if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
     putc ('e', fp);
-  if ((use & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
+  if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
     putc ('s', fp);
   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
     putc ('c', fp);
-  if ((use & KSBA_KEYUSAGE_KEY_ENCIPHERMENT))
+  if ((use & (KSBA_KEYUSAGE_KEY_ENCIPHERMENT|KSBA_KEYUSAGE_DATA_ENCIPHERMENT)))
     putc ('E', fp);
-  if ((use & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
+  if ((use & (KSBA_KEYUSAGE_DIGITAL_SIGNATURE|KSBA_KEYUSAGE_NON_REPUDIATION)))
     putc ('S', fp);
   if ((use & KSBA_KEYUSAGE_KEY_CERT_SIGN))
     putc ('C', fp);
@@ -99,14 +101,12 @@ print_capabilities (KsbaCert cert, FILE *fp)
 
 
 static void
-print_time (time_t t, FILE *fp)
+print_time (gnupg_isotime_t t, FILE *fp)
 {
-  if (!t)
+  if (!t || !*t)
     ;
-  else if ( t == (time_t)(-1) )
-    putc ('?', fp);
-  else
-    fprintf (fp, "%lu", (unsigned long)t);
+  else 
+    fputs (t, fp);
 }
 
 
@@ -150,6 +150,8 @@ list_cert_colon (KsbaCert cert, FILE *fp, int have_secret)
   int idx, trustletter = 0;
   char *p;
   KsbaSexp sexp;
+  char *fpr;
+  ksba_isotime_t t;
 
   fputs (have_secret? "crs:":"crt:", fp);
   trustletter = 0;
@@ -167,14 +169,18 @@ list_cert_colon (KsbaCert cert, FILE *fp, int have_secret)
       putc (trustletter, fp);
     }
 
-  fprintf (fp, ":%u:%d::",
+  fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
+  fprintf (fp, ":%u:%d:%s:",
            /*keylen_of_cert (cert)*/1024,
-           /* pubkey_algo_of_cert (cert)*/1);
+           /* pubkey_algo_of_cert (cert)*/1,
+           fpr+24);
 
   /* we assume --fixed-list-mode for gpgsm */
-  print_time ( ksba_cert_get_validity (cert, 0), fp);
+  ksba_cert_get_validity (cert, 0, t);
+  print_time (t, fp);
   putc (':', fp);
-  print_time ( ksba_cert_get_validity (cert, 1), fp);
+  ksba_cert_get_validity (cert, 1, t);
+  print_time ( t, fp);
   putc (':', fp);
   /* field 8, serial number: */
   if ((sexp = ksba_cert_get_serial (cert)))
@@ -211,9 +217,8 @@ list_cert_colon (KsbaCert cert, FILE *fp, int have_secret)
   putc ('\n', fp);
 
   /* FPR record */
-  p = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1);
-  fprintf (fp, "fpr:::::::::%s:::", p);
-  xfree (p);
+  fprintf (fp, "fpr:::::::::%s:::", fpr);
+  xfree (fpr); fpr = NULL;
   /* print chaining ID (field 13)*/
   {
     KsbaCert next;
@@ -269,6 +274,146 @@ list_cert_colon (KsbaCert cert, FILE *fp, int have_secret)
 }
 
 
+/* List one certificate in standard mode */
+static void
+list_cert_std (KsbaCert cert, FILE *fp, int have_secret)
+{
+  KsbaError kerr;
+  KsbaSexp sexp;
+  char *dn;
+  ksba_isotime_t t;
+  int idx;
+  int is_ca, chainlen;
+  unsigned int kusage;
+  char *string, *p;
+
+  sexp = ksba_cert_get_serial (cert);
+  fputs ("Serial number: ", fp);
+  gpgsm_print_serial (fp, sexp);
+  ksba_free (sexp);
+  putc ('\n', fp);
+
+  dn = ksba_cert_get_issuer (cert, 0);
+  fputs ("       Issuer: ", fp);
+  gpgsm_print_name (fp, dn);
+  ksba_free (dn);
+  putc ('\n', fp);
+  for (idx=1; (dn = ksba_cert_get_issuer (cert, idx)); idx++)
+    {
+      fputs ("          aka: ", fp);
+      gpgsm_print_name (fp, dn);
+      ksba_free (dn);
+      putc ('\n', fp);
+    }
+
+  dn = ksba_cert_get_subject (cert, 0);
+  fputs ("      Subject: ", fp);
+  gpgsm_print_name (fp, dn);
+  ksba_free (dn);
+  putc ('\n', fp);
+  for (idx=1; (dn = ksba_cert_get_subject (cert, idx)); idx++)
+    {
+      fputs ("          aka: ", fp);
+      gpgsm_print_name (fp, dn);
+      ksba_free (dn);
+      putc ('\n', fp);
+    }
+
+  ksba_cert_get_validity (cert, 0, t);
+  fputs ("     validity: ", fp);
+  gpgsm_print_time (fp, t);
+  fputs (" through ", fp);
+  ksba_cert_get_validity (cert, 1, t);
+  gpgsm_print_time (fp, t);
+  putc ('\n', fp);
+
+  kerr = ksba_cert_get_key_usage (cert, &kusage);
+  if (gpg_err_code (kerr) != GPG_ERR_NO_DATA)
+    {
+      fputs ("    key usage:", fp);
+      if (kerr)
+        fprintf (fp, " [error: %s]", gpg_strerror (kerr));
+      else
+        {
+          if ( (kusage & KSBA_KEYUSAGE_DIGITAL_SIGNATURE))
+            fputs (" digitalSignature", fp);
+          if ( (kusage & KSBA_KEYUSAGE_NON_REPUDIATION))  
+            fputs (" nonRepudiation", fp);
+          if ( (kusage & KSBA_KEYUSAGE_KEY_ENCIPHERMENT)) 
+            fputs (" keyEncipherment", fp);
+          if ( (kusage & KSBA_KEYUSAGE_DATA_ENCIPHERMENT))
+            fputs (" dataEncipherment", fp);
+          if ( (kusage & KSBA_KEYUSAGE_KEY_AGREEMENT))    
+            fputs (" keyAgreement", fp);
+          if ( (kusage & KSBA_KEYUSAGE_KEY_CERT_SIGN))
+            fputs (" certSign", fp);
+          if ( (kusage & KSBA_KEYUSAGE_CRL_SIGN))  
+            fputs (" crlSign", fp);
+          if ( (kusage & KSBA_KEYUSAGE_ENCIPHER_ONLY))
+            fputs (" encipherOnly", fp);
+          if ( (kusage & KSBA_KEYUSAGE_DECIPHER_ONLY))  
+            fputs (" decipherOnly", fp);
+        }
+      putc ('\n', fp);
+    }
+
+  kerr = ksba_cert_get_cert_policies (cert, &string);
+  if (gpg_err_code (kerr) != GPG_ERR_NO_DATA)
+    {
+      fputs ("     policies: ", fp);
+      if (kerr)
+        fprintf (fp, "[error: %s]", gpg_strerror (kerr));
+      else
+        {
+          for (p=string; *p; p++)
+            {
+              if (*p == '\n')
+                *p = ',';
+            }
+          print_sanitized_string (fp, string, 0);
+          xfree (string);
+        }
+      putc ('\n', fp);
+    }
+
+  kerr = ksba_cert_is_ca (cert, &is_ca, &chainlen);
+  if (kerr || is_ca)
+    {
+      fputs (" chain length: ", fp);
+      if (kerr)
+        fprintf (fp, "[error: %s]", gpg_strerror (kerr));
+      else if (chainlen == -1)
+        fputs ("unlimited", fp);
+      else
+        fprintf (fp, "%d", chainlen);
+      putc ('\n', fp);
+    }
+
+
+  dn = gpgsm_get_fingerprint_string (cert, 0);
+  fprintf (fp, "  fingerprint: %s\n", dn?dn:"error");
+  xfree (dn);
+}
+
+/* Same as standard mode mode list all certifying certts too */
+static void
+list_cert_chain (KsbaCert cert, FILE *fp)
+{
+  KsbaCert next = NULL;
+
+  list_cert_std (cert, fp, 0);
+  ksba_cert_ref (cert);
+  while (!gpgsm_walk_cert_chain (cert, &next))
+    {
+      ksba_cert_release (cert);
+      fputs ("Certified by\n", fp);
+      list_cert_std (next, fp, 0);
+      cert = next;
+    }
+  ksba_cert_release (cert);
+  putc ('\n', fp);
+}
+
 
 \f
 /* List all internal keys or just the key given as NAMES.
@@ -317,7 +462,7 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
           if (rc)
             {
               log_error ("key `%s' not found: %s\n",
-                         sl->d, gnupg_strerror (rc));
+                         sl->d, gpg_strerror (rc));
               rc = 0;
             }
           else
@@ -342,7 +487,7 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
       rc = keydb_get_cert (hd, &cert);
       if (rc) 
         {
-          log_error ("keydb_get_cert failed: %s\n", gnupg_strerror (rc));
+          log_error ("keydb_get_cert failed: %s\n", gpg_strerror (rc));
           goto leave;
         }
       
@@ -380,14 +525,19 @@ list_internal_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
         {
           if (ctrl->with_colons)
             list_cert_colon (cert, fp, have_secret);
+          else if (ctrl->with_chain)
+            list_cert_chain (cert, fp);
           else
-            list_cert_colon (cert, fp, have_secret);
+            {
+              list_cert_std (cert, fp, have_secret);
+              putc ('\n', fp);
+            }
         }
       ksba_cert_release (cert); 
       cert = NULL;
     }
   if (rc && rc != -1)
-    log_error ("keydb_search failed: %s\n", gnupg_strerror (rc));
+    log_error ("keydb_search failed: %s\n", gpg_strerror (rc));
   
  leave:
   ksba_cert_release (cert);
@@ -402,6 +552,9 @@ list_external_cb (void *cb_value, KsbaCert cert)
 {
   struct list_external_parm_s *parm = cb_value;
 
+  if (keydb_store_cert (cert, 1, NULL))
+    log_error ("error storing certificate as ephemeral\n");
+
   if (parm->print_header)
     {
       const char *resname = "[external keys]";
@@ -416,8 +569,13 @@ list_external_cb (void *cb_value, KsbaCert cert)
 
   if (parm->with_colons)
     list_cert_colon (cert, parm->fp, 0);
+  else if (parm->with_chain)
+    list_cert_chain (cert, parm->fp);
   else
-    list_cert_colon (cert, parm->fp, 0);
+    {
+      list_cert_std (cert, parm->fp, 0);
+      putc ('\n', parm->fp);
+    }
 }
 
 
@@ -433,10 +591,11 @@ list_external_keys (CTRL ctrl, STRLIST names, FILE *fp)
   parm.fp = fp;
   parm.print_header = ctrl->no_server;
   parm.with_colons = ctrl->with_colons;
+  parm.with_chain = ctrl->with_chain;
 
-  rc = gpgsm_dirmngr_lookup (names, list_external_cb, &parm);
+  rc = gpgsm_dirmngr_lookup (ctrl, names, list_external_cb, &parm);
   if (rc)
-    log_error ("listing external keys failed: %s\n", gnupg_strerror (rc));
+    log_error ("listing external keys failed: %s\n", gpg_strerror (rc));
 }
 
 /* List all keys or just the key given as NAMES.