Fixed aegypten bug 299
[gnupg.git] / sm / keylist.c
index 0c8ebd3..39c4e50 100644 (file)
@@ -1,6 +1,6 @@
-/* keylist.c
+/* keylist.c - Print certificates in various formats.
  * Copyright (C) 1998, 1999, 2000, 2001, 2003,
- *               2004 Free Software Foundation, Inc.
+ *               2004, 2005 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -16,7 +16,8 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
  */
 
 #include <config.h>
@@ -66,6 +67,12 @@ struct {
   { "1.3.6.1.5.5.7.3.11", "sbgpCertAAServerAuth" },
   { "1.3.6.1.5.5.7.3.13", "eapOverPPP" },
   { "1.3.6.1.5.5.7.3.14", "wlanSSID" },       
+
+  { "2.16.840.1.113730.4.1", "serverGatedCrypto.ns" }, /* Netscape. */
+  { "1.3.6.1.4.1.311.10.3.3", "serverGatedCrypto.ms"}, /* Microsoft. */
+
+  { "1.3.6.1.5.5.7.48.1.5", "ocspNoCheck" },
+
   { NULL, NULL }
 };
 
@@ -121,8 +128,13 @@ static struct {
   { "1.3.6.1.5.5.7.1.10", "acProxying" },
   { "1.3.6.1.5.5.7.1.11", "subjectInfoAccess" },
 
+  { "1.3.6.1.5.5.7.48.1", "ocsp" },
+  { "1.3.6.1.5.5.7.48.2", "caIssuers" },
+  { "1.3.6.1.5.5.7.48.3", "timeStamping" },
+  { "1.3.6.1.5.5.7.48.5", "caRepository" },
+
   /* X.509 id-ce */
-  { "2.5.29.14", "subjectKeyIdentifier"},
+  { "2.5.29.14", "subjectKeyIdentifier", 1},
   { "2.5.29.15", "keyUsage", 1 },
   { "2.5.29.16", "privateKeyUsagePeriod" },
   { "2.5.29.17", "subjectAltName", 1 },
@@ -160,6 +172,9 @@ static struct {
   { "2.16.840.1.113730.1.12", "netscape-ssl-server-name" },
   { "2.16.840.1.113730.1.13", "netscape-comment" },
 
+  /* GnuPG extensions */
+  { "1.3.6.1.4.1.11591.2.1.1", "pkaAddress" },
+
   { NULL }
 };
 
@@ -207,6 +222,21 @@ print_capabilities (ksba_cert_t cert, FILE *fp)
 {
   gpg_error_t err;
   unsigned int use;
+  size_t buflen;
+  char buffer[1];
+
+  err = ksba_cert_get_user_data (cert, "is_qualified", 
+                                 &buffer, sizeof (buffer), &buflen);
+  if (!err && buflen)
+    {
+      if (*buffer)
+        putc ('q', fp);
+    }    
+  else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
+    ; /* Don't know - will not get marked as 'q' */
+  else
+    log_debug ("get_user_data(is_qualified) failed: %s\n",
+               gpg_strerror (err)); 
 
   err = ksba_cert_get_key_usage (cert, &use);
   if (gpg_err_code (err) == GPG_ERR_NO_DATA)
@@ -251,34 +281,46 @@ print_time (gnupg_isotime_t t, FILE *fp)
 }
 
 
-/* return an allocated string with the email address extracted from a
+/* Return an allocated string with the email address extracted from a
    DN */
 static char *
 email_kludge (const char *name)
 {
-  const unsigned char *p;
+  const char *p, *string;
   unsigned char *buf;
   int n;
 
-  if (strncmp (name, "1.2.840.113549.1.9.1=#", 22))
-    return NULL;
+  string = name;
+  for (;;)
+    {
+      p = strstr (string, "1.2.840.113549.1.9.1=#");
+      if (!p)
+        return NULL;
+      if (p == name || (p > string+1 && p[-1] == ',' && p[-2] != '\\'))
+        {
+          name = p + 22;
+          break;
+        }
+      string = p + 22;
+    }
+
+
   /* This looks pretty much like an email address in the subject's DN
      we use this to add an additional user ID entry.  This way,
      openSSL generated keys get a nicer and usable listing */
-  name += 22;    
   for (n=0, p=name; hexdigitp (p) && hexdigitp (p+1); p +=2, n++)
     ;
-  if (*p != '#' || !n)
+  if (!n)
     return NULL;
   buf = xtrymalloc (n+3);
   if (!buf)
     return NULL; /* oops, out of core */
   *buf = '<';
-  for (n=1, p=name; *p != '#'; p +=2, n++)
+  for (n=1, p=name; hexdigitp (p); p +=2, n++)
     buf[n] = xtoi_2 (p);
   buf[n++] = '>';
   buf[n] = 0;
-  return buf;
+  return (char*)buf;
 }
 
 
@@ -333,6 +375,9 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
 
 
   fputs (have_secret? "crs:":"crt:", fp);
+
+  /* Note: We can't use multiple flags, like "ei", because the
+     validation check does only return one error.  */
   truststring[0] = 0;
   truststring[1] = 0;
   if ((validity & VALIDITY_REVOKED)
@@ -340,8 +385,6 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
     *truststring = 'r';
   else if (gpg_err_code (valerr) == GPG_ERR_CERT_EXPIRED)
     *truststring = 'e';
-  else if (valerr)
-    *truststring = 'i';
   else 
     {
       /* Lets also check whether the certificate under question
@@ -354,14 +397,18 @@ list_cert_colon (ctrl_t ctrl, ksba_cert_t cert, unsigned int validity,
           && !ksba_cert_get_validity (cert, 1, not_after)
           && *not_after && strcmp (current_time, not_after) > 0 )
         *truststring = 'e';
+      else if (valerr)
+        *truststring = 'i';
     }
 
-  /* Is we have no truststring yet (i.e. the certificate might be
+  /* If we have no truststring yet (i.e. the certificate might be
      good) and this is a root certificate, we ask the agent whether
      this is a trusted root certificate. */
   if (!*truststring && is_root)
     {
-      rc = gpgsm_agent_istrusted (ctrl, cert);
+      struct rootca_flags_s dummy_flags;
+
+      rc = gpgsm_agent_istrusted (ctrl, cert, &dummy_flags);
       if (!rc)
         *truststring = 'u';  /* Yes, we trust this one (ultimately). */
       else if (gpg_err_code (rc) == GPG_ERR_NOT_TRUSTED)
@@ -493,7 +540,9 @@ print_names_raw (FILE *fp, int indent, ksba_name_t name)
   for (idx=0; (s = ksba_name_enum (name, idx)); idx++)
     {
       char *p = ksba_name_get_uri (name, idx);
-      printf ("%*s%s\n", idx||indent_all?indent:0, "", p?p:s);
+      printf ("%*s", idx||indent_all?indent:0, "");
+      print_sanitized_string (fp, p?p:s, 0);
+      putc ('\n', fp);
       xfree (p);
     }
 }
@@ -509,7 +558,7 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd,
 {
   gpg_error_t err;
   size_t off, len;
-  ksba_sexp_t sexp;
+  ksba_sexp_t sexp, keyid;
   char *dn;
   ksba_isotime_t t;
   int idx, i;
@@ -560,6 +609,10 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd,
   fprintf (fp, "      md5_fpr: %s\n", dn?dn:"error");
   xfree (dn);
 
+  dn = gpgsm_get_certid (cert);
+  fprintf (fp, "       certid: %s\n", dn?dn:"error");
+  xfree (dn);
+
   dn = gpgsm_get_keygrip_hexstring (cert);
   fprintf (fp, "      keygrip: %s\n", dn?dn:"error");
   xfree (dn);
@@ -585,9 +638,27 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd,
     fprintf (fp, "      keyType: %u bit %s\n",  nbits, algoname? algoname:"?");
   }
 
+  /* subjectKeyIdentifier */
+  fputs ("    subjKeyId: ", fp);
+  err = ksba_cert_get_subj_key_id (cert, NULL, &keyid);
+  if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA)
+    {
+      if (gpg_err_code (err) == GPG_ERR_NO_DATA)
+        fputs ("[none]\n", fp);
+      else
+        {
+          gpgsm_print_serial (fp, keyid);
+          ksba_free (keyid);
+          putc ('\n', fp);
+        }
+    }
+  else
+    fputs ("[?]\n", fp);
+
+
   /* authorityKeyIdentifier */
   fputs ("    authKeyId: ", fp);
-  err = ksba_cert_get_auth_key_id (cert, NULL, &name, &sexp);
+  err = ksba_cert_get_auth_key_id (cert, &keyid, &name, &sexp);
   if (!err || gpg_err_code (err) == GPG_ERR_NO_DATA)
     {
       if (gpg_err_code (err) == GPG_ERR_NO_DATA || !name)
@@ -600,6 +671,13 @@ list_cert_raw (ctrl_t ctrl, KEYDB_HANDLE hd,
           print_names_raw (fp, -15, name);
           ksba_name_release (name);
         }
+      if (keyid)
+        {
+          fputs (" authKeyId.ki: ", fp);
+          gpgsm_print_serial (fp, keyid);
+          ksba_free (keyid);
+          putc ('\n', fp);
+        }
     }
   else
     fputs ("[?]\n", fp);
@@ -992,9 +1070,28 @@ list_cert_std (ctrl_t ctrl, ksba_cert_t cert, FILE *fp, int have_secret,
   fprintf (fp, "  fingerprint: %s\n", dn?dn:"error");
   xfree (dn);
 
+
+
   if (with_validation)
     {
+      gpg_error_t tmperr;
+      size_t buflen;
+      char buffer[1];
+      
       err = gpgsm_validate_chain (ctrl, cert, NULL, 1, fp, 0);
+      tmperr = ksba_cert_get_user_data (cert, "is_qualified", 
+                                        &buffer, sizeof (buffer), &buflen);
+      if (!tmperr && buflen)
+        {
+          if (*buffer)
+            fputs ("  [qualified]\n", fp);
+        }    
+      else if (gpg_err_code (tmperr) == GPG_ERR_NOT_FOUND)
+        ; /* Don't know - will not get marked as 'q' */
+      else
+        log_debug ("get_user_data(is_qualified) failed: %s\n",
+                   gpg_strerror (tmperr)); 
+
       if (!err)
         fprintf (fp, "  [certificate is good]\n");
       else
@@ -1035,15 +1132,15 @@ list_cert_chain (ctrl_t ctrl, KEYDB_HANDLE hd,
 /* List all internal keys or just the keys given as NAMES.  MODE is a
    bit vector to specify what keys are to be included; see
    gpgsm_list_keys (below) for details.  If RAW_MODE is true, the raw
-   output mode will be used intead of the standard beautified one.
+   output mode will be used instead of the standard beautified one.
  */
 static gpg_error_t
-list_internal_keys (ctrl_t ctrl, STRLIST names, FILE *fp,
+list_internal_keys (ctrl_t ctrl, strlist_t names, FILE *fp,
                     unsigned int mode, int raw_mode)
 {
   KEYDB_HANDLE hd;
   KEYDB_SEARCH_DESC *desc = NULL;
-  STRLIST sl;
+  strlist_t sl;
   int ndesc;
   ksba_cert_t cert = NULL;
   gpg_error_t rc = 0;
@@ -1069,7 +1166,7 @@ list_internal_keys (ctrl_t ctrl, STRLIST names, FILE *fp,
   desc = xtrycalloc (ndesc, sizeof *desc);
   if (!ndesc)
     {
-      rc = gpg_error_from_errno (errno);
+      rc = gpg_error_from_syserror ();
       log_error ("out of core\n");
       goto leave;
     }
@@ -1134,7 +1231,7 @@ list_internal_keys (ctrl_t ctrl, STRLIST names, FILE *fp,
             {
               fprintf (fp, "%s\n", resname );
               for (i=strlen(resname); i; i-- )
-                putchar('-');
+                putc ('-', fp);
               putc ('\n', fp);
               lastresname = resname;
             }
@@ -1146,8 +1243,8 @@ list_internal_keys (ctrl_t ctrl, STRLIST names, FILE *fp,
           char *p = gpgsm_get_keygrip_hexstring (cert);
           if (p)
             {
-              rc = gpgsm_agent_havekey (ctrl, p);
-              if (!rc)
+              rc = gpgsm_agent_havekey (ctrl, p); 
+             if (!rc)
                 have_secret = 1;
               else if ( gpg_err_code (rc) != GPG_ERR_NO_SECKEY)
                 goto leave;
@@ -1232,7 +1329,7 @@ list_external_cb (void *cb_value, ksba_cert_t cert)
    make sense here because it would be unwise to list external secret
    keys */
 static gpg_error_t
-list_external_keys (CTRL ctrl, STRLIST names, FILE *fp, int raw_mode)
+list_external_keys (ctrl_t ctrl, strlist_t names, FILE *fp, int raw_mode)
 {
   int rc;
   struct list_external_parm_s parm;
@@ -1262,7 +1359,7 @@ list_external_keys (CTRL ctrl, STRLIST names, FILE *fp, int raw_mode)
     Bit 8: Do a raw format dump.
  */
 gpg_error_t
-gpgsm_list_keys (CTRL ctrl, STRLIST names, FILE *fp, unsigned int mode)
+gpgsm_list_keys (ctrl_t ctrl, strlist_t names, FILE *fp, unsigned int mode)
 {
   gpg_error_t err = 0;