mod_ldap.c

LDAP-based access checking for Apache

Please note: this mod is not supported or under active development.

Written by Jeff Morrow (jmorrow@alum.mit.edu) and Lyonel VINCENT (vincent@trotek.ec-lyon.fr)

changes by Sam Alcoff (alcoff@survival.net) to compile with Apache 1.3
changes by Rick Perry (perry@ece.vill.edu): bugs fixes and code cleanups.

Other contributors:

Version history:

Based on the mod_auth_ldap.c module written by Norman RICHARDS (orb@cs.utexas.edu).


mod_ldap.c may be downloaded from SourceForge


SourceForge.net Logo


Introduction and Compilation Instructions

The goal of this module is to allow access checking through user information stored in an LDAP directory. This module works very similarly to other access checking modules. This new version is meant as a synthesis of Norman Richards's mod_auth_ldap 1.1 and Lyonel Vincent's mod_ldap 1.4, with a few extra features thrown in.

To use the module, you need to add this file to your apache src/modules/extra directory, then add the following flag to your configure directive:

    --activate-module=src/modules/extra/mod_ldap.o

You will also need to add the appropriate locations for your ldap/lber libraries and includes to EXTRA_LIBS and EXTRA_INCLUDES in Apache's Makefile(s).

Note: Jeremy McLeod reports that using LIBS1 rather than EXTRA_LIBS may be the only way to get this part to work. "Your milage may vary". (6/2/00)


Configuration Directives

The following directives can be used in your access.conf file in the same way as you would configure the standard authentication modules.

LDAPAuth <flag>Controls whether LDAP authentication is on or off for the given scope.
LDAPServer <LDAP URL> This sets the LDAP server to be used. The ldap url is of the form "ldap://yourhost.com:portnumber/"
LDAPBindName <Distinguished Name>
LDAPBindPass <password>
If the module needs to authenticate itself, enter the user name and password here.
LDAPBase <Base DN> Specifies the base DN for all LDAP searches.
LDAPuseridAttr <attribute name>
LDAPpasswordAttr <attribute name>
Specifies the attribute names that should be compared with the supplied username and password, respectively.
NOTE: if your LDAP server contains encrypted passwords, this module will only work if the LDAPpasswordAttr config line is omitted.
Default for LDAPuseridAttr is "userid".
LDAPgroupMemberAttr <attribute name> Specifies the attribute name that your LDAP server uses to store the individual members of a group. Default is "uniquemember", which is used by Netscape's Directory Server.
LDAPSearchMode <mode> Specifies the scope to be used for LDAP searches. Can be "base", "onelevel" (default), or "subtree". Mode "compare", equivalent to "base", is allowed for backward compatibility. See LDAP documentation for more info.
LDAPUseDNForRemoteUser <flag> Defaults to "off". If set to "on", this module will reset the identity of the remote user from the username provided by the user to the user's full distinguished name.

The require directives are as follows:

require filter <LDAP search filter> The search filter is in LDAP standard format as specified by RFC1960.
require valid-user Allows any valid LDAP user.
require user <user DN or username> Allows the specified user. May take a DN in the form of "uid=jeffm,o=www.kie.berkeley.edu" or a base username like "jeffm".
require group <group DN> Allows access to anyone in the given group. The group members must be defined in the attribute specified by the LDAPgroupMemberAttr field. Note that the group name must be a full DN.


Tutorial:

Many thanks to Richard Ford (rford@hway.net) for providing this great tutorial!

Configuration of Apache to work with mod_ldap is very straightforward. Things work a lot like the standard Apache. Within your httpd.conf, a typical configuration block might look like this:

<Location /secret>
	AuthType Basic
	AuthName MyAuth
	LDAPAuth On
	LDAPServer "ldap://localhost:389/"
	LDAPBindName cn=apache,dc=myserver
	LDAPBindPass mypassword
	LDAPuseridAttr uid
	LDAPpasswordAttr userpassword
	LDAPBase dc=myserver
	require valid-user
</Location>
Going line by line, this config limits the directions to the location /secret. The AuthType and AuthName tell Apache that it can allow ap_get_basic_auth_pw to return the user's password; that is, they turn on simple authentication. Nothing new so far!

The interesting parts of the config are those lines which begin with the letters LDAP. The initial LDAPAuth turns on LDAP authentication for this location. The server to use is given by LDAPServer; the user to bind with is given in LDAPBindName and LDAPBindPass. Make sure you don't use quote marks around either of these fields! Finally, you must specify the base from which to conduct searches - in this case it is 'dc=myserver'.

In the example given above we have customised LDAPuseridAttr and LDAPpasswordAttr. These directives tell mod_ldap which field to search on within the LDAP directory, as well as which field contains the password. Finally, we apply a require which defines what type of match constitutes authorization. In this case, it simply requires any valid user and password combination in the LDAP directory.

It is also possible to configure access through .htaccess files. Consider the following example:

	AuthType Basic
	AuthName MyAuth
	LDAPAuth On
	LDAPServer "ldap://localhost:389/"
	LDAPBindName cn=apache,dc=myserver
	LDAPBindPass mypassword
	LDAPuseridAttr uid
	LDAPpasswordAttr userpassword
	LDAPBase dc=myserver
	<Limit GET POST>
	require valid-user
	</Limit>
The only trick here is to remember to turn on .htaccess checking in Apache, by setting AllowOverride AuthConfig.


Other Examples:

LDAPServer ldap://x500.hp.com/
require filter (|(&(ou=ENSD)(l=Grenoble))(ou=HP Labs))
require user "cn=Jeff Morrow,o=www.kie.berkeley.edu"
require user "Jeff Morrow"
require group "cn=teachers,o=www.kie.berkeley.edu"

Comparison to Other Apache LDAP Modules

This is the sixth Apache LDAP module to be registered on modules.apache.org. As such, I feel it is necessary to differentiate mine from the other five as objectively as possible. So here goes.

Norman Richards's original mod_auth_ldap and Lyonel Vincent's mod_ldap are what I built my code around. This module, in fact, began its life as my attempt to stitch the two versions together, since I needed functionality from each that the other did not have. This module contains the functionality of both Richards's and Vincent's modules, with a little extra thrown in. (Namely, the LDAPgroupMemberAttr, LDAPSearchMode, and LDAPUseDNForRemoteUser directives.) Neither Richards's nor Vincent's module is being actively supported.

I don't know much about Alexander Mayrhofer's LDAP module except that it contains the directives AuthLDAPAuthoritative (which my module does not have) and it allows for querying multiple LDAP servers. It does not allow the LDAPUseDNForRemoteUser directive (or any equivalent) or the "require filter" directive.

Dave Carrigan's LDAP module has some very useful features in version 1.3. It supports secure LDAP and caches search results for better performance. It also supports the AuthLDAPAuthoritative directive. The AuthLDAPURL directive allows for great flexibility of searches, but can be a bit user-unfriendly. (That's my opinion, of course.) My module can also accept such URL's, but the "require filter" directive allows much of the same functionality, while making the config files a bit easier on the eyes by separating out the LDAP url into several discreet components. Carrigan's module also assumes that members of an LDAP group are defined by either the "member" or "uniquemember" attributes of that group. It also does not allow search mode "compare" (ie, base).

Piet Ruyssinck's module contains similar functionality to mine, but makes the assumption that your LDAP schema is set up in such a way to allow each user to only be a member of ONE group. It also assumes that your LDAP schema contains fields for such items as userPasswordSalt, account, accountDisabled, and expirationDate. It does not allow the LDAPUseDNForRemoteUser directive (or any equivalent) or the "require filter" directive.

Let me stress that I mean no disrespect to the efforts of any of these people. If there are errors in the above analysis, please point them out and I will be happy to correct them.