18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / TKIP countermeasures
304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h"
1404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "radius/radius.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "hostapd.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "sta_info.h"
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_mlme.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_drv_ops.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tkip_countermeasures.h"
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee80211_tkip_countermeasures_stop(void *eloop_ctx,
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt						void *timeout_ctx)
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct hostapd_data *hapd = eloop_ctx;
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hapd->tkip_countermeasures = 0;
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_drv_set_countermeasures(hapd, 0);
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended");
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sta_info *sta;
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated");
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_auth_countermeasures_start(hapd->wpa_auth);
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hapd->tkip_countermeasures = 1;
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_drv_set_countermeasures(hapd, 1);
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_gtk_rekey(hapd->wpa_auth);
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop,
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			       hapd, NULL);
4804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	while ((sta = hapd->sta_list)) {
4904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		sta->acct_terminate_cause =
5004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET;
5104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (sta->flags & WLAN_STA_AUTH) {
5204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			mlme_deauthenticate_indication(
5304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				hapd, sta,
5404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt				WLAN_REASON_MICHAEL_MIC_FAILURE);
5504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hostapd_drv_sta_deauth(hapd, sta->addr,
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       WLAN_REASON_MICHAEL_MIC_FAILURE);
5804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		ap_free_sta(hapd, sta);
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd)
641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{
651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt}
671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt
69d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidtint michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
71fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	struct os_reltime now;
72d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	int ret = 0;
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr && local) {
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		struct sta_info *sta = ap_get_sta(hapd, addr);
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sta != NULL) {
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_auth_sta_local_mic_failure_report(sta->wpa_sm);
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       HOSTAPD_LEVEL_INFO,
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "Michael MIC failure detected in "
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				       "received frame");
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			mlme_michaelmicfailure_indication(hapd, addr);
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else {
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG,
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "MLME-MICHAELMICFAILURE.indication "
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "for not associated STA (" MACSTR
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   ") ignored", MAC2STR(addr));
88d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			return ret;
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
92fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	os_get_reltime(&now);
93fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	if (os_reltime_expired(&now, &hapd->michael_mic_failure, 60)) {
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->michael_mic_failures = 1;
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		hapd->michael_mic_failures++;
97d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		if (hapd->michael_mic_failures > 1) {
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			ieee80211_tkip_countermeasures_start(hapd);
99d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt			ret = 1;
100d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		}
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
102fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt	hapd->michael_mic_failure = now;
103d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
104d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	return ret;
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
106