diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 8a3357c26..a37d86ad5 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2585,6 +2585,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->eap_teap_separate_result = atoi(pos); } else if (os_strcmp(buf, "eap_teap_id") == 0) { bss->eap_teap_id = atoi(pos); + } else if (os_strcmp(buf, "eap_teap_method_sequence") == 0) { + bss->eap_teap_method_sequence = atoi(pos); #endif /* EAP_SERVER_TEAP */ #ifdef EAP_SERVER_SIM } else if (os_strcmp(buf, "eap_sim_db") == 0) { diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 01abd585e..427a49e0c 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1412,6 +1412,12 @@ eap_server=0 # 5 = require both user and machine identity #eap_teap_id=0 +# EAP-TEAP tunneled EAP method behavior +# 0 = minimize roundtrips by merging start of the next EAP method with the +# crypto-binding of the previous one. +# 1 = complete crypto-binding before starting the next EAP method +#eap_teap_method_sequence=0 + # EAP-SIM and EAP-AKA protected success/failure indication using AT_RESULT_IND # (default: 0 = disabled). #eap_sim_aka_result_ind=1 diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 330c9ed65..98ed81a98 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -443,6 +443,7 @@ struct hostapd_bss_config { int eap_teap_pac_no_inner; int eap_teap_separate_result; int eap_teap_id; + int eap_teap_method_sequence; int eap_sim_aka_result_ind; int eap_sim_id; char *imsi_privacy_key; diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c index fd9c96fad..4ab2a4a60 100644 --- a/src/ap/authsrv.c +++ b/src/ap/authsrv.c @@ -211,6 +211,7 @@ static struct eap_config * authsrv_eap_config(struct hostapd_data *hapd) cfg->eap_teap_pac_no_inner = hapd->conf->eap_teap_pac_no_inner; cfg->eap_teap_separate_result = hapd->conf->eap_teap_separate_result; cfg->eap_teap_id = hapd->conf->eap_teap_id; + cfg->eap_teap_method_sequence = hapd->conf->eap_teap_method_sequence; cfg->eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind; cfg->eap_sim_id = hapd->conf->eap_sim_id; cfg->imsi_privacy_key = hapd->imsi_privacy_key; diff --git a/src/eap_server/eap.h b/src/eap_server/eap.h index 2894cfbfe..3696e1d27 100644 --- a/src/eap_server/eap.h +++ b/src/eap_server/eap.h @@ -209,6 +209,7 @@ struct eap_config { EAP_TEAP_ID_REQUEST_MACHINE_ACCEPT_USER = 4, EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE = 5, } eap_teap_id; + int eap_teap_method_sequence; /** * eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication diff --git a/src/eap_server/eap_server_teap.c b/src/eap_server/eap_server_teap.c index 1e5e9a562..e32c6e48c 100644 --- a/src/eap_server/eap_server_teap.c +++ b/src/eap_server/eap_server_teap.c @@ -74,11 +74,15 @@ struct eap_teap_data { enum teap_error_codes error_code; enum teap_identity_types cur_id_type; + + bool check_crypto_binding; }; static int eap_teap_process_phase2_start(struct eap_sm *sm, struct eap_teap_data *data); +static int eap_teap_phase2_init(struct eap_sm *sm, struct eap_teap_data *data, + int vendor, enum eap_type eap_type); static const char * eap_teap_state_txt(int state) @@ -704,6 +708,8 @@ static struct wpabuf * eap_teap_build_crypto_binding( wpa_hexdump(MSG_MSGDUMP, "EAP-TEAP: MSK Compound MAC", cb->msk_compound_mac, sizeof(cb->msk_compound_mac)); + data->check_crypto_binding = true; + return buf; } @@ -889,6 +895,7 @@ static struct wpabuf * eap_teap_buildReq(struct eap_sm *sm, void *priv, u8 id) struct eap_teap_data *data = priv; struct wpabuf *req = NULL; int piggyback = 0; + bool move_to_method = true; if (data->ssl.state == FRAG_ACK) { return eap_server_tls_build_ack(id, EAP_TYPE_TEAP, @@ -940,6 +947,21 @@ static struct wpabuf * eap_teap_buildReq(struct eap_sm *sm, void *priv, u8 id) break; case CRYPTO_BINDING: req = eap_teap_build_crypto_binding(sm, data); + if (req && sm->cfg->eap_teap_auth == 0 && + data->inner_eap_not_done && + !data->phase2_method && + sm->cfg->eap_teap_method_sequence == 0) { + wpa_printf(MSG_DEBUG, + "EAP-TEAP: Continue with inner EAP authentication for second credential (optimized)"); + eap_teap_state(data, PHASE2_ID); + if (eap_teap_phase2_init(sm, data, EAP_VENDOR_IETF, + EAP_TYPE_IDENTITY) < 0) { + eap_teap_state(data, FAILURE); + wpabuf_free(req); + return NULL; + } + move_to_method = false; + } if (data->phase2_method) { /* * Include the start of the next EAP method in the @@ -950,7 +972,8 @@ static struct wpabuf * eap_teap_buildReq(struct eap_sm *sm, void *priv, u8 id) eap = eap_teap_build_phase2_req(sm, data, id); req = wpabuf_concat(req, eap); - eap_teap_state(data, PHASE2_METHOD); + if (move_to_method) + eap_teap_state(data, PHASE2_METHOD); } break; case REQUEST_PAC: @@ -1510,7 +1533,8 @@ static void eap_teap_process_phase2_tlvs(struct eap_sm *sm, struct wpabuf *in_data) { struct eap_teap_tlv_parse tlv; - int check_crypto_binding = data->state == CRYPTO_BINDING; + bool check_crypto_binding = data->state == CRYPTO_BINDING || + data->check_crypto_binding; if (eap_teap_parse_tlvs(in_data, &tlv) < 0) { wpa_printf(MSG_DEBUG, @@ -1593,6 +1617,7 @@ static void eap_teap_process_phase2_tlvs(struct eap_sm *sm, wpa_printf(MSG_DEBUG, "EAP-TEAP: Valid Crypto-Binding TLV received"); + data->check_crypto_binding = false; if (data->final_result) { wpa_printf(MSG_DEBUG, "EAP-TEAP: Authentication completed successfully"); @@ -1671,7 +1696,8 @@ static void eap_teap_process_phase2_tlvs(struct eap_sm *sm, "EAP-TEAP: Continue with basic password authentication for second credential"); eap_teap_state(data, PHASE2_BASIC_AUTH); } else if (check_crypto_binding && data->state == CRYPTO_BINDING && - sm->cfg->eap_teap_auth == 0 && data->inner_eap_not_done) { + sm->cfg->eap_teap_auth == 0 && data->inner_eap_not_done && + sm->cfg->eap_teap_method_sequence == 1) { wpa_printf(MSG_DEBUG, "EAP-TEAP: Continue with inner EAP authentication for second credential"); eap_teap_state(data, PHASE2_ID);