Added support for using SHA256-based stronger key derivation for WPA2
[mech_eap.git] / wpa_supplicant / wpas_glue.c
1 /*
2  * WPA Supplicant - Glue code to setup EAPOL and RSN modules
3  * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "eapol_supp/eapol_supp_sm.h"
19 #include "wpa.h"
20 #include "eloop.h"
21 #include "config.h"
22 #include "l2_packet/l2_packet.h"
23 #include "wpa_common.h"
24 #include "wpa_supplicant_i.h"
25 #include "pmksa_cache.h"
26 #include "mlme.h"
27 #include "ieee802_11_defs.h"
28 #include "wpa_ctrl.h"
29 #include "wpas_glue.h"
30
31
32 #ifndef CONFIG_NO_CONFIG_BLOBS
33 #if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA)
34 static void wpa_supplicant_set_config_blob(void *ctx,
35                                            struct wpa_config_blob *blob)
36 {
37         struct wpa_supplicant *wpa_s = ctx;
38         wpa_config_set_blob(wpa_s->conf, blob);
39 }
40
41
42 static const struct wpa_config_blob *
43 wpa_supplicant_get_config_blob(void *ctx, const char *name)
44 {
45         struct wpa_supplicant *wpa_s = ctx;
46         return wpa_config_get_blob(wpa_s->conf, name);
47 }
48 #endif /* defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA) */
49 #endif /* CONFIG_NO_CONFIG_BLOBS */
50
51
52 #if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA)
53 static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type,
54                             const void *data, u16 data_len,
55                             size_t *msg_len, void **data_pos)
56 {
57         struct ieee802_1x_hdr *hdr;
58
59         *msg_len = sizeof(*hdr) + data_len;
60         hdr = os_malloc(*msg_len);
61         if (hdr == NULL)
62                 return NULL;
63
64         hdr->version = wpa_s->conf->eapol_version;
65         hdr->type = type;
66         hdr->length = host_to_be16(data_len);
67
68         if (data)
69                 os_memcpy(hdr + 1, data, data_len);
70         else
71                 os_memset(hdr + 1, 0, data_len);
72
73         if (data_pos)
74                 *data_pos = hdr + 1;
75
76         return (u8 *) hdr;
77 }
78
79
80 /**
81  * wpa_ether_send - Send Ethernet frame
82  * @wpa_s: Pointer to wpa_supplicant data
83  * @dest: Destination MAC address
84  * @proto: Ethertype in host byte order
85  * @buf: Frame payload starting from IEEE 802.1X header
86  * @len: Frame payload length
87  * Returns: >=0 on success, <0 on failure
88  */
89 static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest,
90                           u16 proto, const u8 *buf, size_t len)
91 {
92         if (wpa_s->l2) {
93                 return l2_packet_send(wpa_s->l2, dest, proto, buf, len);
94         }
95
96         return wpa_drv_send_eapol(wpa_s, dest, proto, buf, len);
97 }
98 #endif /* IEEE8021X_EAPOL || !CONFIG_NO_WPA */
99
100
101 #ifdef IEEE8021X_EAPOL
102
103 /**
104  * wpa_supplicant_eapol_send - Send IEEE 802.1X EAPOL packet to Authenticator
105  * @ctx: Pointer to wpa_supplicant data (wpa_s)
106  * @type: IEEE 802.1X packet type (IEEE802_1X_TYPE_*)
107  * @buf: EAPOL payload (after IEEE 802.1X header)
108  * @len: EAPOL payload length
109  * Returns: >=0 on success, <0 on failure
110  *
111  * This function adds Ethernet and IEEE 802.1X header and sends the EAPOL frame
112  * to the current Authenticator.
113  */
114 static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf,
115                                      size_t len)
116 {
117         struct wpa_supplicant *wpa_s = ctx;
118         u8 *msg, *dst, bssid[ETH_ALEN];
119         size_t msglen;
120         int res;
121
122         /* TODO: could add l2_packet_sendmsg that allows fragments to avoid
123          * extra copy here */
124
125         if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) ||
126             wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) {
127                 /* Current SSID is not using IEEE 802.1X/EAP, so drop possible
128                  * EAPOL frames (mainly, EAPOL-Start) from EAPOL state
129                  * machines. */
130                 wpa_printf(MSG_DEBUG, "WPA: drop TX EAPOL in non-IEEE 802.1X "
131                            "mode (type=%d len=%lu)", type,
132                            (unsigned long) len);
133                 return -1;
134         }
135
136         if (pmksa_cache_get_current(wpa_s->wpa) &&
137             type == IEEE802_1X_TYPE_EAPOL_START) {
138                 /* Trying to use PMKSA caching - do not send EAPOL-Start frames
139                  * since they will trigger full EAPOL authentication. */
140                 wpa_printf(MSG_DEBUG, "RSN: PMKSA caching - do not send "
141                            "EAPOL-Start");
142                 return -1;
143         }
144
145         if (is_zero_ether_addr(wpa_s->bssid)) {
146                 wpa_printf(MSG_DEBUG, "BSSID not set when trying to send an "
147                            "EAPOL frame");
148                 if (wpa_drv_get_bssid(wpa_s, bssid) == 0 &&
149                     !is_zero_ether_addr(bssid)) {
150                         dst = bssid;
151                         wpa_printf(MSG_DEBUG, "Using current BSSID " MACSTR
152                                    " from the driver as the EAPOL destination",
153                                    MAC2STR(dst));
154                 } else {
155                         dst = wpa_s->last_eapol_src;
156                         wpa_printf(MSG_DEBUG, "Using the source address of the"
157                                    " last received EAPOL frame " MACSTR " as "
158                                    "the EAPOL destination",
159                                    MAC2STR(dst));
160                 }
161         } else {
162                 /* BSSID was already set (from (Re)Assoc event, so use it as
163                  * the EAPOL destination. */
164                 dst = wpa_s->bssid;
165         }
166
167         msg = wpa_alloc_eapol(wpa_s, type, buf, len, &msglen, NULL);
168         if (msg == NULL)
169                 return -1;
170
171         wpa_printf(MSG_DEBUG, "TX EAPOL: dst=" MACSTR, MAC2STR(dst));
172         wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", msg, msglen);
173         res = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, msg, msglen);
174         os_free(msg);
175         return res;
176 }
177
178
179 /**
180  * wpa_eapol_set_wep_key - set WEP key for the driver
181  * @ctx: Pointer to wpa_supplicant data (wpa_s)
182  * @unicast: 1 = individual unicast key, 0 = broadcast key
183  * @keyidx: WEP key index (0..3)
184  * @key: Pointer to key data
185  * @keylen: Key length in bytes
186  * Returns: 0 on success or < 0 on error.
187  */
188 static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx,
189                                  const u8 *key, size_t keylen)
190 {
191         struct wpa_supplicant *wpa_s = ctx;
192         if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
193                 int cipher = (keylen == 5) ? WPA_CIPHER_WEP40 :
194                         WPA_CIPHER_WEP104;
195                 if (unicast)
196                         wpa_s->pairwise_cipher = cipher;
197                 else
198                         wpa_s->group_cipher = cipher;
199         }
200         return wpa_drv_set_key(wpa_s, WPA_ALG_WEP,
201                                unicast ? wpa_s->bssid :
202                                (u8 *) "\xff\xff\xff\xff\xff\xff",
203                                keyidx, unicast, (u8 *) "", 0, key, keylen);
204 }
205
206
207 static void wpa_supplicant_aborted_cached(void *ctx)
208 {
209         struct wpa_supplicant *wpa_s = ctx;
210         wpa_sm_aborted_cached(wpa_s->wpa);
211 }
212
213
214 static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol, int success,
215                                     void *ctx)
216 {
217         struct wpa_supplicant *wpa_s = ctx;
218         int res, pmk_len;
219         u8 pmk[PMK_LEN];
220
221         wpa_printf(MSG_DEBUG, "EAPOL authentication completed %ssuccessfully",
222                    success ? "" : "un");
223
224         if (!success || !wpa_s->driver_4way_handshake)
225                 return;
226
227         if (!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt))
228                 return;
229
230         wpa_printf(MSG_DEBUG, "Configure PMK for driver-based RSN 4-way "
231                    "handshake");
232
233         pmk_len = PMK_LEN;
234         res = eapol_sm_get_key(eapol, pmk, PMK_LEN);
235         if (res) {
236                 /*
237                  * EAP-LEAP is an exception from other EAP methods: it
238                  * uses only 16-byte PMK.
239                  */
240                 res = eapol_sm_get_key(eapol, pmk, 16);
241                 pmk_len = 16;
242         }
243
244         if (res) {
245                 wpa_printf(MSG_DEBUG, "Failed to get PMK from EAPOL state "
246                            "machines");
247                 return;
248         }
249
250         if (wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, NULL, 0, pmk,
251                             pmk_len)) {
252                 wpa_printf(MSG_DEBUG, "Failed to set PMK to the driver");
253         }
254
255         wpa_supplicant_cancel_scan(wpa_s);
256         wpa_supplicant_cancel_auth_timeout(wpa_s);
257         wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
258
259 }
260
261
262 static void wpa_supplicant_notify_eapol_done(void *ctx)
263 {
264         struct wpa_supplicant *wpa_s = ctx;
265         wpa_msg(wpa_s, MSG_DEBUG, "WPA: EAPOL processing complete");
266         if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) {
267                 wpa_supplicant_set_state(wpa_s, WPA_4WAY_HANDSHAKE);
268         } else {
269                 wpa_supplicant_cancel_auth_timeout(wpa_s);
270                 wpa_supplicant_set_state(wpa_s, WPA_COMPLETED);
271         }
272 }
273
274 #endif /* IEEE8021X_EAPOL */
275
276
277 #ifndef CONFIG_NO_WPA
278
279 static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s)
280 {
281         size_t i;
282         int ret = 0;
283         struct wpa_scan_res *curr = NULL;
284         struct wpa_ssid *ssid = wpa_s->current_ssid;
285         const u8 *ie;
286
287         if (wpa_s->scan_res == NULL)
288                 return -1;
289
290         for (i = 0; i < wpa_s->scan_res->num; i++) {
291                 struct wpa_scan_res *r = wpa_s->scan_res->res[i];
292                 if (os_memcmp(r->bssid, wpa_s->bssid, ETH_ALEN) != 0)
293                         continue;
294                 ie = wpa_scan_get_ie(r, WLAN_EID_SSID);
295                 if (ssid == NULL ||
296                     ((ie && ie[1] == ssid->ssid_len &&
297                       os_memcmp(ie + 2, ssid->ssid, ssid->ssid_len) == 0) ||
298                      ssid->ssid_len == 0)) {
299                         curr = r;
300                         break;
301                 }
302         }
303
304         if (curr) {
305                 ie = wpa_scan_get_vendor_ie(curr, WPA_IE_VENDOR_TYPE);
306                 if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
307                         ret = -1;
308
309                 ie = wpa_scan_get_ie(curr, WLAN_EID_RSN);
310                 if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0))
311                         ret = -1;
312         } else {
313                 ret = -1;
314         }
315
316         return ret;
317 }
318
319
320 static int wpa_supplicant_get_beacon_ie(void *ctx)
321 {
322         struct wpa_supplicant *wpa_s = ctx;
323         if (wpa_get_beacon_ie(wpa_s) == 0) {
324                 return 0;
325         }
326
327         /* No WPA/RSN IE found in the cached scan results. Try to get updated
328          * scan results from the driver. */
329         if (wpa_supplicant_get_scan_results(wpa_s) < 0) {
330                 return -1;
331         }
332
333         return wpa_get_beacon_ie(wpa_s);
334 }
335
336
337 static u8 * _wpa_alloc_eapol(void *wpa_s, u8 type,
338                              const void *data, u16 data_len,
339                              size_t *msg_len, void **data_pos)
340 {
341         return wpa_alloc_eapol(wpa_s, type, data, data_len, msg_len, data_pos);
342 }
343
344
345 static int _wpa_ether_send(void *wpa_s, const u8 *dest, u16 proto,
346                            const u8 *buf, size_t len)
347 {
348         return wpa_ether_send(wpa_s, dest, proto, buf, len);
349 }
350
351
352 static void _wpa_supplicant_cancel_auth_timeout(void *wpa_s)
353 {
354         wpa_supplicant_cancel_auth_timeout(wpa_s);
355 }
356
357
358 static void _wpa_supplicant_set_state(void *wpa_s, wpa_states state)
359 {
360         wpa_supplicant_set_state(wpa_s, state);
361 }
362
363
364 /**
365  * wpa_supplicant_get_state - Get the connection state
366  * @wpa_s: Pointer to wpa_supplicant data
367  * Returns: The current connection state (WPA_*)
368  */
369 static wpa_states wpa_supplicant_get_state(struct wpa_supplicant *wpa_s)
370 {
371         return wpa_s->wpa_state;
372 }
373
374
375 static wpa_states _wpa_supplicant_get_state(void *wpa_s)
376 {
377         return wpa_supplicant_get_state(wpa_s);
378 }
379
380
381 static void _wpa_supplicant_disassociate(void *wpa_s, int reason_code)
382 {
383         wpa_supplicant_disassociate(wpa_s, reason_code);
384         /* Schedule a scan to make sure we continue looking for networks */
385         wpa_supplicant_req_scan(wpa_s, 0, 0);
386 }
387
388
389 static void _wpa_supplicant_deauthenticate(void *wpa_s, int reason_code)
390 {
391         wpa_supplicant_deauthenticate(wpa_s, reason_code);
392         /* Schedule a scan to make sure we continue looking for networks */
393         wpa_supplicant_req_scan(wpa_s, 0, 0);
394 }
395
396
397 static void * wpa_supplicant_get_network_ctx(void *wpa_s)
398 {
399         return wpa_supplicant_get_ssid(wpa_s);
400 }
401
402
403 static int wpa_supplicant_get_bssid(void *ctx, u8 *bssid)
404 {
405         struct wpa_supplicant *wpa_s = ctx;
406         if (wpa_s->use_client_mlme) {
407                 os_memcpy(bssid, wpa_s->bssid, ETH_ALEN);
408                 return 0;
409         }
410         return wpa_drv_get_bssid(wpa_s, bssid);
411 }
412
413
414 static int wpa_supplicant_set_key(void *wpa_s, wpa_alg alg,
415                                   const u8 *addr, int key_idx, int set_tx,
416                                   const u8 *seq, size_t seq_len,
417                                   const u8 *key, size_t key_len)
418 {
419         return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len,
420                                key, key_len);
421 }
422
423
424 static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr,
425                                              int protection_type,
426                                              int key_type)
427 {
428         return wpa_drv_mlme_setprotection(wpa_s, addr, protection_type,
429                                           key_type);
430 }
431
432
433 static int wpa_supplicant_add_pmkid(void *wpa_s,
434                                     const u8 *bssid, const u8 *pmkid)
435 {
436         return wpa_drv_add_pmkid(wpa_s, bssid, pmkid);
437 }
438
439
440 static int wpa_supplicant_remove_pmkid(void *wpa_s,
441                                        const u8 *bssid, const u8 *pmkid)
442 {
443         return wpa_drv_remove_pmkid(wpa_s, bssid, pmkid);
444 }
445
446
447 #ifdef CONFIG_IEEE80211R
448 static int wpa_supplicant_update_ft_ies(void *ctx, const u8 *md,
449                                         const u8 *ies, size_t ies_len)
450 {
451         struct wpa_supplicant *wpa_s = ctx;
452         if (wpa_s->use_client_mlme)
453                 return ieee80211_sta_update_ft_ies(wpa_s, md, ies, ies_len);
454         return wpa_drv_update_ft_ies(wpa_s, md, ies, ies_len);
455 }
456
457
458 static int wpa_supplicant_send_ft_action(void *ctx, u8 action,
459                                          const u8 *target_ap,
460                                          const u8 *ies, size_t ies_len)
461 {
462         struct wpa_supplicant *wpa_s = ctx;
463         if (wpa_s->use_client_mlme)
464                 return ieee80211_sta_send_ft_action(wpa_s, action, target_ap,
465                                                     ies, ies_len);
466         return wpa_drv_send_ft_action(wpa_s, action, target_ap, ies, ies_len);
467 }
468 #endif /* CONFIG_IEEE80211R */
469
470 #endif /* CONFIG_NO_WPA */
471
472
473 #if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
474 static void wpa_supplicant_eap_param_needed(void *ctx, const char *field,
475                                             const char *txt)
476 {
477         struct wpa_supplicant *wpa_s = ctx;
478         struct wpa_ssid *ssid = wpa_s->current_ssid;
479         char *buf;
480         size_t buflen;
481         int len;
482
483         if (ssid == NULL)
484                 return;
485
486         buflen = 100 + os_strlen(txt) + ssid->ssid_len;
487         buf = os_malloc(buflen);
488         if (buf == NULL)
489                 return;
490         len = os_snprintf(buf, buflen,
491                           WPA_CTRL_REQ "%s-%d:%s needed for SSID ",
492                           field, ssid->id, txt);
493         if (len < 0 || (size_t) len >= buflen) {
494                 os_free(buf);
495                 return;
496         }
497         if (ssid->ssid && buflen > len + ssid->ssid_len) {
498                 os_memcpy(buf + len, ssid->ssid, ssid->ssid_len);
499                 len += ssid->ssid_len;
500                 buf[len] = '\0';
501         }
502         buf[buflen - 1] = '\0';
503         wpa_msg(wpa_s, MSG_INFO, "%s", buf);
504         os_free(buf);
505 }
506 #else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
507 #define wpa_supplicant_eap_param_needed NULL
508 #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */
509
510
511 int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s)
512 {
513 #ifdef IEEE8021X_EAPOL
514         struct eapol_ctx *ctx;
515         ctx = os_zalloc(sizeof(*ctx));
516         if (ctx == NULL) {
517                 wpa_printf(MSG_ERROR, "Failed to allocate EAPOL context.");
518                 return -1;
519         }
520
521         ctx->ctx = wpa_s;
522         ctx->msg_ctx = wpa_s;
523         ctx->eapol_send_ctx = wpa_s;
524         ctx->preauth = 0;
525         ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done;
526         ctx->eapol_send = wpa_supplicant_eapol_send;
527         ctx->set_wep_key = wpa_eapol_set_wep_key;
528         ctx->set_config_blob = wpa_supplicant_set_config_blob;
529         ctx->get_config_blob = wpa_supplicant_get_config_blob;
530         ctx->aborted_cached = wpa_supplicant_aborted_cached;
531 #ifdef EAP_TLS_OPENSSL
532         ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path;
533         ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path;
534         ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path;
535 #endif /* EAP_TLS_OPENSSL */
536         ctx->eap_param_needed = wpa_supplicant_eap_param_needed;
537         ctx->cb = wpa_supplicant_eapol_cb;
538         ctx->cb_ctx = wpa_s;
539         wpa_s->eapol = eapol_sm_init(ctx);
540         if (wpa_s->eapol == NULL) {
541                 os_free(ctx);
542                 wpa_printf(MSG_ERROR, "Failed to initialize EAPOL state "
543                            "machines.");
544                 return -1;
545         }
546 #endif /* IEEE8021X_EAPOL */
547
548         return 0;
549 }
550
551
552 int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
553 {
554 #ifndef CONFIG_NO_WPA
555         struct wpa_sm_ctx *ctx;
556         ctx = os_zalloc(sizeof(*ctx));
557         if (ctx == NULL) {
558                 wpa_printf(MSG_ERROR, "Failed to allocate WPA context.");
559                 return -1;
560         }
561
562         ctx->ctx = wpa_s;
563         ctx->set_state = _wpa_supplicant_set_state;
564         ctx->get_state = _wpa_supplicant_get_state;
565         ctx->deauthenticate = _wpa_supplicant_deauthenticate;
566         ctx->disassociate = _wpa_supplicant_disassociate;
567         ctx->set_key = wpa_supplicant_set_key;
568         ctx->get_network_ctx = wpa_supplicant_get_network_ctx;
569         ctx->get_bssid = wpa_supplicant_get_bssid;
570         ctx->ether_send = _wpa_ether_send;
571         ctx->get_beacon_ie = wpa_supplicant_get_beacon_ie;
572         ctx->alloc_eapol = _wpa_alloc_eapol;
573         ctx->cancel_auth_timeout = _wpa_supplicant_cancel_auth_timeout;
574         ctx->add_pmkid = wpa_supplicant_add_pmkid;
575         ctx->remove_pmkid = wpa_supplicant_remove_pmkid;
576 #ifndef CONFIG_NO_CONFIG_BLOBS
577         ctx->set_config_blob = wpa_supplicant_set_config_blob;
578         ctx->get_config_blob = wpa_supplicant_get_config_blob;
579 #endif /* CONFIG_NO_CONFIG_BLOBS */
580         ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection;
581 #ifdef CONFIG_IEEE80211R
582         ctx->update_ft_ies = wpa_supplicant_update_ft_ies;
583         ctx->send_ft_action = wpa_supplicant_send_ft_action;
584 #endif /* CONFIG_IEEE80211R */
585
586         wpa_s->wpa = wpa_sm_init(ctx);
587         if (wpa_s->wpa == NULL) {
588                 wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
589                            "machine");
590                 return -1;
591         }
592 #endif /* CONFIG_NO_WPA */
593
594         return 0;
595 }
596
597
598 void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
599                                         struct wpa_ssid *ssid)
600 {
601         struct rsn_supp_config conf;
602         if (ssid) {
603                 os_memset(&conf, 0, sizeof(conf));
604                 conf.network_ctx = ssid;
605                 conf.peerkey_enabled = ssid->peerkey;
606                 conf.allowed_pairwise_cipher = ssid->pairwise_cipher;
607 #ifdef IEEE8021X_EAPOL
608                 conf.eap_workaround = ssid->eap_workaround;
609                 conf.eap_conf_ctx = &ssid->eap;
610 #endif /* IEEE8021X_EAPOL */
611                 conf.ssid = ssid->ssid;
612                 conf.ssid_len = ssid->ssid_len;
613         }
614         wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL);
615 }