H3: SASL method
-The LDAP {{TERM:SASL}} method allows use of any SASL authentication
-mechanism. The {{SECT:Using SASL}} discusses use of SASL.
+The LDAP {{TERM:SASL}} method allows the use of any SASL authentication
+mechanism. The {{SECT:Using SASL}} section discusses the use of SASL.
+
+H2: 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 {{EX:DIGEST-MD5}}.
+
+H3: 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
+
+H3: 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 {{EX: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.
+
+H3: 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.
+
+H3: 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=
+
+H3: 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=
+
+H3: 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
+
+H3: 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.
+
+H3: 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).
+
+H2: 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 {{EX:--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.
+
+
+H3: 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
+{{EX:/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 {{EX: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
+
+H3: 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 {{EX: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 {{EX: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.
+
+H3: 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.