Home | History | Annotate | Download | only in ap
      1 /*
      2  * hostapd / TKIP countermeasures
      3  * Copyright (c) 2002-2012, Jouni Malinen <j (at) 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 
     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 
     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 
     63 void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd)
     64 {
     65 	eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL);
     66 }
     67 
     68 
     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