wpa_auth_glue.c revision 214501
1214501Srpaulo/*
2214501Srpaulo * hostapd / WPA authenticator glue code
3214501Srpaulo * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
4214501Srpaulo *
5214501Srpaulo * This program is free software; you can redistribute it and/or modify
6214501Srpaulo * it under the terms of the GNU General Public License version 2 as
7214501Srpaulo * published by the Free Software Foundation.
8214501Srpaulo *
9214501Srpaulo * Alternatively, this software may be distributed under the terms of BSD
10214501Srpaulo * license.
11214501Srpaulo *
12214501Srpaulo * See README and COPYING for more details.
13214501Srpaulo */
14214501Srpaulo
15214501Srpaulo#include "utils/includes.h"
16214501Srpaulo
17214501Srpaulo#include "utils/common.h"
18214501Srpaulo#include "common/ieee802_11_defs.h"
19214501Srpaulo#include "eapol_auth/eapol_auth_sm.h"
20214501Srpaulo#include "eapol_auth/eapol_auth_sm_i.h"
21214501Srpaulo#include "eap_server/eap.h"
22214501Srpaulo#include "l2_packet/l2_packet.h"
23214501Srpaulo#include "drivers/driver.h"
24214501Srpaulo#include "hostapd.h"
25214501Srpaulo#include "ieee802_1x.h"
26214501Srpaulo#include "preauth_auth.h"
27214501Srpaulo#include "sta_info.h"
28214501Srpaulo#include "tkip_countermeasures.h"
29214501Srpaulo#include "ap_drv_ops.h"
30214501Srpaulo#include "ap_config.h"
31214501Srpaulo#include "wpa_auth.h"
32214501Srpaulo
33214501Srpaulo
34214501Srpaulo#ifdef CONFIG_IEEE80211R
35214501Srpaulostatic void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf,
36214501Srpaulo				size_t len);
37214501Srpaulo#endif /* CONFIG_IEEE80211R */
38214501Srpaulo
39214501Srpaulo
40214501Srpaulostatic void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
41214501Srpaulo				  struct wpa_auth_config *wconf)
42214501Srpaulo{
43214501Srpaulo	wconf->wpa = conf->wpa;
44214501Srpaulo	wconf->wpa_key_mgmt = conf->wpa_key_mgmt;
45214501Srpaulo	wconf->wpa_pairwise = conf->wpa_pairwise;
46214501Srpaulo	wconf->wpa_group = conf->wpa_group;
47214501Srpaulo	wconf->wpa_group_rekey = conf->wpa_group_rekey;
48214501Srpaulo	wconf->wpa_strict_rekey = conf->wpa_strict_rekey;
49214501Srpaulo	wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey;
50214501Srpaulo	wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey;
51214501Srpaulo	wconf->rsn_pairwise = conf->rsn_pairwise;
52214501Srpaulo	wconf->rsn_preauth = conf->rsn_preauth;
53214501Srpaulo	wconf->eapol_version = conf->eapol_version;
54214501Srpaulo	wconf->peerkey = conf->peerkey;
55214501Srpaulo	wconf->wmm_enabled = conf->wmm_enabled;
56214501Srpaulo	wconf->wmm_uapsd = conf->wmm_uapsd;
57214501Srpaulo	wconf->okc = conf->okc;
58214501Srpaulo#ifdef CONFIG_IEEE80211W
59214501Srpaulo	wconf->ieee80211w = conf->ieee80211w;
60214501Srpaulo#endif /* CONFIG_IEEE80211W */
61214501Srpaulo#ifdef CONFIG_IEEE80211R
62214501Srpaulo	wconf->ssid_len = conf->ssid.ssid_len;
63214501Srpaulo	if (wconf->ssid_len > SSID_LEN)
64214501Srpaulo		wconf->ssid_len = SSID_LEN;
65214501Srpaulo	os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len);
66214501Srpaulo	os_memcpy(wconf->mobility_domain, conf->mobility_domain,
67214501Srpaulo		  MOBILITY_DOMAIN_ID_LEN);
68214501Srpaulo	if (conf->nas_identifier &&
69214501Srpaulo	    os_strlen(conf->nas_identifier) <= FT_R0KH_ID_MAX_LEN) {
70214501Srpaulo		wconf->r0_key_holder_len = os_strlen(conf->nas_identifier);
71214501Srpaulo		os_memcpy(wconf->r0_key_holder, conf->nas_identifier,
72214501Srpaulo			  wconf->r0_key_holder_len);
73214501Srpaulo	}
74214501Srpaulo	os_memcpy(wconf->r1_key_holder, conf->r1_key_holder, FT_R1KH_ID_LEN);
75214501Srpaulo	wconf->r0_key_lifetime = conf->r0_key_lifetime;
76214501Srpaulo	wconf->reassociation_deadline = conf->reassociation_deadline;
77214501Srpaulo	wconf->r0kh_list = conf->r0kh_list;
78214501Srpaulo	wconf->r1kh_list = conf->r1kh_list;
79214501Srpaulo	wconf->pmk_r1_push = conf->pmk_r1_push;
80214501Srpaulo#endif /* CONFIG_IEEE80211R */
81214501Srpaulo}
82214501Srpaulo
83214501Srpaulo
84214501Srpaulostatic void hostapd_wpa_auth_logger(void *ctx, const u8 *addr,
85214501Srpaulo				    logger_level level, const char *txt)
86214501Srpaulo{
87214501Srpaulo#ifndef CONFIG_NO_HOSTAPD_LOGGER
88214501Srpaulo	struct hostapd_data *hapd = ctx;
89214501Srpaulo	int hlevel;
90214501Srpaulo
91214501Srpaulo	switch (level) {
92214501Srpaulo	case LOGGER_WARNING:
93214501Srpaulo		hlevel = HOSTAPD_LEVEL_WARNING;
94214501Srpaulo		break;
95214501Srpaulo	case LOGGER_INFO:
96214501Srpaulo		hlevel = HOSTAPD_LEVEL_INFO;
97214501Srpaulo		break;
98214501Srpaulo	case LOGGER_DEBUG:
99214501Srpaulo	default:
100214501Srpaulo		hlevel = HOSTAPD_LEVEL_DEBUG;
101214501Srpaulo		break;
102214501Srpaulo	}
103214501Srpaulo
104214501Srpaulo	hostapd_logger(hapd, addr, HOSTAPD_MODULE_WPA, hlevel, "%s", txt);
105214501Srpaulo#endif /* CONFIG_NO_HOSTAPD_LOGGER */
106214501Srpaulo}
107214501Srpaulo
108214501Srpaulo
109214501Srpaulostatic void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr,
110214501Srpaulo					u16 reason)
111214501Srpaulo{
112214501Srpaulo	struct hostapd_data *hapd = ctx;
113214501Srpaulo	wpa_printf(MSG_DEBUG, "%s: WPA authenticator requests disconnect: "
114214501Srpaulo		   "STA " MACSTR " reason %d",
115214501Srpaulo		   __func__, MAC2STR(addr), reason);
116214501Srpaulo	ap_sta_disconnect(hapd, NULL, addr, reason);
117214501Srpaulo}
118214501Srpaulo
119214501Srpaulo
120214501Srpaulostatic void hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr)
121214501Srpaulo{
122214501Srpaulo	struct hostapd_data *hapd = ctx;
123214501Srpaulo	michael_mic_failure(hapd, addr, 0);
124214501Srpaulo}
125214501Srpaulo
126214501Srpaulo
127214501Srpaulostatic void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr,
128214501Srpaulo				       wpa_eapol_variable var, int value)
129214501Srpaulo{
130214501Srpaulo	struct hostapd_data *hapd = ctx;
131214501Srpaulo	struct sta_info *sta = ap_get_sta(hapd, addr);
132214501Srpaulo	if (sta == NULL)
133214501Srpaulo		return;
134214501Srpaulo	switch (var) {
135214501Srpaulo	case WPA_EAPOL_portEnabled:
136214501Srpaulo		ieee802_1x_notify_port_enabled(sta->eapol_sm, value);
137214501Srpaulo		break;
138214501Srpaulo	case WPA_EAPOL_portValid:
139214501Srpaulo		ieee802_1x_notify_port_valid(sta->eapol_sm, value);
140214501Srpaulo		break;
141214501Srpaulo	case WPA_EAPOL_authorized:
142214501Srpaulo		ieee802_1x_set_sta_authorized(hapd, sta, value);
143214501Srpaulo		break;
144214501Srpaulo	case WPA_EAPOL_portControl_Auto:
145214501Srpaulo		if (sta->eapol_sm)
146214501Srpaulo			sta->eapol_sm->portControl = Auto;
147214501Srpaulo		break;
148214501Srpaulo	case WPA_EAPOL_keyRun:
149214501Srpaulo		if (sta->eapol_sm)
150214501Srpaulo			sta->eapol_sm->keyRun = value ? TRUE : FALSE;
151214501Srpaulo		break;
152214501Srpaulo	case WPA_EAPOL_keyAvailable:
153214501Srpaulo		if (sta->eapol_sm)
154214501Srpaulo			sta->eapol_sm->eap_if->eapKeyAvailable =
155214501Srpaulo				value ? TRUE : FALSE;
156214501Srpaulo		break;
157214501Srpaulo	case WPA_EAPOL_keyDone:
158214501Srpaulo		if (sta->eapol_sm)
159214501Srpaulo			sta->eapol_sm->keyDone = value ? TRUE : FALSE;
160214501Srpaulo		break;
161214501Srpaulo	case WPA_EAPOL_inc_EapolFramesTx:
162214501Srpaulo		if (sta->eapol_sm)
163214501Srpaulo			sta->eapol_sm->dot1xAuthEapolFramesTx++;
164214501Srpaulo		break;
165214501Srpaulo	}
166214501Srpaulo}
167214501Srpaulo
168214501Srpaulo
169214501Srpaulostatic int hostapd_wpa_auth_get_eapol(void *ctx, const u8 *addr,
170214501Srpaulo				      wpa_eapol_variable var)
171214501Srpaulo{
172214501Srpaulo	struct hostapd_data *hapd = ctx;
173214501Srpaulo	struct sta_info *sta = ap_get_sta(hapd, addr);
174214501Srpaulo	if (sta == NULL || sta->eapol_sm == NULL)
175214501Srpaulo		return -1;
176214501Srpaulo	switch (var) {
177214501Srpaulo	case WPA_EAPOL_keyRun:
178214501Srpaulo		return sta->eapol_sm->keyRun;
179214501Srpaulo	case WPA_EAPOL_keyAvailable:
180214501Srpaulo		return sta->eapol_sm->eap_if->eapKeyAvailable;
181214501Srpaulo	default:
182214501Srpaulo		return -1;
183214501Srpaulo	}
184214501Srpaulo}
185214501Srpaulo
186214501Srpaulo
187214501Srpaulostatic const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr,
188214501Srpaulo					   const u8 *prev_psk)
189214501Srpaulo{
190214501Srpaulo	struct hostapd_data *hapd = ctx;
191214501Srpaulo	return hostapd_get_psk(hapd->conf, addr, prev_psk);
192214501Srpaulo}
193214501Srpaulo
194214501Srpaulo
195214501Srpaulostatic int hostapd_wpa_auth_get_msk(void *ctx, const u8 *addr, u8 *msk,
196214501Srpaulo				    size_t *len)
197214501Srpaulo{
198214501Srpaulo	struct hostapd_data *hapd = ctx;
199214501Srpaulo	const u8 *key;
200214501Srpaulo	size_t keylen;
201214501Srpaulo	struct sta_info *sta;
202214501Srpaulo
203214501Srpaulo	sta = ap_get_sta(hapd, addr);
204214501Srpaulo	if (sta == NULL)
205214501Srpaulo		return -1;
206214501Srpaulo
207214501Srpaulo	key = ieee802_1x_get_key(sta->eapol_sm, &keylen);
208214501Srpaulo	if (key == NULL)
209214501Srpaulo		return -1;
210214501Srpaulo
211214501Srpaulo	if (keylen > *len)
212214501Srpaulo		keylen = *len;
213214501Srpaulo	os_memcpy(msk, key, keylen);
214214501Srpaulo	*len = keylen;
215214501Srpaulo
216214501Srpaulo	return 0;
217214501Srpaulo}
218214501Srpaulo
219214501Srpaulo
220214501Srpaulostatic int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg,
221214501Srpaulo				    const u8 *addr, int idx, u8 *key,
222214501Srpaulo				    size_t key_len)
223214501Srpaulo{
224214501Srpaulo	struct hostapd_data *hapd = ctx;
225214501Srpaulo	const char *ifname = hapd->conf->iface;
226214501Srpaulo
227214501Srpaulo	if (vlan_id > 0) {
228214501Srpaulo		ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id);
229214501Srpaulo		if (ifname == NULL)
230214501Srpaulo			return -1;
231214501Srpaulo	}
232214501Srpaulo
233214501Srpaulo	return hapd->drv.set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0,
234214501Srpaulo				 key, key_len);
235214501Srpaulo}
236214501Srpaulo
237214501Srpaulo
238214501Srpaulostatic int hostapd_wpa_auth_get_seqnum(void *ctx, const u8 *addr, int idx,
239214501Srpaulo				       u8 *seq)
240214501Srpaulo{
241214501Srpaulo	struct hostapd_data *hapd = ctx;
242214501Srpaulo	return hostapd_get_seqnum(hapd->conf->iface, hapd, addr, idx, seq);
243214501Srpaulo}
244214501Srpaulo
245214501Srpaulo
246214501Srpaulostatic int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr,
247214501Srpaulo				       const u8 *data, size_t data_len,
248214501Srpaulo				       int encrypt)
249214501Srpaulo{
250214501Srpaulo	struct hostapd_data *hapd = ctx;
251214501Srpaulo	return hapd->drv.send_eapol(hapd, addr, data, data_len, encrypt);
252214501Srpaulo}
253214501Srpaulo
254214501Srpaulo
255214501Srpaulostatic int hostapd_wpa_auth_for_each_sta(
256214501Srpaulo	void *ctx, int (*cb)(struct wpa_state_machine *sm, void *ctx),
257214501Srpaulo	void *cb_ctx)
258214501Srpaulo{
259214501Srpaulo	struct hostapd_data *hapd = ctx;
260214501Srpaulo	struct sta_info *sta;
261214501Srpaulo
262214501Srpaulo	for (sta = hapd->sta_list; sta; sta = sta->next) {
263214501Srpaulo		if (sta->wpa_sm && cb(sta->wpa_sm, cb_ctx))
264214501Srpaulo			return 1;
265214501Srpaulo	}
266214501Srpaulo	return 0;
267214501Srpaulo}
268214501Srpaulo
269214501Srpaulo
270214501Srpaulostruct wpa_auth_iface_iter_data {
271214501Srpaulo	int (*cb)(struct wpa_authenticator *sm, void *ctx);
272214501Srpaulo	void *cb_ctx;
273214501Srpaulo};
274214501Srpaulo
275214501Srpaulostatic int wpa_auth_iface_iter(struct hostapd_iface *iface, void *ctx)
276214501Srpaulo{
277214501Srpaulo	struct wpa_auth_iface_iter_data *data = ctx;
278214501Srpaulo	size_t i;
279214501Srpaulo	for (i = 0; i < iface->num_bss; i++) {
280214501Srpaulo		if (iface->bss[i]->wpa_auth &&
281214501Srpaulo		    data->cb(iface->bss[i]->wpa_auth, data->cb_ctx))
282214501Srpaulo			return 1;
283214501Srpaulo	}
284214501Srpaulo	return 0;
285214501Srpaulo}
286214501Srpaulo
287214501Srpaulo
288214501Srpaulostatic int hostapd_wpa_auth_for_each_auth(
289214501Srpaulo	void *ctx, int (*cb)(struct wpa_authenticator *sm, void *ctx),
290214501Srpaulo	void *cb_ctx)
291214501Srpaulo{
292214501Srpaulo	struct hostapd_data *hapd = ctx;
293214501Srpaulo	struct wpa_auth_iface_iter_data data;
294214501Srpaulo	if (hapd->iface->for_each_interface == NULL)
295214501Srpaulo		return -1;
296214501Srpaulo	data.cb = cb;
297214501Srpaulo	data.cb_ctx = cb_ctx;
298214501Srpaulo	return hapd->iface->for_each_interface(hapd->iface->interfaces,
299214501Srpaulo					       wpa_auth_iface_iter, &data);
300214501Srpaulo}
301214501Srpaulo
302214501Srpaulo
303214501Srpaulo#ifdef CONFIG_IEEE80211R
304214501Srpaulo
305214501Srpaulostruct wpa_auth_ft_iface_iter_data {
306214501Srpaulo	struct hostapd_data *src_hapd;
307214501Srpaulo	const u8 *dst;
308214501Srpaulo	const u8 *data;
309214501Srpaulo	size_t data_len;
310214501Srpaulo};
311214501Srpaulo
312214501Srpaulo
313214501Srpaulostatic int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx)
314214501Srpaulo{
315214501Srpaulo	struct wpa_auth_ft_iface_iter_data *idata = ctx;
316214501Srpaulo	struct hostapd_data *hapd;
317214501Srpaulo	size_t j;
318214501Srpaulo
319214501Srpaulo	for (j = 0; j < iface->num_bss; j++) {
320214501Srpaulo		hapd = iface->bss[j];
321214501Srpaulo		if (hapd == idata->src_hapd)
322214501Srpaulo			continue;
323214501Srpaulo		if (os_memcmp(hapd->own_addr, idata->dst, ETH_ALEN) == 0) {
324214501Srpaulo			wpa_printf(MSG_DEBUG, "FT: Send RRB data directly to "
325214501Srpaulo				   "locally managed BSS " MACSTR "@%s -> "
326214501Srpaulo				   MACSTR "@%s",
327214501Srpaulo				   MAC2STR(idata->src_hapd->own_addr),
328214501Srpaulo				   idata->src_hapd->conf->iface,
329214501Srpaulo				   MAC2STR(hapd->own_addr), hapd->conf->iface);
330214501Srpaulo			hostapd_rrb_receive(hapd, idata->src_hapd->own_addr,
331214501Srpaulo					    idata->data, idata->data_len);
332214501Srpaulo			return 1;
333214501Srpaulo		}
334214501Srpaulo	}
335214501Srpaulo
336214501Srpaulo	return 0;
337214501Srpaulo}
338214501Srpaulo
339214501Srpaulo#endif /* CONFIG_IEEE80211R */
340214501Srpaulo
341214501Srpaulo
342214501Srpaulostatic int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto,
343214501Srpaulo				       const u8 *data, size_t data_len)
344214501Srpaulo{
345214501Srpaulo	struct hostapd_data *hapd = ctx;
346214501Srpaulo
347214501Srpaulo#ifdef CONFIG_IEEE80211R
348214501Srpaulo	if (proto == ETH_P_RRB && hapd->iface->for_each_interface) {
349214501Srpaulo		int res;
350214501Srpaulo		struct wpa_auth_ft_iface_iter_data idata;
351214501Srpaulo		idata.src_hapd = hapd;
352214501Srpaulo		idata.dst = dst;
353214501Srpaulo		idata.data = data;
354214501Srpaulo		idata.data_len = data_len;
355214501Srpaulo		res = hapd->iface->for_each_interface(hapd->iface->interfaces,
356214501Srpaulo						      hostapd_wpa_auth_ft_iter,
357214501Srpaulo						      &idata);
358214501Srpaulo		if (res == 1)
359214501Srpaulo			return data_len;
360214501Srpaulo	}
361214501Srpaulo#endif /* CONFIG_IEEE80211R */
362214501Srpaulo
363214501Srpaulo	if (hapd->driver && hapd->driver->send_ether)
364214501Srpaulo		return hapd->driver->send_ether(hapd->drv_priv, dst,
365214501Srpaulo						hapd->own_addr, proto,
366214501Srpaulo						data, data_len);
367214501Srpaulo	if (hapd->l2 == NULL)
368214501Srpaulo		return -1;
369214501Srpaulo	return l2_packet_send(hapd->l2, dst, proto, data, data_len);
370214501Srpaulo}
371214501Srpaulo
372214501Srpaulo
373214501Srpaulo#ifdef CONFIG_IEEE80211R
374214501Srpaulo
375214501Srpaulostatic int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst,
376214501Srpaulo					   const u8 *data, size_t data_len)
377214501Srpaulo{
378214501Srpaulo	struct hostapd_data *hapd = ctx;
379214501Srpaulo	int res;
380214501Srpaulo	struct ieee80211_mgmt *m;
381214501Srpaulo	size_t mlen;
382214501Srpaulo	struct sta_info *sta;
383214501Srpaulo
384214501Srpaulo	sta = ap_get_sta(hapd, dst);
385214501Srpaulo	if (sta == NULL || sta->wpa_sm == NULL)
386214501Srpaulo		return -1;
387214501Srpaulo
388214501Srpaulo	m = os_zalloc(sizeof(*m) + data_len);
389214501Srpaulo	if (m == NULL)
390214501Srpaulo		return -1;
391214501Srpaulo	mlen = ((u8 *) &m->u - (u8 *) m) + data_len;
392214501Srpaulo	m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
393214501Srpaulo					WLAN_FC_STYPE_ACTION);
394214501Srpaulo	os_memcpy(m->da, dst, ETH_ALEN);
395214501Srpaulo	os_memcpy(m->sa, hapd->own_addr, ETH_ALEN);
396214501Srpaulo	os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN);
397214501Srpaulo	os_memcpy(&m->u, data, data_len);
398214501Srpaulo
399214501Srpaulo	res = hapd->drv.send_mgmt_frame(hapd, (u8 *) m, mlen);
400214501Srpaulo	os_free(m);
401214501Srpaulo	return res;
402214501Srpaulo}
403214501Srpaulo
404214501Srpaulo
405214501Srpaulostatic struct wpa_state_machine *
406214501Srpaulohostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr)
407214501Srpaulo{
408214501Srpaulo	struct hostapd_data *hapd = ctx;
409214501Srpaulo	struct sta_info *sta;
410214501Srpaulo
411214501Srpaulo	sta = ap_sta_add(hapd, sta_addr);
412214501Srpaulo	if (sta == NULL)
413214501Srpaulo		return NULL;
414214501Srpaulo	if (sta->wpa_sm) {
415214501Srpaulo		sta->auth_alg = WLAN_AUTH_FT;
416214501Srpaulo		return sta->wpa_sm;
417214501Srpaulo	}
418214501Srpaulo
419214501Srpaulo	sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr);
420214501Srpaulo	if (sta->wpa_sm == NULL) {
421214501Srpaulo		ap_free_sta(hapd, sta);
422214501Srpaulo		return NULL;
423214501Srpaulo	}
424214501Srpaulo	sta->auth_alg = WLAN_AUTH_FT;
425214501Srpaulo
426214501Srpaulo	return sta->wpa_sm;
427214501Srpaulo}
428214501Srpaulo
429214501Srpaulo
430214501Srpaulostatic void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf,
431214501Srpaulo				size_t len)
432214501Srpaulo{
433214501Srpaulo	struct hostapd_data *hapd = ctx;
434214501Srpaulo	wpa_ft_rrb_rx(hapd->wpa_auth, src_addr, buf, len);
435214501Srpaulo}
436214501Srpaulo
437214501Srpaulo#endif /* CONFIG_IEEE80211R */
438214501Srpaulo
439214501Srpaulo
440214501Srpauloint hostapd_setup_wpa(struct hostapd_data *hapd)
441214501Srpaulo{
442214501Srpaulo	struct wpa_auth_config _conf;
443214501Srpaulo	struct wpa_auth_callbacks cb;
444214501Srpaulo	const u8 *wpa_ie;
445214501Srpaulo	size_t wpa_ie_len;
446214501Srpaulo
447214501Srpaulo	hostapd_wpa_auth_conf(hapd->conf, &_conf);
448214501Srpaulo	os_memset(&cb, 0, sizeof(cb));
449214501Srpaulo	cb.ctx = hapd;
450214501Srpaulo	cb.logger = hostapd_wpa_auth_logger;
451214501Srpaulo	cb.disconnect = hostapd_wpa_auth_disconnect;
452214501Srpaulo	cb.mic_failure_report = hostapd_wpa_auth_mic_failure_report;
453214501Srpaulo	cb.set_eapol = hostapd_wpa_auth_set_eapol;
454214501Srpaulo	cb.get_eapol = hostapd_wpa_auth_get_eapol;
455214501Srpaulo	cb.get_psk = hostapd_wpa_auth_get_psk;
456214501Srpaulo	cb.get_msk = hostapd_wpa_auth_get_msk;
457214501Srpaulo	cb.set_key = hostapd_wpa_auth_set_key;
458214501Srpaulo	cb.get_seqnum = hostapd_wpa_auth_get_seqnum;
459214501Srpaulo	cb.send_eapol = hostapd_wpa_auth_send_eapol;
460214501Srpaulo	cb.for_each_sta = hostapd_wpa_auth_for_each_sta;
461214501Srpaulo	cb.for_each_auth = hostapd_wpa_auth_for_each_auth;
462214501Srpaulo	cb.send_ether = hostapd_wpa_auth_send_ether;
463214501Srpaulo#ifdef CONFIG_IEEE80211R
464214501Srpaulo	cb.send_ft_action = hostapd_wpa_auth_send_ft_action;
465214501Srpaulo	cb.add_sta = hostapd_wpa_auth_add_sta;
466214501Srpaulo#endif /* CONFIG_IEEE80211R */
467214501Srpaulo	hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb);
468214501Srpaulo	if (hapd->wpa_auth == NULL) {
469214501Srpaulo		wpa_printf(MSG_ERROR, "WPA initialization failed.");
470214501Srpaulo		return -1;
471214501Srpaulo	}
472214501Srpaulo
473214501Srpaulo	if (hostapd_set_privacy(hapd, 1)) {
474214501Srpaulo		wpa_printf(MSG_ERROR, "Could not set PrivacyInvoked "
475214501Srpaulo			   "for interface %s", hapd->conf->iface);
476214501Srpaulo		return -1;
477214501Srpaulo	}
478214501Srpaulo
479214501Srpaulo	wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len);
480214501Srpaulo	if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) {
481214501Srpaulo		wpa_printf(MSG_ERROR, "Failed to configure WPA IE for "
482214501Srpaulo			   "the kernel driver.");
483214501Srpaulo		return -1;
484214501Srpaulo	}
485214501Srpaulo
486214501Srpaulo	if (rsn_preauth_iface_init(hapd)) {
487214501Srpaulo		wpa_printf(MSG_ERROR, "Initialization of RSN "
488214501Srpaulo			   "pre-authentication failed.");
489214501Srpaulo		return -1;
490214501Srpaulo	}
491214501Srpaulo
492214501Srpaulo#ifdef CONFIG_IEEE80211R
493214501Srpaulo	if (!hostapd_drv_none(hapd)) {
494214501Srpaulo		hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ?
495214501Srpaulo					  hapd->conf->bridge :
496214501Srpaulo					  hapd->conf->iface, NULL, ETH_P_RRB,
497214501Srpaulo					  hostapd_rrb_receive, hapd, 0);
498214501Srpaulo		if (hapd->l2 == NULL &&
499214501Srpaulo		    (hapd->driver == NULL ||
500214501Srpaulo		     hapd->driver->send_ether == NULL)) {
501214501Srpaulo			wpa_printf(MSG_ERROR, "Failed to open l2_packet "
502214501Srpaulo				   "interface");
503214501Srpaulo			return -1;
504214501Srpaulo		}
505214501Srpaulo	}
506214501Srpaulo#endif /* CONFIG_IEEE80211R */
507214501Srpaulo
508214501Srpaulo	return 0;
509214501Srpaulo
510214501Srpaulo}
511214501Srpaulo
512214501Srpaulo
513214501Srpaulovoid hostapd_reconfig_wpa(struct hostapd_data *hapd)
514214501Srpaulo{
515214501Srpaulo	struct wpa_auth_config wpa_auth_conf;
516214501Srpaulo	hostapd_wpa_auth_conf(hapd->conf, &wpa_auth_conf);
517214501Srpaulo	wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf);
518214501Srpaulo}
519214501Srpaulo
520214501Srpaulo
521214501Srpaulovoid hostapd_deinit_wpa(struct hostapd_data *hapd)
522214501Srpaulo{
523214501Srpaulo	rsn_preauth_iface_deinit(hapd);
524214501Srpaulo	if (hapd->wpa_auth) {
525214501Srpaulo		wpa_deinit(hapd->wpa_auth);
526214501Srpaulo		hapd->wpa_auth = NULL;
527214501Srpaulo
528214501Srpaulo		if (hostapd_set_privacy(hapd, 0)) {
529214501Srpaulo			wpa_printf(MSG_DEBUG, "Could not disable "
530214501Srpaulo				   "PrivacyInvoked for interface %s",
531214501Srpaulo				   hapd->conf->iface);
532214501Srpaulo		}
533214501Srpaulo
534214501Srpaulo		if (hostapd_set_generic_elem(hapd, (u8 *) "", 0)) {
535214501Srpaulo			wpa_printf(MSG_DEBUG, "Could not remove generic "
536214501Srpaulo				   "information element from interface %s",
537214501Srpaulo				   hapd->conf->iface);
538214501Srpaulo		}
539214501Srpaulo	}
540214501Srpaulo	ieee802_1x_deinit(hapd);
541214501Srpaulo
542214501Srpaulo#ifdef CONFIG_IEEE80211R
543214501Srpaulo	l2_packet_deinit(hapd->l2);
544214501Srpaulo#endif /* CONFIG_IEEE80211R */
545214501Srpaulo}
546