Hi all,

This is a patch for httpd that adds support for ldapi:// URLs to mod_ldap and 
friends.

It depends on a patch for apr-util posted to the dev@apr list.

Regards,
Graham
—


Index: include/util_ldap.h
===================================================================
--- include/util_ldap.h (revision 1909117)
+++ include/util_ldap.h (working copy)
@@ -45,6 +45,10 @@
 /* this whole thing disappears if LDAP is not enabled */
 #if APR_HAS_LDAP
 
+#ifndef APR_HAS_LDAP_INITIALIZE
+#define APR_HAS_LDAP_INITIALIZE 0
+#endif
+
 #if defined(LDAP_UNAVAILABLE) || APR_HAS_MICROSOFT_LDAPSDK
 #define AP_LDAP_IS_SERVER_DOWN(s)                ((s) == LDAP_SERVER_DOWN \
                 ||(s) == LDAP_UNAVAILABLE)
@@ -126,8 +130,8 @@
     const char *reason;                 /* Reason for an error failure */
 
     struct util_ldap_connection_t *next;
-    struct util_ldap_state_t *st;        /* The LDAP vhost config this 
connection belongs to */
-    int keep;                            /* Will this connection be kept when 
it's unlocked */
+    struct util_ldap_state_t *st;       /* The LDAP vhost config this 
connection belongs to */
+    int keep;                           /* Will this connection be kept when 
it's unlocked */
 
     int ChaseReferrals;                 /* [on|off] (default = 
AP_LDAP_CHASEREFERRALS_ON)*/
     int ReferralHopLimit;               /* # of referral hops to follow 
(default = AP_LDAP_DEFAULT_HOPLIMIT) */
@@ -136,6 +140,12 @@
     int must_rebind;                    /* The connection was last bound with 
other then binddn/bindpw */
     request_rec *r;                     /* request_rec used to find this 
util_ldap_connection_t */
     apr_time_t last_backend_conn;       /* the approximate time of the last 
backend LDAP request */
+
+#if APR_HAS_LDAP_INITIALIZE
+    apr_ldap_err_t result;              /* result of prior operations on this 
connection */
+    const char *url;                    /* URL of the LDAP server (or space 
separated list) */
+    apr_ldap_t *ld;
+#endif
 } util_ldap_connection_t;
 
 typedef struct util_ldap_config_t {
@@ -241,6 +251,7 @@
  * @fn util_ldap_connection_t *util_ldap_connection_find(request_rec *r, const 
char *host, int port,
  *                                                           const char 
*binddn, const char *bindpw, deref_options deref,
  *                                                           int netscapessl, 
int starttls)
+ * @deprecated Replaced by uldap_connection_find_ex()
  */
 APR_DECLARE_OPTIONAL_FN(util_ldap_connection_t 
*,uldap_connection_find,(request_rec *r, const char *host, int port,
                                                   const char *binddn, const 
char *bindpw, deref_options deref,
@@ -247,6 +258,26 @@
                                                   int secure));
 
 /**
+ * Find a connection in a list of connections
+ * @param r The request record
+ * @param url The URL to connect to (multiple URLs space separated)
+ * @param binddn The DN to bind with
+ * @param bindpw The password to bind with
+ * @param deref The dereferencing behavior
+ * @param secure use SSL on the connection
+ * @tip Once a connection is found and returned, a lock will be acquired to
+ *      lock that particular connection, so that another thread does not try 
and
+ *      use this connection while it is busy. Once you are finished with a 
connection,
+ *      apr_ldap_connection_close() must be called to release this connection.
+ * @fn util_ldap_connection_t *util_ldap_connection_find_ex(request_rec *r, 
const char *url,
+ *                                                           const char 
*binddn, const char *bindpw, deref_options deref,
+ *                                                           int netscapessl, 
int starttls)
+ */
+APR_DECLARE_OPTIONAL_FN(util_ldap_connection_t 
*,uldap_connection_find_ex,(request_rec *r, const char *url,
+                                                  const char *binddn, const 
char *bindpw, deref_options deref,
+                                                  int secure));
+
+/**
  * Compare two DNs for sameness
  * @param r The request record
  * @param ldc The LDAP connection being used.
Index: modules/aaa/mod_authnz_ldap.c
===================================================================
--- modules/aaa/mod_authnz_ldap.c       (revision 1909117)
+++ modules/aaa/mod_authnz_ldap.c       (working copy)
@@ -104,7 +104,7 @@
 module AP_MODULE_DECLARE_DATA authnz_ldap_module;
 
 static APR_OPTIONAL_FN_TYPE(uldap_connection_close) 
*util_ldap_connection_close;
-static APR_OPTIONAL_FN_TYPE(uldap_connection_find) *util_ldap_connection_find;
+static APR_OPTIONAL_FN_TYPE(uldap_connection_find_ex) 
*util_ldap_connection_find_ex;
 static APR_OPTIONAL_FN_TYPE(uldap_cache_comparedn) *util_ldap_cache_comparedn;
 static APR_OPTIONAL_FN_TYPE(uldap_cache_compare) *util_ldap_cache_compare;
 static APR_OPTIONAL_FN_TYPE(uldap_cache_check_subgroups) 
*util_ldap_cache_check_subgroups;
@@ -453,9 +453,7 @@
             bindpw = req->password;
     }
 
-    return util_ldap_connection_find(r, sec->host, sec->port,
-                                     binddn, bindpw,
-                                     sec->deref, sec->secure);
+    return util_ldap_connection_find_ex(r, sec->url, binddn, bindpw, 
sec->deref, sec->secure);
 }
 /*
  * Authentication Phase
@@ -527,7 +525,7 @@
     }
 
     /* There is a good AuthLDAPURL, right? */
-    if (sec->host) {
+    if (sec->url) {
         const char *binddn = sec->binddn;
         const char *bindpw = sec->bindpw;
         if (sec->initial_bind_as_user) {
@@ -535,13 +533,13 @@
             binddn = ldap_determine_binddn(r, user);
         }
 
-        ldc = util_ldap_connection_find(r, sec->host, sec->port,
-                                       binddn, bindpw,
-                                       sec->deref, sec->secure);
+        ldc = util_ldap_connection_find_ex(r, sec->url,
+                                           binddn, bindpw,
+                                           sec->deref, sec->secure);
     }
     else {
         ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, APLOGNO(01690)
-                      "auth_ldap authenticate: no sec->host - weird...?");
+                      "auth_ldap authenticate: no sec->url - weird...?");
         return AUTH_GENERAL_ERROR;
     }
 
@@ -1436,13 +1434,14 @@
  * host and port.
  */
 static const char *mod_auth_ldap_parse_url(cmd_parms *cmd,
-                                    void *config,
-                                    const char *url,
-                                    const char *mode)
+                                           void *config,
+                                           const char *url,
+                                           const char *mode)
 {
-    int rc;
+    int rc, i;
     apr_ldap_url_desc_t *urld;
     apr_ldap_err_t *result;
+    const char *end = url;
 
     authn_ldap_config_t *sec = config;
 
@@ -1450,8 +1449,18 @@
     if (rc != APR_SUCCESS) {
         return result->reason;
     }
-    sec->url = apr_pstrdup(cmd->pool, url);
 
+    /* isolate the host/port part of the URL */
+    for (i = 0; end && i < 3; i++) {
+        end = strchr((char *)end + 1, '/');
+    }
+    if (end) {
+        sec->url = apr_pstrndup(cmd->pool, url, end - url);
+    }
+    else {
+        sec->url = apr_pstrdup(cmd->pool, url);
+    }
+
     /* Set all the values, or at least some sane defaults */
     if (sec->host) {
         sec->host = apr_pstrcat(cmd->pool, urld->lud_host, " ", sec->host, 
NULL);
@@ -1528,9 +1537,10 @@
     sec->have_ldap_url = 1;
 
     ap_log_error(APLOG_MARK, APLOG_TRACE1, 0, cmd->server,
-                 "auth_ldap url parse: `%s', Host: %s, Port: %d, DN: %s, "
+                 "auth_ldap url parse: `%s', Url: %s, Host: %s, Port: %d, DN: 
%s, "
                  "attrib: %s, scope: %s, filter: %s, connection mode: %s",
                  url,
+                 sec->url,
                  urld->lud_host,
                  urld->lud_port,
                  urld->lud_dn,
@@ -1921,13 +1931,13 @@
 
 static void ImportULDAPOptFn(void)
 {
-    util_ldap_connection_close  = 
APR_RETRIEVE_OPTIONAL_FN(uldap_connection_close);
-    util_ldap_connection_find   = 
APR_RETRIEVE_OPTIONAL_FN(uldap_connection_find);
-    util_ldap_cache_comparedn   = 
APR_RETRIEVE_OPTIONAL_FN(uldap_cache_comparedn);
-    util_ldap_cache_compare     = 
APR_RETRIEVE_OPTIONAL_FN(uldap_cache_compare);
-    util_ldap_cache_checkuserid = 
APR_RETRIEVE_OPTIONAL_FN(uldap_cache_checkuserid);
-    util_ldap_cache_getuserdn   = 
APR_RETRIEVE_OPTIONAL_FN(uldap_cache_getuserdn);
-    util_ldap_ssl_supported     = 
APR_RETRIEVE_OPTIONAL_FN(uldap_ssl_supported);
+    util_ldap_connection_close      = 
APR_RETRIEVE_OPTIONAL_FN(uldap_connection_close);
+    util_ldap_connection_find_ex    = 
APR_RETRIEVE_OPTIONAL_FN(uldap_connection_find_ex);
+    util_ldap_cache_comparedn       = 
APR_RETRIEVE_OPTIONAL_FN(uldap_cache_comparedn);
+    util_ldap_cache_compare         = 
APR_RETRIEVE_OPTIONAL_FN(uldap_cache_compare);
+    util_ldap_cache_checkuserid     = 
APR_RETRIEVE_OPTIONAL_FN(uldap_cache_checkuserid);
+    util_ldap_cache_getuserdn       = 
APR_RETRIEVE_OPTIONAL_FN(uldap_cache_getuserdn);
+    util_ldap_ssl_supported         = 
APR_RETRIEVE_OPTIONAL_FN(uldap_ssl_supported);
     util_ldap_cache_check_subgroups = 
APR_RETRIEVE_OPTIONAL_FN(uldap_cache_check_subgroups);
 }
 
Index: modules/ldap/util_ldap.c
===================================================================
--- modules/ldap/util_ldap.c    (revision 1909117)
+++ modules/ldap/util_ldap.c    (working copy)
@@ -285,6 +285,25 @@
         (util_ldap_state_t *)ap_get_module_config(r->server->module_config,
         &ldap_module);
     int have_client_certs = !apr_is_empty_array(ldc->client_certs);
+
+#if APR_HAS_LDAP_INITIALIZE
+
+    apr_ldap_initialize(ldc->pool, ldc->url, &(ldc->ld), &(ldc->result));
+
+    if (ldc->ld) {
+        apr_ldap_opt_t opt;
+
+        apr_ldap_get_option_ex(ldc->ld, APR_LDAP_OPT_HANDLE, &opt, 
&(ldc->result));
+
+        ldc->ldap = opt.handle;
+    }
+
+    result = &ldc->result;
+
+#else
+
+    /* remove after apr-util v1.7 */
+
 #if !APR_HAS_SOLARIS_LDAPSDK
     /*
      * Normally we enable SSL/TLS with apr_ldap_set_option(), except
@@ -322,7 +341,9 @@
         return(APR_EGENERAL);
     }
 
-    if (result->rc) {
+#endif
+
+    if (result && result->rc) {
         ldc->reason = result->reason;
         ldc->bound = 0;
         return result->rc;
@@ -697,19 +718,12 @@
 }
 
 
-/*
- * Find an existing ldap connection struct that matches the
- * provided ldap connection parameters.
- *
- * If not found in the cache, a new ldc structure will be allocated
- * from st->pool and returned to the caller.  If found in the cache,
- * a pointer to the existing ldc structure will be returned.
- */
 static util_ldap_connection_t *
-            uldap_connection_find(request_rec *r,
-                                  const char *host, int port,
-                                  const char *binddn, const char *bindpw,
-                                  deref_options deref, int secure)
+            connection_find(request_rec *r,
+                            const char *url,
+                            const char *host, int port,
+                            const char *binddn, const char *bindpw,
+                            deref_options deref, int secure)
 {
     struct util_ldap_connection_t *l, *p; /* To traverse the linked list */
     int secureflag = secure;
@@ -737,12 +751,16 @@
 #if APR_HAS_THREADS
         if (APR_SUCCESS == apr_thread_mutex_trylock(l->lock)) {
 #endif
-        if (   (l->port == port) && (strcmp(l->host, host) == 0)
-            && ((!l->binddn && !binddn) || (l->binddn && binddn
-                                             && !strcmp(l->binddn, binddn)))
-            && ((!l->bindpw && !bindpw) || (l->bindpw && bindpw
-                                             && !strcmp(l->bindpw, bindpw)))
-            && (l->deref == deref) && (l->secure == secureflag)
+        if (   (l->port == port)
+            && ((!url && !l->url) || (url && l->url
+                                             && !strcmp(url, l->url)))
+            && ((!host && !l->host) || (host && l->host
+                                             && !strcmp(l->host, host)))
+            && ((!binddn && !l->binddn) || (binddn && l->binddn
+                                             && !strcmp(binddn, l->binddn)))
+            && ((!bindpw && !l->bindpw) || (bindpw && l->bindpw
+                                             && !strcmp(bindpw, l->bindpw)))
+            && (deref == l->deref) && (secureflag == l->secure)
             && !compare_client_certs(dc->client_certs, l->client_certs))
         {
             if (st->connection_pool_ttl > 0) {
@@ -779,9 +797,13 @@
             if (APR_SUCCESS == apr_thread_mutex_trylock(l->lock)) {
 
 #endif
-            if ((l->port == port) && (strcmp(l->host, host) == 0) &&
-                (l->deref == deref) && (l->secure == secureflag) &&
-                !compare_client_certs(dc->client_certs, l->client_certs))
+            if ((port == l->port)
+                && ((!url && !l->url) || (url && l->url
+                                             && !strcmp(url, l->url)))
+                && ((!host && !l->host) || (host && l->host
+                                             && !strcmp(host, l->host)))
+                && (deref == l->deref) && (secureflag == l->secure)
+                && !compare_client_certs(dc->client_certs, l->client_certs))
             {
                 if (st->connection_pool_ttl > 0) {
                     if (l->bound && (now - l->last_backend_conn) > 
st->connection_pool_ttl) {
@@ -849,6 +871,7 @@
         apr_thread_mutex_lock(l->lock);
 #endif
         l->bound = 0;
+        l->url = apr_pstrdup(l->pool, url);
         l->host = apr_pstrdup(l->pool, host);
         l->port = port;
         l->deref = deref;
@@ -897,6 +920,42 @@
     return l;
 }
 
+/*
+ * Find an existing ldap connection struct that matches the
+ * provided ldap connection parameters.
+ *
+ * If not found in the cache, a new ldc structure will be allocated
+ * from st->pool and returned to the caller.  If found in the cache,
+ * a pointer to the existing ldc structure will be returned.
+ *
+ * Deprecated: replaced by uldap_connection_find_ex()
+ */
+static util_ldap_connection_t *
+            uldap_connection_find(request_rec *r,
+                                  const char *host, int port,
+                                  const char *binddn, const char *bindpw,
+                                  deref_options deref, int secure)
+{
+    return connection_find(r, NULL, host, port, binddn, bindpw, deref, secure);
+}
+
+/*
+ * Find an existing ldap connection struct that matches the
+ * provided ldap connection parameters.
+ *
+ * If not found in the cache, a new ldc structure will be allocated
+ * from st->pool and returned to the caller.  If found in the cache,
+ * a pointer to the existing ldc structure will be returned.
+ */
+static util_ldap_connection_t *
+            uldap_connection_find_ex(request_rec *r,
+                                     const char *url,
+                                     const char *binddn, const char *bindpw,
+                                     deref_options deref, int secure)
+{
+    return connection_find(r, url, NULL, 0, binddn, bindpw, deref, secure);
+}
+
 /* ------------------------------------------------------------------ */
 
 /*
@@ -3216,6 +3275,7 @@
     APR_REGISTER_OPTIONAL_FN(uldap_connection_close);
     APR_REGISTER_OPTIONAL_FN(uldap_connection_unbind);
     APR_REGISTER_OPTIONAL_FN(uldap_connection_find);
+    APR_REGISTER_OPTIONAL_FN(uldap_connection_find_ex);
     APR_REGISTER_OPTIONAL_FN(uldap_cache_comparedn);
     APR_REGISTER_OPTIONAL_FN(uldap_cache_compare);
     APR_REGISTER_OPTIONAL_FN(uldap_cache_checkuserid);


Reply via email to