1214501Srpaulo/* 2214501Srpaulo * hostapd / TKIP countermeasures 3252726Srpaulo * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi> 4214501Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7214501Srpaulo */ 8214501Srpaulo 9214501Srpaulo#include "utils/includes.h" 10214501Srpaulo 11214501Srpaulo#include "utils/common.h" 12214501Srpaulo#include "utils/eloop.h" 13214501Srpaulo#include "common/ieee802_11_defs.h" 14252726Srpaulo#include "radius/radius.h" 15214501Srpaulo#include "hostapd.h" 16214501Srpaulo#include "sta_info.h" 17214501Srpaulo#include "ap_mlme.h" 18214501Srpaulo#include "wpa_auth.h" 19252726Srpaulo#include "ap_drv_ops.h" 20214501Srpaulo#include "tkip_countermeasures.h" 21214501Srpaulo 22214501Srpaulo 23214501Srpaulostatic void ieee80211_tkip_countermeasures_stop(void *eloop_ctx, 24214501Srpaulo void *timeout_ctx) 25214501Srpaulo{ 26214501Srpaulo struct hostapd_data *hapd = eloop_ctx; 27214501Srpaulo hapd->tkip_countermeasures = 0; 28252726Srpaulo hostapd_drv_set_countermeasures(hapd, 0); 29214501Srpaulo hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, 30214501Srpaulo HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended"); 31214501Srpaulo} 32214501Srpaulo 33214501Srpaulo 34214501Srpaulostatic void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd) 35214501Srpaulo{ 36214501Srpaulo struct sta_info *sta; 37214501Srpaulo 38214501Srpaulo hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, 39214501Srpaulo HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated"); 40214501Srpaulo 41214501Srpaulo wpa_auth_countermeasures_start(hapd->wpa_auth); 42214501Srpaulo hapd->tkip_countermeasures = 1; 43252726Srpaulo hostapd_drv_set_countermeasures(hapd, 1); 44214501Srpaulo wpa_gtk_rekey(hapd->wpa_auth); 45214501Srpaulo eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL); 46214501Srpaulo eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop, 47214501Srpaulo hapd, NULL); 48252726Srpaulo while ((sta = hapd->sta_list)) { 49252726Srpaulo sta->acct_terminate_cause = 50252726Srpaulo RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET; 51252726Srpaulo if (sta->flags & WLAN_STA_AUTH) { 52252726Srpaulo mlme_deauthenticate_indication( 53252726Srpaulo hapd, sta, 54252726Srpaulo WLAN_REASON_MICHAEL_MIC_FAILURE); 55252726Srpaulo } 56252726Srpaulo hostapd_drv_sta_deauth(hapd, sta->addr, 57252726Srpaulo WLAN_REASON_MICHAEL_MIC_FAILURE); 58252726Srpaulo ap_free_sta(hapd, sta); 59214501Srpaulo } 60214501Srpaulo} 61214501Srpaulo 62214501Srpaulo 63252726Srpaulovoid ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd) 64214501Srpaulo{ 65252726Srpaulo eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL); 66252726Srpaulo} 67214501Srpaulo 68252726Srpaulo 69252726Srpauloint michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local) 70252726Srpaulo{ 71252726Srpaulo struct os_time now; 72252726Srpaulo int ret = 0; 73252726Srpaulo 74214501Srpaulo if (addr && local) { 75214501Srpaulo struct sta_info *sta = ap_get_sta(hapd, addr); 76214501Srpaulo if (sta != NULL) { 77214501Srpaulo wpa_auth_sta_local_mic_failure_report(sta->wpa_sm); 78214501Srpaulo hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, 79214501Srpaulo HOSTAPD_LEVEL_INFO, 80214501Srpaulo "Michael MIC failure detected in " 81214501Srpaulo "received frame"); 82214501Srpaulo mlme_michaelmicfailure_indication(hapd, addr); 83214501Srpaulo } else { 84214501Srpaulo wpa_printf(MSG_DEBUG, 85214501Srpaulo "MLME-MICHAELMICFAILURE.indication " 86214501Srpaulo "for not associated STA (" MACSTR 87214501Srpaulo ") ignored", MAC2STR(addr)); 88252726Srpaulo return ret; 89214501Srpaulo } 90214501Srpaulo } 91214501Srpaulo 92252726Srpaulo os_get_time(&now); 93252726Srpaulo if (now.sec > hapd->michael_mic_failure + 60) { 94214501Srpaulo hapd->michael_mic_failures = 1; 95214501Srpaulo } else { 96214501Srpaulo hapd->michael_mic_failures++; 97252726Srpaulo if (hapd->michael_mic_failures > 1) { 98214501Srpaulo ieee80211_tkip_countermeasures_start(hapd); 99252726Srpaulo ret = 1; 100252726Srpaulo } 101214501Srpaulo } 102252726Srpaulo hapd->michael_mic_failure = now.sec; 103252726Srpaulo 104252726Srpaulo return ret; 105214501Srpaulo} 106