Spottt
Spottt


Apache

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:

  • OpenLDAP 2.2
    • Client; and
    • Server
  • nss_ldap
  • pam_ldap
  • FreeBSD 5.1 or higher.
  • Patience; and of course
  • Free time.

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).

Credits

These be the folks making this happen…

While this document has been written by myself, Jeremy Tregunna it has also been contributed to, by the following people:

  • HEMI - http://www.puresimplicity.net/~hemi/
    • Found various problems and pointed out issues.
  • Lewis Thompson – http://www.lewiz.org/
    • Submitted updates to the configuration, specifically per-user address books and SSL (though I did chomp it a little to make it more simple).
  • Ian Moore
    • Suggested the usage of the -u option to slapadd to be sure its added properly (avoids headaches if a mistake was made).

Open Source Solutions


View blog authority
Add to Technorati Favorites
SpreadBSD
FreeBSD: The Freedom to Perform!
Unleash your desktop with PC-BSD!