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