* certcheck.c: Fixed use of DBG_CRYPTO and DBG_X509.
authorWerner Koch <wk@gnupg.org>
Thu, 17 Mar 2005 19:10:37 +0000 (19:10 +0000)
committerWerner Koch <wk@gnupg.org>
Thu, 17 Mar 2005 19:10:37 +0000 (19:10 +0000)
* certchain.c (gpgsm_basic_cert_check): Dump certificates after a
failed gcry_pk_verify.
(find_up): Do an external lookup also for an authorityKeyIdentifier
lookup. Factored external lookup code out to ..
(find_up_external): .. new.

sm/ChangeLog
sm/certchain.c
sm/certcheck.c

index 85af542..bb899f5 100644 (file)
@@ -1,3 +1,13 @@
+2005-03-17  Werner Koch  <wk@g10code.com>
+
+       * certcheck.c: Fixed use of DBG_CRYPTO and DBG_X509.
+
+       * certchain.c (gpgsm_basic_cert_check): Dump certificates after a
+       failed gcry_pk_verify.
+       (find_up): Do an external lookup also for an authorityKeyIdentifier
+       lookup. Factored external lookup code out to ..
+       (find_up_external): .. new.
+
 2005-03-03  Werner Koch  <wk@g10code.com>
 
        * Makefile.am (gpgsm_LDADD): Added PTH_LIBS.  Noted by Kazu Yamamoto.
        * server.c (rc_to_assuan_status): New.  Use it for all commands.
 
        
- Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
 
  This file is free software; as a special exception the author gives
  unlimited permission to copy and/or distribute it, with or without
index f32507f..514ee23 100644 (file)
@@ -1,5 +1,5 @@
 /* certchain.c - certificate chain validation
- * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ * Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
  *
  * This file is part of GnuPG.
  *
@@ -275,6 +275,69 @@ find_up_store_certs_cb (void *cb_value, ksba_cert_t cert)
 }
 
 
+
+/* Helper for find_up().  Locate the certificate for ISSUER using an
+   external lookup.  KH is the keydb context we are currently using.
+   On success 0 is returned and the certificate may be retrieved from
+   the keydb using keydb_get_cert().*/
+static int
+find_up_external (KEYDB_HANDLE kh, const char *issuer)
+{
+  int rc;
+  strlist_t names = NULL;
+  int count = 0;
+  char *pattern;
+  const char *s;
+      
+  if (opt.verbose)
+    log_info (_("looking up issuer at external location\n"));
+  /* The DIRMNGR process is confused about unknown attributes.  As a
+     quick and ugly hack we locate the CN and use the issuer string
+     starting at this attribite.  Fixme: we should have far better
+     parsing in the dirmngr. */
+  s = strstr (issuer, "CN=");
+  if (!s || s == issuer || s[-1] != ',')
+    s = issuer;
+
+  pattern = xtrymalloc (strlen (s)+2);
+  if (!pattern)
+    return gpg_error_from_errno (errno);
+  strcpy (stpcpy (pattern, "/"), s);
+  add_to_strlist (&names, pattern);
+  xfree (pattern);
+
+  rc = gpgsm_dirmngr_lookup (NULL, names, find_up_store_certs_cb, &count);
+  free_strlist (names);
+
+  if (opt.verbose)
+    log_info (_("number of issuers matching: %d\n"), count);
+  if (rc) 
+    {
+      log_error ("external key lookup failed: %s\n", gpg_strerror (rc));
+      rc = -1;
+    }
+  else if (!count)
+    rc = -1;
+  else
+    {
+      int old;
+      /* The issuers are currently stored in the ephemeral key DB, so
+         we temporary switch to ephemeral mode. */
+      old = keydb_set_ephemeral (kh, 1);
+      keydb_search_reset (kh);
+      rc = keydb_search_subject (kh, issuer);
+      keydb_set_ephemeral (kh, old);
+    }
+  return rc;
+}
+
+
+/* Locate issuing certificate for CERT. ISSUER is the name of the
+   issuer used as a fallback if the other methods don't work.  If
+   FIND_NEXT is true, the function shall return the next possible
+   issuer.  The certificate itself is not directly returned but a
+   keydb_get_cert on the keyDb context KH will return it.  Returns 0
+   on success, -1 if not found or an error code.  */
 static int
 find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next)
 {
@@ -292,7 +355,7 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next)
               keydb_search_reset (kh);
           
           /* In case of an error try the ephemeral DB.  We can't do
-             that in find-next mode because we can't keep the search
+             that in find_next mode because we can't keep the search
              state then. */
           if (rc == -1 && !find_next)
             { 
@@ -305,7 +368,12 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next)
                 }
               keydb_set_ephemeral (kh, old);
             }
+
+          /* If we didn't found it, try an external lookup.  */
+          if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next)
+            rc = find_up_external (kh, issuer);
         }
+
       /* Print a note so that the user does not feel too helpless when
          an issuer certificate was found and gpgsm prints BAD
          signature because it is not the correct one. */
@@ -315,16 +383,17 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next)
           gpgsm_dump_serial (authidno);
           log_printf ("/");
           gpgsm_dump_string (s);
-          log_printf (") not found\n");
+          log_printf (") not found using authorityKeyIdentifier\n");
         }
       else if (rc)
         log_error ("failed to find authorityKeyIdentifier: rc=%d\n", rc);
       ksba_name_release (authid);
       xfree (authidno);
-      /* Fixme: don't know how to do dirmngr lookup with serial+issuer. */
+      /* Fixme: There is no way to do an external lookup with
+         serial+issuer. */
     }
   
-  if (rc) /* not found via authorithyKeyIdentifier, try regular issuer name */
+  if (rc) /* Not found via authorithyKeyIdentifier, try regular issuer name. */
     rc = keydb_search_subject (kh, issuer);
   if (rc == -1 && !find_next)
     {
@@ -338,51 +407,10 @@ find_up (KEYDB_HANDLE kh, ksba_cert_t cert, const char *issuer, int find_next)
       keydb_set_ephemeral (kh, old);
     }
 
+  /* Still not found.  If enabled, try an external lookup.  */
   if (rc == -1 && opt.auto_issuer_key_retrieve && !find_next)
-    {
-      STRLIST names = NULL;
-      int count = 0;
-      char *pattern;
-      const char *s;
-      
-      if (opt.verbose)
-        log_info (_("looking up issuer at external location\n"));
-      /* dirmngr is confused about unknown attributes so as a quick
-         and ugly hack we locate the CN and use this and the
-         following.  Fixme: we should have far better parsing in the
-         dirmngr. */
-      s = strstr (issuer, "CN=");
-      if (!s || s == issuer || s[-1] != ',')
-        s = issuer;
-
-      pattern = xtrymalloc (strlen (s)+2);
-      if (!pattern)
-        return OUT_OF_CORE (errno);
-      strcpy (stpcpy (pattern, "/"), s);
-      add_to_strlist (&names, pattern);
-      xfree (pattern);
-      rc = gpgsm_dirmngr_lookup (NULL, names, find_up_store_certs_cb, &count);
-      free_strlist (names);
-      if (opt.verbose)
-        log_info (_("number of issuers matching: %d\n"), count);
-      if (rc) 
-        {
-          log_error ("external key lookup failed: %s\n", gpg_strerror (rc));
-          rc = -1;
-        }
-      else if (!count)
-        rc = -1;
-      else
-        {
-          int old;
-          /* The issuers are currently stored in the ephemeral key
-             DB, so we temporary switch to ephemeral mode. */
-          old = keydb_set_ephemeral (kh, 1);
-          keydb_search_reset (kh);
-          rc = keydb_search_subject (kh, issuer);
-          keydb_set_ephemeral (kh, old);
-        }
-    }
+    rc = find_up_external (kh, issuer);
+
   return rc;
 }
 
@@ -959,7 +987,7 @@ gpgsm_basic_cert_check (ksba_cert_t cert)
     }
   else
     {
-      /* find the next cert up the tree */
+      /* Find the next cert up the tree. */
       keydb_search_reset (kh);
       rc = find_up (kh, cert, issuer, 0);
       if (rc)
@@ -990,6 +1018,11 @@ gpgsm_basic_cert_check (ksba_cert_t cert)
         {
           log_error ("certificate has a BAD signature: %s\n",
                      gpg_strerror (rc));
+          if (DBG_X509)
+            {
+              gpgsm_dump_cert ("signing issuer", issuer_cert);
+              gpgsm_dump_cert ("signed subject", cert);
+            }
           rc = gpg_error (GPG_ERR_BAD_CERT);
           goto leave;
         }
index 4f667cb..611d321 100644 (file)
@@ -101,7 +101,7 @@ do_encode_md (gcry_md_hd_t md, int algo, int pkalgo, unsigned int nbits,
       memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len;
       assert ( n == nframe );
     }
-  if (DBG_X509)
+  if (DBG_CRYPTO)
     {
       int j;
       log_debug ("encoded hash:");
@@ -196,7 +196,7 @@ gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
       ksba_free (p);
       return gpg_error (GPG_ERR_BUG);
     }
-  if (DBG_X509)
+  if (DBG_CRYPTO)
     {
       int j;
       log_debug ("signature value:");
@@ -251,7 +251,7 @@ gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert)
 
   
   rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
-  if (DBG_CRYPTO)
+  if (DBG_X509)
       log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
   gcry_md_close (md);
   gcry_sexp_release (s_sig);
@@ -294,7 +294,7 @@ gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval,
       gcry_sexp_release (s_sig);
       return gpg_error (GPG_ERR_BUG);
     }
-  if (DBG_X509)
+  if (DBG_CRYPTO)
     log_printhex ("public key: ", p, n);
 
   rc = gcry_sexp_sscan ( &s_pkey, NULL, p, n);
@@ -321,7 +321,7 @@ gpgsm_check_cms_signature (ksba_cert_t cert, ksba_const_sexp_t sigval,
   gcry_mpi_release (frame);
   
   rc = gcry_pk_verify (s_sig, s_hash, s_pkey);
-  if (DBG_CRYPTO)
+  if (DBG_X509)
       log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc));
   gcry_sexp_release (s_sig);
   gcry_sexp_release (s_hash);