mod_auth_ldap
LDAP Authentication module for Apache
(For Linux/Unix, MS NT/2000)
by
Muhammad A Muquit

[mod_auth_ldap Release 2.4]

Last Updated: Apr 14, 2001

Table of Contents

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.

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)

  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.

  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
    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:

    If you find this module useful, please let me know. Bug reports, suggestions, patches are always welcome.

    Enjoy!

    ChangeLog

    (Page Last updated: Sun Apr 15 14:51:43 2001 GMT

    URL of this page:http://www.muquit.com/muquit/software/mod_auth_ldap/mod_auth_ldap.html