296a34f0c1
Previously, the STA entry was removed only from the driver and the STA entry within hostapd was just marked disassociated. However, this left the WPA authenticator state machine with an entry and the session was not terminated properly. In addition, the STA entry could have remaining indefinitely if the STA did not reconnect after TKIP countermeasures. Fix this by removing the STA entry from hostapd instead of just leaving it disassociated. Signed-hostap: Jouni Malinen <j@w1.fi>
100 lines
2.7 KiB
C
100 lines
2.7 KiB
C
/*
|
|
* hostapd / TKIP countermeasures
|
|
* Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
|
*
|
|
* This software may be distributed under the terms of the BSD license.
|
|
* See README for more details.
|
|
*/
|
|
|
|
#include "utils/includes.h"
|
|
|
|
#include "utils/common.h"
|
|
#include "utils/eloop.h"
|
|
#include "common/ieee802_11_defs.h"
|
|
#include "radius/radius.h"
|
|
#include "hostapd.h"
|
|
#include "sta_info.h"
|
|
#include "ap_mlme.h"
|
|
#include "wpa_auth.h"
|
|
#include "ap_drv_ops.h"
|
|
#include "tkip_countermeasures.h"
|
|
|
|
|
|
static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx,
|
|
void *timeout_ctx)
|
|
{
|
|
struct hostapd_data *hapd = eloop_ctx;
|
|
hapd->tkip_countermeasures = 0;
|
|
hostapd_drv_set_countermeasures(hapd, 0);
|
|
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
|
|
HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended");
|
|
}
|
|
|
|
|
|
static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
|
|
{
|
|
struct sta_info *sta;
|
|
|
|
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
|
|
HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated");
|
|
|
|
wpa_auth_countermeasures_start(hapd->wpa_auth);
|
|
hapd->tkip_countermeasures = 1;
|
|
hostapd_drv_set_countermeasures(hapd, 1);
|
|
wpa_gtk_rekey(hapd->wpa_auth);
|
|
eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
|
|
eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop,
|
|
hapd, NULL);
|
|
while ((sta = hapd->sta_list)) {
|
|
sta->acct_terminate_cause =
|
|
RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET;
|
|
if (sta->flags & WLAN_STA_AUTH) {
|
|
mlme_deauthenticate_indication(
|
|
hapd, sta,
|
|
WLAN_REASON_MICHAEL_MIC_FAILURE);
|
|
}
|
|
hostapd_drv_sta_deauth(hapd, sta->addr,
|
|
WLAN_REASON_MICHAEL_MIC_FAILURE);
|
|
ap_free_sta(hapd, sta);
|
|
}
|
|
}
|
|
|
|
|
|
void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd)
|
|
{
|
|
eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
|
|
}
|
|
|
|
|
|
void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
|
|
{
|
|
struct os_time now;
|
|
|
|
if (addr && local) {
|
|
struct sta_info *sta = ap_get_sta(hapd, addr);
|
|
if (sta != NULL) {
|
|
wpa_auth_sta_local_mic_failure_report(sta->wpa_sm);
|
|
hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
|
|
HOSTAPD_LEVEL_INFO,
|
|
"Michael MIC failure detected in "
|
|
"received frame");
|
|
mlme_michaelmicfailure_indication(hapd, addr);
|
|
} else {
|
|
wpa_printf(MSG_DEBUG,
|
|
"MLME-MICHAELMICFAILURE.indication "
|
|
"for not associated STA (" MACSTR
|
|
") ignored", MAC2STR(addr));
|
|
return;
|
|
}
|
|
}
|
|
|
|
os_get_time(&now);
|
|
if (now.sec > hapd->michael_mic_failure + 60) {
|
|
hapd->michael_mic_failures = 1;
|
|
} else {
|
|
hapd->michael_mic_failures++;
|
|
if (hapd->michael_mic_failures > 1)
|
|
ieee80211_tkip_countermeasures_start(hapd);
|
|
}
|
|
hapd->michael_mic_failure = now.sec;
|
|
}
|