From: Jouni Malinen Date: Sat, 17 Aug 2019 13:12:09 +0000 (+0300) Subject: EAP-TEAP peer: Support vendor EAP method in Phase 2 X-Git-Tag: hostap_2_10~2439 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fhostap.git;a=commitdiff_plain;h=62af2b18f74dbb848cba31dcf5fa7db6863df4bd EAP-TEAP peer: Support vendor EAP method in Phase 2 The implementation was previously hardcoded to use only the non-expanded IETF EAP methods in Phase 2. Extend that to allow vendor EAP methods with expanded header to be used. Signed-off-by: Jouni Malinen --- diff --git a/src/eap_common/eap_teap_common.c b/src/eap_common/eap_teap_common.c index 0af7f4a13..3c21d8bb3 100644 --- a/src/eap_common/eap_teap_common.c +++ b/src/eap_common/eap_teap_common.c @@ -679,12 +679,13 @@ struct wpabuf * eap_teap_tlv_error(enum teap_error_codes error) } -int eap_teap_allowed_anon_prov_phase2_method(u8 type) +int eap_teap_allowed_anon_prov_phase2_method(int vendor, enum eap_type type) { /* RFC 7170, Section 3.8.3: MUST provide mutual authentication, * provide key generation, and be resistant to dictionary attack. * Section 3.8 also mentions requirement for using EMSK Compound MAC. */ - return type == EAP_TYPE_PWD || type == EAP_TYPE_EKE; + return vendor == EAP_VENDOR_IETF && + (type == EAP_TYPE_PWD || type == EAP_TYPE_EKE); } diff --git a/src/eap_common/eap_teap_common.h b/src/eap_common/eap_teap_common.h index 7448cf51d..d92e4ca2f 100644 --- a/src/eap_common/eap_teap_common.h +++ b/src/eap_common/eap_teap_common.h @@ -215,7 +215,8 @@ int eap_teap_parse_tlv(struct eap_teap_tlv_parse *tlv, const char * eap_teap_tlv_type_str(enum teap_tlv_types type); struct wpabuf * eap_teap_tlv_result(int status, int intermediate); struct wpabuf * eap_teap_tlv_error(enum teap_error_codes error); -int eap_teap_allowed_anon_prov_phase2_method(u8 type); +enum eap_type; +int eap_teap_allowed_anon_prov_phase2_method(int vendor, enum eap_type type); int eap_teap_allowed_anon_prov_cipher_suite(u16 cs); #endif /* EAP_TEAP_H */ diff --git a/src/eap_peer/eap_teap.c b/src/eap_peer/eap_teap.c index 801e4a392..3dee2ad16 100644 --- a/src/eap_peer/eap_teap.c +++ b/src/eap_peer/eap_teap.c @@ -327,7 +327,8 @@ static int eap_teap_init_phase2_method(struct eap_sm *sm, } -static int eap_teap_select_phase2_method(struct eap_teap_data *data, u8 type) +static int eap_teap_select_phase2_method(struct eap_teap_data *data, + int vendor, enum eap_type type) { size_t i; @@ -335,15 +336,15 @@ static int eap_teap_select_phase2_method(struct eap_teap_data *data, u8 type) * completed inner EAP authentication (EAP-pwd or EAP-EKE) and TNC */ if (data->anon_provisioning && - !eap_teap_allowed_anon_prov_phase2_method(type)) { + !eap_teap_allowed_anon_prov_phase2_method(vendor, type)) { wpa_printf(MSG_INFO, - "EAP-TEAP: EAP type %u not allowed during unauthenticated provisioning", - type); + "EAP-TEAP: EAP type %u:%u not allowed during unauthenticated provisioning", + vendor, type); return -1; } #ifdef EAP_TNC - if (type == EAP_TYPE_TNC) { + if (vendor == EAP_VENDOR_IETF && type == EAP_TYPE_TNC) { data->phase2_type.vendor = EAP_VENDOR_IETF; data->phase2_type.method = EAP_TYPE_TNC; wpa_printf(MSG_DEBUG, @@ -355,7 +356,7 @@ static int eap_teap_select_phase2_method(struct eap_teap_data *data, u8 type) #endif /* EAP_TNC */ for (i = 0; i < data->num_phase2_types; i++) { - if (data->phase2_types[i].vendor != EAP_VENDOR_IETF || + if (data->phase2_types[i].vendor != vendor || data->phase2_types[i].method != type) continue; @@ -368,7 +369,9 @@ static int eap_teap_select_phase2_method(struct eap_teap_data *data, u8 type) break; } - if (type != data->phase2_type.method || type == EAP_TYPE_NONE) + if (vendor != data->phase2_type.vendor || + type != data->phase2_type.method || + (vendor == EAP_VENDOR_IETF && type == EAP_TYPE_NONE)) return -1; return 0; @@ -386,6 +389,8 @@ static int eap_teap_phase2_request(struct eap_sm *sm, struct eap_method_ret iret; struct eap_peer_config *config = eap_get_config(sm); struct wpabuf msg; + int vendor = EAP_VENDOR_IETF; + enum eap_type method; if (len <= sizeof(struct eap_hdr)) { wpa_printf(MSG_INFO, @@ -394,14 +399,27 @@ static int eap_teap_phase2_request(struct eap_sm *sm, return -1; } pos = (u8 *) (hdr + 1); - wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 2 Request: type=%d", *pos); - if (*pos == EAP_TYPE_IDENTITY) { + method = *pos; + if (method == EAP_TYPE_EXPANDED) { + if (len < sizeof(struct eap_hdr) + 8) { + wpa_printf(MSG_INFO, + "EAP-TEAP: Too short Phase 2 request (expanded header) (len=%lu)", + (unsigned long) len); + return -1; + } + vendor = WPA_GET_BE24(pos + 1); + method = WPA_GET_BE32(pos + 4); + } + wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 2 Request: type=%u:%u", + vendor, method); + if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_IDENTITY) { *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1); return 0; } if (data->phase2_priv && data->phase2_method && - *pos != data->phase2_type.method) { + (vendor != data->phase2_type.vendor || + method != data->phase2_type.method)) { wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 2 EAP sequence - deinitialize previous method"); data->phase2_method->deinit(sm, data->phase2_priv); @@ -413,7 +431,7 @@ static int eap_teap_phase2_request(struct eap_sm *sm, if (data->phase2_type.vendor == EAP_VENDOR_IETF && data->phase2_type.method == EAP_TYPE_NONE && - eap_teap_select_phase2_method(data, *pos) < 0) { + eap_teap_select_phase2_method(data, vendor, method) < 0) { if (eap_peer_tls_phase2_nak(data->phase2_types, data->num_phase2_types, hdr, resp)) @@ -424,8 +442,8 @@ static int eap_teap_phase2_request(struct eap_sm *sm, if ((!data->phase2_priv && eap_teap_init_phase2_method(sm, data) < 0) || !data->phase2_method) { wpa_printf(MSG_INFO, - "EAP-TEAP: Failed to initialize Phase 2 EAP method %d", - *pos); + "EAP-TEAP: Failed to initialize Phase 2 EAP method %u:%u", + vendor, method); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; return -1; @@ -1333,6 +1351,7 @@ static int eap_teap_process_decrypted(struct eap_sm *sm, data->phase2_method->vendor == 0 && eap_teap_allowed_anon_prov_cipher_suite(data->tls_cs) && eap_teap_allowed_anon_prov_phase2_method( + data->phase2_method->vendor, data->phase2_method->method))) && (tlv.iresult == TEAP_STATUS_SUCCESS || tlv.result == TEAP_STATUS_SUCCESS)) {