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.
17 #ifdef CONFIG_RSN_PREAUTH
20 #include "l2_packet/l2_packet.h"
21 #include "ieee802_1x.h"
24 #include "wpa_common.h"
30 #define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
31 #endif /* ETH_P_PREAUTH */
33 static const int dot11RSNAConfigPMKLifetime
= 43200;
35 struct rsn_preauth_interface
{
36 struct rsn_preauth_interface
*next
;
37 struct hostapd_data
*hapd
;
38 struct l2_packet_data
*l2
;
44 static void rsn_preauth_receive(void *ctx
, const u8
*src_addr
,
45 const u8
*buf
, size_t len
)
47 struct rsn_preauth_interface
*piface
= ctx
;
48 struct hostapd_data
*hapd
= piface
->hapd
;
49 struct ieee802_1x_hdr
*hdr
;
51 struct l2_ethhdr
*ethhdr
;
53 wpa_printf(MSG_DEBUG
, "RSN: receive pre-auth packet "
54 "from interface '%s'", piface
->ifname
);
55 if (len
< sizeof(*ethhdr
) + sizeof(*hdr
)) {
56 wpa_printf(MSG_DEBUG
, "RSN: too short pre-auth packet "
57 "(len=%lu)", (unsigned long) len
);
61 ethhdr
= (struct l2_ethhdr
*) buf
;
62 hdr
= (struct ieee802_1x_hdr
*) (ethhdr
+ 1);
64 if (os_memcmp(ethhdr
->h_dest
, hapd
->own_addr
, ETH_ALEN
) != 0) {
65 wpa_printf(MSG_DEBUG
, "RSN: pre-auth for foreign address "
66 MACSTR
, MAC2STR(ethhdr
->h_dest
));
70 sta
= ap_get_sta(hapd
, ethhdr
->h_source
);
71 if (sta
&& (sta
->flags
& WLAN_STA_ASSOC
)) {
72 wpa_printf(MSG_DEBUG
, "RSN: pre-auth for already association "
73 "STA " MACSTR
, MAC2STR(sta
->addr
));
76 if (!sta
&& hdr
->type
== IEEE802_1X_TYPE_EAPOL_START
) {
77 sta
= ap_sta_add(hapd
, ethhdr
->h_source
);
80 sta
->flags
= WLAN_STA_PREAUTH
;
82 ieee802_1x_new_station(hapd
, sta
);
83 if (sta
->eapol_sm
== NULL
) {
84 ap_free_sta(hapd
, sta
);
87 sta
->eapol_sm
->radius_identifier
= -1;
88 sta
->eapol_sm
->portValid
= TRUE
;
89 sta
->eapol_sm
->flags
|= EAPOL_SM_PREAUTH
;
94 sta
->preauth_iface
= piface
;
95 ieee802_1x_receive(hapd
, ethhdr
->h_source
, (u8
*) (ethhdr
+ 1),
96 len
- sizeof(*ethhdr
));
100 static int rsn_preauth_iface_add(struct hostapd_data
*hapd
, const char *ifname
)
102 struct rsn_preauth_interface
*piface
;
104 wpa_printf(MSG_DEBUG
, "RSN pre-auth interface '%s'", ifname
);
106 piface
= os_zalloc(sizeof(*piface
));
111 piface
->ifname
= os_strdup(ifname
);
112 if (piface
->ifname
== NULL
) {
116 piface
->l2
= l2_packet_init(piface
->ifname
, NULL
, ETH_P_PREAUTH
,
117 rsn_preauth_receive
, piface
, 1);
118 if (piface
->l2
== NULL
) {
119 wpa_printf(MSG_ERROR
, "Failed to open register layer 2 access "
124 piface
->next
= hapd
->preauth_iface
;
125 hapd
->preauth_iface
= piface
;
129 os_free(piface
->ifname
);
136 void rsn_preauth_iface_deinit(struct hostapd_data
*hapd
)
138 struct rsn_preauth_interface
*piface
, *prev
;
140 piface
= hapd
->preauth_iface
;
141 hapd
->preauth_iface
= NULL
;
144 piface
= piface
->next
;
145 l2_packet_deinit(prev
->l2
);
146 os_free(prev
->ifname
);
152 int rsn_preauth_iface_init(struct hostapd_data
*hapd
)
154 char *tmp
, *start
, *end
;
156 if (hapd
->conf
->rsn_preauth_interfaces
== NULL
)
159 tmp
= os_strdup(hapd
->conf
->rsn_preauth_interfaces
);
164 while (*start
== ' ')
168 end
= os_strchr(start
, ' ');
172 if (rsn_preauth_iface_add(hapd
, start
)) {
173 rsn_preauth_iface_deinit(hapd
);
187 static void rsn_preauth_finished_cb(void *eloop_ctx
, void *timeout_ctx
)
189 struct hostapd_data
*hapd
= eloop_ctx
;
190 struct sta_info
*sta
= timeout_ctx
;
191 wpa_printf(MSG_DEBUG
, "RSN: Removing pre-authentication STA entry for "
192 MACSTR
, MAC2STR(sta
->addr
));
193 ap_free_sta(hapd
, sta
);
197 void rsn_preauth_finished(struct hostapd_data
*hapd
, struct sta_info
*sta
,
202 hostapd_logger(hapd
, sta
->addr
, HOSTAPD_MODULE_WPA
,
203 HOSTAPD_LEVEL_INFO
, "pre-authentication %s",
204 success
? "succeeded" : "failed");
206 key
= ieee802_1x_get_key(sta
->eapol_sm
, &len
);
209 if (success
&& key
) {
210 if (wpa_auth_pmksa_add_preauth(hapd
->wpa_auth
, key
, len
,
212 dot11RSNAConfigPMKLifetime
,
213 sta
->eapol_sm
) == 0) {
214 hostapd_logger(hapd
, sta
->addr
, HOSTAPD_MODULE_WPA
,
216 "added PMKSA cache entry (pre-auth)");
218 hostapd_logger(hapd
, sta
->addr
, HOSTAPD_MODULE_WPA
,
220 "failed to add PMKSA cache entry "
226 * Finish STA entry removal from timeout in order to avoid freeing
227 * STA data before the caller has finished processing.
229 eloop_register_timeout(0, 0, rsn_preauth_finished_cb
, hapd
, sta
);
233 void rsn_preauth_send(struct hostapd_data
*hapd
, struct sta_info
*sta
,
236 struct rsn_preauth_interface
*piface
;
237 struct l2_ethhdr
*ethhdr
;
239 piface
= hapd
->preauth_iface
;
241 if (piface
== sta
->preauth_iface
)
243 piface
= piface
->next
;
246 if (piface
== NULL
) {
247 wpa_printf(MSG_DEBUG
, "RSN: Could not find pre-authentication "
248 "interface for " MACSTR
, MAC2STR(sta
->addr
));
252 ethhdr
= os_malloc(sizeof(*ethhdr
) + len
);
256 os_memcpy(ethhdr
->h_dest
, sta
->addr
, ETH_ALEN
);
257 os_memcpy(ethhdr
->h_source
, hapd
->own_addr
, ETH_ALEN
);
258 ethhdr
->h_proto
= htons(ETH_P_PREAUTH
);
259 os_memcpy(ethhdr
+ 1, buf
, len
);
261 if (l2_packet_send(piface
->l2
, sta
->addr
, ETH_P_PREAUTH
, (u8
*) ethhdr
,
262 sizeof(*ethhdr
) + len
) < 0) {
263 wpa_printf(MSG_ERROR
, "Failed to send preauth packet using "
270 void rsn_preauth_free_station(struct hostapd_data
*hapd
, struct sta_info
*sta
)
272 eloop_cancel_timeout(rsn_preauth_finished_cb
, hapd
, sta
);
275 #endif /* CONFIG_RSN_PREAUTH */