13. Security Considerations
OpenLDAP Software is designed to run in a wide variety of computing environments from tightly-controlled closed networks to the global Internet. Hence, OpenLDAP Software supports many different security mechanisms. This chapter describes these mechanisms and discusses security considerations for using OpenLDAP Software.
13.1. Network Security
13.1.1. Selective Listening
By default, slapd(8) will listen on both the IPv4 and IPv6 "any" addresses. It is often desirable to have slapd listen on select address/port pairs. For example, listening only on the IPv4 address 127.0.0.1 will disallow remote access to the directory server. E.g.:
slapd -h ldap://127.0.0.1
While the server can be configured to listen on a particular interface address, this doesn't necessarily restrict access to the server to only those networks accessible via that interface. To selective restrict remote access, it is recommend that an IP Firewall be used to restrict access.
See
13.1.2. IP Firewall
Generally, slapd(8) listens on port 389/tcp for ldap:// sessions and port 636/tcp for ldaps://) sessions. slapd(8) may be configured to listen on other ports.
As specifics of how to configure IP firewall are dependent on the particular kind of IP firewall used, no examples are provided here. See the document associated with your IP firewall.
13.1.3. TCP Wrappers
slapd(8) supports
slapd: 10.0.0.0/255.0.0.0 127.0.0.1 : ALLOW slapd: ALL : DENY
allows only incoming connections from the private network 10.0.0.0 and localhost (127.0.0.1) to access the directory service. Note that IP addresses are used as slapd(8) is not normally configured to perform reverse lookups.
It is noted that TCP wrappers require the connection to be accepted. As significant processing is required just to deny a connection, it is generally advised that IP firewall protection be used instead of TCP wrappers.
See hosts_access(5) for more information on TCP wrapper rules.
13.2. Data Integrity and Confidentiality Protection
A number of
13.2.1. Security Strength Factors
The server uses
A number of administrative controls rely on SSFs associated with TLS and SASL protection in place on an LDAP session.
security controls disallow operations when appropriate protections are not in place. For example:
security ssf=1 update_ssf=112
requires integrity protection for all operations and encryption protection, 3DES equivalent, for update operations (e.g. add, delete, modify, etc.). See slapd.conf(5) for details.
For fine-grained control, SSFs may be used in access controls. See
13.3. Authentication Methods
13.3.1. "simple" method
The LDAP "simple" method has three modes of operation:
- anonymous,
- unauthenticated, and
- user/password authenticated.
Anonymous access is requested by providing no name and no password to the "simple" bind operation. Unauthenticated access is requested by providing a name but no password. Authenticated access is requested by providing a valid name and password.
An anonymous bind results in an anonymous authorization association. Anonymous bind mechanism is enabled by default, but can be disabled by specifying "disallow bind_anon" in slapd.conf(5). Note that disabling the anonymous bind mechanism does not prevent anonymous access to the directory. To require authentication to access the directory, one should instead specify "require authc".
An unauthenticated bind also results in an anonymous authorization association. Unauthenticated bind mechanism is disabled by default, but can be enabled by specifying "allow bind_anon_cred" in slapd.conf(5). As a number of LDAP applications mistakenly generate unauthenticated bind request when authenticated access was intended (that is, they do not ensure a password was provided), this mechanism should generally remain disabled.
A successful user/password authenticated bind results in a user authorization identity, the provided name, being associated with the session. User/password authenticated bind is enabled by default. However, as this mechanism itself offers no eavesdropping protection (e.g., the password is set in the clear), it is recommended that it be used only in tightly controlled systems or when the LDAP session is protected by other means (e.g., TLS,
The user/password authenticated bind mechanism can be completely disabled by setting "disallow bind_simple".
Note: An unsuccessful bind always results in the session having an anonymous authorization association.
13.3.2. SASL method
The LDAP
13.4. Password Storage
LDAP passwords are normally stored in the userPassword attribute. RFC4519 specifies that passwords are not stored in encrypted form, but this can create an unwanted security exposure so slapd provides several options for the administrator to choose from.
The userPassword attribute is allowed to have more than one value, and it is possible for each value to be stored in a different form. During authentication, slapd will iterate through the values until it finds one that matches the offered password or until it runs out of values to inspect. The storage scheme is stored as a prefix on the value, so a Unix crypt-style password might look like this:
userPassword: {CRYPT}.7D8U/PCF00Hw
In general is is safest to store passwords in a salted hashed format like SSHA. This makes it very hard for an attacker to derive passwords from stolen backups or by obtaining access to the on-disk slapd database.
The disadvantage of hashed storage is that it prevents the use of some authentication mechanisms such as DIGEST-MD5.
13.4.1. CLEARTEXT password storage scheme
Cleartext passwords can be stored directly in the userPassword attribute, or can have the '{CLEARTEXT}' prefix. These two values are equivalent:
userPassword: secret userPassword: {CLEARTEXT}secret
13.4.2. CRYPT password storage scheme
This scheme uses the operating system's crypt(3) hash function. It normally produces the traditional Unix-style 13 character hash, but on systems with glibc2 it can also generate the more secure 34-byte MD5 hash.
userPassword: {CRYPT}aUihad99hmev6 userPassword: {CRYPT}$1$czBJdDqS$TmkzUAb836oMxg/BmIwN.1
The advantage of the CRYPT scheme is that passwords can be transferred to or from an existing Unix password file without having to know the cleartext form. Both forms of crypt include salt so they have some resistance to dictionary attacks.
13.4.3. MD5 password storage scheme
This scheme simply takes the MD5 hash of the password and stores it in base64 encoded form:
userPassword: {MD5}Xr4ilOzQ4PCOq3aQ0qbuaQ==
Although safer than cleartext storage, this is not a very secure scheme. The MD5 algorithm is fast, and because there is no salt the scheme is vulnerable to a dictionary attack.
13.4.4. SMD5 password storage scheme
This improves on the basic MD5 scheme by adding salt (random data which means that there are many possible representations of a given plaintext password). For example, both of these values represent the same password:
userPassword: {SMD5}4QWGWZpj9GCmfuqEvm8HtZhZS6E= userPassword: {SMD5}g2/J/7D5EO6+oPdklp5p8YtNFk4=
13.4.5. SHA password storage scheme
Like the MD5 scheme, this simply feeds the password through an SHA hash process. SHA is thought to be more secure than MD5, but the lack of salt leaves the scheme exposed to dictionary attacks.
userPassword: {SHA}5en6G6MezRroT3XKqkdPOmY/BfQ=
13.4.6. SSHA password storage scheme
This is the salted version of the SHA scheme. It is believed to be the most secure password storage sheme supported by slapd.
These values represent the same password:
userPassword: {SSHA}DkMTwBl+a/3DQTxCYEApdUtNXGgdUac3 userPassword: {SSHA}d0Q0626PSH9VUld7yWpR0k6BlpQmtczb
13.4.7. SASL password storage scheme
This is not really a password storage scheme at all. It uses the value of the userPassword attribute to delegate password verification to another process. See below for more information.
Note that this is not the same as using SASL to authenticate the LDAP session.
13.4.8. KERBEROS password storage scheme
This is not really a password storage scheme at all. It uses the value of the userPassword attribute to delegate password verification to Kerberos. Note that this is not the same as using Kerberos authentication of the LDAP session. This scheme could be said to defeat the advantages of Kerberos by causing the Kerberos password to be exposed to the slapd server (and possibly on the network as well).
13.5. Pass-Through authentication
Since OpenLDAP 2.0 slapd has had the ability to delegate password verification to a separate process. This uses the sasl_checkpass(3) function so it can use any back-end server that Cyrus SASL supports for checking passwords. The choice is very wide, as one option is to use saslauthd(8) which in turn can use local files, Kerberos, an IMAP server, another LDAP server, or anything supported by the PAM mechanism.
The server must be built with the --enable-spasswd configuration option to enable pass-through authentication.
Note that this is not the same as using a SASL mechanism to authenticate the LDAP session. Pass-Through authentication works only with plaintext passwords, as used in the "simple bind" and "SASL PLAIN" authentication mechanisms.
Pass-Through authentication is selective: it only affects users whose userPassword attribute has a value marked with the "{SASL}" scheme. The format of the attribute is:
userPassword: {SASL}username@realm
The username and realm are passed to the SASL authentication mechanism and are used to identify the account whose password is to be verified. This allows arbitrary mapping between entries in OpenLDAP and accounts known to the backend authentication service.
Note that there is no support for changing passwords in the backend via slapd. It would be wise to use access control to prevent users from changing their passwords through LDAP where they have pass-through authentication enabled.
13.5.1. Configuring slapd to use an authentication provider
Where an entry has a "{SASL}" password value, OpenLDAP delegates the whole process of validating that entry's password to Cyrus SASL. All the configuration is therefore done in SASL config files.
The first file to be considered is confusingly named slapd.conf and is typically found in the SASL library directory, often /usr/lib/sasl2/slapd.conf This file governs the use of SASL when talking LDAP to slapd as well as the use of SASL backends for pass-through authentication. See options.html in the Cyrus SASL docs for full details. Here is a simple example for a server that will use saslauthd to verify passwords:
mech_list: plain pwcheck_method: saslauthd saslauthd_path: /var/run/sasl2/mux
13.5.2. Configuring saslauthd
saslauthd is capable of using many different authentication services: see saslauthd(8) for details. A common requirement is to delegate some or all authentication to another LDAP server. Here is a sample saslauthd.conf that uses AD:
ldap_servers: ldap://dc1.example.com/ ldap://dc2.example.com/ ldap_search_base: cn=Users,DC=ad,DC=example,DC=com ldap_filter: (userPrincipalName=%u) ldap_bind_dn: cn=saslauthd,cn=Users,DC=ad,DC=example,DC=com ldap_password: secret
In this case, saslauthd is run with the ldap authentication mechanism and is set to combine the SASL realm with the login name:
saslauthd -a ldap -r
This means that the "username@realm" string from the userPassword attribute ends up being used to search AD for "userPrincipalName=username@realm" - the password is then verified by attempting to bind to AD using the entry found by the search and the password supplied by the LDAP client.
13.5.3. Testing pass-through authentication
It is usually best to start with the back-end authentication provider and work through saslauthd and slapd towards the LDAP client.
In the AD example above, first check that the DN and password that saslauthd will use when it connects to AD are valid:
ldapsearch -x -H ldap://dc1.example.com/ \ -D cn=saslauthd,cn=Users,DC=ad,DC=example,DC=com \ -w secret \ -b '' \ -s base
Next check that a sample AD user can be found:
ldapsearch -x -H ldap://dc1.example.com/ \ -D cn=saslauthd,cn=Users,DC=ad,DC=example,DC=com \ -w secret \ -b cn=Users,DC=ad,DC=example,DC=com \ "(userPrincipalName=user@ad.example.com)"
Check that the user can bind to AD:
ldapsearch -x -H ldap://dc1.example.com/ \ -D cn=user,cn=Users,DC=ad,DC=example,DC=com \ -w userpassword \ -b cn=user,cn=Users,DC=ad,DC=example,DC=com \ -s base \ "(objectclass=*)"
If all that works then saslauthd should be able to do the same:
testsaslauthd -u user@ad.example.com -p userpassword testsaslauthd -u user@ad.example.com -p wrongpassword
Now put the magic token into an entry in OpenLDAP:
userPassword: {SASL}user@ad.example.com
It should now be possible to bind to OpenLDAP using the DN of that entry and the password of the AD user.