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