OpenLDAP, Part 2: Adding Basic Security Measures

OpenLDAP securityIn the second part of the series on OpenLDAP, we’ll cover rootdn password encryption with slappasswd, understand 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 directories anonymously and seen that we could not add entries (write data to the directory) anonymously. This is because of the default security policy in slapd.conf, the LDAP daemon configuration file. In this article, we will take a look at adding an initial level of security to OpenLDAP servers.

The first and the foremost line of defence in any *nix operating system are the file and folder permissions. You must ensure that the server configuration /etc/openldap/slapd.conf file has 640 permissions and root:ldap are the user and group owners, respectively, as shown below:

[vbg@vbg ~]$ ll /etc/openldap/slapd.conf
-rw-r----- 1 root ldap 3729 Jan 20 11:05 /etc/openldap/slapd.conf
[vbg@vbg ~]

Besides, ideally, the openLDAP rootdn password must be encrypted rather than remain in plain text. In the last article, we had specified a plain-text password for the rootdn, as is evident from the terminal output below:

[root@vbg ~]# cat /etc/openldap/slapd.conf | grep rootpw
rootpw		 FOSTERingLinux
[root@vbg ~]#

As a security measure, this should also be encrypted. To encrypt the root password, we use the slappasswd command:

[root@vbg ~]# slappasswd -s FOSTERinglinux
{SSHA}gX7E8mXSkbl14Bt42nZQzMG33HbUZfA4
[root@vbg ~]#

As can be seen above, SSHA encryption is the default encryption mechanism. You can also change the encryption algorithm to crypt or md5, but SSHA is the preferred scheme.

We can now add this encrypted password to slapd.conf to further protect the rootdn password. Edit /etc/openldap/slapd.conf and set the encrypted password as follows:

[root@vbg ~]# cat /etc/openldap/slapd.conf | grep rootpw
rootpw		 {SSHA}gX7E8mXSkbl14Bt42nZQzMG33HbUZfA4
[root@vbg ~]#

…and restart the ldap service:

[root@vbg ~]# /etc/init.d/ldap restart
Stopping slapd:                                            [  OK  ]
config file testing succeeded
                                                           [  OK  ]
Starting slapd:                                            [  OK  ]
[root@vbg ~]#

How would you test whether the new password is working or not? Do we have to always write something to the directory and check the password?

An easier and risk-free approach to the above would be to search the directory using a user name and password. The syntax for providing the userdn and password in the ldapsearch command is similar to that of the ldapadd command:

[vbg@vbg-work ~]$ ldapsearch -x -h 192.168.122.1 -b "dc=knafl,dc=org"
# extended LDIF
# #
# # LDAPv3
# # base  with scope subtree
# # filter: (objectclass=*)
# # requesting: ALL
Anonymous Search works .....

Now let us try searching with a user name and an incorrect password:

[vbg@vbg-work ~]$ ldapsearch -x -h 192.168.122.1 -b "dc=knafl,dc=org" -D "cn=Manager,dc=knafl,dc=org" -w xyz
ldap_bind: Invalid credentials (49)

This fails. Therefore, we know that the supplied credentials (user name/password) are incorrect. To run a successful search, we will need to specify the correct password. That is left as an exercise for the reader.

Making successful authentication a prerequisite for successful search (disable anonymous directory read) is another security measure that I would recommend. Though this depends on the kind of data maintained in your directory, if you are unsure, it is best to disable anonymous read. This is done through “access control instructions” in the configuration file.

But before we move on to “access control restrictions”, we first need to understand the structure of slapd.conf.

slapd.conf structure

Why did I simply not append a line to the top of the configuration file specifying the encrypted password, above? It would have been very easy to demonstrate by mentioning the following command, for instance:

[root@vbg ~]# MYPASS=`slappasswd -s tr`;sed -ie '1i\rootpw '$MYPASS'\' /etc/openldap/slapd.conf
[root@vbg ~]# head -n 1 /etc/openldap/slapd.conf
rootpw {SSHA}LiHyBXx3qZNd6I2ZpUjHrXT4WFK1+1TF
[root@vbg ~]#

[root@vbg ~]# service ldap restart
Stopping slapd:                                            [  OK  ]
Checking configuration files for slapd:  slaptest: bad configuration file!
                                                           [FAILED]
[root@vbg ~]#

So, we see that by randomly inserting lines, we are unable to set up the configuration file, slapd.conf. This can be achieved in some other configuration files though.

Now, if we delete the first line and add the same line to the bottom of the file, let us see what happens. Delete the first line:

[root@vbg ~]# sed -ie '1,1D' /etc/openldap/slapd.conf

Add the rootpw to the bottom:

[root@vbg ~]# echo "rootpw `slappasswd -s FOSTERinglinux`" >> /etc/openldap/slapd.conf

This will add the encrypted root password to the configuration file, as demonstrated by the command below:

[root@vbg ~]# tail -n 1 /etc/openldap/slapd.conf
rootpw {SSHA}Di8MFfCGtHGR2AfazXN3IomZJqFkoiK1
[root@vbg ~]#

Now, let us restart the ldap service:

[root@vbg ~]# service ldap restart
Stopping slapd:                                            [FAILED]
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 ~]#

Obviously, we cannot insert rootpw at the top of slapd.conf, but in the case of the default slapd.conf, we can do so at the bottom.

Why is it so? This is because slapd.conf, follows a certain structure. So let us ask ourselves: what is the need for a structure? One reason that I can think of is, backends.

OpenLDAP backends

Let’s take a detailed look at backends in the later part of this series. It is the wide availability of backends that really makes OpenLDAP such an exciting piece of software. OpenLDAP is very modular and can be thought of as having a frontend and a backend. The frontend basically is about the LDAP protocol, networking, etc, whereas the backend deals with the directory data storage.

At this point, it is sufficient to know that we can actually store data in an SQL database (MySQL, MS-SQL) and access that data through OpenLDAP using the “sql” backend. We can also create a proxy LDAP server, actually getting LDAP data from other servers using the “meta” backend.

Normally, we use the Berkeley Data Base (bdb) backend with OpenLDAP servers, by default. The reasons and benefits for doing so can be explored in a subsequent article in this series.

It is this availability of backends and the possibility of using various backends together in a single instance of the OpenLDAP server that necessitates a prescribed structure for slapd.conf.

The default structure for sladp.conf as described in the man page (man 5 slapd.conf) is:

# comment - these options apply to every database
...
....
.....
# first database definition & configuration options
database
......
......
......
# subsequent database definitions & configuration options

Global configuration options are defined at the top of slapd.conf. These options apply to all backends, unless explicitly overridden within a backend definition.

Databases are then defined by the keyword database. Then database-specific options such as suffix, rootdn, rootpw, indexes, etc, are defined.

As we can see now, since we have only one database backend, specifying rootpw at the bottom of the file worked, as the rootpw is a database configuration option, but since it is not a global configuration option, specifying rootpw as the topmost line, failed.

Since slapd.conf requires a structured configuration, a utility called slaptest is included in the openldap-servers package. slaptest reads the configuration file and checks whether it is okay or not. We use the -f flag to perform a sanity check on a configuration file:

[root@vbg ~]# slaptest -f /etc/openldap/slapd.conf
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
[root@vbg ~]#

Note: slaptest is a very useful and important tool, especially in production environments, where configuration changes and updates must be thoroughly tested before applying them.

Access control restrictions

Since this article focuses more on securing the OpenLDAP server, we go back to our discussion on access control restrictions. ACLs (access controls) in slapd.conf in their most simple form can be described by the following syntax:

access to [What] by [Who] [Permission]

As an example, the default access control restriction (when none is explicitly specified in the configuration file) is:

access to * by * read

By evaluating this syntax, it becomes:

  • [What] is * (all parts of the directory)
  • [Who] is * (all users, including anonymous)
  • [Permission] is read

Thus the default access control restriction in slapd.conf, in plain English, means: Allow all users to read all portions of the directory.

Can we allow anonymous writes into the directory as well?

Let us test this by changing the access control restriction to: Allow all users to write to all parts of the directory.

access to * by * write

Add this ACL to slapd.conf and restart the ldap service. Let us also create a new addressbook entry, by the cn (common name) of “lfy user”. A copy of the sample LDIF used in the first article of this series is given below:

[vbg@vbg-work ~]$ cat /tmp/lfy-user.ldif
dn:cn=lfy user,ou=addressbook,dc=knafl,dc=org
cn: lfy user
sn: user
l: Gurgaon
street: M-37, Old DLF Colony, Sector-14
st: Haryana
postalCode: 122003
homePhone: 0124 3333333
mobile: 0955555555
mail: [email protected]
objectClass: top
objectClass: inetOrgPerson

Let us now try to add this entry to the directory:

[vbg@vbg-work ~]$ ldapadd -x -h 192.168.122.1 -f /tmp/lfy-user.ldif
adding new entry "cn=lfy user,ou=addressbook,dc=knafl,dc=org"
ldap_add: Strong(er) authentication required (8)
additional info: modifications require authentication

[vbg@vbg-work ~]$

Surprisingly, our ACL did not work. Despite the fact that we specified any/all users to write to the directory, we were unable to do so.

To enable anonymous writes (not at all recommended) to your directory, we will have to use another security directive — allow.

To enable anonymous updates to directory, add the following global configuration option to slapd.conf:

allow update_anon

Save the configuration file, check for errors in the configuration file, restart the ldap service and test whether you can add a user anonymously. This should succeed.

The allow update_anon option generally should not be enabled, as we do not want anyone to write data into our directory without authentication. It has some very special use cases that we might cover in the later part of this series.

Now, let us apply a more common security requirement to our LDAP server — disable anonymous access altogether. In other words, valid authentication will be required even for the ldapsearch command. How would we create that ACL?

access to * by anonymous none

The above ACL does not give any permissions to anonymous users. You can check whether the syntax of the ACL is correct or not, using the slaptest command discussed earlier.

But what are the possible permissions that can be specified in slapd.conf? We have already seen three of them: read, write, and none. The others are: disclose, auth, compare, and search. We will go into the details of each of these permissions later; we intuitively know the meaning of the other permissions — read, write, and none.

Similarly, what are the possible values for who? We have discussed two of these: * (all), and anonymous. Two other possible values are: users, and self. users means entries or DNs that exist in the directory, and self means the user who is currently authenticated.

There are many possible values for what. This depends on the directory data. In this article, we have only discussed * as a possible value for what. As we delve deeper into LDAP and understand attributes, ObjectClasses and schema, we will be able to better define the what part of an ACL.

ACLs can also take more complex forms, including a “control” option as per the security requirements of a directory. We will touch on these aspects once we create a central directory with users and passwords for authentication. For those of you who would like to experiment with ACLs right away and not wait for the upcoming articles, man slapd.access is a storehouse of information — including a wealth of information on slapd.conf access control options and is a must read when securing an LDAP server.

In the next article in this series, we will explore LDAP concepts such as schema, ObjectClasses and attributes, and build an LDAP server capable of authenticating Linux users.

All published articles are released under Creative Commons Attribution-NonCommercial 3.0 Unported License, unless otherwise noted.
Open Source For You is powered by WordPress, which gladly sits on top of a CentOS-based LEMP stack.

Creative Commons License.