From e54cfbb56abd7585ae0182d43638db3fa4685df1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 20 Aug 2019 01:37:31 +0300 Subject: [PATCH] EAP-TEAP server: Allow a specific Identity-Type to be requested/required The new hostapd configuration parameter eap_teap_id can be used to configure the expected behavior for used identity type. Signed-off-by: Jouni Malinen --- hostapd/config_file.c | 2 + hostapd/hostapd.conf | 8 +++ src/ap/ap_config.h | 1 + src/ap/authsrv.c | 1 + src/ap/ieee802_1x.c | 1 + src/eap_server/eap.h | 7 +++ src/eap_server/eap_server_teap.c | 88 +++++++++++++++++++++++++++----- src/radius/radius_server.c | 1 + src/radius/radius_server.h | 1 + 9 files changed, 98 insertions(+), 12 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 1ef7d57cc..4a2f12d94 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2622,6 +2622,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->eap_teap_pac_no_inner = atoi(pos); } else if (os_strcmp(buf, "eap_teap_separate_result") == 0) { bss->eap_teap_separate_result = atoi(pos); + } else if (os_strcmp(buf, "eap_teap_id") == 0) { + bss->eap_teap_id = 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 f36e1fa3a..5497df24a 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1206,6 +1206,14 @@ eap_server=0 # 1 = send in a separate message (for testing purposes) #eap_teap_separate_result=0 +# EAP-TEAP identities +# 0 = allow any identity type (default) +# 1 = require user identity +# 2 = require machine identity +# 3 = request user identity; accept either user or machine identity +# 4 = request machine identity; accept either user or machine identity +#eap_teap_id=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 daf787e16..484e1b679 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -430,6 +430,7 @@ struct hostapd_bss_config { int eap_teap_auth; int eap_teap_pac_no_inner; int eap_teap_separate_result; + int eap_teap_id; int eap_sim_aka_result_ind; int eap_sim_id; int tnc; diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c index 21e4c22d8..1fd1e382b 100644 --- a/src/ap/authsrv.c +++ b/src/ap/authsrv.c @@ -123,6 +123,7 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd) srv.eap_teap_auth = conf->eap_teap_auth; srv.eap_teap_pac_no_inner = conf->eap_teap_pac_no_inner; srv.eap_teap_separate_result = conf->eap_teap_separate_result; + srv.eap_teap_id = conf->eap_teap_id; srv.eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; srv.eap_sim_id = conf->eap_sim_id; srv.tnc = conf->tnc; diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c index 34637f35e..fd47013ef 100644 --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c @@ -2433,6 +2433,7 @@ static struct eap_config * ieee802_1x_eap_config(struct hostapd_data *hapd) cfg->pac_key_refresh_time = hapd->conf->pac_key_refresh_time; cfg->eap_teap_auth = hapd->conf->eap_teap_auth; cfg->eap_teap_separate_result = hapd->conf->eap_teap_separate_result; + cfg->eap_teap_id = hapd->conf->eap_teap_id; cfg->eap_sim_aka_result_ind = hapd->conf->eap_sim_aka_result_ind; cfg->eap_sim_id = hapd->conf->eap_sim_id; cfg->tnc = hapd->conf->tnc; diff --git a/src/eap_server/eap.h b/src/eap_server/eap.h index 6988e0b0f..0b8265e46 100644 --- a/src/eap_server/eap.h +++ b/src/eap_server/eap.h @@ -198,6 +198,13 @@ struct eap_config { int eap_teap_auth; int eap_teap_pac_no_inner; int eap_teap_separate_result; + enum eap_teap_id { + EAP_TEAP_ID_ALLOW_ANY = 0, + EAP_TEAP_ID_REQUIRE_USER = 1, + 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; /** * 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 f2f917b77..f45034e14 100644 --- a/src/eap_server/eap_server_teap.c +++ b/src/eap_server/eap_server_teap.c @@ -529,30 +529,56 @@ static struct wpabuf * eap_teap_build_phase2_req(struct eap_sm *sm, struct eap_teap_data *data, u8 id) { - struct wpabuf *req; + struct wpabuf *req, *id_tlv = NULL; + + if (sm->cfg->eap_teap_auth == 1 || + (data->phase2_priv && data->phase2_method && + data->phase2_method->vendor == EAP_VENDOR_IETF && + data->phase2_method->method == EAP_TYPE_IDENTITY)) { + switch (sm->cfg->eap_teap_id) { + case EAP_TEAP_ID_ALLOW_ANY: + 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); + 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); + break; + } + } if (sm->cfg->eap_teap_auth == 1) { wpa_printf(MSG_DEBUG, "EAP-TEAP: Initiate Basic-Password-Auth"); req = wpabuf_alloc(sizeof(struct teap_tlv_hdr)); - if (!req) + if (!req) { + wpabuf_free(id_tlv); return NULL; + } eap_teap_put_tlv_hdr(req, TEAP_TLV_BASIC_PASSWORD_AUTH_REQ, 0); - return req; + return wpabuf_concat(req, id_tlv); } wpa_printf(MSG_DEBUG, "EAP-TEAP: Initiate inner EAP method"); if (!data->phase2_priv) { wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 2 method not initialized"); + wpabuf_free(id_tlv); return NULL; } req = data->phase2_method->buildReq(sm, data->phase2_priv, id); - if (!req) + if (!req) { + wpabuf_free(id_tlv); return NULL; + } wpa_hexdump_buf_key(MSG_MSGDUMP, "EAP-TEAP: Phase 2 EAP-Request", req); - return eap_teap_tlv_eap_payload(req); + + return wpabuf_concat(eap_teap_tlv_eap_payload(req), id_tlv); } @@ -960,9 +986,27 @@ 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, + enum teap_identity_types id_type) +{ + if (sm->cfg->eap_teap_id == EAP_TEAP_ID_REQUIRE_USER && + id_type != TEAP_IDENTITY_TYPE_USER) + return 0; + 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_ALLOW_ANY && + id_type != TEAP_IDENTITY_TYPE_USER && + id_type != TEAP_IDENTITY_TYPE_MACHINE) + return 0; + return 1; +} + + static void eap_teap_process_phase2_response(struct eap_sm *sm, struct eap_teap_data *data, - u8 *in_data, size_t in_len) + u8 *in_data, size_t in_len, + enum teap_identity_types id_type) { int next_vendor = EAP_VENDOR_IETF; enum eap_type next_type = EAP_TYPE_NONE; @@ -1041,6 +1085,13 @@ 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)) { + wpa_printf(MSG_DEBUG, + "EAP-TEAP: Provided Identity-Type %u not allowed", + id_type); + eap_teap_req_failure(data, TEAP_ERROR_INNER_METHOD); + break; + } if (eap_user_get(sm, sm->identity, sm->identity_len, 1) != 0) { wpa_hexdump_ascii(MSG_DEBUG, "EAP-TEAP: Phase 2 Identity not found in the user database", @@ -1097,7 +1148,8 @@ static void eap_teap_process_phase2_response(struct eap_sm *sm, static void eap_teap_process_phase2_eap(struct eap_sm *sm, struct eap_teap_data *data, - u8 *in_data, size_t in_len) + u8 *in_data, size_t in_len, + enum teap_identity_types id_type) { struct eap_hdr *hdr; size_t len; @@ -1124,7 +1176,8 @@ static void eap_teap_process_phase2_eap(struct eap_sm *sm, (unsigned long) len); switch (hdr->code) { case EAP_CODE_RESPONSE: - eap_teap_process_phase2_response(sm, data, (u8 *) hdr, len); + eap_teap_process_phase2_response(sm, data, (u8 *) hdr, len, + id_type); break; default: wpa_printf(MSG_INFO, @@ -1137,11 +1190,20 @@ static void eap_teap_process_phase2_eap(struct eap_sm *sm, static void eap_teap_process_basic_auth_resp(struct eap_sm *sm, struct eap_teap_data *data, - u8 *in_data, size_t in_len) -{ + 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)) { + wpa_printf(MSG_DEBUG, + "EAP-TEAP: Provided Identity-Type %u not allowed", + id_type); + eap_teap_req_failure(data, 0); + return; + } + pos = in_data; end = pos + in_len; @@ -1533,7 +1595,8 @@ static void eap_teap_process_phase2_tlvs(struct eap_sm *sm, return; } eap_teap_process_basic_auth_resp(sm, data, tlv.basic_auth_resp, - tlv.basic_auth_resp_len); + tlv.basic_auth_resp_len, + tlv.identity_type); } if (tlv.eap_payload_tlv) { @@ -1544,7 +1607,8 @@ static void eap_teap_process_phase2_tlvs(struct eap_sm *sm, return; } eap_teap_process_phase2_eap(sm, data, tlv.eap_payload_tlv, - tlv.eap_payload_tlv_len); + tlv.eap_payload_tlv_len, + tlv.identity_type); } if (data->state == SUCCESS_SEND_RESULT && diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c index a24caec11..067147b7b 100644 --- a/src/radius/radius_server.c +++ b/src/radius/radius_server.c @@ -2242,6 +2242,7 @@ radius_server_init(struct radius_server_conf *conf) eap_cfg->eap_teap_auth = conf->eap_teap_auth; eap_cfg->eap_teap_pac_no_inner = conf->eap_teap_pac_no_inner; eap_cfg->eap_teap_separate_result = conf->eap_teap_separate_result; + eap_cfg->eap_teap_id = conf->eap_teap_id; data->get_eap_user = conf->get_eap_user; eap_cfg->eap_sim_aka_result_ind = conf->eap_sim_aka_result_ind; eap_cfg->eap_sim_id = conf->eap_sim_id; diff --git a/src/radius/radius_server.h b/src/radius/radius_server.h index c8c17dbb6..580a653ef 100644 --- a/src/radius/radius_server.h +++ b/src/radius/radius_server.h @@ -131,6 +131,7 @@ struct radius_server_conf { int eap_teap_auth; int eap_teap_pac_no_inner; int eap_teap_separate_result; + int eap_teap_id; /** * eap_sim_aka_result_ind - EAP-SIM/AKA protected success indication