Configuring xsupplicant 1.0 for use with PEAP

by Matthew Gast

Related link:

In March of this year, I wrote up instructions for using xsupplicant in the wake of my experience at the Interop Labs. In the last five months, xsupplicant has changed dramatically for the better. Internally, there's a new frame handler for Linux that's much cleaner, and there's a new configuration file format.

I decided to revisit xsupplicant to work with the 1.0 release. I recently installed Slackware 10.0, which is based on a 2.4 series kernel. My card is an Atheros-based tri-mode card, which uses the madwifi driver.
I fetched the latest madwifi driver out of CVS today and followed my earlier instructions. Pleasantly, the patch to madwifi distributed by the xsupplicant team is no longer necessary. All told, it took about an hour to fetch the code for both madwifi and xsupplicant and get them running.

As with xsupplicant 0.8, you'll need to have OpenSSL installed, and it helps greatly to have 802.11 already working on your system. If you can run iwconfig to instruct the card to attach to an ESSID, and see it go to the right channel with an AP's MAC address displayed, the wireless subsystem is running.

Compiling and installing xsupplicant 1.0

As with the previous version, there isn't much to say about installing the code. Generally speaking, it follows the same routine that any other open-source package. Fetch the code from sourceforge, and compile in the standard Unix way:

# tar -xzvf xsupplicant-1.0.1.tar.gz
(output for filenames in the tarball)
# cd xsupplicant
# ./configure
(output for configuration tests)
# make
(output for build)
# make install
(output for install)

As a result of the build, you get three executables installed; the only one you are likely to use is /usr/local/sbin/xsupplicant.

Configuring xsupplicant

When run, xsupplicant searches for its configuration file in /etc. The config file, /etc/xsupplicant.conf, does not get installed by default, but it's easy enough to copy over.

# cp xsupplicant.conf /etc/xsupplicant.conf

You specify the user identity, possibly the password, and the root CA certificate in the configuration file. Passwords are stored in cleartext, so you may wish to have the system prompt for the password to avoid putting sensitive information in configuration files. When no password is in the file for the network you are connecting to, xsupplicant will prompt the user. The configuration file that follows is a bit contrived. I certainly wouldn't recommend turning off certificate authentication of the wireless network by setting the CA certificate to NONE.

You must have the CA certificate that will be used to validate that you are connecting to the right network. xsupplicant does not have a configuration option to disable certificate validation. The configuration file appears to request the root CA in PEM format; you may need to use OpenSSL to convert your root certificate into the right format. (See the section at the end for more details.)

In the configuration file, settings can be stored as part of a profile for an SSID. If I were to connect to a network named "batnet", the configuration file might have some entries that looked like this:

root@laptop:~# cat /etc/xsupplicant.conf
# This is an example configuration file for xsupplicant versions after 0.8b.


# network_list: defines all of the networks in this file which
# should be kept in memory and used.Comma delimited list or "all"
# for keeping all defined configurations in memory. For efficiency,
# keep only the networks you might roam to in memory.
# To avoid errors, make sure your default network is always
# in the network_list. In general, you will want to leave this set to
# "all".

network_list = all

# default_netname: some users may actually have a network named "default".
# since "default" is a keyword in the network section below, you can
# change which is to be used as the replacement for this keyword

default_netname = batnet

# first_auth_command: the command to run when xsupplicant authenticates to
# a wireless network for the first time. This will usually be used to
# start a DHCP client process.
first_auth_command = dhcpcd %i

logfile = /var/log/xsupplicant.log


#type = wireless

# allow_types: describes which EAP types this network will allow. The
# first type listed will be requested if the server tries to use something
# not in this list.
# allow_types = eap_tls, eap_md5, eap_gtc, eap-otp
allow_types = all

# identity: what to respond with when presented with an EAP Id Request
# Typically, this is the username for this network. Since this can
# be an arbitrary string, enclose within and
identity = msg

eap-peap {
# As in tls, define either a root certificate or a directory
# containing root certificates.
#root_cert = /path/to/root/certificate
#root_dir = /path/to/root/certificate/dir
#crl_dir = /path/to/dir/with/crl
root_cert = NONE
chunk_size = 1398
random_file = /path/to/random/source
#session_resume = yes

#Currently 'all' is just mschapv2
#If no allow_types is defined, all is assumed
allow_types = all # where all = MSCHAPv2, MD5, OTP, GTC, SIM
#allow_types = eap_mschapv2

# right now you can do any of these methods in PEAP:
eap-mschapv2 {
username = msg
password = imnottelling

Connecting and authenticating to a network

Step 1: Configure the network.You need to use the Linux utilities to connect to a network. The first step is to use iwconfig, or whatever other method your driver may require, to select a network and put in a dummy WEP key. The dummy key is used to indicate to the driver that it should run in encrypted mode; xsupplicant will replace the key after successful authentication. The most common way of configuring the connection is to use iwconfig to plumb a key and configure the network, and then use ifconfig to bring the interface up and start searching for the network:

# iwconfig ath0 key 12345678901234567890123456
# iwconfig essid "batnet"
# ifconfig ath0 up

Depending on the driver, your interface name may not be "ath0". Madwifi uses the "ath" prefix; other drivers may use the "eth" prefix, and the "wlan" prefix is also somewhat common.

Step 2: Run xsupplicant. Use the "-i" option to indicate which interface it should run on. To print debug output to the screen, use the "-f" option. The "-d" option controls what is printed. In the following example, I've cut most of the packet dumps from the printout for simplicity.

root@laptop:~# /usr/local/sbin/xsupplicant -i ath0 -dasic -f
Using default config!
network_list: all
Default network: "default"
Startup command: "echo "some command""
First_Auth command: "dhclient %i"
Reauth command: "echo "authenticated user %i""
Logfile: "/var/log/xsupplicant.log"
Allow Types: ALL
ID: "msg"
peap root_cert: "NONE"
peap chunk: 1398
peap rand: "/path/to/random/source"
PEAP Allow Types: ALL
mschapv2 username: "msg"
mschapv2 password: "imnottelling"
Interface ath0 initalized!
[INT] Interface ath0 is wireless!
[INT] The card reported that the destination MAC address is now 00 0B 0E 00 F0 40
[INT] Working with ESSID : batnet
[CONFIG] Working from config file /etc/xsupplicant.conf.
[STATE] Processing DISCONNECTED state.
[STATE] Processing ACQUIRED state.
Connection established, authenticating...
[STATE] Sending EAPOL-Response-Identification
[STATE] Processing AUTHENTICATING state.
[STATE] Sending EAPOL-Response-Authentication
****WARNING**** Turning off certificate verification is a *VERY* bad idea! You should not use this mode outside of basic testing, as it will compromise the security of your connection!
[AUTH TYPE] Packet in (1) :
[AUTH TYPE] Setting Key Constant for PEAP v0!
[INT] Interface eth0 is NOT wireless!
Userdata is NULL! We will probably have problems!
[STATE] Processing DISCONNECTED state.
[STATE] Processing AUTHENTICATING state.
[STATE] Sending EAPOL-Response-Authentication
(lots of certificate and SSL exchange cut)
[AUTH TYPE] (EAP-MSCHAPv2) Challenge
[AUTH TYPE] Authenticator Challenge : C6 02 26 BE C3 E0 44 03 13 6E 1F BA F0 B3 1D 5A
[AUTH TYPE] Generated PeerChallenge : 28 62 AA A2 8C 8E EB 82 D1 9B 2F 9A 54 67 93 2C
[AUTH TYPE] PeerChallenge : 28 62 AA A2 8C 8E EB 82
[AUTH TYPE] AuthenticatorChallenge : C6 02 26 BE C3 E0 44 03
[AUTH TYPE] Username : msg
[AUTH TYPE] Challenge : 48 E7 AA 53 54 52 98 62
[AUTH TYPE] PasswordHash : C5 A2 37 B7 E9 D8 E7 08 D8 43 6B 61 48 A2 5F A1
[AUTH TYPE] Response : 4D 96 51 8C 18 3A F7 C7 70 15 47 13 19 D8 D6 9B 36 00 AD E8 FA 9A 0F 28
[AUTH TYPE] myvars->NtResponse = 4D 96 51 8C 18 3A F7 C7 70 15 47 13 19 D8 D6 9B 36 00 AD E8 FA 9A 0F 28
[AUTH TYPE] response->NT_Response = 4D 96 51 8C 18 3A F7 C7 70 15 47 13 19 D8 D6 9B 36 00 AD E8 FA 9A 0F 28
[AUTH TYPE] Server authentication check success! Sending phase 2 success!
Processing EAPoL-Key!
[INT] Key Descriptor = 1
[INT] Key Length = 13
[INT] Replay Counter = 41 2F BB 2D 00 00 00 D5
[INT] Key IV = 69 4C 45 D7 CF C3 DD CD 2A 3A F3 CB 04 7A F4 A3
[INT] Key Index (RAW) = 01
[INT] Key Signature = C2 05 6C 3A EB 25 E9 B9 8E FC 60 D6 77 44 57 22
[INT] EAPoL Key Processed: broadcast [2] 13 bytes.
[INT] Key before decryption : ED 5D 03 D2 7A DE B4 60 29 FD FD F5 42
[INT] Key after decryption : FB BB AC D3 6F 7D 0A 3F FF 2A CF 33 4E
[INT] Successfully set WEP key [2]
Processing EAPoL-Key!
[INT] Key Descriptor = 1
[INT] Key Length = 13
[INT] Replay Counter = 41 2F BB 2D 00 00 00 D6
[INT] Key IV = 66 15 69 E2 B2 8C 0E 89 7C D3 94 8C 93 25 43 1B
[INT] Key Index (RAW) = 80
[INT] Key Signature = 49 C1 15 B8 E9 D0 87 53 A6 FD 5D 76 CB 51 9D 65
[INT] EAPoL Key Processed: unicast [1] 13 bytes.
[INT] Using peer key!
[INT] Successfully set WEP key [1]
[INT] Successfully set the WEP transmit key [1]