2 * hostapd - Authenticator for IEEE 802.11i RSN pre-authentication
3 * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
15 #include "utils/includes.h"
17 #ifdef CONFIG_RSN_PREAUTH
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"
26 #include "ap_config.h"
27 #include "ieee802_1x.h"
30 #include "preauth_auth.h"
33 #define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
34 #endif /* ETH_P_PREAUTH */
36 static const int dot11RSNAConfigPMKLifetime
= 43200;
38 struct rsn_preauth_interface
{
39 struct rsn_preauth_interface
*next
;
40 struct hostapd_data
*hapd
;
41 struct l2_packet_data
*l2
;
47 static void rsn_preauth_receive(void *ctx
, const u8
*src_addr
,
48 const u8
*buf
, size_t len
)
50 struct rsn_preauth_interface
*piface
= ctx
;
51 struct hostapd_data
*hapd
= piface
->hapd
;
52 struct ieee802_1x_hdr
*hdr
;
54 struct l2_ethhdr
*ethhdr
;
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
);
64 ethhdr
= (struct l2_ethhdr
*) buf
;
65 hdr
= (struct ieee802_1x_hdr
*) (ethhdr
+ 1);
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
));
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
));
79 if (!sta
&& hdr
->type
== IEEE802_1X_TYPE_EAPOL_START
) {
80 sta
= ap_sta_add(hapd
, ethhdr
->h_source
);
83 sta
->flags
= WLAN_STA_PREAUTH
;
85 ieee802_1x_new_station(hapd
, sta
);
86 if (sta
->eapol_sm
== NULL
) {
87 ap_free_sta(hapd
, sta
);
90 sta
->eapol_sm
->radius_identifier
= -1;
91 sta
->eapol_sm
->portValid
= TRUE
;
92 sta
->eapol_sm
->flags
|= EAPOL_SM_PREAUTH
;
97 sta
->preauth_iface
= piface
;
98 ieee802_1x_receive(hapd
, ethhdr
->h_source
, (u8
*) (ethhdr
+ 1),
99 len
- sizeof(*ethhdr
));
103 static int rsn_preauth_iface_add(struct hostapd_data
*hapd
, const char *ifname
)
105 struct rsn_preauth_interface
*piface
;
107 wpa_printf(MSG_DEBUG
, "RSN pre-auth interface '%s'", ifname
);
109 piface
= os_zalloc(sizeof(*piface
));
114 piface
->ifname
= os_strdup(ifname
);
115 if (piface
->ifname
== NULL
) {
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 "
127 piface
->next
= hapd
->preauth_iface
;
128 hapd
->preauth_iface
= piface
;
132 os_free(piface
->ifname
);
139 void rsn_preauth_iface_deinit(struct hostapd_data
*hapd
)
141 struct rsn_preauth_interface
*piface
, *prev
;
143 piface
= hapd
->preauth_iface
;
144 hapd
->preauth_iface
= NULL
;
147 piface
= piface
->next
;
148 l2_packet_deinit(prev
->l2
);
149 os_free(prev
->ifname
);
155 int rsn_preauth_iface_init(struct hostapd_data
*hapd
)
157 char *tmp
, *start
, *end
;
159 if (hapd
->conf
->rsn_preauth_interfaces
== NULL
)
162 tmp
= os_strdup(hapd
->conf
->rsn_preauth_interfaces
);
167 while (*start
== ' ')
171 end
= os_strchr(start
, ' ');
175 if (rsn_preauth_iface_add(hapd
, start
)) {
176 rsn_preauth_iface_deinit(hapd
);
190 static void rsn_preauth_finished_cb(void *eloop_ctx
, void *timeout_ctx
)
192 struct hostapd_data
*hapd
= eloop_ctx
;
193 struct sta_info
*sta
= timeout_ctx
;
194 wpa_printf(MSG_DEBUG
, "RSN: Removing pre-authentication STA entry for "
195 MACSTR
, MAC2STR(sta
->addr
));
196 ap_free_sta(hapd
, sta
);
200 void rsn_preauth_finished(struct hostapd_data
*hapd
, struct sta_info
*sta
,
205 hostapd_logger(hapd
, sta
->addr
, HOSTAPD_MODULE_WPA
,
206 HOSTAPD_LEVEL_INFO
, "pre-authentication %s",
207 success
? "succeeded" : "failed");
209 key
= ieee802_1x_get_key(sta
->eapol_sm
, &len
);
212 if (success
&& key
) {
213 if (wpa_auth_pmksa_add_preauth(hapd
->wpa_auth
, key
, len
,
215 dot11RSNAConfigPMKLifetime
,
216 sta
->eapol_sm
) == 0) {
217 hostapd_logger(hapd
, sta
->addr
, HOSTAPD_MODULE_WPA
,
219 "added PMKSA cache entry (pre-auth)");
221 hostapd_logger(hapd
, sta
->addr
, HOSTAPD_MODULE_WPA
,
223 "failed to add PMKSA cache entry "
229 * Finish STA entry removal from timeout in order to avoid freeing
230 * STA data before the caller has finished processing.
232 eloop_register_timeout(0, 0, rsn_preauth_finished_cb
, hapd
, sta
);
236 void rsn_preauth_send(struct hostapd_data
*hapd
, struct sta_info
*sta
,
239 struct rsn_preauth_interface
*piface
;
240 struct l2_ethhdr
*ethhdr
;
242 piface
= hapd
->preauth_iface
;
244 if (piface
== sta
->preauth_iface
)
246 piface
= piface
->next
;
249 if (piface
== NULL
) {
250 wpa_printf(MSG_DEBUG
, "RSN: Could not find pre-authentication "
251 "interface for " MACSTR
, MAC2STR(sta
->addr
));
255 ethhdr
= os_malloc(sizeof(*ethhdr
) + len
);
259 os_memcpy(ethhdr
->h_dest
, sta
->addr
, ETH_ALEN
);
260 os_memcpy(ethhdr
->h_source
, hapd
->own_addr
, ETH_ALEN
);
261 ethhdr
->h_proto
= host_to_be16(ETH_P_PREAUTH
);
262 os_memcpy(ethhdr
+ 1, buf
, len
);
264 if (l2_packet_send(piface
->l2
, sta
->addr
, ETH_P_PREAUTH
, (u8
*) ethhdr
,
265 sizeof(*ethhdr
) + len
) < 0) {
266 wpa_printf(MSG_ERROR
, "Failed to send preauth packet using "
273 void rsn_preauth_free_station(struct hostapd_data
*hapd
, struct sta_info
*sta
)
275 eloop_cancel_timeout(rsn_preauth_finished_cb
, hapd
, sta
);
278 #endif /* CONFIG_RSN_PREAUTH */