fix(esp_wifi): Populate appropriate reason codes when softAP sends deauthentication

Populate appropriate reason for sending deauthentication when softAP receives
invalid RSN IE from association request
This commit is contained in:
Shyamal Khachane
2024-05-07 15:49:46 +05:30
committed by Sarvesh Bodakhe
parent fca3fab225
commit 325ce1f8f9
5 changed files with 151 additions and 97 deletions

View File

@ -7,6 +7,7 @@
#include "utils/includes.h" #include "utils/includes.h"
#include "utils/common.h" #include "utils/common.h"
#include "utils/eloop.h"
#include "crypto/sha1.h" #include "crypto/sha1.h"
#include "common/ieee802_11_defs.h" #include "common/ieee802_11_defs.h"
#include "common/eapol_common.h" #include "common/eapol_common.h"
@ -21,6 +22,9 @@
#include "esp_wps.h" #include "esp_wps.h"
#include "esp_wps_i.h" #include "esp_wps_i.h"
#include "ap/sta_info.h"
#include "common/sae.h"
#include "ap/ieee802_11.h"
#define WIFI_PASSWORD_LEN_MAX 65 #define WIFI_PASSWORD_LEN_MAX 65
struct hostapd_data *global_hapd; struct hostapd_data *global_hapd;
@ -322,3 +326,143 @@ done:
os_free(reply); os_free(reply);
return res; return res;
} }
uint8_t wpa_status_to_reason_code(int status)
{
switch (status) {
case WLAN_STATUS_INVALID_IE:
return WLAN_REASON_INVALID_IE;
case WLAN_STATUS_GROUP_CIPHER_NOT_VALID:
return WLAN_REASON_GROUP_CIPHER_NOT_VALID;
case WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID:
return WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
case WLAN_STATUS_AKMP_NOT_VALID:
return WLAN_REASON_AKMP_NOT_VALID;
case WLAN_STATUS_CIPHER_REJECTED_PER_POLICY:
return WLAN_REASON_CIPHER_SUITE_REJECTED;
case WLAN_STATUS_INVALID_PMKID:
return WLAN_REASON_INVALID_PMKID;
case WLAN_STATUS_INVALID_MDIE:
return WLAN_REASON_INVALID_MDE;
default:
return WLAN_REASON_UNSPECIFIED;
}
}
bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie,
uint8_t wpa_ie_len, uint8_t *rsnxe, uint8_t rsnxe_len,
bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason)
{
struct hostapd_data *hapd = (struct hostapd_data*)esp_wifi_get_hostap_private_internal();
enum wpa_validate_result res = WPA_IE_OK;
int status = WLAN_STATUS_SUCCESS;
bool omit_rsnxe = false;
if (!sta || !bssid || !wpa_ie) {
return false;
}
if (hapd) {
if (hapd->wpa_auth->conf.wpa) {
if (sta->wpa_sm) {
wpa_auth_sta_deinit(sta->wpa_sm);
}
sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, bssid);
wpa_printf(MSG_DEBUG, "init wpa sm=%p", sta->wpa_sm);
if (sta->wpa_sm == NULL) {
status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
goto send_resp;
}
res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, wpa_ie, wpa_ie_len, rsnxe, rsnxe_len);
#ifdef CONFIG_SAE
if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae &&
sta->sae->state == SAE_ACCEPTED) {
wpa_auth_add_sae_pmkid(sta->wpa_sm, sta->sae->pmkid);
}
#endif /* CONFIG_SAE */
status = wpa_res_to_status_code(res);
send_resp:
if (!rsnxe) {
omit_rsnxe = true;
}
if (esp_send_assoc_resp(hapd, bssid, status, omit_rsnxe, subtype) != WLAN_STATUS_SUCCESS) {
status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
}
if (status != WLAN_STATUS_SUCCESS) {
*reason = wpa_status_to_reason_code(status);
return false;
}
//Check whether AP uses Management Frame Protection for this connection
*pmf_enable = wpa_auth_uses_mfp(sta->wpa_sm);
*pairwise_cipher = GET_BIT_POSITION(sta->wpa_sm->pairwise);
}
wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
}
return true;
}
#ifdef CONFIG_WPS_REGISTRAR
static void ap_free_sta_timeout(void *ctx, void *data)
{
struct hostapd_data *hapd = (struct hostapd_data *) ctx;
u8 *addr = (u8 *) data;
struct sta_info *sta = ap_get_sta(hapd, addr);
if (sta) {
ap_free_sta(hapd, sta);
}
os_free(addr);
}
#endif
bool wpa_ap_remove(u8* bssid)
{
struct hostapd_data *hapd = hostapd_get_hapd_data();
if (!hapd) {
return false;
}
struct sta_info *sta = ap_get_sta(hapd, bssid);
if (!sta) {
return false;
}
#ifdef CONFIG_SAE
if (sta->lock) {
if (os_semphr_take(sta->lock, 0)) {
ap_free_sta(hapd, sta);
} else {
sta->remove_pending = true;
}
return true;
}
#endif /* CONFIG_SAE */
#ifdef CONFIG_WPS_REGISTRAR
wpa_printf(MSG_DEBUG, "wps_status=%d", wps_get_status());
if (wps_get_status() == WPS_STATUS_PENDING) {
u8 *addr = os_malloc(ETH_ALEN);
if (!addr) {
return false;
}
os_memcpy(addr, sta->addr, ETH_ALEN);
eloop_register_timeout(0, 10000, ap_free_sta_timeout, hapd, addr);
} else
#endif
ap_free_sta(hapd, sta);
return true;
}

View File

@ -321,6 +321,7 @@ static bool hostap_sta_join(void **sta, u8 *bssid, u8 *wpa_ie, u8 wpa_ie_len, u8
{ {
struct sta_info *sta_info = NULL; struct sta_info *sta_info = NULL;
struct hostapd_data *hapd = hostapd_get_hapd_data(); struct hostapd_data *hapd = hostapd_get_hapd_data();
uint8_t reason = WLAN_REASON_PREV_AUTH_NOT_VALID;
if (!hapd) { if (!hapd) {
goto fail; goto fail;
@ -379,7 +380,7 @@ process_old_sta:
goto fail; goto fail;
} }
#endif #endif
if (wpa_ap_join(sta_info, bssid, wpa_ie, wpa_ie_len, rsnxe, rsnxe_len, pmf_enable, subtype, pairwise_cipher)) { if (hostap_new_assoc_sta(sta_info, bssid, wpa_ie, wpa_ie_len, rsnxe, rsnxe_len, pmf_enable, subtype, pairwise_cipher, &reason)) {
goto done; goto done;
} else { } else {
goto fail; goto fail;
@ -400,7 +401,7 @@ fail:
os_semphr_give(sta_info->lock); os_semphr_give(sta_info->lock);
} }
#endif /* CONFIG_SAE */ #endif /* CONFIG_SAE */
esp_wifi_ap_deauth_internal(bssid, WLAN_REASON_PREV_AUTH_NOT_VALID); esp_wifi_ap_deauth_internal(bssid, reason);
return false; return false;
} }
#endif #endif

View File

@ -382,9 +382,9 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf,
const u8 *addr, const u8 *prev_psk); const u8 *addr, const u8 *prev_psk);
int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf); int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf);
struct sta_info; struct sta_info;
bool wpa_ap_join(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie, bool hostap_new_assoc_sta(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie,
uint8_t wpa_ie_len,uint8_t *rsnxe, uint8_t rsnxe_len, uint8_t wpa_ie_len,uint8_t *rsnxe, uint8_t rsnxe_len,
bool *pmf_enable, int subtype, uint8_t *pairwise_cipher); bool *pmf_enable, int subtype, uint8_t *pairwise_cipher, uint8_t *reason);
bool wpa_ap_remove(u8* bssid); bool wpa_ap_remove(u8* bssid);
#endif /* HOSTAPD_CONFIG_H */ #endif /* HOSTAPD_CONFIG_H */

View File

@ -13,7 +13,6 @@
#include "common/ieee802_11_defs.h" #include "common/ieee802_11_defs.h"
#include "common/sae.h" #include "common/sae.h"
#include "ap/sta_info.h" #include "ap/sta_info.h"
#include "ap/ieee802_11.h"
#include "ap/wpa_auth.h" #include "ap/wpa_auth.h"
#include "ap/wpa_auth_i.h" #include "ap/wpa_auth_i.h"
#include "ap/wpa_auth_ie.h" #include "ap/wpa_auth_ie.h"
@ -36,7 +35,6 @@
#include "esp_wifi.h" #include "esp_wifi.h"
#include "esp_private/wifi.h" #include "esp_private/wifi.h"
#include "esp_wpas_glue.h" #include "esp_wpas_glue.h"
#include "esp_wps_i.h"
#include "esp_hostap.h" #include "esp_hostap.h"
#define STATE_MACHINE_DATA struct wpa_state_machine #define STATE_MACHINE_DATA struct wpa_state_machine
@ -2557,97 +2555,6 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth)
} }
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
bool wpa_ap_join(struct sta_info *sta, uint8_t *bssid, uint8_t *wpa_ie,
uint8_t wpa_ie_len, uint8_t *rsnxe, uint8_t rsnxe_len,
bool *pmf_enable, int subtype, uint8_t *pairwise_cipher)
{
struct hostapd_data *hapd = (struct hostapd_data*)esp_wifi_get_hostap_private_internal();
enum wpa_validate_result status_code = WPA_IE_OK;
int resp = WLAN_STATUS_SUCCESS;
bool omit_rsnxe = false;
if (!sta || !bssid || !wpa_ie) {
return false;
}
if (hapd) {
if (hapd->wpa_auth->conf.wpa) {
if (sta->wpa_sm){
wpa_auth_sta_deinit(sta->wpa_sm);
}
sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, bssid);
wpa_printf( MSG_DEBUG, "init wpa sm=%p", sta->wpa_sm);
if (sta->wpa_sm == NULL) {
resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
goto send_resp;
}
status_code = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, wpa_ie, wpa_ie_len, rsnxe, rsnxe_len);
#ifdef CONFIG_SAE
if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae &&
sta->sae->state == SAE_ACCEPTED) {
wpa_auth_add_sae_pmkid(sta->wpa_sm, sta->sae->pmkid);
}
#endif /* CONFIG_SAE */
resp = wpa_res_to_status_code(status_code);
send_resp:
if (!rsnxe) {
omit_rsnxe = true;
}
if (esp_send_assoc_resp(hapd, bssid, resp, omit_rsnxe, subtype) != WLAN_STATUS_SUCCESS) {
resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
}
if (resp != WLAN_STATUS_SUCCESS) {
return false;
}
//Check whether AP uses Management Frame Protection for this connection
*pmf_enable = wpa_auth_uses_mfp(sta->wpa_sm);
*pairwise_cipher = GET_BIT_POSITION(sta->wpa_sm->pairwise);
}
wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm);
}
return true;
}
bool wpa_ap_remove(u8* bssid)
{
struct hostapd_data *hapd = hostapd_get_hapd_data();
if (!hapd) {
return false;
}
struct sta_info *sta = ap_get_sta(hapd, bssid);
if (!sta) {
return false;
}
#ifdef CONFIG_SAE
if (sta->lock) {
if (os_semphr_take(sta->lock, 0)) {
ap_free_sta(hapd, sta);
} else {
sta->remove_pending = true;
}
return true;
}
#endif /* CONFIG_SAE */
ap_free_sta(hapd, sta);
return true;
}
#endif /* CONFIG_ESP_WIFI_SOFTAP_SUPPORT */
void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth,
const u8 *sta_addr) const u8 *sta_addr)
{ {

View File

@ -186,6 +186,8 @@
#define WLAN_REASON_INVALID_RSN_IE_CAPAB 22 #define WLAN_REASON_INVALID_RSN_IE_CAPAB 22
#define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23 #define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23
#define WLAN_REASON_CIPHER_SUITE_REJECTED 24 #define WLAN_REASON_CIPHER_SUITE_REJECTED 24
#define WLAN_REASON_INVALID_PMKID 49
#define WLAN_REASON_INVALID_MDE 50
/* Information Element IDs (IEEE Std 802.11-2016, 9.4.2.1, Table 9-77) */ /* Information Element IDs (IEEE Std 802.11-2016, 9.4.2.1, Table 9-77) */
#define WLAN_EID_SSID 0 #define WLAN_EID_SSID 0