]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
EAP-TTLS peer: Support vendor EAP method in Phase 2
authorJouni Malinen <j@w1.fi>
Sat, 17 Aug 2019 09:11:50 +0000 (12:11 +0300)
committerJouni Malinen <j@w1.fi>
Sat, 17 Aug 2019 13:14:56 +0000 (16:14 +0300)
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_ttls.c

index 1c8dbe2b433101e51cc4c547dac05a494b30c6f2..bed4094a9764f6e660d6085c787d55bb22390993 100644 (file)
@@ -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;
        }