On 10/31/06, Graham Leggett <[EMAIL PROTECTED]> wrote:
On Tue, October 31, 2006 1:25 am, Eric Covener wrote:

> Looks like the openldap 2.4 series (alpha) can support this by
> requesting a new openssl CTX
> (ldap_set_option(...,APR_LDAP_OPT_X_TLS_NEWCTX,...) but I had to
> explicitly call openssl's SSL_library_init(); before ldap_set_option
> or it died creating the new context.
>
> (with the added calls, test program works as expected in per-connection
> context)
>
> May be a limitation for util_ldap to not poke around in per-connection
> settings for (earlier than 2.4) openldap, and some rework to flip the
> right switches at the right time for 2.4 and better.

The logic to try and determine which behaviour to use with which LDAP SDK
was abstracted into apr-util, so ideally any toolkit specific fix should
go in there.

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?

Is it possible to post a diff of the code that made it work for you?

Attached is the rough patch for  what it took to get the following
kind of config to work when linked against the 2.4.3 (alpha) openldap.
 not ready for prime-time but for discussion purposes only (comments
below)

(when using older/current openldap I think httpd has to refuse
LDAPTrustedClientCert altogether and require users code
LDAPTrustedGlobalCert exclusively)

...
LDAPTrustedGlobalCert CA_BASE64 /home/covener/CA.crt
LDAPTrustedGlobalCert CERT_BASE64 /home/covener/globalcert.pem
LDAPTrustedGlobalCert KEY_BASE64 /home/covener/globalcert.key

<VirtualHost *:80>
<Location /useothercert>
LDAPUrl ...
LDAPTrustedClientCert CERT_BASE64 /home/covener/othercert.pem
LDAPTrsutedClientKey  KEY_BASE64 /home/covener/othercert.key
</Location>
</VirtualHost>

The repeating of the apr_ldap_opt_set(global_certs) is due to  the
"new" openssl CTX no longer having the stuff we pushed into the global
environment.  No idea if this is harmless for other SDKs but I
couldn't figure out a way to push that aspect down into apr-util.

I will test w/ the mozilla SDK sometime to see how things work out
using the prescribed CERT_NICKNAME in LDAPTrustedClientCert which
might give me a better idea of how to isolate the per-directory client
certs SDK-dependent behavior.

--
Eric Covener
[EMAIL PROTECTED]
Index: modules/ldap/util_ldap.c
===================================================================
--- modules/ldap/util_ldap.c	(revision 469462)
+++ modules/ldap/util_ldap.c	(working copy)
@@ -268,7 +268,18 @@
 
         /* set client certificates */
         if (!apr_is_empty_array(ldc->client_certs)) {
+            /* Add any global settings to this ldap connection, otherwise global CA won't be available */
             apr_ldap_set_option(ldc->pool, ldc->ldap, APR_LDAP_OPT_TLS_CERT,
+                                st->global_certs, &(result));
+            if (LDAP_SUCCESS != result->rc) {
+                ldap_unbind_s(ldc->ldap);
+                ldc->ldap = NULL;
+                ldc->bound = 0;
+                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) {
                 ldap_unbind_s(ldc->ldap);
@@ -402,9 +413,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;
         }
     }
 
@@ -434,8 +448,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);
@@ -458,7 +473,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;
         }
@@ -483,7 +498,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;
@@ -537,7 +552,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,
@@ -1595,6 +1610,8 @@
     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;
@@ -1634,7 +1651,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;
@@ -1751,6 +1768,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 =
@@ -1772,7 +1796,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;
@@ -1806,8 +1829,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;
 
@@ -1877,6 +1898,12 @@
 #endif
         return OK;
     }
+#if AP_DEBUG
+{    
+    int LDAP_DEBUG_LEVEL = -1;
+    ldap_set_option(NULL , LDAP_OPT_DEBUG_LEVEL, &(LDAP_DEBUG_LEVEL));
+}
+#endif
 
 #if APR_HAS_SHARED_MEMORY
     /* initializing cache if shared memory size is not zero and we already
@@ -2050,7 +2077,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 "
@@ -2097,7 +2124,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: include/util_ldap.h
===================================================================
--- include/util_ldap.h	(revision 469462)
+++ include/util_ldap.h	(working copy)
@@ -105,6 +105,10 @@
     struct util_ldap_connection_t *next;
 } util_ldap_connection_t;
 
+typedef struct util_ldap_config_t { 
+    apr_array_header_t *client_certs;   /* Client certificates on this connection */
+} util_ldap_config_t;
+
 /* LDAP cache state information */ 
 typedef struct util_ldap_state_t {
     apr_pool_t *pool;           /* pool from which this state is allocated */

Reply via email to