Wireless Lan with 802.1x

OpenSSL

This program creates the certificates used by FreeRADIUS and other programs.

Add object identifiers to tell Windows XP clients what the certificates are for: cat /usr/share/doc/freeradius/examples/scripts/xpextensions >> /etc/ssl/openssl.cnf

Then alter the other options in openssl.conf, especially paths for certificates in CA_default and defaults for new certiciates in req_distinguished_name

First, you probably want a root certificate if you dont already have one. This is used to sign the other certificates, so clients only need to trust it, so that trust is implied for the other certificates. I used this script from the Jabber server. It asks for a password, but the password is taken off when it is requested again.

#!/bin/sh
## This generates the cert and key
## The key will be valid for 3650 days.
## Be sure to enter the FQDN of your Jabber
## server as the "Common Name".
# -x509 means make root selfsigned cert
#
openssl req -new -x509 -newkey rsa:1024 -days 3650 -keyout privkey.pem -out key.pem
## This will remove the passphrase
openssl rsa -in privkey.pem -out privkey.pem
## Put it all together
cat privkey.pem >> key.pem
## Cleanup
rm privkey.pem

I rename key.pem to root.pem and it goes in the /etc/ssl/certs/ directory. If other users on the system cannot be trusted, then the private key can be split off the certificate and kept in /etc/ssl/certs/private/ directory. Do remember to edit [ CA_default ] in /etc/ssl/openssl.conf to tell it where the root certificate is.

Now a server certificate for freeradius can be made, with a common root. Server certs for other SSL using things like imaps, https, jabber are made similarly.

## This generates the cert and key
## The key will be valid for 3650 days.
## Be sure to enter the FQDN of your Jabber
## server as the "Common Name".
# -x509 means make root selfsigned cert
#
openssl req -new -newkey rsa:1024 -days 3650 -keyout privkey.pem -out key.pem

## This will remove the passphrase
# if you bother keeping this ... it matches that specified in /etc/freeradius/eap.conf as "private_key_password ="
# however it also ask for a challenge which is what xsupplicant might ask about
openssl rsa -in privkey.pem -out privkey.pem

## Put it all together
cat privkey.pem >> key.pem

# You may need to create these files as so if this is the first cert.
#echo > /etc/ssl/index.txt
#echo 01 > /etc/ssl/serial

# -extensions read in from section in openssl.cnf
# -extensions xpclient_ext if generating for supplicant, -extensions xpserver_ext if generating for FreeRADIUS
# XP does not recognise Radius or choose its certificate otherwise.
#
openssl ca -extensions xpserver_ext -policy policy_anything -out signedkey.pem -infiles key.pem

cat privkey.pem >> signedkey.pem
rm privkey.pem
rm key.pem

-extensions xpserver_ext is only used when making the FreeRADIUS server certificate. It is needed for Windows XP clients to be able to use the access point.

Windows XP seems to like its certificates provided in p12 files though... In this case the passphrase has to be used to encrypt the private key, but windows lets the user remove it when this certificate/private-key is imported!

#!/bin/sh

openssl req -new -keyout newreq.pem -out newreq.pem -days 3650
openssl ca -extensions xpclient_ext -policy policy_anything -out newcert.pem -infiles newreq.pem
openssl pkcs12 -export -in newcert.pem -inkey newreq.pem -out cert-clt.p12 -clcerts
openssl pkcs12 -in cert-clt.p12 -out cert-clt.pem

To complete the XP setup, the public portion of the root certificate is also imported to trust it, then Certificate authentication is set up in wireless lan settings, with My key is provided for me

Freeradius Setup

I have patched freeradius 1.5.0. We want EAP-TLS to be built.

I like to keep all my certificates together in OpenSSL, so in the tls section of eap.conf I write:

tls {
# password is not needed if the certificate does not have one
# private_key_password = cats
private_key_file = /etc/ssl/certs/radius.pem
certificate_file = /etc/ssl/certs/radius.pem
CA_file = /etc/ssl/certs/root.pem
# CA_path = /etc/ssl/certs/
dh_file = /dev/urandom
random_file = /dev/urandom
fragment_size = 1024
# include_length = yes
# check_crl = yes
check_cert_cn = %{User-Name}
}

Freeradius with SQL

Firstly it’s needed to give Freeradius access to an SQL database. I’m using MySQL, so to do that do like:

create database freerad;
GRANT ALL ON freerad.* TO freerad@localhost IDENTIFIED BY 'password';
use freerad;
\. /usr/share/freeradius-dialupadmin/sql/userinfo.sql
\. /usr/share/freeradius-dialupadmin/sql/badusers.sql
\. /usr/share/freeradius-dialupadmin/sql/totacct.sql
\. /usr/share/freeradius-dialupadmin/sql/mtotacct.sql
-- import the following, though it's needed to gunzip db_mysql.sql.gz and uncomment all the tables in that.
\. /usr/share/doc/freeradius/examples/db_mysql.sql.gz

The dbms login details, i.e. server, database, username, password are also specified in the /etc/freeradius/sql.conf file. Also, for security, I activate the default profile features, so usernames that are not authorised are rejected, rather than default accepting them.

default_user_profile = "DEFAULT"
query_on_not_found = yes

Add a 802.1x user (I use EAP) to a Freeradius SQL Database.

It can be tested by trying to auth the user User's Laptop. DELETE FROM radcheck; should result in the auth attempt being rejected instead. The =27 is a mime HEX-escape for a ', and they are only used to check the UserName column. Thereafter the PHP dialupadmin provided with freeradius can be used to admin which usernames are authorised to connect via 802.1x

-- Here is the first SQL that I had FreeRADIUS accepting iff a given username is mentioned in the table

DELETE FROM radcheck;
DELETE FROM radreply;
DELETE FROM usergroup;
DELETE FROM radgroupcheck;
DELETE FROM radgroupreply;

INSERT INTO radcheck (UserName, Attribute, op, Value) VALUES
        ('User=27s Laptop', 'User-Name', '==', 'User''s Laptop'),
        ('User=27s Laptop', 'Auth-Type', ':=', 'EAP');

INSERT INTO radreply (UserName, Attribute, op, Value) VALUES
        ('User=27s Laptop', 'Reply-Message', '=', 'Welcome user %u on the laptop');

INSERT INTO usergroup (UserName, GroupName) VALUES
        ('DEFAULT', 'DEFAULT');

INSERT INTO radgroupcheck (GroupName, Attribute, op, Value) VALUES
        ('DEFAULT', 'User-Name', '!=', 'DEFAULT'),
        ('DEFAULT', 'Auth-Type', ':=', 'Reject');

INSERT INTO radgroupreply (GroupName, Attribute, op, Value) VALUES
        ('DEFAULT', 'Reply-Message', '=', 'You have no account!');

Some more openssl commands

openssl x509 -inform PEM -in root.pem -outform DER -out /tmp/root.cer