1 |
|
/* |
2 |
|
* hostapd / WPA authenticator glue code |
3 |
< |
* Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi> |
3 |
> |
* Copyright (c) 2002-2011, 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. |
5 |
> |
* This software may be distributed under the terms of the BSD license. |
6 |
> |
* See README for more details. |
7 |
|
*/ |
8 |
|
|
9 |
|
#include "utils/includes.h" |
23 |
|
#include "ap_drv_ops.h" |
24 |
|
#include "ap_config.h" |
25 |
|
#include "wpa_auth.h" |
26 |
+ |
#include "wpa_auth_glue.h" |
27 |
|
|
28 |
|
|
34 |
– |
#ifdef CONFIG_IEEE80211R |
35 |
– |
static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf, |
36 |
– |
size_t len); |
37 |
– |
#endif /* CONFIG_IEEE80211R */ |
38 |
– |
|
39 |
– |
|
29 |
|
static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, |
30 |
|
struct wpa_auth_config *wconf) |
31 |
|
{ |
32 |
+ |
os_memset(wconf, 0, sizeof(*wconf)); |
33 |
|
wconf->wpa = conf->wpa; |
34 |
|
wconf->wpa_key_mgmt = conf->wpa_key_mgmt; |
35 |
|
wconf->wpa_pairwise = conf->wpa_pairwise; |
44 |
|
wconf->peerkey = conf->peerkey; |
45 |
|
wconf->wmm_enabled = conf->wmm_enabled; |
46 |
|
wconf->wmm_uapsd = conf->wmm_uapsd; |
47 |
+ |
wconf->disable_pmksa_caching = conf->disable_pmksa_caching; |
48 |
|
wconf->okc = conf->okc; |
49 |
|
#ifdef CONFIG_IEEE80211W |
50 |
|
wconf->ieee80211w = conf->ieee80211w; |
68 |
|
wconf->r0kh_list = conf->r0kh_list; |
69 |
|
wconf->r1kh_list = conf->r1kh_list; |
70 |
|
wconf->pmk_r1_push = conf->pmk_r1_push; |
71 |
+ |
wconf->ft_over_ds = conf->ft_over_ds; |
72 |
|
#endif /* CONFIG_IEEE80211R */ |
73 |
+ |
#ifdef CONFIG_HS20 |
74 |
+ |
wconf->disable_gtk = conf->disable_dgaf; |
75 |
+ |
#endif /* CONFIG_HS20 */ |
76 |
|
} |
77 |
|
|
78 |
|
|
112 |
|
} |
113 |
|
|
114 |
|
|
115 |
< |
static void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr) |
115 |
> |
static int hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr) |
116 |
|
{ |
117 |
|
struct hostapd_data *hapd = ctx; |
118 |
< |
michael_mic_failure(hapd, addr, 0); |
118 |
> |
return michael_mic_failure(hapd, addr, 0); |
119 |
|
} |
120 |
|
|
121 |
|
|
183 |
|
const u8 *prev_psk) |
184 |
|
{ |
185 |
|
struct hostapd_data *hapd = ctx; |
186 |
< |
return hostapd_get_psk(hapd->conf, addr, prev_psk); |
186 |
> |
struct sta_info *sta = ap_get_sta(hapd, addr); |
187 |
> |
const u8 *psk = hostapd_get_psk(hapd->conf, addr, prev_psk); |
188 |
> |
/* |
189 |
> |
* This is about to iterate over all psks, prev_psk gives the last |
190 |
> |
* returned psk which should not be returned again. |
191 |
> |
* logic list (all hostapd_get_psk; all sta->psk) |
192 |
> |
*/ |
193 |
> |
if (sta && sta->psk && !psk) { |
194 |
> |
struct hostapd_sta_wpa_psk_short *pos; |
195 |
> |
psk = sta->psk->psk; |
196 |
> |
for (pos = sta->psk; pos; pos = pos->next) { |
197 |
> |
if (pos->psk == prev_psk) { |
198 |
> |
psk = pos->next ? pos->next->psk : NULL; |
199 |
> |
break; |
200 |
> |
} |
201 |
> |
} |
202 |
> |
} |
203 |
> |
return psk; |
204 |
|
} |
205 |
|
|
206 |
|
|
242 |
|
return -1; |
243 |
|
} |
244 |
|
|
245 |
< |
return hapd->drv.set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0, |
246 |
< |
key, key_len); |
245 |
> |
return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0, |
246 |
> |
key, key_len); |
247 |
|
} |
248 |
|
|
249 |
|
|
260 |
|
int encrypt) |
261 |
|
{ |
262 |
|
struct hostapd_data *hapd = ctx; |
263 |
< |
return hapd->drv.send_eapol(hapd, addr, data, data_len, encrypt); |
263 |
> |
struct sta_info *sta; |
264 |
> |
u32 flags = 0; |
265 |
> |
|
266 |
> |
sta = ap_get_sta(hapd, addr); |
267 |
> |
if (sta) |
268 |
> |
flags = hostapd_sta_flags_to_drv(sta->flags); |
269 |
> |
|
270 |
> |
return hostapd_drv_hapd_send_eapol(hapd, addr, data, data_len, |
271 |
> |
encrypt, flags); |
272 |
|
} |
273 |
|
|
274 |
|
|
311 |
|
{ |
312 |
|
struct hostapd_data *hapd = ctx; |
313 |
|
struct wpa_auth_iface_iter_data data; |
314 |
< |
if (hapd->iface->for_each_interface == NULL) |
314 |
> |
if (hapd->iface->interfaces == NULL || |
315 |
> |
hapd->iface->interfaces->for_each_interface == NULL) |
316 |
|
return -1; |
317 |
|
data.cb = cb; |
318 |
|
data.cb_ctx = cb_ctx; |
319 |
< |
return hapd->iface->for_each_interface(hapd->iface->interfaces, |
320 |
< |
wpa_auth_iface_iter, &data); |
319 |
> |
return hapd->iface->interfaces->for_each_interface( |
320 |
> |
hapd->iface->interfaces, wpa_auth_iface_iter, &data); |
321 |
|
} |
322 |
|
|
323 |
|
|
348 |
|
MAC2STR(idata->src_hapd->own_addr), |
349 |
|
idata->src_hapd->conf->iface, |
350 |
|
MAC2STR(hapd->own_addr), hapd->conf->iface); |
351 |
< |
hostapd_rrb_receive(hapd, idata->src_hapd->own_addr, |
352 |
< |
idata->data, idata->data_len); |
351 |
> |
wpa_ft_rrb_rx(hapd->wpa_auth, |
352 |
> |
idata->src_hapd->own_addr, |
353 |
> |
idata->data, idata->data_len); |
354 |
|
return 1; |
355 |
|
} |
356 |
|
} |
365 |
|
const u8 *data, size_t data_len) |
366 |
|
{ |
367 |
|
struct hostapd_data *hapd = ctx; |
368 |
+ |
struct l2_ethhdr *buf; |
369 |
+ |
int ret; |
370 |
|
|
371 |
|
#ifdef CONFIG_IEEE80211R |
372 |
< |
if (proto == ETH_P_RRB && hapd->iface->for_each_interface) { |
372 |
> |
if (proto == ETH_P_RRB && hapd->iface->interfaces && |
373 |
> |
hapd->iface->interfaces->for_each_interface) { |
374 |
|
int res; |
375 |
|
struct wpa_auth_ft_iface_iter_data idata; |
376 |
|
idata.src_hapd = hapd; |
377 |
|
idata.dst = dst; |
378 |
|
idata.data = data; |
379 |
|
idata.data_len = data_len; |
380 |
< |
res = hapd->iface->for_each_interface(hapd->iface->interfaces, |
381 |
< |
hostapd_wpa_auth_ft_iter, |
382 |
< |
&idata); |
380 |
> |
res = hapd->iface->interfaces->for_each_interface( |
381 |
> |
hapd->iface->interfaces, hostapd_wpa_auth_ft_iter, |
382 |
> |
&idata); |
383 |
|
if (res == 1) |
384 |
|
return data_len; |
385 |
|
} |
391 |
|
data, data_len); |
392 |
|
if (hapd->l2 == NULL) |
393 |
|
return -1; |
394 |
< |
return l2_packet_send(hapd->l2, dst, proto, data, data_len); |
394 |
> |
|
395 |
> |
buf = os_malloc(sizeof(*buf) + data_len); |
396 |
> |
if (buf == NULL) |
397 |
> |
return -1; |
398 |
> |
os_memcpy(buf->h_dest, dst, ETH_ALEN); |
399 |
> |
os_memcpy(buf->h_source, hapd->own_addr, ETH_ALEN); |
400 |
> |
buf->h_proto = host_to_be16(proto); |
401 |
> |
os_memcpy(buf + 1, data, data_len); |
402 |
> |
ret = l2_packet_send(hapd->l2, dst, proto, (u8 *) buf, |
403 |
> |
sizeof(*buf) + data_len); |
404 |
> |
os_free(buf); |
405 |
> |
return ret; |
406 |
|
} |
407 |
|
|
408 |
|
|
432 |
|
os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN); |
433 |
|
os_memcpy(&m->u, data, data_len); |
434 |
|
|
435 |
< |
res = hapd->drv.send_mgmt_frame(hapd, (u8 *) m, mlen); |
435 |
> |
res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen, 0); |
436 |
|
os_free(m); |
437 |
|
return res; |
438 |
|
} |
444 |
|
struct hostapd_data *hapd = ctx; |
445 |
|
struct sta_info *sta; |
446 |
|
|
447 |
+ |
if (hostapd_add_sta_node(hapd, sta_addr, WLAN_AUTH_FT) < 0) |
448 |
+ |
return NULL; |
449 |
+ |
|
450 |
|
sta = ap_sta_add(hapd, sta_addr); |
451 |
|
if (sta == NULL) |
452 |
|
return NULL; |
470 |
|
size_t len) |
471 |
|
{ |
472 |
|
struct hostapd_data *hapd = ctx; |
473 |
< |
wpa_ft_rrb_rx(hapd->wpa_auth, src_addr, buf, len); |
473 |
> |
struct l2_ethhdr *ethhdr; |
474 |
> |
if (len < sizeof(*ethhdr)) |
475 |
> |
return; |
476 |
> |
ethhdr = (struct l2_ethhdr *) buf; |
477 |
> |
wpa_printf(MSG_DEBUG, "FT: RRB received packet " MACSTR " -> " |
478 |
> |
MACSTR, MAC2STR(ethhdr->h_source), MAC2STR(ethhdr->h_dest)); |
479 |
> |
wpa_ft_rrb_rx(hapd->wpa_auth, ethhdr->h_source, buf + sizeof(*ethhdr), |
480 |
> |
len - sizeof(*ethhdr)); |
481 |
|
} |
482 |
|
|
483 |
+ |
|
484 |
+ |
static int hostapd_wpa_auth_add_tspec(void *ctx, const u8 *sta_addr, |
485 |
+ |
u8 *tspec_ie, size_t tspec_ielen) |
486 |
+ |
{ |
487 |
+ |
struct hostapd_data *hapd = ctx; |
488 |
+ |
return hostapd_add_tspec(hapd, sta_addr, tspec_ie, tspec_ielen); |
489 |
+ |
} |
490 |
+ |
|
491 |
|
#endif /* CONFIG_IEEE80211R */ |
492 |
|
|
493 |
|
|
499 |
|
size_t wpa_ie_len; |
500 |
|
|
501 |
|
hostapd_wpa_auth_conf(hapd->conf, &_conf); |
502 |
+ |
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS) |
503 |
+ |
_conf.tx_status = 1; |
504 |
+ |
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME) |
505 |
+ |
_conf.ap_mlme = 1; |
506 |
|
os_memset(&cb, 0, sizeof(cb)); |
507 |
|
cb.ctx = hapd; |
508 |
|
cb.logger = hostapd_wpa_auth_logger; |
521 |
|
#ifdef CONFIG_IEEE80211R |
522 |
|
cb.send_ft_action = hostapd_wpa_auth_send_ft_action; |
523 |
|
cb.add_sta = hostapd_wpa_auth_add_sta; |
524 |
+ |
cb.add_tspec = hostapd_wpa_auth_add_tspec; |
525 |
|
#endif /* CONFIG_IEEE80211R */ |
526 |
|
hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb); |
527 |
|
if (hapd->wpa_auth == NULL) { |
553 |
|
hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ? |
554 |
|
hapd->conf->bridge : |
555 |
|
hapd->conf->iface, NULL, ETH_P_RRB, |
556 |
< |
hostapd_rrb_receive, hapd, 0); |
556 |
> |
hostapd_rrb_receive, hapd, 1); |
557 |
|
if (hapd->l2 == NULL && |
558 |
|
(hapd->driver == NULL || |
559 |
|
hapd->driver->send_ether == NULL)) { |
579 |
|
|
580 |
|
void hostapd_deinit_wpa(struct hostapd_data *hapd) |
581 |
|
{ |
582 |
+ |
ieee80211_tkip_countermeasures_deinit(hapd); |
583 |
|
rsn_preauth_iface_deinit(hapd); |
584 |
|
if (hapd->wpa_auth) { |
585 |
|
wpa_deinit(hapd->wpa_auth); |