sme.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
1/* 2 * wpa_supplicant - SME 3 * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15#include "includes.h" 16 17#include "common.h" 18#include "utils/eloop.h" 19#include "common/ieee802_11_defs.h" 20#include "common/ieee802_11_common.h" 21#include "eapol_supp/eapol_supp_sm.h" 22#include "common/wpa_common.h" 23#include "rsn_supp/wpa.h" 24#include "rsn_supp/pmksa_cache.h" 25#include "config.h" 26#include "wpa_supplicant_i.h" 27#include "driver_i.h" 28#include "wpas_glue.h" 29#include "wps_supplicant.h" 30#include "p2p_supplicant.h" 31#include "notify.h" 32#include "blacklist.h" 33#include "bss.h" 34#include "scan.h" 35#include "sme.h" 36 37#define SME_AUTH_TIMEOUT 5 38#define SME_ASSOC_TIMEOUT 5 39 40static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx); 41static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx); 42#ifdef CONFIG_IEEE80211W 43static void sme_stop_sa_query(struct wpa_supplicant *wpa_s); 44#endif /* CONFIG_IEEE80211W */ 45 46 47void sme_authenticate(struct wpa_supplicant *wpa_s, 48 struct wpa_bss *bss, struct wpa_ssid *ssid) 49{ 50 struct wpa_driver_auth_params params; 51 struct wpa_ssid *old_ssid; 52#ifdef CONFIG_IEEE80211R 53 const u8 *ie; 54#endif /* CONFIG_IEEE80211R */ 55#ifdef CONFIG_IEEE80211R 56 const u8 *md = NULL; 57#endif /* CONFIG_IEEE80211R */ 58 int i, bssid_changed; 59 60 if (bss == NULL) { 61 wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for " 62 "the network"); 63 return; 64 } 65 66 wpa_s->current_bss = bss; 67 68 os_memset(¶ms, 0, sizeof(params)); 69 wpa_s->reassociate = 0; 70 71 params.freq = bss->freq; 72 params.bssid = bss->bssid; 73 params.ssid = bss->ssid; 74 params.ssid_len = bss->ssid_len; 75 76 if (wpa_s->sme.ssid_len != params.ssid_len || 77 os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0) 78 wpa_s->sme.prev_bssid_set = 0; 79 80 wpa_s->sme.freq = params.freq; 81 os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len); 82 wpa_s->sme.ssid_len = params.ssid_len; 83 84 params.auth_alg = WPA_AUTH_ALG_OPEN; 85#ifdef IEEE8021X_EAPOL 86 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 87 if (ssid->leap) { 88 if (ssid->non_leap == 0) 89 params.auth_alg = WPA_AUTH_ALG_LEAP; 90 else 91 params.auth_alg |= WPA_AUTH_ALG_LEAP; 92 } 93 } 94#endif /* IEEE8021X_EAPOL */ 95 wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", 96 params.auth_alg); 97 if (ssid->auth_alg) { 98 params.auth_alg = ssid->auth_alg; 99 wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: " 100 "0x%x", params.auth_alg); 101 } 102 103 for (i = 0; i < NUM_WEP_KEYS; i++) { 104 if (ssid->wep_key_len[i]) 105 params.wep_key[i] = ssid->wep_key[i]; 106 params.wep_key_len[i] = ssid->wep_key_len[i]; 107 } 108 params.wep_tx_keyidx = ssid->wep_tx_keyidx; 109 110 bssid_changed = !is_zero_ether_addr(wpa_s->bssid); 111 os_memset(wpa_s->bssid, 0, ETH_ALEN); 112 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); 113 if (bssid_changed) 114 wpas_notify_bssid_changed(wpa_s); 115 116 if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || 117 wpa_bss_get_ie(bss, WLAN_EID_RSN)) && 118 (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK | 119 WPA_KEY_MGMT_FT_IEEE8021X | 120 WPA_KEY_MGMT_FT_PSK | 121 WPA_KEY_MGMT_IEEE8021X_SHA256 | 122 WPA_KEY_MGMT_PSK_SHA256))) { 123 int try_opportunistic; 124 try_opportunistic = ssid->proactive_key_caching && 125 (ssid->proto & WPA_PROTO_RSN); 126 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, 127 wpa_s->current_ssid, 128 try_opportunistic) == 0) 129 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); 130 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); 131 if (wpa_supplicant_set_suites(wpa_s, bss, ssid, 132 wpa_s->sme.assoc_req_ie, 133 &wpa_s->sme.assoc_req_ie_len)) { 134 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " 135 "key management and encryption suites"); 136 return; 137 } 138 } else if (ssid->key_mgmt & 139 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X | 140 WPA_KEY_MGMT_WPA_NONE | WPA_KEY_MGMT_FT_PSK | 141 WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_PSK_SHA256 | 142 WPA_KEY_MGMT_IEEE8021X_SHA256)) { 143 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); 144 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, 145 wpa_s->sme.assoc_req_ie, 146 &wpa_s->sme.assoc_req_ie_len)) { 147 wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " 148 "key management and encryption suites (no " 149 "scan results)"); 150 return; 151 } 152#ifdef CONFIG_WPS 153 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { 154 struct wpabuf *wps_ie; 155 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); 156 if (wps_ie && wpabuf_len(wps_ie) <= 157 sizeof(wpa_s->sme.assoc_req_ie)) { 158 wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie); 159 os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie), 160 wpa_s->sme.assoc_req_ie_len); 161 } else 162 wpa_s->sme.assoc_req_ie_len = 0; 163 wpabuf_free(wps_ie); 164 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); 165#endif /* CONFIG_WPS */ 166 } else { 167 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); 168 wpa_s->sme.assoc_req_ie_len = 0; 169 } 170 171#ifdef CONFIG_IEEE80211R 172 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); 173 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) 174 md = ie + 2; 175 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); 176 if (md) { 177 /* Prepare for the next transition */ 178 wpa_ft_prepare_auth_request(wpa_s->wpa, ie); 179 } 180 181 if (md && ssid->key_mgmt & (WPA_KEY_MGMT_FT_PSK | 182 WPA_KEY_MGMT_FT_IEEE8021X)) { 183 if (wpa_s->sme.assoc_req_ie_len + 5 < 184 sizeof(wpa_s->sme.assoc_req_ie)) { 185 struct rsn_mdie *mdie; 186 u8 *pos = wpa_s->sme.assoc_req_ie + 187 wpa_s->sme.assoc_req_ie_len; 188 *pos++ = WLAN_EID_MOBILITY_DOMAIN; 189 *pos++ = sizeof(*mdie); 190 mdie = (struct rsn_mdie *) pos; 191 os_memcpy(mdie->mobility_domain, md, 192 MOBILITY_DOMAIN_ID_LEN); 193 mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN]; 194 wpa_s->sme.assoc_req_ie_len += 5; 195 } 196 197 if (wpa_s->sme.ft_used && 198 os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 && 199 wpa_sm_has_ptk(wpa_s->wpa)) { 200 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT " 201 "over-the-air"); 202 params.auth_alg = WPA_AUTH_ALG_FT; 203 params.ie = wpa_s->sme.ft_ies; 204 params.ie_len = wpa_s->sme.ft_ies_len; 205 } 206 } 207#endif /* CONFIG_IEEE80211R */ 208 209#ifdef CONFIG_IEEE80211W 210 wpa_s->sme.mfp = ssid->ieee80211w; 211 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) { 212 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); 213 struct wpa_ie_data _ie; 214 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 && 215 _ie.capabilities & 216 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { 217 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports " 218 "MFP: require MFP"); 219 wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED; 220 } 221 } 222#endif /* CONFIG_IEEE80211W */ 223 224#ifdef CONFIG_P2P 225 if (wpa_s->global->p2p) { 226 u8 *pos; 227 size_t len; 228 int res; 229 int p2p_group; 230 p2p_group = wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE; 231 pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; 232 len = sizeof(wpa_s->sme.assoc_req_ie) - 233 wpa_s->sme.assoc_req_ie_len; 234 res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, p2p_group); 235 if (res >= 0) 236 wpa_s->sme.assoc_req_ie_len += res; 237 } 238#endif /* CONFIG_P2P */ 239 240 wpa_supplicant_cancel_scan(wpa_s); 241 242 wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR 243 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), 244 wpa_ssid_txt(params.ssid, params.ssid_len), params.freq); 245 246 wpa_clear_keys(wpa_s, bss->bssid); 247 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); 248 old_ssid = wpa_s->current_ssid; 249 wpa_s->current_ssid = ssid; 250 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); 251 wpa_supplicant_initiate_eapol(wpa_s); 252 if (old_ssid != wpa_s->current_ssid) 253 wpas_notify_network_changed(wpa_s); 254 255 wpa_s->sme.auth_alg = params.auth_alg; 256 if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) { 257 wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the " 258 "driver failed"); 259 wpa_supplicant_req_scan(wpa_s, 1, 0); 260 return; 261 } 262 263 eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s, 264 NULL); 265 266 /* 267 * Association will be started based on the authentication event from 268 * the driver. 269 */ 270} 271 272 273void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data) 274{ 275 struct wpa_ssid *ssid = wpa_s->current_ssid; 276 277 if (ssid == NULL) { 278 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event " 279 "when network is not selected"); 280 return; 281 } 282 283 if (wpa_s->wpa_state != WPA_AUTHENTICATING) { 284 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event " 285 "when not in authenticating state"); 286 return; 287 } 288 289 if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0) { 290 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with " 291 "unexpected peer " MACSTR, 292 MAC2STR(data->auth.peer)); 293 return; 294 } 295 296 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR 297 " auth_type=%d status_code=%d", 298 MAC2STR(data->auth.peer), data->auth.auth_type, 299 data->auth.status_code); 300 wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs", 301 data->auth.ies, data->auth.ies_len); 302 303 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL); 304 305 if (data->auth.status_code != WLAN_STATUS_SUCCESS) { 306 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication failed (status " 307 "code %d)", data->auth.status_code); 308 309 if (data->auth.status_code != 310 WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG || 311 wpa_s->sme.auth_alg == data->auth.auth_type || 312 wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) { 313 wpas_connection_failed(wpa_s, wpa_s->pending_bssid); 314 return; 315 } 316 317 switch (data->auth.auth_type) { 318 case WLAN_AUTH_OPEN: 319 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED; 320 321 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying SHARED auth"); 322 wpa_supplicant_associate(wpa_s, wpa_s->current_bss, 323 wpa_s->current_ssid); 324 return; 325 326 case WLAN_AUTH_SHARED_KEY: 327 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_LEAP; 328 329 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying LEAP auth"); 330 wpa_supplicant_associate(wpa_s, wpa_s->current_bss, 331 wpa_s->current_ssid); 332 return; 333 334 default: 335 return; 336 } 337 } 338 339#ifdef CONFIG_IEEE80211R 340 if (data->auth.auth_type == WLAN_AUTH_FT) { 341 union wpa_event_data edata; 342 os_memset(&edata, 0, sizeof(edata)); 343 edata.ft_ies.ies = data->auth.ies; 344 edata.ft_ies.ies_len = data->auth.ies_len; 345 os_memcpy(edata.ft_ies.target_ap, data->auth.peer, ETH_ALEN); 346 wpa_supplicant_event(wpa_s, EVENT_FT_RESPONSE, &edata); 347 } 348#endif /* CONFIG_IEEE80211R */ 349 350 sme_associate(wpa_s, ssid->mode, data->auth.peer, 351 data->auth.auth_type); 352} 353 354 355void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, 356 const u8 *bssid, u16 auth_type) 357{ 358 struct wpa_driver_associate_params params; 359 struct ieee802_11_elems elems; 360 361 os_memset(¶ms, 0, sizeof(params)); 362 params.bssid = bssid; 363 params.ssid = wpa_s->sme.ssid; 364 params.ssid_len = wpa_s->sme.ssid_len; 365 params.freq = wpa_s->sme.freq; 366 params.wpa_ie = wpa_s->sme.assoc_req_ie_len ? 367 wpa_s->sme.assoc_req_ie : NULL; 368 params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len; 369 params.pairwise_suite = cipher_suite2driver(wpa_s->pairwise_cipher); 370 params.group_suite = cipher_suite2driver(wpa_s->group_cipher); 371#ifdef CONFIG_IEEE80211R 372 if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) { 373 params.wpa_ie = wpa_s->sme.ft_ies; 374 params.wpa_ie_len = wpa_s->sme.ft_ies_len; 375 } 376#endif /* CONFIG_IEEE80211R */ 377 params.mode = mode; 378 params.mgmt_frame_protection = wpa_s->sme.mfp; 379 if (wpa_s->sme.prev_bssid_set) 380 params.prev_bssid = wpa_s->sme.prev_bssid; 381 382 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR 383 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), 384 params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "", 385 params.freq); 386 387 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING); 388 389 if (params.wpa_ie == NULL || 390 ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0) 391 < 0) { 392 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!"); 393 os_memset(&elems, 0, sizeof(elems)); 394 } 395 if (elems.rsn_ie) 396 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2, 397 elems.rsn_ie_len + 2); 398 else if (elems.wpa_ie) 399 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2, 400 elems.wpa_ie_len + 2); 401 else 402 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); 403 if (elems.p2p && 404 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE)) 405 params.p2p = 1; 406 407 if (wpa_s->parent->set_sta_uapsd) 408 params.uapsd = wpa_s->parent->sta_uapsd; 409 else 410 params.uapsd = -1; 411 412 if (wpa_drv_associate(wpa_s, ¶ms) < 0) { 413 wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the " 414 "driver failed"); 415 wpas_connection_failed(wpa_s, wpa_s->pending_bssid); 416 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); 417 return; 418 } 419 420 eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s, 421 NULL); 422} 423 424 425int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md, 426 const u8 *ies, size_t ies_len) 427{ 428 if (md == NULL || ies == NULL) { 429 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Remove mobility domain"); 430 os_free(wpa_s->sme.ft_ies); 431 wpa_s->sme.ft_ies = NULL; 432 wpa_s->sme.ft_ies_len = 0; 433 wpa_s->sme.ft_used = 0; 434 return 0; 435 } 436 437 os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN); 438 wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len); 439 os_free(wpa_s->sme.ft_ies); 440 wpa_s->sme.ft_ies = os_malloc(ies_len); 441 if (wpa_s->sme.ft_ies == NULL) 442 return -1; 443 os_memcpy(wpa_s->sme.ft_ies, ies, ies_len); 444 wpa_s->sme.ft_ies_len = ies_len; 445 return 0; 446} 447 448 449static void sme_deauth(struct wpa_supplicant *wpa_s) 450{ 451 int bssid_changed; 452 453 bssid_changed = !is_zero_ether_addr(wpa_s->bssid); 454 455 if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid, 456 WLAN_REASON_DEAUTH_LEAVING) < 0) { 457 wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver " 458 "failed"); 459 } 460 wpa_s->sme.prev_bssid_set = 0; 461 462 wpas_connection_failed(wpa_s, wpa_s->pending_bssid); 463 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 464 os_memset(wpa_s->bssid, 0, ETH_ALEN); 465 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); 466 if (bssid_changed) 467 wpas_notify_bssid_changed(wpa_s); 468} 469 470 471void sme_event_assoc_reject(struct wpa_supplicant *wpa_s, 472 union wpa_event_data *data) 473{ 474 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association with " MACSTR " failed: " 475 "status code %d", MAC2STR(wpa_s->pending_bssid), 476 data->assoc_reject.status_code); 477 478 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL); 479 480 /* 481 * For now, unconditionally terminate the previous authentication. In 482 * theory, this should not be needed, but mac80211 gets quite confused 483 * if the authentication is left pending.. Some roaming cases might 484 * benefit from using the previous authentication, so this could be 485 * optimized in the future. 486 */ 487 sme_deauth(wpa_s); 488} 489 490 491void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s, 492 union wpa_event_data *data) 493{ 494 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out"); 495 wpas_connection_failed(wpa_s, wpa_s->pending_bssid); 496} 497 498 499void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s, 500 union wpa_event_data *data) 501{ 502 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out"); 503 wpas_connection_failed(wpa_s, wpa_s->pending_bssid); 504 wpa_supplicant_mark_disassoc(wpa_s); 505} 506 507 508void sme_event_disassoc(struct wpa_supplicant *wpa_s, 509 union wpa_event_data *data) 510{ 511 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Disassociation event received"); 512 if (wpa_s->sme.prev_bssid_set && 513 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)) { 514 /* 515 * cfg80211/mac80211 can get into somewhat confused state if 516 * the AP only disassociates us and leaves us in authenticated 517 * state. For now, force the state to be cleared to avoid 518 * confusing errors if we try to associate with the AP again. 519 */ 520 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Deauthenticate to clear " 521 "driver state"); 522 wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid, 523 WLAN_REASON_DEAUTH_LEAVING); 524 } 525} 526 527 528static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx) 529{ 530 struct wpa_supplicant *wpa_s = eloop_ctx; 531 if (wpa_s->wpa_state == WPA_AUTHENTICATING) { 532 wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout"); 533 sme_deauth(wpa_s); 534 } 535} 536 537 538static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx) 539{ 540 struct wpa_supplicant *wpa_s = eloop_ctx; 541 if (wpa_s->wpa_state == WPA_ASSOCIATING) { 542 wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout"); 543 sme_deauth(wpa_s); 544 } 545} 546 547 548void sme_state_changed(struct wpa_supplicant *wpa_s) 549{ 550 /* Make sure timers are cleaned up appropriately. */ 551 if (wpa_s->wpa_state != WPA_ASSOCIATING) 552 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL); 553 if (wpa_s->wpa_state != WPA_AUTHENTICATING) 554 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL); 555} 556 557 558void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s, 559 const u8 *prev_pending_bssid) 560{ 561 /* 562 * mac80211-workaround to force deauth on failed auth cmd, 563 * requires us to remain in authenticating state to allow the 564 * second authentication attempt to be continued properly. 565 */ 566 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Allow pending authentication " 567 "to proceed after disconnection event"); 568 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); 569 os_memcpy(wpa_s->pending_bssid, prev_pending_bssid, ETH_ALEN); 570 571 /* 572 * Re-arm authentication timer in case auth fails for whatever reason. 573 */ 574 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL); 575 eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s, 576 NULL); 577} 578 579 580void sme_deinit(struct wpa_supplicant *wpa_s) 581{ 582 os_free(wpa_s->sme.ft_ies); 583 wpa_s->sme.ft_ies = NULL; 584 wpa_s->sme.ft_ies_len = 0; 585#ifdef CONFIG_IEEE80211W 586 sme_stop_sa_query(wpa_s); 587#endif /* CONFIG_IEEE80211W */ 588 589 eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL); 590 eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL); 591} 592 593 594#ifdef CONFIG_IEEE80211W 595 596static const unsigned int sa_query_max_timeout = 1000; 597static const unsigned int sa_query_retry_timeout = 201; 598 599static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s) 600{ 601 u32 tu; 602 struct os_time now, passed; 603 os_get_time(&now); 604 os_time_sub(&now, &wpa_s->sme.sa_query_start, &passed); 605 tu = (passed.sec * 1000000 + passed.usec) / 1024; 606 if (sa_query_max_timeout < tu) { 607 wpa_dbg(wpa_s, MSG_DEBUG, "SME: SA Query timed out"); 608 sme_stop_sa_query(wpa_s); 609 wpa_supplicant_deauthenticate( 610 wpa_s, WLAN_REASON_PREV_AUTH_NOT_VALID); 611 return 1; 612 } 613 614 return 0; 615} 616 617 618static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s, 619 const u8 *trans_id) 620{ 621 u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN]; 622 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Request to " 623 MACSTR, MAC2STR(wpa_s->bssid)); 624 wpa_hexdump(MSG_DEBUG, "SME: SA Query Transaction ID", 625 trans_id, WLAN_SA_QUERY_TR_ID_LEN); 626 req[0] = WLAN_ACTION_SA_QUERY; 627 req[1] = WLAN_SA_QUERY_REQUEST; 628 os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN); 629 if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, 630 wpa_s->own_addr, wpa_s->bssid, 631 req, sizeof(req)) < 0) 632 wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query " 633 "Request"); 634} 635 636 637static void sme_sa_query_timer(void *eloop_ctx, void *timeout_ctx) 638{ 639 struct wpa_supplicant *wpa_s = eloop_ctx; 640 unsigned int timeout, sec, usec; 641 u8 *trans_id, *nbuf; 642 643 if (wpa_s->sme.sa_query_count > 0 && 644 sme_check_sa_query_timeout(wpa_s)) 645 return; 646 647 nbuf = os_realloc(wpa_s->sme.sa_query_trans_id, 648 (wpa_s->sme.sa_query_count + 1) * 649 WLAN_SA_QUERY_TR_ID_LEN); 650 if (nbuf == NULL) 651 return; 652 if (wpa_s->sme.sa_query_count == 0) { 653 /* Starting a new SA Query procedure */ 654 os_get_time(&wpa_s->sme.sa_query_start); 655 } 656 trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN; 657 wpa_s->sme.sa_query_trans_id = nbuf; 658 wpa_s->sme.sa_query_count++; 659 660 os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN); 661 662 timeout = sa_query_retry_timeout; 663 sec = ((timeout / 1000) * 1024) / 1000; 664 usec = (timeout % 1000) * 1024; 665 eloop_register_timeout(sec, usec, sme_sa_query_timer, wpa_s, NULL); 666 667 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d", 668 wpa_s->sme.sa_query_count); 669 670 sme_send_sa_query_req(wpa_s, trans_id); 671} 672 673 674static void sme_start_sa_query(struct wpa_supplicant *wpa_s) 675{ 676 sme_sa_query_timer(wpa_s, NULL); 677} 678 679 680void sme_stop_sa_query(struct wpa_supplicant *wpa_s) 681{ 682 eloop_cancel_timeout(sme_sa_query_timer, wpa_s, NULL); 683 os_free(wpa_s->sme.sa_query_trans_id); 684 wpa_s->sme.sa_query_trans_id = NULL; 685 wpa_s->sme.sa_query_count = 0; 686} 687 688 689void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa, 690 const u8 *da, u16 reason_code) 691{ 692 struct wpa_ssid *ssid; 693 694 if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)) 695 return; 696 if (wpa_s->wpa_state != WPA_COMPLETED) 697 return; 698 ssid = wpa_s->current_ssid; 699 if (ssid == NULL || ssid->ieee80211w == 0) 700 return; 701 if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) 702 return; 703 if (reason_code != WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA && 704 reason_code != WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA) 705 return; 706 if (wpa_s->sme.sa_query_count > 0) 707 return; 708 709 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Unprotected disconnect dropped - " 710 "possible AP/STA state mismatch - trigger SA Query"); 711 sme_start_sa_query(wpa_s); 712} 713 714 715void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa, 716 const u8 *data, size_t len) 717{ 718 int i; 719 720 if (wpa_s->sme.sa_query_trans_id == NULL || 721 len < 1 + WLAN_SA_QUERY_TR_ID_LEN || 722 data[0] != WLAN_SA_QUERY_RESPONSE) 723 return; 724 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from " 725 MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]); 726 727 if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) 728 return; 729 730 for (i = 0; i < wpa_s->sme.sa_query_count; i++) { 731 if (os_memcmp(wpa_s->sme.sa_query_trans_id + 732 i * WLAN_SA_QUERY_TR_ID_LEN, 733 data + 1, WLAN_SA_QUERY_TR_ID_LEN) == 0) 734 break; 735 } 736 737 if (i >= wpa_s->sme.sa_query_count) { 738 wpa_dbg(wpa_s, MSG_DEBUG, "SME: No matching SA Query " 739 "transaction identifier found"); 740 return; 741 } 742 743 wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reply to pending SA Query received " 744 "from " MACSTR, MAC2STR(sa)); 745 sme_stop_sa_query(wpa_s); 746} 747 748#endif /* CONFIG_IEEE80211W */ 749