From eaeec4da2daec858c36243ec030bfed8d017d136 Mon Sep 17 00:00:00 2001 From: Ilan Peer Date: Mon, 15 Mar 2021 14:57:12 +0200 Subject: [PATCH] PASN: Add support for deauthentication flow in station The new wpa_supplicant control interface command "PASN_DEAUTH bssid=" can now be used to flush the local PTKSA cache for the specified BSS and to notify the AP to request it to drop its PTKSA as well. Signed-off-by: Ilan Peer --- wpa_supplicant/ctrl_iface.c | 19 +++++++++++ wpa_supplicant/pasn_supplicant.c | 56 +++++++++++++++++++++++++++++++ wpa_supplicant/wpa_cli.c | 10 ++++++ wpa_supplicant/wpa_supplicant_i.h | 2 ++ 4 files changed, 87 insertions(+) diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index c05175822..b54d7d496 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -10655,6 +10655,22 @@ static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd) return wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group, id); } + + +static int wpas_ctrl_iface_pasn_deauthenticate(struct wpa_supplicant *wpa_s, + const char *cmd) +{ + u8 bssid[ETH_ALEN]; + + if (os_strncmp(cmd, "bssid=", 6) != 0 || hwaddr_aton(cmd + 6, bssid)) { + wpa_printf(MSG_DEBUG, + "CTRL: PASN_DEAUTH without valid BSSID"); + return -1; + } + + return wpas_pasn_deauthenticate(wpa_s, bssid); +} + #endif /* CONFIG_PASN */ @@ -11576,6 +11592,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, wpas_pasn_auth_stop(wpa_s); } else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) { reply_len = ptksa_cache_list(wpa_s->ptksa, reply, reply_size); + } else if (os_strncmp(buf, "PASN_DEAUTH ", 12) == 0) { + if (wpas_ctrl_iface_pasn_deauthenticate(wpa_s, buf + 12) < 0) + reply_len = -1; #endif /* CONFIG_PASN */ } else { os_memcpy(reply, "UNKNOWN COMMAND\n", 16); diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c index f7c61542f..e6adf73f3 100644 --- a/wpa_supplicant/pasn_supplicant.c +++ b/wpa_supplicant/pasn_supplicant.c @@ -1526,3 +1526,59 @@ int wpas_pasn_auth_tx_status(struct wpa_supplicant *wpa_s, return 0; } + + +int wpas_pasn_deauthenticate(struct wpa_supplicant *wpa_s, const u8 *bssid) +{ + struct wpa_bss *bss; + struct wpabuf *buf; + struct ieee80211_mgmt *deauth; + int ret; + + if (os_memcmp(wpa_s->bssid, bssid, ETH_ALEN) == 0) { + wpa_printf(MSG_DEBUG, + "PASN: Cannot deauthenticate from current BSS"); + return -1; + } + + wpa_printf(MSG_DEBUG, "PASN: deauth: Flushing all PTKSA entries for " + MACSTR, MAC2STR(bssid)); + ptksa_cache_flush(wpa_s->ptksa, bssid, WPA_CIPHER_NONE); + + bss = wpa_bss_get_bssid(wpa_s, bssid); + if (!bss) { + wpa_printf(MSG_DEBUG, "PASN: deauth: BSS not found"); + return -1; + } + + buf = wpabuf_alloc(64); + if (!buf) { + wpa_printf(MSG_DEBUG, "PASN: deauth: Failed wpabuf allocate"); + return -1; + } + + deauth = wpabuf_put(buf, offsetof(struct ieee80211_mgmt, + u.deauth.variable)); + + deauth->frame_control = host_to_le16((WLAN_FC_TYPE_MGMT << 2) | + (WLAN_FC_STYPE_DEAUTH << 4)); + + os_memcpy(deauth->da, bssid, ETH_ALEN); + os_memcpy(deauth->sa, wpa_s->own_addr, ETH_ALEN); + os_memcpy(deauth->bssid, bssid, ETH_ALEN); + deauth->u.deauth.reason_code = + host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); + + /* + * Since we do not expect any response from the AP, implement the + * Deauthentication frame transmission using direct call to the driver + * without a radio work. + */ + ret = wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, + bss->freq, 0); + + wpabuf_free(buf); + wpa_printf(MSG_DEBUG, "PASN: deauth: send_mlme ret=%d", ret); + + return ret; +} diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 95608971f..fea7b85e0 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -3210,6 +3210,13 @@ static int wpa_cli_cmd_ptksa_cache_list(struct wpa_ctrl *ctrl, int argc, return wpa_cli_cmd(ctrl, "PTKSA_CACHE_LIST", 0, argc, argv); } + +static int wpa_cli_cmd_pasn_deauth(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "PASN_DEAUTH", 1, argc, argv); +} + #endif /* CONFIG_PASN */ @@ -3913,6 +3920,9 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { { "ptksa_cache_list", wpa_cli_cmd_ptksa_cache_list, NULL, cli_cmd_flag_none, "= Get the PTKSA Cache" }, + { "pasn_deauth", wpa_cli_cmd_pasn_deauth, NULL, + cli_cmd_flag_none, + "bssid= = Remove PASN PTKSA state" }, #endif /* CONFIG_PASN */ { NULL, NULL, NULL, cli_cmd_flag_none, NULL } }; diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 68d78c11f..7ed8c0ee4 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -1737,4 +1737,6 @@ int wpas_pasn_auth_tx_status(struct wpa_supplicant *wpa_s, int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s, const struct ieee80211_mgmt *mgmt, size_t len); +int wpas_pasn_deauthenticate(struct wpa_supplicant *wpa_s, const u8 *bssid); + #endif /* WPA_SUPPLICANT_I_H */