On 10/31/06, Graham Leggett <[EMAIL PROTECTED]> wrote:
On Tue, October 31, 2006 1:25 am, Eric Covener wrote:
Not having looked at the openldap SDK for a while - at what point do we
call ldap_set_option(...,APR_LDAP_OPT_X_TLS_NEWCTX,...) - is this done
just before connection? Or is it done when setting the client certificate?

Oops, just occured to me that my svn diff didn't pick up the
accompanying apr-util changes.  These changes happen right after the
client certificate is set with ldap_set_option()
http://mail-archives.apache.org/mod_mbox/apr-dev/200611.mbox/[EMAIL PROTECTED]

The patch above is required to get the LDAPTrustedClientCert stuff we
push onto the LDAP* to actually affect the openldap/openssl TLS
environment.

Attached here are patches against trunk for the httpd side.  This
makes LDAPTrustedClientCert really act like a per-directory
configuration setting.

Linking against openldap-HEAD you can do:

LDAPTrustedGlobalCert CA_BASE64 /home/covener/CA.crt
LDAPTrustedGlobalCert CERT_BASE64 /home/covener/cert.pem
LDAPTrustedGlobalCert KEY_BASE64 /home/covener/cert..key
<Location /default>
AuthLDAPURL ...
...
<Location /other>
LDAPTrustedClientCert CERT_BASE64 /home/covener/other.pem
LDAPTrustedClientCert KEY_BASE64 /home/covener/other.key
AuthLDAPURL ...
...

The attached doc patch is a bit fishy -- I didn't see a precedent for
this kind of "teaser". The alternative is to claim global client certs
only for OpenLDAP until openldap 2.4.x is mainstream.

While I didn't yet get a chance to test w/ Mozilla, this can't do
anything but help per-connection nicknames become usable.

(Thanks for keeping an eye on this thread)

--
Eric Covener
[EMAIL PROTECTED]
Index: modules/ldap/util_ldap.c
===================================================================
--- modules/ldap/util_ldap.c	(revision 475423)
+++ modules/ldap/util_ldap.c	(working copy)
@@ -244,7 +244,16 @@
 
     /* set client certificates */
     if (!apr_is_empty_array(ldc->client_certs)) {
+        /* Push global certs onto this per-connection config */
         apr_ldap_set_option(ldc->pool, ldc->ldap, APR_LDAP_OPT_TLS_CERT,
+                            st->global_certs, &(result));
+        if (LDAP_SUCCESS != result->rc) {
+            uldap_connection_unbind( ldc );
+            ldc->reason = result->reason;
+            return(result->rc);
+        }
+
+        apr_ldap_set_option(ldc->pool, ldc->ldap, APR_LDAP_OPT_TLS_CERT,
                             ldc->client_certs, &(result));
         if (LDAP_SUCCESS != result->rc) {
             uldap_connection_unbind( ldc );
@@ -416,9 +425,12 @@
     dest = (struct apr_ldap_opt_tls_cert_t *)dests->elts;
     for (i = 0; i < srcs->nelts; i++) {
         if (strcmp(src[i].path, dest[i].path) ||
-            strcmp(src[i].password, dest[i].password) ||
-            src[i].type != dest[i].type) {
-            return 1;
+           (src[i].type != dest[i].type)  ||
+           /* One is passwordless? If so, then not equal */
+           ((src[i].password == NULL) ^ (dest[i].password == NULL)) ||
+           (src[i].password != NULL && dest[i].password != NULL &&
+           strcmp(src[i].password, dest[i].password))) {
+               return 1;
         }
     }
 
@@ -448,8 +460,9 @@
     util_ldap_state_t *st =
         (util_ldap_state_t *)ap_get_module_config(r->server->module_config,
         &ldap_module);
+    util_ldap_config_t *dc = 
+        (util_ldap_config_t *) ap_get_module_config(r->per_dir_config, &ldap_module);
 
-
 #if APR_HAS_THREADS
     /* mutex lock this function */
     apr_thread_mutex_lock(st->mutex);
@@ -472,7 +485,7 @@
             && ((!l->bindpw && !bindpw) || (l->bindpw && bindpw
                                              && !strcmp(l->bindpw, bindpw)))
             && (l->deref == deref) && (l->secure == secureflag)
-            && !compare_client_certs(st->client_certs, l->client_certs))
+            && !compare_client_certs(dc->client_certs, l->client_certs))
         {
             break;
         }
@@ -497,7 +510,7 @@
 #endif
             if ((l->port == port) && (strcmp(l->host, host) == 0) &&
                 (l->deref == deref) && (l->secure == secureflag) &&
-                !compare_client_certs(st->client_certs, l->client_certs))
+                !compare_client_certs(dc->client_certs, l->client_certs))
             {
                 /* the bind credentials have changed */
                 l->bound = 0;
@@ -551,7 +564,7 @@
         l->secure = secureflag;
 
         /* save away a copy of the client cert list that is presently valid */
-        l->client_certs = apr_array_copy_hdr(l->pool, st->client_certs);
+        l->client_certs = apr_array_copy_hdr(l->pool, dc->client_certs);
 
         /* add the cleanup to the pool */
         apr_pool_cleanup_register(l->pool, l,
@@ -1606,9 +1619,8 @@
                                                      const char *file,
                                                      const char *password)
 {
-    util_ldap_state_t *st =
-        (util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
-                                                  &ldap_module);
+    util_ldap_config_t *dc =  config;
+
     apr_finfo_t finfo;
     apr_status_t rv;
     int cert_type = 0;
@@ -1648,7 +1660,7 @@
                        file, type);
 
     /* add the certificate to the global array */
-    cert = (apr_ldap_opt_tls_cert_t *)apr_array_push(st->global_certs);
+    cert = (apr_ldap_opt_tls_cert_t *)apr_array_push(dc->client_certs);
     cert->type = cert_type;
     cert->path = file;
     cert->password = password;
@@ -1765,6 +1777,13 @@
 }
 
 
+static void *util_ldap_create_dir_config(apr_pool_t *p, char *d) { 
+   util_ldap_config_t *dc = 
+       (util_ldap_config_t *) apr_pcalloc(p,sizeof(util_ldap_config_t));
+
+   dc->client_certs = apr_array_make(p, 10, sizeof(apr_ldap_opt_tls_cert_t));
+   return dc;
+}
 static void *util_ldap_create_config(apr_pool_t *p, server_rec *s)
 {
     util_ldap_state_t *st =
@@ -1787,7 +1806,6 @@
     st->connections = NULL;
     st->ssl_supported = 0;
     st->global_certs = apr_array_make(p, 10, sizeof(apr_ldap_opt_tls_cert_t));
-    st->client_certs = apr_array_make(p, 10, sizeof(apr_ldap_opt_tls_cert_t));
     st->secure = APR_LDAP_NONE;
     st->secure_set = 0;
     st->connectionTimeout = 10;
@@ -1821,8 +1839,6 @@
     st->ssl_supported = 0;
     st->global_certs = apr_array_append(p, base->global_certs,
                                            overrides->global_certs);
-    st->client_certs = apr_array_append(p, base->client_certs,
-                                           overrides->client_certs);
     st->secure = (overrides->secure_set == 0) ? base->secure
                                               : overrides->secure;
 
@@ -2065,7 +2081,7 @@
                    "Third arg is an optional passphrase if applicable."),
 
     AP_INIT_TAKE23("LDAPTrustedClientCert", util_ldap_set_trusted_client_cert,
-                   NULL, RSRC_CONF,
+                   NULL, OR_AUTHCFG,
                    "Takes three args; the file and/or directory containing "
                    "the client certificate, or certificate ID used to "
                    "validate this LDAP client.  Second arg is the cert type "
@@ -2112,7 +2128,7 @@
 
 module AP_MODULE_DECLARE_DATA ldap_module = {
    STANDARD20_MODULE_STUFF,
-   NULL,                        /* create dir config */
+   util_ldap_create_dir_config,  /* create dir config */
    NULL,                        /* merge dir config */
    util_ldap_create_config,     /* create server config */
    util_ldap_merge_config,      /* merge server config */
Index: mod/mod_ldap.xml
===================================================================
--- mod/mod_ldap.xml	(revision 475382)
+++ mod/mod_ldap.xml	(working copy)
@@ -325,9 +325,15 @@
         SDK to work correctly. These certificates can be specified as
         binary DER or Base64 (PEM) encoded files.</p>
 
-        <p>Client certificates are specified per connection using the
-        LDAPTrustedClientCert directive.</p>
+        <p>Client certificates may only be specified using the LDAPTrustedGlobalCert directive</p>
 
+        <note>When httpd has been built against version 2.4.4 or higher of the OpenLDAP SDK,
+        Client certificates may be specified on a per-connection basis via the LDAPTrustedClientCert directive. 
+        </note> 
+
+        <p>Password protected private keys are not supported by the 
+        OpenLDAP SDK </p>
+
         <p>The documentation for the SDK claims to support both SSL and
         STARTTLS, however STARTTLS does not seem to work on all versions
         of the SDK. The SSL/TLS mode can be set using the
@@ -340,14 +346,19 @@
              # Specify two CA certificate files<br />
              LDAPTrustedGlobalCert CA_DER /certs/cacert1.der<br />
              LDAPTrustedGlobalCert CA_BASE64 /certs/cacert2.pem<br />
+             # Specify client certificate to be used globally<br />
+             LDAPTrustedGlobalCert CERT_BASE64 /certs/cert1.pem<br />
+             LDAPTrustedGlobalCert KEY_BASE64 /certs/key1.pem<br />
             &lt;Location /ldap-status&gt;<br />
             <indent>
                 SetHandler ldap-status<br />
                 Order deny,allow<br />
                 Deny from all<br />
                 Allow from yourdomain.example.com<br />
-                LDAPTrustedClientCert CERT_BASE64 /certs/cert1.pem<br />
-                LDAPTrustedClientCert KEY_BASE64 /certs/key1.pem<br />
+                # Version 2.4.4 or higher  of the SDK allows per-connection client certificates<br />
+                # to be specified<br />
+                # LDAPTrustedClientCert CERT_BASE64 /certs/othercert.pem<br />
+                # LDAPTrustedClientCert KEY_BASE64 /certs/otherkey.pem<br />
                 AuthLDAPURL ldaps://127.0.0.1/dc=example,dc=com?uid?one<br />
                 AuthzLDAPAuthoritative off<br />
                 require valid-user<br />

Reply via email to