Branch data Line data Source code
1 : : /*
2 : : * WPA Supplicant - Glue code to setup EAPOL and RSN modules
3 : : * Copyright (c) 2003-2012, 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 "eapol_supp/eapol_supp_sm.h"
13 : : #include "rsn_supp/wpa.h"
14 : : #include "eloop.h"
15 : : #include "config.h"
16 : : #include "l2_packet/l2_packet.h"
17 : : #include "common/wpa_common.h"
18 : : #include "wpa_supplicant_i.h"
19 : : #include "driver_i.h"
20 : : #include "rsn_supp/pmksa_cache.h"
21 : : #include "sme.h"
22 : : #include "common/ieee802_11_defs.h"
23 : : #include "common/wpa_ctrl.h"
24 : : #include "wpas_glue.h"
25 : : #include "wps_supplicant.h"
26 : : #include "bss.h"
27 : : #include "scan.h"
28 : : #include "notify.h"
29 : :
30 : :
31 : : #ifndef CONFIG_NO_CONFIG_BLOBS
32 : : #if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA)
33 : 1 : static void wpa_supplicant_set_config_blob(void *ctx,
34 : : struct wpa_config_blob *blob)
35 : : {
36 : 1 : struct wpa_supplicant *wpa_s = ctx;
37 : 1 : wpa_config_set_blob(wpa_s->conf, blob);
38 [ - + ]: 1 : if (wpa_s->conf->update_config) {
39 : 0 : int ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
40 [ # # ]: 0 : if (ret) {
41 : 0 : wpa_printf(MSG_DEBUG, "Failed to update config after "
42 : : "blob set");
43 : : }
44 : : }
45 : 1 : }
46 : :
47 : :
48 : : static const struct wpa_config_blob *
49 : 2 : wpa_supplicant_get_config_blob(void *ctx, const char *name)
50 : : {
51 : 2 : struct wpa_supplicant *wpa_s = ctx;
52 : 2 : return wpa_config_get_blob(wpa_s->conf, name);
53 : : }
54 : : #endif /* defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA) */
55 : : #endif /* CONFIG_NO_CONFIG_BLOBS */
56 : :
57 : :
58 : : #if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA)
59 : 1528 : static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type,
60 : : const void *data, u16 data_len,
61 : : size_t *msg_len, void **data_pos)
62 : : {
63 : : struct ieee802_1x_hdr *hdr;
64 : :
65 : 1528 : *msg_len = sizeof(*hdr) + data_len;
66 : 1528 : hdr = os_malloc(*msg_len);
67 [ - + ]: 1528 : if (hdr == NULL)
68 : 0 : return NULL;
69 : :
70 : 1528 : hdr->version = wpa_s->conf->eapol_version;
71 : 1528 : hdr->type = type;
72 : 1528 : hdr->length = host_to_be16(data_len);
73 : :
74 [ + + ]: 1528 : if (data)
75 : 996 : os_memcpy(hdr + 1, data, data_len);
76 : : else
77 : 532 : os_memset(hdr + 1, 0, data_len);
78 : :
79 [ + + ]: 1528 : if (data_pos)
80 : 532 : *data_pos = hdr + 1;
81 : :
82 : 1528 : return (u8 *) hdr;
83 : : }
84 : :
85 : :
86 : : /**
87 : : * wpa_ether_send - Send Ethernet frame
88 : : * @wpa_s: Pointer to wpa_supplicant data
89 : : * @dest: Destination MAC address
90 : : * @proto: Ethertype in host byte order
91 : : * @buf: Frame payload starting from IEEE 802.1X header
92 : : * @len: Frame payload length
93 : : * Returns: >=0 on success, <0 on failure
94 : : */
95 : 1528 : static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
96 : : u16 proto, const u8 *buf, size_t len)
97 : : {
98 [ + - ]: 1528 : if (wpa_s->l2) {
99 : 1528 : return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
100 : : }
101 : :
102 : 1528 : return wpa_drv_send_eapol(wpa_s, dest, proto, buf, len);
103 : : }
104 : : #endif /* IEEE8021X_EAPOL || !CONFIG_NO_WPA */
105 : :
106 : :
107 : : #ifdef IEEE8021X_EAPOL
108 : :
109 : : /**
110 : : * wpa_supplicant_eapol_send - Send IEEE 802.1X EAPOL packet to Authenticator
111 : : * @ctx: Pointer to wpa_supplicant data (wpa_s)
112 : : * @type: IEEE 802.1X packet type (IEEE802_1X_TYPE_*)
113 : : * @buf: EAPOL payload (after IEEE 802.1X header)
114 : : * @len: EAPOL payload length
115 : : * Returns: >=0 on success, <0 on failure
116 : : *
117 : : * This function adds Ethernet and IEEE 802.1X header and sends the EAPOL frame
118 : : * to the current Authenticator.
119 : : */
120 : 997 : static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf,
121 : : size_t len)
122 : : {
123 : 997 : struct wpa_supplicant *wpa_s = ctx;
124 : : u8 *msg, *dst, bssid[ETH_ALEN];
125 : : size_t msglen;
126 : : int res;
127 : :
128 : : /* TODO: could add l2_packet_sendmsg that allows fragments to avoid
129 : : * extra copy here */
130 : :
131 [ + + ][ - + ]: 997 : if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
132 : 996 : wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
133 : : /* Current SSID is not using IEEE 802.1X/EAP, so drop possible
134 : : * EAPOL frames (mainly, EAPOL-Start) from EAPOL state
135 : : * machines. */
136 : 1 : wpa_printf(MSG_DEBUG, "WPA: drop TX EAPOL in non-IEEE 802.1X "
137 : : "mode (type=%d len=%lu)", type,
138 : : (unsigned long) len);
139 : 1 : return -1;
140 : : }
141 : :
142 [ - + ][ # # ]: 996 : if (pmksa_cache_get_current(wpa_s->wpa) &&
143 : : type == IEEE802_1X_TYPE_EAPOL_START) {
144 : : /* Trying to use PMKSA caching - do not send EAPOL-Start frames
145 : : * since they will trigger full EAPOL authentication. */
146 : 0 : wpa_printf(MSG_DEBUG, "RSN: PMKSA caching - do not send "
147 : : "EAPOL-Start");
148 : 0 : return -1;
149 : : }
150 : :
151 [ - + ]: 996 : if (is_zero_ether_addr(wpa_s->bssid)) {
152 : 0 : wpa_printf(MSG_DEBUG, "BSSID not set when trying to send an "
153 : : "EAPOL frame");
154 [ # # # # ]: 0 : if (wpa_drv_get_bssid(wpa_s, bssid) == 0 &&
155 : 0 : !is_zero_ether_addr(bssid)) {
156 : 0 : dst = bssid;
157 : 0 : wpa_printf(MSG_DEBUG, "Using current BSSID " MACSTR
158 : : " from the driver as the EAPOL destination",
159 : 0 : MAC2STR(dst));
160 : : } else {
161 : 0 : dst = wpa_s->last_eapol_src;
162 : 0 : wpa_printf(MSG_DEBUG, "Using the source address of the"
163 : : " last received EAPOL frame " MACSTR " as "
164 : : "the EAPOL destination",
165 : 0 : MAC2STR(dst));
166 : : }
167 : : } else {
168 : : /* BSSID was already set (from (Re)Assoc event, so use it as
169 : : * the EAPOL destination. */
170 : 996 : dst = wpa_s->bssid;
171 : : }
172 : :
173 : 996 : msg = wpa_alloc_eapol(wpa_s, type, buf, len, &msglen, NULL);
174 [ - + ]: 996 : if (msg == NULL)
175 : 0 : return -1;
176 : :
177 : 996 : wpa_printf(MSG_DEBUG, "TX EAPOL: dst=" MACSTR, MAC2STR(dst));
178 : 996 : wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", msg, msglen);
179 : 996 : res = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, msg, msglen);
180 : 996 : os_free(msg);
181 : 997 : return res;
182 : : }
183 : :
184 : :
185 : : /**
186 : : * wpa_eapol_set_wep_key - set WEP key for the driver
187 : : * @ctx: Pointer to wpa_supplicant data (wpa_s)
188 : : * @unicast: 1 = individual unicast key, 0 = broadcast key
189 : : * @keyidx: WEP key index (0..3)
190 : : * @key: Pointer to key data
191 : : * @keylen: Key length in bytes
192 : : * Returns: 0 on success or < 0 on error.
193 : : */
194 : 0 : static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx,
195 : : const u8 *key, size_t keylen)
196 : : {
197 : 0 : struct wpa_supplicant *wpa_s = ctx;
198 [ # # ]: 0 : if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
199 [ # # ]: 0 : int cipher = (keylen == 5) ? WPA_CIPHER_WEP40 :
200 : : WPA_CIPHER_WEP104;
201 [ # # ]: 0 : if (unicast)
202 : 0 : wpa_s->pairwise_cipher = cipher;
203 : : else
204 : 0 : wpa_s->group_cipher = cipher;
205 : : }
206 [ # # ]: 0 : return wpa_drv_set_key(wpa_s, WPA_ALG_WEP,
207 : : unicast ? wpa_s->bssid : NULL,
208 : : keyidx, unicast, NULL, 0, key, keylen);
209 : : }
210 : :
211 : :
212 : 5 : static void wpa_supplicant_aborted_cached(void *ctx)
213 : : {
214 : 5 : struct wpa_supplicant *wpa_s = ctx;
215 : 5 : wpa_sm_aborted_cached(wpa_s->wpa);
216 : 5 : }
217 : :
218 : :
219 : 353 : static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol, int success,
220 : : void *ctx)
221 : : {
222 : 353 : struct wpa_supplicant *wpa_s = ctx;
223 : : int res, pmk_len;
224 : : u8 pmk[PMK_LEN];
225 : :
226 [ + + ]: 353 : wpa_printf(MSG_DEBUG, "EAPOL authentication completed %ssuccessfully",
227 : : success ? "" : "un");
228 : :
229 [ + + ]: 353 : if (wpas_wps_eapol_cb(wpa_s) > 0)
230 : 87 : return;
231 : :
232 [ + + ]: 266 : if (!success) {
233 : : /*
234 : : * Make sure we do not get stuck here waiting for long EAPOL
235 : : * timeout if the AP does not disconnect in case of
236 : : * authentication failure.
237 : : */
238 : 3 : wpa_supplicant_req_auth_timeout(wpa_s, 2, 0);
239 : : }
240 : :
241 [ + + ][ + - ]: 266 : if (!success || !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE))
242 : 266 : return;
243 : :
244 [ # # ]: 0 : if (!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt))
245 : 0 : return;
246 : :
247 : 0 : wpa_printf(MSG_DEBUG, "Configure PMK for driver-based RSN 4-way "
248 : : "handshake");
249 : :
250 : 0 : pmk_len = PMK_LEN;
251 [ # # ]: 0 : if (wpa_key_mgmt_ft(wpa_s->key_mgmt)) {
252 : : #ifdef CONFIG_IEEE80211R
253 : : u8 buf[2 * PMK_LEN];
254 : 0 : wpa_printf(MSG_DEBUG, "RSN: Use FT XXKey as PMK for "
255 : : "driver-based 4-way hs and FT");
256 : 0 : res = eapol_sm_get_key(eapol, buf, 2 * PMK_LEN);
257 [ # # ]: 0 : if (res == 0) {
258 : 0 : os_memcpy(pmk, buf + PMK_LEN, PMK_LEN);
259 : 0 : os_memset(buf, 0, sizeof(buf));
260 : : }
261 : : #else /* CONFIG_IEEE80211R */
262 : : res = -1;
263 : : #endif /* CONFIG_IEEE80211R */
264 : : } else {
265 : 0 : res = eapol_sm_get_key(eapol, pmk, PMK_LEN);
266 [ # # ]: 0 : if (res) {
267 : : /*
268 : : * EAP-LEAP is an exception from other EAP methods: it
269 : : * uses only 16-byte PMK.
270 : : */
271 : 0 : res = eapol_sm_get_key(eapol, pmk, 16);
272 : 0 : pmk_len = 16;
273 : : }
274 : : }
275 : :
276 [ # # ]: 0 : if (res) {
277 : 0 : wpa_printf(MSG_DEBUG, "Failed to get PMK from EAPOL state "
278 : : "machines");
279 : 0 : return;
280 : : }
281 : :
282 : 0 : wpa_hexdump_key(MSG_DEBUG, "RSN: Configure PMK for driver-based 4-way "
283 : : "handshake", pmk, pmk_len);
284 : :
285 [ # # ]: 0 : if (wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, NULL, 0, pmk,
286 : : pmk_len)) {
287 : 0 : wpa_printf(MSG_DEBUG, "Failed to set PMK to the driver");
288 : : }
289 : :
290 : 0 : wpa_supplicant_cancel_scan(wpa_s);
291 : 0 : wpa_supplicant_cancel_auth_timeout(wpa_s);
292 : 353 : wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
293 : :
294 : : }
295 : :
296 : :
297 : 0 : static void wpa_supplicant_notify_eapol_done(void *ctx)
298 : : {
299 : 0 : struct wpa_supplicant *wpa_s = ctx;
300 : 0 : wpa_msg(wpa_s, MSG_DEBUG, "WPA: EAPOL processing complete");
301 [ # # ]: 0 : if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
302 : 0 : wpa_supplicant_set_state(wpa_s, WPA_4WAY_HANDSHAKE);
303 : : } else {
304 : 0 : wpa_supplicant_cancel_auth_timeout(wpa_s);
305 : 0 : wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
306 : : }
307 : 0 : }
308 : :
309 : : #endif /* IEEE8021X_EAPOL */
310 : :
311 : :
312 : : #ifndef CONFIG_NO_WPA
313 : :
314 : 0 : static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
315 : : {
316 : 0 : int ret = 0;
317 : 0 : struct wpa_bss *curr = NULL, *bss;
318 : 0 : struct wpa_ssid *ssid = wpa_s->current_ssid;
319 : : const u8 *ie;
320 : :
321 [ # # ]: 0 : dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
322 [ # # ]: 0 : if (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) != 0)
323 : 0 : continue;
324 [ # # ][ # # ]: 0 : if (ssid == NULL ||
325 [ # # ]: 0 : ((bss->ssid_len == ssid->ssid_len &&
326 [ # # ]: 0 : os_memcmp(bss->ssid, ssid->ssid, ssid->ssid_len) == 0) ||
327 : 0 : ssid->ssid_len == 0)) {
328 : 0 : curr = bss;
329 : 0 : break;
330 : : }
331 : : }
332 : :
333 [ # # ]: 0 : if (curr) {
334 : 0 : ie = wpa_bss_get_vendor_ie(curr, WPA_IE_VENDOR_TYPE);
335 [ # # ][ # # ]: 0 : if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
336 : 0 : ret = -1;
337 : :
338 : 0 : ie = wpa_bss_get_ie(curr, WLAN_EID_RSN);
339 [ # # ][ # # ]: 0 : if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
340 : 0 : ret = -1;
341 : : } else {
342 : 0 : ret = -1;
343 : : }
344 : :
345 : 0 : return ret;
346 : : }
347 : :
348 : :
349 : 0 : static int wpa_supplicant_get_beacon_ie(void *ctx)
350 : : {
351 : 0 : struct wpa_supplicant *wpa_s = ctx;
352 [ # # ]: 0 : if (wpa_get_beacon_ie(wpa_s) == 0) {
353 : 0 : return 0;
354 : : }
355 : :
356 : : /* No WPA/RSN IE found in the cached scan results. Try to get updated
357 : : * scan results from the driver. */
358 [ # # ]: 0 : if (wpa_supplicant_update_scan_results(wpa_s) < 0)
359 : 0 : return -1;
360 : :
361 : 0 : return wpa_get_beacon_ie(wpa_s);
362 : : }
363 : :
364 : :
365 : 532 : static u8 * _wpa_alloc_eapol(void *wpa_s, u8 type,
366 : : const void *data, u16 data_len,
367 : : size_t *msg_len, void **data_pos)
368 : : {
369 : 532 : return wpa_alloc_eapol(wpa_s, type, data, data_len, msg_len, data_pos);
370 : : }
371 : :
372 : :
373 : 532 : static int _wpa_ether_send(void *wpa_s, const u8 *dest, u16 proto,
374 : : const u8 *buf, size_t len)
375 : : {
376 : 532 : return wpa_ether_send(wpa_s, dest, proto, buf, len);
377 : : }
378 : :
379 : :
380 : 264 : static void _wpa_supplicant_cancel_auth_timeout(void *wpa_s)
381 : : {
382 : 264 : wpa_supplicant_cancel_auth_timeout(wpa_s);
383 : 264 : }
384 : :
385 : :
386 : 1037 : static void _wpa_supplicant_set_state(void *wpa_s, enum wpa_states state)
387 : : {
388 : 1037 : wpa_supplicant_set_state(wpa_s, state);
389 : 1037 : }
390 : :
391 : :
392 : : /**
393 : : * wpa_supplicant_get_state - Get the connection state
394 : : * @wpa_s: Pointer to wpa_supplicant data
395 : : * Returns: The current connection state (WPA_*)
396 : : */
397 : 757 : static enum wpa_states wpa_supplicant_get_state(struct wpa_supplicant *wpa_s)
398 : : {
399 : 757 : return wpa_s->wpa_state;
400 : : }
401 : :
402 : :
403 : 757 : static enum wpa_states _wpa_supplicant_get_state(void *wpa_s)
404 : : {
405 : 757 : return wpa_supplicant_get_state(wpa_s);
406 : : }
407 : :
408 : :
409 : 9 : static void _wpa_supplicant_deauthenticate(void *wpa_s, int reason_code)
410 : : {
411 : 9 : wpa_supplicant_deauthenticate(wpa_s, reason_code);
412 : : /* Schedule a scan to make sure we continue looking for networks */
413 : 9 : wpa_supplicant_req_scan(wpa_s, 5, 0);
414 : 9 : }
415 : :
416 : :
417 : 271 : static void * wpa_supplicant_get_network_ctx(void *wpa_s)
418 : : {
419 : 271 : return wpa_supplicant_get_ssid(wpa_s);
420 : : }
421 : :
422 : :
423 : 1 : static int wpa_supplicant_get_bssid(void *ctx, u8 *bssid)
424 : : {
425 : 1 : struct wpa_supplicant *wpa_s = ctx;
426 : 1 : return wpa_drv_get_bssid(wpa_s, bssid);
427 : : }
428 : :
429 : :
430 : 629 : static int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg,
431 : : const u8 *addr, int key_idx, int set_tx,
432 : : const u8 *seq, size_t seq_len,
433 : : const u8 *key, size_t key_len)
434 : : {
435 : 629 : struct wpa_supplicant *wpa_s = _wpa_s;
436 [ + + ][ + + ]: 629 : if (alg == WPA_ALG_TKIP && key_idx == 0 && key_len == 32) {
[ + - ]
437 : : /* Clear the MIC error counter when setting a new PTK. */
438 : 8 : wpa_s->mic_errors_seen = 0;
439 : : }
440 : : #ifdef CONFIG_TESTING_GET_GTK
441 : : if (key_idx > 0 && addr && is_broadcast_ether_addr(addr) &&
442 : : alg != WPA_ALG_NONE && key_len <= sizeof(wpa_s->last_gtk)) {
443 : : os_memcpy(wpa_s->last_gtk, key, key_len);
444 : : wpa_s->last_gtk_len = key_len;
445 : : }
446 : : #endif /* CONFIG_TESTING_GET_GTK */
447 : 629 : return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len,
448 : : key, key_len);
449 : : }
450 : :
451 : :
452 : 503 : static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr,
453 : : int protection_type,
454 : : int key_type)
455 : : {
456 : 503 : return wpa_drv_mlme_setprotection(wpa_s, addr, protection_type,
457 : : key_type);
458 : : }
459 : :
460 : :
461 : 81 : static int wpa_supplicant_add_pmkid(void *wpa_s,
462 : : const u8 *bssid, const u8 *pmkid)
463 : : {
464 : 81 : return wpa_drv_add_pmkid(wpa_s, bssid, pmkid);
465 : : }
466 : :
467 : :
468 : 81 : static int wpa_supplicant_remove_pmkid(void *wpa_s,
469 : : const u8 *bssid, const u8 *pmkid)
470 : : {
471 : 81 : return wpa_drv_remove_pmkid(wpa_s, bssid, pmkid);
472 : : }
473 : :
474 : :
475 : : #ifdef CONFIG_IEEE80211R
476 : 76 : static int wpa_supplicant_update_ft_ies(void *ctx, const u8 *md,
477 : : const u8 *ies, size_t ies_len)
478 : : {
479 : 76 : struct wpa_supplicant *wpa_s = ctx;
480 [ + - ]: 76 : if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)
481 : 76 : return sme_update_ft_ies(wpa_s, md, ies, ies_len);
482 : 76 : return wpa_drv_update_ft_ies(wpa_s, md, ies, ies_len);
483 : : }
484 : :
485 : :
486 : 6 : static int wpa_supplicant_send_ft_action(void *ctx, u8 action,
487 : : const u8 *target_ap,
488 : : const u8 *ies, size_t ies_len)
489 : : {
490 : 6 : struct wpa_supplicant *wpa_s = ctx;
491 : 6 : return wpa_drv_send_ft_action(wpa_s, action, target_ap, ies, ies_len);
492 : : }
493 : :
494 : :
495 : 16 : static int wpa_supplicant_mark_authenticated(void *ctx, const u8 *target_ap)
496 : : {
497 : 16 : struct wpa_supplicant *wpa_s = ctx;
498 : : struct wpa_driver_auth_params params;
499 : : struct wpa_bss *bss;
500 : :
501 : 16 : bss = wpa_bss_get_bssid(wpa_s, target_ap);
502 [ - + ]: 16 : if (bss == NULL)
503 : 0 : return -1;
504 : :
505 : 16 : os_memset(¶ms, 0, sizeof(params));
506 : 16 : params.bssid = target_ap;
507 : 16 : params.freq = bss->freq;
508 : 16 : params.ssid = bss->ssid;
509 : 16 : params.ssid_len = bss->ssid_len;
510 : 16 : params.auth_alg = WPA_AUTH_ALG_FT;
511 : 16 : params.local_state_change = 1;
512 : 16 : return wpa_drv_authenticate(wpa_s, ¶ms);
513 : : }
514 : : #endif /* CONFIG_IEEE80211R */
515 : :
516 : :
517 : : #ifdef CONFIG_TDLS
518 : :
519 : 22 : static int wpa_supplicant_tdls_get_capa(void *ctx, int *tdls_supported,
520 : : int *tdls_ext_setup)
521 : : {
522 : 22 : struct wpa_supplicant *wpa_s = ctx;
523 : :
524 : 22 : *tdls_supported = 0;
525 : 22 : *tdls_ext_setup = 0;
526 : :
527 [ - + ]: 22 : if (!wpa_s->drv_capa_known)
528 : 0 : return -1;
529 : :
530 [ + - ]: 22 : if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)
531 : 22 : *tdls_supported = 1;
532 : :
533 [ + - ]: 22 : if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP)
534 : 22 : *tdls_ext_setup = 1;
535 : :
536 : 22 : return 0;
537 : : }
538 : :
539 : :
540 : 105 : static int wpa_supplicant_send_tdls_mgmt(void *ctx, const u8 *dst,
541 : : u8 action_code, u8 dialog_token,
542 : : u16 status_code, const u8 *buf,
543 : : size_t len)
544 : : {
545 : 105 : struct wpa_supplicant *wpa_s = ctx;
546 : 105 : return wpa_drv_send_tdls_mgmt(wpa_s, dst, action_code, dialog_token,
547 : : status_code, buf, len);
548 : : }
549 : :
550 : :
551 : 98 : static int wpa_supplicant_tdls_oper(void *ctx, int oper, const u8 *peer)
552 : : {
553 : 98 : struct wpa_supplicant *wpa_s = ctx;
554 : 98 : return wpa_drv_tdls_oper(wpa_s, oper, peer);
555 : : }
556 : :
557 : :
558 : 81 : static int wpa_supplicant_tdls_peer_addset(
559 : : void *ctx, const u8 *peer, int add, u16 aid, u16 capability,
560 : : const u8 *supp_rates, size_t supp_rates_len,
561 : : const struct ieee80211_ht_capabilities *ht_capab,
562 : : const struct ieee80211_vht_capabilities *vht_capab,
563 : : u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len)
564 : : {
565 : 81 : struct wpa_supplicant *wpa_s = ctx;
566 : : struct hostapd_sta_add_params params;
567 : :
568 : 81 : os_memset(¶ms, 0, sizeof(params));
569 : :
570 : 81 : params.addr = peer;
571 : 81 : params.aid = aid;
572 : 81 : params.capability = capability;
573 : 81 : params.flags = WPA_STA_TDLS_PEER | WPA_STA_AUTHORIZED;
574 : :
575 : : /*
576 : : * TDLS Setup frames do not contain WMM IEs, hence need to depend on
577 : : * qosinfo to check if the peer is WMM capable.
578 : : */
579 [ - + ]: 81 : if (qosinfo)
580 : 0 : params.flags |= WPA_STA_WMM;
581 : :
582 : 81 : params.ht_capabilities = ht_capab;
583 : 81 : params.vht_capabilities = vht_capab;
584 : 81 : params.qosinfo = qosinfo;
585 : 81 : params.listen_interval = 0;
586 : 81 : params.supp_rates = supp_rates;
587 : 81 : params.supp_rates_len = supp_rates_len;
588 : 81 : params.set = !add;
589 : 81 : params.ext_capab = ext_capab;
590 : 81 : params.ext_capab_len = ext_capab_len;
591 : :
592 : 81 : return wpa_drv_sta_add(wpa_s, ¶ms);
593 : : }
594 : :
595 : : #endif /* CONFIG_TDLS */
596 : :
597 : : #endif /* CONFIG_NO_WPA */
598 : :
599 : :
600 : 2 : enum wpa_ctrl_req_type wpa_supplicant_ctrl_req_from_string(const char *field)
601 : : {
602 [ - + ]: 2 : if (os_strcmp(field, "IDENTITY") == 0)
603 : 0 : return WPA_CTRL_REQ_EAP_IDENTITY;
604 [ - + ]: 2 : else if (os_strcmp(field, "PASSWORD") == 0)
605 : 0 : return WPA_CTRL_REQ_EAP_PASSWORD;
606 [ - + ]: 2 : else if (os_strcmp(field, "NEW_PASSWORD") == 0)
607 : 0 : return WPA_CTRL_REQ_EAP_NEW_PASSWORD;
608 [ - + ]: 2 : else if (os_strcmp(field, "PIN") == 0)
609 : 0 : return WPA_CTRL_REQ_EAP_PIN;
610 [ - + ]: 2 : else if (os_strcmp(field, "OTP") == 0)
611 : 0 : return WPA_CTRL_REQ_EAP_OTP;
612 [ - + ]: 2 : else if (os_strcmp(field, "PASSPHRASE") == 0)
613 : 0 : return WPA_CTRL_REQ_EAP_PASSPHRASE;
614 [ + - ]: 2 : else if (os_strcmp(field, "SIM") == 0)
615 : 2 : return WPA_CTRL_REQ_SIM;
616 : 2 : return WPA_CTRL_REQ_UNKNOWN;
617 : : }
618 : :
619 : :
620 : 2 : const char * wpa_supplicant_ctrl_req_to_string(enum wpa_ctrl_req_type field,
621 : : const char *default_txt,
622 : : const char **txt)
623 : : {
624 : 2 : const char *ret = NULL;
625 : :
626 : 2 : *txt = default_txt;
627 : :
628 [ - - - - : 2 : switch (field) {
- - + - ]
629 : : case WPA_CTRL_REQ_EAP_IDENTITY:
630 : 0 : *txt = "Identity";
631 : 0 : ret = "IDENTITY";
632 : 0 : break;
633 : : case WPA_CTRL_REQ_EAP_PASSWORD:
634 : 0 : *txt = "Password";
635 : 0 : ret = "PASSWORD";
636 : 0 : break;
637 : : case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
638 : 0 : *txt = "New Password";
639 : 0 : ret = "NEW_PASSWORD";
640 : 0 : break;
641 : : case WPA_CTRL_REQ_EAP_PIN:
642 : 0 : *txt = "PIN";
643 : 0 : ret = "PIN";
644 : 0 : break;
645 : : case WPA_CTRL_REQ_EAP_OTP:
646 : 0 : ret = "OTP";
647 : 0 : break;
648 : : case WPA_CTRL_REQ_EAP_PASSPHRASE:
649 : 0 : *txt = "Private key passphrase";
650 : 0 : ret = "PASSPHRASE";
651 : 0 : break;
652 : : case WPA_CTRL_REQ_SIM:
653 : 2 : ret = "SIM";
654 : 2 : break;
655 : : default:
656 : 0 : break;
657 : : }
658 : :
659 : : /* txt needs to be something */
660 [ - + ]: 2 : if (*txt == NULL) {
661 : 0 : wpa_printf(MSG_WARNING, "No message for request %d", field);
662 : 0 : ret = NULL;
663 : : }
664 : :
665 : 2 : return ret;
666 : : }
667 : :
668 : : #ifdef IEEE8021X_EAPOL
669 : : #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
670 : 2 : static void wpa_supplicant_eap_param_needed(void *ctx,
671 : : enum wpa_ctrl_req_type field,
672 : : const char *default_txt)
673 : : {
674 : 2 : struct wpa_supplicant *wpa_s = ctx;
675 : 2 : struct wpa_ssid *ssid = wpa_s->current_ssid;
676 : 2 : const char *field_name, *txt = NULL;
677 : : char *buf;
678 : : size_t buflen;
679 : : int len;
680 : :
681 [ - + ]: 2 : if (ssid == NULL)
682 : 0 : return;
683 : :
684 : 2 : wpas_notify_network_request(wpa_s, ssid, field, default_txt);
685 : :
686 : 2 : field_name = wpa_supplicant_ctrl_req_to_string(field, default_txt,
687 : : &txt);
688 [ - + ]: 2 : if (field_name == NULL) {
689 : 0 : wpa_printf(MSG_WARNING, "Unhandled EAP param %d needed",
690 : : field);
691 : 0 : return;
692 : : }
693 : :
694 : 2 : wpas_notify_eap_status(wpa_s, "eap parameter needed", field_name);
695 : :
696 : 2 : buflen = 100 + os_strlen(txt) + ssid->ssid_len;
697 : 2 : buf = os_malloc(buflen);
698 [ - + ]: 2 : if (buf == NULL)
699 : 0 : return;
700 : 2 : len = os_snprintf(buf, buflen,
701 : : WPA_CTRL_REQ "%s-%d:%s needed for SSID ",
702 : : field_name, ssid->id, txt);
703 [ + - ][ - + ]: 2 : if (len < 0 || (size_t) len >= buflen) {
704 : 0 : os_free(buf);
705 : 0 : return;
706 : : }
707 [ + - ][ + - ]: 2 : if (ssid->ssid && buflen > len + ssid->ssid_len) {
708 : 2 : os_memcpy(buf + len, ssid->ssid, ssid->ssid_len);
709 : 2 : len += ssid->ssid_len;
710 : 2 : buf[len] = '\0';
711 : : }
712 : 2 : buf[buflen - 1] = '\0';
713 : 2 : wpa_msg(wpa_s, MSG_INFO, "%s", buf);
714 : 2 : os_free(buf);
715 : : }
716 : : #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
717 : : #define wpa_supplicant_eap_param_needed NULL
718 : : #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
719 : :
720 : :
721 : 5792 : static void wpa_supplicant_port_cb(void *ctx, int authorized)
722 : : {
723 : 5792 : struct wpa_supplicant *wpa_s = ctx;
724 : : #ifdef CONFIG_AP
725 [ + + ]: 5792 : if (wpa_s->ap_iface) {
726 [ - + ]: 10 : wpa_printf(MSG_DEBUG, "AP mode active - skip EAPOL Supplicant "
727 : : "port status: %s",
728 : : authorized ? "Authorized" : "Unauthorized");
729 : 5792 : return;
730 : : }
731 : : #endif /* CONFIG_AP */
732 [ + + ]: 5782 : wpa_printf(MSG_DEBUG, "EAPOL: Supplicant port status: %s",
733 : : authorized ? "Authorized" : "Unauthorized");
734 : 5782 : wpa_drv_set_supp_port(wpa_s, authorized);
735 : : }
736 : :
737 : :
738 : 109 : static void wpa_supplicant_cert_cb(void *ctx, int depth, const char *subject,
739 : : const char *cert_hash,
740 : : const struct wpabuf *cert)
741 : : {
742 : 109 : struct wpa_supplicant *wpa_s = ctx;
743 : :
744 : 109 : wpas_notify_certification(wpa_s, depth, subject, cert_hash, cert);
745 : 109 : }
746 : :
747 : :
748 : 643 : static void wpa_supplicant_status_cb(void *ctx, const char *status,
749 : : const char *parameter)
750 : : {
751 : 643 : struct wpa_supplicant *wpa_s = ctx;
752 : :
753 : 643 : wpas_notify_eap_status(wpa_s, status, parameter);
754 : 643 : }
755 : :
756 : :
757 : 8 : static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len)
758 : : {
759 : 8 : struct wpa_supplicant *wpa_s = ctx;
760 : : char *str;
761 : : int res;
762 : :
763 : 8 : wpa_hexdump_ascii(MSG_DEBUG, "EAP method updated anonymous_identity",
764 : : id, len);
765 : :
766 [ - + ]: 8 : if (wpa_s->current_ssid == NULL)
767 : 0 : return;
768 : :
769 [ - + ]: 8 : if (id == NULL) {
770 [ # # ]: 0 : if (wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
771 : : "NULL", 0) < 0)
772 : 0 : return;
773 : : } else {
774 : 8 : str = os_malloc(len * 2 + 1);
775 [ - + ]: 8 : if (str == NULL)
776 : 0 : return;
777 : 8 : wpa_snprintf_hex(str, len * 2 + 1, id, len);
778 : 8 : res = wpa_config_set(wpa_s->current_ssid, "anonymous_identity",
779 : : str, 0);
780 : 8 : os_free(str);
781 [ - + ]: 8 : if (res < 0)
782 : 0 : return;
783 : : }
784 : :
785 [ - + ]: 8 : if (wpa_s->conf->update_config) {
786 : 0 : res = wpa_config_write(wpa_s->confname, wpa_s->conf);
787 [ # # ]: 0 : if (res) {
788 : 8 : wpa_printf(MSG_DEBUG, "Failed to update config after "
789 : : "anonymous_id update");
790 : : }
791 : : }
792 : : }
793 : : #endif /* IEEE8021X_EAPOL */
794 : :
795 : :
796 : 22 : int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
797 : : {
798 : : #ifdef IEEE8021X_EAPOL
799 : : struct eapol_ctx *ctx;
800 : 22 : ctx = os_zalloc(sizeof(*ctx));
801 [ - + ]: 22 : if (ctx == NULL) {
802 : 0 : wpa_printf(MSG_ERROR, "Failed to allocate EAPOL context.");
803 : 0 : return -1;
804 : : }
805 : :
806 : 22 : ctx->ctx = wpa_s;
807 : 22 : ctx->msg_ctx = wpa_s;
808 : 22 : ctx->eapol_send_ctx = wpa_s;
809 : 22 : ctx->preauth = 0;
810 : 22 : ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done;
811 : 22 : ctx->eapol_send = wpa_supplicant_eapol_send;
812 : 22 : ctx->set_wep_key = wpa_eapol_set_wep_key;
813 : : #ifndef CONFIG_NO_CONFIG_BLOBS
814 : 22 : ctx->set_config_blob = wpa_supplicant_set_config_blob;
815 : 22 : ctx->get_config_blob = wpa_supplicant_get_config_blob;
816 : : #endif /* CONFIG_NO_CONFIG_BLOBS */
817 : 22 : ctx->aborted_cached = wpa_supplicant_aborted_cached;
818 : 22 : ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path;
819 : 22 : ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
820 : 22 : ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
821 : 22 : ctx->wps = wpa_s->wps;
822 : 22 : ctx->eap_param_needed = wpa_supplicant_eap_param_needed;
823 : 22 : ctx->port_cb = wpa_supplicant_port_cb;
824 : 22 : ctx->cb = wpa_supplicant_eapol_cb;
825 : 22 : ctx->cert_cb = wpa_supplicant_cert_cb;
826 : 22 : ctx->status_cb = wpa_supplicant_status_cb;
827 : 22 : ctx->set_anon_id = wpa_supplicant_set_anon_id;
828 : 22 : ctx->cb_ctx = wpa_s;
829 : 22 : wpa_s->eapol = eapol_sm_init(ctx);
830 [ - + ]: 22 : if (wpa_s->eapol == NULL) {
831 : 0 : os_free(ctx);
832 : 0 : wpa_printf(MSG_ERROR, "Failed to initialize EAPOL state "
833 : : "machines.");
834 : 0 : return -1;
835 : : }
836 : : #endif /* IEEE8021X_EAPOL */
837 : :
838 : 22 : return 0;
839 : : }
840 : :
841 : :
842 : : #ifndef CONFIG_NO_WPA
843 : 248 : static void wpa_supplicant_set_rekey_offload(void *ctx, const u8 *kek,
844 : : const u8 *kck,
845 : : const u8 *replay_ctr)
846 : : {
847 : 248 : struct wpa_supplicant *wpa_s = ctx;
848 : :
849 : 248 : wpa_drv_set_rekey_info(wpa_s, kek, kck, replay_ctr);
850 : 248 : }
851 : : #endif /* CONFIG_NO_WPA */
852 : :
853 : :
854 : 22 : int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
855 : : {
856 : : #ifndef CONFIG_NO_WPA
857 : : struct wpa_sm_ctx *ctx;
858 : 22 : ctx = os_zalloc(sizeof(*ctx));
859 [ - + ]: 22 : if (ctx == NULL) {
860 : 0 : wpa_printf(MSG_ERROR, "Failed to allocate WPA context.");
861 : 0 : return -1;
862 : : }
863 : :
864 : 22 : ctx->ctx = wpa_s;
865 : 22 : ctx->msg_ctx = wpa_s;
866 : 22 : ctx->set_state = _wpa_supplicant_set_state;
867 : 22 : ctx->get_state = _wpa_supplicant_get_state;
868 : 22 : ctx->deauthenticate = _wpa_supplicant_deauthenticate;
869 : 22 : ctx->set_key = wpa_supplicant_set_key;
870 : 22 : ctx->get_network_ctx = wpa_supplicant_get_network_ctx;
871 : 22 : ctx->get_bssid = wpa_supplicant_get_bssid;
872 : 22 : ctx->ether_send = _wpa_ether_send;
873 : 22 : ctx->get_beacon_ie = wpa_supplicant_get_beacon_ie;
874 : 22 : ctx->alloc_eapol = _wpa_alloc_eapol;
875 : 22 : ctx->cancel_auth_timeout = _wpa_supplicant_cancel_auth_timeout;
876 : 22 : ctx->add_pmkid = wpa_supplicant_add_pmkid;
877 : 22 : ctx->remove_pmkid = wpa_supplicant_remove_pmkid;
878 : : #ifndef CONFIG_NO_CONFIG_BLOBS
879 : 22 : ctx->set_config_blob = wpa_supplicant_set_config_blob;
880 : 22 : ctx->get_config_blob = wpa_supplicant_get_config_blob;
881 : : #endif /* CONFIG_NO_CONFIG_BLOBS */
882 : 22 : ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection;
883 : : #ifdef CONFIG_IEEE80211R
884 : 22 : ctx->update_ft_ies = wpa_supplicant_update_ft_ies;
885 : 22 : ctx->send_ft_action = wpa_supplicant_send_ft_action;
886 : 22 : ctx->mark_authenticated = wpa_supplicant_mark_authenticated;
887 : : #endif /* CONFIG_IEEE80211R */
888 : : #ifdef CONFIG_TDLS
889 : 22 : ctx->tdls_get_capa = wpa_supplicant_tdls_get_capa;
890 : 22 : ctx->send_tdls_mgmt = wpa_supplicant_send_tdls_mgmt;
891 : 22 : ctx->tdls_oper = wpa_supplicant_tdls_oper;
892 : 22 : ctx->tdls_peer_addset = wpa_supplicant_tdls_peer_addset;
893 : : #endif /* CONFIG_TDLS */
894 : 22 : ctx->set_rekey_offload = wpa_supplicant_set_rekey_offload;
895 : :
896 : 22 : wpa_s->wpa = wpa_sm_init(ctx);
897 [ - + ]: 22 : if (wpa_s->wpa == NULL) {
898 : 0 : wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
899 : : "machine");
900 : 0 : return -1;
901 : : }
902 : : #endif /* CONFIG_NO_WPA */
903 : :
904 : 22 : return 0;
905 : : }
906 : :
907 : :
908 : 431 : void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
909 : : struct wpa_ssid *ssid)
910 : : {
911 : : struct rsn_supp_config conf;
912 [ + - ]: 431 : if (ssid) {
913 : 431 : os_memset(&conf, 0, sizeof(conf));
914 : 431 : conf.network_ctx = ssid;
915 : 431 : conf.peerkey_enabled = ssid->peerkey;
916 : 431 : conf.allowed_pairwise_cipher = ssid->pairwise_cipher;
917 : : #ifdef IEEE8021X_EAPOL
918 : 862 : conf.proactive_key_caching = ssid->proactive_key_caching < 0 ?
919 [ + + ]: 431 : wpa_s->conf->okc : ssid->proactive_key_caching;
920 : 431 : conf.eap_workaround = ssid->eap_workaround;
921 : 431 : conf.eap_conf_ctx = &ssid->eap;
922 : : #endif /* IEEE8021X_EAPOL */
923 : 431 : conf.ssid = ssid->ssid;
924 : 431 : conf.ssid_len = ssid->ssid_len;
925 : 431 : conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey;
926 : : }
927 [ + - ]: 431 : wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL);
928 : 431 : }
|