13ff40c12SJohn Marino /*
23ff40c12SJohn Marino * hostapd / TKIP countermeasures
33ff40c12SJohn Marino * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
43ff40c12SJohn Marino *
53ff40c12SJohn Marino * This software may be distributed under the terms of the BSD license.
63ff40c12SJohn Marino * See README for more details.
73ff40c12SJohn Marino */
83ff40c12SJohn Marino
93ff40c12SJohn Marino #include "utils/includes.h"
103ff40c12SJohn Marino
113ff40c12SJohn Marino #include "utils/common.h"
123ff40c12SJohn Marino #include "utils/eloop.h"
133ff40c12SJohn Marino #include "common/ieee802_11_defs.h"
143ff40c12SJohn Marino #include "radius/radius.h"
153ff40c12SJohn Marino #include "hostapd.h"
163ff40c12SJohn Marino #include "sta_info.h"
173ff40c12SJohn Marino #include "ap_mlme.h"
183ff40c12SJohn Marino #include "wpa_auth.h"
193ff40c12SJohn Marino #include "ap_drv_ops.h"
203ff40c12SJohn Marino #include "tkip_countermeasures.h"
213ff40c12SJohn Marino
223ff40c12SJohn Marino
ieee80211_tkip_countermeasures_stop(void * eloop_ctx,void * timeout_ctx)233ff40c12SJohn Marino static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx,
243ff40c12SJohn Marino void *timeout_ctx)
253ff40c12SJohn Marino {
263ff40c12SJohn Marino struct hostapd_data *hapd = eloop_ctx;
273ff40c12SJohn Marino hapd->tkip_countermeasures = 0;
283ff40c12SJohn Marino hostapd_drv_set_countermeasures(hapd, 0);
293ff40c12SJohn Marino hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
303ff40c12SJohn Marino HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended");
313ff40c12SJohn Marino }
323ff40c12SJohn Marino
333ff40c12SJohn Marino
ieee80211_tkip_countermeasures_start(struct hostapd_data * hapd)343ff40c12SJohn Marino static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd)
353ff40c12SJohn Marino {
363ff40c12SJohn Marino struct sta_info *sta;
373ff40c12SJohn Marino
383ff40c12SJohn Marino hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
393ff40c12SJohn Marino HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated");
403ff40c12SJohn Marino
413ff40c12SJohn Marino wpa_auth_countermeasures_start(hapd->wpa_auth);
423ff40c12SJohn Marino hapd->tkip_countermeasures = 1;
433ff40c12SJohn Marino hostapd_drv_set_countermeasures(hapd, 1);
443ff40c12SJohn Marino wpa_gtk_rekey(hapd->wpa_auth);
453ff40c12SJohn Marino eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
463ff40c12SJohn Marino eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop,
473ff40c12SJohn Marino hapd, NULL);
483ff40c12SJohn Marino while ((sta = hapd->sta_list)) {
493ff40c12SJohn Marino sta->acct_terminate_cause =
503ff40c12SJohn Marino RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET;
513ff40c12SJohn Marino if (sta->flags & WLAN_STA_AUTH) {
523ff40c12SJohn Marino mlme_deauthenticate_indication(
533ff40c12SJohn Marino hapd, sta,
543ff40c12SJohn Marino WLAN_REASON_MICHAEL_MIC_FAILURE);
553ff40c12SJohn Marino }
563ff40c12SJohn Marino hostapd_drv_sta_deauth(hapd, sta->addr,
573ff40c12SJohn Marino WLAN_REASON_MICHAEL_MIC_FAILURE);
583ff40c12SJohn Marino ap_free_sta(hapd, sta);
593ff40c12SJohn Marino }
603ff40c12SJohn Marino }
613ff40c12SJohn Marino
623ff40c12SJohn Marino
ieee80211_tkip_countermeasures_deinit(struct hostapd_data * hapd)633ff40c12SJohn Marino void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd)
643ff40c12SJohn Marino {
653ff40c12SJohn Marino eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
663ff40c12SJohn Marino }
673ff40c12SJohn Marino
683ff40c12SJohn Marino
michael_mic_failure(struct hostapd_data * hapd,const u8 * addr,int local)693ff40c12SJohn Marino int michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local)
703ff40c12SJohn Marino {
713ff40c12SJohn Marino struct os_reltime now;
723ff40c12SJohn Marino int ret = 0;
733ff40c12SJohn Marino
74*a1157835SDaniel Fojt hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
75*a1157835SDaniel Fojt HOSTAPD_LEVEL_INFO,
76*a1157835SDaniel Fojt "Michael MIC failure detected in received frame%s",
77*a1157835SDaniel Fojt local ? " (local)" : "");
78*a1157835SDaniel Fojt
793ff40c12SJohn Marino if (addr && local) {
803ff40c12SJohn Marino struct sta_info *sta = ap_get_sta(hapd, addr);
813ff40c12SJohn Marino if (sta != NULL) {
823ff40c12SJohn Marino wpa_auth_sta_local_mic_failure_report(sta->wpa_sm);
833ff40c12SJohn Marino hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
843ff40c12SJohn Marino HOSTAPD_LEVEL_INFO,
853ff40c12SJohn Marino "Michael MIC failure detected in "
863ff40c12SJohn Marino "received frame");
873ff40c12SJohn Marino mlme_michaelmicfailure_indication(hapd, addr);
883ff40c12SJohn Marino } else {
893ff40c12SJohn Marino wpa_printf(MSG_DEBUG,
903ff40c12SJohn Marino "MLME-MICHAELMICFAILURE.indication "
913ff40c12SJohn Marino "for not associated STA (" MACSTR
923ff40c12SJohn Marino ") ignored", MAC2STR(addr));
933ff40c12SJohn Marino return ret;
943ff40c12SJohn Marino }
953ff40c12SJohn Marino }
963ff40c12SJohn Marino
973ff40c12SJohn Marino os_get_reltime(&now);
983ff40c12SJohn Marino if (os_reltime_expired(&now, &hapd->michael_mic_failure, 60)) {
993ff40c12SJohn Marino hapd->michael_mic_failures = 1;
1003ff40c12SJohn Marino } else {
1013ff40c12SJohn Marino hapd->michael_mic_failures++;
1023ff40c12SJohn Marino if (hapd->michael_mic_failures > 1) {
1033ff40c12SJohn Marino ieee80211_tkip_countermeasures_start(hapd);
1043ff40c12SJohn Marino ret = 1;
1053ff40c12SJohn Marino }
1063ff40c12SJohn Marino }
1073ff40c12SJohn Marino hapd->michael_mic_failure = now;
1083ff40c12SJohn Marino
1093ff40c12SJohn Marino return ret;
1103ff40c12SJohn Marino }
111