EAP-TTLS 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>
This commit is contained in:
Jouni Malinen
2019-08-17 12:11:50 +03:00
committed by Sarvesh Bodakhe
parent a9170c6a20
commit a5b01a93ff

View File

@@ -259,11 +259,11 @@ static u8 * eap_ttls_implicit_challenge(struct eap_sm *sm,
static void eap_ttls_phase2_select_eap_method(struct eap_ttls_data *data, static void eap_ttls_phase2_select_eap_method(struct eap_ttls_data *data,
u8 method) int vendor, enum eap_type method)
{ {
size_t i; size_t i;
for (i = 0; i < data->num_phase2_eap_types; 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) data->phase2_eap_types[i].method != method)
continue; continue;
@@ -310,17 +310,19 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
struct eap_ttls_data *data, struct eap_ttls_data *data,
struct eap_method_ret *ret, struct eap_method_ret *ret,
struct eap_hdr *hdr, size_t len, struct eap_hdr *hdr, size_t len,
u8 method, struct wpabuf **resp) int vendor, enum eap_type method,
struct wpabuf **resp)
{ {
#ifdef EAP_TNC #ifdef EAP_TNC
if (data->tnc_started && data->phase2_method && 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) data->phase2_eap_type.method == EAP_TYPE_TNC)
return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len, return eap_ttls_phase2_eap_process(sm, data, ret, hdr, len,
resp); resp);
if (data->ready_for_tnc && !data->tnc_started && 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 " wpa_printf(MSG_DEBUG, "EAP-TTLS: Start TNC after completed "
"EAP method"); "EAP method");
data->tnc_started = 1; data->tnc_started = 1;
@@ -334,7 +336,7 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
return -1; return -1;
} }
data->phase2_eap_type.vendor = EAP_VENDOR_IETF; data->phase2_eap_type.vendor = vendor;
data->phase2_eap_type.method = method; data->phase2_eap_type.method = method;
wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected " wpa_printf(MSG_DEBUG, "EAP-TTLS: Selected "
"Phase 2 EAP vendor %d method %d (TNC)", "Phase 2 EAP vendor %d method %d (TNC)",
@@ -348,10 +350,11 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF && if (data->phase2_eap_type.vendor == EAP_VENDOR_IETF &&
data->phase2_eap_type.method == EAP_TYPE_NONE) 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, if (eap_peer_tls_phase2_nak(data->phase2_eap_types,
data->num_phase2_eap_types, data->num_phase2_eap_types,
hdr, resp)) hdr, resp))
@@ -360,8 +363,7 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
} }
if (data->phase2_priv == NULL) { if (data->phase2_priv == NULL) {
data->phase2_method = eap_peer_get_eap_method( data->phase2_method = eap_peer_get_eap_method(vendor, method);
EAP_VENDOR_IETF, method);
if (data->phase2_method) { if (data->phase2_method) {
sm->init_phase2 = 1; sm->init_phase2 = 1;
data->phase2_priv = data->phase2_method->init(sm); data->phase2_priv = data->phase2_method->init(sm);
@@ -369,8 +371,9 @@ static int eap_ttls_phase2_request_eap_method(struct eap_sm *sm,
} }
} }
if (data->phase2_priv == NULL || data->phase2_method == NULL) { if (data->phase2_priv == NULL || data->phase2_method == NULL) {
wpa_printf(MSG_INFO, "EAP-TTLS: failed to initialize " wpa_printf(MSG_INFO,
"Phase 2 EAP method %d", method); "EAP-TTLS: failed to initialize Phase 2 EAP method %u:%u",
vendor, method);
return -1; return -1;
} }
@@ -399,9 +402,23 @@ static int eap_ttls_phase2_request_eap(struct eap_sm *sm,
case EAP_TYPE_IDENTITY: case EAP_TYPE_IDENTITY:
*resp = eap_sm_buildIdentity(sm, hdr->identifier, 1); *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
break; 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: default:
if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len, if (eap_ttls_phase2_request_eap_method(sm, data, ret, hdr, len,
*pos, resp) < 0) EAP_VENDOR_IETF, *pos,
resp) < 0)
return -1; return -1;
break; break;
} }