1 /*
2  * hostapd / TKIP countermeasures
3  * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "utils/includes.h"
10 
11 #include "utils/common.h"
12 #include "utils/eloop.h"
13 #include "common/ieee802_11_defs.h"
14 #include "radius/radius.h"
15 #include "hostapd.h"
16 #include "sta_info.h"
17 #include "ap_mlme.h"
18 #include "wpa_auth.h"
19 #include "ap_drv_ops.h"
20 #include "tkip_countermeasures.h"
21 
22 
ieee80211_tkip_countermeasures_stop(void * eloop_ctx,void * timeout_ctx)23 static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx,
24 						void *timeout_ctx)
25 {
26 	struct hostapd_data *hapd = eloop_ctx;
27 	hapd->tkip_countermeasures = 0;
28 	hostapd_drv_set_countermeasures(hapd, 0);
29 	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
30 		       HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended");
31 }
32 
33 
ieee80211_tkip_countermeasures_start(struct hostapd_data * hapd)34 static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
35 {
36 	struct sta_info *sta;
37 
38 	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
39 		       HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated");
40 
41 	wpa_auth_countermeasures_start(hapd->wpa_auth);
42 	hapd->tkip_countermeasures = 1;
43 	hostapd_drv_set_countermeasures(hapd, 1);
44 	wpa_gtk_rekey(hapd->wpa_auth);
45 	eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
46 	eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop,
47 			       hapd, NULL);
48 	while ((sta = hapd->sta_list)) {
49 		sta->acct_terminate_cause =
50 			RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET;
51 		if (sta->flags & WLAN_STA_AUTH) {
52 			mlme_deauthenticate_indication(
53 				hapd, sta,
54 				WLAN_REASON_MICHAEL_MIC_FAILURE);
55 		}
56 		hostapd_drv_sta_deauth(hapd, sta->addr,
57 				       WLAN_REASON_MICHAEL_MIC_FAILURE);
58 		ap_free_sta(hapd, sta);
59 	}
60 }
61 
62 
ieee80211_tkip_countermeasures_deinit(struct hostapd_data * hapd)63 void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd)
64 {
65 	eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
66 }
67 
68 
michael_mic_failure(struct hostapd_data * hapd,const u8 * addr,int local)69 int michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
70 {
71 	struct os_reltime now;
72 	int ret = 0;
73 
74 	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
75 		       HOSTAPD_LEVEL_INFO,
76 		       "Michael MIC failure detected in received frame%s",
77 		       local ? " (local)" : "");
78 
79 	if (addr && local) {
80 		struct sta_info *sta = ap_get_sta(hapd, addr);
81 		if (sta != NULL) {
82 			wpa_auth_sta_local_mic_failure_report(sta->wpa_sm);
83 			hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
84 				       HOSTAPD_LEVEL_INFO,
85 				       "Michael MIC failure detected in "
86 				       "received frame");
87 			mlme_michaelmicfailure_indication(hapd, addr);
88 		} else {
89 			wpa_printf(MSG_DEBUG,
90 				   "MLME-MICHAELMICFAILURE.indication "
91 				   "for not associated STA (" MACSTR
92 				   ") ignored", MAC2STR(addr));
93 			return ret;
94 		}
95 	}
96 
97 	os_get_reltime(&now);
98 	if (os_reltime_expired(&now, &hapd->michael_mic_failure, 60)) {
99 		hapd->michael_mic_failures = 1;
100 	} else {
101 		hapd->michael_mic_failures++;
102 		if (hapd->michael_mic_failures > 1) {
103 			ieee80211_tkip_countermeasures_start(hapd);
104 			ret = 1;
105 		}
106 	}
107 	hapd->michael_mic_failure = now;
108 
109 	return ret;
110 }
111