EAP-FAST support in FreeRADIUS is handled by the eap2 module. The only
documentation is what is contained in raddb/experimental.conf.

Below, I describe how I managed to get EAP-FAST running. There is a bit
of hacking involved. 

According to raddb/experimental.conf, you need the "libeap.so" from hostapd.
Unfortunalely this library is built inside the eap-example directory of
hostapd, which is not a part of standard hostap distribution. 

I have found only one version of hostap, which has eap-example directory,
it is the git version. To get it, go to
http://hostap.epitest.fi/gitweb/gitweb.cgi
and get the snapshot of hostap-06.git project 
or do:
git clone git://w1.fi/srv/git/hostap-06.git

The current development version hostap.git has been changed and is now 
incompatible with FreeRADIUS. The incompatibility is not very serious, 
but for testing purposes the 06 version is quite sufficient. 

To build libeap.so, a patched version of openssl is required. The patches for
different versions are available in the "patches" subdirectory of hostap
distribution. 
To configure openssl with tlsext enabled, you need to specify the
enable-tlsext option in the config command.

It turns out that the source of hostapd has changed since EAP-FAST was tested 
by the author of FreeRADIUS. There are some fixes required.

cd hostap-06/eap-example
vi Makefile
add:
OBJS_peer += ../src/eap_common/eap_fast_common.o
OBJS_server += ../src/eap_server/eap_fast.o
CFLAGS += -DEAP_FAST

also add 
CFLAGS += -I/opt/SSL/include
LDFLAGS += -L/opt/lib/SSL -Xlinker -R/opt/lib/SSL 
in appropratie places (assuming that /opt/lib/SSL is the location of your
customised SSL installation)

vi ../src/eap_server/eap_fast.c
In the eap_fast_init function you have to comment six lines below
	data->force_version = -1;
to skip changing EAP-FAST version.
Then:
make CONFIG_SOLIB=yes

This creates libeap.so, which is used by rlm_eap2 in FreeRADIUS.

Following the comment in raddb/experimental.conf, 
you need to edit src/modules/rlm_eap2/Makefile and point it to the the
location of hostap directory. You also need to fix the TARGET variable,
the corresponding line should be:
TARGET	    = rlm_eap2

Then I've configured FreeRADIUS with these options:
--with-experimental-modules --with-rlm_eap2

libeap.so expects to get some configurations variables from rlm_eap2 module, 
like: eap_fast_a_id, eap_fast_a_id_info, pac_opaque_encr_key, pac_key_lifetime,
pac_key_refresh_time, backend_auth.

I've added:
1. in the rlm_eap_t stucture, in the "Configuration items" section
	char            *pac_opaque_encr_key;
        char            *eap_fast_a_id;
        char            *eap_fast_a_id_info;
        int             eap_fast_prov;
        int             pac_key_lifetime;
        int             pac_key_refresh_time;
        int             backend_auth;

2. in module_config table (above the end of list):
	{ "backend_auth", PW_TYPE_BOOLEAN,
          offsetof(rlm_eap_t, backend_auth), NULL, "yes" },
	{ "fast", PW_TYPE_SUBSECTION, 0, NULL, (const void *) fast_config },

3. in tls_config table the entry
	{ "dh_file", PW_TYPE_STRING_PTR,
          offsetof(rlm_eap_t, tparams.dh_file), NULL, "whatever" },
   is needed to provide a Diffie-Hellman key used in EAP-FAST 
   Server-Unauthenticated Provisioning Mode 

4. the new table fast_config[] is used to define variables for EAP-FAST
   static CONF_PARSER fast_config[] = {
        { "pac_opaque_encr_key", PW_TYPE_STRING_PTR,
          offsetof(rlm_eap_t, pac_opaque_encr_key), NULL, NULL },
        { "eap_fast_a_id", PW_TYPE_STRING_PTR,
          offsetof(rlm_eap_t, eap_fast_a_id), NULL, NULL },
        { "eap_fast_a_id_info", PW_TYPE_STRING_PTR,
          offsetof(rlm_eap_t, eap_fast_a_id_info), NULL, NULL },
        { "eap_fast_prov", PW_TYPE_INTEGER,
          offsetof(rlm_eap_t, eap_fast_prov), NULL, "3"},
        { "pac_key_lifetime", PW_TYPE_INTEGER,
          offsetof(rlm_eap_t, pac_key_lifetime), NULL, "604800"},
        { "pac_key_refresh_time", PW_TYPE_INTEGER,
          offsetof(rlm_eap_t, pac_key_refresh_time), NULL, "86400"},
        { NULL, -1, 0, NULL, NULL }           /* end the list */
   };
5. in the eap_authenticate function, below
	handler->eap_conf.ssl_ctx = inst->tls_ctx;
   add:
	handler->eap_conf.pac_opaque_encr_key = inst->pac_opaque_encr_key;
        handler->eap_conf.eap_fast_a_id = inst->eap_fast_a_id;
        handler->eap_conf.eap_fast_a_id_len = strlen(inst->eap_fast_a_id);
        handler->eap_conf.eap_fast_a_id_info = inst->eap_fast_a_id_info;
        handler->eap_conf.eap_fast_prov = inst->eap_fast_prov;
        handler->eap_conf.pac_key_lifetime = inst->pac_key_lifetime;
        handler->eap_conf.pac_key_refresh_time = inst->pac_key_refresh_time;
        handler->eap_conf.backend_auth = inst->backend_auth;

Now you should be able to compile the code.

In FreeRADIUS configuration I've added raddb/modules/eap2.conf 
with the following content:

eap2 {
                tls {
                        ca_cert = ${confdir}/certs/ca.cert
                        server_cert = ${confdir}/certs/radius1-crt.pem
                        private_key_file = ${confdir}/certs/radius1-key.pem
                        private_key_password = ******
			dh_file = ${confdir}/certs/dh
                        random_file = ${confdir}/certs/random
                }
		
		peap {
                }
		
		ttls {
		}

                md5 {
                }

                mschapv2 {
                }

                fast {
                        pac_opaque_encr_key = 000102030405060708090a0b0c0d0e0f
                        eap_fast_a_id = xxxxxx
                        eap_fast_a_id_info = my_server
                }

}

I have an example user in the users file:
mgw     Auth-Type := EAP2, Cleartext-Password := "tttt"

In my sites-enabled I have only default (inner-tunnel isn't used by eap2).
In the default I've replaces eap with eap2 in the authenticate section and
commented out eap calls in the authorize and post-auth sections.

To successfully start radiusd I have to add  the environement variable
(it may depend on system):
LD_PRELOAD=path_to/libeap.so

The server successfully authenticates clients using EAP_FAST method. 
We tested: eapol_test, Mac OS client (Snow Leopard), CISCO client with
anonymous PAC provisioning. It also works fine with other methods called
from eapol_test. Unfortunately the rlm_eap2 module does not seem to have
EAP fragmentation, which causes IP fragmentation between server and AP
and our AP is unable to handle that, so we were not able to test other methods
on the wireless network. 

EAP fragmenation would have to be added to get a server which could be
considered even partially working.

