OpenLDAP, Part 1: Setting Up the Directory Server

1
8042
Getting started with OpenLDAP

Getting started with OpenLDAPLet us begin this series on LDAP by setting up OpenLDAP on our machines and unravelling its mysteries as the series progresses.

OpenLDAP is the open source implementation of the LDAP protocol to access a directory. Simply put, a directory is a repository of data, much like a database (but with significant differences) that is used to store huge amounts of data. Directories are optimised for fast search and retrieval. Directories are also fairly static — in the sense that the data in a directory is not updated very frequently.

LDAP or “Lightweight Directory Access Protocol” is a protocol used to access directories. OpenLDAP is an open source directory software suite conforming to the LDAP protocol (version 3) and it supports all major platforms. The current version of OpenLDAP is 2.4. There are significant changes in this version compared to v2.3. In this article though, we will cover features that apply to the previous versions as well.

The OpenLDAP software suite consists of a directory server (openldap-server) and a client (openldap-clients) to access the directory. To be able to query other LDAP servers, only the openldap-client is required.

The openldap-client package provides popular client tools such as ldapsearch, ldapadd, etc. The openldap-server software is required if you want to build a directory of your own.

On a RHEL/CentOS/Fedora system, the OpenLDAP RPMS are available as openldap-server and openldap-clients. A simple check will reveal the RPMs installed in your system. To query the RPM database for the installed OpenLDAP RPMS, run the following command:

[vbg@vbg-work scratch]$ rpm -qa | grep openldap

In my system, the output was as follows:

openldap-2.4.19-1.fc12.i686
openldap-devel-2.4.19-1.fc12.i686

Installing the OpenLDAP client

To be able to query other LDAP servers, you will need to install the openldap-clients package:

[root@vbg-work ~]# yum install openldap-clients

With the client software installed, you can access other LDAP servers. There are quite a few LDAP servers on the Internet that allow anonymous querying, which implies querying a server without providing a user name and password, much like in anonymous FTP transactions where you can download files without providing a username/password for authentication.

To query a directory server conforming to the LDAP protocol, use the ldapsearch command. A list of public LDAP servers can be found here. To test whether your OpenLDAP client software is installed correctly and is able to query remote LDAP servers, you may query any one of the listed servers.

As an example, I chose to query the server x500.bund.de:

[vbg@vbg-work scratch]$ ldapsearch -x -h x500.bund.de -b "o=bund,c=de"

The -h flag above specifies the hostname to be queried. The -b flag specifies the “base” from which the search should begin and -x specifies “simple authentication”.

Running the command displays a lot of output on the screen. Redirecting this output to a file will help us in understanding LDAP:

[vbg@vbg-work scratch]$ ldapsearch -x -h x500.bund.de -b "o=bund,c=de" > /tmp/ldapTGH-1.txt
ldap_bind: Success (0)
        additional info: Bind succeeded
[vbg@vbg-work scratch]$

The stderror output (which was not redirected by the above command) shows that binding (or authenticating and connecting) to the LDAP server was successful. Let us now look at the contents of this file, which contain the output of our query:

[vbg@vbg-work scratch]$ less /tmp/ldapTGH-1.txt
# extended LDIF
#
# LDAPv3
# base  with scope subtree
# filter: (objectclass=*)
# requesting: ALL

The opening line shows us that the output is in the LDIF format. It stands for LDAP Data Interchange Format. LDIF is used to represent LDAP data in text form. An understanding of LDIF is critical to be able to perform successful add/modify/delete/search operations on an LDAP server. LDIF files are useful for:

  1. adding data to the LDAP directory,
  2. modifying directory data,
  3. deleting directory data, and
  4. pretty much anything that has to do with visualisation of directory data.

The other lines also give us some more meaningful information. Note that all these are preceded with a # (hash). This means that these are comments, not the results of our query. They just provide additional information. The other important information is the version of the LDAP protocol used for querying (v3), the base of the LDAP tree on which the search operation was performed, and filters applied to refine search results.

A detailed explanation of this is beyond the scope of this article. Maybe in a future article, we can delve deep into the workings of LDAP and uncover its hidden treasures.

Most directories do not allow anonymous writing. To be able to add/modify/delete data, you need to bind to the directory server host with a valid user name and password. Most directories also do not allow anonymous read (or search). Depending on your environment and sensitivity, you may also wish to do away with anonymous read on your directory. This will depend on your LDAP server configuration.

Configuring the LDAP client

If you query a single directory server (within your organisation), typing the hostname and search base on the command line each time might seem like a mundane and irritating task. You can customise the /etc/openldap/ldap.conf file (on Fedora/RHEL) as shown below to specify an LDAP server and base. The OpenLDAP client utilities read the /etc/openldap/ldap.conf file.

Warning: Do not modify the /etc/ldap.conf file. It is for a different purpose and is accessed by a different set of programs.

To be able to simply query the above server (x500.bund.de), just specify the following two lines in /etc/openldap/ldap.conf:

HOST x500.bund.de
BASE o=bund,c=de

Make sure you comment out all the other lines at this stage. Once you have done this, just execute the ldapsearch command without the host and the base options:

[vbg@vbg-work scratch]$ ldapsearch -x

This will connect to the server specified in the configuration file and will search from the base mentioned there.

LDAP is a TCP/IP protocol and an LDAP server binds to TCP port 389 by default. When using TLS, the default secure LDAP port is 636. Instead of specifying a host, an LDAP URI can also be used. LDAP URIs are of the form: ldap://host-fqdn

The above LDAP search using LDAP URI instead of the hostname can be executed as follows:

[vbg@vbg-work scratch]$ ldapsearch -x -H ldap://x500.bund.de -b "o=bund,c=de"

…and the corresponding entry in /etc/openldap/ldap.conf will be:

URI ldap://x500.bund.de

Installing the OpenLDAP server

To query other directory servers is one thing and to be able to create your own directory server to store and serve data is quite another. The first step towards creating your own directory server is installing the required software. In Fedora, a yum install openldap-servers will do the job.

For the purpose of this article, I will create the openldap-server on a virtual RHEL 5.4 server and the client will reside on my virtual Fedora 12 host. The details of the test setup are:

  1. LDAP server hostname: vbg.knafl.org (192.168.122.1) — RHEL 5.4 (64 bit)
  2. LDAP client hostname: vbg-work.knafl.org (192.168.122.244) — Fedora 12 (32 bit)

The LDAP server software installs the standalone LDAP daemon (slapd). The version of the OpenLDAP server on RHEL 5.4 is 2.3 (openldap-servers-2.3.43-3.el5).

The slapd daemon binds on Port 389 and serves client requests based on its directory data. In Fedora/RHEL systems, the important locations are:

  • /usr/sbin/slapd — the standalone LDAP daemon binary program
  • /var/lib/ldap/ — the folder containing directory data files
  • /etc/openldap/slapd.conf — the LDAP server configuration file
  • /etc/init.d/ldap — init script for the LDAP daemon

It also creates the user and group LDAP. For security purposes, the slapd daemon runs with the privileges of this user:

[root@vbg ~]# cat /etc/passwd | grep ldap
ldap:x:55:55:LDAP User:/var/lib/ldap:/bin/false

Configuring the LDAP server

The main configuration file is /etc/openldap/slapd.conf. For the init script to be able to read this file, the permissions of this file should be set to 640 and the owner group should be set to “ldap”:

[root@vbg openldap]# ls -l /etc/openldap/slapd.conf
-rw-r----- 1 root ldap 3731 Nov 6 2008 /etc/openldap/slapd.conf

Let’s start configuring our very own LDAP server. As always, remember to keep a backup of the main config file — just in case something goes wrong:

[root@vbg openldap]# cp -a slapd.conf slapd.conf.org
[root@vbg openldap]# vim /etc/openldap/slapd.conf

The include section of this config includes certain files from the schema directory. These files describe the structure of our directory. We will examine these in more detail in another article. For now, to get going quickly, the other important directives in the configuration file are:

database        bdb # this defines the database backend used by openldap. In this case - Berkeley Data Base Backend
suffix          "dc=my-domain,dc=com" # This is the root of the Directory Tree
rootdn          "cn=Manager,dc=my-domain,dc=com" # This is the Distinguished Name of the superuser of the directory
# rootpw        secret

For a directory server, the DN and the base suffix are important concepts.

The base suffix of a directory specifies the top of the directory tree (much like “/” signifies the root of the Linux filesystem). All directory data is stored under this base suffix, much like folders and files in the traditional Linux filesystem. The DN (Distinguished Name) is the unique name of a directory entry (much like file names and directories — which need to be unique within the same parent folder).

LDAP is generally associated with DNS as most organisations would want their domain names mapped to their directory data. Therefore, if my domain name is knafl.org, this domain context can be represented in the directory as follows:
knafl.org directory representation
Therefore, in the directory, the domain knafl.org can be represented in a hierarchical fashion as: dc=knafl, dc=org.

We need to specify this base in our directory configuration file along with the superuser name and password. The superuser is referred to as rootdn (the DN of the “root” user). This should also fall under the base of the directory tree and could be referred to by the Common Name (CN) of Manager. Finally, we should set the password of the root user.

We can also set the rootdn password in clear text. This is a security risk and should be avoided. The password should be stored in an encrypted form. I am only including the “text password” for demo purposes.

#Sample /etc/openldap/slapd.conf
database        bdb
suffix          "dc=knafl,dc=org"
rootdn          "cn=Manager,dc=knafl,dc=org"
                   # Cleartext passwords, especially for the rootdn, should
                   # be avoided.  See slappasswd(8) and slapd.conf(5) for details.
                   # Use of strong authentication encouraged.
rootpw          FOSTERingLinux

Apart from the above, I have made no changes to the default configuration file. Once we have set up the server, we need to start the LDAP daemon. The LDAP service will read the configuration file and start the slapd daemon.

[root@vbg openldap]# service ldap start
Checking configuration files for slapd:  bdb_db_open: Warning - No DB_CONFIG file found in directory /var/lib/ldap: (2)
Expect poor performance for suffix dc=knafl,dc=org.
config file testing succeeded                              [  OK  ]
Starting slapd:                                            [  OK  ]
[root@vbg openldap]#

To check whether our LDAP is up, we will query our server as follows:

[root@vbg openldap]# ldapsearch -x -h localhost -b "dc=knafl,dc=org"
# extended LDIF
#
# LDAPv3
# base  with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
#
# search result
# search: 2
# result: 32 No such object
#
# numResponses: 1
# [root@vbg openldap]#

We will receive the “No such object” message from the server. This means that our LDAP server is running, but it could not locate our directory tree or the data.

Now we need to create the base data for our LDAP server. To do that, we need to create an LDIF file and use the client command ldapadd.

First, let us create a simple LDIF file for our directory base and save it in the file /tmp/ldap-base:

[root@vbg ~]# cat /tmp/ldap-base
dn: dc=knafl,dc=org
dc: knafl
objectClass: top
objectClass: domain

Adding the entries to the directory:

[root@vbg ~]# ldapadd -x -D "cn=Manager,dc=knafl,dc=org" -W -f /tmp/ldap-base
Enter LDAP Password:
adding new entry "dc=knafl,dc=org"
[root@vbg ~]#

By default, we require rootdn privileges to write data in the directory. The -D flag specifies the user name (DN in LDAP terminology), and -W specifies that the password will be entered on the command line prompt. Finally, -f specifies the name of the LDIF file that contains entries to be added to the directory.

Now when we query the directory, we get an output as follows:

root@vbg ~]# ldapsearch -x -h localhost -b "dc=knafl,dc=org"
# extended LDIF
#
# LDAPv3
# base  with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#
# knafl.org
dn: dc=knafl,dc=org
dc: knafl
objectClass: top
objectClass: domain
#
# search result
search: 2
result: 0 Success
# numResponses: 2
# numEntries: 1

Thus we have created the base of our directory. Now we need to add more data to it and also beef up the security of the LDAP server.

Let us first add some more data to create an address book. Let us add a section called “addressbook” in our LDAP tree under the base suffix. This section can be denoted as an Organisational Unit (OU). Therefore, our LDIF file will be:

[root@vbg ~]# cat /tmp/addressbook-base.ldif
dn: ou=addressbook,dc=knafl,dc=org
ou: addressbook
objectClass: top
objectClass: organizationalUnit

Let us add this OU to our directory:

[root@vbg ~]# ldapadd -x -D "cn=Manager,dc=knafl,dc=org" -W -f /tmp/addressbook-base.ldif
Enter LDAP Password:
adding new entry "ou=addressbook,dc=knafl,dc=org"

[root@vbg ~]#

Now let us add some addressbook entries under the OU “addressbook”. An example of an LDIF file with a user entry might look like the file displayed below:

[root@vbg ~]# cat /tmp/addressbook.ldif
dn:cn=Varad Gupta,ou=addressbook,dc=knafl,dc=org
cn: Varad Gupta
sn: Gupta
l: Gurgaon
street: M-37, Old DLF Colony, Sector-14
st: Haryana
postalCode: 122003
homePhone: 0124 22222222
mobile: 0999999999
mail: varad.gupta@fosteringlinux.com
objectClass: top
objectClass: inetOrgPerson
[root@vbg ~]#

Add this entry to our directory:

[root@vbg ~]# ldapadd -x -D "cn=Manager,dc=knafl,dc=org" -w FOSTERingLinux -f /tmp/addressbook.ldif
adding new entry "cn=Varad Gupta,ou=addressbook,dc=knafl,dc=org"

[root@vbg ~]#

Note the -w flag followed by the password of the rootdn instead of the -W used earlier. With the -w option, you can specify the password on the command line instead of being prompted for it.

You can similarly add other entries. Let us now query our directory from the Fedora client host:

[root@vbg ~]# ldapsearch -x -h localhost -b "dc=knafl,dc=org"
# extended LDIF
#
# LDAPv3
# base  with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#

# knafl.org
dn: dc=knafl,dc=org
dc: knafl
objectClass: top
objectClass: domain

# addressbook, knafl.org
dn: ou=addressbook,dc=knafl,dc=org
ou: addressbook
objectClass: top
objectClass: organizationalUnit

# Varad Gupta, addressbook, knafl.org
dn: cn=Varad Gupta,ou=addressbook,dc=knafl,dc=org
cn: Varad Gupta
sn: Gupta
l: Gurgaon
street: M-37, Old DLF Colony, Sector-14
st: Haryana
postalCode: 122003
homePhone: 0124 22222222
mobile: 09999999999
mail: varad.gupta@fosteringlinux.com
objectClass: top
objectClass: inetOrgPerson
#
# search result
search: 2
result: 0 Success
#
numResponses: 5
numEntries: 4
[root@vbg ~]#

In the next article, we will look at how to secure our basic LDAP server — adding an encrypted rootdn password, implementing access control, disallowing anonymous search, modifying and deleting entries, etc.

1 COMMENT

  1. […] slapd.conf file structure, disable anonymous directory reads, and ACLs (access controls).In Part 1, we had set up a basic OpenLDAP server and populated it with data. We had also searched the […]

LEAVE A REPLY

Please enter your comment!
Please enter your name here