tkip_countermeasures.c revision 04949598a23f501be6eec21697465fd46a28840a
1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)/*
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * hostapd / TKIP countermeasures
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) *
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * This software may be distributed under the terms of the BSD license.
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * See README for more details.
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) */
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "utils/includes.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "utils/common.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "utils/eloop.h"
13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "common/ieee802_11_defs.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "radius/radius.h"
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "hostapd.h"
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "sta_info.h"
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ap_mlme.h"
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "wpa_auth.h"
197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ap_drv_ops.h"
207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "tkip_countermeasures.h"
217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx,
247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)						void *timeout_ctx)
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	struct hostapd_data *hapd = eloop_ctx;
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	hapd->tkip_countermeasures = 0;
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	hostapd_drv_set_countermeasures(hapd, 0);
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)		       HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended");
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	struct sta_info *sta;
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)		       HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated");
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	wpa_auth_countermeasures_start(hapd->wpa_auth);
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	hapd->tkip_countermeasures = 1;
43a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	hostapd_drv_set_countermeasures(hapd, 1);
44a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	wpa_gtk_rekey(hapd->wpa_auth);
45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
46a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop,
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)			       hapd, NULL);
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	while ((sta = hapd->sta_list)) {
49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		sta->acct_terminate_cause =
50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)			RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET;
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (sta->flags & WLAN_STA_AUTH) {
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			mlme_deauthenticate_indication(
53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)				hapd, sta,
54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)				WLAN_REASON_MICHAEL_MIC_FAILURE);
55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		}
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		hostapd_drv_sta_deauth(hapd, sta->addr,
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)				       WLAN_REASON_MICHAEL_MIC_FAILURE);
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		ap_free_sta(hapd, sta);
59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	}
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd)
643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles){
653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)	eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles){
713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)	struct os_time now;
72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)	if (addr && local) {
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		struct sta_info *sta = ap_get_sta(hapd, addr);
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)		if (sta != NULL) {
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)			wpa_auth_sta_local_mic_failure_report(sta->wpa_sm);
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)				       HOSTAPD_LEVEL_INFO,
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)				       "Michael MIC failure detected in "
800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch				       "received frame");
810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch			mlme_michaelmicfailure_indication(hapd, addr);
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)		} else {
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)			wpa_printf(MSG_DEBUG,
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)				   "MLME-MICHAELMICFAILURE.indication "
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)				   "for not associated STA (" MACSTR
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)				   ") ignored", MAC2STR(addr));
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)			return;
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)		}
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	}
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	os_get_time(&now);
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	if (now.sec > hapd->michael_mic_failure + 60) {
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)		hapd->michael_mic_failures = 1;
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch	} else {
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch		hapd->michael_mic_failures++;
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)		if (hapd->michael_mic_failures > 1)
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)			ieee80211_tkip_countermeasures_start(hapd);
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	}
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)	hapd->michael_mic_failure = now.sec;
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)