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 />
<Location /ldap-status><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 />