Consulting services
Implementing, installing and supporting open source applications in your environment email consulting

FreeBSD LDAP Guide

This document describes the process one will need to take when setting up LDAP as a means for authenticating users on a FreeBSD 5.1+ system.

This book is outlined very much like a tutorial aimed at the most novice of users (you will only require basic knowledge of the FreeBSD ports system, and an editor of your choice, the rest of the process is described by me).

This is a work in progress, and as I learn new things, I will add to this book.

In The Beginning…

Introduction

First off, you may be asking yourself, “Why would I need to do this?” Well I have two answers to that question, first, if you didn’t need it, why would you be here in the first place? But incase you are truly unknowing, it is a very handy thing to have a set of user accounts maintained in one central location to share among several machines. Traditionally this has been done with NIS/YP, but when using LDAP you can share this information amongst many different operating systems, not just those like the Unix operating systems which support NIS/YP, but Windows as well (for example).

Also please note that at this time, this guide simply lays out the procedure to set up and configure an LDAP server (OpenLDAP) for one machine. It does not deal with setting up a server, and then a client (though it can easily be abstracted) but rather, assumes they will be on the same system (not optimal). It also does not deal with replication, this is a topic that will be covered in future versions. If you wish to contribute any of the above (or possibly other sections you feel are relevant), please send them to me.

Now since that’s out of the way, let’s continue.

Requirements

You will need a few tools before you can continue, I will assume you know how to update your FreeBSD ports tree. (If you do not, please read the FreeBSD handbook.)

You will need:

FreeBSD 5.1 or higher is required due to the NSS module being imported at that time. It is not available prior to FreeBSD 5.1, and while it is possible to perform LDAP authentication on FreeBSD 4.x, the procedure is entirely different and, I will not cover that here.

Getting everything ready

Installing ports

First off, we’ll need to perform installation of some ports that we will be using on this system.

Incase you don’t know, the # symbol represents a root prompt. You can become root by using su or gain super-user privileges by using sudo. Whichever way you want to do this, is up to you.

To start off, install the OpenLDAP package. Become root, and do the following:

    # cd /usr/ports/net/openldap22-server
    # make install
    

This will cause the ports system to fetch and install all ports that depend on openldap22-server (openldap22-client being one) and install them, before building and installing openldap22-server.

Next, we need to install the nss_ldap port, to do so, execute the following two commands:

    # cd /usr/ports/net/nss_ldap
    # make install
    

Be sure to read any messages that are printed while registering the port. These messages are not there just for the maintainers amusement, they contain important information about installing software.

Next, let’s install the pam_ldap port. Again we need to execute a couple of commands:

    # cd /usr/ports/security/pam_ldap
    # make install
    

Now then, since that is all over and done with, let’s focus our attention on configuring openldap.

Configuration

Read this first.

This section will guide you through the steps you will need to take to set up various configuration files, data files for LDAP and setting up permissions.

Please note: If you do not want to set up OpenLDAP with SSL support (I recommend you do) please skip all the parts about SSL.

Generating SSL keys

This page will be brief. It will outline the simple procedure of creating a self-signed certificate for use with your shiny new LDAP server; so pay attention, this won’t take but a minute.

We need to start off by of course, becoming root.

    $ sudo -s
    

Yes I expect you should have sudo installed. If you do not, use su instead to get a root shell.

Now then, let’s get to business.

You’ll need to create a directory in /usr/local/etc/openldap called ‘ssl’ (for the sake of simplicity).

    # mkdir ssl
    

Now let’s go into that directory, and generate our keys using openssl.

    # openssl req -new > ldap.csr
    

From this point on, it (OpenSSL) is going to ask you a few questions, like a pass phrase, country, etc. Fill them out to the best of your abilities. Please note: The “Common Name” in your certificate should be the fully qualified domain name of your ldap server (that is, the output of “hostname”. Check it if you are not sure what your server’s FQDN is).

Now, we need to remove the passphrase from the key we just generated, to do this, we issue this command:

    # openssl rsa -in privkey.pem -out ldap.key
    

It is going to ask you to enter your pass phrase, do this now.

Next we want to turn this into a self-signed certificate, so let’s do the following:

    # openssl x509 -in ldap.csr -out ldap.cert -req -signkey ldap.key -days 365
    

1 year should be good, adjust to your will however.

Now you can continue on to configuring slapd.conf.

slapd.conf

You will need to create a /usr/local/etc/openldap/slapd.conf file something to the effect of this (customize this file all you like based on documentation from the openldap project).

    include         /usr/local/etc/openldap/schema/core.schema
    include         /usr/local/etc/openldap/schema/cosine.schema
    include         /usr/local/etc/openldap/schema/nis.schema
    include         /usr/local/etc/openldap/schema/misc.schema
    include         /usr/local/etc/openldap/schema/inetorgperson.schema
    pidfile         /var/run/openldap/slapd.pid
    argsfile        /var/run/openldap/slapd.args

    access to dn.base=""
    by * read

    # Members of admin group can write to everything
    # USE THIS WITH CAUTION
    access to *
    by group.base="cn=admin,ou=Groups,dc=yourdomain,dc=dom" write
    by * break

    # Allow only user to change its password
    access to attr=userPassword
    by self write
    by anonymous auth
    by * none

    # Addressbook per user (create).
    access to dn.regex="^ou=addressbook,uid([^,]+),ou=People,dc=yourdomain,dc=dom$" attrs=entry
    by dn.exact,expand="uid=$1,ou=People,dc=yourdomain,dc=dom" read
    by anonymous auth
    by * none

    # Addressbook per user (add entries)
    access to dn.regex="ou=addressbook,uid=([^,]+),ou=People,dc=yourdomain,dc=dom$" attrs=children
    by dn.regex="uid=$1,ou=People,dc=yourdomain,dc=dom" write
    by anonymous auth
    by * none

    # Addressbook per user (add entries)
    access to dn.regex="ou=addressbook,uid=([^,]+),ou=People,dc=yourdomain,dc=dom$" attrs=entry
    by dn.regex="uid=$1,ou=People,dc=yourdomain,dc=dom" write
    by anonymous auth
    by * none

    # Owner can write, authenticated can read
    access to *
    by self write
    by users read
    by anonymous auth

    ## This is optional, only if you wanted SSL.
    TLSCipherSuite HIGH:MEDIUM:+SSLv2
    TLSCertificateFile /usr/local/etc/openldap/ssl/ldap.cert
    TLSCertificateKeyFile /usr/local/etc/openldap/ssl/ldap.key

    database        ldbm
    suffix          "dc=yourdomain,dc=dom"
    rootdn          "cn=Manager,dc=yourdomain,dc=dom"
    rootpw          Encrypted_Password
    password-hash   {SMD5}
    directory       /var/db/openldap-data
    index           objectClass     eq
    index           uid,uidNumber,gidNumber,memberUid       pres,eq
    

Take special note of the “rootpw” line. It needs an encrypted password that we are now going to generate. To do this, we use the slappasswd program like this:

    # slappasswd -s MySecretPassword
    

This will return a string like:

    {SSHA}613vutG4Gbt6LNUZtvymWOOmP9Nrt4QQ
    

You need to take that string, and put it in your slapd.conf file above, replacing the text “Encrypted_Password” for that encrypted password we just generated. Once this process is done, you can now safely save, and exit that file. Just as a bit of extra security, we are going to change permissions on this file since the openldap server by default, changes its effective user and group its run as. To accomplish this, we remember back to Unix basics 101, and execute:

    # chown ldap:ldap /usr/local/etc/openldap/slapd.conf
    # chmod 0440 /usr/local/etc/openldap/slapd.conf
    

The second line tells the system to only allow read permission for the user and group who own the file (in this case, the user ‘ldap’ and the group ‘ldap’).

ldap.conf

Next we will need to set up an /usr/local/etc/ldap.conf file. Add the following text to a new file /usr/local/etc/ldap.conf:

    uri ldaps://127.0.0.1/
    base "dc=yourdomain,dc=dom"
    port 389
    binddn cn=pamclient,ou=SystemAccounts,dc=yourdomain,dc=dom
    bindpw SuperSecretPassword
    scope sub
    pam_password exop
    ## The immediately following command is optional. Only if you want SSL.
    ssl on
    nss_base_passwd ou=People,dc=yourdomain,dc=dom?one
    nss_base_group ou=Groups,dc=yourdomain,dc=dom?one
    

Here we set our binddn and bindpw to values of an object whos sole purpose will be to be used for fetching information, it is not a real user (we will add this account later in the book). One thing you should take note of, is our bindpw here is unencrypted. Please make sure to remember that when we add this object to our database, we will need to feed it the password you specify here in an encrypted form. For nss_ldap, we must symlink this (or copy whichever you prefer) file to /usr/local/etc/nss_ldap.conf otherwise we won’t be able to do much of anything.

Interlude…

Before we populate our database, we need to make sure that the database directories have appropriate permissions, we can do this by just running one command:

    # chown -R ldap:ldap /var/db/openldap-*
    

Now, we’re halfway there. Stop, take a break, think about how easy this has been so far… It only gets worse. :)

Creating our LDIF file…

From this point on, we can create our ldif file which we will use to feed our information into the ldap server. As usual, I will provide an example:

    dn: dc=yourdomain,dc=dom
    dc: yourdomain
    objectClass: top
    objectClass: domain
    objectClass: domainRelatedObject
    associatedDomain: yourdomain.dom
    objectClass: domain

    dn: ou=SystemAccounts,dc=blurgle,dc=ca
    ou: SystemAccounts
    objectClass: top
    objectClass: organizationalUnit

    dn: cn=pamclient,ou=SystemAccounts,dc=blurgle,dc=ca
    sn: pamclient
    cn: pamclient
    objectClass: top
    objectClass: person
    userPassword: {SSHA}ZHZ2AHjwr4MyX5zKmw1/IgRNnEjIzSwf

    dn: ou=People,dc=blurgle,dc=ca
    ou: People
    objectClass: top
    objectClass: organizationalUnit

    dn: ou=Groups,dc=blurgle,dc=ca
    ou: Groups
    objectClass: top
    objectClass: organizationalUnit

    dn: uid=testuser,ou=People,dc=yourdomain,dc=dom
    cn: testuser
    sn: Dummy
    objectClass: person
    objectClass: organizationalPerson
    objectClass: inetOrgPerson
    objectClass: posixAccount
    objectClass: top
    objectClass: shadowAccount
    uid: testuser
    userpassword: Encrypted_Password_Generated_by_slappasswd_-s
    uidnumber: 10000
    gidnumber: 10000
    gecos: Test User Dummy
    loginShell: /bin/tcsh
    homeDirectory: /usr/home/testuser
    description: A simple test user.

    dn: ou=Addressbook,uid=testuser,ou=People,dc=yourdomain,dc=dom
    ou: Addressbook
    objectClass: organizationalUnit

    dn: cn=testgroup,ou=Groups,dc=yourdomain,dc=dom
    cn: testgroup
    objectClass: top
    objectClass: posixGroup
    gidnumber: 10000
    memberuid: testuser
    

NOTE: The userPassword section for our “pamclient” person object is in the encrypted form of the password you used in nss_ldap.conf previously. Please remember this!

The first five sections are required even if you don’t plan on adding any users right away. They define where your data goes. The next (sixth) section defines your user. All the fields should be self explanitory, for those who do not know, the “gecos” field is the “Full Name” field in chfn(1). The seventh section indicates the storage area for testuser’s address book. The final field is a group definition. It again, is self explanitory.

To add this, you can use one of two tools, I will discuss the usage of “slapadd” as we havn’t started openldap yet (if you have already started openldap, you can use “ldapadd”). Anyway, putting all the above information into a file called “input.ldif”, we will run the following command to test to make sure we got no typos:

    # slapadd -u -l input.ldif
    

If that works okay, run it again without the -u option:

    # slapadd -l input.ldif
    

Next, we’ll look at putting it all together, and seeing just exactly what we can do.

rc.conf

You will need to make one change to your /etc/rc.conf before you can successfully start up the openldap server on boot, and that one line would be:

    slapd_enable="YES"
    slapd_flags="-h 'ldap:/// ldaps:///'"
    

Once again, if you are choosing not to use SSL, you can ignore the slapd_flags line entirely.

pam.d files

Now, we should also edit a couple of files in /etc/pam.d so we can actually log in with the newly created user (we will add it to the database in the next step). We first must create a new /etc/pam.d/ldap file like the pam_ldap pkg-message file told us too, in case you weren’t paying attention, it goes a little something like this:

    login   auth    sufficient      /usr/local/lib/pam_ldap.so
    

Now let’s alter the /etc/pam.d/sshd file so we can ssh in under our testuser. We will simply find the line that looks like this:

    auth required pam_unix.so no_warn try_first_pass
    

And add this line just before it:

    auth sufficient /usr/local/lib/pam_ldap.so no_warn try_first_pass
    

We’ll also need to edit the pam.d/passwd file so we can change passwords for our user accounts. To do this, do the following:

    password  sufficient  pam_unix.so  no_warn try_first_pass nullok
    password  sufficient  /usr/local/lib/pam_ldap.so  use_first_pass
    

You can of course, edit more files (ie /etc/pam.d/su would be another one that quickly comes to mind, /etc/pam.d/system, /etc/pam.d/ftpd, and so on), but for now, we’ll just stick to sshd.

Special note: In order for you to be able to change LDAP user’s passwords with passwd(1) you will need to apply the patch outlined in the immediately following page, 3.9.

passwd.c patch

This page tells you where you need to make a modification to a file that is a part of your FreeBSD world to make sure that you are able to change user’s passwords who are stored in LDAP (though this ought to work for users stored in a MySQL backed DB, etc. as well).

You need to open up /usr/src/usr.bin/passwd/passwd.c in your favourite text editor (please note that this requires you to have the FreeBSD sources downloaded on your system); then make the following changes around line 123 of the file.

Remove this bit:

    errx(1,
    "Sorry, `passwd' can only change passwords for local or NIS users.");
    

And replace that with these lines:

    /* XXX: Green men ought to be supported via PAM. */
    fprintf(stderr, "Now you can change LDAP passwordi via PAM\n");
    

Then you need to execute a command to build and install this new version:

    # make obj depend all install
    

This should give you a brand new /usr/bin/passwd capable of changing passwords of your LDAP user. Try it out at the end of this guide to change the password of your “testuser” user.

nsswitch.conf

We need to make one more change to a file in /etc. Specifically, we need to edit (or create if one doesn’t exist), an /etc/nsswitch.conf file which contains the following information:

    passwd: files ldap
    group: files ldap
    

It is very important that ‘files’ remains first, and ‘ldap’ comes after. If nss is unable to contact your ldap server for whatever reason, you will experience problems trying to log in as your backup user (you should have a user that can log in who authenticates against the standard FreeBSD files.

Getting ready to go

Start OpenLDAP

At this stage, we now want to start up the openldap server, to do this we run its rc script:

    # /usr/local/etc/rc.d/slapd.sh start
    

This may, or may not stall on you for up to 30 to 120 seconds, don’t worry, this is normal from what I’ve found (first time I fired it up, it hung for 120 seconds, then each time I ran it after it hung for a few more seconds).

Test it out

Next, if we were successful, we should be able to see our new user:

    # id testuser
    uid=10000(testuser) gid=10000(testgroup) groups=10000(testgroup)
    

Now, if you ssh to localhost, it should work just fine. Entering in the password you created the account with (its unencrypted form of course).

Open Source software

Open source is not freeware or shareware. Open Source software is built from a community of developers committed to a common goal who then make the source code and program available to download allowing modifications and contributions back into the source code.