Gentoo Wiki




LDAP stands for Lightweight Directory Access Protocol. Based on X.500 it encompasses most of its primary functions, but lacks the more esoteric functions that X.500 has. Now what is this X.500 and why is there an LDAP?

X.500 is a model for Directory Services in the OSI concept. It contains namespace definitions and the protocols for querying and updating the directory. However, X.500 has been found to be overkill in many situations. Enter LDAP. Like X.500 it provides a data/namespace model for the directory and a protocol too. However, LDAP is designed to run directly over the TCP/IP stack. See LDAP as a slim-down version of X.500.

A directory is a specialized database designed for frequent queries but infrequent updates. Unlike general databases they don't contain transaction support or roll-back functionality. Directories are easily replicated to increase availability and reliability. When directories are replicated, temporary inconsistencies are allowed as long as they get synchronised eventually.

All information inside a directory is structured hierarchically. Even more, if you want to enter data inside a directory, the directory must know how to store this data inside a tree. Lets take a look at a fictional company and an Internet-like tree:

                           __________/          \_________
                          /                               \
                 ou=UsersGroups                       ou=Services
             ____/            \_____                 /           \
            /                       \              DHCP         BIND
        ou=Users                ou=Groups
        /     \
    ___/       \___
   /               \
cn=root          cn=tux

Dc means directory component, o means organization, ou means organizational unit.

For this guide, there will be some assumptions and conventions.

You have one server and one client. Your server is named 'myserver'. Your client is called 'myclient'. You have a domain, called ''. You want to use your server to authenticate your client logins.

Since you don't feed data to the database in this ascii-art like manner, every node of such a tree must be defined. To name such nodes, LDAP uses a naming scheme. Most LDAP distributions (including OpenLDAP) already contain quite a number of predefined (and general approved) schemes, such as the inetorgperson, a frequently used scheme to define users.

Interested users are encouraged to read the OpenLDAP Admin Guide.

LDAP can be used for various things. This document focuses on centralised user management, keeping all user accounts in a single LDAP location (which doesn't mean that it's housed on a single server, LDAP supports high availability and redundancy), yet other goals can be achieved using LDAP as well.

This Guide is divided into two parts: Server and Client.

Server setup


We don't want anyone eavesdropping the LDAP server, so let's make sure that the connection inside the domain is secure. There are many references online, here we'll just produce the basic steps to bring SASL functional. If you want to go ahead and skip this dull part, go ahead, but remember that you will have to get back here later. The later instructions rely that all this has been commenced.

First, generate an SSL certificate to secure your directory. Answer the question you receive as good as possible. When asked for your Common Name, enter the name the clients will use when contacting the server. This is usually the full domainname.

Servers also often support the non-standard "LDAPS" ("Secure LDAP", commonly known as "LDAP over SSL") protocol. The LDAPS differs from LDAP in that it connects to a special port, ldaps (tcp/636). OpenLDAP has the ability to enable SSLv3 capabilities. Similar to SSL is Transport Layer Security (TLSv1). While SSL operates on a secure connection (ldaps://:636) and is a Netscape-defined protocol, TLS offers the same encryption on regular LDAP connections (ldap://:389) and is an industry standard (RFC 2830). Both types of secure connections are set up identically. It is only the URL that is different.

For more information, see

Insecure - strongly discouraged
DIGEST-MD5 relies on the client and the server sharing a "secret", usually a password. Good for relatively secure networks.
utilizes Kerberos V to provide secure authentication services. Kerberos is viewed as a secure, distributed authentication system suitable for both small and large enterprises.
When used in conjunction with TLS X.509-based public key technology, EXTERNAL offers strong authentication.

SSL Certificates

Since we are using SSL/TLS, we need to generate a certificate to allow incoming and outgoing transactions. Generating a self-signed certificate is pretty easy, and it needs to be done any time a server's domain name is changed. You can put additional hostnames in the subjectAltName extension field of the certificate, but how to do this is beyond the scope of this document.

For now, just do the following. Make sure to answer the questions as best you can.

Note: When asked for a Common Name, you must enter the fully-qualified distinguished name of the server, in this case, and not 'your name' as is suggested by the OpenSSL prompt. This common mistake is the cause of over 90% of server certificate errors!
(It may be a good idea to edit the defaults in /etc/ssl/openssl.conf to reflect your location and organization. Vsnine 17:59, 16 July 2008 (UTC))
openssl req -config /etc/ssl/openssl.cnf -new -x509 -nodes \
       -out /etc/ssl/ldap.pem -keyout /etc/openldap/ldap-key.pem -days 999999

This will generate the SSL/TLS certificate to /etc/ssl/ldap.pem and private key to /etc/openldap/ldap-key.pem. Keep these files on the server, and copy both of them onto the clients.

On Gentoo, edit /etc/conf.d/slapd and add the following, commenting out the existing line:

File: /etc/conf.d/slapd
OPTS="-h 'ldaps:// ldapi://%2fvar%2frun%2fopenldap%2fslapd.sock'"

The above is only for ldap over ssl. If you do not desire it, or are troubleshooting it might help to change that to the following (ldap:// is the only thing that is added):

File: /etc/conf.d/slapd (if you want to add support for ldap without ssl)
OPTS="-h 'ldaps:// ldap:// ldapi://%2fvar%2frun%2fopenldap%2fslapd.sock'"

For help with intermediate/chained SSL certificates (e.g. Go Daddy's Turbo SSL certs), see OpenLDAP with a Go Daddy “Turbo SSL Secure Certificate” in Disruptive Library Technology Jester.

Installing OpenLDAP

On your server, you need to install the following software.

GDBM is the weak fallback supported by OpenLDAP, and is generally not the suggested backend database provider for OpenLDAP. BerkeleyDB (hdb) is much more robust. To use BerkelyDB, enable the USE flag berkdb for OpenLDAP:

echo 'net-nds/openldap -gdbm berkdb' >> /etc/portage/package.use

Install OpenLDAP using: emerge --ask --verbose openldap pam_ldap nss_ldap.

Alter the file permissions for security reasons:

chown ldap:ldap -R /var/lib/openldap-{ldbm,data,slurp}


Sudo schema

To let LDAP users use sudo, download the sudo schema from: sudo.schema

Kerberos 5 schema

Here is the krb5-kdc.schema file that is referenced in the /etc/openldap/slapd.conf file: krb5-kdc.schema.

Slapd configuration

You should now have a file called /etc/openldap/slapd.conf. This is the file that controls all the ldap access and tree layout for OpenLDAP. We will make a few changes to it.

We want to make sure that it accepts "INetOrgPerson" and "NIS" schemas, because we want to authenticate net users, and nis stuff. The cosine schema adds support for COSINE and X.500 directory pilots (RFC 1274). This simply fills a dependency for the other schemas. Also, if we want kerberos and/or samba, we need to stick that in here.

Now edit the LDAP Server config at /etc/openldap/slapd.conf:

File: /etc/openldap/slapd.conf
# Include the needed data schemes below core.schema
include         /etc/openldap/schema/cosine.schema
include         /etc/openldap/schema/inetorgperson.schema
include         /etc/openldap/schema/nis.schema

Uncomment modulepath and hdb module
# Load dynamic backend modules:
modulepath    /usr/lib/openldap/openldap
# moduleload
# moduleload
# moduleload
# moduleload
# moduleload
# moduleload
# moduleload
# moduleload

# Uncomment sample access restrictions (Note: maintain indentation!)
access to dn.base="" by * read
access to dn.base="cn=Subschema" by * read
access to *
   by self write
   by users read
   by anonymous auth

# BDB Database definition

database        hdb
suffix          "dc=genfic,dc=com"
checkpoint      32      30 # <kbyte> <min>
rootdn          "cn=Manager,dc=genfic,dc=com"
rootpw          {SSHA}EzP6I82DZRnW+ou6lyiXHGxSpSOw2XO4
directory       /var/lib/openldap-ldbm
index           objectClass     eq

Note that if you change the indexes, which you may do later on to improve performance, you will need to run slapindex while slapd is not running.

Generate an encrypted password we'll use later on:

Code: Generate password
# slappasswd
New password: my-password
Re-enter new password: my-password

Then change the variable rootpw to the generated password in /etc/openldap/slapd.conf.

The password (and rootdn) is database-specific, so it must be introduced in the proper section inside the config file. rootpw can only be set when rootdn is under suffix.

Create the DB_CONFIG file in /var/lib/openldap-data to increase the performance. You can use DB_CONFIG.example as a template:

cp /var/lib/openldap-data/DB_CONFIG.example /var/lib/openldap-data/DB_CONFIG

Enable TLS

File: /etc/openldap/ldap.conf
BASE    dc=myserver,dc=mydomain,dc=org
URI     ldap://

TLS_REQUEST     allow
TLS_CERT        /etc/ssl/ldap.pem
TLS_KEY         /etc/openldap/ldap-key.pem
#TLS_REQCERT     never

The TLS_CERT variable should point to the certificate you have created and transferred to the client. TLS_REQCERT tells the client not to request the certificate since we have already installed it on the local client.

If you want to use LDAPS, then change ldap:// to ldaps:// in the URI variable. If you want to use the LDAPv3 standard, then you want to use startTLS operations over the normal ldap:// port. The LDAPv2 specification did not include a way to handle TLS, so LDAPS was made up. It is not part of any standard. Most applications can handle it, though. When LDAPv3 was developed, they addressed this missing functionality by adding support for startTLS. Most applications support it too.

Importing base

You can use this file as the base:

File: base.ldif
dn: dc=mydomain,dc=org
objectclass: organization
objectclass: dcObject
o: My Domain Name
dc: mydomain
description: My new LDAP domain

dn: ou=Hosts,dc=mydomain,dc=org
ou: Hosts
objectClass: top
objectClass: organizationalUnit
objectClass: domainRelatedObject
associatedDomain: mydomain

dn: ou=Rpc,dc=mydomain,dc=org
ou: Rpc
objectClass: top
objectClass: organizationalUnit
objectClass: domainRelatedObject
associatedDomain: mydomain

dn: ou=Services,dc=mydomain,dc=org
ou: Services
objectClass: top
objectClass: organizationalUnit
objectClass: domainRelatedObject
associatedDomain: mydomain

dn: nisMapName=netgroup.byuser,dc=mydomain,dc=org
nismapname: netgroup.byuser
objectClass: top
objectClass: nisMap
objectClass: domainRelatedObject
associatedDomain: mydomain

dn: ou=Mounts,dc=mydomain,dc=org
ou: Mounts
objectClass: top
objectClass: organizationalUnit
objectClass: domainRelatedObject
associatedDomain: mydomain

dn: ou=Networks,dc=mydomain,dc=org
ou: Networks
objectClass: top
objectClass: organizationalUnit
objectClass: domainRelatedObject
associatedDomain: mydomain

dn: ou=People,dc=mydomain,dc=org
ou: People
objectClass: top
objectClass: organizationalUnit
objectClass: domainRelatedObject
associatedDomain: mydomain

dn: ou=Group,dc=mydomain,dc=org
ou: Group
objectClass: top
objectClass: organizationalUnit
objectClass: domainRelatedObject
associatedDomain: mydomain

dn: ou=Netgroup,dc=mydomain,dc=org
ou: Netgroup
objectClass: top
objectClass: organizationalUnit
objectClass: domainRelatedObject
associatedDomain: mydomain

dn: ou=Protocols,dc=mydomain,dc=org
ou: Protocols
objectClass: top
objectClass: organizationalUnit
objectClass: domainRelatedObject
associatedDomain: mydomain

dn: ou=Aliases,dc=mydomain,dc=org
ou: Aliases
objectClass: top
objectClass: organizationalUnit
objectClass: domainRelatedObject
associatedDomain: mydomain

dn: nisMapName=netgroup.byhost,dc=mydomain,dc=org
nismapname: netgroup.byhost
objectClass: top
objectClass: nisMap
objectClass: domainRelatedObject
associatedDomain: mydomain
ldapadd -x -D "cn=admin,dc=mydomain,dc=org" -W -f base.ldif

Note: The above command cannot run unless the server is running. Should this be moved? Vsnine 20:10, 16 July 2008 (UTC)

Startup and testing

First do a simple syntax check of your slapd.conf file by running slaptest as root. If there are any errors and you need more detail try increasing slaptest's debug level: slaptest -d 10. If this does not reveal any useful information, try slaptest -d 255.

Start the slapd service:

/etc/init.d/slapd start

Add it into default runlevel:

rc-update add slapd default

Configure a client for testing, so that you can use ldapsearch to test and debug basic connectivity.

Your friends here are ldapsearch and openssl s_client. You may test different things if the communication works, whether you can establish a secure tunnel and your certificate is ok.

You may first try to search rootDSE, for which the anonymous operation should be permitted.

ldapsearch -x -s base -b "" 

The following should produce a list of all the entries in your ldap:

ldapsearch -x -D "cn=admin,dc=mydomain,dc=org" -W

With a user account you should first try that the queries are working without SASL or TSL. Use the -W switch, or put your password into /etc/ldap.secret for a while (remember to remove it).

ldapsearch -Hldap:// -b "" -s base -D "cn=admin,dc=myserver,dc=mydomain,dc=org" -y /etc/ldap.secret

If successful, you should receive an output describing the Active Directory LDAP description. If you cannot perform simple top level searches on your Active Directory, then you should locate and fix any problems.

Once that works try with SASL but without TSL:

ldapsearch -Hldap:// -b "" -s base -Omaxssf=0

Notice the '-Omaxssf=0' which should disable SASL security layers.

If you use SSL, you can use the openssl s_client:

openssl s_client -connect openad.local:636 -CAfile /etc/ssl/ldap.pem
Note: The host variable is the fully qualified domain name FQDN or IP address of the Active Directory you wish to authenticate against. We could list a number of domain controllers separated by a space, or we could just enter the domain name of which a domain controller would be returned from DNS. If you enable SSL, you will have to use the FQDN.

Finally, try with both SASL and TSL:

ldapsearch -Hldap:// -b "" -s base -Omaxssf=0 -ZZ

If you get:

certificate verify failed. check your certificate status requirements.

Also don't forget to append the following line to your /etc/hosts.allow

File: /etc/hosts.allow
slapd: all
FIXME: Discuss possible problems at this point.

Home directories on the server

Later in this document the pam module pam_mount will be introduced, that mounts the user home directories. See the NFS page on how to setup the NFS server for shared home directories.


You can either use the existing structure by migrating it to the proper format with migrationtools, or create a blank template by hand. Either way, you'll end up with an LDIF template.

Open and edit the following:

$DEFAULT_BASE = "dc=mydomain,dc=org";
# Comment these lines out unless you have a mail schema loaded

Now run the migration scripts:

export ETC_SHADOW=/etc/shadow
cd /usr/share/migrationtools
./ > /tmp/base.ldif
./ /etc/group /tmp/group.ldif
./ /etc/hosts /tmp/hosts.ldif
./ /etc/passwd /tmp/passwd.ldif

You probably do not want (local) root or non-person users to your LDAP, so edit the passwd.ldif file and remove the entries you do not like.

posixAccount does not accept UTF-8 gecos fields. This is a huge problem is some countries, and should be fixed by editing nis.schema:

File: nis.schema.diff
--- nis.schema~ 2007-05-03 16:45:29.000000000 +0600
+++ nis.schema  2007-05-03 16:45:51.000000000 +0600
@@ -48,9 +48,9 @@

 attributetype ( NAME 'gecos'
        DESC 'The GECOS field; the common name'
-       EQUALITY caseIgnoreIA5Match
-       SUBSTR caseIgnoreIA5SubstringsMatch
+       EQUALITY caseIgnoreMatch
+       SUBSTR caseIgnoreSubstringsMatch

 attributetype ( NAME 'homeDirectory'
        DESC 'The absolute path to the home directory' 
Note: This disagree with RFC 2307, and some programs may not work properly.

You can import the template from the web interface or from the command line:

ldapadd -D "cn=admin,dc=mydomain,dc=org" -W -f <template_file>

Note: If you didn't install the SSL sertificates, you may disable security check and use the -x switch.

Creating new users

Next step is to create users. The following attributes need to be set for the NSS module to work.

gidNumber - the respective group also has to be set

There's a handy package called ldapscripts (in Debian - on Gentoo the package exists in the layman portage overlay sunrise) with which adding users to LDAP is similar to creating POSIX accounts.

Edit /etc/ldapscripts/ldapscripts.conf. On Gentoo, the package installation didn't initialize the LDAP database for you, thus you need to manually run (with slapd running):


Add a new user:

ldapadduser newuser users

which will create the minimal structure for the ldapscripts in the database. The users can then change their password with the command:

ldappasswd -x -W -S -D "uid=$(whoami),ou=People,dn=...."

Example LDAP layout LDIF

Here is an example ldif, if you don't want to use migrationtools:

Code: small but complete ldif for testing
dn: dc=myserver,dc=mydomain,dc=org
dc: myLdapServer
objectClass: top
objectClass: domain
objectClass: domainRelatedObject

dn: ou=People,dc=myserver,dc=mydomain,dc=org
ou: People
objectClass: top
objectClass: organizationalUnit
objectClass: domainRelatedObject

dn: ou=Group,dc=myserver,dc=mydomain,dc=org
ou: Group
objectClass: top
objectClass: organizationalUnit
objectClass: domainRelatedObject

dn: cn=users,ou=Group,dc=myserver,dc=mydomain,dc=org
objectClass: posixGroup
objectClass: top
cn: users
userPassword: {crypt}x
gidNumber: 100

Add the schema:

ldapadd -x -D "cn=admin," -W -f test.ldif

Remove the test user:

ldapdelete "uid=myuser,ou=People," -x -D "cn=admin," -W

If you defined a BASE, you can leave off the base definition here, and use a plain comma instead.

Set desired username and uid (I'm using uid == 1000 + lastipoctet). You will be able to set initial password to the user using phpldapadmin. New users can be copied from the existing one via phpldapadmin. Pay attention at the host field - it specifies list of hosts where this user is allowed to login.

Now you can start adding sudo rules with almost the same format as /etc/sudoers:

Code: SUDO entry
dn: cn=iced,ou=sudoers,dc=iowg
cn: iced
sudoCommand: ALL
sudoHost: ALL
sudoUser: iced
objectClass: sudoRole
objectClass: top

Note: You can add sudoOption: !authenticate if you wish to allow a user to use sudo without secondary authentication, however this is not recommended for any entry which grants root privileges.


Some setup is necessary on client side (including server itself). Some packages for start:

emerge pam_ldap nss_ldap openldap


You should have a file called /etc/openldap/ldap.conf. This file tells the client programs from the openldap package (ldapsearch, ldapadd, ...) which server it should connect to. Don't confuse this one with /etc/ldap.conf (/etc/libnss-ldap.conf) which is for the pam_ldap and nss_ldap packages from

Here we use TLS in a standard LDAP port. LDAP is a standard, and not less secure given that TLS is configured properly. The client and server establish TLS before any LDAP messages are transferred (without a Start TLS operation). The LDAPS connection must be closed upon TLS closure.

This file configures the NSS/PAM modules:

File: /etc/ldap.conf or /etc/libnss-ldap.conf
uri   ldap://
base  dc=mydomain,dc=org

ldap_version 3
ssl on
ssl start_tls
rootbinddn cn=admin,dc=...
scope sub
bind_policy soft

TODO: add definition for binduser

pam_password exop

pam_filter objectclass=posixAccount
pam_login_attribute uid
pam_member_attribute memberUid
pam_check_host_attr yes

nss_base_passwd ou=users,dc=...
nss_base_shadow ou=users,dc=...
nss_base_group  ou=groups,dc=...

Bind_policy is necessary to be set to 'soft' to prevent system boot failure due to udev looking for ldap server before network startup.

Modify your /etc/pamd.d/system-auth file to use ldap too so that all other files including it use ldap. This enables for example kdm,login and sshd to use ldap. With following construction you can avoid problems with duplicated accounts in ldap, and system files.

File: /etc/pam.d/system-auth

auth    required
auth    [success=ignore default=1]
auth    [success=done new_authtok_reqd=done default=1] likeauth nullok try_first_pass
auth    sufficient try_first_pass
auth    required

account    sufficient
account    sufficient

password   required difok=2 minlen=8 dcredit=2 ocredit=2 retry=3
password   sufficient nullok md5 shadow use_authtok
password   sufficient use_authtok
password   required

session    required
session    required
#Creates the home directories if they do not exist
session    required skel=/etc/skel/ umask=0022
session    optional

Enable LDAP searches for the NSS module:

File: /etc/nsswitch.conf
passwd:      compat db ldap
shadow:      compat db ldap
group:       compat db ldap
Note: There is a problem with nss_ldap > 239-r1 and portage. Be sure to perform a echo ">sys-auth/nss_ldap-239-r1" >> /etc/portage/package.mask and update nss_ldap before changing nsswitch.conf

For SUDO configuration, gentoo uses /etc/ldap.conf.sudo. Be sure to configure this file, otherwise you'll end up ripping out your hair for some time like i did....

Emerge package sudo with USE flag ldap, if you want file ldap.conf.sudo installed.

File: /etc/ldap.conf.sudo
# See ldap.conf(5) and README.LDAP for details
# This file should only be readable by root

# supported directives: host, port, ssl, ldap_version
# uri, binddn, bindpw, sudoers_base, sudoers_debug
# tls_{checkpeer,cacertfile,cacertdir,randfile,ciphers,cert,key}

suffix dc=mydomain,dc=org
sudoers_base ou=sudoers,dc=mydomain,dc=org

Using offline authentication

To use offline authentication for ldap users, in case if server is down, or if you are using laptop out of network, it is needed to install in your client station:

# emerge sys-libs/nss-db sys-auth/nss_updatedb sys-auth/pam_ccreds

Some of these packages you can find in swegener overlay.

Then change configuration files:

Set nsswitch.conf to use system files, then ldap, and then if cannot use ldap, local copy of ldap base in db.

File: /etc/nsswitch.conf
passwd: files ldap [NOTFOUND=return] db
shadow: files ldap [NOTFOUND=return] db
group:  files ldap [NOTFOUND=return] db

Set system auth to use pam_unix for local users, or ldap/copy of passwords for LDAP users. There is a restriction for LDAP uids, all users with uid > 10000 are assumed as LDAP users.

File: /etc/pam.d/system-auth

auth    required
auth    [success=ignore default=1]
auth    [success=done new_authtok_reqd=done default=die] likeauth nullok shadow
auth    [authinfo_unavail=1 success=ignore default=2]
auth    [default=done] action=store use_first_pass
auth    [success=done default=die] action=validate use_first_pass
auth    [default=ignore] Delete cached password
auth    [default=bad] action=update
auth    required

account [authinfo_unavail=ignore user_unknown=ignore default=done]
account sufficient
account [success=ignore default=1] uid > 10000
account [authinfo_unavail=ignore default=done]
account sufficient

password    required difok=2 minlen=8 dcredit=2 ocredit=2 try_first_pass retry=3
password    sufficient nullok use_authtok shadow md5 try_first_pass
password    sufficient use_authtok use_first_pass
password    required

session required
session required
session required skel=/etc/skel/ umask=0066
session optional

The last step is regular update of local copy of ldap base. It can be performed using cron job, for example using following file:

File: /etc/cron.daily/nss_updatedb
/usr/sbin/nss_updatedb ldap

Administration GUIs

Now it's time to step out from the command line and text-based editors for a while, and install a nice administration GUI for the LDAP.

Fedora directory server


Luma is a nice-and-simple LDAP browser that can delete nodes and change attributes, but can't create new entries. Very easy to setup and looks quite attractive.


JXplorer is an LDAP-Browser written in Java. It is available for a lot of operating systems, including Linux, Windows and MacOS.

It is a pity, that it does not support {crypt} encryption, so you have to use another LDAP-Tool if you have to reset a user password, but apart from this fact it is one of the best browsers.


A good choice is phpldapadmin. The Apache configuration is beyond the scope of this document. The default configuration is just OK so go to the http://localhost/phpldapadmin/ and login using the admin account.

If you started phpldapadmin before adding the sudo schema, delete all php sessions (phpldapadmin stores all schema in session and is not smart enough to reload it) and import following ldif:

Code: SUDO ldif
dn: ou=sudoers,dc=....
ou: sudoers
objectClass: organizationalUnit
objectClass: top

Apache Directory Studio

Excellent full featured open source ldap manager, versions available for Windows, Linux & OSX and can also connect to MS AD:

See also

Retrieved from ""

Last modified: Fri, 26 Sep 2008 08:44:00 +0000 Hits: 74,866