EAP-FAST: Allow A-ID and A-ID-Info to be configured separately
authorJouni Malinen <j@w1.fi>
Sun, 19 Oct 2008 06:55:59 +0000 (09:55 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 19 Oct 2008 06:55:59 +0000 (09:55 +0300)
Changed EAP-FAST configuration to use separate fields for A-ID and
A-ID-Info (eap_fast_a_id_info) to allow A-ID to be set to a fixed
16-octet len binary value for better interoperability with some peer
implementations; eap_fast_a_id is now configured as a hex string.

14 files changed:
hostapd/ChangeLog
hostapd/config.c
hostapd/config.h
hostapd/eapol_sm.c
hostapd/eapol_sm.h
hostapd/hostapd.c
hostapd/hostapd.conf
hostapd/ieee802_1x.c
src/eap_server/eap.c
src/eap_server/eap.h
src/eap_server/eap_fast.c
src/eap_server/eap_i.h
src/radius/radius_server.c
src/radius/radius_server.h

index 613f3e3..c8c3539 100644 (file)
@@ -19,6 +19,10 @@ ChangeLog for hostapd
          (driver=none in hostapd.conf; CONFIG_DRIVER_NONE=y in .config)
        * fixed WPA/RSN IE validation to verify that the proto (WPA vs. WPA2)
          is enabled in configuration
+       * changed EAP-FAST configuration to use separate fields for A-ID and
+         A-ID-Info (eap_fast_a_id_info) to allow A-ID to be set to a fixed
+         16-octet len binary value for better interoperability with some peer
+         implementations; eap_fast_a_id is now configured as a hex string
 
 2008-08-10 - v0.6.4
        * added peer identity into EAP-FAST PAC-Opaque and skip Phase 2
index 6574745..7fceacb 100644 (file)
@@ -1509,8 +1509,26 @@ struct hostapd_config * hostapd_config_read(const char *fname)
                                errors++;
                        }
                } else if (os_strcmp(buf, "eap_fast_a_id") == 0) {
-                       os_free(bss->eap_fast_a_id);
-                       bss->eap_fast_a_id = os_strdup(pos);
+                       size_t idlen = os_strlen(pos);
+                       if (idlen & 1) {
+                               printf("Line %d: Invalid eap_fast_a_id\n",
+                                      line);
+                               errors++;
+                       } else {
+                               os_free(bss->eap_fast_a_id);
+                               bss->eap_fast_a_id = os_malloc(idlen / 2);
+                               if (bss->eap_fast_a_id == NULL ||
+                                   hexstr2bin(pos, bss->eap_fast_a_id,
+                                              idlen / 2)) {
+                                       printf("Line %d: Failed to parse "
+                                              "eap_fast_a_id\n", line);
+                                       errors++;
+                               } else
+                                       bss->eap_fast_a_id_len = idlen / 2;
+                       }
+               } else if (os_strcmp(buf, "eap_fast_a_id_info") == 0) {
+                       os_free(bss->eap_fast_a_id_info);
+                       bss->eap_fast_a_id_info = os_strdup(pos);
                } else if (os_strcmp(buf, "eap_fast_prov") == 0) {
                        bss->eap_fast_prov = atoi(pos);
                } else if (os_strcmp(buf, "pac_key_lifetime") == 0) {
@@ -2164,6 +2182,7 @@ static void hostapd_config_free_bss(struct hostapd_bss_config *conf)
        os_free(conf->dh_file);
        os_free(conf->pac_opaque_encr_key);
        os_free(conf->eap_fast_a_id);
+       os_free(conf->eap_fast_a_id_info);
        os_free(conf->eap_sim_db);
        os_free(conf->radius_server_clients);
        os_free(conf->test_socket);
index 9cabc69..5c7d040 100644 (file)
@@ -250,7 +250,9 @@ struct hostapd_bss_config {
        int check_crl;
        char *dh_file;
        u8 *pac_opaque_encr_key;
-       char *eap_fast_a_id;
+       u8 *eap_fast_a_id;
+       size_t eap_fast_a_id_len;
+       char *eap_fast_a_id_info;
        int eap_fast_prov;
        int pac_key_lifetime;
        int pac_key_refresh_time;
index 40bb23d..cc2c4e7 100644 (file)
@@ -805,6 +805,8 @@ eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr,
        eap_conf.eap_sim_db_priv = eapol->conf.eap_sim_db_priv;
        eap_conf.pac_opaque_encr_key = eapol->conf.pac_opaque_encr_key;
        eap_conf.eap_fast_a_id = eapol->conf.eap_fast_a_id;
+       eap_conf.eap_fast_a_id_len = eapol->conf.eap_fast_a_id_len;
+       eap_conf.eap_fast_a_id_info = eapol->conf.eap_fast_a_id_info;
        eap_conf.eap_fast_prov = eapol->conf.eap_fast_prov;
        eap_conf.pac_key_lifetime = eapol->conf.pac_key_lifetime;
        eap_conf.pac_key_refresh_time = eapol->conf.pac_key_refresh_time;
@@ -1236,10 +1238,26 @@ static int eapol_auth_conf_clone(struct eapol_auth_config *dst,
                          16);
        } else
                dst->pac_opaque_encr_key = NULL;
-       if (src->eap_fast_a_id)
-               dst->eap_fast_a_id = os_strdup(src->eap_fast_a_id);
-       else
+       if (src->eap_fast_a_id) {
+               dst->eap_fast_a_id = os_malloc(src->eap_fast_a_id_len);
+               if (dst->eap_fast_a_id == NULL) {
+                       os_free(dst->eap_req_id_text);
+                       return -1;
+               }
+               os_memcpy(dst->eap_fast_a_id, src->eap_fast_a_id,
+                         src->eap_fast_a_id_len);
+               dst->eap_fast_a_id_len = src->eap_fast_a_id_len;
+       } else
                dst->eap_fast_a_id = NULL;
+       if (src->eap_fast_a_id_info) {
+               dst->eap_fast_a_id_info = os_strdup(src->eap_fast_a_id_info);
+               if (dst->eap_fast_a_id_info == NULL) {
+                       os_free(dst->eap_req_id_text);
+                       os_free(dst->eap_fast_a_id);
+                       return -1;
+               }
+       } else
+               dst->eap_fast_a_id_info = NULL;
        dst->eap_fast_prov = src->eap_fast_prov;
        dst->pac_key_lifetime = src->pac_key_lifetime;
        dst->pac_key_refresh_time = src->pac_key_refresh_time;
@@ -1257,6 +1275,8 @@ static void eapol_auth_conf_free(struct eapol_auth_config *conf)
        conf->pac_opaque_encr_key = NULL;
        os_free(conf->eap_fast_a_id);
        conf->eap_fast_a_id = NULL;
+       os_free(conf->eap_fast_a_id_info);
+       conf->eap_fast_a_id_info = NULL;
 }
 
 
index 3618b16..f2ca800 100644 (file)
@@ -48,7 +48,9 @@ struct eapol_auth_config {
        char *eap_req_id_text; /* a copy of this will be allocated */
        size_t eap_req_id_text_len;
        u8 *pac_opaque_encr_key;
-       char *eap_fast_a_id;
+       u8 *eap_fast_a_id;
+       size_t eap_fast_a_id_len;
+       char *eap_fast_a_id_info;
        int eap_fast_prov;
        int pac_key_lifetime;
        int pac_key_refresh_time;
index 22054cf..fdc61b2 100644 (file)
@@ -1170,6 +1170,8 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd,
        srv.ssl_ctx = hapd->ssl_ctx;
        srv.pac_opaque_encr_key = conf->pac_opaque_encr_key;
        srv.eap_fast_a_id = conf->eap_fast_a_id;
+       srv.eap_fast_a_id_len = conf->eap_fast_a_id_len;
+       srv.eap_fast_a_id_info = conf->eap_fast_a_id_info;
        srv.eap_fast_prov = conf->eap_fast_prov;
        srv.pac_key_lifetime = conf->pac_key_lifetime;
        srv.pac_key_refresh_time = conf->pac_key_refresh_time;
index 5bb3cec..898a3a3 100644 (file)
@@ -506,7 +506,18 @@ eap_server=0
 #pac_opaque_encr_key=000102030405060708090a0b0c0d0e0f
 
 # EAP-FAST authority identity (A-ID)
-#eap_fast_a_id=test server
+# A-ID indicates the identity of the authority that issues PACs. The A-ID
+# should be unique across all issuing servers. In theory, this is a variable
+# length field, but due to some existing implementations required A-ID to be
+# 16 octets in length, it is strongly recommended to use that length for the
+# field to provided interoperability with deployed peer implementation. This
+# field is configured in hex format.
+#eap_fast_a_id=101112131415161718191a1b1c1d1e1f
+
+# EAP-FAST authority identifier information (A-ID-Info)
+# This is a user-friendly name for the A-ID. For example, the enterprise name
+# and server name in a human-readable format. This field is encoded as UTF-8.
+#eap_fast_a_id_info=test server
 
 # Enable/disable different EAP-FAST provisioning modes:
 #0 = provisioning disabled
index 2e4ed1b..4ba4b23 100644 (file)
@@ -1605,6 +1605,8 @@ int ieee802_1x_init(struct hostapd_data *hapd)
        conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len;
        conf.pac_opaque_encr_key = hapd->conf->pac_opaque_encr_key;
        conf.eap_fast_a_id = hapd->conf->eap_fast_a_id;
+       conf.eap_fast_a_id_len = hapd->conf->eap_fast_a_id_len;
+       conf.eap_fast_a_id_info = hapd->conf->eap_fast_a_id_info;
        conf.eap_fast_prov = hapd->conf->eap_fast_prov;
        conf.pac_key_lifetime = hapd->conf->pac_key_lifetime;
        conf.pac_key_refresh_time = hapd->conf->pac_key_refresh_time;
index 179eaa0..0786f56 100644 (file)
@@ -1151,8 +1151,16 @@ struct eap_sm * eap_server_sm_init(void *eapol_ctx,
                                  conf->pac_opaque_encr_key, 16);
                }
        }
-       if (conf->eap_fast_a_id)
-               sm->eap_fast_a_id = os_strdup(conf->eap_fast_a_id);
+       if (conf->eap_fast_a_id) {
+               sm->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len);
+               if (sm->eap_fast_a_id) {
+                       os_memcpy(sm->eap_fast_a_id, conf->eap_fast_a_id,
+                                 conf->eap_fast_a_id_len);
+                       sm->eap_fast_a_id_len = conf->eap_fast_a_id_len;
+               }
+       }
+       if (conf->eap_fast_a_id_info)
+               sm->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info);
        sm->eap_fast_prov = conf->eap_fast_prov;
        sm->pac_key_lifetime = conf->pac_key_lifetime;
        sm->pac_key_refresh_time = conf->pac_key_refresh_time;
@@ -1186,6 +1194,7 @@ void eap_server_sm_deinit(struct eap_sm *sm)
        os_free(sm->identity);
        os_free(sm->pac_opaque_encr_key);
        os_free(sm->eap_fast_a_id);
+       os_free(sm->eap_fast_a_id_info);
        wpabuf_free(sm->eap_if.aaaEapReqData);
        wpabuf_free(sm->eap_if.aaaEapRespData);
        os_free(sm->eap_if.aaaEapKeyData);
index 965d188..0dfca33 100644 (file)
@@ -95,7 +95,9 @@ struct eap_config {
        Boolean backend_auth;
        int eap_server;
        u8 *pac_opaque_encr_key;
-       char *eap_fast_a_id;
+       u8 *eap_fast_a_id;
+       size_t eap_fast_a_id_len;
+       char *eap_fast_a_id_info;
        int eap_fast_prov;
        int pac_key_lifetime;
        int pac_key_refresh_time;
index c811fed..a97a41b 100644 (file)
@@ -56,7 +56,9 @@ struct eap_fast_data {
        int simck_idx;
 
        u8 pac_opaque_encr[16];
-       char *srv_id;
+       u8 *srv_id;
+       size_t srv_id_len;
+       char *srv_id_info;
 
        int anon_provisioning;
        int send_new_pac; /* server triggered re-keying of Tunnel PAC */
@@ -445,11 +447,24 @@ static void * eap_fast_init(struct eap_sm *sm)
                eap_fast_reset(sm, data);
                return NULL;
        }
-       data->srv_id = os_strdup(sm->eap_fast_a_id);
+       data->srv_id = os_malloc(sm->eap_fast_a_id_len);
        if (data->srv_id == NULL) {
                eap_fast_reset(sm, data);
                return NULL;
        }
+       os_memcpy(data->srv_id, sm->eap_fast_a_id, sm->eap_fast_a_id_len);
+       data->srv_id_len = sm->eap_fast_a_id_len;
+
+       if (sm->eap_fast_a_id_info == NULL) {
+               wpa_printf(MSG_INFO, "EAP-FAST: No A-ID-Info configured");
+               eap_fast_reset(sm, data);
+               return NULL;
+       }
+       data->srv_id_info = os_strdup(sm->eap_fast_a_id_info);
+       if (data->srv_id_info == NULL) {
+               eap_fast_reset(sm, data);
+               return NULL;
+       }
 
        /* PAC-Key lifetime in seconds (hard limit) */
        data->pac_key_lifetime = sm->pac_key_lifetime;
@@ -474,6 +489,7 @@ static void eap_fast_reset(struct eap_sm *sm, void *priv)
                data->phase2_method->reset(sm, data->phase2_priv);
        eap_server_tls_ssl_deinit(sm, &data->ssl);
        os_free(data->srv_id);
+       os_free(data->srv_id_info);
        os_free(data->key_block_p);
        wpabuf_free(data->pending_phase2_resp);
        os_free(data->identity);
@@ -485,10 +501,9 @@ static struct wpabuf * eap_fast_build_start(struct eap_sm *sm,
                                            struct eap_fast_data *data, u8 id)
 {
        struct wpabuf *req;
-       size_t srv_id_len = os_strlen(data->srv_id);
 
        req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_FAST,
-                           1 + sizeof(struct pac_tlv_hdr) + srv_id_len,
+                           1 + sizeof(struct pac_tlv_hdr) + data->srv_id_len,
                            EAP_CODE_REQUEST, id);
        if (req == NULL) {
                wpa_printf(MSG_ERROR, "EAP-FAST: Failed to allocate memory for"
@@ -500,7 +515,7 @@ static struct wpabuf * eap_fast_build_start(struct eap_sm *sm,
        wpabuf_put_u8(req, EAP_TLS_FLAGS_START | data->fast_version);
 
        /* RFC 4851, 4.1.1. Authority ID Data */
-       eap_fast_put_tlv(req, PAC_TYPE_A_ID, data->srv_id, srv_id_len);
+       eap_fast_put_tlv(req, PAC_TYPE_A_ID, data->srv_id, data->srv_id_len);
 
        eap_fast_state(data, PHASE1);
 
@@ -648,7 +663,7 @@ static struct wpabuf * eap_fast_build_pac(struct eap_sm *sm,
        u8 *pac_buf, *pac_opaque;
        struct wpabuf *buf;
        u8 *pos;
-       size_t buf_len, srv_id_len, pac_len;
+       size_t buf_len, srv_id_info_len, pac_len;
        struct eap_tlv_hdr *pac_tlv;
        struct pac_tlv_hdr *pac_info;
        struct eap_tlv_result_tlv *result;
@@ -666,7 +681,7 @@ static struct wpabuf * eap_fast_build_pac(struct eap_sm *sm,
        if (pac_buf == NULL)
                return NULL;
 
-       srv_id_len = os_strlen(data->srv_id);
+       srv_id_info_len = os_strlen(data->srv_id_info);
 
        pos = pac_buf;
        *pos++ = PAC_OPAQUE_TYPE_KEY;
@@ -712,7 +727,7 @@ static struct wpabuf * eap_fast_build_pac(struct eap_sm *sm,
        buf_len = sizeof(*pac_tlv) +
                sizeof(struct pac_tlv_hdr) + EAP_FAST_PAC_KEY_LEN +
                sizeof(struct pac_tlv_hdr) + pac_len +
-               2 * srv_id_len + 100 + sizeof(*result);
+               data->srv_id_len + srv_id_info_len + 100 + sizeof(*result);
        buf = wpabuf_alloc(buf_len);
        if (buf == NULL) {
                os_free(pac_opaque);
@@ -749,12 +764,13 @@ static struct wpabuf * eap_fast_build_pac(struct eap_sm *sm,
        wpabuf_put_be32(buf, now.sec + data->pac_key_lifetime);
 
        /* A-ID (inside PAC-Info) */
-       eap_fast_put_tlv(buf, PAC_TYPE_A_ID, data->srv_id, srv_id_len);
+       eap_fast_put_tlv(buf, PAC_TYPE_A_ID, data->srv_id, data->srv_id_len);
        
        /* Note: headers may be misaligned after A-ID */
 
        /* A-ID-Info (inside PAC-Info) */
-       eap_fast_put_tlv(buf, PAC_TYPE_A_ID_INFO, data->srv_id, srv_id_len);
+       eap_fast_put_tlv(buf, PAC_TYPE_A_ID_INFO, data->srv_id_info,
+                        srv_id_info_len);
 
        /* PAC-Type (inside PAC-Info) */
        eap_fast_put_tlv_hdr(buf, PAC_TYPE_PAC_TYPE, 2);
index 4195466..d955ae9 100644 (file)
@@ -171,7 +171,9 @@ struct eap_sm {
        u8 *peer_challenge;
 
        u8 *pac_opaque_encr_key;
-       char *eap_fast_a_id;
+       u8 *eap_fast_a_id;
+       size_t eap_fast_a_id_len;
+       char *eap_fast_a_id_info;
        enum {
                NO_PROV, ANON_PROV, AUTH_PROV, BOTH_PROV
        } eap_fast_prov;
index e0c4b21..19be48a 100644 (file)
@@ -85,7 +85,9 @@ struct radius_server_data {
        void *eap_sim_db_priv;
        void *ssl_ctx;
        u8 *pac_opaque_encr_key;
-       char *eap_fast_a_id;
+       u8 *eap_fast_a_id;
+       size_t eap_fast_a_id_len;
+       char *eap_fast_a_id_info;
        int eap_fast_prov;
        int pac_key_lifetime;
        int pac_key_refresh_time;
@@ -314,6 +316,8 @@ radius_server_get_new_session(struct radius_server_data *data,
        eap_conf.eap_server = 1;
        eap_conf.pac_opaque_encr_key = data->pac_opaque_encr_key;
        eap_conf.eap_fast_a_id = data->eap_fast_a_id;
+       eap_conf.eap_fast_a_id_len = data->eap_fast_a_id_len;
+       eap_conf.eap_fast_a_id_info = data->eap_fast_a_id_info;
        eap_conf.eap_fast_prov = data->eap_fast_prov;
        eap_conf.pac_key_lifetime = data->pac_key_lifetime;
        eap_conf.pac_key_refresh_time = data->pac_key_refresh_time;
@@ -1020,8 +1024,16 @@ radius_server_init(struct radius_server_conf *conf)
                os_memcpy(data->pac_opaque_encr_key, conf->pac_opaque_encr_key,
                          16);
        }
-       if (conf->eap_fast_a_id)
-               data->eap_fast_a_id = os_strdup(conf->eap_fast_a_id);
+       if (conf->eap_fast_a_id) {
+               data->eap_fast_a_id = os_malloc(conf->eap_fast_a_id_len);
+               if (data->eap_fast_a_id) {
+                       os_memcpy(data->eap_fast_a_id, conf->eap_fast_a_id,
+                                 conf->eap_fast_a_id_len);
+                       data->eap_fast_a_id_len = conf->eap_fast_a_id_len;
+               }
+       }
+       if (conf->eap_fast_a_id_info)
+               data->eap_fast_a_id_info = os_strdup(conf->eap_fast_a_id_info);
        data->eap_fast_prov = conf->eap_fast_prov;
        data->pac_key_lifetime = conf->pac_key_lifetime;
        data->pac_key_refresh_time = conf->pac_key_refresh_time;
@@ -1074,6 +1086,7 @@ void radius_server_deinit(struct radius_server_data *data)
 
        os_free(data->pac_opaque_encr_key);
        os_free(data->eap_fast_a_id);
+       os_free(data->eap_fast_a_id_info);
        os_free(data);
 }
 
index 8e5145f..37c6527 100644 (file)
@@ -25,7 +25,9 @@ struct radius_server_conf {
        void *eap_sim_db_priv;
        void *ssl_ctx;
        u8 *pac_opaque_encr_key;
-       char *eap_fast_a_id;
+       u8 *eap_fast_a_id;
+       size_t eap_fast_a_id_len;
+       char *eap_fast_a_id_info;
        int eap_fast_prov;
        int pac_key_lifetime;
        int pac_key_refresh_time;