diff --git a/components/wpa_supplicant/src/eap_peer/eap.c b/components/wpa_supplicant/src/eap_peer/eap.c index 164448cd0c..640c0d8510 100644 --- a/components/wpa_supplicant/src/eap_peer/eap.c +++ b/components/wpa_supplicant/src/eap_peer/eap.c @@ -48,6 +48,7 @@ void eap_deinit_prev_method(struct eap_sm *sm, const char *txt); #ifdef EAP_PEER_METHOD static struct eap_method *eap_methods = NULL; +static struct eap_method_type *config_methods; const struct eap_method * eap_peer_get_eap_method(int vendor, EapType method) { @@ -71,6 +72,33 @@ const struct eap_method * eap_peer_get_methods(size_t *count) return eap_methods; } +/** + * eap_config_allowed_method - Check whether EAP method is allowed + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @config: EAP configuration + * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types + * @method: EAP type + * Returns: 1 = allowed EAP method, 0 = not allowed + */ +static int eap_config_allowed_method(struct eap_sm *sm, + struct eap_peer_config *config, + int vendor, u32 method) +{ + int i; + struct eap_method_type *m; + + if (config == NULL || config->eap_methods == NULL) + return 1; + + m = config->eap_methods; + for (i = 0; m[i].vendor != EAP_VENDOR_IETF || + m[i].method != EAP_TYPE_NONE; i++) { + if (m[i].vendor == vendor && m[i].method == method) + return 1; + } + return 0; +} + EapType eap_peer_get_type(const char *name, int *vendor) { struct eap_method *m; @@ -84,7 +112,21 @@ EapType eap_peer_get_type(const char *name, int *vendor) return EAP_TYPE_NONE; } -static int +/** + * eap_allowed_method - Check whether EAP method is allowed + * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() + * @vendor: Vendor-Id for expanded types or 0 = IETF for legacy types + * @method: EAP type + * Returns: 1 = allowed EAP method, 0 = not allowed + */ +int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method) +{ + return eap_config_allowed_method(sm, eap_get_config(sm), vendor, + method); +} + + +static int eap_allowed_phase2_type(int vendor, int type) { if (vendor != EAP_VENDOR_IETF) @@ -191,6 +233,21 @@ void eap_peer_unregister_methods(void) } } +bool eap_sm_allowMethod(struct eap_sm *sm, int vendor, + EapType method) +{ + if (!eap_allowed_method(sm, vendor, method)) { + wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: " + "vendor %u method %u", vendor, method); + return FALSE; + } + if (eap_peer_get_eap_method(vendor, method)) + return TRUE; + wpa_printf(MSG_DEBUG, "EAP: not included in build: " + "vendor %u method %u", vendor, method); + return FALSE; +} + int eap_peer_register_methods(void) { int ret = 0; @@ -483,6 +540,52 @@ int eap_peer_config_init( if (g_wpa_phase1_options) { sm->config.phase1 = g_wpa_phase1_options; } + + /* Allow methods with correct configuration only */ + size_t mcount; + int allowed_method_count = 0; + const struct eap_method *methods; + + if (!config_methods) { + methods = eap_peer_get_methods(&mcount); + if (methods == NULL) { + wpa_printf(MSG_ERROR, "EAP: Set config init: EAP methods not registered."); + return -1; + } + + // Allocate a buffer large enough to accomodate all the registered methods. + config_methods = os_malloc(mcount * sizeof(struct eap_method_type)); + if (config_methods == NULL) { + wpa_printf(MSG_ERROR, "EAP: Set config init: Out of memory, set configured methods failed"); + return -1; + } + + if (g_wpa_username) { + //set EAP-PEAP + config_methods[allowed_method_count].vendor = EAP_VENDOR_IETF; + config_methods[allowed_method_count++].method = EAP_TYPE_PEAP; + //set EAP-TTLS + config_methods[allowed_method_count].vendor = EAP_VENDOR_IETF; + config_methods[allowed_method_count++].method = EAP_TYPE_TTLS; + } + if (g_wpa_private_key) { + //set EAP-TLS + config_methods[allowed_method_count].vendor = EAP_VENDOR_IETF; + config_methods[allowed_method_count++].method = EAP_TYPE_TLS; + } +#ifndef USE_MBEDTLS_CRYPTO + if (g_wpa_pac_file) { + //set EAP-FAST + config_methods[allowed_method_count].vendor = EAP_VENDOR_IETF; + config_methods[allowed_method_count++].method = EAP_TYPE_FAST; + } +#endif + // Terminate the allowed method list + config_methods[allowed_method_count].vendor = EAP_VENDOR_IETF; + config_methods[allowed_method_count++].method = EAP_TYPE_NONE; + // Set the allowed methods to config + sm->config.eap_methods = config_methods; + } return 0; } @@ -496,6 +599,7 @@ void eap_peer_config_deinit(struct eap_sm *sm) os_free(sm->config.identity); os_free(sm->config.password); os_free(sm->config.new_password); + os_free(sm->config.eap_methods); os_bzero(&sm->config, sizeof(struct eap_peer_config)); } diff --git a/components/wpa_supplicant/src/eap_peer/eap.h b/components/wpa_supplicant/src/eap_peer/eap.h index da613f7080..2554d4aa93 100644 --- a/components/wpa_supplicant/src/eap_peer/eap.h +++ b/components/wpa_supplicant/src/eap_peer/eap.h @@ -60,5 +60,6 @@ int eap_peer_register_methods(void); void eap_sm_request_identity(struct eap_sm *sm); void eap_sm_request_password(struct eap_sm *sm); void eap_sm_request_new_password(struct eap_sm *sm); +bool eap_sm_allowMethod(struct eap_sm *sm, int vendor, EapType method); #endif /* EAP_H */ diff --git a/components/wpa_supplicant/src/eap_peer/eap_i.h b/components/wpa_supplicant/src/eap_peer/eap_i.h index e70673d1bb..8353542aea 100644 --- a/components/wpa_supplicant/src/eap_peer/eap_i.h +++ b/components/wpa_supplicant/src/eap_peer/eap_i.h @@ -155,6 +155,7 @@ const u8 * eap_get_config_new_password(struct eap_sm *sm, size_t *len); struct eap_peer_config * eap_get_config(struct eap_sm *sm); void eap_set_config_blob(struct eap_sm *sm, struct wpa_config_blob *blob); const struct wpa_config_blob * eap_get_config_blob(struct eap_sm *sm, const char *name); +int eap_allowed_method(struct eap_sm *sm, int vendor, u32 method); bool wifi_sta_get_enterprise_disable_time_check(void); struct wpabuf * eap_sm_build_identity_resp(struct eap_sm *sm, u8 id, int encrypted); diff --git a/components/wpa_supplicant/src/esp_supplicant/esp_wpa2.c b/components/wpa_supplicant/src/esp_supplicant/esp_wpa2.c index 252f833edc..5695b47f14 100644 --- a/components/wpa_supplicant/src/esp_supplicant/esp_wpa2.c +++ b/components/wpa_supplicant/src/esp_supplicant/esp_wpa2.c @@ -460,6 +460,15 @@ int eap_sm_process_request(struct eap_sm *sm, struct wpabuf *reqData) if (m == NULL) { goto build_nak; } + + if (!eap_sm_allowMethod(sm, reqVendor, reqVendorMethod)) { + wpa_printf(MSG_DEBUG, "EAP: vendor %u method %u not allowed", + reqVendor, reqVendorMethod); + wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_PROPOSED_METHOD + "vendor=%u method=%u -> NAK", + reqVendor, reqVendorMethod); + goto build_nak; + } if (sm->m) { eap_deinit_prev_method(sm, "GET_METHOD"); }