Sync usage with man page.
[netbsd-mini2440.git] / dist / wpa / hostapd / preauth.c
blob36af4e31fe950f2b5c3617066123be09d91072fe
1 /*
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
10 * license.
12 * See README and COPYING for more details.
15 #include "includes.h"
17 #ifdef CONFIG_RSN_PREAUTH
19 #include "hostapd.h"
20 #include "l2_packet/l2_packet.h"
21 #include "ieee802_1x.h"
22 #include "eloop.h"
23 #include "sta_info.h"
24 #include "wpa_common.h"
25 #include "eapol_sm.h"
26 #include "wpa.h"
27 #include "preauth.h"
29 #ifndef ETH_P_PREAUTH
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;
39 char *ifname;
40 int ifindex;
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;
50 struct sta_info *sta;
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);
58 return;
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));
67 return;
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));
74 return;
76 if (!sta && hdr->type == IEEE802_1X_TYPE_EAPOL_START) {
77 sta = ap_sta_add(hapd, ethhdr->h_source);
78 if (sta == NULL)
79 return;
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);
85 sta = NULL;
86 } else {
87 sta->eapol_sm->radius_identifier = -1;
88 sta->eapol_sm->portValid = TRUE;
89 sta->eapol_sm->flags |= EAPOL_SM_PREAUTH;
92 if (sta == NULL)
93 return;
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));
107 if (piface == NULL)
108 return -1;
109 piface->hapd = hapd;
111 piface->ifname = os_strdup(ifname);
112 if (piface->ifname == NULL) {
113 goto fail1;
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 "
120 "to ETH_P_PREAUTH");
121 goto fail2;
124 piface->next = hapd->preauth_iface;
125 hapd->preauth_iface = piface;
126 return 0;
128 fail2:
129 os_free(piface->ifname);
130 fail1:
131 os_free(piface);
132 return -1;
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;
142 while (piface) {
143 prev = piface;
144 piface = piface->next;
145 l2_packet_deinit(prev->l2);
146 os_free(prev->ifname);
147 os_free(prev);
152 int rsn_preauth_iface_init(struct hostapd_data *hapd)
154 char *tmp, *start, *end;
156 if (hapd->conf->rsn_preauth_interfaces == NULL)
157 return 0;
159 tmp = os_strdup(hapd->conf->rsn_preauth_interfaces);
160 if (tmp == NULL)
161 return -1;
162 start = tmp;
163 for (;;) {
164 while (*start == ' ')
165 start++;
166 if (*start == '\0')
167 break;
168 end = os_strchr(start, ' ');
169 if (end)
170 *end = '\0';
172 if (rsn_preauth_iface_add(hapd, start)) {
173 rsn_preauth_iface_deinit(hapd);
174 return -1;
177 if (end)
178 start = end + 1;
179 else
180 break;
182 os_free(tmp);
183 return 0;
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,
198 int success)
200 const u8 *key;
201 size_t len;
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);
207 if (len > PMK_LEN)
208 len = PMK_LEN;
209 if (success && key) {
210 if (wpa_auth_pmksa_add_preauth(hapd->wpa_auth, key, len,
211 sta->addr,
212 dot11RSNAConfigPMKLifetime,
213 sta->eapol_sm) == 0) {
214 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
215 HOSTAPD_LEVEL_DEBUG,
216 "added PMKSA cache entry (pre-auth)");
217 } else {
218 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
219 HOSTAPD_LEVEL_DEBUG,
220 "failed to add PMKSA cache entry "
221 "(pre-auth)");
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,
234 u8 *buf, size_t len)
236 struct rsn_preauth_interface *piface;
237 struct l2_ethhdr *ethhdr;
239 piface = hapd->preauth_iface;
240 while (piface) {
241 if (piface == sta->preauth_iface)
242 break;
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));
249 return;
252 ethhdr = os_malloc(sizeof(*ethhdr) + len);
253 if (ethhdr == NULL)
254 return;
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 "
264 "l2_packet_send\n");
266 os_free(ethhdr);
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 */