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 "common/ieee802_11_defs.h" 19 #include "common/ieee802_11_common.h" 20 #include "eapol_supp/eapol_supp_sm.h" 21 #include "common/wpa_common.h" 22 #include "rsn_supp/wpa.h" 23 #include "rsn_supp/pmksa_cache.h" 24 #include "config.h" 25 #include "wpa_supplicant_i.h" 26 #include "driver_i.h" 27 #include "wpas_glue.h" 28 #include "wps_supplicant.h" 29 #include "notify.h" 30 #include "blacklist.h" 31 #include "bss.h" 32 #include "scan.h" 33 #include "sme.h" 34 35 void sme_authenticate(struct wpa_supplicant *wpa_s, 36 struct wpa_bss *bss, struct wpa_ssid *ssid) 37 { 38 struct wpa_driver_auth_params params; 39 struct wpa_ssid *old_ssid; 40 #ifdef CONFIG_IEEE80211R 41 const u8 *ie; 42 #endif /* CONFIG_IEEE80211R */ 43 #ifdef CONFIG_IEEE80211R 44 const u8 *md = NULL; 45 #endif /* CONFIG_IEEE80211R */ 46 int i, bssid_changed; 47 48 if (bss == NULL) { 49 wpa_printf(MSG_ERROR, "SME: No scan result available for the " 50 "network"); 51 return; 52 } 53 54 wpa_s->current_bss = bss; 55 56 os_memset(¶ms, 0, sizeof(params)); 57 wpa_s->reassociate = 0; 58 59 params.freq = bss->freq; 60 params.bssid = bss->bssid; 61 params.ssid = bss->ssid; 62 params.ssid_len = bss->ssid_len; 63 64 if (wpa_s->sme.ssid_len != params.ssid_len || 65 os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0) 66 wpa_s->sme.prev_bssid_set = 0; 67 68 wpa_s->sme.freq = params.freq; 69 os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len); 70 wpa_s->sme.ssid_len = params.ssid_len; 71 72 params.auth_alg = WPA_AUTH_ALG_OPEN; 73 #ifdef IEEE8021X_EAPOL 74 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 75 if (ssid->leap) { 76 if (ssid->non_leap == 0) 77 params.auth_alg = WPA_AUTH_ALG_LEAP; 78 else 79 params.auth_alg |= WPA_AUTH_ALG_LEAP; 80 } 81 } 82 #endif /* IEEE8021X_EAPOL */ 83 wpa_printf(MSG_DEBUG, "Automatic auth_alg selection: 0x%x", 84 params.auth_alg); 85 if (ssid->auth_alg) { 86 params.auth_alg = ssid->auth_alg; 87 wpa_printf(MSG_DEBUG, "Overriding auth_alg selection: 0x%x", 88 params.auth_alg); 89 } 90 91 for (i = 0; i < NUM_WEP_KEYS; i++) { 92 if (ssid->wep_key_len[i]) 93 params.wep_key[i] = ssid->wep_key[i]; 94 params.wep_key_len[i] = ssid->wep_key_len[i]; 95 } 96 params.wep_tx_keyidx = ssid->wep_tx_keyidx; 97 98 bssid_changed = !is_zero_ether_addr(wpa_s->bssid); 99 os_memset(wpa_s->bssid, 0, ETH_ALEN); 100 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); 101 if (bssid_changed) 102 wpas_notify_bssid_changed(wpa_s); 103 104 if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || 105 wpa_bss_get_ie(bss, WLAN_EID_RSN)) && 106 (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK | 107 WPA_KEY_MGMT_FT_IEEE8021X | 108 WPA_KEY_MGMT_FT_PSK | 109 WPA_KEY_MGMT_IEEE8021X_SHA256 | 110 WPA_KEY_MGMT_PSK_SHA256))) { 111 int try_opportunistic; 112 try_opportunistic = ssid->proactive_key_caching && 113 (ssid->proto & WPA_PROTO_RSN); 114 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, 115 wpa_s->current_ssid, 116 try_opportunistic) == 0) 117 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); 118 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); 119 if (wpa_supplicant_set_suites(wpa_s, bss, ssid, 120 wpa_s->sme.assoc_req_ie, 121 &wpa_s->sme.assoc_req_ie_len)) { 122 wpa_printf(MSG_WARNING, "SME: Failed to set WPA key " 123 "management and encryption suites"); 124 return; 125 } 126 } else if (ssid->key_mgmt & 127 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X | 128 WPA_KEY_MGMT_WPA_NONE | WPA_KEY_MGMT_FT_PSK | 129 WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_PSK_SHA256 | 130 WPA_KEY_MGMT_IEEE8021X_SHA256)) { 131 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); 132 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, 133 wpa_s->sme.assoc_req_ie, 134 &wpa_s->sme.assoc_req_ie_len)) { 135 wpa_printf(MSG_WARNING, "SME: Failed to set WPA key " 136 "management and encryption suites (no scan " 137 "results)"); 138 return; 139 } 140 #ifdef CONFIG_WPS 141 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { 142 struct wpabuf *wps_ie; 143 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); 144 if (wps_ie && wpabuf_len(wps_ie) <= 145 sizeof(wpa_s->sme.assoc_req_ie)) { 146 wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie); 147 os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie), 148 wpa_s->sme.assoc_req_ie_len); 149 } else 150 wpa_s->sme.assoc_req_ie_len = 0; 151 wpabuf_free(wps_ie); 152 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); 153 #endif /* CONFIG_WPS */ 154 } else { 155 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); 156 wpa_s->sme.assoc_req_ie_len = 0; 157 } 158 159 #ifdef CONFIG_IEEE80211R 160 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); 161 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) 162 md = ie + 2; 163 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); 164 if (md) { 165 /* Prepare for the next transition */ 166 wpa_ft_prepare_auth_request(wpa_s->wpa, ie); 167 } 168 169 if (md && ssid->key_mgmt & (WPA_KEY_MGMT_FT_PSK | 170 WPA_KEY_MGMT_FT_IEEE8021X)) { 171 if (wpa_s->sme.assoc_req_ie_len + 5 < 172 sizeof(wpa_s->sme.assoc_req_ie)) { 173 struct rsn_mdie *mdie; 174 u8 *pos = wpa_s->sme.assoc_req_ie + 175 wpa_s->sme.assoc_req_ie_len; 176 *pos++ = WLAN_EID_MOBILITY_DOMAIN; 177 *pos++ = sizeof(*mdie); 178 mdie = (struct rsn_mdie *) pos; 179 os_memcpy(mdie->mobility_domain, md, 180 MOBILITY_DOMAIN_ID_LEN); 181 mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN]; 182 wpa_s->sme.assoc_req_ie_len += 5; 183 } 184 185 if (wpa_s->sme.ft_used && 186 os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 && 187 wpa_sm_has_ptk(wpa_s->wpa)) { 188 wpa_printf(MSG_DEBUG, "SME: Trying to use FT " 189 "over-the-air"); 190 params.auth_alg = WPA_AUTH_ALG_FT; 191 params.ie = wpa_s->sme.ft_ies; 192 params.ie_len = wpa_s->sme.ft_ies_len; 193 } 194 } 195 #endif /* CONFIG_IEEE80211R */ 196 197 #ifdef CONFIG_IEEE80211W 198 wpa_s->sme.mfp = ssid->ieee80211w; 199 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) { 200 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); 201 struct wpa_ie_data _ie; 202 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 && 203 _ie.capabilities & 204 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { 205 wpa_printf(MSG_DEBUG, "WPA: Selected AP supports MFP: " 206 "require MFP"); 207 wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED; 208 } 209 } 210 #endif /* CONFIG_IEEE80211W */ 211 212 wpa_supplicant_cancel_scan(wpa_s); 213 214 wpa_msg(wpa_s, MSG_INFO, "Trying to authenticate with " MACSTR 215 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), 216 wpa_ssid_txt(params.ssid, params.ssid_len), params.freq); 217 218 wpa_clear_keys(wpa_s, bss->bssid); 219 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); 220 old_ssid = wpa_s->current_ssid; 221 wpa_s->current_ssid = ssid; 222 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); 223 wpa_supplicant_initiate_eapol(wpa_s); 224 if (old_ssid != wpa_s->current_ssid) 225 wpas_notify_network_changed(wpa_s); 226 227 wpa_s->sme.auth_alg = params.auth_alg; 228 if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) { 229 wpa_msg(wpa_s, MSG_INFO, "Authentication request to the " 230 "driver failed"); 231 wpa_supplicant_req_scan(wpa_s, 1, 0); 232 return; 233 } 234 235 /* TODO: add timeout on authentication */ 236 237 /* 238 * Association will be started based on the authentication event from 239 * the driver. 240 */ 241 } 242 243 244 void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data) 245 { 246 struct wpa_ssid *ssid = wpa_s->current_ssid; 247 248 if (ssid == NULL) { 249 wpa_printf(MSG_DEBUG, "SME: Ignore authentication event when " 250 "network is not selected"); 251 return; 252 } 253 254 if (wpa_s->wpa_state != WPA_AUTHENTICATING) { 255 wpa_printf(MSG_DEBUG, "SME: Ignore authentication event when " 256 "not in authenticating state"); 257 return; 258 } 259 260 if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0) { 261 wpa_printf(MSG_DEBUG, "SME: Ignore authentication with " 262 "unexpected peer " MACSTR, 263 MAC2STR(data->auth.peer)); 264 return; 265 } 266 267 wpa_printf(MSG_DEBUG, "SME: Authentication response: peer=" MACSTR 268 " auth_type=%d status_code=%d", 269 MAC2STR(data->auth.peer), data->auth.auth_type, 270 data->auth.status_code); 271 wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs", 272 data->auth.ies, data->auth.ies_len); 273 274 if (data->auth.status_code != WLAN_STATUS_SUCCESS) { 275 wpa_printf(MSG_DEBUG, "SME: Authentication failed (status " 276 "code %d)", data->auth.status_code); 277 278 if (data->auth.status_code != 279 WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG || 280 wpa_s->sme.auth_alg == data->auth.auth_type || 281 wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) 282 return; 283 284 switch (data->auth.auth_type) { 285 case WLAN_AUTH_OPEN: 286 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED; 287 288 wpa_printf(MSG_DEBUG, "SME: Trying SHARED auth"); 289 wpa_supplicant_associate(wpa_s, wpa_s->current_bss, 290 wpa_s->current_ssid); 291 return; 292 293 case WLAN_AUTH_SHARED_KEY: 294 wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_LEAP; 295 296 wpa_printf(MSG_DEBUG, "SME: Trying LEAP auth"); 297 wpa_supplicant_associate(wpa_s, wpa_s->current_bss, 298 wpa_s->current_ssid); 299 return; 300 301 default: 302 return; 303 } 304 } 305 306 #ifdef CONFIG_IEEE80211R 307 if (data->auth.auth_type == WLAN_AUTH_FT) { 308 union wpa_event_data edata; 309 os_memset(&edata, 0, sizeof(edata)); 310 edata.ft_ies.ies = data->auth.ies; 311 edata.ft_ies.ies_len = data->auth.ies_len; 312 os_memcpy(edata.ft_ies.target_ap, data->auth.peer, ETH_ALEN); 313 wpa_supplicant_event(wpa_s, EVENT_FT_RESPONSE, &edata); 314 } 315 #endif /* CONFIG_IEEE80211R */ 316 317 sme_associate(wpa_s, ssid->mode, data->auth.peer, 318 data->auth.auth_type); 319 } 320 321 322 void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, 323 const u8 *bssid, u16 auth_type) 324 { 325 struct wpa_driver_associate_params params; 326 struct ieee802_11_elems elems; 327 328 os_memset(¶ms, 0, sizeof(params)); 329 params.bssid = bssid; 330 params.ssid = wpa_s->sme.ssid; 331 params.ssid_len = wpa_s->sme.ssid_len; 332 params.freq = wpa_s->sme.freq; 333 params.wpa_ie = wpa_s->sme.assoc_req_ie_len ? 334 wpa_s->sme.assoc_req_ie : NULL; 335 params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len; 336 #ifdef CONFIG_IEEE80211R 337 if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) { 338 params.wpa_ie = wpa_s->sme.ft_ies; 339 params.wpa_ie_len = wpa_s->sme.ft_ies_len; 340 } 341 #endif /* CONFIG_IEEE80211R */ 342 params.mode = mode; 343 params.mgmt_frame_protection = wpa_s->sme.mfp; 344 if (wpa_s->sme.prev_bssid_set) 345 params.prev_bssid = wpa_s->sme.prev_bssid; 346 347 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR 348 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), 349 params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "", 350 params.freq); 351 352 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING); 353 354 if (params.wpa_ie == NULL || 355 ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0) 356 < 0) { 357 wpa_printf(MSG_DEBUG, "SME: Could not parse own IEs?!"); 358 os_memset(&elems, 0, sizeof(elems)); 359 } 360 if (elems.rsn_ie) 361 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2, 362 elems.rsn_ie_len + 2); 363 else if (elems.wpa_ie) 364 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2, 365 elems.wpa_ie_len + 2); 366 else 367 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); 368 369 if (wpa_drv_associate(wpa_s, ¶ms) < 0) { 370 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver " 371 "failed"); 372 wpa_supplicant_req_scan(wpa_s, 5, 0); 373 return; 374 } 375 376 /* TODO: add timeout on association */ 377 } 378 379 380 int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md, 381 const u8 *ies, size_t ies_len) 382 { 383 if (md == NULL || ies == NULL) { 384 wpa_printf(MSG_DEBUG, "SME: Remove mobility domain"); 385 os_free(wpa_s->sme.ft_ies); 386 wpa_s->sme.ft_ies = NULL; 387 wpa_s->sme.ft_ies_len = 0; 388 wpa_s->sme.ft_used = 0; 389 return 0; 390 } 391 392 os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN); 393 wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len); 394 os_free(wpa_s->sme.ft_ies); 395 wpa_s->sme.ft_ies = os_malloc(ies_len); 396 if (wpa_s->sme.ft_ies == NULL) 397 return -1; 398 os_memcpy(wpa_s->sme.ft_ies, ies, ies_len); 399 wpa_s->sme.ft_ies_len = ies_len; 400 return 0; 401 } 402 403 404 void sme_event_assoc_reject(struct wpa_supplicant *wpa_s, 405 union wpa_event_data *data) 406 { 407 int bssid_changed; 408 int timeout = 5000; 409 410 wpa_printf(MSG_DEBUG, "SME: Association with " MACSTR " failed: " 411 "status code %d", MAC2STR(wpa_s->pending_bssid), 412 data->assoc_reject.status_code); 413 414 bssid_changed = !is_zero_ether_addr(wpa_s->bssid); 415 416 /* 417 * For now, unconditionally terminate the previous authentication. In 418 * theory, this should not be needed, but mac80211 gets quite confused 419 * if the authentication is left pending.. Some roaming cases might 420 * benefit from using the previous authentication, so this could be 421 * optimized in the future. 422 */ 423 if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid, 424 WLAN_REASON_DEAUTH_LEAVING) < 0) { 425 wpa_msg(wpa_s, MSG_INFO, 426 "Deauth request to the driver failed"); 427 } 428 wpa_s->sme.prev_bssid_set = 0; 429 430 if (wpa_blacklist_add(wpa_s, wpa_s->pending_bssid) == 0) { 431 struct wpa_blacklist *b; 432 b = wpa_blacklist_get(wpa_s, wpa_s->pending_bssid); 433 if (b && b->count < 3) { 434 /* 435 * Speed up next attempt if there could be other APs 436 * that could accept association. 437 */ 438 timeout = 100; 439 } 440 } 441 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 442 os_memset(wpa_s->bssid, 0, ETH_ALEN); 443 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); 444 if (bssid_changed) 445 wpas_notify_bssid_changed(wpa_s); 446 447 /* 448 * TODO: if more than one possible AP is available in scan results, 449 * could try the other ones before requesting a new scan. 450 */ 451 wpa_supplicant_req_scan(wpa_s, timeout / 1000, 452 1000 * (timeout % 1000)); 453 } 454 455 456 void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s, 457 union wpa_event_data *data) 458 { 459 wpa_printf(MSG_DEBUG, "SME: Authentication timed out"); 460 wpa_supplicant_req_scan(wpa_s, 5, 0); 461 } 462 463 464 void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s, 465 union wpa_event_data *data) 466 { 467 wpa_printf(MSG_DEBUG, "SME: Association timed out"); 468 wpa_supplicant_mark_disassoc(wpa_s); 469 wpa_supplicant_req_scan(wpa_s, 5, 0); 470 } 471 472 473 void sme_event_disassoc(struct wpa_supplicant *wpa_s, 474 union wpa_event_data *data) 475 { 476 wpa_printf(MSG_DEBUG, "SME: Disassociation event received"); 477 if (wpa_s->sme.prev_bssid_set && 478 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)) { 479 /* 480 * cfg80211/mac80211 can get into somewhat confused state if 481 * the AP only disassociates us and leaves us in authenticated 482 * state. For now, force the state to be cleared to avoid 483 * confusing errors if we try to associate with the AP again. 484 */ 485 wpa_printf(MSG_DEBUG, "SME: Deauthenticate to clear driver " 486 "state"); 487 wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid, 488 WLAN_REASON_DEAUTH_LEAVING); 489 } 490 } 491