From: Michal Kazior <michal@xxxxxxxxx> The wpa_psk_file can now be modified and hostapd can be told to re-read it with: $ hostapd_cli reload_wpa_psk It must be noted special care must be taken if WPS is configured (wps_state=2, eap_server=1) because WPS appends PMKs to the wpa_psk_file. Signed-off-by: Michal Kazior <michal@xxxxxxxxx> --- Notes: v1: - use hostapd_config_clear_wpa_psk() instead of hand crafted for() loop, so now it also does a memset before freeing like the rest of the code - tweak commit log hostapd/ctrl_iface.c | 56 +++++++++++++++++++++++++++++++++++++++++++ hostapd/hostapd_cli.c | 9 +++++++ 2 files changed, 65 insertions(+) diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index e539a0902..059e03cb2 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -1488,6 +1488,59 @@ static int hostapd_ctrl_iface_disable(struct hostapd_iface *iface) } +static int hostapd_ctrl_iface_kick_mismatch_psk_sta_iter(struct hostapd_data *hapd, + struct sta_info *sta, + void *ctx) +{ + struct hostapd_wpa_psk *psk; + const u8 *pmk; + int pmk_len; + int pmk_match; + int sta_match; + int bss_match; + int reason; + + pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len); + + for (psk = hapd->conf->ssid.wpa_psk; pmk && psk; psk = psk->next) { + pmk_match = PMK_LEN == pmk_len && !os_memcmp(psk->psk, pmk, pmk_len); + sta_match = psk->group == 0 && !os_memcmp(sta->addr, psk->addr, ETH_ALEN); + bss_match = psk->group == 1; + + if (pmk_match && (sta_match || bss_match)) + return 0; + } + + wpa_printf(MSG_INFO, "STA " MACSTR " password no longer valid, kicking", MAC2STR(sta->addr)); + reason = WLAN_REASON_PREV_AUTH_NOT_VALID; + hostapd_drv_sta_deauth(hapd, sta->addr, reason); + ap_sta_deauthenticate(hapd, sta, reason); + + return 0; +} + + +static int hostapd_ctrl_iface_reload_wpa_psk(struct hostapd_data *hapd) +{ + struct hostapd_bss_config *conf = hapd->conf; + int err; + + hostapd_config_clear_wpa_psk(&conf->ssid.wpa_psk); + + err = hostapd_setup_wpa_psk(conf); + if (err < 0) { + wpa_printf(MSG_ERROR, "Reloading WPA-PSK passwords failed: %d", err); + return -1; + } + + ap_for_each_sta(hapd, + hostapd_ctrl_iface_kick_mismatch_psk_sta_iter, + NULL); + + return 0; +} + + #ifdef CONFIG_TESTING_OPTIONS static int hostapd_ctrl_iface_radar(struct hostapd_data *hapd, char *cmd) @@ -3013,6 +3066,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, } else if (os_strncmp(buf, "ENABLE", 6) == 0) { if (hostapd_ctrl_iface_enable(hapd->iface)) reply_len = -1; + } else if (os_strncmp(buf, "RELOAD_WPA_PSK", 14) == 0) { + if (hostapd_ctrl_iface_reload_wpa_psk(hapd)) + reply_len = -1; } else if (os_strncmp(buf, "RELOAD", 6) == 0) { if (hostapd_ctrl_iface_reload(hapd->iface)) reply_len = -1; diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c index fbec5d246..7e9cee1bb 100644 --- a/hostapd/hostapd_cli.c +++ b/hostapd/hostapd_cli.c @@ -903,6 +903,13 @@ static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc, } +static int hostapd_cli_cmd_reload_wpa_psk(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "RELOAD_WPA_PSK"); +} + + static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[]) { hostapd_cli_quit = 1; @@ -1651,6 +1658,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = { "=Add/Delete/Show/Clear deny MAC ACL" }, { "poll_sta", hostapd_cli_cmd_poll_sta, hostapd_complete_stations, "<addr> = poll a STA to check connectivity with a QoS null frame" }, + { "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL, + "=reload wpa_psk_file only" }, { NULL, NULL, NULL, NULL } }; -- 2.20.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap