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 -days
365
-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 -days
365
-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 -days
365
-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 -days
365
-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 olcPasswordHash
Another 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+lrQZILpiUdf16Z9KmDmSwT77Dj4U
The 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 eq
This 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.ldif
dn: 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:
#
cat
dn: 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>.