From 357c1062dc0d8a0efce8cd8d9ddab151d7ac9f72 Mon Sep 17 00:00:00 2001 From: Jouni Malinen <j@w1.fi> Date: Sat, 17 Aug 2019 15:58:26 +0300 Subject: [PATCH] EAP-FAST 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 <j@w1.fi> --- src/eap_peer/eap_fast.c | 48 +++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/src/eap_peer/eap_fast.c b/src/eap_peer/eap_fast.c index 94ce57d62..61d0a6b10 100644 --- a/src/eap_peer/eap_fast.c +++ b/src/eap_peer/eap_fast.c @@ -364,22 +364,24 @@ static int eap_fast_init_phase2_method(struct eap_sm *sm, } -static int eap_fast_select_phase2_method(struct eap_fast_data *data, u8 type) +static int eap_fast_select_phase2_method(struct eap_fast_data *data, + int vendor, enum eap_type type) { size_t i; /* TODO: TNC with anonymous provisioning; need to require both * completed MSCHAPv2 and TNC */ - if (data->anon_provisioning && type != EAP_TYPE_MSCHAPV2) { - wpa_printf(MSG_INFO, "EAP-FAST: Only EAP-MSCHAPv2 is allowed " - "during unauthenticated provisioning; reject phase2" - " type %d", type); + if (data->anon_provisioning && + (vendor != EAP_VENDOR_IETF || type != EAP_TYPE_MSCHAPV2)) { + wpa_printf(MSG_INFO, + "EAP-FAST: Only EAP-MSCHAPv2 is allowed during unauthenticated provisioning; reject phase2 type %u:%u", + 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, "EAP-FAST: Selected Phase 2 EAP " @@ -391,7 +393,7 @@ static int eap_fast_select_phase2_method(struct eap_fast_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; @@ -404,7 +406,9 @@ static int eap_fast_select_phase2_method(struct eap_fast_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; @@ -422,6 +426,8 @@ static int eap_fast_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, "EAP-FAST: too short " @@ -429,14 +435,27 @@ static int eap_fast_phase2_request(struct eap_sm *sm, return -1; } pos = (u8 *) (hdr + 1); - wpa_printf(MSG_DEBUG, "EAP-FAST: 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-FAST: 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-FAST: 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-FAST: Phase 2 EAP sequence - " "deinitialize previous method"); data->phase2_method->deinit(sm, data->phase2_priv); @@ -448,7 +467,7 @@ static int eap_fast_phase2_request(struct eap_sm *sm, if (data->phase2_type.vendor == EAP_VENDOR_IETF && data->phase2_type.method == EAP_TYPE_NONE && - eap_fast_select_phase2_method(data, *pos) < 0) { + eap_fast_select_phase2_method(data, vendor, method) < 0) { if (eap_peer_tls_phase2_nak(data->phase2_types, data->num_phase2_types, hdr, resp)) @@ -459,8 +478,9 @@ static int eap_fast_phase2_request(struct eap_sm *sm, if ((data->phase2_priv == NULL && eap_fast_init_phase2_method(sm, data) < 0) || data->phase2_method == NULL) { - wpa_printf(MSG_INFO, "EAP-FAST: Failed to initialize " - "Phase 2 EAP method %d", *pos); + wpa_printf(MSG_INFO, + "EAP-FAST: Failed to initialize Phase 2 EAP method %u:%u", + vendor, method); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; return -1;