$search
00001 /* 00002 * wpa_supplicant - SME 00003 * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "common/ieee802_11_defs.h" 00019 #include "common/ieee802_11_common.h" 00020 #include "eapol_supp/eapol_supp_sm.h" 00021 #include "common/wpa_common.h" 00022 #include "rsn_supp/wpa.h" 00023 #include "rsn_supp/pmksa_cache.h" 00024 #include "config.h" 00025 #include "wpa_supplicant_i.h" 00026 #include "driver_i.h" 00027 #include "wpas_glue.h" 00028 #include "wps_supplicant.h" 00029 #include "notify.h" 00030 #include "blacklist.h" 00031 #include "bss.h" 00032 #include "scan.h" 00033 #include "sme.h" 00034 00035 #include "../../src/nodes/wpa_supplicant_node.h" 00036 00037 void sme_authenticate(struct wpa_supplicant *wpa_s, 00038 struct wpa_bss *bss, struct wpa_ssid *ssid) 00039 { 00040 struct wpa_driver_auth_params params; 00041 struct wpa_ssid *old_ssid; 00042 #ifdef CONFIG_IEEE80211R 00043 const u8 *ie; 00044 #endif /* CONFIG_IEEE80211R */ 00045 #ifdef CONFIG_IEEE80211R 00046 const u8 *md = NULL; 00047 #endif /* CONFIG_IEEE80211R */ 00048 int i, bssid_changed; 00049 00050 if (bss == NULL) { 00051 wpa_printf(MSG_ERROR, "SME: No scan result available for the " 00052 "network"); 00053 return; 00054 } 00055 00056 wpa_s->current_bss = bss; 00057 00058 os_memset(¶ms, 0, sizeof(params)); 00059 wpa_s->reassociate = 0; 00060 00061 params.freq = bss->freq; 00062 params.bssid = bss->bssid; 00063 params.ssid = bss->ssid; 00064 params.ssid_len = bss->ssid_len; 00065 00066 if (wpa_s->sme.ssid_len != params.ssid_len || 00067 os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0) 00068 wpa_s->sme.prev_bssid_set = 0; 00069 00070 wpa_s->sme.freq = params.freq; 00071 os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len); 00072 wpa_s->sme.ssid_len = params.ssid_len; 00073 00074 params.auth_alg = WPA_AUTH_ALG_OPEN; 00075 #ifdef IEEE8021X_EAPOL 00076 if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { 00077 if (ssid->leap) { 00078 if (ssid->non_leap == 0) 00079 params.auth_alg = WPA_AUTH_ALG_LEAP; 00080 else 00081 params.auth_alg |= WPA_AUTH_ALG_LEAP; 00082 } 00083 } 00084 #endif /* IEEE8021X_EAPOL */ 00085 wpa_printf(MSG_DEBUG, "Automatic auth_alg selection: 0x%x", 00086 params.auth_alg); 00087 if (ssid->auth_alg) { 00088 params.auth_alg = ssid->auth_alg; 00089 wpa_printf(MSG_DEBUG, "Overriding auth_alg selection: 0x%x", 00090 params.auth_alg); 00091 } 00092 00093 for (i = 0; i < NUM_WEP_KEYS; i++) { 00094 if (ssid->wep_key_len[i]) 00095 params.wep_key[i] = ssid->wep_key[i]; 00096 params.wep_key_len[i] = ssid->wep_key_len[i]; 00097 } 00098 params.wep_tx_keyidx = ssid->wep_tx_keyidx; 00099 00100 bssid_changed = !is_zero_ether_addr(wpa_s->bssid); 00101 os_memset(wpa_s->bssid, 0, ETH_ALEN); 00102 os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); 00103 if (bssid_changed) 00104 wpas_notify_bssid_changed(wpa_s); 00105 00106 if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || 00107 wpa_bss_get_ie(bss, WLAN_EID_RSN)) && 00108 (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK | 00109 WPA_KEY_MGMT_FT_IEEE8021X | 00110 WPA_KEY_MGMT_FT_PSK | 00111 WPA_KEY_MGMT_IEEE8021X_SHA256 | 00112 WPA_KEY_MGMT_PSK_SHA256))) { 00113 int try_opportunistic; 00114 try_opportunistic = ssid->proactive_key_caching && 00115 (ssid->proto & WPA_PROTO_RSN); 00116 if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, 00117 wpa_s->current_ssid, 00118 try_opportunistic) == 0) 00119 eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); 00120 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); 00121 if (wpa_supplicant_set_suites(wpa_s, bss, ssid, 00122 wpa_s->sme.assoc_req_ie, 00123 &wpa_s->sme.assoc_req_ie_len)) { 00124 wpa_printf(MSG_WARNING, "SME: Failed to set WPA key " 00125 "management and encryption suites"); 00126 return; 00127 } 00128 } else if (ssid->key_mgmt & 00129 (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X | 00130 WPA_KEY_MGMT_WPA_NONE | WPA_KEY_MGMT_FT_PSK | 00131 WPA_KEY_MGMT_FT_IEEE8021X | WPA_KEY_MGMT_PSK_SHA256 | 00132 WPA_KEY_MGMT_IEEE8021X_SHA256)) { 00133 wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); 00134 if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, 00135 wpa_s->sme.assoc_req_ie, 00136 &wpa_s->sme.assoc_req_ie_len)) { 00137 wpa_printf(MSG_WARNING, "SME: Failed to set WPA key " 00138 "management and encryption suites (no scan " 00139 "results)"); 00140 return; 00141 } 00142 #ifdef CONFIG_WPS 00143 } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { 00144 struct wpabuf *wps_ie; 00145 wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); 00146 if (wps_ie && wpabuf_len(wps_ie) <= 00147 sizeof(wpa_s->sme.assoc_req_ie)) { 00148 wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie); 00149 os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie), 00150 wpa_s->sme.assoc_req_ie_len); 00151 } else 00152 wpa_s->sme.assoc_req_ie_len = 0; 00153 wpabuf_free(wps_ie); 00154 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); 00155 #endif /* CONFIG_WPS */ 00156 } else { 00157 wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); 00158 wpa_s->sme.assoc_req_ie_len = 0; 00159 } 00160 00161 #ifdef CONFIG_IEEE80211R 00162 ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); 00163 if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) 00164 md = ie + 2; 00165 wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); 00166 if (md) { 00167 /* Prepare for the next transition */ 00168 wpa_ft_prepare_auth_request(wpa_s->wpa, ie); 00169 } 00170 00171 if (md && ssid->key_mgmt & (WPA_KEY_MGMT_FT_PSK | 00172 WPA_KEY_MGMT_FT_IEEE8021X)) { 00173 if (wpa_s->sme.assoc_req_ie_len + 5 < 00174 sizeof(wpa_s->sme.assoc_req_ie)) { 00175 struct rsn_mdie *mdie; 00176 u8 *pos = wpa_s->sme.assoc_req_ie + 00177 wpa_s->sme.assoc_req_ie_len; 00178 *pos++ = WLAN_EID_MOBILITY_DOMAIN; 00179 *pos++ = sizeof(*mdie); 00180 mdie = (struct rsn_mdie *) pos; 00181 os_memcpy(mdie->mobility_domain, md, 00182 MOBILITY_DOMAIN_ID_LEN); 00183 mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN]; 00184 wpa_s->sme.assoc_req_ie_len += 5; 00185 } 00186 00187 if (wpa_s->sme.ft_used && 00188 os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 && 00189 wpa_sm_has_ptk(wpa_s->wpa)) { 00190 wpa_printf(MSG_DEBUG, "SME: Trying to use FT " 00191 "over-the-air"); 00192 params.auth_alg = WPA_AUTH_ALG_FT; 00193 params.ie = wpa_s->sme.ft_ies; 00194 params.ie_len = wpa_s->sme.ft_ies_len; 00195 } 00196 } 00197 #endif /* CONFIG_IEEE80211R */ 00198 00199 #ifdef CONFIG_IEEE80211W 00200 wpa_s->sme.mfp = ssid->ieee80211w; 00201 if (ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION) { 00202 const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); 00203 struct wpa_ie_data _ie; 00204 if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 && 00205 _ie.capabilities & 00206 (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { 00207 wpa_printf(MSG_DEBUG, "WPA: Selected AP supports MFP: " 00208 "require MFP"); 00209 wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED; 00210 } 00211 } 00212 #endif /* CONFIG_IEEE80211W */ 00213 00214 wpa_supplicant_cancel_scan(wpa_s); 00215 00216 wpa_msg(wpa_s, MSG_INFO, "Trying to authenticate with " MACSTR 00217 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), 00218 wpa_ssid_txt(params.ssid, params.ssid_len), params.freq); 00219 00220 wpa_clear_keys(wpa_s, bss->bssid); 00221 wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); 00222 old_ssid = wpa_s->current_ssid; 00223 wpa_s->current_ssid = ssid; 00224 wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); 00225 wpa_supplicant_initiate_eapol(wpa_s); 00226 if (old_ssid != wpa_s->current_ssid) 00227 wpas_notify_network_changed(wpa_s); 00228 00229 wpa_s->sme.auth_alg = params.auth_alg; 00230 if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) { 00231 wpa_msg(wpa_s, MSG_INFO, "Authentication request to the " 00232 "driver failed"); 00233 //wpa_supplicant_req_scan(wpa_s, 0, 200000); 00234 ros_assoc_failed(wpa_s, bss->bssid, "Driver request to authenticate failed"); 00235 return; 00236 } 00237 00238 /* TODO: add timeout on authentication */ 00239 00240 /* 00241 * Association will be started based on the authentication event from 00242 * the driver. 00243 */ 00244 } 00245 00246 00247 void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data) 00248 { 00249 struct wpa_ssid *ssid = wpa_s->current_ssid; 00250 00251 if (ssid == NULL) { 00252 wpa_printf(MSG_DEBUG, "SME: Ignore authentication event when " 00253 "network is not selected"); 00254 return; 00255 } 00256 00257 if (wpa_s->wpa_state != WPA_AUTHENTICATING) { 00258 wpa_printf(MSG_DEBUG, "SME: Ignore authentication event when " 00259 "not in authenticating state"); 00260 return; 00261 } 00262 00263 if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0) { 00264 wpa_printf(MSG_DEBUG, "SME: Ignore authentication with " 00265 "unexpected peer " MACSTR, 00266 MAC2STR(data->auth.peer)); 00267 return; 00268 } 00269 00270 wpa_printf(MSG_DEBUG, "SME: Authentication response: peer=" MACSTR 00271 " auth_type=%d status_code=%d", 00272 MAC2STR(data->auth.peer), data->auth.auth_type, 00273 data->auth.status_code); 00274 wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs", 00275 data->auth.ies, data->auth.ies_len); 00276 00277 if (data->auth.status_code != WLAN_STATUS_SUCCESS) { 00278 wpa_printf(MSG_DEBUG, "SME: Authentication failed (status " 00279 "code %d)", data->auth.status_code); 00280 ros_assoc_failed(wpa_s, data->auth.peer, "Authentication failed"); 00281 return; 00282 } 00283 00284 #ifdef CONFIG_IEEE80211R 00285 if (data->auth.auth_type == WLAN_AUTH_FT) { 00286 union wpa_event_data edata; 00287 os_memset(&edata, 0, sizeof(edata)); 00288 edata.ft_ies.ies = data->auth.ies; 00289 edata.ft_ies.ies_len = data->auth.ies_len; 00290 os_memcpy(edata.ft_ies.target_ap, data->auth.peer, ETH_ALEN); 00291 wpa_supplicant_event(wpa_s, EVENT_FT_RESPONSE, &edata); 00292 } 00293 #endif /* CONFIG_IEEE80211R */ 00294 00295 sme_associate(wpa_s, ssid->mode, data->auth.peer, 00296 data->auth.auth_type); 00297 } 00298 00299 00300 void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, 00301 const u8 *bssid, u16 auth_type) 00302 { 00303 struct wpa_driver_associate_params params; 00304 struct ieee802_11_elems elems; 00305 00306 os_memset(¶ms, 0, sizeof(params)); 00307 params.bssid = bssid; 00308 params.ssid = wpa_s->sme.ssid; 00309 params.ssid_len = wpa_s->sme.ssid_len; 00310 params.freq = wpa_s->sme.freq; 00311 params.wpa_ie = wpa_s->sme.assoc_req_ie_len ? 00312 wpa_s->sme.assoc_req_ie : NULL; 00313 params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len; 00314 #ifdef CONFIG_IEEE80211R 00315 if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) { 00316 params.wpa_ie = wpa_s->sme.ft_ies; 00317 params.wpa_ie_len = wpa_s->sme.ft_ies_len; 00318 } 00319 #endif /* CONFIG_IEEE80211R */ 00320 params.mode = mode; 00321 params.mgmt_frame_protection = wpa_s->sme.mfp; 00322 if (wpa_s->sme.prev_bssid_set) 00323 params.prev_bssid = wpa_s->sme.prev_bssid; 00324 00325 wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR 00326 " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), 00327 params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "", 00328 params.freq); 00329 00330 wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING); 00331 00332 if (params.wpa_ie == NULL || 00333 ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0) 00334 < 0) { 00335 wpa_printf(MSG_DEBUG, "SME: Could not parse own IEs?!"); 00336 os_memset(&elems, 0, sizeof(elems)); 00337 } 00338 if (elems.rsn_ie) 00339 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2, 00340 elems.rsn_ie_len + 2); 00341 else if (elems.wpa_ie) 00342 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2, 00343 elems.wpa_ie_len + 2); 00344 else 00345 wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); 00346 00347 if (wpa_drv_associate(wpa_s, ¶ms) < 0) { 00348 wpa_msg(wpa_s, MSG_INFO, "Association request to the driver " 00349 "failed"); 00350 //wpa_supplicant_req_scan(wpa_s, 5, 0); 00351 ros_assoc_failed(wpa_s, bssid, "Driver request to associate failed"); 00352 return; 00353 } 00354 00355 /* TODO: add timeout on association */ 00356 } 00357 00358 00359 int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md, 00360 const u8 *ies, size_t ies_len) 00361 { 00362 if (md == NULL || ies == NULL) { 00363 wpa_printf(MSG_DEBUG, "SME: Remove mobility domain"); 00364 os_free(wpa_s->sme.ft_ies); 00365 wpa_s->sme.ft_ies = NULL; 00366 wpa_s->sme.ft_ies_len = 0; 00367 wpa_s->sme.ft_used = 0; 00368 return 0; 00369 } 00370 00371 os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN); 00372 wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len); 00373 os_free(wpa_s->sme.ft_ies); 00374 wpa_s->sme.ft_ies = os_malloc(ies_len); 00375 if (wpa_s->sme.ft_ies == NULL) 00376 return -1; 00377 os_memcpy(wpa_s->sme.ft_ies, ies, ies_len); 00378 wpa_s->sme.ft_ies_len = ies_len; 00379 return 0; 00380 } 00381 00382 00383 void sme_event_assoc_reject(struct wpa_supplicant *wpa_s, 00384 union wpa_event_data *data) 00385 { 00386 int bssid_changed; 00387 int timeout = 5000; 00388 00389 wpa_printf(MSG_DEBUG, "SME: Association with " MACSTR " failed: " 00390 "status code %d", MAC2STR(wpa_s->pending_bssid), 00391 data->assoc_reject.status_code); 00392 00393 bssid_changed = !is_zero_ether_addr(wpa_s->bssid); 00394 00395 /* 00396 * For now, unconditionally terminate the previous authentication. In 00397 * theory, this should not be needed, but mac80211 gets quite confused 00398 * if the authentication is left pending.. Some roaming cases might 00399 * benefit from using the previous authentication, so this could be 00400 * optimized in the future. 00401 */ 00402 if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid, 00403 WLAN_REASON_DEAUTH_LEAVING) < 0) { 00404 wpa_msg(wpa_s, MSG_INFO, 00405 "Deauth request to the driver failed"); 00406 } 00407 wpa_s->sme.prev_bssid_set = 0; 00408 00409 if (wpa_blacklist_add(wpa_s, wpa_s->pending_bssid) == 0) { 00410 struct wpa_blacklist *b; 00411 b = wpa_blacklist_get(wpa_s, wpa_s->pending_bssid); 00412 if (b && b->count < 3) { 00413 /* 00414 * Speed up next attempt if there could be other APs 00415 * that could accept association. 00416 */ 00417 timeout = 100; 00418 } 00419 } 00420 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); 00421 os_memset(wpa_s->bssid, 0, ETH_ALEN); 00422 os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); 00423 if (bssid_changed) 00424 wpas_notify_bssid_changed(wpa_s); 00425 00426 /* 00427 * TODO: if more than one possible AP is available in scan results, 00428 * could try the other ones before requesting a new scan. 00429 */ 00430 ros_assoc_failed(wpa_s, wpa_s->pending_bssid, "Association rejected"); 00431 //wpa_supplicant_req_scan(wpa_s, timeout / 1000, 00432 // 1000 * (timeout % 1000)); 00433 } 00434 00435 00436 void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s, 00437 union wpa_event_data *data) 00438 { 00439 int timeout = 5000; 00440 00441 wpa_printf(MSG_DEBUG, "SME: Authentication timed out"); 00442 00443 if (wpa_blacklist_add(wpa_s, wpa_s->pending_bssid) == 0) { 00444 struct wpa_blacklist *b; 00445 b = wpa_blacklist_get(wpa_s, wpa_s->pending_bssid); 00446 if (b && b->count < 3) { 00447 /* 00448 * Speed up next attempt if there could be other APs 00449 * that could accept association. 00450 */ 00451 timeout = 100; 00452 } 00453 } 00454 ros_assoc_failed(wpa_s, wpa_s->pending_bssid, "Authentication timed out"); 00455 //wpa_supplicant_req_scan(wpa_s, timeout / 1000, 00456 // 1000 * (timeout % 1000)); 00457 } 00458 00459 00460 void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s, 00461 union wpa_event_data *data) 00462 { 00463 wpa_printf(MSG_DEBUG, "SME: Association timed out"); 00464 wpa_supplicant_mark_disassoc(wpa_s); 00465 ros_assoc_failed(wpa_s, wpa_s->pending_bssid, "Association timed out"); 00466 //wpa_supplicant_req_scan(wpa_s, 5, 0); 00467 } 00468 00469 00470 void sme_event_disassoc(struct wpa_supplicant *wpa_s, 00471 union wpa_event_data *data) 00472 { 00473 wpa_printf(MSG_DEBUG, "SME: Disassociation event received"); 00474 if (!is_zero_ether_addr(wpa_s->bssid) && 00475 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)) { 00476 /* 00477 * cfg80211/mac80211 can get into somewhat confused state if 00478 * the AP only disassociates us and leaves us in authenticated 00479 * state. For now, force the state to be cleared to avoid 00480 * confusing errors if we try to associate with the AP again. 00481 */ 00482 wpa_printf(MSG_DEBUG, "SME: Deauthenticate to clear driver " 00483 "state"); 00484 wpa_drv_deauthenticate(wpa_s, wpa_s->bssid, 00485 WLAN_REASON_DEAUTH_LEAVING); 00486 } 00487 }