]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
EAP-TEAP peer: Support vendor EAP method in Phase 2
authorJouni Malinen <j@w1.fi>
Sat, 17 Aug 2019 13:12:09 +0000 (16:12 +0300)
committerJouni Malinen <j@w1.fi>
Sat, 17 Aug 2019 13:18:21 +0000 (16:18 +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_common/eap_teap_common.c
src/eap_common/eap_teap_common.h
src/eap_peer/eap_teap.c

index 0af7f4a13de6b5a7389f72eb0e004b90866dd51f..3c21d8bb3a55eeb08210c2e8b80bdc77e6799a6d 100644 (file)
@@ -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);
 }
 
 
index 7448cf51de6be430146e1a5f8ccc69ddfdca5aa8..d92e4ca2f71c5d71331a687b886338fb2f00cc81 100644 (file)
@@ -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 */
index 801e4a3920e9f944c3d09b2b16da0a3d24e17ba3..3dee2ad16882b6dabde46500b3ac3825ada1eb16 100644 (file)
@@ -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)) {