From: Jouni Malinen Date: Sat, 24 Aug 2019 13:48:34 +0000 (+0300) Subject: EAP-TEAP server: Add support for requiring user and machine credentials X-Git-Tag: hostap_2_10~2412 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=93cd29d2b8b8f2dd3c359dba8699bd418dccc200;p=thirdparty%2Fhostap.git EAP-TEAP server: Add support for requiring user and machine credentials The new eap_teap_id=5 hostapd configuration parameter value can be used to configure EAP-TEAP server to request and require user and machine credentials within the tunnel. This can be done either with Basic Password Authentication or with inner EAP authentication methods. Signed-off-by: Jouni Malinen --- diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 5497df24a..b6091a1e2 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1212,6 +1212,7 @@ eap_server=0 # 2 = require machine identity # 3 = request user identity; accept either user or machine identity # 4 = request machine identity; accept either user or machine identity +# 5 = require both user and machine identity #eap_teap_id=0 # EAP-SIM and EAP-AKA protected success/failure indication using AT_RESULT_IND diff --git a/src/eap_server/eap.h b/src/eap_server/eap.h index 0b8265e46..9192c1af6 100644 --- a/src/eap_server/eap.h +++ b/src/eap_server/eap.h @@ -204,6 +204,7 @@ struct eap_config { EAP_TEAP_ID_REQUIRE_MACHINE = 2, EAP_TEAP_ID_REQUEST_USER_ACCEPT_MACHINE = 3, EAP_TEAP_ID_REQUEST_MACHINE_ACCEPT_USER = 4, + EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE = 5, } eap_teap_id; /** diff --git a/src/eap_server/eap_server_teap.c b/src/eap_server/eap_server_teap.c index 295f4df3c..a2cbf7a7b 100644 --- a/src/eap_server/eap_server_teap.c +++ b/src/eap_server/eap_server_teap.c @@ -56,6 +56,8 @@ struct eap_teap_data { size_t srv_id_len; char *srv_id_info; + unsigned int basic_auth_not_done:1; + unsigned int inner_eap_not_done:1; int anon_provisioning; int skipped_inner_auth; int send_new_pac; /* server triggered re-keying of Tunnel PAC */ @@ -71,6 +73,7 @@ struct eap_teap_data { int pac_key_refresh_time; enum teap_error_codes error_code; + enum teap_identity_types cur_id_type; }; @@ -541,19 +544,27 @@ static struct wpabuf * eap_teap_build_phase2_req(struct eap_sm *sm, break; case EAP_TEAP_ID_REQUIRE_USER: case EAP_TEAP_ID_REQUEST_USER_ACCEPT_MACHINE: - id_tlv = eap_teap_tlv_identity_type( - TEAP_IDENTITY_TYPE_USER); + data->cur_id_type = TEAP_IDENTITY_TYPE_USER; + id_tlv = eap_teap_tlv_identity_type(data->cur_id_type); break; case EAP_TEAP_ID_REQUIRE_MACHINE: case EAP_TEAP_ID_REQUEST_MACHINE_ACCEPT_USER: - id_tlv = eap_teap_tlv_identity_type( - TEAP_IDENTITY_TYPE_MACHINE); + data->cur_id_type = TEAP_IDENTITY_TYPE_MACHINE; + id_tlv = eap_teap_tlv_identity_type(data->cur_id_type); + break; + case EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE: + if (data->cur_id_type == TEAP_IDENTITY_TYPE_USER) + data->cur_id_type = TEAP_IDENTITY_TYPE_MACHINE; + else + data->cur_id_type = TEAP_IDENTITY_TYPE_USER; + id_tlv = eap_teap_tlv_identity_type(data->cur_id_type); break; } } if (sm->cfg->eap_teap_auth == 1) { wpa_printf(MSG_DEBUG, "EAP-TEAP: Initiate Basic-Password-Auth"); + data->basic_auth_not_done = 1; req = wpabuf_alloc(sizeof(struct teap_tlv_hdr)); if (!req) { wpabuf_free(id_tlv); @@ -564,6 +575,7 @@ static struct wpabuf * eap_teap_build_phase2_req(struct eap_sm *sm, } wpa_printf(MSG_DEBUG, "EAP-TEAP: Initiate inner EAP method"); + data->inner_eap_not_done = 1; if (!data->phase2_priv) { wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 2 method not initialized"); @@ -596,12 +608,14 @@ static struct wpabuf * eap_teap_build_crypto_binding( return NULL; if (data->send_new_pac || data->anon_provisioning || + data->basic_auth_not_done || data->inner_eap_not_done || data->phase2_method || sm->cfg->eap_teap_separate_result) data->final_result = 0; else data->final_result = 1; - if (!data->final_result || data->eap_seq > 0) { + if (!data->final_result || data->eap_seq > 0 || + sm->cfg->eap_teap_auth == 1) { /* Intermediate-Result */ wpa_printf(MSG_DEBUG, "EAP-TEAP: Add Intermediate-Result TLV (status=SUCCESS)"); @@ -987,7 +1001,7 @@ static int eap_teap_phase2_init(struct eap_sm *sm, struct eap_teap_data *data, } -static int eap_teap_valid_id_type(struct eap_sm *sm, +static int eap_teap_valid_id_type(struct eap_sm *sm, struct eap_teap_data *data, enum teap_identity_types id_type) { if (sm->cfg->eap_teap_id == EAP_TEAP_ID_REQUIRE_USER && @@ -996,6 +1010,9 @@ static int eap_teap_valid_id_type(struct eap_sm *sm, if (sm->cfg->eap_teap_id == EAP_TEAP_ID_REQUIRE_MACHINE && id_type != TEAP_IDENTITY_TYPE_MACHINE) return 0; + if (sm->cfg->eap_teap_id == EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE && + id_type != data->cur_id_type) + return 0; if (sm->cfg->eap_teap_id != EAP_TEAP_ID_ALLOW_ANY && id_type != TEAP_IDENTITY_TYPE_USER && id_type != TEAP_IDENTITY_TYPE_MACHINE) @@ -1086,7 +1103,7 @@ static void eap_teap_process_phase2_response(struct eap_sm *sm, switch (data->state) { case PHASE2_ID: - if (!eap_teap_valid_id_type(sm, id_type)) { + if (!eap_teap_valid_id_type(sm, data, id_type)) { wpa_printf(MSG_DEBUG, "EAP-TEAP: Provided Identity-Type %u not allowed", id_type); @@ -1122,6 +1139,11 @@ static void eap_teap_process_phase2_response(struct eap_sm *sm, case PHASE2_METHOD: case CRYPTO_BINDING: eap_teap_update_icmk(sm, data); + if (data->state == PHASE2_METHOD && + (sm->cfg->eap_teap_id != + EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE || + data->cur_id_type == TEAP_IDENTITY_TYPE_MACHINE)) + data->inner_eap_not_done = 0; eap_teap_state(data, CRYPTO_BINDING); data->eap_seq++; next_vendor = EAP_VENDOR_IETF; @@ -1193,11 +1215,11 @@ static void eap_teap_process_basic_auth_resp(struct eap_sm *sm, struct eap_teap_data *data, u8 *in_data, size_t in_len, enum teap_identity_types id_type) - { +{ u8 *pos, *end, *username, *password, *new_id; u8 userlen, passlen; - if (!eap_teap_valid_id_type(sm, id_type)) { + if (!eap_teap_valid_id_type(sm, data, id_type)) { wpa_printf(MSG_DEBUG, "EAP-TEAP: Provided Identity-Type %u not allowed", id_type); @@ -1282,6 +1304,9 @@ static void eap_teap_process_basic_auth_resp(struct eap_sm *sm, sm->identity = new_id; sm->identity_len = userlen; } + if (sm->cfg->eap_teap_id != EAP_TEAP_ID_REQUIRE_USER_AND_MACHINE || + data->cur_id_type == TEAP_IDENTITY_TYPE_MACHINE) + data->basic_auth_not_done = 0; eap_teap_state(data, CRYPTO_BINDING); eap_teap_update_icmk(sm, data); } @@ -1618,6 +1643,19 @@ static void eap_teap_process_phase2_tlvs(struct eap_sm *sm, wpa_printf(MSG_DEBUG, "EAP-TEAP: Peer agreed with final success - authentication completed"); eap_teap_state(data, SUCCESS); + } else if (check_crypto_binding && data->state == CRYPTO_BINDING && + sm->cfg->eap_teap_auth == 1 && data->basic_auth_not_done) { + wpa_printf(MSG_DEBUG, + "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) { + wpa_printf(MSG_DEBUG, + "EAP-TEAP: Continue with inner EAP authentication for second credential"); + 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); } }