dirmngr (13 files)

cvs user wk cvs at cvs.gnupg.org
Tue Feb 1 17:40:09 CET 2005


    Date: Tuesday, February 1, 2005 @ 17:49:15
  Author: wk
    Path: /cvs/dirmngr/dirmngr

Modified: ChangeLog THANKS TODO doc/dirmngr.texi jnlib/argparse.c
          src/ChangeLog src/certcache.c src/certcache.h src/crlcache.c
          src/crlfetch.c src/crlfetch.h src/dirmngr.c src/ldap.c

* crlcache.c (crl_parse_insert): Renamed a few variables and
changed diagnostic strings for clarity.
(get_issuer_cert): Renamed to get_crlissuer_cert. Try to locate
the certificate from the cache using the subject name.  Use new
fetch function.
(get_crlissuer_cert_bysn): New.
(crl_parse_insert): Use it here.
* crlfetch.c (ca_cert_fetch): Changed interface.
(fetch_next_ksba_cert): New.
* ldap.c (run_ldap_wrapper): Add arg MULTI_MODE.  Changed all
callers.
(start_default_fetch_ldap): New
* certcache.c (get_cert_bysubject): New.
(clean_cache_slot, put_cert): Store the subject DN if available.
(MAX_EXTRA_CACHED_CERTS): Increase limit of cachable certificates
to 1000.
(find_cert_bysn): Loop until a certificate with a matching S/N has
been found.

* dirmngr.c (main): Add honor-http-proxy to the gpgconf list.


------------------+
 ChangeLog        |    4 +
 THANKS           |    9 +--
 TODO             |   11 +++-
 doc/dirmngr.texi |    2 
 jnlib/argparse.c |    2 
 src/ChangeLog    |   32 +++++++++++
 src/certcache.c  |   86 +++++++++++++++++++++++--------
 src/certcache.h  |    5 +
 src/crlcache.c   |  143 +++++++++++++++++++++++++++++++++--------------------
 src/crlfetch.c   |   53 +++++++++++++++++--
 src/crlfetch.h   |   16 ++++-
 src/dirmngr.c    |   12 +++-
 src/ldap.c       |  134 +++++++++++++++++++++++++++++++++++++++++++++----
 13 files changed, 398 insertions(+), 111 deletions(-)


Index: dirmngr/ChangeLog
diff -u dirmngr/ChangeLog:1.84 dirmngr/ChangeLog:1.85
--- dirmngr/ChangeLog:1.84	Tue Jan  4 20:19:49 2005
+++ dirmngr/ChangeLog	Tue Feb  1 17:49:15 2005
@@ -1,3 +1,7 @@
+2005-01-21  Werner Koch  <wk at g10code.com>
+
+	* doc/dirmngr.texi (Dirmngr Options): Typo fix; s/URL/CRL.
+
 2005-01-04  Werner Koch  <wk at g10code.com>
 
 	* configure.ac (PTH_LIBS): Die if Pth is not available.  There is
Index: dirmngr/THANKS
diff -u dirmngr/THANKS:1.3 dirmngr/THANKS:1.4
--- dirmngr/THANKS:1.3	Sat Dec 18 09:50:39 2004
+++ dirmngr/THANKS	Tue Feb  1 17:49:15 2005
@@ -1,5 +1,6 @@
-Bernhard Reiter    <bernhard at intevation.de>
-Marcus Brinkmann   <marcus at g10code.de>
-Michael Nottebrock <michaelnottebrock at gmx.net>
+Bernhard Reiter     bernhard at intevation.de
+Marcus Brinkmann    marcus at g10code.de
+Michael Nottebrock  michaelnottebrock at gmx.net
+Neil Dunbar         neil.dunbar at hp.com
 
-The whole Ägypten Project team.
+The whole Ägypten project team.
Index: dirmngr/TODO
diff -u dirmngr/TODO:1.17 dirmngr/TODO:1.18
--- dirmngr/TODO:1.17	Fri Dec 17 11:42:18 2004
+++ dirmngr/TODO	Tue Feb  1 17:49:15 2005
@@ -7,8 +7,6 @@
    This is the server where a baseDN has been given and that baseDN is
    contained in the search pattern.
 
-* Properly use locks in crlcache.c
-
 * name subordination (nameRelativeToCRLIssuer) 
    is not yet supported by Dirmngr.
 
@@ -18,4 +16,13 @@
   this yet.  Solution is to have a mapping DN->host in our ldapservers
   configuration file.
 
+* crlcache.c
+  We use a simple approach to get the CRL issuing certificate.  We
+  might want to enhance it in case no authorityKeyIdentifier is
+  available to try all available matching certificates with the given
+  DN. OTOH, rfc3280 requires the use of authorityKeyIdentifier if
+  different signing keys are used.
+
+
+
 
Index: dirmngr/doc/dirmngr.texi
diff -u dirmngr/doc/dirmngr.texi:1.20 dirmngr/doc/dirmngr.texi:1.21
--- dirmngr/doc/dirmngr.texi:1.20	Tue Jan  4 15:16:39 2005
+++ dirmngr/doc/dirmngr.texi	Tue Feb  1 17:49:15 2005
@@ -380,7 +380,7 @@
 @opindex ignore-http-dp
 When looking for the location of a CRL, the to be tested certificate
 usually contains so called @dfn{CRL Distribution Point} (DP) entries
-which are URLs describing the way to access the URL.  The first found DP
+which are URLs describing the way to access the CRL.  The first found DP
 entry is used.  With this option all entries using the @acronym{HTTP}
 scheme are ignored when looking for a suitable DP.
 
Index: dirmngr/jnlib/argparse.c
diff -u dirmngr/jnlib/argparse.c:1.5 dirmngr/jnlib/argparse.c:1.6
--- dirmngr/jnlib/argparse.c:1.5	Tue Sep 28 14:27:26 2004
+++ dirmngr/jnlib/argparse.c	Tue Feb  1 17:49:15 2005
@@ -904,7 +904,7 @@
     switch( level ) {
       case 11: p = "foo"; break;
       case 13: p = "0.0"; break;
-      case 14: p = "Copyright (C) 2004 Free Software Foundation, Inc."; break;
+      case 14: p = "Copyright (C) 2005 Free Software Foundation, Inc."; break;
       case 15: p =
 "This program comes with ABSOLUTELY NO WARRANTY.\n"
 "This is free software, and you are welcome to redistribute it\n"
Index: dirmngr/src/ChangeLog
diff -u dirmngr/src/ChangeLog:1.41 dirmngr/src/ChangeLog:1.42
--- dirmngr/src/ChangeLog:1.41	Wed Jan  5 21:07:08 2005
+++ dirmngr/src/ChangeLog	Tue Feb  1 17:49:15 2005
@@ -1,3 +1,33 @@
+2005-02-01  Werner Koch  <wk at g10code.com>
+
+	* crlcache.c (crl_parse_insert): Renamed a few variables and
+	changed diagnostic strings for clarity.
+	(get_issuer_cert): Renamed to get_crlissuer_cert. Try to locate
+	the certificate from the cache using the subject name.  Use new
+	fetch function.
+	(get_crlissuer_cert_bysn): New.
+	(crl_parse_insert): Use it here.
+	* crlfetch.c (ca_cert_fetch): Changed interface.
+	(fetch_next_ksba_cert): New.
+	* ldap.c (run_ldap_wrapper): Add arg MULTI_MODE.  Changed all
+	callers.
+	(start_default_fetch_ldap): New
+	* certcache.c (get_cert_bysubject): New.
+	(clean_cache_slot, put_cert): Store the subject DN if available.
+	(MAX_EXTRA_CACHED_CERTS): Increase limit of cachable certificates
+	to 1000.
+	(find_cert_bysn): Loop until a certificate with a matching S/N has
+	been found.
+
+	* dirmngr.c (main): Add honor-http-proxy to the gpgconf list.
+
+2005-01-31  Werner Koch  <wk at g10code.com>
+
+	* ldap.c: Started to work on support for userSMIMECertificates.
+	
+	* dirmngr.c (main): Make sure to always pass a server control
+	structure to the caching functions.  Reported by Neil Dunbar.
+
 2005-01-05  Werner Koch  <wk at g10code.com>
 
 	* dirmngr-client.c (read_pem_certificate): Skip trailing percent
@@ -350,7 +380,7 @@
 	ChangeLog.
 	
 	
- Copyright 2004 g10 Code GmbH
+ Copyright 2004, 2005 g10 Code GmbH
 
  This file is free software; as a special exception the author gives
  unlimited permission to copy and/or distribute it, with or without
Index: dirmngr/src/certcache.c
diff -u dirmngr/src/certcache.c:1.8 dirmngr/src/certcache.c:1.9
--- dirmngr/src/certcache.c:1.8	Fri Dec  3 15:42:36 2004
+++ dirmngr/src/certcache.c	Tue Feb  1 17:49:15 2005
@@ -1,5 +1,5 @@
 /* certcache.c - Certificate caching
- *      Copyright (C) 2004 g10 Code GmbH
+ *      Copyright (C) 2004, 2005 g10 Code GmbH
  *
  * This file is part of DirMngr.
  *
@@ -36,7 +36,7 @@
 #include "certcache.h"
 
 
-#define MAX_EXTRA_CACHED_CERTS 200 /* FIXME: This is a debugging value.  */
+#define MAX_EXTRA_CACHED_CERTS 1000
 
 
 /* A certificate cache item.  This consists of a the ksba cert object
@@ -51,6 +51,7 @@
   unsigned char fpr[20];    /* The fingerprint of this object. */
   char *issuer_dn;          /* The malloced issuer DN.  */
   ksba_sexp_t sn;           /* The malloced serial number  */
+  char *subject_dn;         /* The malloced subject DN - maybe NULL.  */
   struct 
   {
     unsigned int loaded:1;  /* It has been explicitly loaded.  */
@@ -180,6 +181,8 @@
   ci->sn = NULL;
   ksba_free (ci->issuer_dn);
   ci->issuer_dn = NULL;
+  ksba_free (ci->subject_dn);
+  ci->subject_dn = NULL;
   cert = ci->cert;
   ci->cert = NULL;
 
@@ -268,6 +271,7 @@
       clean_cache_slot (ci);
       return gpg_error (GPG_ERR_INV_CERT_OBJ);
     }
+  ci->subject_dn = ksba_cert_get_subject (cert, 0);
   ci->flags.loaded  = !!is_loaded;
   ci->flags.trusted = !!is_trusted;
 
@@ -585,6 +589,34 @@
 }
 
 
+/* Return the certificate matching SUBJEC_DN.  SEQ should initially be
+   set to 0 and bumped up to get the next subject with that DN. */
+ksba_cert_t
+get_cert_bysubject (const char *subject_dn, unsigned int seq)
+{
+  /* Simple and very inefficient implementation and API.  fixme! */
+  cert_item_t ci;
+  int i;
+
+  acquire_cache_read_lock ();
+  for (i=0; i < 256; i++)
+    {
+      for (ci=cert_cache[i]; ci; ci = ci->next)
+        if (ci->cert && ci->subject_dn
+            && !strcmp (ci->subject_dn, subject_dn))
+          if (!seq--)
+            {
+              ksba_cert_ref (ci->cert);
+              release_cache_lock ();
+              return ci->cert;
+            }
+    }
+
+  release_cache_lock ();
+  return NULL;
+}
+
+
 
 
 /* Return the certificate matching ISSUER_DN and SERIALNO; if it is
@@ -593,43 +625,39 @@
 find_cert_bysn (ctrl_t ctrl, const char *issuer_dn, ksba_sexp_t serialno)
 {
   gpg_error_t err;
-  ksba_cert_t cert;
-  ksba_reader_t reader;
+  ksba_cert_t cert = NULL;
+  cert_fetch_context_t context = NULL;
 
   cert = get_cert_bysn (issuer_dn, serialno);
 
-  /* Fixme: We should not use the simple ca-fetch_cert but do a
-     regular lookup and iterate over all certificates until we found
-     a matching S/N.  */
   while (!cert)
     {
       ksba_sexp_t sn;
       char *issdn;
 
-      err = ca_cert_fetch (ctrl, issuer_dn, &reader);
-      if (err)
+      if (!context)
         {
-          log_error (_("error fetching certificate for issuer: %s\n"),
-                     gpg_strerror (err));
-          return NULL;
+          err = ca_cert_fetch (ctrl, &context, issuer_dn);
+          if (err)
+            {
+              log_error (_("error fetching certificate by S/N: %s\n"),
+                         gpg_strerror (err));
+              break;
+            }
         }
       
-      err = ksba_cert_new (&cert);
-      if (!err)
-        err = ksba_cert_read_der (cert, reader);
-      ksba_reader_release (reader);
+      err = fetch_next_ksba_cert (context, &cert);
       if (err)
         {
-          log_error (_("invalid issuer certificate: %s\n"),
+          log_error (_("error fetching certificate by S/N: %s\n"),
                      gpg_strerror (err) );
-          ksba_cert_release (cert);
-          return NULL;
+          break;
         }
       
       issdn = ksba_cert_get_issuer (cert, 0);
       if (strcmp (issuer_dn, issdn))
         {
-          log_debug ("find_cert_bysn: Ooops: Issuer DN does not match\n");
+          log_debug ("find_cert_bysn: Ooops: issuer DN does not match\n");
           ksba_cert_release (cert);
           cert = NULL;
           ksba_free (issdn);
@@ -637,20 +665,32 @@
         }
 
       sn = ksba_cert_get_serial (cert);
+
+      if (DBG_LOOKUP)
+        {
+          log_debug ("   considering certificate (#");
+          dump_serial (sn);
+          log_printf ("/");
+          dump_string (issdn);
+          log_printf (")\n");
+        }
+
       if (!compare_serialno (serialno, sn))
         {
           ksba_free (sn);
           cache_cert (cert);
+          if (DBG_LOOKUP)
+            log_debug ("   found\n");
           break; /* Ready.  */
         }
 
-      log_debug ("find_cert_bysn: S/N does not match\n");
+      ksba_free (sn);
+
       ksba_cert_release (cert);
       cert = NULL;
-      ksba_free (sn);
-      break; /* FIXME: That should be a get next cert.  */ 
     }
 
+  end_cert_fetch (context);
   return cert;
 }
 
Index: dirmngr/src/certcache.h
diff -u dirmngr/src/certcache.h:1.6 dirmngr/src/certcache.h:1.7
--- dirmngr/src/certcache.h:1.6	Wed Dec 15 23:11:59 2004
+++ dirmngr/src/certcache.h	Tue Feb  1 17:49:15 2005
@@ -56,11 +56,16 @@
    certificate.  */
 ksba_cert_t get_cert_byhexfpr (const char *string);
 
+/* Return the certificate matching ISSUER_DN and SERIALNO.  */
+ksba_cert_t get_cert_bysn (const char *issuer_dn, ksba_sexp_t serialno);
 
 /* Return the certificate matching ISSUER_DN.  SEQ should initially be
    set to 0 and bumped up to get the next issuer with that DN. */
 ksba_cert_t get_cert_byissuer (const char *issuer_dn, unsigned int seq);
 
+/* Return the certificate matching SUBJECT_DN.  SEQ should initially be
+   set to 0 and bumped up to get the next issuer with that DN. */
+ksba_cert_t get_cert_bysubject (const char *subject_dn, unsigned int seq);
 
 /* Return the certificate matching ISSUER_DN and SERIALNO; if it is
    not already in the cache, try to find it from other resources.  */
Index: dirmngr/src/crlcache.c
diff -u dirmngr/src/crlcache.c:1.52 dirmngr/src/crlcache.c:1.53
--- dirmngr/src/crlcache.c:1.52	Wed Dec 15 23:11:59 2004
+++ dirmngr/src/crlcache.c	Tue Feb  1 17:49:15 2005
@@ -1,6 +1,6 @@
 /* crlcache.c - LDAP access
  *      Copyright (C) 2002 Klarälvdalens Datakonsult AB
- *      Copyright (C) 2003, 2004 g10 Code GmbH
+ *      Copyright (C) 2003, 2004, 2005 g10 Code GmbH
  *
  * This file is part of DirMngr.
  *
@@ -1365,57 +1365,89 @@
 }  
 
 
-/* Return the certificate for ISSUER or NULL if it can't be found. */
+/* Return the certificate for NAME or NULL if it can't be found.  Note
+   that we will only return the first matching certificate. */
 static ksba_cert_t 
-get_issuer_cert (ctrl_t ctrl, const char *issuer)
+get_crlissuer_cert (ctrl_t ctrl, const char *name)
 {
   gpg_error_t err;
-  ksba_cert_t issuer_cert = NULL;
-  ksba_reader_t reader;
+  ksba_cert_t cert = NULL;
+  cert_fetch_context_t context;
 
   /* First check whether it has already been cached.  */
-  issuer_cert = get_cert_byissuer (issuer, 0);
-  if (issuer_cert)
-    return issuer_cert; /* Done. */
+  cert = get_cert_bysubject (name, 0); 
+  if (cert)
+    return cert; /* Done. */
     
   /* Ask back to the service requester to return the certificate.
      This is because we can assume that he already used the
      certificate while checking for the CRL. */
-  issuer_cert = get_cert_local (ctrl, issuer);
-  if (issuer_cert)
-    return issuer_cert; /* Done. */
+  cert = get_cert_local (ctrl, name);
+  if (cert)
+    return cert; /* Done. */
 
   /* If this fails do a regular certificate lookup. */
   if (DBG_LOOKUP)
     log_debug ("certificate for CRL issuer not returned by caller"
                " - doing lookup\n");
 
-  err = ca_cert_fetch (ctrl, issuer, &reader);
+  err = ca_cert_fetch (ctrl, &context, name);
   if (err)
     {
-      log_error (_("error fetching certificate for issuer: %s\n"),
+      log_error (_("error fetching certificate for CRL issuer: %s\n"),
                  gpg_strerror (err));
       return NULL;
     }
 
-  err = ksba_cert_new (&issuer_cert);
-  if (!err)
-    {
-      err = ksba_cert_read_der (issuer_cert, reader);
-      if (err)
-        {
-          ksba_cert_release (issuer_cert);
-          issuer_cert = NULL;
-        }
-    }
+  err = fetch_next_ksba_cert (context, &cert);
   if (err)
-    log_error (_("invalid issuer certificate: %s\n"), gpg_strerror (err) );
-  ksba_reader_release (reader);
+    log_error (_("invalid CRL issuer certificate: %s\n"), gpg_strerror (err) );
+  end_cert_fetch (context);
 
   if (!err)
-    cache_cert (issuer_cert);
+    cache_cert (cert);
+
+  return cert;
+}
+
+
+/* Return the certificate from the issuer DN NAME and the S/N SN.
+   First tries the local chache, then asks the caller and then tries
+   an ldap search. */
+static ksba_cert_t 
+get_crlissuer_cert_bysn (ctrl_t ctrl, const char *name, ksba_sexp_t sn)
+{
+  ksba_cert_t cert;
+  char *snbuf, *buf;
+
+  /* First check whether it has already been cached.  */
+  cert = get_cert_bysn (name, sn);
+  if (cert)
+    return cert; /* Done. */
+
+  /* Ask back to the service requester to return the certificate.
+     This is because we can assume that he already used the
+     certificate while checking for the CRL. */
+  snbuf = serial_hex (sn);
+  if (!snbuf)
+    snbuf = "";
+  buf = xtrymalloc (1 + strlen (snbuf) + 1 + strlen (name) + 1 );
+  if (!buf)
+    {
+      xfree (snbuf);
+      return NULL;
+    }
+  strcpy (stpcpy (stpcpy (stpcpy (buf, "#"), snbuf), "/"), name);
+  xfree (snbuf);
+  cert = get_cert_local (ctrl, buf);
+  xfree (buf);
+  if (cert)
+    {
+      cache_cert (cert);
+      return cert; /* Done. */
+    }
 
-  return issuer_cert;
+  return find_cert_bysn (ctrl, name, sn);
 }
 
 
@@ -1540,28 +1572,29 @@
    CRL object and stored in the data base file DB with the name FNAME
    (only used for printing error messages).  That DB should be a
    temporary one and not the actual one.  If the function fails the
-   caller should delete this temporary databse file.  CTRL is required
-   to retrieve certificates using the general dirmngr callback
-   service.  R_ISSUER returns an allocated string with the issuer DB,
-   THIS_UPDATE and NEXT_UPDATE are filled with the correspondind data
-   from the CRL.  Note that these values might get set even if the CRL
-   processing fails at a later step; thus the caller should free
-   *R_ISSUER even when the function returns with an error.
+   caller should delete this temporary database file.  CTRL is
+   required to retrieve certificates using the general dirmngr
+   callback service.  R_CRLISSUER returns an allocated string with the
+   crl-issuer DN, THIS_UPDATE and NEXT_UPDATE are filled with the
+   correspondind data from the CRL.  Note that these values might get
+   set even if the CRL processing fails at a later step; thus the
+   caller should free *R_ISSUER even if the function returns with an
+   error.
 */ 
 static int 
 crl_parse_insert (ctrl_t ctrl, ksba_crl_t crl,
                   struct cdb_make *cdb, const char *fname,
-                  char **r_issuer,
+                  char **r_crlissuer,
                   ksba_isotime_t thisupdate, ksba_isotime_t nextupdate)
 {  
   gpg_error_t err;
   ksba_stop_reason_t stopreason;
-  ksba_cert_t issuer_cert = NULL;
+  ksba_cert_t crlissuer_cert = NULL;
   gcry_md_hd_t md = NULL;
   int algo = 0;
   size_t n;
 
-  *r_issuer = NULL;
+  *r_crlissuer = NULL;
   *thisupdate = *nextupdate = 0;
 
   /* Start of the KSBA parser loop. */
@@ -1638,20 +1671,24 @@
       
         case KSBA_SR_READY:
           {
-            char *issuer;
+            char *crlissuer;
             ksba_name_t authid;
             ksba_sexp_t authidsn;
 
-            err = ksba_crl_get_issuer (crl, &issuer);
+            /* We need to look for the issuer only after having read
+               all items.  The issuer itselfs comes before the items
+               but the optional authorityKeyIdentifier comes after the
+               items. */
+            err = ksba_crl_get_issuer (crl, &crlissuer);
             if( err )
               {
-                log_error (_("no issuer found in CRL: %s\n"),
+                log_error (_("no CRL issuer found in CRL: %s\n"),
                            gpg_strerror (err) );
                 err = gpg_error (GPG_ERR_INV_CRL);
                 goto failure;
               }
-            *r_issuer = issuer; /* (Do it here so we don't need to
-                                    free it later) */
+            *r_crlissuer = crlissuer; /* (Do it here so we don't need
+                                         to free it later) */
 
             if (!ksba_crl_get_auth_key_id (crl, NULL, &authid, &authidsn))
               {
@@ -1663,10 +1700,10 @@
                 
                 s = ksba_name_enum (authid, 0);
                 if (s && *authidsn)
-                  issuer_cert = find_cert_bysn (ctrl, s, authidsn);
-                if (!issuer_cert)
+                  crlissuer_cert = get_crlissuer_cert_bysn (ctrl, s, authidsn);
+                if (!crlissuer_cert)
                   {
-                    log_info ("issuer certificate (#");
+                    log_info ("CRL issuer certificate (#");
                     dump_serial (authidsn);
                     log_printf ("/");
                     dump_string (s);
@@ -1676,27 +1713,27 @@
                 xfree (authidsn);
               }
             else
-              issuer_cert = get_issuer_cert (ctrl, issuer);
+              crlissuer_cert = get_crlissuer_cert (ctrl, crlissuer);
             err = 0;
-            if (!issuer_cert)
+            if (!crlissuer_cert)
               {
                 err = gpg_error (GPG_ERR_MISSING_CERT);
                 goto failure;
               }
         
-            err = finish_sig_check (crl, md, algo, issuer_cert);
+            err = finish_sig_check (crl, md, algo, crlissuer_cert);
             if (err)
               {
                 log_error (_("CRL signature verification failed: %s\n"), 
                            gpg_strerror (err));
                 goto failure;
               }
-            err = validate_cert_chain (ctrl, issuer_cert,
+            err = validate_cert_chain (ctrl, crlissuer_cert,
                                        NULL, VALIDATE_MODE_CRL);
             if (err)
               {
                 log_error (_("error checking validity of CRL "
-                             "signing certificate: %s\n"), 
+                             "issuer certificate: %s\n"), 
                            gpg_strerror (err));
                 goto failure;
               }
@@ -1715,7 +1752,7 @@
 
 
  failure:
-  ksba_cert_release (issuer_cert);
+  ksba_cert_release (crlissuer_cert);
   return err;
 }
 
@@ -1813,7 +1850,7 @@
 
 
   /* FIXME: We should acquire a mutex for the URL, so that we don't
-     simultaneously enter the same CRL twice.  However this needs t be
+     simultaneously enter the same CRL twice.  However this needs to be
      interweaved with the checking function.*/
  
   err2 = 0;
@@ -1935,7 +1972,7 @@
           || !strcmp (oid, oidstr_authorityKeyIdentifier)
           || !strcmp (oid, oidstr_crlNumber) )
         continue;
-      log_error (_("unknown crtical CRL extension %s\n"), oid);
+      log_error (_("unknown critical CRL extension %s\n"), oid);
       if (!err2)
         err2 = gpg_error (GPG_ERR_INV_CRL);
       invalidate_crl |= 2;
Index: dirmngr/src/crlfetch.c
diff -u dirmngr/src/crlfetch.c:1.23 dirmngr/src/crlfetch.c:1.24
--- dirmngr/src/crlfetch.c:1.23	Wed Dec  1 17:11:14 2004
+++ dirmngr/src/crlfetch.c	Tue Feb  1 17:49:15 2005
@@ -1,6 +1,6 @@
 /* crlfetch.c - LDAP access
  *      Copyright (C) 2002 Klarälvdalens Datakonsult AB
- *      Copyright (C) 2003, 2004 g10 Code GmbH
+ *      Copyright (C) 2003, 2004, 2005 g10 Code GmbH
  *
  * This file is part of DirMngr.
  *
@@ -142,9 +142,12 @@
 }
 
 
-/* Fetch a CA certificate for DN using the default server. */
-int
-ca_cert_fetch (ctrl_t ctrl, const char *dn, ksba_reader_t *reader)
+/* Fetch a CA certificate for DN using the default server. This
+   function only initiates the fetch; fetch_next_cert must be used to
+   actually read the certificate; end_cert_fetch to end the
+   operation. */
+gpg_error_t
+ca_cert_fetch (ctrl_t ctrl, cert_fetch_context_t *context, const char *dn)
 {
   if (opt.disable_ldap)
     {
@@ -152,7 +155,7 @@
                  "LDAP");
       return gpg_error (GPG_ERR_NOT_SUPPORTED);
     }
-  return attr_fetch_ldap (ctrl, dn, "cACertificate", reader);
+  return start_default_fetch_ldap (ctrl, context, dn, "cACertificate");
 }
 
 
@@ -162,7 +165,7 @@
 {
   if (opt.disable_ldap)
     {
-      log_error (_("Certificate search not possible due to disabled %s\n"),
+      log_error (_("certificate search not possible due to disabled %s\n"),
                  "LDAP");
       return gpg_error (GPG_ERR_NOT_SUPPORTED);
     }
@@ -176,6 +179,44 @@
   return fetch_next_cert_ldap (context, value, valuelen);
 }
 
+
+/* Fetch the next data from CONTEXT, assuming it is a certificate and return
+   it as a cert object in R_CERT.  */
+gpg_error_t
+fetch_next_ksba_cert (cert_fetch_context_t context, ksba_cert_t *r_cert)
+{
+  gpg_error_t err;
+  unsigned char *value;
+  size_t valuelen;
+  ksba_cert_t cert;
+  
+  *r_cert = NULL;
+
+  err = fetch_next_cert_ldap (context, &value, &valuelen);
+  if (!err && !value)
+    err = gpg_error (GPG_ERR_BUG);
+  if (err)
+    return err;
+
+  err = ksba_cert_new (&cert);
+  if (err)
+    {
+      xfree (value);
+      return err;
+    }
+
+  err = ksba_cert_init_from_mem (cert, value, valuelen);
+  xfree (value);
+  if (err)
+    {
+      ksba_cert_release (cert);
+      return err;
+    }
+  *r_cert = cert;
+  return 0;
+}
+
+
 void
 end_cert_fetch (cert_fetch_context_t context)
 {
Index: dirmngr/src/crlfetch.h
diff -u dirmngr/src/crlfetch.h:1.13 dirmngr/src/crlfetch.h:1.14
--- dirmngr/src/crlfetch.h:1.13	Fri Dec 17 16:16:12 2004
+++ dirmngr/src/crlfetch.h	Tue Feb  1 17:49:15 2005
@@ -39,7 +39,8 @@
 
 
 /* Fetch cert for DN. */
-int ca_cert_fetch (ctrl_t ctrl, const char *dn, ksba_reader_t *reader);
+gpg_error_t ca_cert_fetch (ctrl_t ctrl, cert_fetch_context_t *context,
+                           const char *dn);
 
 
 /* Query the server for certs matching patterns. */
@@ -49,6 +50,8 @@
                               const ldap_server_t server);
 gpg_error_t fetch_next_cert(cert_fetch_context_t context,
                             unsigned char **value, size_t *valuelen);
+gpg_error_t fetch_next_ksba_cert (cert_fetch_context_t context,
+                                  ksba_cert_t *r_cert);
 void end_cert_fetch (cert_fetch_context_t context);
 
 /* Close a reader object. */
@@ -70,10 +73,13 @@
                              ksba_reader_t *reader);
 
 
-gpg_error_t start_cert_fetch_ldap(ctrl_t ctrl,
-                                  cert_fetch_context_t *context,
-                                  strlist_t patterns,
-                                  const ldap_server_t server );
+gpg_error_t start_default_fetch_ldap (ctrl_t ctrl,
+                                      cert_fetch_context_t *context,
+                                      const char *dn, const char *attr);
+gpg_error_t start_cert_fetch_ldap( ctrl_t ctrl,
+                                   cert_fetch_context_t *context,
+                                   strlist_t patterns,
+                                   const ldap_server_t server );
 gpg_error_t fetch_next_cert_ldap (cert_fetch_context_t context,
                                   unsigned char **value, size_t *valuelen );
 void end_cert_fetch_ldap (cert_fetch_context_t context);
Index: dirmngr/src/dirmngr.c
diff -u dirmngr/src/dirmngr.c:1.54 dirmngr/src/dirmngr.c:1.55
--- dirmngr/src/dirmngr.c:1.54	Fri Dec 17 16:16:12 2004
+++ dirmngr/src/dirmngr.c	Tue Feb  1 17:49:15 2005
@@ -931,15 +931,20 @@
     }
   else if (cmd == aLoadCRL)
     {
+      struct server_control_s ctrlbuf;
+
+      memset (&ctrlbuf, 0, sizeof ctrlbuf);
+      dirmngr_init_default_ctrl (&ctrlbuf);
+
       launch_reaper_thread ();
       cert_cache_init ();
       crl_cache_init ();
       if (!argc)
-        rc = crl_cache_load (NULL, NULL);
+        rc = crl_cache_load (&ctrlbuf, NULL);
       else
         {
           for (; !rc && argc; argc--, argv++)
-            rc = crl_cache_load (NULL, *argv);
+            rc = crl_cache_load (&ctrlbuf, *argv);
         }
     }
   else if (cmd == aFetchCRL)
@@ -962,7 +967,7 @@
                      argv[0], gpg_strerror (rc));
       else
         {
-          rc = crl_cache_insert (NULL, argv[0], reader); 
+          rc = crl_cache_insert (&ctrlbuf, argv[0], reader); 
           if (rc)
             log_error (_("processing CRL from `%s' failed: %s\n"),
                        argv[0], gpg_strerror (rc));
@@ -1035,6 +1040,7 @@
 
       printf ("disable-http:%lu:\n", GC_OPT_FLAG_NONE);
       printf ("disable-ldap:%lu:\n", GC_OPT_FLAG_NONE);
+      printf ("honor-http-proxy:%lu\n", GC_OPT_FLAG_NONE);
       printf ("http-proxy:%lu:\n", GC_OPT_FLAG_NONE);
       printf ("ldap-proxy:%lu:\n", GC_OPT_FLAG_NONE);
       printf ("only-ldap-proxy:%lu:\n", GC_OPT_FLAG_NONE);
Index: dirmngr/src/ldap.c
diff -u dirmngr/src/ldap.c:1.45 dirmngr/src/ldap.c:1.46
--- dirmngr/src/ldap.c:1.45	Fri Dec 17 16:16:12 2004
+++ dirmngr/src/ldap.c	Tue Feb  1 17:49:15 2005
@@ -1,6 +1,6 @@
 /* ldap.c - LDAP access
  *      Copyright (C) 2002 Klarälvdalens Datakonsult AB
- *      Copyright (C) 2003, 2004 g10 Code GmbH
+ *      Copyright (C) 2003, 2004, 2005 g10 Code GmbH
  *
  * This file is part of DirMngr.
  *
@@ -51,6 +51,7 @@
                             "$-_.+!*'(),"
 #define USERCERTIFICATE "userCertificate"
 #define CACERTIFICATE   "caCertificate"
+#define USERSMIMECERTIFICATE "userSMIMECertificate"
 
 
 /* Definition for the context of the cert fetch functions. */
@@ -705,7 +706,7 @@
   if (opt.verbose)
     log_info (_("ldap wrapper %d started\n"), (int)ctx->pid);
 
-  /* Need to wait for the first byte so we are able todetect an empty
+  /* Need to wait for the first byte so we are able to detect an empty
      output and not let the consumer se an EOF without further error
      indications.  The CRL loading logic assumes that after return
      from this function, a failed search (e.g. host not found ) is
@@ -737,6 +738,7 @@
 static gpg_error_t
 run_ldap_wrapper (ctrl_t ctrl, 
                   int ignore_timeout,
+                  int multi_mode,
                   const char *proxy,
                   const char *host, int port, 
                   const char *user, const char *pass,
@@ -744,7 +746,7 @@
                   const char *url,
                   ksba_reader_t *reader)
 {
-  const char *argv[30];
+  const char *argv[40];
   int argc;
   char portbuf[30], timeoutbuf[30];
   
@@ -760,6 +762,8 @@
   if (opt.verbose)
     argv[argc++] = "-vv";
   argv[argc++] = "--log-with-pid";
+  if (multi_mode)
+    argv[argc++] = "--multi";
   if (opt.ldaptimeout)
     {
       sprintf (timeoutbuf, "%u", opt.ldaptimeout);
@@ -825,6 +829,7 @@
   err = run_ldap_wrapper (ctrl,
                           1, /* Ignore explicit timeout because CRLS
                                 might be very large. */
+                          0,
                           opt.ldap_proxy,
                           host, port,
                           NULL, NULL,
@@ -864,6 +869,7 @@
         {
           err = run_ldap_wrapper (ctrl,
                                   0,
+                                  0,
                                   NULL,
                                   server->host, server->port,
                                   NULL, NULL,
@@ -896,6 +902,7 @@
     {
       err = run_ldap_wrapper (ctrl,
                               0,
+                              0,
                               opt.ldap_proxy,
                               server->host, server->port,
                               server->user, server->pass,
@@ -1041,7 +1048,9 @@
 {
   gpg_error_t err;
   char *u_dn, *u_filter;
-  char const attrs[] = (USERCERTIFICATE "," CACERTIFICATE);
+  char const attrs[] = (USERCERTIFICATE ","
+/*                         USERSMIMECERTIFICATE "," */
+                        CACERTIFICATE);
 
   *url = NULL;
 
@@ -1079,8 +1088,48 @@
 }
 
 
+/* Prepare an LDAP query to return the attribute ATTR for the DN.  All
+   vonfigured default servers are queried until one responds.  This
+   function returns an error code or 0 and a CONTEXT on success. */
+gpg_error_t
+start_default_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *context,
+                          const char *dn, const char *attr)
+{
+  gpg_error_t err;
+  struct ldap_server_s *server;
+
+  *context = xtrycalloc (1, sizeof **context);
+  if (!*context)
+    return gpg_error_from_errno (errno);
+
+  /* FIXME; we might want to look at the Base SN to try matching
+     servers first. */
+  err = gpg_error (GPG_ERR_CONFIGURATION);
+  for (server = opt.ldapservers; server; server = server->next)
+    {
+      err = run_ldap_wrapper (ctrl,
+                              0,
+                              1,
+                              opt.ldap_proxy,
+                              server->host, server->port,
+                              server->user, server->pass,
+                              dn, "objectClass=*", attr, NULL,
+                              &(*context)->reader);
+      if (!err)
+        break; /* Probably found a result. */
+    }
+
+  if (err)
+    {
+      xfree (*context);
+      *context = NULL;
+    }
+  return err;
+}
+
+
 /* Prepare an LDAP query to return certificates maching PATTERNS using
-   the SERVER.  This function retruns an error code or 0 and a CONTEXT
+   the SERVER.  This function returns an error code or 0 and a CONTEXT
    on success. */
 gpg_error_t
 start_cert_fetch_ldap (ctrl_t ctrl, cert_fetch_context_t *context,
@@ -1227,13 +1276,14 @@
    has been truncated. */
 gpg_error_t
 fetch_next_cert_ldap (cert_fetch_context_t context,
-  unsigned char **value, size_t *valuelen)
+                      unsigned char **value, size_t *valuelen)
 {
   gpg_error_t err;
   unsigned char hdr[5];
   char *p, *pend;
   int n;
   int okay = 0;
+  int is_cms = 0;
 
   *value = NULL;
   *valuelen = 0;
@@ -1247,12 +1297,63 @@
       n = (hdr[1] << 24)|(hdr[2]<<16)|(hdr[3]<<8)|hdr[4];
       if (*hdr == 'V' && okay)
         {
-          *value = xtrymalloc (n);
-          if (!*value)
-            return gpg_error_from_errno (errno);
-          *valuelen = n; 
-          err = read_buffer (context->reader, *value, n);
-          break; /* Ready or error.  */
+#if 0  /* That code is not yet ready.  */
+       
+          if (is_cms)
+            {
+              /* The certificate needs to be parsed from CMS data.  Read */
+              ksba_cms_t cms;
+              ksba_stop_reason_t stopreason;
+              int i;
+          
+              err = ksba_cms_new (&cms);
+              if (err)
+                goto leave;
+              err = ksba_cms_set_reader_writer (cms, context->reader, NULL);
+              if (err)
+                {
+                  log_error ("ksba_cms_set_reader_writer failed: %s\n",
+                             gpg_strerror (err));
+                  goto leave;
+                }
+
+              do 
+                {
+                  err = ksba_cms_parse (cms, &stopreason);
+                  if (err)
+                    {
+                      log_error ("ksba_cms_parse failed: %s\n",
+                                 gpg_strerror (err));
+                      goto leave;
+                    }
+
+                  if (stopreason == KSBA_SR_BEGIN_DATA)
+                    log_error ("userSMIMECertificate is not "
+                               "a certs-only message\n");
+                }
+              while (stopreason != KSBA_SR_READY);   
+      
+              for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++)
+                {
+                  check_and_store (ctrl, stats, cert, 0);
+                  ksba_cert_release (cert); 
+                  cert = NULL;
+                }
+              if (!i)
+                log_error ("no certificate found\n");
+              else
+                any = 1;
+            }
+          else
+#endif
+            {
+              *value = xtrymalloc (n);
+              if (!*value)
+                return gpg_error_from_errno (errno);
+              *valuelen = n; 
+              err = read_buffer (context->reader, *value, n);
+              break; /* Ready or error.  */
+            }
         }
       else if (!n && *hdr == 'A')
         okay = 0;
@@ -1274,6 +1375,7 @@
             {
               p = context->tmpbuf;
               p[n] = 0; /*(we allocated one extra byte for this.)*/
+              is_cms = 0;
               if ( (pend = strchr (p, ';')) )
                 *pend = 0; /* Strip off the extension. */
               if (!ascii_strcasecmp (p, USERCERTIFICATE))
@@ -1290,6 +1392,14 @@
                                CACERTIFICATE);
                   okay = 1;
                 }
+/*               else if (!ascii_strcasecmp (p, USERSMIMECERTIFICATE)) */
+/*                 { */
+/*                   if (DBG_LOOKUP) */
+/*                     log_debug ("fetch_next_cert_ldap: got attribute `%s'\n", */
+/*                                USERSMIMECERTIFICATE); */
+/*                   okay = 1; */
+/*                   is_cms = 1; */
+/*                 } */
               else
                 {
                   if (DBG_LOOKUP)




More information about the Gnupg-commits mailing list