Background LDAP is a client-server protocol for accessing a directory service. LDAP server can be used as a central point for user authentication over the network. LDAP is the industry standard for
directory access and embraced by companies such as IBM, Netscape, Novell, Microsoft etc.
This module can be used for http basic authentication using the user data stored in a Lightweight Directory Access Protocol (LDAP)
server. I wrote it in September of 1998. I think the module is simple and clean! I'd like to know what you think though.
Before compiling the module, you need to compile and install LDAP libraries. Above all, you must have a
working LDAP server. You can use Netscape Directory server or free Open LDAP server. I found Netscape LDAP server is significantly faster and robust, however OpenLDAP server is getting better everyday. Netscape directory server SDK
can be used with Open LDAP server and vice versa (netscape SDK has few extra functions).
Download If you're on Linux/Unix, you must download the source. If you're on MS NT/2000, you can download and use the supplied dll.
* Download (v 2.4.1) source: mod_auth_ldap.tar.gz (20644 bytes) (md5=5c78fc7e99b285c13de4821c54358bb2) (Last updated: Sep-24-2002)
* Download (v
2.4.1) DLL for MS NT/2000: mod_auth_ldap_dll.zip (94970 bytes) (md5=99bf6c73cb61ef997e311e986dc89192) (Last updated: Sep-24-2002)
(Compiled with Apache 1.3.26 on Windows 2000 with iPlanet C SDK 5.08)
Steps to compile and install
1. (All platforms) Install/configure a LDAP server. Choices:
- Netscape Directory server (very easy) or - Open LDAP server (not hard if you read instructions)
- Microsoft Active Directory in Win 2000. - Novell NDS with LDAP gateway. Any LDAP server should work though.
2. (Linux/Unix) Install a LDAP C SDK. Choices: - If you installed Open LDAP server, you already have it. - The other choice is Netscape Directory C SDK
If you already have Apache compiled with Dynamic Shared Object (DSO) support, please skip the next section and go to the section Compiling as Dynamic Shared Object.
3. Compiling in with apache (Linux/Unix) * Download Apache from: http://www.apache.org/httpd.html
* Extract apache (as of today the current version is 1.3.26) $ gunzip < apache_1.3.26.tar.gz | tar xvf -
Apache will be extracted in the directory apache_1.3.26.
* Extract Auth module
$ gunzip < mod_auth_ldap.tar.gz | tar xvf - Auth module will be extracted in the directory
modauthldap. Look at the file modauthldap/mod_auth_ldap.c. By default, debugging for the module is OFF. If you are installing the module for the very first time, it's a good idea to turn the debugging on. You can turn on debugging
by un-commenting the line
#define DEBUG_LDAP 1
If you compile with debugging on,
watch the apache error_log file. Do not forget to comment it out and recompile, re-install apache, when you're sure that the module works or you server error log will have lots of messages.
* At the shell prompt, type: $ cd apache_1.3.26
$ mv ../modauthldap ./src/modules/ldap
$ ./configure --activate-module=src/modules/ldap/mod_auth_ldap.c $ make
$ make install
4. Compiling as Dynamic Shared Object (Linux/Unix) To use this method, you must have apache
compiled and installed with DSO support. Stock RedHat Linux comes with Apache compiled with DSO support.
* Extract Auth module
$ gunzip < mod_auth_ldap.tar.gz | tar xvf -
* Find out where the program apxs is installed. I
assume it is in /usr/local/apache/bin. At the shell prompt type: $ cd modauthldap
$ /usr/local/apache/bin/apxs -I/usr/local/include \
-L/usr/local/lib -lldap -llber -i -a -c mod_auth_ldap.c
In Solaris, you may not need -llber.
If you installed your LDAP headers and libraries
elsewhere, edit -I/usr/local/include and -L/usr/local/lib and specify the correct paths. apxs will compile, copy the module to the correct place and modify httpd.conf file for you.
5. Compiling as DLL in Windows MS NT/2000 You do not need to compile the module in MS NT or 2000. An already compiled DLL is supplied. Howerver, if you need to coimpile it for some
reason, you'll need MS Visual C++ (I used MS Visual C++ 6.0) which is NOT free. Download the source, extract it inside src/modules directory of Apache source.. Open a command shell and type:
cd mod_auth_ldap nmake -f makefile.wnt
The DLL modu_auth_ldap.dll will be created.
6. Install compiled/supplied DLL in Windows MS NT/2000 Download and extract the zip file containing the module (unless you compiled the DLL yourself). The supplied zip file has the
following files:
mod_auth_ldap_dll/ mod_auth_ldap_dll/mod_auth_ldap.dll - non debug version mod_auth_ldap_dll/mod_auth_ldap.dll.debug - debug version
mod_auth_ldap_dll/README
The debug version of the module writes debug messages in the server error_log file. So you should use this module first, when you're sure that the module works
properly, replace it with the non debug version.
Copy the debug version of the module in the Apache modules directory first, e.g.
copy mod_auth_ldap.dll.debug c:/Apache/modules/mod_auth_ldap.dll
Modify the file httpd.conf and put the following lines:
LoadModule ldap_auth_module modules/mod_auth_ldap.dll
Then put the following line under the line ClearModuleList
AddModule mod_auth_ldap.c
Note:
When you're sure that the module works properly, replace the installed module with the non debug version or error_log file will have lots of debug messages.
7. Read the INSTALL file comes with apache to configure and start apache.
8. Now I assume you finished installing and testing Apache. It's time to make use of the LDAP authentication module. If you
want to protect a directory say foo in the server's document root, put a section like below in the httpd.conf file:
<Directory "/usr/local/apache/htdocs/foo">
#<Directory "C:/Apache/htdocs/foo"> Options Indexes FollowSymLinks AllowOverride None
order allow,deny allow from all AuthName "RCS Staff only" AuthType Basic
LDAP_Server ldap.fccc.edu LDAP_Port 389 Base_DN "o=Fox Chase Cancer Center,c=US"
#Bind_DN "uid=admin,o=Fox Chase Cancer Center,c=US" #Bind_Pass "secret" UID_Attr uid
#require valid-user require user muquit foo bar "john doe" #require roomnumber "123 Center Building"
#require filter "(&(telephonenumber=1234)(roomnumber=123))" #require group cn=rcs,ou=Groups </Directory>
DO NOT forget to edit the above section. Make sure you change the LDAP_Server to your one, change the Base_DN and require attribute as well.
Note, you can use
<Location "/foo"> instead of <Directory "/usr/local/apache/htdocs/foo"> I prefer to use Directory, because I don't have to wonder around to find out what the real directory is.
Or create a file .htaccess with the following contents in the directory you want to protect:
AuthName "RCS Staff only"
AuthType Basic LDAP_Server ldap.fccc.edu LDAP_Port 389
Base_DN "o=Fox Chase Cancer Center,c=US" UID_Attr uid #require valid-user
require user muquit foo bar "john doe" #require roomnumber "123 Center Building"
#require filter "(&(telephonenumber=1234)(roomnumber=123))" #require group cn=rcs,ou=Groups
Note: In order to make
.htaccess work, make sure you allow it with AllowOverride option. By default it is OFF.
9. Stop and start apache (Linux/Unix): /usr/local/apache/bin/apachectl stop
/usr/local/apache/bin/apachectl start
MS NT/2000 users, please follow the Apache doc on how to start/stop the server. If you installed apache as service, you can
stop/start from command line as:
If there is no syntax error in apache configuration file/s, (or if the module loaded successfully in NT/2000) server will start withoug any error in error_log
file. net stop "Apache" net start "Apache"
Environment variables At this time the following environ variables are set if the
authentication is successful which can be checked from CGI program etc:
LDAP_USER MOD_AUTH_LDAP_VERSION
If you need any other env var to be set, please let me know.
Explanation of the directives
AuthLDAPAuthoritative Setting this directive to 'no' (by default it is 'yes') allows for both authentication and authorization to be passed on to lower level modules ( as defined in the
Configuration and modules.c file if there is no userID or rule matching the supplied userID. For example, if you want to protect a directory by authentication using text files, set this directive to no for this directory (in this
case use a userid in the text file which does not exist in the LDAP server). LDAP_Server The hostname of your LDAP server, e.g. ldap.foo.com. If this directive is not defined in the config file for a directory, then the control
will be given back so that you can authenticate with other mechanism. LDAP_Port The port on LDAP server. The default and standard port number for LDAP is 389. Base_DN The LDAP Base Distinguished Name (DN) for search.
Bind_DN If your LDAP server does not allow anonymous binding (e.g. MS Windows 2000 Active Directory), specify the full Distinguised Name (DN) to bind to the server. Bind_Pass The bind password (in plain text). UID_Attr The
attribute to use in LDAP search. The default LDAP attribute is uid. To explain it little more, the name you enter in the browser's authentication dialog, this can be any attribute, for example, givenname, surname, cn etc. To use
uid is the best as it is normally a unique attribute for each person. The authentication will fail if multiple matches are found. require You MUST have this directive. There are four forms of this directive, you'll only use one
of them and comment out the other three.
# If you specify valid-user, then any valid user with correct password is allowed.
# You can also specify a space separated list of user ids with require user directive to
allow those users only. If a id has space in it, put double or single quote around the name.
# Or with require filter option, a valid LDAP filter can be specified in order to authenticate the use on arbitrary condition.
# Or you can only allow users who have certain attribute, for example you might allow all the users whose roomnumber is say 123 or all users with telephonenumber 1234 etc.
# The require group attribute is followed by the
partial Distinguished name (DN), the base DN will be appended, So do not add base DN with this attribute.
** The directive require group only works with netscape LDAP server schema and object class out of the box. You can
use this directive to allow all the users belong to a certain group. ** However require group should work with Open LDAP server too provided you use similar object class and schema as netscape LDAP server. Here's an LDIF snippet
of group in netscape LDAP server:
dn: cn=rcs,ou=Groups,o=Fox Chase Cancer Center,c=US objectclass: top objectclass: groupOfUniqueNames cn: rcs description: Research Computing Services Staff
creatorsname: uid=admin,o=Fox Chase Cancer Center,c=US uniquemember: uid=muquit,ou=People,o=Fox Chase Cancer Center,c=US uniquemember: uid=foo,ou=People,o=Fox Chase Cancer Center,c=US
Web publishing You can use this
module for authentication with netscape communicator (or other browsers which supports HTTP PUT method) to publish (File->Publish... menu) web pages. But you need to compile apache with mod_put module first. Now lets say, you
want to publish in the directory publish at the server document root, put a section like below in the httpd.conf file:
<Directory "/usr/local/apache/htdocs/publish"> EnablePut On
Options Indexes FollowSymLinks AllowOverride None order allow,deny allow from all AuthName "Web publishing" AuthType Basic LDAP_Server ldap.fccc.edu LDAP_Port 389
Base_DN "o=Fox Chase Cancer Center,c=US" UID_Attr uid <Limit PUT> #require valid-user require user muquit foo bar doe #require roomnumber "123 Center Building"
#require filter "(&(telephonenumber=1234)(roomnumber=123))" #require group cn=rcs,ou=groups </Limit> </Directory> Remember, Apache server writes as the user specified with the directive User in
the httpd.conf file. So make sure that user has write permission to the directory where you're publishing. Also if there are any existing files in the directory, make sure they are writable by that user too.
Passing control to lower-level modules If you're not familiar with Apache, you might be wondering what it means by passing authentication and authorization to lower level modules. If apache is compiled with this module, it will
try to authenticate user/group all from LDAP server. But some times you might want to authenticate access to a directory by other means e.g. by a file or database. If you want to do so, you've to use the directive
AuthLDAPAuthoritative no first and then use the usual means to specify the alternative authentication mechanism. Here're we'll show an example using .htaccess file in some directory:
AuthName "File_based Auth"
AuthType Basic AuthLDAPAuthoritative no LDAP_Server ldap.fccc.edu LDAP_Port 389 Base_DN "o=Fox Chase Cancer Center,c=US" UID_Attr uid require user muquit foo bar doe
AuthUserFile /usr/local/apache/.htpasswd
The file /usr/local/apache/.htpasswd contains userid:crypted_password in each line, for example:
muquit:12o7559gAGYWY foo:1dfd87efYYWpo
Make sure the file .htpasswd
is not accessible via a web browser. Now, if the user muquit does not exist in the LDAP server or authentication failed in LDAP then the module will use the userid and password from .htpasswd file to authenticate the user.
Similarly group authentication can be passed to lower level modules using require group and AuthGroupFile directives.
How you can help You always can help by contributing code, reporting bugs etc. I want to implement the
following things but not getting time to do so. You probably can help to do this:
* Add a filter directive in httpd.conf file. This will allow authentication on arbitrary condition.
Example:
require filter "(&(ou=foo dept)(telephonenumber=1234))"
Status: done (Apr-14-2001)
* Allow multiple ldap servers in httpd.conf file. Example:
LDAP_Server "ldap.muquit.com:389 ldap.foo.edu:489"
If you find this module useful, please let me know. Bug reports, suggestions, patches are always welcome.
Enjoy!
ChangeLog
Release 2.4.1
* Source was in DOS format. Sorry :( (Oct-08-2002) * Replaced the call free(dn) with ldap_memfree(dn). It was dying on Windows 2000 if compiled with iPlanet
C SDK 5.08. (Sep-24-2002)
* closing connection message is finally put inside DEBUG_LDAP directive. (Sep-24-2002)
Release 2.4 * Added filter option in the server config file, so that any arbitrary condition can be used on a user authentication. (Apr-14-2001)
* The directive require user can have space in ithe values. Example: require user foo "john doe" bar (Apr-14-2001)
Release 2.3 * Makefile.wnt for NT/2000 was missing. (Apr-11-2001)
* Added Bind_DN and Bind_Pass. Requested by Martin
Zardecki to use the module with Windows 2000 Active Directory (AD). Thanks to Martin for testing the module with Win 2000 AD. Thanks to Alexis for some tips on Win 2000 AD. (Mar-15-2001)
Release 2.2 * Sets another environment variable MOD_AUTH_LDAP_VERSION if the authentication is successfull. (Mar-15-2001)
* Compiled the DLL on Windows NT (no porting was necessary). Linked with some old version of netscape LDAP C SDK (I think 2.0). (Mar-05-2001)
* Possible memory leak plugged. result var in ldap_search_s() was not freed by calling ldap_msgfree(). (Feb-05-2001) |