Open LDAP configuration

ldap startup script

The ldap startup script is included in the Open LDAP RPM. If you compiled Open LDAP you will need to create your own and add the symbolic links to your run levels. The Open LDAP RPM startup script for Red Hat (which uses the Red Hat initscripts functions) follows:

Example 4-2. Open LDAP RPM Startup Script for Red Hat Linux

    #!/bin/sh
    #
    # ldap  This shell script takes care of starting and stopping
    #       ldap servers (slapd and slurpd).
    #
    # chkconfig: - 70 40
    # description: LDAP stands for Lightweight Directory Access Protocol, used \
    #              for implementing the industry standard directory services.
    # processname: slapd
    # config: /etc/openldap/slapd.conf
    # pidfile: /var/run/slapd.pid

    # Source function library.
    . /etc/rc.d/init.d/functions

    # Source networking configuration.
    . /etc/sysconfig/network

    # Check that networking is up.

    [ ${NETWORKING} = "no" ] && exit 0

    [ -f /usr/sbin/slapd ] || exit 0

    [ -f /usr/sbin/slurpd ] || exit 0
    RETVAL=0
    # See how we were called.
    case "$1" in
        start)
            # Start daemons.
            echo -n "Starting ldap: "
            daemon slapd
            RETVAL=$?
            if [ $RETVAL -eq 0 ]; then
                if grep -q "^replogfile" /etc/openldap/slapd.conf; then
                    daemon slurpd
                    RETVAL=$?
                    [ $RETVAL -eq 0 ] && pidof slurpd | cut -f 1 -d " " > /var/run/slurpd
                fi
            fi
            echo
            [ $RETVAL -eq 0 ] && touch /var/lock/subsys/ldap
            ;;
        stop)
            # Stop daemons.
            echo -n "Shutting down ldap: "
            killproc slapd
            RETVAL=$?
            if [ $RETVAL -eq 0 ]; then
                if grep -q "^replogfile" /etc/openldap/slapd.conf; then
                    killproc slurpd
                    RETVAL=$?
                fi
            fi
            echo
            if [ $RETVAL -eq 0 ]; then
                rm -f /var/lock/subsys/ldap
                rm -f /var/run/slapd.args
            fi
            ;;
        status)
            status slapd
            RETVAL=$?
            if [ $RETVAL -eq 0 ]; then
                if grep -q "^replogfile" /etc/openldap/slapd.conf; then
                    status slurpd
                    RETVAL=$?
                fi
            fi
            ;;
        restart)
            $0 stop
            $0 start
            RETVAL=$?
            ;;
        reload)
            killproc -HUP slapd
            RETVAL=$?
            if [ $RETVAL -eq 0 ]; then
                if grep -q "^replogfile" /etc/openldap/slapd.conf; then
                    killproc -HUP slurpd
                    RETVAL=$?
                fi
            fi
            ;;
        *)
            echo "Usage: $0 start|stop|restart|status}"
            exit 1
    esac

    exit $RETVAL

If you use this file with a version of OpenLDAP that you compiled yourself, you will need to change the paths of the executable and config files to reflect your installation. Next you will need to add run level links to this file. I startup the OpenLDAP server in runlevels 2,3,4 and 5 and kill it in run levels 0,1 and 6. Use the following commands from /etc/rc.d/init.d to create the appropriate symbolic links:

Example 4-3. Create The Proper Symlinks

    ln -s ldap /etc/rc.d/rc0.d/K31ldap
    ln -s ldap /etc/rc.d/rc1.d/K31ldap
    ln -s ldap /etc/rc.d/rc2.d/S79ldap
    ln -s ldap /etc/rc.d/rc3.d/S79ldap
    ln -s ldap /etc/rc.d/rc4.d/S79ldap
    ln -s ldap /etc/rc.d/rc5.d/S79ldap
    ln -s ldap /etc/rc.d/rc6.d/K31ldap

This will start ldap before sendmail and kill it after sendmail so that any unprocessed mail can get through before the LDAP server goes down.

slapd.conf

You will need to make the following changes to the Open LDAP configuration file. This is where some of the LDAP learning curve starts to hit, so pay attention. The slapd.conf file will be located in /usr/local/etc/openldap/ if you compiled OpenLDAP with defaults or /etc/openldap if you used the RPM. The modified file should look like the following example minus the notes. Paths should be changed depending on your LDAP installation.

Note: Replace all data inside <> (including <>) to reflect your information.

Example 4-4. Listing of slapd.conf


    #
    # See slapd.conf(5) for details on configuration options.
    # This file should NOT be world readable.
    #
    include         /usr/local/etc/openldap/slapd.at.conf
    include         /usr/local/etc/openldap/slapd.oc.conf
    schemacheck     off
    #referral       ldap://ldap.itd.umich.edu

    pidfile         /usr/local/var/slapd.pid
    argsfile        /usr/local/var/slapd.args


    #######################################################################
    # ldbm database definitions

    #######################################################################

    database        ldbm

    Note: The suffix is the called the Base DN by most LDAP utilities.
    It is the root of the LDAP tree, all data branches from the Base
    DN.  Two of the most common Base DN's are the domain name and the
    organization name plus the country code.  You may choose whichever
    you like, but all subsequent entries must reflect your choice.

    #suffix         "dc=<your domain name>, dc=<your domain extension ie com, net, org>"
    suffix          "o=<your organization name>, c=<your country code ie US>"
    directory       /usr/tmp

    Note: The rootdn is the default ldap user created when the server
    starts and is not in the database itself.  This is the user that
    you will use to manage the LDAP database and is commonly called
    the Bind DN by many tools and utilities.  The rootpw is also known
    as the Bind Password.  This file should be protected, due to the
    fact that control of your LDAP database lies in these two lines.
    You may encrypt this entry, see the man page for slapd.conf.

    #rootdn         "cn=root, dc=<your domain name>, dc=<your domain extension>"
    rootdn          "cn=root, o=<your organization name>, c=<your country code>"
    rootpw          secret
    # cleartext passwords, especially for the rootdn, should
    # be avoided.  See slapd.conf(5) for details.

    Note: The following are Access Control Lists that I have on my
    LDAP server, these were modified from example ACLs on the OpenLDAP
    Faq-O-Matic.  I have an Administrators group created and I limit
    access to passwords for user entries.  Keep in mind that you may
    need to add this section after you have added the initial entries
    into the LDAP server.  These ACLs may generate errors on startup
    if the entries they protect are not in the LDAP database.

    index default pres,eq,approx,sub,none
    lastmod on

    defaultaccess read
    access to dn="cn=Administrators,o=<your organization name>,c=<your country code>"
      by dnattr=member selfwrite
      by * none
    access to dn="*,o=<your organization name>,c=<your country code>"
      by self write 
      by dn="cn=root,o=<your organization name>,c=<your country code>" write
      by * read
    access to attr=userPassword 
      by self write 
      by dn="cn=root,o=<your organization name>,c=<your country code>" write
      by * compare

Initial LDIF File and ldapadd

Next we will add some initial entries to the LDAP server. I suggest creating an LDIF file and loading the contents into the database using the ldapadd utility. This is the content of my initial LDIF file. If you have suggestions for additional fields and classes in order to help with compatibility with various LDAP clients such as MS Outlook or Netscape Navigator, please let me know. This is a bit minimal and since the scope of this document is to replace an MS Exchange server, we would like to make our LDAP entries as feature rich as possible. Remember to replace all information inside <> with your own. Multiple entries of same type within a dn (distinguished name) will simply return multiple results. You may use multiple entries to not options such as a state abbreviation and a state spelled out for the `st' field.

Example 4-5. LDIF File

    dn: o=<your organization name>, c=<your country code>
    dc: <your domain name>
    dc: <your domain extension>
    o: <your organization name>
    l: <your city>
    st: <your state or province mail abbreviation>
    st: <your state or province, spelled out>
    postalcode: <in the US, your zip code>
    postofficebox: <your street address>
    c: <your country code>
    telephonenumber: <organization phone number>
    objectclass: top
    objectclass: organization

    Note: This is a group of names that I use for ACLs and other various management tasks
    dn: cn=Administrators, o=<your organization name>, c=<your country code>
    cn: Administrators
    objectclass: groupofNames
    objectclass: top
    member: cn=<First User>, o=<your organization name>, c=<your country code>
    member: cn=<Second User>, o=<your organization name>, c=<your country code>

    dn: cn=<First User>, o=<your organization name>, c=<your country code>
    cn: <First User>
    sn: <User>
    givenname: <First>
    objectclass: person
    objectclass: uid
    objectclass: organizationalPerson
    objectclass: top
    locality: <city>
    st: <state or province>
    mail: <email address>
    title: <title>
    postofficebox: <street address>
    postalcode: <zip code>
    countryname: <your country code>
    telephonenumber: <your phone number>
    o: <your organization name>
    xmozillanickname: <First>
    xmozillausehtmlmail: TRUE
    pagerphone: <pager number>
    uid: <User id, this is the username that is used in the email address>

    dn: cn=<Second User>, o=<your organization name>, c=<your country code>
    cn: <Second User>
    sn: <User>
    givenname: <Second>
    objectclass: person
    objectclass: uid
    objectclass: organizationalPerson
    objectclass: top
    locality: <city>
    st: <state or province>
    mail: <email address>
    title: <title>
    postofficebox: <street address>
    postalcode: <zip code>
    countryname: <your country code>
    telephonenumber: <your phone number>
    o: <your organization name>
    xmozillanickname: <Second>
    xmozillausehtmlmail: TRUE
    pagerphone: <pager number>
    uid: <User id, this is the username that is used in the email address>

Once this has been written to a file <yourldiffile>.ldif you may import it using the the ldapadd utility. First make sure your LDAP server has been started. If you receive errors about the ACLs, comment them out and restart the LDAP server. Next change directories to the directory containing the ldap file you just created and run the ldapadd utility. You will give the -D argument with the Bind DN or rootdn in quotes, the -W argument and then stream the <yourldiffile>.ldif into the ldapadd utility.

ldapadd -D “cn=root,o=<your organization name>,c=<your country code>” -W < <yourldiffile>.ldif

You will be prompted for the rootpw (Bind Password). Enter the password and the utility should dump you to a command prompt if no errors are encountered. You may want to look over the man page for ldapadd.

ldappasswd: Setting user passwords

Use the ldappasswd utility to set user passwords. For the two entries we just added, to give them passwords, we will type the following:

ldappasswd -D “cn=root,o=<your organization name>,c=<your country code>” -w <rootpw> -t “cn=<First User>,o=<your organization name>,c=<your country code>”

This will prompt us for a new password, which will be stored in the LDAP database as a UNIX crypt password. There are other options for encryption, but they may require modification to the cyrus server configuration. This is also the reason we use ACLs on the userPassword entry, there are other safeguards built into OpenLDAP, please read the documentation on their website and the man pages. If you find a more secure way to set this up, please let me know so that we can add it in here.

ldappasswd -D “cn=root,o=<your organization name>,c=<your country code>” -w <rootpw> -t “cn=<Second User>,o=<your organization name>,c=<your country code>”

Again you will be prompted for the new password. Also, you should notice the -t argument, this is the target dn. In other words, this is the dn that we are changing the password for.