diff --git a/src/eap_peer/eap_ttls.c b/src/eap_peer/eap_ttls.c index 1c8dbe2b4..bed4094a9 100644 --- a/src/eap_peer/eap_ttls.c +++ b/src/eap_peer/eap_ttls.c @@ -311,11 +311,11 @@ static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm, static void eap_ttls_phase2_select_eap_method(struct eap_ttls_data *data, - u8 method) + int vendor, enum eap_type method) { size_t i; for (i = 0; i < data->num_phase2_eap_types; i++) { - if (data->phase2_eap_types[i].vendor != EAP_VENDOR_IETF || + if (data->phase2_eap_types[i].vendor != vendor || data->phase2_eap_types[i].method != method) continue; @@ -362,17 +362,19 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm, struct eap_ttls_data *data, struct eap_method_ret *ret, struct eap_hdr *hdr, size_t len, - u8 method, struct wpabuf **resp) + int vendor, enum eap_type method, + struct wpabuf **resp) { #ifdef EAP_TNC if (data->tnc_started && data->phase2_method && - data->phase2_priv && method == EAP_TYPE_TNC && + data->phase2_priv && + vendor == EAP_VENDOR_IETF && method == EAP_TYPE_TNC && data->phase2_eap_type.method == EAP_TYPE_TNC) return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len, resp); if (data->ready_for_tnc && !data->tnc_started && - method == EAP_TYPE_TNC) { + vendor == EAP_VENDOR_IETF && method == EAP_TYPE_TNC) { wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed " "EAP method"); data->tnc_started = 1; @@ -386,7 +388,7 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm, return -1; } - data->phase2_eap_type.vendor = EAP_VENDOR_IETF; + data->phase2_eap_type.vendor = vendor; data->phase2_eap_type.method = method; wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected " "Phase 2 EAP vendor %d method %d (TNC)", @@ -400,10 +402,11 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm, if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF && data->phase2_eap_type.method == EAP_TYPE_NONE) - eap_ttls_phase2_select_eap_method(data, method); + eap_ttls_phase2_select_eap_method(data, vendor, method); - if (method != data->phase2_eap_type.method || method == EAP_TYPE_NONE) - { + if (vendor != data->phase2_eap_type.vendor || + method != data->phase2_eap_type.method || + (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE)) { if (eap_peer_tls_phase2_nak(data->phase2_eap_types, data->num_phase2_eap_types, hdr, resp)) @@ -412,8 +415,7 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm, } if (data->phase2_priv == NULL) { - data->phase2_method = eap_peer_get_eap_method( - EAP_VENDOR_IETF, method); + data->phase2_method = eap_peer_get_eap_method(vendor, method); if (data->phase2_method) { sm->init_phase2 = 1; data->phase2_priv = data->phase2_method->init(sm); @@ -421,8 +423,9 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm, } } if (data->phase2_priv == NULL || data->phase2_method == NULL) { - wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize " - "Phase 2 EAP method %d", method); + wpa_printf(MSG_INFO, + "EAP-TTLS: failed to initialize Phase 2 EAP method %u:%u", + vendor, method); return -1; } @@ -451,9 +454,23 @@ static int eap_ttls_phase2_request_eap(struct eap_sm *sm, case EAP_TYPE_IDENTITY: *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1); break; + case EAP_TYPE_EXPANDED: + if (len < sizeof(struct eap_hdr) + 8) { + wpa_printf(MSG_INFO, + "EAP-TTLS: Too short Phase 2 request (expanded header) (len=%lu)", + (unsigned long) len); + return -1; + } + if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len, + WPA_GET_BE24(pos + 1), + WPA_GET_BE32(pos + 4), + resp) < 0) + return -1; + break; default: if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len, - *pos, resp) < 0) + EAP_VENDOR_IETF, *pos, + resp) < 0) return -1; break; }