Branch data 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 : 0 : static void rsn_preauth_receive(void *ctx, const u8 *src_addr,
42 : : const u8 *buf, size_t len)
43 : : {
44 : 0 : struct rsn_preauth_interface *piface = ctx;
45 : 0 : struct hostapd_data *hapd = piface->hapd;
46 : : struct ieee802_1x_hdr *hdr;
47 : : struct sta_info *sta;
48 : : struct l2_ethhdr *ethhdr;
49 : :
50 : 0 : wpa_printf(MSG_DEBUG, "RSN: receive pre-auth packet "
51 : : "from interface '%s'", piface->ifname);
52 [ # # ]: 0 : 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 : 0 : ethhdr = (struct l2_ethhdr *) buf;
59 : 0 : hdr = (struct ieee802_1x_hdr *) (ethhdr + 1);
60 : :
61 [ # # ]: 0 : 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 : 0 : sta = ap_get_sta(hapd, ethhdr->h_source);
68 [ # # ][ # # ]: 0 : 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 [ # # ][ # # ]: 0 : if (!sta && hdr->type == IEEE802_1X_TYPE_EAPOL_START) {
74 : 0 : sta = ap_sta_add(hapd, ethhdr->h_source);
75 [ # # ]: 0 : if (sta == NULL)
76 : 0 : return;
77 : 0 : sta->flags = WLAN_STA_PREAUTH;
78 : :
79 : 0 : ieee802_1x_new_station(hapd, sta);
80 [ # # ]: 0 : if (sta->eapol_sm == NULL) {
81 : 0 : ap_free_sta(hapd, sta);
82 : 0 : sta = NULL;
83 : : } else {
84 : 0 : sta->eapol_sm->radius_identifier = -1;
85 : 0 : sta->eapol_sm->portValid = TRUE;
86 : 0 : sta->eapol_sm->flags |= EAPOL_SM_PREAUTH;
87 : : }
88 : : }
89 [ # # ]: 0 : if (sta == NULL)
90 : 0 : return;
91 : 0 : sta->preauth_iface = piface;
92 : 0 : ieee802_1x_receive(hapd, ethhdr->h_source, (u8 *) (ethhdr + 1),
93 : : len - sizeof(*ethhdr));
94 : : }
95 : :
96 : :
97 : 0 : static int rsn_preauth_iface_add(struct hostapd_data *hapd, const char *ifname)
98 : : {
99 : : struct rsn_preauth_interface *piface;
100 : :
101 : 0 : wpa_printf(MSG_DEBUG, "RSN pre-auth interface '%s'", ifname);
102 : :
103 : 0 : piface = os_zalloc(sizeof(*piface));
104 [ # # ]: 0 : if (piface == NULL)
105 : 0 : return -1;
106 : 0 : piface->hapd = hapd;
107 : :
108 : 0 : piface->ifname = os_strdup(ifname);
109 [ # # ]: 0 : if (piface->ifname == NULL) {
110 : 0 : goto fail1;
111 : : }
112 : :
113 : 0 : piface->l2 = l2_packet_init(piface->ifname, NULL, ETH_P_PREAUTH,
114 : : rsn_preauth_receive, piface, 1);
115 [ # # ]: 0 : 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 : 0 : piface->next = hapd->preauth_iface;
122 : 0 : hapd->preauth_iface = piface;
123 : 0 : 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 : 159 : void rsn_preauth_iface_deinit(struct hostapd_data *hapd)
134 : : {
135 : : struct rsn_preauth_interface *piface, *prev;
136 : :
137 : 159 : piface = hapd->preauth_iface;
138 : 159 : hapd->preauth_iface = NULL;
139 [ - + ]: 159 : while (piface) {
140 : 0 : prev = piface;
141 : 0 : piface = piface->next;
142 : 0 : l2_packet_deinit(prev->l2);
143 : 0 : os_free(prev->ifname);
144 : 0 : os_free(prev);
145 : : }
146 : 159 : }
147 : :
148 : :
149 : 115 : int rsn_preauth_iface_init(struct hostapd_data *hapd)
150 : : {
151 : : char *tmp, *start, *end;
152 : :
153 [ + - ]: 115 : if (hapd->conf->rsn_preauth_interfaces == NULL)
154 : 115 : return 0;
155 : :
156 : 0 : tmp = os_strdup(hapd->conf->rsn_preauth_interfaces);
157 [ # # ]: 0 : if (tmp == NULL)
158 : 0 : return -1;
159 : 0 : start = tmp;
160 : : for (;;) {
161 [ # # ]: 0 : while (*start == ' ')
162 : 0 : start++;
163 [ # # ]: 0 : if (*start == '\0')
164 : 0 : break;
165 : 0 : end = os_strchr(start, ' ');
166 [ # # ]: 0 : if (end)
167 : 0 : *end = '\0';
168 : :
169 [ # # ]: 0 : 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 [ # # ]: 0 : if (end)
176 : 0 : start = end + 1;
177 : : else
178 : 0 : break;
179 : 0 : }
180 : 0 : os_free(tmp);
181 : 115 : return 0;
182 : : }
183 : :
184 : :
185 : 0 : static void rsn_preauth_finished_cb(void *eloop_ctx, void *timeout_ctx)
186 : : {
187 : 0 : struct hostapd_data *hapd = eloop_ctx;
188 : 0 : struct sta_info *sta = timeout_ctx;
189 : 0 : wpa_printf(MSG_DEBUG, "RSN: Removing pre-authentication STA entry for "
190 : 0 : MACSTR, MAC2STR(sta->addr));
191 : 0 : ap_free_sta(hapd, sta);
192 : 0 : }
193 : :
194 : :
195 : 0 : 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 [ # # ]: 0 : hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
201 : : HOSTAPD_LEVEL_INFO, "pre-authentication %s",
202 : : success ? "succeeded" : "failed");
203 : :
204 : 0 : key = ieee802_1x_get_key(sta->eapol_sm, &len);
205 [ # # ]: 0 : if (len > PMK_LEN)
206 : 0 : len = PMK_LEN;
207 [ # # ][ # # ]: 0 : if (success && key) {
208 [ # # ]: 0 : if (wpa_auth_pmksa_add_preauth(hapd->wpa_auth, key, len,
209 : 0 : sta->addr,
210 : : dot11RSNAConfigPMKLifetime,
211 : : sta->eapol_sm) == 0) {
212 : 0 : 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 : 0 : eloop_register_timeout(0, 0, rsn_preauth_finished_cb, hapd, sta);
228 : 0 : }
229 : :
230 : :
231 : 0 : 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 : 0 : piface = hapd->preauth_iface;
238 [ # # ]: 0 : while (piface) {
239 [ # # ]: 0 : if (piface == sta->preauth_iface)
240 : 0 : break;
241 : 0 : piface = piface->next;
242 : : }
243 : :
244 [ # # ]: 0 : 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 : 0 : ethhdr = os_malloc(sizeof(*ethhdr) + len);
251 [ # # ]: 0 : if (ethhdr == NULL)
252 : 0 : return;
253 : :
254 : 0 : os_memcpy(ethhdr->h_dest, sta->addr, ETH_ALEN);
255 : 0 : os_memcpy(ethhdr->h_source, hapd->own_addr, ETH_ALEN);
256 : 0 : ethhdr->h_proto = host_to_be16(ETH_P_PREAUTH);
257 : 0 : os_memcpy(ethhdr + 1, buf, len);
258 : :
259 [ # # ]: 0 : 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 : 0 : os_free(ethhdr);
265 : : }
266 : :
267 : :
268 : 212 : void rsn_preauth_free_station(struct hostapd_data *hapd, struct sta_info *sta)
269 : : {
270 : 212 : eloop_cancel_timeout(rsn_preauth_finished_cb, hapd, sta);
271 : 212 : }
272 : :
273 : : #endif /* CONFIG_RSN_PREAUTH */
|