diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index c4108e7f9..a87f11742 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -2310,6 +2310,8 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, } else if (os_strcmp(buf, "PMKSA") == 0) { reply_len = hostapd_ctrl_iface_pmksa_list(hapd, reply, reply_size); + } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) { + hostapd_ctrl_iface_pmksa_flush(hapd); } else { os_memcpy(reply, "UNKNOWN COMMAND\n", 16); reply_len = 16; diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c index 1ee251e1b..bf86d376e 100644 --- a/hostapd/hostapd_cli.c +++ b/hostapd/hostapd_cli.c @@ -1136,6 +1136,13 @@ static int hostapd_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[]) } +static int hostapd_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "PMKSA_FLUSH"); +} + + struct hostapd_cli_cmd { const char *cmd; int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); @@ -1196,6 +1203,7 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = { { "erp_flush", hostapd_cli_cmd_erp_flush }, { "log_level", hostapd_cli_cmd_log_level }, { "pmksa", hostapd_cli_cmd_pmksa }, + { "pmksa_flush", hostapd_cli_cmd_pmksa_flush }, { NULL, NULL } }; diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index cfe25e5ce..317b238c7 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -575,3 +575,9 @@ int hostapd_ctrl_iface_pmksa_list(struct hostapd_data *hapd, char *buf, { return wpa_auth_pmksa_list(hapd->wpa_auth, buf, len); } + + +void hostapd_ctrl_iface_pmksa_flush(struct hostapd_data *hapd) +{ + wpa_auth_pmksa_flush(hapd->wpa_auth); +} diff --git a/src/ap/ctrl_iface_ap.h b/src/ap/ctrl_iface_ap.h index 43c9f7c7e..3ad622f01 100644 --- a/src/ap/ctrl_iface_ap.h +++ b/src/ap/ctrl_iface_ap.h @@ -26,5 +26,6 @@ int hostapd_parse_csa_settings(const char *pos, int hostapd_ctrl_iface_stop_ap(struct hostapd_data *hapd); int hostapd_ctrl_iface_pmksa_list(struct hostapd_data *hapd, char *buf, size_t len); +void hostapd_ctrl_iface_pmksa_flush(struct hostapd_data *hapd); #endif /* CTRL_IFACE_AP_H */ diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c index 8f1ca3e55..b4193489c 100644 --- a/src/ap/pmksa_cache_auth.c +++ b/src/ap/pmksa_cache_auth.c @@ -92,6 +92,20 @@ void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa, } +/** + * pmksa_cache_auth_flush - Flush all PMKSA cache entries + * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() + */ +void pmksa_cache_auth_flush(struct rsn_pmksa_cache *pmksa) +{ + while (pmksa->pmksa) { + wpa_printf(MSG_DEBUG, "RSN: Flush PMKSA cache entry for " + MACSTR, MAC2STR(pmksa->pmksa->spa)); + pmksa_cache_free_entry(pmksa, pmksa->pmksa); + } +} + + static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx) { struct rsn_pmksa_cache *pmksa = eloop_ctx; diff --git a/src/ap/pmksa_cache_auth.h b/src/ap/pmksa_cache_auth.h index aa6f4cd77..d8d9c5a25 100644 --- a/src/ap/pmksa_cache_auth.h +++ b/src/ap/pmksa_cache_auth.h @@ -64,5 +64,6 @@ void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa, int pmksa_cache_auth_radius_das_disconnect(struct rsn_pmksa_cache *pmksa, struct radius_das_attrs *attr); int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len); +void pmksa_cache_auth_flush(struct rsn_pmksa_cache *pmksa); #endif /* PMKSA_CACHE_H */ diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 57839feea..ad1a7bcc8 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -3368,6 +3368,13 @@ int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf, } +void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth) +{ + if (wpa_auth && wpa_auth->pmksa) + pmksa_cache_auth_flush(wpa_auth->pmksa); +} + + /* * Remove and free the group from wpa_authenticator. This is triggered by a * callback to make sure nobody is currently iterating the group list while it diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 0d099805c..166976648 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -300,6 +300,7 @@ void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, const u8 *sta_addr); int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf, size_t len); +void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth); int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id); void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, int ack); diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 716fa8a94..b133d0384 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -1404,6 +1404,20 @@ int wpas_ap_pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf, } +void wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s) +{ + size_t i; + + if (wpa_s->ap_iface) { + for (i = 0; i < wpa_s->ap_iface->num_bss; i++) + hostapd_ctrl_iface_pmksa_flush(wpa_s->ap_iface->bss[i]); + } + + if (wpa_s->ifmsh) + hostapd_ctrl_iface_pmksa_flush(wpa_s->ifmsh->bss[0]); +} + + #ifdef NEED_AP_MLME void wpas_event_dfs_radar_detected(struct wpa_supplicant *wpa_s, struct dfs_event *radar) diff --git a/wpa_supplicant/ap.h b/wpa_supplicant/ap.h index c3c1d9f5f..5a59ddcc1 100644 --- a/wpa_supplicant/ap.h +++ b/wpa_supplicant/ap.h @@ -84,6 +84,7 @@ int wpas_ap_stop_ap(struct wpa_supplicant *wpa_s); int wpas_ap_pmksa_cache_list(struct wpa_supplicant *wpa_s, char *buf, size_t len); +void wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s); void wpas_event_dfs_radar_detected(struct wpa_supplicant *wpa_s, struct dfs_event *radar); diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 98f7e29ae..381d5210c 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -8368,6 +8368,15 @@ static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s, } +static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s) +{ + wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL); +#ifdef CONFIG_AP + wpas_ap_pmksa_cache_flush(wpa_s); +#endif /* CONFIG_AP */ +} + + static int wpas_ctrl_cmd_debug_level(const char *cmd) { if (os_strcmp(cmd, "PING") == 0 || @@ -8441,7 +8450,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strcmp(buf, "PMKSA") == 0) { reply_len = wpas_ctrl_iface_pmksa(wpa_s, reply, reply_size); } else if (os_strcmp(buf, "PMKSA_FLUSH") == 0) { - wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL); + wpas_ctrl_iface_pmksa_flush(wpa_s); } else if (os_strncmp(buf, "SET ", 4) == 0) { if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4)) reply_len = -1;