Line data Source code
1 : /*
2 : * wpa_supplicant - SME
3 : * Copyright (c) 2009-2014, Jouni Malinen <j@w1.fi>
4 : *
5 : * This software may be distributed under the terms of the BSD license.
6 : * See README for more details.
7 : */
8 :
9 : #include "includes.h"
10 :
11 : #include "common.h"
12 : #include "utils/eloop.h"
13 : #include "common/ieee802_11_defs.h"
14 : #include "common/ieee802_11_common.h"
15 : #include "eapol_supp/eapol_supp_sm.h"
16 : #include "common/wpa_common.h"
17 : #include "common/sae.h"
18 : #include "rsn_supp/wpa.h"
19 : #include "rsn_supp/pmksa_cache.h"
20 : #include "config.h"
21 : #include "wpa_supplicant_i.h"
22 : #include "driver_i.h"
23 : #include "wpas_glue.h"
24 : #include "wps_supplicant.h"
25 : #include "p2p_supplicant.h"
26 : #include "notify.h"
27 : #include "bss.h"
28 : #include "scan.h"
29 : #include "sme.h"
30 : #include "hs20_supplicant.h"
31 :
32 : #define SME_AUTH_TIMEOUT 5
33 : #define SME_ASSOC_TIMEOUT 5
34 :
35 : static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx);
36 : static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx);
37 : static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx);
38 : #ifdef CONFIG_IEEE80211W
39 : static void sme_stop_sa_query(struct wpa_supplicant *wpa_s);
40 : #endif /* CONFIG_IEEE80211W */
41 :
42 :
43 : #ifdef CONFIG_SAE
44 :
45 38 : static int index_within_array(const int *array, int idx)
46 : {
47 : int i;
48 50 : for (i = 0; i < idx; i++) {
49 12 : if (array[i] <= 0)
50 0 : return 0;
51 : }
52 38 : return 1;
53 : }
54 :
55 :
56 38 : static int sme_set_sae_group(struct wpa_supplicant *wpa_s)
57 : {
58 38 : int *groups = wpa_s->conf->sae_groups;
59 38 : int default_groups[] = { 19, 20, 21, 25, 26, 0 };
60 :
61 38 : if (!groups || groups[0] <= 0)
62 21 : groups = default_groups;
63 :
64 : /* Configuration may have changed, so validate current index */
65 38 : if (!index_within_array(groups, wpa_s->sme.sae_group_index))
66 0 : return -1;
67 :
68 : for (;;) {
69 38 : int group = groups[wpa_s->sme.sae_group_index];
70 38 : if (group < 0)
71 0 : break;
72 38 : if (sae_set_group(&wpa_s->sme.sae, group) == 0) {
73 38 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected SAE group %d",
74 : wpa_s->sme.sae.group);
75 38 : return 0;
76 : }
77 0 : wpa_s->sme.sae_group_index++;
78 0 : }
79 :
80 0 : return -1;
81 : }
82 :
83 :
84 39 : static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s,
85 : struct wpa_ssid *ssid,
86 : const u8 *bssid)
87 : {
88 : struct wpabuf *buf;
89 : size_t len;
90 :
91 39 : if (ssid->passphrase == NULL) {
92 4 : wpa_printf(MSG_DEBUG, "SAE: No password available");
93 4 : return NULL;
94 : }
95 :
96 35 : if (sme_set_sae_group(wpa_s) < 0) {
97 0 : wpa_printf(MSG_DEBUG, "SAE: Failed to select group");
98 0 : return NULL;
99 : }
100 :
101 105 : if (sae_prepare_commit(wpa_s->own_addr, bssid,
102 35 : (u8 *) ssid->passphrase,
103 35 : os_strlen(ssid->passphrase),
104 : &wpa_s->sme.sae) < 0) {
105 0 : wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
106 0 : return NULL;
107 : }
108 :
109 35 : len = wpa_s->sme.sae_token ? wpabuf_len(wpa_s->sme.sae_token) : 0;
110 35 : buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + len);
111 35 : if (buf == NULL)
112 0 : return NULL;
113 :
114 35 : wpabuf_put_le16(buf, 1); /* Transaction seq# */
115 35 : wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
116 35 : sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token);
117 :
118 35 : return buf;
119 : }
120 :
121 :
122 27 : static struct wpabuf * sme_auth_build_sae_confirm(struct wpa_supplicant *wpa_s)
123 : {
124 : struct wpabuf *buf;
125 :
126 27 : buf = wpabuf_alloc(4 + SAE_CONFIRM_MAX_LEN);
127 27 : if (buf == NULL)
128 0 : return NULL;
129 :
130 27 : wpabuf_put_le16(buf, 2); /* Transaction seq# */
131 27 : wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
132 27 : sae_write_confirm(&wpa_s->sme.sae, buf);
133 :
134 27 : return buf;
135 : }
136 :
137 : #endif /* CONFIG_SAE */
138 :
139 :
140 : /**
141 : * sme_auth_handle_rrm - Handle RRM aspects of current authentication attempt
142 : * @wpa_s: Pointer to wpa_supplicant data
143 : * @bss: Pointer to the bss which is the target of authentication attempt
144 : */
145 2404 : static void sme_auth_handle_rrm(struct wpa_supplicant *wpa_s,
146 : struct wpa_bss *bss)
147 : {
148 2404 : const u8 rrm_ie_len = 5;
149 : u8 *pos;
150 : const u8 *rrm_ie;
151 :
152 2404 : wpa_s->rrm.rrm_used = 0;
153 :
154 2404 : wpa_printf(MSG_DEBUG,
155 : "RRM: Determining whether RRM can be used - device support: 0x%x",
156 : wpa_s->drv_rrm_flags);
157 :
158 2404 : rrm_ie = wpa_bss_get_ie(bss, WLAN_EID_RRM_ENABLED_CAPABILITIES);
159 2404 : if (!rrm_ie || !(bss->caps & IEEE80211_CAP_RRM)) {
160 2403 : wpa_printf(MSG_DEBUG, "RRM: No RRM in network");
161 2403 : return;
162 : }
163 :
164 1 : if (!(wpa_s->drv_rrm_flags &
165 1 : WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES) ||
166 1 : !(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_QUIET)) {
167 0 : wpa_printf(MSG_DEBUG,
168 : "RRM: Insufficient RRM support in driver - do not use RRM");
169 0 : return;
170 : }
171 :
172 1 : if (sizeof(wpa_s->sme.assoc_req_ie) <
173 1 : wpa_s->sme.assoc_req_ie_len + rrm_ie_len + 2) {
174 0 : wpa_printf(MSG_INFO,
175 : "RRM: Unable to use RRM, no room for RRM IE");
176 0 : return;
177 : }
178 :
179 1 : wpa_printf(MSG_DEBUG, "RRM: Adding RRM IE to Association Request");
180 1 : pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
181 1 : os_memset(pos, 0, 2 + rrm_ie_len);
182 1 : *pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES;
183 1 : *pos++ = rrm_ie_len;
184 :
185 : /* Set supported capabilites flags */
186 1 : if (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)
187 0 : *pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT;
188 :
189 1 : wpa_s->sme.assoc_req_ie_len += rrm_ie_len + 2;
190 1 : wpa_s->rrm.rrm_used = 1;
191 : }
192 :
193 :
194 2408 : static void sme_send_authentication(struct wpa_supplicant *wpa_s,
195 : struct wpa_bss *bss, struct wpa_ssid *ssid,
196 : int start)
197 : {
198 : struct wpa_driver_auth_params params;
199 : struct wpa_ssid *old_ssid;
200 : #ifdef CONFIG_IEEE80211R
201 : const u8 *ie;
202 : #endif /* CONFIG_IEEE80211R */
203 : #ifdef CONFIG_IEEE80211R
204 2408 : const u8 *md = NULL;
205 : #endif /* CONFIG_IEEE80211R */
206 : int i, bssid_changed;
207 2408 : struct wpabuf *resp = NULL;
208 : u8 ext_capab[18];
209 : int ext_capab_len;
210 :
211 2408 : if (bss == NULL) {
212 0 : wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for "
213 : "the network");
214 0 : wpas_connect_work_done(wpa_s);
215 0 : return;
216 : }
217 :
218 2408 : wpa_s->current_bss = bss;
219 :
220 2408 : os_memset(¶ms, 0, sizeof(params));
221 2408 : wpa_s->reassociate = 0;
222 :
223 2408 : params.freq = bss->freq;
224 2408 : params.bssid = bss->bssid;
225 2408 : params.ssid = bss->ssid;
226 2408 : params.ssid_len = bss->ssid_len;
227 2408 : params.p2p = ssid->p2p_group;
228 :
229 4235 : if (wpa_s->sme.ssid_len != params.ssid_len ||
230 1827 : os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0)
231 714 : wpa_s->sme.prev_bssid_set = 0;
232 :
233 2408 : wpa_s->sme.freq = params.freq;
234 2408 : os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len);
235 2408 : wpa_s->sme.ssid_len = params.ssid_len;
236 :
237 2408 : params.auth_alg = WPA_AUTH_ALG_OPEN;
238 : #ifdef IEEE8021X_EAPOL
239 2408 : if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
240 10 : if (ssid->leap) {
241 0 : if (ssid->non_leap == 0)
242 0 : params.auth_alg = WPA_AUTH_ALG_LEAP;
243 : else
244 0 : params.auth_alg |= WPA_AUTH_ALG_LEAP;
245 : }
246 : }
247 : #endif /* IEEE8021X_EAPOL */
248 2408 : wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x",
249 : params.auth_alg);
250 2408 : if (ssid->auth_alg) {
251 256 : params.auth_alg = ssid->auth_alg;
252 256 : wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: "
253 : "0x%x", params.auth_alg);
254 : }
255 : #ifdef CONFIG_SAE
256 2408 : wpa_s->sme.sae_pmksa_caching = 0;
257 2408 : if (wpa_key_mgmt_sae(ssid->key_mgmt)) {
258 : const u8 *rsn;
259 : struct wpa_ie_data ied;
260 :
261 70 : rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
262 70 : if (!rsn) {
263 0 : wpa_dbg(wpa_s, MSG_DEBUG,
264 : "SAE enabled, but target BSS does not advertise RSN");
265 140 : } else if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0 &&
266 70 : wpa_key_mgmt_sae(ied.key_mgmt)) {
267 70 : wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg");
268 70 : params.auth_alg = WPA_AUTH_ALG_SAE;
269 : } else {
270 0 : wpa_dbg(wpa_s, MSG_DEBUG,
271 : "SAE enabled, but target BSS does not advertise SAE AKM for RSN");
272 : }
273 : }
274 : #endif /* CONFIG_SAE */
275 :
276 12040 : for (i = 0; i < NUM_WEP_KEYS; i++) {
277 9632 : if (ssid->wep_key_len[i])
278 26 : params.wep_key[i] = ssid->wep_key[i];
279 9632 : params.wep_key_len[i] = ssid->wep_key_len[i];
280 : }
281 2408 : params.wep_tx_keyidx = ssid->wep_tx_keyidx;
282 :
283 2408 : bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
284 2408 : os_memset(wpa_s->bssid, 0, ETH_ALEN);
285 2408 : os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN);
286 2408 : if (bssid_changed)
287 264 : wpas_notify_bssid_changed(wpa_s);
288 :
289 4753 : if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) ||
290 4403 : wpa_bss_get_ie(bss, WLAN_EID_RSN)) &&
291 3849 : wpa_key_mgmt_wpa(ssid->key_mgmt)) {
292 : int try_opportunistic;
293 3590 : try_opportunistic = (ssid->proactive_key_caching < 0 ?
294 1777 : wpa_s->conf->okc :
295 3590 : ssid->proactive_key_caching) &&
296 18 : (ssid->proto & WPA_PROTO_RSN);
297 1795 : if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
298 1795 : wpa_s->current_ssid,
299 : try_opportunistic) == 0)
300 67 : eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
301 1795 : wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
302 3590 : if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
303 1795 : wpa_s->sme.assoc_req_ie,
304 : &wpa_s->sme.assoc_req_ie_len)) {
305 4 : wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
306 : "key management and encryption suites");
307 4 : wpas_connect_work_done(wpa_s);
308 4 : return;
309 : }
310 623 : } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
311 10 : wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
312 : /*
313 : * Both WPA and non-WPA IEEE 802.1X enabled in configuration -
314 : * use non-WPA since the scan results did not indicate that the
315 : * AP is using WPA or WPA2.
316 : */
317 0 : wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
318 0 : wpa_s->sme.assoc_req_ie_len = 0;
319 613 : } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) {
320 1 : wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
321 2 : if (wpa_supplicant_set_suites(wpa_s, NULL, ssid,
322 1 : wpa_s->sme.assoc_req_ie,
323 : &wpa_s->sme.assoc_req_ie_len)) {
324 0 : wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
325 : "key management and encryption suites (no "
326 : "scan results)");
327 0 : wpas_connect_work_done(wpa_s);
328 0 : return;
329 : }
330 : #ifdef CONFIG_WPS
331 612 : } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) {
332 : struct wpabuf *wps_ie;
333 278 : wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid));
334 278 : if (wps_ie && wpabuf_len(wps_ie) <=
335 : sizeof(wpa_s->sme.assoc_req_ie)) {
336 278 : wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie);
337 278 : os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie),
338 : wpa_s->sme.assoc_req_ie_len);
339 : } else
340 0 : wpa_s->sme.assoc_req_ie_len = 0;
341 278 : wpabuf_free(wps_ie);
342 278 : wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
343 : #endif /* CONFIG_WPS */
344 : } else {
345 334 : wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
346 334 : wpa_s->sme.assoc_req_ie_len = 0;
347 : }
348 :
349 : #ifdef CONFIG_IEEE80211R
350 2404 : ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
351 2404 : if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
352 148 : md = ie + 2;
353 2404 : wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0);
354 2404 : if (md) {
355 : /* Prepare for the next transition */
356 148 : wpa_ft_prepare_auth_request(wpa_s->wpa, ie);
357 : }
358 :
359 2404 : if (md && wpa_key_mgmt_ft(ssid->key_mgmt)) {
360 140 : if (wpa_s->sme.assoc_req_ie_len + 5 <
361 : sizeof(wpa_s->sme.assoc_req_ie)) {
362 : struct rsn_mdie *mdie;
363 140 : u8 *pos = wpa_s->sme.assoc_req_ie +
364 140 : wpa_s->sme.assoc_req_ie_len;
365 140 : *pos++ = WLAN_EID_MOBILITY_DOMAIN;
366 140 : *pos++ = sizeof(*mdie);
367 140 : mdie = (struct rsn_mdie *) pos;
368 140 : os_memcpy(mdie->mobility_domain, md,
369 : MOBILITY_DOMAIN_ID_LEN);
370 140 : mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN];
371 140 : wpa_s->sme.assoc_req_ie_len += 5;
372 : }
373 :
374 253 : if (wpa_s->sme.ft_used &&
375 226 : os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 &&
376 113 : wpa_sm_has_ptk(wpa_s->wpa)) {
377 113 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT "
378 : "over-the-air");
379 113 : params.auth_alg = WPA_AUTH_ALG_FT;
380 113 : params.ie = wpa_s->sme.ft_ies;
381 113 : params.ie_len = wpa_s->sme.ft_ies_len;
382 : }
383 : }
384 : #endif /* CONFIG_IEEE80211R */
385 :
386 : #ifdef CONFIG_IEEE80211W
387 2404 : wpa_s->sme.mfp = wpas_get_ssid_pmf(wpa_s, ssid);
388 2404 : if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) {
389 340 : const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
390 : struct wpa_ie_data _ie;
391 680 : if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 &&
392 340 : _ie.capabilities &
393 : (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) {
394 47 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports "
395 : "MFP: require MFP");
396 47 : wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED;
397 : }
398 : }
399 : #endif /* CONFIG_IEEE80211W */
400 :
401 : #ifdef CONFIG_P2P
402 2404 : if (wpa_s->global->p2p) {
403 : u8 *pos;
404 : size_t len;
405 : int res;
406 2404 : pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len;
407 2404 : len = sizeof(wpa_s->sme.assoc_req_ie) -
408 2404 : wpa_s->sme.assoc_req_ie_len;
409 2404 : res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len,
410 : ssid->p2p_group);
411 2404 : if (res >= 0)
412 2398 : wpa_s->sme.assoc_req_ie_len += res;
413 : }
414 : #endif /* CONFIG_P2P */
415 :
416 : #ifdef CONFIG_HS20
417 2404 : if (is_hs20_network(wpa_s, ssid, bss)) {
418 : struct wpabuf *hs20;
419 89 : hs20 = wpabuf_alloc(20);
420 89 : if (hs20) {
421 89 : int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid);
422 : size_t len;
423 :
424 89 : wpas_hs20_add_indication(hs20, pps_mo_id);
425 89 : len = sizeof(wpa_s->sme.assoc_req_ie) -
426 89 : wpa_s->sme.assoc_req_ie_len;
427 89 : if (wpabuf_len(hs20) <= len) {
428 89 : os_memcpy(wpa_s->sme.assoc_req_ie +
429 : wpa_s->sme.assoc_req_ie_len,
430 : wpabuf_head(hs20), wpabuf_len(hs20));
431 89 : wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20);
432 : }
433 89 : wpabuf_free(hs20);
434 : }
435 : }
436 : #endif /* CONFIG_HS20 */
437 :
438 2404 : ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab,
439 : sizeof(ext_capab));
440 2404 : if (ext_capab_len > 0) {
441 2404 : u8 *pos = wpa_s->sme.assoc_req_ie;
442 2404 : if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN)
443 1773 : pos += 2 + pos[1];
444 2404 : os_memmove(pos + ext_capab_len, pos,
445 : wpa_s->sme.assoc_req_ie_len -
446 : (pos - wpa_s->sme.assoc_req_ie));
447 2404 : wpa_s->sme.assoc_req_ie_len += ext_capab_len;
448 2404 : os_memcpy(pos, ext_capab, ext_capab_len);
449 : }
450 :
451 2404 : if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
452 1 : struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
453 : size_t len;
454 :
455 1 : len = sizeof(wpa_s->sme.assoc_req_ie) -
456 1 : wpa_s->sme.assoc_req_ie_len;
457 1 : if (wpabuf_len(buf) <= len) {
458 1 : os_memcpy(wpa_s->sme.assoc_req_ie +
459 : wpa_s->sme.assoc_req_ie_len,
460 : wpabuf_head(buf), wpabuf_len(buf));
461 1 : wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
462 : }
463 : }
464 :
465 2404 : sme_auth_handle_rrm(wpa_s, bss);
466 :
467 : #ifdef CONFIG_SAE
468 2472 : if (params.auth_alg == WPA_AUTH_ALG_SAE &&
469 68 : pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, ssid, 0) == 0)
470 : {
471 2 : wpa_dbg(wpa_s, MSG_DEBUG,
472 : "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication");
473 2 : params.auth_alg = WPA_AUTH_ALG_OPEN;
474 2 : wpa_s->sme.sae_pmksa_caching = 1;
475 : }
476 :
477 2404 : if (params.auth_alg == WPA_AUTH_ALG_SAE) {
478 66 : if (start)
479 39 : resp = sme_auth_build_sae_commit(wpa_s, ssid,
480 39 : bss->bssid);
481 : else
482 27 : resp = sme_auth_build_sae_confirm(wpa_s);
483 66 : if (resp == NULL) {
484 4 : wpas_connection_failed(wpa_s, bss->bssid);
485 4 : return;
486 : }
487 62 : params.sae_data = wpabuf_head(resp);
488 62 : params.sae_data_len = wpabuf_len(resp);
489 62 : wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED;
490 : }
491 : #endif /* CONFIG_SAE */
492 :
493 2400 : wpa_supplicant_cancel_sched_scan(wpa_s);
494 2400 : wpa_supplicant_cancel_scan(wpa_s);
495 :
496 16800 : wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR
497 14400 : " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
498 : wpa_ssid_txt(params.ssid, params.ssid_len), params.freq);
499 :
500 2400 : wpa_clear_keys(wpa_s, bss->bssid);
501 2400 : wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
502 2400 : old_ssid = wpa_s->current_ssid;
503 2400 : wpa_s->current_ssid = ssid;
504 2400 : wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid);
505 2400 : wpa_supplicant_initiate_eapol(wpa_s);
506 2400 : if (old_ssid != wpa_s->current_ssid)
507 762 : wpas_notify_network_changed(wpa_s);
508 :
509 : #ifdef CONFIG_P2P
510 : /*
511 : * If multi-channel concurrency is not supported, check for any
512 : * frequency conflict. In case of any frequency conflict, remove the
513 : * least prioritized connection.
514 : */
515 2400 : if (wpa_s->num_multichan_concurrent < 2) {
516 : int freq, num;
517 2391 : num = get_shared_radio_freqs(wpa_s, &freq, 1);
518 2391 : if (num > 0 && freq > 0 && freq != params.freq) {
519 1 : wpa_printf(MSG_DEBUG,
520 : "Conflicting frequency found (%d != %d)",
521 : freq, params.freq);
522 1 : if (wpas_p2p_handle_frequency_conflicts(wpa_s,
523 : params.freq,
524 : ssid) < 0) {
525 0 : wpas_connection_failed(wpa_s, bss->bssid);
526 0 : wpa_supplicant_mark_disassoc(wpa_s);
527 0 : wpabuf_free(resp);
528 0 : wpas_connect_work_done(wpa_s);
529 0 : return;
530 : }
531 : }
532 : }
533 : #endif /* CONFIG_P2P */
534 :
535 2400 : wpa_s->sme.auth_alg = params.auth_alg;
536 2400 : if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) {
537 0 : wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the "
538 : "driver failed");
539 0 : wpas_connection_failed(wpa_s, bss->bssid);
540 0 : wpa_supplicant_mark_disassoc(wpa_s);
541 0 : wpabuf_free(resp);
542 0 : wpas_connect_work_done(wpa_s);
543 0 : return;
544 : }
545 :
546 2400 : eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
547 : NULL);
548 :
549 : /*
550 : * Association will be started based on the authentication event from
551 : * the driver.
552 : */
553 :
554 2400 : wpabuf_free(resp);
555 : }
556 :
557 :
558 2376 : static void sme_auth_start_cb(struct wpa_radio_work *work, int deinit)
559 : {
560 2376 : struct wpa_connect_work *cwork = work->ctx;
561 2376 : struct wpa_supplicant *wpa_s = work->wpa_s;
562 :
563 2376 : if (deinit) {
564 2 : if (work->started)
565 0 : wpa_s->connect_work = NULL;
566 :
567 2 : wpas_connect_work_free(cwork);
568 2 : return;
569 : }
570 :
571 2374 : wpa_s->connect_work = work;
572 :
573 4747 : if (cwork->bss_removed ||
574 2373 : !wpas_valid_bss_ssid(wpa_s, cwork->bss, cwork->ssid)) {
575 1 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: BSS/SSID entry for authentication not valid anymore - drop connection attempt");
576 1 : wpas_connect_work_done(wpa_s);
577 1 : return;
578 : }
579 :
580 2373 : sme_send_authentication(wpa_s, cwork->bss, cwork->ssid, 1);
581 : }
582 :
583 :
584 2378 : void sme_authenticate(struct wpa_supplicant *wpa_s,
585 : struct wpa_bss *bss, struct wpa_ssid *ssid)
586 : {
587 : struct wpa_connect_work *cwork;
588 :
589 2378 : if (bss == NULL || ssid == NULL)
590 2 : return;
591 2376 : if (wpa_s->connect_work) {
592 0 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reject sme_authenticate() call since connect_work exist");
593 0 : return;
594 : }
595 :
596 2376 : if (radio_work_pending(wpa_s, "sme-connect")) {
597 : /*
598 : * The previous sme-connect work might no longer be valid due to
599 : * the fact that the BSS list was updated. In addition, it makes
600 : * sense to adhere to the 'newer' decision.
601 : */
602 0 : wpa_dbg(wpa_s, MSG_DEBUG,
603 : "SME: Remove previous pending sme-connect");
604 0 : radio_remove_works(wpa_s, "sme-connect", 0);
605 : }
606 :
607 2376 : cwork = os_zalloc(sizeof(*cwork));
608 2376 : if (cwork == NULL)
609 0 : return;
610 2376 : cwork->bss = bss;
611 2376 : cwork->ssid = ssid;
612 2376 : cwork->sme = 1;
613 :
614 : #ifdef CONFIG_SAE
615 2376 : wpa_s->sme.sae.state = SAE_NOTHING;
616 2376 : wpa_s->sme.sae.send_confirm = 0;
617 2376 : wpa_s->sme.sae_group_index = 0;
618 : #endif /* CONFIG_SAE */
619 :
620 2376 : if (radio_add_work(wpa_s, bss->freq, "sme-connect", 1,
621 : sme_auth_start_cb, cwork) < 0)
622 0 : wpas_connect_work_free(cwork);
623 : }
624 :
625 :
626 : #ifdef CONFIG_SAE
627 :
628 62 : static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
629 : u16 status_code, const u8 *data, size_t len)
630 : {
631 : int *groups;
632 :
633 62 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE authentication transaction %u "
634 : "status code %u", auth_transaction, status_code);
635 :
636 62 : if (auth_transaction == 1 &&
637 5 : status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
638 10 : wpa_s->sme.sae.state == SAE_COMMITTED &&
639 10 : wpa_s->current_bss && wpa_s->current_ssid) {
640 5 : int default_groups[] = { 19, 20, 21, 25, 26, 0 };
641 : u16 group;
642 :
643 5 : groups = wpa_s->conf->sae_groups;
644 5 : if (!groups || groups[0] <= 0)
645 5 : groups = default_groups;
646 :
647 5 : if (len < sizeof(le16)) {
648 0 : wpa_dbg(wpa_s, MSG_DEBUG,
649 : "SME: Too short SAE anti-clogging token request");
650 0 : return -1;
651 : }
652 5 : group = WPA_GET_LE16(data);
653 5 : wpa_dbg(wpa_s, MSG_DEBUG,
654 : "SME: SAE anti-clogging token requested (group %u)",
655 : group);
656 5 : if (sae_group_allowed(&wpa_s->sme.sae, groups, group) !=
657 : WLAN_STATUS_SUCCESS) {
658 0 : wpa_dbg(wpa_s, MSG_ERROR,
659 : "SME: SAE group %u of anti-clogging request is invalid",
660 : group);
661 0 : return -1;
662 : }
663 5 : wpabuf_free(wpa_s->sme.sae_token);
664 5 : wpa_s->sme.sae_token = wpabuf_alloc_copy(data + sizeof(le16),
665 : len - sizeof(le16));
666 5 : sme_send_authentication(wpa_s, wpa_s->current_bss,
667 : wpa_s->current_ssid, 1);
668 5 : return 0;
669 : }
670 :
671 57 : if (auth_transaction == 1 &&
672 3 : status_code == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
673 6 : wpa_s->sme.sae.state == SAE_COMMITTED &&
674 6 : wpa_s->current_bss && wpa_s->current_ssid) {
675 3 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE group not supported");
676 3 : wpa_s->sme.sae_group_index++;
677 3 : if (sme_set_sae_group(wpa_s) < 0)
678 0 : return -1; /* no other groups enabled */
679 3 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Try next enabled SAE group");
680 3 : sme_send_authentication(wpa_s, wpa_s->current_bss,
681 : wpa_s->current_ssid, 1);
682 3 : return 0;
683 : }
684 :
685 54 : if (status_code != WLAN_STATUS_SUCCESS)
686 0 : return -1;
687 :
688 54 : if (auth_transaction == 1) {
689 27 : groups = wpa_s->conf->sae_groups;
690 :
691 27 : wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit");
692 54 : if (wpa_s->current_bss == NULL ||
693 27 : wpa_s->current_ssid == NULL)
694 0 : return -1;
695 27 : if (wpa_s->sme.sae.state != SAE_COMMITTED)
696 0 : return -1;
697 27 : if (groups && groups[0] <= 0)
698 13 : groups = NULL;
699 27 : if (sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
700 : groups) != WLAN_STATUS_SUCCESS)
701 0 : return -1;
702 :
703 27 : if (sae_process_commit(&wpa_s->sme.sae) < 0) {
704 0 : wpa_printf(MSG_DEBUG, "SAE: Failed to process peer "
705 : "commit");
706 0 : return -1;
707 : }
708 :
709 27 : wpabuf_free(wpa_s->sme.sae_token);
710 27 : wpa_s->sme.sae_token = NULL;
711 27 : sme_send_authentication(wpa_s, wpa_s->current_bss,
712 : wpa_s->current_ssid, 0);
713 27 : return 0;
714 27 : } else if (auth_transaction == 2) {
715 27 : wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE confirm");
716 27 : if (wpa_s->sme.sae.state != SAE_CONFIRMED)
717 0 : return -1;
718 27 : if (sae_check_confirm(&wpa_s->sme.sae, data, len) < 0)
719 0 : return -1;
720 27 : wpa_s->sme.sae.state = SAE_ACCEPTED;
721 27 : sae_clear_temp_data(&wpa_s->sme.sae);
722 27 : return 1;
723 : }
724 :
725 0 : return -1;
726 : }
727 : #endif /* CONFIG_SAE */
728 :
729 :
730 2380 : void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
731 : {
732 2380 : struct wpa_ssid *ssid = wpa_s->current_ssid;
733 :
734 2380 : if (ssid == NULL) {
735 5 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
736 : "when network is not selected");
737 5 : return;
738 : }
739 :
740 2375 : if (wpa_s->wpa_state != WPA_AUTHENTICATING) {
741 0 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event "
742 : "when not in authenticating state");
743 0 : return;
744 : }
745 :
746 2375 : if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0) {
747 0 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with "
748 : "unexpected peer " MACSTR,
749 : MAC2STR(data->auth.peer));
750 0 : return;
751 : }
752 :
753 2375 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR
754 : " auth_type=%d auth_transaction=%d status_code=%d",
755 : MAC2STR(data->auth.peer), data->auth.auth_type,
756 : data->auth.auth_transaction, data->auth.status_code);
757 4750 : wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs",
758 2375 : data->auth.ies, data->auth.ies_len);
759 :
760 2375 : eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
761 :
762 : #ifdef CONFIG_SAE
763 2375 : if (data->auth.auth_type == WLAN_AUTH_SAE) {
764 : int res;
765 124 : res = sme_sae_auth(wpa_s, data->auth.auth_transaction,
766 62 : data->auth.status_code, data->auth.ies,
767 : data->auth.ies_len);
768 62 : if (res < 0) {
769 0 : wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
770 0 : wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
771 :
772 : }
773 62 : if (res != 1)
774 35 : return;
775 :
776 27 : wpa_printf(MSG_DEBUG, "SME: SAE completed - setting PMK for "
777 : "4-way handshake");
778 27 : wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, PMK_LEN,
779 27 : wpa_s->pending_bssid);
780 : }
781 : #endif /* CONFIG_SAE */
782 :
783 2340 : if (data->auth.status_code != WLAN_STATUS_SUCCESS) {
784 19 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication failed (status "
785 : "code %d)", data->auth.status_code);
786 :
787 19 : if (data->auth.status_code !=
788 5 : WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG ||
789 10 : wpa_s->sme.auth_alg == data->auth.auth_type ||
790 5 : wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) {
791 17 : wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
792 17 : wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
793 17 : return;
794 : }
795 :
796 2 : wpas_connect_work_done(wpa_s);
797 :
798 2 : switch (data->auth.auth_type) {
799 : case WLAN_AUTH_OPEN:
800 1 : wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED;
801 :
802 1 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying SHARED auth");
803 1 : wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
804 : wpa_s->current_ssid);
805 1 : return;
806 :
807 : case WLAN_AUTH_SHARED_KEY:
808 1 : wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_LEAP;
809 :
810 1 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying LEAP auth");
811 1 : wpa_supplicant_associate(wpa_s, wpa_s->current_bss,
812 : wpa_s->current_ssid);
813 1 : return;
814 :
815 : default:
816 0 : return;
817 : }
818 : }
819 :
820 : #ifdef CONFIG_IEEE80211R
821 2321 : if (data->auth.auth_type == WLAN_AUTH_FT) {
822 : union wpa_event_data edata;
823 113 : os_memset(&edata, 0, sizeof(edata));
824 113 : edata.ft_ies.ies = data->auth.ies;
825 113 : edata.ft_ies.ies_len = data->auth.ies_len;
826 113 : os_memcpy(edata.ft_ies.target_ap, data->auth.peer, ETH_ALEN);
827 113 : wpa_supplicant_event(wpa_s, EVENT_FT_RESPONSE, &edata);
828 : }
829 : #endif /* CONFIG_IEEE80211R */
830 :
831 2321 : sme_associate(wpa_s, ssid->mode, data->auth.peer,
832 2321 : data->auth.auth_type);
833 : }
834 :
835 :
836 2429 : void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
837 : const u8 *bssid, u16 auth_type)
838 : {
839 : struct wpa_driver_associate_params params;
840 : struct ieee802_11_elems elems;
841 : #ifdef CONFIG_HT_OVERRIDES
842 : struct ieee80211_ht_capabilities htcaps;
843 : struct ieee80211_ht_capabilities htcaps_mask;
844 : #endif /* CONFIG_HT_OVERRIDES */
845 : #ifdef CONFIG_VHT_OVERRIDES
846 : struct ieee80211_vht_capabilities vhtcaps;
847 : struct ieee80211_vht_capabilities vhtcaps_mask;
848 : #endif /* CONFIG_VHT_OVERRIDES */
849 :
850 2429 : os_memset(¶ms, 0, sizeof(params));
851 2429 : params.bssid = bssid;
852 2429 : params.ssid = wpa_s->sme.ssid;
853 2429 : params.ssid_len = wpa_s->sme.ssid_len;
854 2429 : params.freq.freq = wpa_s->sme.freq;
855 4858 : params.bg_scan_period = wpa_s->current_ssid ?
856 2429 : wpa_s->current_ssid->bg_scan_period : -1;
857 4858 : params.wpa_ie = wpa_s->sme.assoc_req_ie_len ?
858 2429 : wpa_s->sme.assoc_req_ie : NULL;
859 2429 : params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
860 2429 : params.pairwise_suite = wpa_s->pairwise_cipher;
861 2429 : params.group_suite = wpa_s->group_cipher;
862 2429 : params.key_mgmt_suite = wpa_s->key_mgmt;
863 2429 : params.wpa_proto = wpa_s->wpa_proto;
864 : #ifdef CONFIG_HT_OVERRIDES
865 2429 : os_memset(&htcaps, 0, sizeof(htcaps));
866 2429 : os_memset(&htcaps_mask, 0, sizeof(htcaps_mask));
867 2429 : params.htcaps = (u8 *) &htcaps;
868 2429 : params.htcaps_mask = (u8 *) &htcaps_mask;
869 2429 : wpa_supplicant_apply_ht_overrides(wpa_s, wpa_s->current_ssid, ¶ms);
870 : #endif /* CONFIG_HT_OVERRIDES */
871 : #ifdef CONFIG_VHT_OVERRIDES
872 2429 : os_memset(&vhtcaps, 0, sizeof(vhtcaps));
873 2429 : os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask));
874 2429 : params.vhtcaps = &vhtcaps;
875 2429 : params.vhtcaps_mask = &vhtcaps_mask;
876 2429 : wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, ¶ms);
877 : #endif /* CONFIG_VHT_OVERRIDES */
878 : #ifdef CONFIG_IEEE80211R
879 2429 : if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
880 221 : params.wpa_ie = wpa_s->sme.ft_ies;
881 221 : params.wpa_ie_len = wpa_s->sme.ft_ies_len;
882 : }
883 : #endif /* CONFIG_IEEE80211R */
884 2429 : params.mode = mode;
885 2429 : params.mgmt_frame_protection = wpa_s->sme.mfp;
886 2429 : params.rrm_used = wpa_s->rrm.rrm_used;
887 2429 : if (wpa_s->sme.prev_bssid_set)
888 301 : params.prev_bssid = wpa_s->sme.prev_bssid;
889 :
890 21861 : wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR
891 14574 : " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid),
892 4858 : params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "",
893 : params.freq.freq);
894 :
895 2429 : wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING);
896 :
897 4858 : if (params.wpa_ie == NULL ||
898 2429 : ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0)
899 : < 0) {
900 0 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!");
901 0 : os_memset(&elems, 0, sizeof(elems));
902 : }
903 2429 : if (elems.rsn_ie) {
904 1823 : params.wpa_proto = WPA_PROTO_RSN;
905 1823 : wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2,
906 1823 : elems.rsn_ie_len + 2);
907 606 : } else if (elems.wpa_ie) {
908 16 : params.wpa_proto = WPA_PROTO_WPA;
909 16 : wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2,
910 16 : elems.wpa_ie_len + 2);
911 590 : } else if (elems.osen) {
912 1 : params.wpa_proto = WPA_PROTO_OSEN;
913 1 : wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.osen - 2,
914 1 : elems.osen_len + 2);
915 : } else
916 589 : wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
917 2429 : if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group)
918 349 : params.p2p = 1;
919 :
920 2429 : if (wpa_s->parent->set_sta_uapsd)
921 0 : params.uapsd = wpa_s->parent->sta_uapsd;
922 : else
923 2429 : params.uapsd = -1;
924 :
925 2429 : if (wpa_drv_associate(wpa_s, ¶ms) < 0) {
926 0 : wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the "
927 : "driver failed");
928 0 : wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
929 0 : wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
930 0 : os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
931 2429 : return;
932 : }
933 :
934 2429 : eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s,
935 : NULL);
936 : }
937 :
938 :
939 851 : int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md,
940 : const u8 *ies, size_t ies_len)
941 : {
942 851 : if (md == NULL || ies == NULL) {
943 24 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Remove mobility domain");
944 24 : os_free(wpa_s->sme.ft_ies);
945 24 : wpa_s->sme.ft_ies = NULL;
946 24 : wpa_s->sme.ft_ies_len = 0;
947 24 : wpa_s->sme.ft_used = 0;
948 24 : return 0;
949 : }
950 :
951 827 : os_memcpy(wpa_s->sme.mobility_domain, md, MOBILITY_DOMAIN_ID_LEN);
952 827 : wpa_hexdump(MSG_DEBUG, "SME: FT IEs", ies, ies_len);
953 827 : os_free(wpa_s->sme.ft_ies);
954 827 : wpa_s->sme.ft_ies = os_malloc(ies_len);
955 827 : if (wpa_s->sme.ft_ies == NULL)
956 0 : return -1;
957 827 : os_memcpy(wpa_s->sme.ft_ies, ies, ies_len);
958 827 : wpa_s->sme.ft_ies_len = ies_len;
959 827 : return 0;
960 : }
961 :
962 :
963 8 : static void sme_deauth(struct wpa_supplicant *wpa_s)
964 : {
965 : int bssid_changed;
966 :
967 8 : bssid_changed = !is_zero_ether_addr(wpa_s->bssid);
968 :
969 8 : if (wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
970 : WLAN_REASON_DEAUTH_LEAVING) < 0) {
971 8 : wpa_msg(wpa_s, MSG_INFO, "SME: Deauth request to the driver "
972 : "failed");
973 : }
974 8 : wpa_s->sme.prev_bssid_set = 0;
975 :
976 8 : wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
977 8 : wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
978 8 : os_memset(wpa_s->bssid, 0, ETH_ALEN);
979 8 : os_memset(wpa_s->pending_bssid, 0, ETH_ALEN);
980 8 : if (bssid_changed)
981 0 : wpas_notify_bssid_changed(wpa_s);
982 8 : }
983 :
984 :
985 9 : void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
986 : union wpa_event_data *data)
987 : {
988 9 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association with " MACSTR " failed: "
989 : "status code %d", MAC2STR(wpa_s->pending_bssid),
990 : data->assoc_reject.status_code);
991 :
992 9 : eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
993 :
994 : #ifdef CONFIG_SAE
995 10 : if (wpa_s->sme.sae_pmksa_caching && wpa_s->current_ssid &&
996 1 : wpa_key_mgmt_sae(wpa_s->current_ssid->key_mgmt)) {
997 1 : wpa_dbg(wpa_s, MSG_DEBUG,
998 : "PMKSA caching attempt rejected - drop PMKSA cache entry and fall back to SAE authentication");
999 1 : wpa_sm_aborted_cached(wpa_s->wpa);
1000 1 : wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid);
1001 1 : if (wpa_s->current_bss) {
1002 1 : struct wpa_bss *bss = wpa_s->current_bss;
1003 1 : struct wpa_ssid *ssid = wpa_s->current_ssid;
1004 :
1005 1 : wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
1006 : WLAN_REASON_DEAUTH_LEAVING);
1007 1 : wpas_connect_work_done(wpa_s);
1008 1 : wpa_supplicant_mark_disassoc(wpa_s);
1009 1 : wpa_supplicant_connect(wpa_s, bss, ssid);
1010 10 : return;
1011 : }
1012 : }
1013 : #endif /* CONFIG_SAE */
1014 :
1015 : /*
1016 : * For now, unconditionally terminate the previous authentication. In
1017 : * theory, this should not be needed, but mac80211 gets quite confused
1018 : * if the authentication is left pending.. Some roaming cases might
1019 : * benefit from using the previous authentication, so this could be
1020 : * optimized in the future.
1021 : */
1022 8 : sme_deauth(wpa_s);
1023 : }
1024 :
1025 :
1026 20 : void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s,
1027 : union wpa_event_data *data)
1028 : {
1029 20 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication timed out");
1030 20 : wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
1031 20 : wpa_supplicant_mark_disassoc(wpa_s);
1032 20 : }
1033 :
1034 :
1035 1 : void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s,
1036 : union wpa_event_data *data)
1037 : {
1038 1 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association timed out");
1039 1 : wpas_connection_failed(wpa_s, wpa_s->pending_bssid);
1040 1 : wpa_supplicant_mark_disassoc(wpa_s);
1041 1 : }
1042 :
1043 :
1044 4 : void sme_event_disassoc(struct wpa_supplicant *wpa_s,
1045 : struct disassoc_info *info)
1046 : {
1047 4 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Disassociation event received");
1048 4 : if (wpa_s->sme.prev_bssid_set) {
1049 : /*
1050 : * cfg80211/mac80211 can get into somewhat confused state if
1051 : * the AP only disassociates us and leaves us in authenticated
1052 : * state. For now, force the state to be cleared to avoid
1053 : * confusing errors if we try to associate with the AP again.
1054 : */
1055 4 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Deauthenticate to clear "
1056 : "driver state");
1057 4 : wpa_drv_deauthenticate(wpa_s, wpa_s->sme.prev_bssid,
1058 : WLAN_REASON_DEAUTH_LEAVING);
1059 : }
1060 4 : }
1061 :
1062 :
1063 0 : static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx)
1064 : {
1065 0 : struct wpa_supplicant *wpa_s = eloop_ctx;
1066 0 : if (wpa_s->wpa_state == WPA_AUTHENTICATING) {
1067 0 : wpa_msg(wpa_s, MSG_DEBUG, "SME: Authentication timeout");
1068 0 : sme_deauth(wpa_s);
1069 : }
1070 0 : }
1071 :
1072 :
1073 0 : static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx)
1074 : {
1075 0 : struct wpa_supplicant *wpa_s = eloop_ctx;
1076 0 : if (wpa_s->wpa_state == WPA_ASSOCIATING) {
1077 0 : wpa_msg(wpa_s, MSG_DEBUG, "SME: Association timeout");
1078 0 : sme_deauth(wpa_s);
1079 : }
1080 0 : }
1081 :
1082 :
1083 17809 : void sme_state_changed(struct wpa_supplicant *wpa_s)
1084 : {
1085 : /* Make sure timers are cleaned up appropriately. */
1086 17809 : if (wpa_s->wpa_state != WPA_ASSOCIATING)
1087 15323 : eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
1088 17809 : if (wpa_s->wpa_state != WPA_AUTHENTICATING)
1089 15433 : eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
1090 17809 : }
1091 :
1092 :
1093 7 : void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s,
1094 : const u8 *prev_pending_bssid)
1095 : {
1096 : /*
1097 : * mac80211-workaround to force deauth on failed auth cmd,
1098 : * requires us to remain in authenticating state to allow the
1099 : * second authentication attempt to be continued properly.
1100 : */
1101 7 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Allow pending authentication "
1102 : "to proceed after disconnection event");
1103 7 : wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING);
1104 7 : os_memcpy(wpa_s->pending_bssid, prev_pending_bssid, ETH_ALEN);
1105 :
1106 : /*
1107 : * Re-arm authentication timer in case auth fails for whatever reason.
1108 : */
1109 7 : eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
1110 7 : eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s,
1111 : NULL);
1112 7 : }
1113 :
1114 :
1115 4916 : void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s)
1116 : {
1117 4916 : wpa_s->sme.prev_bssid_set = 0;
1118 : #ifdef CONFIG_SAE
1119 4916 : wpabuf_free(wpa_s->sme.sae_token);
1120 4916 : wpa_s->sme.sae_token = NULL;
1121 4916 : sae_clear_data(&wpa_s->sme.sae);
1122 : #endif /* CONFIG_SAE */
1123 : #ifdef CONFIG_IEEE80211R
1124 4916 : if (wpa_s->sme.ft_ies)
1125 24 : sme_update_ft_ies(wpa_s, NULL, NULL, 0);
1126 : #endif /* CONFIG_IEEE80211R */
1127 4916 : }
1128 :
1129 :
1130 212 : void sme_deinit(struct wpa_supplicant *wpa_s)
1131 : {
1132 212 : os_free(wpa_s->sme.ft_ies);
1133 212 : wpa_s->sme.ft_ies = NULL;
1134 212 : wpa_s->sme.ft_ies_len = 0;
1135 : #ifdef CONFIG_IEEE80211W
1136 212 : sme_stop_sa_query(wpa_s);
1137 : #endif /* CONFIG_IEEE80211W */
1138 212 : sme_clear_on_disassoc(wpa_s);
1139 :
1140 212 : eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
1141 212 : eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
1142 212 : eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
1143 212 : }
1144 :
1145 :
1146 4 : static void sme_send_2040_bss_coex(struct wpa_supplicant *wpa_s,
1147 : const u8 *chan_list, u8 num_channels,
1148 : u8 num_intol)
1149 : {
1150 : struct ieee80211_2040_bss_coex_ie *bc_ie;
1151 : struct ieee80211_2040_intol_chan_report *ic_report;
1152 : struct wpabuf *buf;
1153 :
1154 28 : wpa_printf(MSG_DEBUG, "SME: Send 20/40 BSS Coexistence to " MACSTR
1155 : " (num_channels=%u num_intol=%u)",
1156 24 : MAC2STR(wpa_s->bssid), num_channels, num_intol);
1157 4 : wpa_hexdump(MSG_DEBUG, "SME: 20/40 BSS Intolerant Channels",
1158 : chan_list, num_channels);
1159 :
1160 4 : buf = wpabuf_alloc(2 + /* action.category + action_code */
1161 : sizeof(struct ieee80211_2040_bss_coex_ie) +
1162 : sizeof(struct ieee80211_2040_intol_chan_report) +
1163 : num_channels);
1164 4 : if (buf == NULL)
1165 4 : return;
1166 :
1167 4 : wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
1168 4 : wpabuf_put_u8(buf, WLAN_PA_20_40_BSS_COEX);
1169 :
1170 4 : bc_ie = wpabuf_put(buf, sizeof(*bc_ie));
1171 4 : bc_ie->element_id = WLAN_EID_20_40_BSS_COEXISTENCE;
1172 4 : bc_ie->length = 1;
1173 4 : if (num_intol)
1174 2 : bc_ie->coex_param |= WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ;
1175 :
1176 4 : if (num_channels > 0) {
1177 3 : ic_report = wpabuf_put(buf, sizeof(*ic_report));
1178 3 : ic_report->element_id = WLAN_EID_20_40_BSS_INTOLERANT;
1179 3 : ic_report->length = num_channels + 1;
1180 3 : ic_report->op_class = 0;
1181 3 : os_memcpy(wpabuf_put(buf, num_channels), chan_list,
1182 : num_channels);
1183 : }
1184 :
1185 8 : if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
1186 4 : wpa_s->own_addr, wpa_s->bssid,
1187 4 : wpabuf_head(buf), wpabuf_len(buf), 0) < 0) {
1188 0 : wpa_msg(wpa_s, MSG_INFO,
1189 : "SME: Failed to send 20/40 BSS Coexistence frame");
1190 : }
1191 :
1192 4 : wpabuf_free(buf);
1193 : }
1194 :
1195 :
1196 1543 : int sme_proc_obss_scan(struct wpa_supplicant *wpa_s)
1197 : {
1198 : struct wpa_bss *bss;
1199 : const u8 *ie;
1200 : u16 ht_cap;
1201 : u8 chan_list[P2P_MAX_CHANNELS], channel;
1202 1543 : u8 num_channels = 0, num_intol = 0, i;
1203 :
1204 1543 : if (!wpa_s->sme.sched_obss_scan)
1205 1539 : return 0;
1206 :
1207 4 : wpa_s->sme.sched_obss_scan = 0;
1208 4 : if (!wpa_s->current_bss || wpa_s->wpa_state != WPA_COMPLETED)
1209 0 : return 1;
1210 :
1211 : /*
1212 : * Check whether AP uses regulatory triplet or channel triplet in
1213 : * country info. Right now the operating class of the BSS channel
1214 : * width trigger event is "unknown" (IEEE Std 802.11-2012 10.15.12),
1215 : * based on the assumption that operating class triplet is not used in
1216 : * beacon frame. If the First Channel Number/Operating Extension
1217 : * Identifier octet has a positive integer value of 201 or greater,
1218 : * then its operating class triplet.
1219 : *
1220 : * TODO: If Supported Operating Classes element is present in beacon
1221 : * frame, have to lookup operating class in Annex E and fill them in
1222 : * 2040 coex frame.
1223 : */
1224 4 : ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_COUNTRY);
1225 4 : if (ie && (ie[1] >= 6) && (ie[5] >= 201))
1226 0 : return 1;
1227 :
1228 4 : os_memset(chan_list, 0, sizeof(chan_list));
1229 :
1230 11 : dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
1231 : /* Skip other band bss */
1232 : enum hostapd_hw_mode mode;
1233 7 : mode = ieee80211_freq_to_chan(bss->freq, &channel);
1234 7 : if (mode != HOSTAPD_MODE_IEEE80211G &&
1235 : mode != HOSTAPD_MODE_IEEE80211B)
1236 0 : continue;
1237 :
1238 7 : ie = wpa_bss_get_ie(bss, WLAN_EID_HT_CAP);
1239 7 : ht_cap = (ie && (ie[1] == 26)) ? WPA_GET_LE16(ie + 2) : 0;
1240 49 : wpa_printf(MSG_DEBUG, "SME OBSS scan BSS " MACSTR
1241 : " freq=%u chan=%u ht_cap=0x%x",
1242 42 : MAC2STR(bss->bssid), bss->freq, channel, ht_cap);
1243 :
1244 7 : if (!ht_cap || (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)) {
1245 3 : if (ht_cap & HT_CAP_INFO_40MHZ_INTOLERANT)
1246 2 : num_intol++;
1247 :
1248 : /* Check whether the channel is already considered */
1249 3 : for (i = 0; i < num_channels; i++) {
1250 0 : if (channel == chan_list[i])
1251 0 : break;
1252 : }
1253 3 : if (i != num_channels)
1254 0 : continue;
1255 :
1256 3 : chan_list[num_channels++] = channel;
1257 : }
1258 : }
1259 :
1260 4 : sme_send_2040_bss_coex(wpa_s, chan_list, num_channels, num_intol);
1261 4 : return 1;
1262 : }
1263 :
1264 :
1265 4 : static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
1266 : u16 num_modes,
1267 : enum hostapd_hw_mode mode)
1268 : {
1269 : u16 i;
1270 :
1271 4 : for (i = 0; i < num_modes; i++) {
1272 4 : if (modes[i].mode == mode)
1273 4 : return &modes[i];
1274 : }
1275 :
1276 0 : return NULL;
1277 : }
1278 :
1279 :
1280 4 : static void wpa_obss_scan_freqs_list(struct wpa_supplicant *wpa_s,
1281 : struct wpa_driver_scan_params *params)
1282 : {
1283 : /* Include only affected channels */
1284 : struct hostapd_hw_modes *mode;
1285 : int count, i;
1286 : int start, end;
1287 :
1288 4 : mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
1289 : HOSTAPD_MODE_IEEE80211G);
1290 4 : if (mode == NULL) {
1291 : /* No channels supported in this band - use empty list */
1292 0 : params->freqs = os_zalloc(sizeof(int));
1293 0 : return;
1294 : }
1295 :
1296 7 : if (wpa_s->sme.ht_sec_chan == HT_SEC_CHAN_UNKNOWN &&
1297 3 : wpa_s->current_bss) {
1298 : const u8 *ie;
1299 :
1300 3 : ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_OPERATION);
1301 3 : if (ie && ie[1] >= 2) {
1302 : u8 o;
1303 :
1304 3 : o = ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK;
1305 3 : if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
1306 0 : wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_ABOVE;
1307 3 : else if (o == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
1308 2 : wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_BELOW;
1309 : }
1310 : }
1311 :
1312 4 : start = wpa_s->assoc_freq - 10;
1313 4 : end = wpa_s->assoc_freq + 10;
1314 4 : switch (wpa_s->sme.ht_sec_chan) {
1315 : case HT_SEC_CHAN_UNKNOWN:
1316 : /* HT40+ possible on channels 1..9 */
1317 1 : if (wpa_s->assoc_freq <= 2452)
1318 1 : start -= 20;
1319 : /* HT40- possible on channels 5-13 */
1320 1 : if (wpa_s->assoc_freq >= 2432)
1321 1 : end += 20;
1322 1 : break;
1323 : case HT_SEC_CHAN_ABOVE:
1324 0 : end += 20;
1325 0 : break;
1326 : case HT_SEC_CHAN_BELOW:
1327 3 : start -= 20;
1328 3 : break;
1329 : }
1330 4 : wpa_printf(MSG_DEBUG,
1331 : "OBSS: assoc_freq %d possible affected range %d-%d",
1332 : wpa_s->assoc_freq, start, end);
1333 :
1334 4 : params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
1335 4 : if (params->freqs == NULL)
1336 0 : return;
1337 60 : for (count = 0, i = 0; i < mode->num_channels; i++) {
1338 : int freq;
1339 :
1340 56 : if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
1341 0 : continue;
1342 56 : freq = mode->channels[i].freq;
1343 56 : if (freq - 10 >= end || freq + 10 <= start)
1344 16 : continue; /* not affected */
1345 40 : params->freqs[count++] = freq;
1346 : }
1347 : }
1348 :
1349 :
1350 4 : static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx)
1351 : {
1352 4 : struct wpa_supplicant *wpa_s = eloop_ctx;
1353 : struct wpa_driver_scan_params params;
1354 :
1355 4 : if (!wpa_s->current_bss) {
1356 0 : wpa_printf(MSG_DEBUG, "SME OBSS: Ignore scan request");
1357 4 : return;
1358 : }
1359 :
1360 4 : os_memset(¶ms, 0, sizeof(params));
1361 4 : wpa_obss_scan_freqs_list(wpa_s, ¶ms);
1362 4 : params.low_priority = 1;
1363 4 : wpa_printf(MSG_DEBUG, "SME OBSS: Request an OBSS scan");
1364 :
1365 4 : if (wpa_supplicant_trigger_scan(wpa_s, ¶ms))
1366 0 : wpa_printf(MSG_DEBUG, "SME OBSS: Failed to trigger scan");
1367 : else
1368 4 : wpa_s->sme.sched_obss_scan = 1;
1369 4 : os_free(params.freqs);
1370 :
1371 4 : eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
1372 : sme_obss_scan_timeout, wpa_s, NULL);
1373 : }
1374 :
1375 :
1376 12325 : void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable)
1377 : {
1378 : const u8 *ie;
1379 12325 : struct wpa_bss *bss = wpa_s->current_bss;
1380 12325 : struct wpa_ssid *ssid = wpa_s->current_ssid;
1381 12325 : struct hostapd_hw_modes *hw_mode = NULL;
1382 : int i;
1383 :
1384 12325 : eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL);
1385 12325 : wpa_s->sme.sched_obss_scan = 0;
1386 12325 : wpa_s->sme.ht_sec_chan = HT_SEC_CHAN_UNKNOWN;
1387 12325 : if (!enable)
1388 10309 : return;
1389 :
1390 : /*
1391 : * Schedule OBSS scan if driver is using station SME in wpa_supplicant
1392 : * or it expects OBSS scan to be performed by wpa_supplicant.
1393 : */
1394 2051 : if (!((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
1395 2016 : (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OBSS_SCAN)) ||
1396 1981 : ssid == NULL || ssid->mode != IEEE80211_MODE_INFRA)
1397 290 : return;
1398 :
1399 1726 : if (!wpa_s->hw.modes)
1400 0 : return;
1401 :
1402 : /* only HT caps in 11g mode are relevant */
1403 1726 : for (i = 0; i < wpa_s->hw.num_modes; i++) {
1404 1726 : hw_mode = &wpa_s->hw.modes[i];
1405 1726 : if (hw_mode->mode == HOSTAPD_MODE_IEEE80211G)
1406 1726 : break;
1407 : }
1408 :
1409 : /* Driver does not support HT40 for 11g or doesn't have 11g. */
1410 3452 : if (i == wpa_s->hw.num_modes || !hw_mode ||
1411 1726 : !(hw_mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
1412 0 : return;
1413 :
1414 1726 : if (bss == NULL || bss->freq < 2400 || bss->freq > 2500)
1415 33 : return; /* Not associated on 2.4 GHz band */
1416 :
1417 : /* Check whether AP supports HT40 */
1418 1693 : ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_CAP);
1419 3362 : if (!ie || ie[1] < 2 ||
1420 1669 : !(WPA_GET_LE16(ie + 2) & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET))
1421 1678 : return; /* AP does not support HT40 */
1422 :
1423 15 : ie = wpa_bss_get_ie(wpa_s->current_bss,
1424 : WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS);
1425 15 : if (!ie || ie[1] < 14)
1426 11 : return; /* AP does not request OBSS scans */
1427 :
1428 4 : wpa_s->sme.obss_scan_int = WPA_GET_LE16(ie + 6);
1429 4 : if (wpa_s->sme.obss_scan_int < 10) {
1430 2 : wpa_printf(MSG_DEBUG, "SME: Invalid OBSS Scan Interval %u "
1431 : "replaced with the minimum 10 sec",
1432 2 : wpa_s->sme.obss_scan_int);
1433 2 : wpa_s->sme.obss_scan_int = 10;
1434 : }
1435 4 : wpa_printf(MSG_DEBUG, "SME: OBSS Scan Interval %u sec",
1436 4 : wpa_s->sme.obss_scan_int);
1437 4 : eloop_register_timeout(wpa_s->sme.obss_scan_int, 0,
1438 : sme_obss_scan_timeout, wpa_s, NULL);
1439 : }
1440 :
1441 :
1442 : #ifdef CONFIG_IEEE80211W
1443 :
1444 : static const unsigned int sa_query_max_timeout = 1000;
1445 : static const unsigned int sa_query_retry_timeout = 201;
1446 :
1447 5 : static int sme_check_sa_query_timeout(struct wpa_supplicant *wpa_s)
1448 : {
1449 : u32 tu;
1450 : struct os_reltime now, passed;
1451 5 : os_get_reltime(&now);
1452 5 : os_reltime_sub(&now, &wpa_s->sme.sa_query_start, &passed);
1453 5 : tu = (passed.sec * 1000000 + passed.usec) / 1024;
1454 5 : if (sa_query_max_timeout < tu) {
1455 1 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: SA Query timed out");
1456 1 : sme_stop_sa_query(wpa_s);
1457 1 : wpa_supplicant_deauthenticate(
1458 : wpa_s, WLAN_REASON_PREV_AUTH_NOT_VALID);
1459 1 : return 1;
1460 : }
1461 :
1462 4 : return 0;
1463 : }
1464 :
1465 :
1466 8 : static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s,
1467 : const u8 *trans_id)
1468 : {
1469 : u8 req[2 + WLAN_SA_QUERY_TR_ID_LEN];
1470 8 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Sending SA Query Request to "
1471 : MACSTR, MAC2STR(wpa_s->bssid));
1472 8 : wpa_hexdump(MSG_DEBUG, "SME: SA Query Transaction ID",
1473 : trans_id, WLAN_SA_QUERY_TR_ID_LEN);
1474 8 : req[0] = WLAN_ACTION_SA_QUERY;
1475 8 : req[1] = WLAN_SA_QUERY_REQUEST;
1476 8 : os_memcpy(req + 2, trans_id, WLAN_SA_QUERY_TR_ID_LEN);
1477 8 : if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
1478 8 : wpa_s->own_addr, wpa_s->bssid,
1479 : req, sizeof(req), 0) < 0)
1480 0 : wpa_msg(wpa_s, MSG_INFO, "SME: Failed to send SA Query "
1481 : "Request");
1482 8 : }
1483 :
1484 :
1485 9 : static void sme_sa_query_timer(void *eloop_ctx, void *timeout_ctx)
1486 : {
1487 9 : struct wpa_supplicant *wpa_s = eloop_ctx;
1488 : unsigned int timeout, sec, usec;
1489 : u8 *trans_id, *nbuf;
1490 :
1491 14 : if (wpa_s->sme.sa_query_count > 0 &&
1492 5 : sme_check_sa_query_timeout(wpa_s))
1493 1 : return;
1494 :
1495 8 : nbuf = os_realloc_array(wpa_s->sme.sa_query_trans_id,
1496 8 : wpa_s->sme.sa_query_count + 1,
1497 : WLAN_SA_QUERY_TR_ID_LEN);
1498 8 : if (nbuf == NULL)
1499 0 : return;
1500 8 : if (wpa_s->sme.sa_query_count == 0) {
1501 : /* Starting a new SA Query procedure */
1502 4 : os_get_reltime(&wpa_s->sme.sa_query_start);
1503 : }
1504 8 : trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN;
1505 8 : wpa_s->sme.sa_query_trans_id = nbuf;
1506 8 : wpa_s->sme.sa_query_count++;
1507 :
1508 8 : if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) {
1509 0 : wpa_printf(MSG_DEBUG, "Could not generate SA Query ID");
1510 0 : return;
1511 : }
1512 :
1513 8 : timeout = sa_query_retry_timeout;
1514 8 : sec = ((timeout / 1000) * 1024) / 1000;
1515 8 : usec = (timeout % 1000) * 1024;
1516 8 : eloop_register_timeout(sec, usec, sme_sa_query_timer, wpa_s, NULL);
1517 :
1518 8 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d",
1519 : wpa_s->sme.sa_query_count);
1520 :
1521 8 : sme_send_sa_query_req(wpa_s, trans_id);
1522 : }
1523 :
1524 :
1525 4 : static void sme_start_sa_query(struct wpa_supplicant *wpa_s)
1526 : {
1527 4 : sme_sa_query_timer(wpa_s, NULL);
1528 4 : }
1529 :
1530 :
1531 216 : static void sme_stop_sa_query(struct wpa_supplicant *wpa_s)
1532 : {
1533 216 : eloop_cancel_timeout(sme_sa_query_timer, wpa_s, NULL);
1534 216 : os_free(wpa_s->sme.sa_query_trans_id);
1535 216 : wpa_s->sme.sa_query_trans_id = NULL;
1536 216 : wpa_s->sme.sa_query_count = 0;
1537 216 : }
1538 :
1539 :
1540 38 : void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa,
1541 : const u8 *da, u16 reason_code)
1542 : {
1543 : struct wpa_ssid *ssid;
1544 : struct os_reltime now;
1545 :
1546 38 : if (wpa_s->wpa_state != WPA_COMPLETED)
1547 34 : return;
1548 38 : ssid = wpa_s->current_ssid;
1549 38 : if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION)
1550 0 : return;
1551 38 : if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
1552 0 : return;
1553 38 : if (reason_code != WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA &&
1554 : reason_code != WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA)
1555 4 : return;
1556 34 : if (wpa_s->sme.sa_query_count > 0)
1557 6 : return;
1558 :
1559 28 : os_get_reltime(&now);
1560 53 : if (wpa_s->sme.last_unprot_disconnect.sec &&
1561 25 : !os_reltime_expired(&now, &wpa_s->sme.last_unprot_disconnect, 10))
1562 24 : return; /* limit SA Query procedure frequency */
1563 4 : wpa_s->sme.last_unprot_disconnect = now;
1564 :
1565 4 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Unprotected disconnect dropped - "
1566 : "possible AP/STA state mismatch - trigger SA Query");
1567 4 : sme_start_sa_query(wpa_s);
1568 : }
1569 :
1570 :
1571 3 : void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa,
1572 : const u8 *data, size_t len)
1573 : {
1574 : int i;
1575 :
1576 3 : if (wpa_s->sme.sa_query_trans_id == NULL ||
1577 3 : len < 1 + WLAN_SA_QUERY_TR_ID_LEN ||
1578 3 : data[0] != WLAN_SA_QUERY_RESPONSE)
1579 0 : return;
1580 3 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Received SA Query response from "
1581 : MACSTR " (trans_id %02x%02x)", MAC2STR(sa), data[1], data[2]);
1582 :
1583 3 : if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0)
1584 0 : return;
1585 :
1586 3 : for (i = 0; i < wpa_s->sme.sa_query_count; i++) {
1587 3 : if (os_memcmp(wpa_s->sme.sa_query_trans_id +
1588 : i * WLAN_SA_QUERY_TR_ID_LEN,
1589 : data + 1, WLAN_SA_QUERY_TR_ID_LEN) == 0)
1590 3 : break;
1591 : }
1592 :
1593 3 : if (i >= wpa_s->sme.sa_query_count) {
1594 0 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: No matching SA Query "
1595 : "transaction identifier found");
1596 0 : return;
1597 : }
1598 :
1599 3 : wpa_dbg(wpa_s, MSG_DEBUG, "SME: Reply to pending SA Query received "
1600 : "from " MACSTR, MAC2STR(sa));
1601 3 : sme_stop_sa_query(wpa_s);
1602 : }
1603 :
1604 : #endif /* CONFIG_IEEE80211W */
|