preauth_auth.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
1/*
2 * hostapd - Authenticator for IEEE 802.11i RSN pre-authentication
3 * Copyright (c) 2004-2007, 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 "utils/includes.h"
16
17#ifdef CONFIG_RSN_PREAUTH
18
19#include "utils/common.h"
20#include "utils/eloop.h"
21#include "l2_packet/l2_packet.h"
22#include "common/wpa_common.h"
23#include "eapol_auth/eapol_auth_sm.h"
24#include "eapol_auth/eapol_auth_sm_i.h"
25#include "hostapd.h"
26#include "ap_config.h"
27#include "ieee802_1x.h"
28#include "sta_info.h"
29#include "wpa_auth.h"
30#include "preauth_auth.h"
31
32#ifndef ETH_P_PREAUTH
33#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
34#endif /* ETH_P_PREAUTH */
35
36static const int dot11RSNAConfigPMKLifetime = 43200;
37
38struct rsn_preauth_interface {
39	struct rsn_preauth_interface *next;
40	struct hostapd_data *hapd;
41	struct l2_packet_data *l2;
42	char *ifname;
43	int ifindex;
44};
45
46
47static void rsn_preauth_receive(void *ctx, const u8 *src_addr,
48				const u8 *buf, size_t len)
49{
50	struct rsn_preauth_interface *piface = ctx;
51	struct hostapd_data *hapd = piface->hapd;
52	struct ieee802_1x_hdr *hdr;
53	struct sta_info *sta;
54	struct l2_ethhdr *ethhdr;
55
56	wpa_printf(MSG_DEBUG, "RSN: receive pre-auth packet "
57		   "from interface '%s'", piface->ifname);
58	if (len < sizeof(*ethhdr) + sizeof(*hdr)) {
59		wpa_printf(MSG_DEBUG, "RSN: too short pre-auth packet "
60			   "(len=%lu)", (unsigned long) len);
61		return;
62	}
63
64	ethhdr = (struct l2_ethhdr *) buf;
65	hdr = (struct ieee802_1x_hdr *) (ethhdr + 1);
66
67	if (os_memcmp(ethhdr->h_dest, hapd->own_addr, ETH_ALEN) != 0) {
68		wpa_printf(MSG_DEBUG, "RSN: pre-auth for foreign address "
69			   MACSTR, MAC2STR(ethhdr->h_dest));
70		return;
71	}
72
73	sta = ap_get_sta(hapd, ethhdr->h_source);
74	if (sta && (sta->flags & WLAN_STA_ASSOC)) {
75		wpa_printf(MSG_DEBUG, "RSN: pre-auth for already association "
76			   "STA " MACSTR, MAC2STR(sta->addr));
77		return;
78	}
79	if (!sta && hdr->type == IEEE802_1X_TYPE_EAPOL_START) {
80		sta = ap_sta_add(hapd, ethhdr->h_source);
81		if (sta == NULL)
82			return;
83		sta->flags = WLAN_STA_PREAUTH;
84
85		ieee802_1x_new_station(hapd, sta);
86		if (sta->eapol_sm == NULL) {
87			ap_free_sta(hapd, sta);
88			sta = NULL;
89		} else {
90			sta->eapol_sm->radius_identifier = -1;
91			sta->eapol_sm->portValid = TRUE;
92			sta->eapol_sm->flags |= EAPOL_SM_PREAUTH;
93		}
94	}
95	if (sta == NULL)
96		return;
97	sta->preauth_iface = piface;
98	ieee802_1x_receive(hapd, ethhdr->h_source, (u8 *) (ethhdr + 1),
99			   len - sizeof(*ethhdr));
100}
101
102
103static int rsn_preauth_iface_add(struct hostapd_data *hapd, const char *ifname)
104{
105	struct rsn_preauth_interface *piface;
106
107	wpa_printf(MSG_DEBUG, "RSN pre-auth interface '%s'", ifname);
108
109	piface = os_zalloc(sizeof(*piface));
110	if (piface == NULL)
111		return -1;
112	piface->hapd = hapd;
113
114	piface->ifname = os_strdup(ifname);
115	if (piface->ifname == NULL) {
116		goto fail1;
117	}
118
119	piface->l2 = l2_packet_init(piface->ifname, NULL, ETH_P_PREAUTH,
120				    rsn_preauth_receive, piface, 1);
121	if (piface->l2 == NULL) {
122		wpa_printf(MSG_ERROR, "Failed to open register layer 2 access "
123			   "to ETH_P_PREAUTH");
124		goto fail2;
125	}
126
127	piface->next = hapd->preauth_iface;
128	hapd->preauth_iface = piface;
129	return 0;
130
131fail2:
132	os_free(piface->ifname);
133fail1:
134	os_free(piface);
135	return -1;
136}
137
138
139void rsn_preauth_iface_deinit(struct hostapd_data *hapd)
140{
141	struct rsn_preauth_interface *piface, *prev;
142
143	piface = hapd->preauth_iface;
144	hapd->preauth_iface = NULL;
145	while (piface) {
146		prev = piface;
147		piface = piface->next;
148		l2_packet_deinit(prev->l2);
149		os_free(prev->ifname);
150		os_free(prev);
151	}
152}
153
154
155int rsn_preauth_iface_init(struct hostapd_data *hapd)
156{
157	char *tmp, *start, *end;
158
159	if (hapd->conf->rsn_preauth_interfaces == NULL)
160		return 0;
161
162	tmp = os_strdup(hapd->conf->rsn_preauth_interfaces);
163	if (tmp == NULL)
164		return -1;
165	start = tmp;
166	for (;;) {
167		while (*start == ' ')
168			start++;
169		if (*start == '\0')
170			break;
171		end = os_strchr(start, ' ');
172		if (end)
173			*end = '\0';
174
175		if (rsn_preauth_iface_add(hapd, start)) {
176			rsn_preauth_iface_deinit(hapd);
177			os_free(tmp);
178			return -1;
179		}
180
181		if (end)
182			start = end + 1;
183		else
184			break;
185	}
186	os_free(tmp);
187	return 0;
188}
189
190
191static void rsn_preauth_finished_cb(void *eloop_ctx, void *timeout_ctx)
192{
193	struct hostapd_data *hapd = eloop_ctx;
194	struct sta_info *sta = timeout_ctx;
195	wpa_printf(MSG_DEBUG, "RSN: Removing pre-authentication STA entry for "
196		   MACSTR, MAC2STR(sta->addr));
197	ap_free_sta(hapd, sta);
198}
199
200
201void rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta,
202			  int success)
203{
204	const u8 *key;
205	size_t len;
206	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
207		       HOSTAPD_LEVEL_INFO, "pre-authentication %s",
208		       success ? "succeeded" : "failed");
209
210	key = ieee802_1x_get_key(sta->eapol_sm, &len);
211	if (len > PMK_LEN)
212		len = PMK_LEN;
213	if (success && key) {
214		if (wpa_auth_pmksa_add_preauth(hapd->wpa_auth, key, len,
215					       sta->addr,
216					       dot11RSNAConfigPMKLifetime,
217					       sta->eapol_sm) == 0) {
218			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
219				       HOSTAPD_LEVEL_DEBUG,
220				       "added PMKSA cache entry (pre-auth)");
221		} else {
222			hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
223				       HOSTAPD_LEVEL_DEBUG,
224				       "failed to add PMKSA cache entry "
225				       "(pre-auth)");
226		}
227	}
228
229	/*
230	 * Finish STA entry removal from timeout in order to avoid freeing
231	 * STA data before the caller has finished processing.
232	 */
233	eloop_register_timeout(0, 0, rsn_preauth_finished_cb, hapd, sta);
234}
235
236
237void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta,
238		      u8 *buf, size_t len)
239{
240	struct rsn_preauth_interface *piface;
241	struct l2_ethhdr *ethhdr;
242
243	piface = hapd->preauth_iface;
244	while (piface) {
245		if (piface == sta->preauth_iface)
246			break;
247		piface = piface->next;
248	}
249
250	if (piface == NULL) {
251		wpa_printf(MSG_DEBUG, "RSN: Could not find pre-authentication "
252			   "interface for " MACSTR, MAC2STR(sta->addr));
253		return;
254	}
255
256	ethhdr = os_malloc(sizeof(*ethhdr) + len);
257	if (ethhdr == NULL)
258		return;
259
260	os_memcpy(ethhdr->h_dest, sta->addr, ETH_ALEN);
261	os_memcpy(ethhdr->h_source, hapd->own_addr, ETH_ALEN);
262	ethhdr->h_proto = host_to_be16(ETH_P_PREAUTH);
263	os_memcpy(ethhdr + 1, buf, len);
264
265	if (l2_packet_send(piface->l2, sta->addr, ETH_P_PREAUTH, (u8 *) ethhdr,
266			   sizeof(*ethhdr) + len) < 0) {
267		wpa_printf(MSG_ERROR, "Failed to send preauth packet using "
268			   "l2_packet_send\n");
269	}
270	os_free(ethhdr);
271}
272
273
274void rsn_preauth_free_station(struct hostapd_data *hapd, struct sta_info *sta)
275{
276	eloop_cancel_timeout(rsn_preauth_finished_cb, hapd, sta);
277}
278
279#endif /* CONFIG_RSN_PREAUTH */
280