*** xref:modules/expiration.adoc[Expiration]
*** xref:modules/krb5.adoc[Krb5]
*** xref:modules/ldap.adoc[LDAP]
+**** xref:modules/ldap_docker.adoc[Docker]
+**** xref:modules/ldap_search.adoc[Testing with ldapsearch]
+**** xref:modules/ldap_authentication.adoc[Authenticating Users with LDAP]
*** xref:modules/mschap.adoc[MS-CHAP]
*** xref:modules/pam.adoc[PAM]
*** xref:modules/passwd.adoc[Passwd]
* Create a dedicated account for use by FreeRADIUS
-* Ensure that this account is a not an administrator
+* Ensure that this account does not have administrator access
* Ensure that this account is read-only, and has no write permissions
-* Start by using 'simple authentication' (instead of
- https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer[SASL]
- SASL should be attempted only after 'simple authentication' has been
- verified to wrork.
+* Start by using 'simple authentication' instead of
+ https://en.wikipedia.org/wiki/Simple_Authentication_and_Security_Layer[SASL].
+ The SASL protocol should be attempted only after 'simple
+ authentication' has been verified to work.
* Use TLS for connecting between FreeRADIUS and the LDAP server. See
- the `tls` sub-section of the default `ldap` module.
+ the `tls` sub-section of the default `ldap` module for instructions
* When storing RADIUS user profiles (quotas, `Simultaneous-Use` flags,
-access time restrictions, etc) in LDAP, the LDAP schema
-`doc/schemas/ldap/openldap/freeradius.schema` must be imported first
-into the LDAP server.
-
-=== Authentication
-
-There are several authentication flows you can use depending on your environment:
-
- * user attempts to authenticate sending a plaintext password (ie. PAP or EAP-TTLS/PAP)
- ** FreeRADIUS reads and uses the LDAP `userPassword` (or `ntPassword`) attributes to perform authentication against; `userPassword` may be hashed (recommended at https://openldap.org/doc/admin24/security.html#Password%20Storage[least using SSHA])
- ** you can attempt to LDAP bind as that user; this is possibly slower than the `userPassword` method
- * user attempts to authenticate sending a hashed password (ie. MSCHAPv2 or EAP-{PEAP,TTLS}/MSCHAPv2)
- ** FreeRADIUS reads and uses the LDAP `userPassword` attribute which *must* contain a plaintext password
- ** if MSCHAPv2 is being used, you need to store and make available an LDAP `ntPassword` attribute in the user object
-
-These are technical limitations not of FreeRADIUS but in the components required to be able to authenticate any user.
-
-Picking up from where we left off with the `ldapsearch` test above, if `userPassword` is returned:
-
- * if the value is not prepended with `{...}`
- ** your LDAP server stores plaintext passwords
- ** provides the greatest flexibility to use MSCHAPv2 and other hashing authentication mechanisms in your RADIUS packets
- * if the value is prepended with `{...}` (for example `{SSHA}`)
- ** you *must* use PAP (or EAP-TTLS/PAP) in your RADIUS packets to authenticate your users
-
-*N.B.* LDAP attribute names (such as `userPassword`) may be appended
-with `::` (two colons rather than one) to indicate a binary value and
-the value will be the https://en.wikipedia.org/wiki/Base64[base64]
-representation of the actual value, which you can decode using
-`printf "%s" "VALUE" | base64 -d` to inspect
-
-If `userPassword` is not returned then permissions for the credentials
-used need to be adjusted so that it is accessible. If this is not
-feasible and/or possible you *must* use PAP (or EAP-TTLS/PAP) in your
-RADIUS packets so that you can use an LDAP bind to authenticate your
-users.
-
-You may notice that by using PAP (or EAP-TTLS/PAP) in your RADIUS
-requests will work will all LDAP environments regardless of how
-passwords have been stored.
-
-You will need to balance the implications of sending RADIUS packets
-containing plaintext passwords (though EAP-TTLS/PAP makes the risk
-similar to HTTPS) over the wire with, or in addition to, storing
-plaintext passwords in LDAP.
-
-Ultimately the decision is yours though it may have already been
-decided by your LDAP administrator. If the LDAP `userPassword`
-attribute is unavailable or does not contain a plaintext password you
-have no option but to use PAP (or EAP-TTLS/PAP) in your RADIUS
-requests.
+ access time restrictions, etc) in LDAP, the LDAP schema
+ `doc/schemas/ldap/openldap/freeradius.schema` must first be imported
+ into the LDAP server.
+
+== Authentication
+
+The LDAP module can be used by FreeRADIUS to read passwords order to
+xref:modules/ldap_authentication.adoc[authenticate] users. Please be
+aware the FreeRADIUS is an _authentication server_, and LDAP is a
+_database_. This separation of roles means that FreeRADIUS supports
+multiple kinds of authentication protocols such as `PAP`, `CHAP`,
+`MS-CHAP`, etc. An LDAP database supports only one authentication
+method: "bind as user". This authentication method is compatible only
+with PAP.
+
+Our recommendation is to use LDAP as a database. FreeRADIUS should
+read the "known good" password from LDAP, and then use that
+information to authenticate the user. It is almost always wrong to
+use the LDAP "bind as user" method for authenticating users.
+
+The only caveat to the above recommendation is Active Directory. For
+"security" reasons, Active Directory will not return the "known good"
+password to FreeRADIUS over a standard LDAP query. Therefore when
+Active Directory is used, the choices are:
+
+PAP::
+Use "bind as user"
+
+MS-CHAP::
+Use xref:raddb:mods-available/ntlm_auth.adoc[`ntlm`] or xref:raddb:mods-available/winbind.adoc[`winbind`].
+
+Due to the limitations of Active Directory, There are unfortunately no
+other possible choices.
+
+Please see the xref:modules/ldap_authentication.adoc[LDAP
+authentication] page for more information on authenticating users with LDAP.
=== Authorization
--- /dev/null
+= Authenticating Users with LDAP
+
+The LDAP module supports a few different kinds of authentication
+flows.
+
+PAP::
+The user supplies a `User-Password` (plaintext or EAP-TTLS/PAP)
++
+FreeRADIUS reads the "known good" password from LDAP, and compares
+that to what the user entered.
+
+Bind as user::
+The user supplies a `User-Password` (plaintext or EAP-TTLS/PAP)
++
+FreeRADIUS uses that password to "bind as the user" to LDAP, using the
+supplied `User-Name` and `User-Password. If the bind is successfull,
+the user is authenticated. Otherwise, authentication fails.
+
+CHAP::
+The user supplies a `CHAP` password attribute/
++
+FreeRADIUS reads the "known good" password from LDAP in cleartext, and
+compares that to what the user entered.
+
+MS-CHAP::
+The user supplies a `MS-CHAP` password attribute.
++
+FreeRADIUS reads the "known good" password from LDAP in cleartext, or
+as an NT hash, and compares that to what the user entered.
+
+== Caveats
+
+There are some major caveats with the above authentication flows. The
+first is that we *strongly recommend* against using "bind as user".
+This process is slow, and causes unnecessary churn in the connections
+used to contact the LDAP server. Further, the "bind as user" process
+works _only_ when a `User-Password attribute exists in the request.
+If any other authentication type is used in the request, then the
+"bind as user" _will not work_. There is no amount of "fixing" things
+or configuration changes which will make it work.
+
+The second caveat is that the `CHAP` authentication type works _only_
+when a "clear text" password is stored in the LDAP database. The
+`CHAP` calclulations are designed around having access to the "clear
+text" password. It is impossible to use any "encrypted" or "hashed"
+passwords with `CHAP`.
+
+The third caveat is that the `MS-CHAP` authentication type works
+_only_ when a "clear text" password or "NT hashed" passwords which are
+stored in the LDAP database. The `MS-CHAP` calclulations are designed
+around having access to "known good" passwords in those formats. It
+is impossible to use any other kind of "encrypted" or "hashed"
+passwords with `MS-CHAP`.
+
+The final caveat is that when the LDAP database contains "encrypted"
+or "hashed" passwords, the _only_ authentication type which is
+compatible with those passwords is PAP. i.e. when the `User-Password`
+is supplied to FreeRADIUS.
+
+For recommendations on password storage in LDAP, please see the LDAP
+https://openldap.org/doc/admin24/security.html#Password%20Storage[password
+storage] page. Please note that the recommendations there are made
+for LDAP security, and pay no attention to the caveats described
+above. When both RADIUS and LDAP are used together, then the
+requirements of _both_ systems must be met in order for them to work
+together. In many cases, a naive approach to LDAP security will
+prevent RADIUS from working. In those cases, the only solutions are
+to give up on using RADIUS, or to relax the security requirements on
+LDAP.
+
+Picking up from where we left off with the `ldapsearch` test above, if `userPassword` is returned:
+
+ * if the value is not prepended with `{...}`
+ ** your LDAP server stores plaintext passwords
+ ** provides the greatest flexibility to use MSCHAPv2 and other hashing authentication mechanisms in your RADIUS packets
+ * if the value is prepended with `{...}` (for example `{SSHA}`)
+ ** you *must* use PAP (or EAP-TTLS/PAP) in your RADIUS packets to authenticate your users
+
+*N.B.* LDAP attribute names (such as `userPassword`) may be appended
+with `::` (two colons rather than one) to indicate a binary value and
+the value will be the https://en.wikipedia.org/wiki/Base64[base64]
+representation of the actual value, which you can decode using
+`printf "%s" "VALUE" | base64 -d` to inspect
+
+If `userPassword` is not returned then permissions for the credentials
+used need to be adjusted so that it is accessible. If this is not
+feasible and/or possible you *must* use PAP (or EAP-TTLS/PAP) in your
+RADIUS packets so that you can use an LDAP bind to authenticate your
+users.
+
+You may notice that by using PAP (or EAP-TTLS/PAP) in your RADIUS
+requests will work will all LDAP environments regardless of how
+passwords have been stored.
+
+You will need to balance the implications of sending RADIUS packets
+containing plaintext passwords (though EAP-TTLS/PAP makes the risk
+similar to HTTPS) over the wire with, or in addition to, storing
+plaintext passwords in LDAP.
+
+Ultimately the decision is yours though it may have already been
+decided by your LDAP administrator. If the LDAP `userPassword`
+attribute is unavailable or does not contain a plaintext password you
+have no option but to use PAP (or EAP-TTLS/PAP) in your RADIUS
+requests.