HowTo: WPA with FreeRADIUS and SMB-LDAP

WPA-Enterprise with Open Source Software

by John Lucas 

I. Introduction

The "smbldap-installer" script by Matt Oquist and David Trask (http://majen.net/smbldap/) has gone a long way
toward establishing an Open Source, cross-platform, single sign-on infrastructure for Linux and Windows
workstations. This script has taken the sting out of installing and configuring a Samba-based Windows NT-style
domain with credentials stored in OpenLDAP. Having once set up such an environment from scratch without such a
wonderful tool (back when Windows NT was the current Microsoft release), I appreciate what a monumental step
forward "smbldap-installer" is.

This document describes how an NT Domain set up with "smbldap-installer" can be leveraged to provide
authentication for "WPA-Enterprise" (aka 802.11i RSN) Wifi security.

Wifi (aka 802.11) has become a popular and nearly ubiquitous technology in recent years. One common problem
with many Wifi implementations is a lack of adequate security. There are many methods that can be used to
secure Wifi, but since about 2004 there has been an IEEE 802.11 standard that provides "AAA" (Authorization,
Authentication, and Accounting) and transport privacy via stong encryption. This standard is best known as
"WPA", officially known as IEEE 802.11i. There are two common implementations of 802.11i known as "Personal"
(aka PSK for pre-shared key), and "Enterprise". WPA Personal is suitable for home use or with a small group of
trusted users; since all users share the same "pre-shared key", it tends to get passed around and it is
possible for users to "see" (decrypt) each other's net traffic. WPA Personal does not scale well and is
unsuitable for larger installations.

WPA "Enterprise" uses a RADIUS (Remote Authentication Dial-in User Service) server to provide authentication of
users and unique encryption keys for each user. As the name implies, this implementation is designed to support
large Wifi deployments. This document describes how to set up WPA Enterprise with Open Source software and
low-end hardware.

The model deployment I had in mind when choosing to begin this project was deploying Wifi in a K-12 school. A
natural limit for the number of Wifi clients is 250: a class C subnet can have 254 IP addresses and a common
deployment scenario is to isolate Wifi traffic onto a separate subnet (VLAN) connected to the main LAN via a
firewall. I think 250 is a good starting value anyway. To support 250 *simultaneous* users would require a
minimum of 10 Access Points, probably closer to 20 in the real world. When deploying LDAP, you should have at
least one "master" and one "slave" server for redundancy. If you install RADIUS on each LDAP server and split
the authentication load, I don't think there would be any issue with supporting WPA-Enterprise for 250
simultaneous users and you would have RADIUS redundancy that way too.

Caveat: The system described here is a testbed, not a production network.

II. Objectives

I set several goals for this exercise that I consider important, mostly to hold down costs and simplify the
installation/configuration and administration process. These goals are:

    - Use the LDAP tree set up through "smbldap-installer" w/o mods.
    - Use only Open Source software
    - Use commonly available and inexpensive Wifi Access Points
    - Use methods that work across platforms (Win, Mac & *NIX)
    - Use "Networkmanager" as the Linux 802.1X supplicant
    - Avoid the generation/distribution of client certificates
   
The various pieces integrated into this demo system were:

    Server Pieces:
   
    SMB-LDAP server: Fedora Core 5 (VMware virtual machine)
    LDAP: openldap-D2.3.19-4
    Samba: samba-3.0.24-1.fc5
    RADIUS server: freeradius-1.0.5-1.2
    smbldap-installer: v3.1
    PKI: openvpn-2.1-0.17.rc2.fc5 (only used to generate certs)
    Encryption Libs: openssl-0.9.8a-5.4
   
    Client Pieces:
   
    Dell Inspiron 6400 laptop w/ Intel 3945 802.11 a/b/g Wifi NIC
    Fedora Core 6 OS with KDE 3.5.6-0.1    

   NetworkManager:
        NetworkManager-0.6.4-5.fc6
        NetworkManager-vpnc-0.6.4-2.fc6
        NetworkManager-glib-0.6.4-5.fc6
        NetworkManager-gnome-0.6.4-5.fc6
        NetworkManager-openvpn-0.3.2-7.fc6
        knetworkmanager-0.1-0.6.svn20061113.fc6
    Wifi NIC packages (from Freshrpms for FC6):
        ipw3945-firmware-1.13-1
        dkms-ipw3945-1.2.0-1
        ipw3945d-1.7.22-4

    Access Point
   
    LinkSys WAP54G firmware version 3.04


Whenever possible packages were installed via "yum" and no source compilation was required.

III. Server Setup


I started with a minimal Fedora Core 5 installation setup as a Samba-NT Primary Domain Controller using the
"smbldap-installer" script, which automatically installed the needed packages and their dependancies,
configured OpenLDAP and Samba and left me impressed with the work that went into that script. I named my domain
"Minibox.net" and other than adding the /opt/IDEALX/bin to the execution PATH, the only other change was to add
some access control rules to the "slapd.conf" file (more about that later). This server is a virtual machine
using VMware Server v1.0 with it's NIC bridged to my LAN and named "vNAS" (since I use this as a virtual file
server (Network Attached Storage) too).

Once I had this PDC/NAS server up and tested, I added "FreeRADIUS" from the updates repository via "yum
install" and then went in search of information about how to configure FreeRADIUS to implement WPA-Enterprise
with LDAP. I settled on "PEAP" as the target 802.1X authentication method, since it can be used by Linux,
Windows and Mac "natively" (without third party add-ons for the proprietary systems) and it does not require
client-side certificates (two of my initial goals).

I didn't find a comprehensive "HowTo", but I did find enough to figure out the missing pieces. The two HowTos
closest to my needs were:

    http://vuksan.com/linux/dot1x/802-1x-LDAP.html#Set_up_FreeRADIUS

By Vladimir Vuksan. This almost covered the RADIUS-LDAP piece and referred to:

    http://tldp.org/HOWTO/html_single/8021X-HOWTO/#confradius

By Lars Strand, which covered the EAP-PEAP parts (but didn't use LDAP). The Vuksan approach required extending
the OpenLDAP schema with the FreeRADIUS schema and adding attributes to user entries. I wanted to leave the
schema alone so that the smbldap tools could be used without modification (another of my goals).

FreeRADIUS Setup

I made two trivial changes to the "ldap" module in the "radiusd.conf" file from the Vuksan HowTo: I used the
"uid" LDAP attribute as the "access_attribute" as suggested in the text:

    access_attr = "uid"

and also added a vital "password_attribute" missing from the Vuksan HowTo:

    password_attribute = "userPassword"

Without this addition, authentication will fail, since RADIUS requests require both ID and Password. This might
seem obvious, but the actual PEAP method performs comparisons on the "sambaNTPassword" attribute via additional
"checkItem" mappings (more later). But without the request supplying a value pair (ID/Password) you don't get
that far. The revised "ldap module" configuration in the "radiusd.conf" file looks like this:

   
    ldap {
        server = "127.0.0.1"
        identity = "uid=onex,ou=Users,dc=Minibox,dc=net"
        password = "SuperSecret"
        basedn = "dc=Minibox,dc=net"
        start_tls = no

        base_filter = "(objectclass=posixAccount)"
        filter = "(uid=%{Stripped-User-Name:-%{User-Name}})"
        access_attr = "uid"
        password_attribute = "userPassword"
        dictionary_mapping = ${raddbdir}/ldap.attrmap
        authtype = ldap

        ldap_connections_number = 5
        timeout = 4
        timelimit = 3
        net_timeout = 1
    }


The entire "radiusd.conf" file is included in the accompanying tarball. I added a dummy user that has read
privleges to the three password attributes in LDAP, as detailed in the Vuksan HowTo. Another change was to
alter the "base_filter" from "radiusprofile" to "posixAccount" (since the former objectclass was not added to
OpenLDAP) and added "filter" to supply stripped user IDs. This module completely replaced the "ldap" stanza in
the generic radiusd.conf file. I am not planning to use this RADIUS server for any other purpose other than
Wifi authentication. I don't need TLS talking to the LDAP server since they are on the same host and
communicate over the localhost interface. If RADIUS and OpenLDAP were on different hosts, you should add
certificates to both RADIUS and LDAP servers and set "start_tls" to "yes".

Next, we need to make sure that we have both "eap" and "ldap" listed in the "authorize" and "authenticate" stanzas
of the "radiusd.conf" file:

     authorize {
        preprocess
        chap
        mschap
        suffix
        ldap
        files
        eap
    }

    authenticate {
            Auth-Type PAP {
            pap
        }

        Auth-Type CHAP {
            chap
        }
        Auth-Type MS-CHAP {
            mschap

        }  

        unix

        Auth-Type LDAP {

                ldap
        }
        eap
    }


To finish off the LDAP parts of FreeRADIUS setup, I modified the "ldap.attrmap" that is included by
radiusd.conf. This file maps RADIUS attributes to LDAP attributes and by default uses the FreeRADIUS LDAP
schema extentions, which I didn't use. I did need four items mapped, and I eliminated everything else. My
complete ldap.attrmap file looks liks this: 


 
     checkItem       User-Password                   userPassword
    checkItem       LM-Password                     sambaLMPassword
    checkItem       NT-Password                     sambaNTPassword
    checkItem       SMB-Account-CTRL-TEXT           sambaAcctFlags
    
    checkItem       $GENERIC$                       radiusCheckItem
    replyItem       $GENERIC$                       radiusReplyItem


The critical ones are are "userPassword" to provide the required ID/Password value pair, and "sambaNTPassword"
used by the actual PEAP authentication.

FreeRADIUS EAP Setup

The last part of FreeRADIUS setup was configuring EAP-PEAP. PEAP requires that the "authenticator" (FreeRADIUS
in this case) have valid public key encryption certificates to enable TLS and provide the encrypted tunnel in
which "mschapv2" authentication can safely take place. The MD4 NT password hash is a "password equivalent" and
should not appear unprotected over the air (or wire for that matter).

In order to most easily generate and manage certificates, I used the Certificate Authority scripts supplied
with OpenVPN (http://openvpn.net/). I needed to sign the certificates and supply the public root certificate
for the CA. So I followed the OpenVPN directions to create a new CA and generate and sign a server certificate
for FreeRADIUS and for the CA. The root CA cert can be distributed to your clients to (optionally) verify the
server certificate (recommended). If you have a Windows 2000 or 2003 server, you should probably use
certificates from your PKI for your clients; I understand that Windows clients are picky that way. I don't have
a Windows server (or client), so I took the open source path.

The certificates are part of the "tls" EAP method, which is the "outer" authentication method used by PEAP,
which uses "mschapv2" for the "inner" authentication.

Next step was to modify the "eap.conf" file to refer to our new certificates and set the default EAP type. Here
is my complete "eap.conf" file:
    eap {
        default_eap_type = peap
        timer_expire     = 60
        ignore_unknown_eap_types = no
        cisco_accounting_username_bug = no

        md5 {
        }

        leap {
        }
   
        gtc {
            auth_type = PAP
        }

        tls {
            private_key_file = ${raddbdir}/certs/vnas.key
            certificate_file = ${raddbdir}/certs/vnas.crt
            CA_file = ${raddbdir}/certs/demoCA/vnas-ca.crt
            dh_file = ${raddbdir}/certs/dh
            random_file = ${raddbdir}/certs/random
            fragment_size = 1024
        }

        peap {
            default_eap_type = mschapv2
        }

        mschapv2 {
        }
    }


Notice that the certificates and keys are in the "tls" module. Even though we are using PEAP, the outer
authentication calls the "tls" module to set up the encrypted tunnel used for inner authentication via
PEAP/mschapv2.

We need to make some changes in the "mschap" stanza in "radiusd.conf" in order to have the "mschapv2" work as we intend (from the Strand HowTo):

	mschap {
authtype = MS-CHAP
use_mppe = yes
require_encryption = yes
require_strong = yes
}

Only two more pieces to the FreeRADIUS setup. The "users" file is simplified to two entries: One entry is for
my chosen anonymous user "nobody", which is used as a dummy user to set up the TLS tunnel without revealing the
real user identity "in the clear", i.e. before the encrypted tunnel is set up. The other entry is used to
perform LDAP authentication for all other user IDs.

     nobody  Auth-Type := System
    DEFAULT Auth-Type := LDAP


This setup will allow anyone with a valid "uid" and password to authenticate. If you wanted to restrict which
users can use Wifi, you could explicitly enter them in the "users" file, so that if they aren't listed they
can't authenticate. Something like this:
 

    jlucas    Auth-Type := LDAP
   
    vvuksan    Auth-Type := LDAP
   
    lstrand Auth-Type := LDAP
   
    DEFAULT    Auth-Type := System


Since their isn't an sambaNTPassword in the local /etc/passwd file, without a matching "Auth-Type := LDAP"
entry for their ID, innner authentication will fail.

The last part of FreeRADIUS setup is the "clients.conf" file, included in radiusd.conf to allow RADIUS clients
to communicate with the RADIUS server. In this demo setup, I have only two clients: the local RADIUS host (for
testing) and my Wifi Access Point. These are easy. Here is my complete "clients.conf" file:
 

    client 127.0.0.1 {
        secret          = testing123
        shortname       = localhost
    }

    client 192.168.0.11 {
        secret          = AnotherSuperSecretPassword
        shortname       = wap54g
        nastype         = other
    }

 
The "secret" entry is the shared secret between the Access Point and the RADIUS server. Normally this would be
pretty insecure, but by communicating in the EAP-TLS tunnel set up during PEAP outer authentication, it is
considered secure. You need to use a very good, long secret here, and you will need to enter it in the Access
Point setup too.

Once you get to this point, you should test your RADIUS-LDAP setup by using "radtest" on the RADIUS host (see
man page for radtest):

    radtest jlucas MyPassword localhost 0 testing123

If you can't get an "Access-Accept", check your configuration before proceeding with your Wifi setup.

Running radiusd in the foreground is a great help in troubleshooting the authentication process:

    radiusd -X -f


IV. Wifi Access Point Setup

Before implementing any advanced Wifi security setup, make sure you can use Wifi on a completely "open" Access
Point (open authentication, no encryption). Save yourself some trouble by making sure you don't have any basic
Wifi problems.

My test setup uses a LinkSys WAP54G with firmware v3.04 and the Wifi security setup is very straightforward and
easy. After logging into the built-in web configuration interface (from the "wired" side of the AP), navigate
to the "Wireless Security" setup screen and select:

 
         Security Mode: WPA Enterpise
      Encryption: AES        (use TKIP for widest compatibility)
      RADIUS Server: IP address of your RADIUS Server
      Port: 1812
      Shared Secret: AnotherSuperSecretPassword (match "clients.conf" file)
      Key Renewel: 300 secs. (default)
 

One drawback to using a low end Access Point is that it doesn't support RADIUS accounting. If you need
accounting you would need something like the Proxim AP-700 for $329 instead of a Linksys WAP54G for $69. So in
this case I missed one of my goals by failing to provide the third "A" in AAA. The "/var/log/radius/radius.log"
file does contain authentication information, but there is no record of dis-associations with the AP so session
duration is not known.

V. NetworkManager Setup

My test setup is limited to one Wifi client: I only have one Wifi NIC that is capable of WPA security and it is
the built-in NIC in my Dell laptop, so I am limited to testing Linux (I hope to borrow a WinXP laptop to test
further). I very carefully selected my laptop hardware so that I could use Wifi with Linux without resorting to
the "NDIS-wrapper" and would be compatible with NetworkManager.

I installed the Intel 3945 drivers and firmware from FreshRPMs following the procedure described in this HowTo
by Paul Wayper:

    http://www.mabula.net/dell_inspiron_6400.html

I use KDE as my primary desktop, so I used the "knetworkmanager" GUI tool to configure Networkmanager. In the
"Connect to Other Wireless Network..." dialog, fill in:


       ESSID: Minibox (my SSID, use yours instead)
      Check the Encryption box
      Encryption: WPA Enterprise
      EAP Method: PEAP
      Identity: jlucas (your user ID)
      Password: MyPassword (your password)
    Anonymous Identity: nobody (dummy user used in outer authentication)
    WPA Version: 1 (there is no version 2 of WPA Enterprise)
    CA Certificate File: path to your root CA certificate for server
   
    The CA certificate file is optional but highly recommended. It allows
    the client to authenticate the server.
   
    The other fields can be left blank, they are used for other EAP methods
    (EAP-TLS uses both client and server certificates).

 Hit the "Connect" button and cross your fingers. You should see the gears turning and if you connect
successfully, you will see the 4 blue bars. You should also get a prompt from KWallet to enter your Wallet
password to store kneetworkmanager credentials.

Caveat: I have not been successful in getting knetworkmanager to save my credentials in kwallet. It worked when
I used "WPA Personal" security, but not with the more complicated setup. In fact I have had to delete the
"Minibox" network and re-attach each time I use it. This seems to be a common failing with Networkmanager
(knetworkmanager handing off to kwallet), but it is frustrating. At least I don't have to use "regedit" to
clear things out (as you would with Windows). I don't know if the Gnome Networkmanager applet is any better. I
am sticking with KDE and so I'll put up with the hassle and hope that in future knetworkmanger is improved.

VI. Notes

Security on both RADIUS and LDAP needs to be tightened up.

By default the "smbldap-installer" scripts allow all users to read the 3 password attributes (userPassword,
sambaLMPassword, and sambaNTPassword). This is insecure. I added some basic access control to the OpenLDAP
"/etc/openldap/slapd.conf" file:

    access to attrs=userPassword,sambaNTPassword,sambaLMPassword
        by dn="uid=onex,ou=Users,dc=minibox,dc=net" read
        by dn="uid=root,ou=Users,dc=minibox,dc=net" write
        by self write
        by * auth

    access to *
        by dn="uid=root,ou=Users,dc=Minibox,dc=net" write
        by * read

 This allows the user "onex" to read the password attributes (needed for the "ldap" module in FreeRADIUS). The
"root" user is the only one able to create users with the smbldap-tools scripts. I am still trying to allow the
"Domain Users" group members the same access, but somehow the documented syntax doesn't seem to work (or I am
misunderstanding it).

You should also generate and configure certificates for OpenLDAP so that LDAP queries can be performed in a TLS
tunnel. The default smbldap-installer script does not do this for you. Additionally on a production system I
think I would  create an old-style SSL tunnel for LDAP on port 636 via "stunnel" invoked from xinetd, for those
LDAP clients that can't do STARTTLS. Don't forget to restrict access to LDAP through tcpwrappers too.

It is important to protect the configuration files with restriced permissions, especially the ones with
passwords and private keys in them. Something like:

    chown -R root:radiusd /etc/raddb chmod -R o-r,o-w,o-x ./etc/raddb
    chown -R root:ldap /etc/openldap chmod -R o-r,o-w,o-x /etc/openldap

I find RADIUS extremely powerful, but arcane. I hadn't set up a RADIUS server in over a decade prior to this
project (my last RADIUS setup still used port 1645, that's how long ago it was). Add the novelty (for me at
least) of EAP and PEAP and there are lacuna in the available documentation. Here are some resources you can
draw on:

Books:

    "802.11 Wireless Networks the Definitive Guide" 2nd Edition by  Matthew S.Gast,    O'Reilly copyright 2005

    "LDAP System Administration" by Gerald Carver, O'Reilly copyright 2003

    "RADIUS" by Jonathan Hassell, O'Reilly copyright 2003

Links:


    http://vuksan.com/linux/dot1x/802-1x-LDAP.html#Set_up_FreeRADIUS

    http://tldp.org/HOWTO/html_single/8021X-HOWTO/#confradius
   
    http://majen.net/smbldap/
   
    http://www.mabula.net/dell_inspiron_6400.html

    http://openvpn.net/