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 return; 232 } 233 234 /* TODO: add timeout on authentication */ 235 236 /* 237 * Association will be started based on the authentication event from 238 * the driver. 239 */ 240 } 241 242 243 void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data) 244 { 245 struct wpa_ssid *ssid = wpa_s->current_ssid; 246 247 if (ssid == NULL) { 248 wpa_printf(MSG_DEBUG, "SME: Ignore authentication event when " 249 "network is not selected"); 250 return; 251 } 252 253 if (wpa_s->wpa_state != WPA_AUTHENTICATING) { 254 wpa_printf(MSG_DEBUG, "SME: Ignore authentication event when " 255 "not in authenticating state"); 256 return; 257 } 258 259 if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0) { 260 wpa_printf(MSG_DEBUG, "SME: Ignore authentication with " 261 "unexpected peer " MACSTR, 262 MAC2STR(data->auth.peer)); 263 return; 264 } 265 266 wpa_printf(MSG_DEBUG, "SME: Authentication response: peer=" MACSTR 267 " auth_type=%d status_code=%d", 268 MAC2STR(data->auth.peer), data->auth.auth_type, 269 data->auth.status_code); 270 wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs", 271 data->auth.ies, data->auth.ies_len); 272 273 if (data->auth.status_code != WLAN_STATUS_SUCCESS) { 274 wpa_printf(MSG_DEBUG, "SME: Authentication failed (status " 275 "code %d)", data->auth.status_code); 276 return; 277 } 278 279 #ifdef CONFIG_IEEE80211R 280 if (data->auth.auth_type == WLAN_AUTH_FT) { 281 union wpa_event_data edata; 282 os_memset(&edata, 0, sizeof(edata)); 283 edata.ft_ies.ies = data->auth.ies; 284 edata.ft_ies.ies_len = data->auth.ies_len; 285 os_memcpy(edata.ft_ies.target_ap, data->auth.peer, ETH_ALEN); 286 wpa_supplicant_event(wpa_s, EVENT_FT_RESPONSE, &edata); 287 } 288 #endif /* CONFIG_IEEE80211R */ 289 290 sme_associate(wpa_s, ssid->mode, data->auth.peer, 291 data->auth.auth_type); 292 } 293 294 295 void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, 296 const u8 *bssid, u16 auth_type) 297 { 298 struct wpa_driver_associate_params params; 299 struct ieee802_11_elems elems; 300 301 os_memset(¶ms, 0, sizeof(params)); 302 params.bssid = bssid; 303 params.ssid = wpa_s->sme.ssid; 304 params.ssid_len = wpa_s->sme.ssid_len; 305 params.freq = wpa_s->sme.freq; 306 params.wpa_ie = wpa_s->sme.assoc_req_ie_len ? 307 wpa_s->sme.assoc_req_ie : NULL; 308 params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len; 309 #ifdef CONFIG_IEEE80211R 310 if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) { 311 params.wpa_ie = wpa_s->sme.ft_ies; 312 params.wpa_ie_len = wpa_s->sme.ft_ies_len; 313 } 314 #endif /* CONFIG_IEEE80211R */ 315 params.mode = mode; 316 params.mgmt_frame_protection = wpa_s->sme.mfp; 317 if (wpa_s->sme.prev_bssid_set) 318 params.prev_bssid = wpa_s->sme.prev_bssid; 319 320 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR 321 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), 322 params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "", 323 params.freq); 324 325 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING); 326 327 if (params.wpa_ie == NULL || 328 ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0) 329 < 0) { 330 wpa_printf(MSG_DEBUG, "SME: Could not parse own IEs?!"); 331 os_memset(&elems, 0, sizeof(elems)); 332 } 333 if (elems.rsn_ie) 334 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2, 335 elems.rsn_ie_len + 2); 336 else if (elems.wpa_ie) 337 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2, 338 elems.wpa_ie_len + 2); 339 else 340 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); 341 342 if (wpa_drv_associate(wpa_s, ¶ms) < 0) { 343 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver " 344 "failed"); 345 wpa_supplicant_req_scan(wpa_s, 5, 0); 346 return; 347 } 348 349 /* TODO: add timeout on association */ 350 } 351 352 353 int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md, 354 const u8 *ies, size_t ies_len) 355 { 356 if (md == NULL || ies == NULL) { 357 wpa_printf(MSG_DEBUG, "SME: Remove mobility domain"); 358 os_free(wpa_s->sme.ft_ies); 359 wpa_s->sme.ft_ies = NULL; 360 wpa_s->sme.ft_ies_len = 0; 361 wpa_s->sme.ft_used = 0; 362 return 0; 363 } 364 365 os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN); 366 wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len); 367 os_free(wpa_s->sme.ft_ies); 368 wpa_s->sme.ft_ies = os_malloc(ies_len); 369 if (wpa_s->sme.ft_ies == NULL) 370 return -1; 371 os_memcpy(wpa_s->sme.ft_ies, ies, ies_len); 372 wpa_s->sme.ft_ies_len = ies_len; 373 return 0; 374 } 375 376 377 void sme_event_assoc_reject(struct wpa_supplicant *wpa_s, 378 union wpa_event_data *data) 379 { 380 int bssid_changed; 381 int timeout = 5000; 382 383 wpa_printf(MSG_DEBUG, "SME: Association with " MACSTR " failed: " 384 "status code %d", MAC2STR(wpa_s->pending_bssid), 385 data->assoc_reject.status_code); 386 387 bssid_changed = !is_zero_ether_addr(wpa_s->bssid); 388 389 /* 390 * For now, unconditionally terminate the previous authentication. In 391 * theory, this should not be needed, but mac80211 gets quite confused 392 * if the authentication is left pending.. Some roaming cases might 393 * benefit from using the previous authentication, so this could be 394 * optimized in the future. 395 */ 396 if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid, 397 WLAN_REASON_DEAUTH_LEAVING) < 0) { 398 wpa_msg(wpa_s, MSG_INFO, 399 "Deauth request to the driver failed"); 400 } 401 wpa_s->sme.prev_bssid_set = 0; 402 403 if (wpa_blacklist_add(wpa_s, wpa_s->pending_bssid) == 0) { 404 struct wpa_blacklist *b; 405 b = wpa_blacklist_get(wpa_s, wpa_s->pending_bssid); 406 if (b && b->count < 3) { 407 /* 408 * Speed up next attempt if there could be other APs 409 * that could accept association. 410 */ 411 timeout = 100; 412 } 413 } 414 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 415 os_memset(wpa_s->bssid, 0, ETH_ALEN); 416 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); 417 if (bssid_changed) 418 wpas_notify_bssid_changed(wpa_s); 419 420 /* 421 * TODO: if more than one possible AP is available in scan results, 422 * could try the other ones before requesting a new scan. 423 */ 424 wpa_supplicant_req_scan(wpa_s, timeout / 1000, 425 1000 * (timeout % 1000)); 426 } 427 428 429 void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s, 430 union wpa_event_data *data) 431 { 432 wpa_printf(MSG_DEBUG, "SME: Authentication timed out"); 433 wpa_supplicant_req_scan(wpa_s, 5, 0); 434 } 435 436 437 void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s, 438 union wpa_event_data *data) 439 { 440 wpa_printf(MSG_DEBUG, "SME: Association timed out"); 441 wpa_supplicant_mark_disassoc(wpa_s); 442 wpa_supplicant_req_scan(wpa_s, 5, 0); 443 } 444 445 446 void sme_event_disassoc(struct wpa_supplicant *wpa_s, 447 union wpa_event_data *data) 448 { 449 wpa_printf(MSG_DEBUG, "SME: Disassociation event received"); 450 if (!is_zero_ether_addr(wpa_s->bssid) && 451 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)) { 452 /* 453 * cfg80211/mac80211 can get into somewhat confused state if 454 * the AP only disassociates us and leaves us in authenticated 455 * state. For now, force the state to be cleared to avoid 456 * confusing errors if we try to associate with the AP again. 457 */ 458 wpa_printf(MSG_DEBUG, "SME: Deauthenticate to clear driver " 459 "state"); 460 wpa_drv_deauthenticate(wpa_s, wpa_s->bssid, 461 WLAN_REASON_DEAUTH_LEAVING); 462 } 463 } 464