Skip to content
Permalink
Browse files

more cleanups and split authentication into its own page

  • Loading branch information
alandekok committed Aug 27, 2019
1 parent 92abaa7 commit 26d91fbb4832e2411528a82d18d431c03984ea8a
@@ -5,6 +5,9 @@
*** 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]
@@ -39,70 +39,55 @@ following recommendations for LDAP "best practices" security.

* 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

@@ -0,0 +1,104 @@
= 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.

0 comments on commit 26d91fb

Please sign in to comment.
You can’t perform that action at this time.