Lampros - Weird Bricks

OpenLDAP 101 - Step by Step on FreeBSD 8.1

01 April, 2011 | FreeBSD

Intro

In this post we'll go through installing and setting up OpenLDAP with SSL (encryption support). For those who don't know, an LDAP server (LDAP standing for Lightweight Directory Access Protocol) is a type of database usually adhering to a schema. The word 'schema' is taken from Greek, meaning 'shape'. So basically it's kind of like a database that is shaped in a way so that it is standardized.

Note:
For more info on schemas Google/Bing for the following RFCs (Request for Comments)standardizing those schemas:


Now, the most famous LDAP server must be Active Directory. Active Directory is Microsoft's server implementation of LDAP coming with it's own schema. There are efforts out there to create Active Directory compatible schemas, but that can be tricky business and we won't be covering this here. For more info on those projects look at Samba 4.

Most usually an LDAP server is used as a centralized repository for user's information. In other words a database that many other servers can access to authenticate users.

Example:
On the same computer we have an FTP server, an ejabberd server and a mail server. Now all of those can seperately have their own authentication mechanisms and yes – you could write scripts that add a user in every one of those authentication systems seperately. There is however, an alternative: use an LDAP server.

The LDAP server will hold the username/password combinations along with names,last names, phone numbers, etc. Then each one of the other servers will ask the LDAP server if the username/password is correct.

Open Source LDAP Servers:
The most famous LDAP server for Unix/Linux is probably OpenLDAP. Other ones you may want to look into is RedHat's/CentOS 389, OpenDS and the Apache Directory Server. Note that OpenDS and Apache Directory Server are implemented in Java, meaning you will need Java to be installed on FreeBSD prior to them.

In this tutorial we'll go with OpenLDAP, it doesn't require Java and well no one (as far as I know!) has reported so far 389 successfully installing on FreeBSD.

OpenLDAP Installation:
1. Boot up FreeBSD and make sure you are logged in as root.
2. Type time pkg_add -r openldap24-server (The time part is so we can see how much time this operation will take).

Took under 19 seconds on my system.

3. Create the directory where OpenLDAP expects it's database configuration file and then copy the database configuration file:
mkdir /var/db/openldap-data

cp /usr/local/etc/openldap/DB_CONFIG.example /var/db/openldap-data/DB_CONFIG

4. Now let's create the certificates necessary for OpenLDAP.
Note: This has been the most troublesome part of the whole OpenLDAP installation, as it seems that the error messages that OpenLDAP will throw for certificates, are not always very clear. If this is your first time ever installing OpenLDAP try to follow these commands to the letter, unless you really know what you're doing. The most common source of problem seems to come from the permissions on the certificates/keys and having the files in directories where OpenLDAP cannot access them.

To make things easier, I've color coded the filenames in those commands as:
Green = This command will OUTPUT a file in a PUBLIC folder
Red = This command will OUTPUT a file in a PRIVATE folder
Blue = This FILE will be used as INPUT

Let's start:
After you installed OpenLDAP the subdirectory /usr/local/etc/openldap should be already created.
Go there by typing cd /usr/local/etc/openldap

Now let's create the directory for the private certificates/keys. It will be a subdirectory to /usr/local/etc/openldap. Create it by typing:
mkdir /usr/local/etc/openldap/private

Note: To save yourself a lot of trouble and headaches, double check the filenames before you even hit enter for the following commands! - again this is the most troublesome part of OpenLDAP.
Creation of the Root CA (Certification Authority)
Type:
openssl req -days 3650 -nodes -new -x509 -keyout /usr/local/etc/openldap/private/ca.key -out /usr/local/etc/openldap/ca.crt

You can leave all the fields blank (just hit enter) but when you get to the 'Common Name' you NEED to 'fake' a name for the certification authority. In my case I will use the HOSTNAME of my FreeBSD system(weirdbricks.com) prefixed by the initials ca. OpenLDAP is very picky about this. The reason is, the Certification Authority (CA) cannot be the same as the domain. It's like saying 'lampros is verifying that I am lampros'. Hence I will use 'ca.weirdbricks.com', as in the following screenshot:

CN = ca.weirdbricks.com
Creation of the Private Key and Certificate Signing Request (CSR)
openssl req -days 3650 -nodes -new -keyout /usr/local/etc/openldap/private/server.key -out /usr/local/etc/openldap/private/server.csr

Again when typing this command remember to respect the Common Name:

CN = weirdbricks.com
When you're asked for a 'Challenge password' and an 'Optional Company Name' you can leave those blank too just by pressing Enter.

Sign Server Certificate
openssl x509 -req -days 3650 -in /usr/local/etc/openldap/private/server.csr -out /usr/local/etc/openldap/server.crt -CA /usr/local/etc/openldap/ca.crt -CAkey /usr/local/etc/openldap/private/ca.key -CAcreateserial

The result of this should be:

Generate the Client Certificate
openssl req -days 3650 -nodes -new -keyout /usr/local/etc/openldap/private/client.key -out /usr/local/etc/openldap/private/client.csr

Again when typing this command remember to respect the Common Name:
CN = weirdbricks.com
When you're asked for a 'Challenge password' and an 'Optional Company Name' you can leave those blank too just by pressing Enter, just like before.
Sign Client Certificate
openssl x509 -req -days 3650 -in /usr/local/etc/openldap/private/client.csr -out /usr/local/etc/openldap/client.crt -CA /usr/local/etc/openldap/ca.crt -CAkey /usr/local/etc/openldap/private/ca.key

The result of this should be:

Directory structure should look like this (8 files) if all has gone well:
Type ls -l
Public Certificates:
/usr/local/etc/openldap/ca.crt
/usr/local/etc/openldap/client.crt
/usr/local/etc/openldap/server.crt


Private Certificates/Keys:
/usr/local/etc/openldap/private/ca.key
/usr/local/etc/openldap/private/client.csr
/usr/local/etc/openldap/private/client.key
/usr/local/etc/openldap/private/server.csr
/usr/local/etc/openldap/private/server.key


Certificate Configuration (Using the Certificates we created)
Wow, that was something wasn't it? Let's go ahead and configure the openldap server (slapd) to use those certificates.

Edit the /usr/local/etc/openldap/slapd.conf by typing:
ee /usr/local/etc/openldap/slapd.conf

Add lines at the end of the file:
TLSCipherSuite HIGH:MEDIUM:+SSLv3
TLSCertificateFile /usr/local/etc/openldap/server.crt
TLSCertificateKeyFile /usr/local/etc/openldap/private/server.key
TLSCACertificateFile /usr/local/etc/openldap/ca.crt

Save and exit

Now edit the client side (this is mandatory irregardless which program you'll later use to access OpenLDAP), type:
ee /usr/local/etc/openldap/ldap.conf

Add lines at the end of the file:
TLS_CACERT /usr/local/etc/openldap/ca.crt
TLS_CIPHER_SUITE HIGH:MEDIUM:+SSLv3
Save and exit.

Edit /etc/rc.conf so the OpenLDAP server starts at boot time:
Type:
ee /etc/rc.conf

Add the lines at the end of the file:
slapd_enable="YES"
slapd_flags="-4 -u ldap -g ldap -h "
The above line means 'start ldap for IPv4, by user ldap, group ldap, listening at URI
Save and exit. Should look like this:

Change permissions on the private certificate directory, type:
cd /usr/local/etc/openldap
chown -R private
chmod -R 700 private/
chmod -R 700 private/*


If done correctly the permissions should look like this upon typing ls -l
For directory private

For files inside private:
ls -l

If those are not correct OpenLDAP will fail and even worse won't tell you why! You''ll get something like this:

After all this, check that OpenLDAP is not crashing violently, type the following to run slapd with debug options:
/usr/local/libexec/slapd -d -1

If you're getting something like this, you're good:

To stop slapd just press ctrl+C (break).

Start slapd properly type:
/usr/local/etc/rc.d/slapd start

Confirm that slapd is indeed running,type:
sockstat -4 -p 636
Note: We use port 636 since this is the standard SSL port for LDAP. 389 Is the regular port.

You should see something like this:

DIRECTORY CONFIGURATION:
Now let's configure LAPD and SLAPD for our domain/company.

Begin by editing /usr/local/etc/openldap/ldap.conf. Type:
ee /usr/local/etc/openldap/ldap.conf

Change line 8 from:
#BASE dc=example,dc=com
to
BASE dc=weirdbricks,dc=com
change line 9 from:
#URI
to
URI
also change lines 11-12 from:
#SIZELIMIT 12
#TIMELIMIT 15

to
SIZELIMIT 12
TIMELIMIT 15

Save and exit.

Now let's create a password for the OpenLDAP server. Type:
/usr/local/sbin/slappasswd -h "{MD5}" >> /usr/local/etc/openldap/slapd.conf

Type your password, press enter, type password again and press enter again. Your password will be directly appended to the end of the /usr/local/etc/openldap/slapd.conf file in MD5 form, however you will receive no confirmation of this here, just like in this screenshot:

Let's go edit the file, type:
ee /usr/local/etc/openldap/slapd.conf

At line 06 add these lines to include additional schemas:
include /usr/local/etc/openldap/schema/cosine.schema
include /usr/local/etc/openldap/schema/inetorgperson.schema

And those lines:
password-hash {md5}
allow bind_v2


Change line 54 from:
suffix "dc=my-domain,dc=com"
to
suffix "dc=weirdbricks,dc=com"
Change line 55 from:
rootdn "cn=Manager,dc=my-domain,dc=com"
to
rootdn "cn=Manager,dc=weirdbricks,dc=com"

Delete the line 'rootpw secret' (should be line 59)

Delete also the lines "New password:" and "re-enter new password" that may have been appended.

Change line 70: Add the word 'rootpw' in front of the {MD5} line (with a space following 'rootpw').

Save and exit file.

Now it's a good time to restart slapd. Do this by typing:
/usr/local/etc/rc.d/slapd restart

If you get an error like "WARNING: failed to start slapd" like this:

Type /usr/local/libexec/slapd -d -1 to debug slapd.

To test if you can search the directory, just type /usr/local/bin/ldapsearch -Z
This is what you should see:

If instead you see an error about 'TLS: hostname does not match CN in peer certificate' like this

Type hostname weirdbricks.com (in other words make sure the computer hostname is the same as the one you entered in the certificate). To permanently change this edit your /etc/rc.conf file and change the hostname line, so at next boot it will stay permanently changed.

If instead of that you see the message 'ldap_sasl_bind(SIMPLE):Can't contact LDAP server (-1)

Type /usr/local/libexec/slapd -d -1 to debug slapd.
If you are getting an error message about 'database already in use' like this:

What you need to do is:
1. Make sure that slapd is not already running. Type sockstat -4 and check to see if slapd shows up – if it is, stop it by typing /usr/local/etc/rc.d/slapd stop .If it is not go to 2.
2.delete the files previously created in the directory /var/db/openldap-data.
To do this, type :
cd /var/db/openldap-data

Type the following: (NOTE: Do not do this in a production environment!!!!!!)
rm _*
rm alock
rm dn2id.bdb
rm id2entry.bdb
rm log.*


Now try: /usr/local/libexec/slapd -d -1
You should be getting this:

Press ctrl+c to stop execution and try starting slapd the proper way again:
If you are still having problems, like this:

chances are you are having permissions/certificate problems.
Try the chmod commands again:
cd /usr/local/etc/openldap
chown -R private
chmod -R 700 private/
chmod -R 700 private/*


Try starting slapd again:
/usr/local/etc/rc.d/slapd restart
Let's add some data in our directory. The following will create an Organization called WeirdBricks and the Manager type user. The Manager is equal to an administrator or the root user – he has full power over the system.


Create a file with test entries:
ee /root/example.ldif

Inside add this:
dn: dc=weirdbricks,dc=com
objectclass: dcObject
objectclass: organization
o: WeirdBricks
dc: WeirdBricks

dn: cn=Manager,dc=weirdbricks,dc=com
objectclass: organizationalRole
cn: Manager


Save and exit.

This will create the basic structure for our directory and add the Manager user – the Manager has unlimited read/write access to our directory.
To add(inject) this file, type:
ldapadd -Z -D "cn=Manager,dc=weirdbricks,dc=com" -W -f /root/example.ldif
Upon pressing enter you'll get a prompt for the password:

Upon entering the password you should see something like this:

Now type ldapsearch again without any parameteres. You should get this:

Seems to be working fine. Let's install a Windows client to manipulate our directory.
Fire up Google and search for JXplorer.

Click 'Install Package'
Click on the Windows version, at the time of writing this is jxplorer-3.2.1-windows-installer.exe

Save the installer file on your desktop..

Double click on the file, the setup will start. Click 'Next'

Click on 'I accept the agreement' and 'Next'

Take the default install directory and click 'Next'

Click 'Next' to start installation.

Untick 'View Readme File' and click 'Finish'.

Click 'Start->Programs->JXplorer->JXplorer to start Jxplorer.

Click on the connect icon to start a new connection:

Fill in the values as in the screenshot
Host: 192.168.2.101 – The IP of the FreeBSD virtual machine
Port: 636 – for LDAP SSL
Protocol: LDAP v3
DSML Service: Empty
Base DN: Empty
Level: SSL+User+Password - so we can login as the Manager
User DN: cn=Manager,dc=weirdbricks,dc=com
Password: whatever password you used in the OpenLDAP installation

Click 'OK' when done. JXplorer will try to connect to OpenLDAP.

You'll get a warning for the certificate. You can ignore this, since we have signed the certificate ourselves. Just click 'This Session Only' – I have found Jxplorer having problems when click on 'Always'.

You should be already seeing the existing Directory – it's pretty empty, only the Manager is here:

Right click on 'weirdbricks' and click 'New'. We'll add a couple test users.

You'll get the Set Entry Object Classes – choose which classes our new entry will adhere to.
For users you definitely need to pick inetOrgPerson and person. You can remove the 'organizationalRole' class. Also in 'Enter RDN:' you should put the username – this is a unique identifier for the user in the directory. In this example I'll use my first name to keep things simple and clear.

It should look like this by now:


Click 'OK' when done.

You're going to get a long form. Thankfully we only need to fill in a couple of fields.
Fill in the sn field – sn stands for surname. You can put the same thing as the cn (common name) for now.

Then scroll down to the bottom, till you see userPassword. Click on it. A pop up will come up 'User Password Data'. Enter any password you like, and change the drop down to plain. When done click 'OK'.

Another value we'll want to fill in is 'mail'. Lots of programs will use this to pick up your e-mail address.

Now click 'Submit' to save to the server.

Do the exact same procedure to add atleast one more user. I'll add users 'matt' and 'jamie' for my examples. In all of the users make sure you add a PLAIN type password, a surname (even if it's the same as the cn) and mail. Also don't forget to add the classes person and inetOrgPerson.

When done, my directory looks like this:

Now that we have some users, let's go test this with Thunderbird.

Fire up Thunderbird and click on 'Address Book'

Click 'File'->'New'->'LDAP Directory...'

You'll get the Directory Server Properties window.
Name: weirdbricks directory (You can set this to whatever you like)
Hostname: 192.168.2.101 (The IP address where OpenLDAP is)
Base DN: dc=weirdbricks,dc=com
Port number: 636 – although you don't have to change this, Thunderbird will change it automatically once you tick 'Use secure connection (SSL)'
Bind DN: Empty
When you're done it should look like this:

When you're done, click on 'OK'

You can see the 'weirdbricks directory' added to the Address Book. Double click it to enter it's properties again.

Click on 'Offline'. Then click on 'Download Now'. You should see the message 'Replication succeeded'. Click 'OK' to finish here.

In the search bar, type 'lampros' and press Enter. If you see no results, close Thunderbird completely and restart it. Sometimes I see this error message:

Which unfortunately I have no idea why happens. Click 'OK' and restart Thunderbird, go back to the Address Book and try again.

In the search box if instead of 'lampros' you type '.' you'll see everyone in the directory.. pretty cool

If for example you were to right click on 'lampros' and click 'Write'

You'll get the Compose screen of Thunderbird populated with the e-mail address of lampros.

Pretty cool huh?

In the next posts I'll show you how to connect OpenLDAP with ejabberd for more fun.

Sources/Links: