Matt Horan's Blog

FreeRADIUS on FreeBSD and OpenLDAP

Instead of relying on PAM or /etc/passwd for authentication and authorization, I decided to store account information in an OpenLDAP database. Of course I could have used NIS or flat file databases, but OpenLDAP proved to be the best solution for my situation.

sudo portinstall net/openldap23-server

This will install the OpenLDAP 2.3 client and server.

sudo portinstall net/freeradius

This will install the FreeRADIUS server. To enable the LDAP backend, check the LDAP option.

Once FreeRADIUS has finished compiling, OpenLDAP can be configured.

First, the RADIUS LDAP schema must be copied to the OpenLDAP schema directory.

sudo cp /usr/local/share/freeradius/openldap.schema /usr/local/etc/openldap/radius.schema

Next, slapd must be configured.

sudoedit /usr/local/etc/openldap/slapd.conf

The RADIUS schema must be added to the include section. The Cosine schema provides the account objectclass.

include    /usr/local/etc/openldap/schema/core.schema
include    /usr/local/etc/openldap/schema/cosine.schema

You must also configure at least one database backend.

database   bdb
suffix     "dc=matthoran,dc=com"
rootdn     "cn=Manager,dc=matthoran,dc=com"
rootpw     secret
directory  /var/db/openldap-data
index      objectClass eq
index      uid         eq

Indexing the objectclass and uid will speed up LDAP queries.

To enable slapd on FreeBSD, add the following to /etc/rc.conf and run the init script.

slapd_enable="YES"
slapd_flags="-h ldap://127.0.0.1/"
sudo /usr/local/etc/rc.d/slapd start

Note that this will cause slapd to listen on localhost only.

The ldapadd tool is used to add entries to the LDAP database. The ldapmodify command is used to modify entries in the LDAP database. Both tools take a number of arguments as well as an LDIF file.

dn: dc=matthoran,dc=com
objectclass: dcObject
objectclass: organization
o: Matt Horan
dc: matthoran
dn: cn=Manager,dc=matthoran,dc=com
objectclass: organizationalRole
cn: Manager

If not saved to a file, the above could be fed to ldapadd through stdin.

ldapadd -x -D "cn=Manager,dc=matthoran,dc=com" -W base.ldif

The -x flag causes ldapadd to use simple bind instaed of SASL. The -D flag indicates the distinguished name used to connect to the database and the -W flag causes ldapadd to prompt for simple authentication.

Now the first user may be added to the database.

uid=test,dc=matthoran,dc=com
objectclass: account
objectclass: simpleSecurityObject
objectclass: radiusprofile
uid: test
userPassword: {SSHA}53jF+nBYXuouGDSpKNaUIvOkyxCCEsah
ldapadd -x -D "cn=Manager,dc=matthoran,dc=com" -W test.ldif

This will add a user test with password test to the database. The slappasswd command may be used to generate hashed passwords. The default hash algorithm is SSHA and can be changed with the -h flag.

The ldapsearch command may be used to ensure that the above entry was successfully added to the database.

ldapsearch -x -b "dc=matthoran,dc=com" "(uid=test)"

This should return an LDIF identical to the content of test.ldif.

Now that the LDAP database contains a test user, FreeRADIUS can be configured.

Since my FreeRADIUS server is only performing AAA for EAP clients, there are only two parts of the default configuration file that need to be changed. Many of the others can be slimmed down or completely removed.

To get FreeRADIUS to talk to the LDAP server, the following LDAP configuration options must be changed, assuming that slapd is listening on localhost, that your rootdn is cn=Manager,dc=matthoran,dc=com and that your rootpw is secret.

server = "localhost"
identity = "cn=Manager,dc=matthoran,dc=com"
password = secret
basedn = "dc=matthoran,dc=com"
password_attribute = userPassword
set_auth_type = no

I commented out access_attr so that all users were allowed access, added password_attribute so that the PAP module can extract the userPassword attribute and set set_auth_type to no so that the PAP module will handle authentication.

Now that the LDAP module has been configured, the authorization module must be told to use LDAP for authorization. To do so, just uncomment the ldap line from the authorization section.

PAP is last in the default authorization chain. The default users file will set AuthType = System which will cause authentication to fail. Setting set_auth_type = yes in the LDAP configuration section will not solve this problem as the files database is checked before LDAP due to the order of the modules in the authorization section and would also require an additional LDAP bind. As I am not using the local passwd database for authorization or authentication, I commented out the files module in the authorization section. This will prevent Auth-Type from being set to System. The System Auth-Type may also be commented out in the Authorization section since it will not be used.

Now that the core is configured, EAP can be configured. By default, EAP is enabled, but the default configuration won’t get you too far.

I decided to use PEAP with GTC, which supports encrypted passwords in the database. Because incoming EAP messages do not specify which EAP type they are using, the default must be set for the EAP module. Be sure that you change the default EAP type for the EAP module and not PEAP.

sudoedit /usr/local/etc/raddb/eap.conf
default_eap_type = peap

The TLS and PEAP configuration sections are commented out by default. Because PEAP relies on TLS to set up a secure channel, the TLS module must be configured. The following configuration options must be uncommented:

private_key_password = whatever
private_key_file = ${raddbdir}/certs/cert-srv.pem
certificate_file = ${raddbdir}/certs/cert-srv.pem
CA_file = ${raddbdir}/certs/demoCA/cacert.pem
dh_file = ${raddbdir}/certs/dh
random_file = ${raddbdir}/certs/random

This configuration is sufficient for testing. Be sure to replace the distributed certificates with a signed certificate in a production environment.

If GTC is to be used as the innermost PEAP protocol, the default_eap_type must be set to gtc for the PEAP module. Be sure that you are setting default_eap_type for the PEAP module and not for the EAP module.

default_eap_type = gtc

Now that FreeRADIUS has been configured, it is time to start up the server.

sudo /usr/local/etc/rc.d/radiusd start

The radtest command line tool provides a quick and easy way to make sure that RADIUS can authenticate users. The default clients file includes an entry for localhost with the shared key testing123. Be sure to change this in a production environment.

radtest test test localhost 10 testing123

The first and second arguments to radtest are the username and password of the test user, respectively. radtest is connecting to localhost. The fifth option is the NAS-Port, used for accounting. The final argument is the shared key.

If you do not receive an Access-Accept packet, run FreeRADIUS from the command line in debug mode.

sudo /usr/local/etc/rc.d/radiusd stop
sudo radiusd -X

Now you can go ahead and test EAP interactively. I will not go into how to configure your NAS device to communicate with the RADIUS server. Make sure that you have an entry in /usr/local/etc/raddb/clients.conf for the NAS device.