]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - contrib/wpa/hostapd/preauth.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / contrib / wpa / hostapd / preauth.c
1 /*
2  * hostapd - Authenticator for IEEE 802.11i RSN pre-authentication
3  * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
4  *
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.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #ifdef CONFIG_RSN_PREAUTH
18
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"
28
29 #ifndef ETH_P_PREAUTH
30 #define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */
31 #endif /* ETH_P_PREAUTH */
32
33 static const int dot11RSNAConfigPMKLifetime = 43200;
34
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;
41 };
42
43
44 static void rsn_preauth_receive(void *ctx, const u8 *src_addr,
45                                 const u8 *buf, size_t len)
46 {
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;
52
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;
59         }
60
61         ethhdr = (struct l2_ethhdr *) buf;
62         hdr = (struct ieee802_1x_hdr *) (ethhdr + 1);
63
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;
68         }
69
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;
75         }
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;
81
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;
90                 }
91         }
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));
97 }
98
99
100 static int rsn_preauth_iface_add(struct hostapd_data *hapd, const char *ifname)
101 {
102         struct rsn_preauth_interface *piface;
103
104         wpa_printf(MSG_DEBUG, "RSN pre-auth interface '%s'", ifname);
105
106         piface = os_zalloc(sizeof(*piface));
107         if (piface == NULL)
108                 return -1;
109         piface->hapd = hapd;
110
111         piface->ifname = os_strdup(ifname);
112         if (piface->ifname == NULL) {
113                 goto fail1;
114         }
115
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;
122         }
123
124         piface->next = hapd->preauth_iface;
125         hapd->preauth_iface = piface;
126         return 0;
127
128 fail2:
129         os_free(piface->ifname);
130 fail1:
131         os_free(piface);
132         return -1;
133 }
134
135
136 void rsn_preauth_iface_deinit(struct hostapd_data *hapd)
137 {
138         struct rsn_preauth_interface *piface, *prev;
139
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);
148         }
149 }
150
151
152 int rsn_preauth_iface_init(struct hostapd_data *hapd)
153 {
154         char *tmp, *start, *end;
155
156         if (hapd->conf->rsn_preauth_interfaces == NULL)
157                 return 0;
158
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';
171
172                 if (rsn_preauth_iface_add(hapd, start)) {
173                         rsn_preauth_iface_deinit(hapd);
174                         return -1;
175                 }
176
177                 if (end)
178                         start = end + 1;
179                 else
180                         break;
181         }
182         os_free(tmp);
183         return 0;
184 }
185
186
187 static void rsn_preauth_finished_cb(void *eloop_ctx, void *timeout_ctx)
188 {
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);
194 }
195
196
197 void rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta,
198                           int success)
199 {
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");
205
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)");
222                 }
223         }
224
225         /*
226          * Finish STA entry removal from timeout in order to avoid freeing
227          * STA data before the caller has finished processing.
228          */
229         eloop_register_timeout(0, 0, rsn_preauth_finished_cb, hapd, sta);
230 }
231
232
233 void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta,
234                       u8 *buf, size_t len)
235 {
236         struct rsn_preauth_interface *piface;
237         struct l2_ethhdr *ethhdr;
238
239         piface = hapd->preauth_iface;
240         while (piface) {
241                 if (piface == sta->preauth_iface)
242                         break;
243                 piface = piface->next;
244         }
245
246         if (piface == NULL) {
247                 wpa_printf(MSG_DEBUG, "RSN: Could not find pre-authentication "
248                            "interface for " MACSTR, MAC2STR(sta->addr));
249                 return;
250         }
251
252         ethhdr = os_malloc(sizeof(*ethhdr) + len);
253         if (ethhdr == NULL)
254                 return;
255
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);
260
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");
265         }
266         os_free(ethhdr);
267 }
268
269
270 void rsn_preauth_free_station(struct hostapd_data *hapd, struct sta_info *sta)
271 {
272         eloop_cancel_timeout(rsn_preauth_finished_cb, hapd, sta);
273 }
274
275 #endif /* CONFIG_RSN_PREAUTH */