The Lightweight Directory Access Protocol (LDAP) is an application layer protocol used to access, modify, and authenticate objects using a distributed directory information service. Think of it as a phone or record book which stores several levels of hierarchical, homogeneous information. It is used in Active Directory and OpenLDAP networks and allows users to access to several levels of internal information utilizing a single account. For example, email authentication, pulling employee contact information, and internal website authentication might all make use of a single user account in the LDAP server's record base.
This section provides a quick start guide for configuring an LDAP server on a FreeBSD system. It assumes that the administrator already has a design plan which includes the type of information to store, what that information will be used for, which users should have access to that information, and how to secure this information from unauthorized access.
LDAP uses several terms which should be understood before starting the configuration. All directory entries consist of a group of attributes. Each of these attribute sets contains a unique identifier known as a Distinguished Name (DN) which is normally built from several other attributes such as the common or Relative Distinguished Name (RDN). Similar to how directories have absolute and relative paths, consider a DN as an absolute path and the RDN as the relative path.
An example LDAP entry looks like the
following. This example searches for the entry for the
specified user account (uid),
organizational unit (ou), and organization
(o):
%ldapsearch -xb "uid=# extended LDIF # # LDAPv3 # base <uid=trhodes,ou=users,o=example.com> with scope subtree # filter: (objectclass=*) # requesting: ALL # # trhodes, users, example.com dn: uid=trhodes,ou=users,o=example.com mail: trhodes@example.com cn: Tom Rhodes uid: trhodes telephoneNumber: (123) 456-7890 # search result search: 2 result: 0 Success # numResponses: 2 # numEntries: 1trhodes,ou=users,o=example.com"
This example entry shows the values for the
dn, mail,
cn, uid, and
telephoneNumber attributes. The
cn attribute is the
RDN.
More information about LDAP and its
terminology can be found at http://www.openldap.org/doc/admin24/intro.html.
FreeBSD does not provide a built-in LDAP server. Begin the configuration by installing net/openldap-server package or port:
#pkg install openldap-server
There is a large set of default options enabled in the
package. Review them by running
pkg info openldap-server. If they are not
sufficient (for example if SQL support is needed), please
consider recompiling the port using the appropriate framework.
The installation creates the directory
/var/db/openldap-data to hold the data.
The directory to store the certificates must be
created:
#mkdir /usr/local/etc/openldap/private
The next phase is to configure the Certificate Authority.
The following commands must be executed from
/usr/local/etc/openldap/private. This is
important as the file permissions need to be restrictive and
users should not have access to these files. More detailed
information about certificates and their parameters can be
found in Section 13.6, “OpenSSL”. To create the
Certificate Authority, start with this command and follow the
prompts:
#openssl req -days365-nodes -new -x509 -keyout ca.key -out ../ca.crt
The entries for the prompts may be generic
except for the
Common Name. This entry must be
different than the system hostname. If
this will be a self signed certificate, prefix the hostname
with CA for Certificate Authority.
The next task is to create a certificate signing request and a private key. Input this command and follow the prompts:
#openssl req -days365-nodes -new -keyout server.key -out server.csr
During the certificate generation process, be sure to
correctly set the Common Name attribute.
The Certificate Signing Request must be signed with the
Certificate Authority in order to be used as a valid
certificate:
#openssl x509 -req -days365-in server.csr -out ../server.crt -CA ../ca.crt -CAkey ca.key -CAcreateserial
The final part of the certificate generation process is to generate and sign the client certificates:
#openssl req -days365-nodes -new -keyout client.key -out client.csr#openssl x509 -req -days 3650 -in client.csr -out ../client.crt -CA ../ca.crt -CAkey ca.key
Remember to use the same Common Name
attribute when prompted. When finished, ensure that a total
of eight (8) new files have been generated through the
proceeding commands.
The daemon running the OpenLDAP server is
slapd. Its configuration is performed
through slapd.ldif: the old
slapd.conf has been deprecated by
OpenLDAP.
Configuration
examples for slapd.ldif are
available and can also be found in
/usr/local/etc/openldap/slapd.ldif.sample.
Options are documented in slapd-config(5). Each section
of slapd.ldif, like all the other LDAP
attribute sets, is uniquely identified through a DN. Be sure
that no blank lines are left between the
dn: statement and the desired end of the
section. In the following example, TLS will be used to
implement a secure channel. The first section represents the
global configuration:
# # See slapd-config(5) for details on configuration options. # This file should NOT be world readable. # dn: cn=config objectClass: olcGlobal cn: config # # # Define global ACLs to disable default read access. # olcArgsFile: /var/run/openldap/slapd.args olcPidFile: /var/run/openldap/slapd.pid olcTLSCertificateFile: /usr/local/etc/openldap/server.crt olcTLSCertificateKeyFile: /usr/local/etc/openldap/private/server.key olcTLSCACertificateFile: /usr/local/etc/openldap/ca.crt #olcTLSCipherSuite: HIGH olcTLSProtocolMin: 3.1 olcTLSVerifyClient: never
The Certificate Authority, server certificate and server
private key files must be specified here. It is recommended
to let the clients choose the security cipher and omit option
olcTLSCipherSuite (incompatible with TLS
clients other than openssl). Option
olcTLSProtocolMin lets the server require a
minimum security level: it is recommended. While
verification is mandatory for the server, it is not for the
client: olcTLSVerifyClient: never.
The second section is about the backend modules and can be configured as follows:
# # Load dynamic backend modules: # dn: cn=module,cn=config objectClass: olcModuleList cn: module olcModulepath: /usr/local/libexec/openldap olcModuleload: back_mdb.la #olcModuleload: back_bdb.la #olcModuleload: back_hdb.la #olcModuleload: back_ldap.la #olcModuleload: back_passwd.la #olcModuleload: back_shell.la
The third section is devoted to load the needed
ldif schemas to be used by the databases:
they are essential.
dn: cn=schema,cn=config objectClass: olcSchemaConfig cn: schema include: file:///usr/local/etc/openldap/schema/core.ldif include: file:///usr/local/etc/openldap/schema/cosine.ldif include: file:///usr/local/etc/openldap/schema/inetorgperson.ldif include: file:///usr/local/etc/openldap/schema/nis.ldif
Next, the frontend configuration section:
# Frontend settings
#
dn: olcDatabase={-1}frontend,cn=config
objectClass: olcDatabaseConfig
objectClass: olcFrontendConfig
olcDatabase: {-1}frontend
olcAccess: to * by * read
#
# Sample global access control policy:
# Root DSE: allow anyone to read it
# Subschema (sub)entry DSE: allow anyone to read it
# Other DSEs:
# Allow self write access
# Allow authenticated users read access
# Allow anonymous users to authenticate
#
#olcAccess: to dn.base="" by * read
#olcAccess: to dn.base="cn=Subschema" by * read
#olcAccess: to *
# by self write
# by users read
# by anonymous auth
#
# if no access controls are present, the default policy
# allows anyone and everyone to read anything but restricts
# updates to rootdn. (e.g., "access to * by * read")
#
# rootdn can always read and write EVERYTHING!
#
olcPasswordHash: {SSHA}
# {SSHA} is already the default for olcPasswordHashAnother section is devoted to the configuration backend, the only way to later access the OpenLDAP server configuration is as a global super-user.
dn: olcDatabase={0}config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: {0}config
olcAccess: to * by * none
olcRootPW: {SSHA}iae+lrQZILpiUdf16Z9KmDmSwT77Dj4UThe default administrator username is
cn=config. Type
slappasswd in a shell, choose a password
and use its hash in olcRootPW. If this
option is not specified now, before
slapd.ldif is imported, no one will be
later able to modify the
global configuration section.
The last section is about the database backend:
#######################################################################
# LMDB database definitions
#######################################################################
#
dn: olcDatabase=mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: mdb
olcDbMaxSize: 1073741824
olcSuffix: dc=domain,dc=example
olcRootDN: cn=mdbadmin,dc=domain,dc=example
# Cleartext passwords, especially for the rootdn, should
# be avoided. See slappasswd(8) and slapd-config(5) for details.
# Use of strong authentication encouraged.
olcRootPW: {SSHA}X2wHvIWDk6G76CQyCMS1vDCvtICWgn0+
# The database directory MUST exist prior to running slapd AND
# should only be accessible by the slapd and slap tools.
# Mode 700 recommended.
olcDbDirectory: /var/db/openldap-data
# Indices to maintain
olcDbIndex: objectClass eqThis database hosts the actual
contents of the LDAP
directory. Types other than mdb are
available. Its super-user, not to be confused with the global
one, is configured here: a (possibly custom) username in
olcRootDN and the password hash in
olcRootPW; slappasswd
can be used as before.
This repository
contains four examples of slapd.ldif. To
convert an existing slapd.conf into
slapd.ldif, refer to this
page (please note that this may introduce some
unuseful options).
When the configuration is completed,
slapd.ldif must be placed in an empty
directory. It is recommended to create it as:
#mkdir /usr/local/etc/openldap/slapd.d/
Import the configuration database:
#/usr/local/sbin/slapadd -n0 -F /usr/local/etc/openldap/slapd.d/ -l /usr/local/etc/openldap/slapd.ldif
Start the slapd daemon:
#/usr/local/libexec/slapd -F /usr/local/etc/openldap/slapd.d/
Option -d can be used for debugging,
as specified in slapd(8). To verify that the server is
running and working:
#ldapsearch -x -b '' -s base '(objectclass=*)' namingContexts# extended LDIF # # LDAPv3 # base <> with scope baseObject # filter: (objectclass=*) # requesting: namingContexts # # dn: namingContexts: dc=domain,dc=example # search result search: 2 result: 0 Success # numResponses: 2 # numEntries: 1
The server must still be trusted. If that has never been done before, follow these instructions. Install the OpenSSL package or port:
#pkg install openssl
From the directory where ca.crt is
stored (in this example,
/usr/local/etc/openldap), run:
#c_rehash .
Both the CA and the server certificate are now correctly
recognized in their respective roles. To verify this, run
this command from the server.crt
directory:
#openssl verify -verbose -CApath . server.crt
If slapd was running, restart it. As
stated in /usr/local/etc/rc.d/slapd, to
properly run slapd at boot the
following lines must be added to
/etc/rc.conf:
lapd_enable="YES" slapd_flags='-h "ldapi://%2fvar%2frun%2fopenldap%2fldapi/ ldap://0.0.0.0/"' slapd_sockets="/var/run/openldap/ldapi" slapd_cn_config="YES"
slapd does not provide debugging at
boot. Check /var/log/debug.log,
dmesg -a and
/var/log/messages for this
purpose.
The following example adds the group
team and the user john
to the domain.example
LDAP database, which is still empty.
First, create the file
domain.ldif:
#cat domain.ldifdn: dc=domain,dc=example objectClass: dcObject objectClass: organization o: domain.example dc: domain dn: ou=groups,dc=domain,dc=example objectClass: top objectClass: organizationalunit ou: groups dn: ou=users,dc=domain,dc=example objectClass: top objectClass: organizationalunit ou: users dn: cn=team,ou=groups,dc=domain,dc=example objectClass: top objectClass: posixGroup cn: team gidNumber: 10001 dn: uid=john,ou=users,dc=domain,dc=example objectClass: top objectClass: account objectClass: posixAccount objectClass: shadowAccount cn: John McUser uid: john uidNumber: 10001 gidNumber: 10001 homeDirectory: /home/john/ loginShell: /usr/bin/bash userPassword: secret
See the OpenLDAP documentation for more details. Use
slappasswd to replace the plain text
password secret with a hash in
userPassword. The path specified as
loginShell must exist in all the systems
where john is allowed to login. Finally,
use the mdb administrator to modify the
database:
#ldapadd -W -D "cn=mdbadmin,dc=domain,dc=example" -f domain.ldif
Modifications to the global
configuration section can only be performed by
the global super-user. For example, assume that the option
olcTLSCipherSuite: HIGH:MEDIUM:SSLv3 was
initially specified and must now be deleted. First, create a
file that contains the following:
#catdn: cn=config changetype: modify delete: olcTLSCipherSuiteglobal_mod
Then, apply the modifications:
#ldapmodify -f global_mod -x -D "cn=config" -W
When asked, provide the password chosen in the
configuration backend section. The
username is not required: here, cn=config
represents the DN of the database section to be modified.
Alternatively, use ldapmodify to delete a
single line of the database, ldapdelete to
delete a whole entry.
If something goes wrong, or if the global super-user cannot access the configuration backend, it is possible to delete and re-write the whole configuration:
#rm -rf /usr/local/etc/openldap/slapd.d/
slapd.ldif can then be edited and
imported again. Please, follow this procedure only when no
other solution is available.
This is the configuration of the server only. The same machine can also host an LDAP client, with its own separate configuration.
All FreeBSD documents are available for download at https://download.freebsd.org/ftp/doc/
Questions that are not answered by the
documentation may be
sent to <freebsd-questions@FreeBSD.org>.
Send questions about this document to <freebsd-doc@FreeBSD.org>.