Hi,

the attached patch adds a second option for non-anonymous binds to the
authnz_ldap module. Please consider it for adoption.

The current situation:
The authnz_ldap module supports only one kind of non-anonymous bind to the ldap
server: by specifying the username ("binddn") and password ("bindpw") in an
apache config file. This is obviously not a very pretty thing, since you need
to take good care for file permissions (as an admin) and also users may feel a
little bit uncomfortable to put their plaintext login data into an htaccess
file.


Use cases where anonymous binds don't work:

1) The most common use case for non-anonymous binds is an Active Directory
server, that (by default) does not accept anonymous binds. Usually this is
solved by creating a specific ldap user with limited read access and putting
its credentials into the apache config file. See examples:
http://www.held-im-ruhestand.de/software/apache-ldap-active-directory-authentication
http://www.jejik.com/articles/2007/06/apache_and_subversion_authentication_with_microsoft_active_directory/

2) My specific use case are some servers, that provide various services (mail,
webspace, wikis, svn, ...) to different people. All accounts are managed in a
single LDAP database. Since privacy is important for our users, it is not
acceptable, that they can get a complete user list from the ldap server. Thus
the servers, that offer shell access or webspace to users may not bind to the
LDAP server anonymously and even authenticated users may only access their own
accounts within the ldap database.
In this setup we can't use the authnz_ldap module, since we need
authenticated binds, but we don't want our users to store their precious
credentials in a plain text file.

One way of solving this issue is already implemented in Muquit's "mod_auth_ldap"
(http://www.muquit.com/muquit/software/mod_auth_ldap/mod_auth_ldap_apache2.html).
There the respective option is called "AuthOnBind".

The patch, that I attached (not based on Muquit's code), allows the following:
 - a user tries to log into an apache-served location, that requires
   authentication
 - the given credentials (username and password) are combined with the "basedn"
   and "attrib" value (defined in "AuthLDAPUrl")
 - the authnz_ldap module uses these credentials to bind to the server
   (for authentication and authorization)

The above behaviour is triggered by a new configuration directive, that I named
"AuthLDAPAuthOnBind". It defaults to "off", thus nothing changes for current
configurations.
This new behaviour covers the two use cases described above (even though I did
not check it in an Active Directory setup).

The patch is currently in use in our setup (see use case (2) above) and it runs
without problems.

Regarding the code quality:
I am not used to the apache codebase, thus I am not sure, if I used the string
functions in the proper way (around line 387). Please comment, if I overlooked
something!

cheers,
Lars

PS: I just e-mailed a signed "Individual Contributor License Agreement" to
secret...@apache.org - I am not sure, if this is necessary - just to let you
know ...
Index: mod_authnz_ldap.c
===================================================================
--- mod_authnz_ldap.c	(Revision 902678)
+++ mod_authnz_ldap.c	(Arbeitskopie)
@@ -65,6 +65,7 @@
     char *bindpw;                   /* Password to bind to server (can be NULL) */
     int bind_authoritative;         /* If true, will return errors when bind fails */
 
+    int auth_on_bind;               /* If true, connection->user + basedn for initial bind  */
     int user_is_dn;                 /* If true, connection->user is DN instead of userid */
     char *remote_user_attribute;    /* If set, connection->user is this attribute instead of userid */
     int compare_dn_on_server;       /* If true, will use server to do DN compare */
@@ -327,6 +328,7 @@
     sec->maxNestingDepth = 10;
     sec->sgAttributes = apr_pcalloc(p, sizeof (char *) * GROUPATTR_MAX_ELTS + 1);
 
+    sec->auth_on_bind = 0;
     sec->user_is_dn = 0;
     sec->remote_user_attribute = NULL;
     sec->compare_dn_on_server = 0;
@@ -384,6 +386,11 @@
         return AUTH_GENERAL_ERROR;
     }
 
+    if (sec->auth_on_bind) {
+        sec->binddn = apr_psprintf(r->pool, "%s=%s,%s", sec->attribute, user, sec->basedn);
+        sec->bindpw = apr_pstrdup(r->pool, password);
+    }
+
 start_over:
 
     /* There is a good AuthLDAPURL, right? */
@@ -1501,6 +1508,13 @@
                     "A list of attribute labels used to identify the user members of groups - defaults to "
                     "member and uniquemember"),
 
+    AP_INIT_FLAG("AuthLDAPAuthOnBind", ap_set_flag_slot,
+                 (void *)APR_OFFSETOF(authn_ldap_config_t, auth_on_bind), OR_AUTHCFG,
+                 "If set to 'on', auth_ldap uses the entered username (combined with the \"basedn\" and "
+                 "\"Attrib\" from AuthLDAPURL) and password to perform an authenticated bind to the ldap "
+                 "server (during the search/bind phase). "
+                 "AuthLDAPBindDN and AuthLDAPBindPassword are ignored."),
+
     AP_INIT_FLAG("AuthLDAPGroupAttributeIsDN", ap_set_flag_slot,
                  (void *)APR_OFFSETOF(authn_ldap_config_t, group_attrib_is_dn), OR_AUTHCFG,
                  "If set to 'on', auth_ldap uses the DN that is retrieved from the server for"

Reply via email to