PASN: Add support for deauthentication flow in station

The new wpa_supplicant control interface command "PASN_DEAUTH
bssid=<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 <ilan.peer@intel.com>
This commit is contained in:
Ilan Peer 2021-03-15 14:57:12 +02:00 committed by Jouni Malinen
parent 4f436d5378
commit eaeec4da2d
4 changed files with 87 additions and 0 deletions

View file

@ -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);

View file

@ -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;
}

View file

@ -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=<BSSID> = Remove PASN PTKSA state" },
#endif /* CONFIG_PASN */
{ NULL, NULL, NULL, cli_cmd_flag_none, NULL }
};

View file

@ -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 */