Merge branch 'vendor/GCC50'
[dragonfly.git] / contrib / hostapd / src / ap / preauth_auth.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 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 static void rsn_preauth_receive(void *ctx, const u8 *src_addr,
42                                 const u8 *buf, size_t len)
43 {
44         struct rsn_preauth_interface *piface = ctx;
45         struct hostapd_data *hapd = piface->hapd;
46         struct ieee802_1x_hdr *hdr;
47         struct sta_info *sta;
48         struct l2_ethhdr *ethhdr;
49
50         wpa_printf(MSG_DEBUG, "RSN: receive pre-auth packet "
51                    "from interface '%s'", piface->ifname);
52         if (len < sizeof(*ethhdr) + sizeof(*hdr)) {
53                 wpa_printf(MSG_DEBUG, "RSN: too short pre-auth packet "
54                            "(len=%lu)", (unsigned long) len);
55                 return;
56         }
57
58         ethhdr = (struct l2_ethhdr *) buf;
59         hdr = (struct ieee802_1x_hdr *) (ethhdr + 1);
60
61         if (os_memcmp(ethhdr->h_dest, hapd->own_addr, ETH_ALEN) != 0) {
62                 wpa_printf(MSG_DEBUG, "RSN: pre-auth for foreign address "
63                            MACSTR, MAC2STR(ethhdr->h_dest));
64                 return;
65         }
66
67         sta = ap_get_sta(hapd, ethhdr->h_source);
68         if (sta && (sta->flags & WLAN_STA_ASSOC)) {
69                 wpa_printf(MSG_DEBUG, "RSN: pre-auth for already association "
70                            "STA " MACSTR, MAC2STR(sta->addr));
71                 return;
72         }
73         if (!sta && hdr->type == IEEE802_1X_TYPE_EAPOL_START) {
74                 sta = ap_sta_add(hapd, ethhdr->h_source);
75                 if (sta == NULL)
76                         return;
77                 sta->flags = WLAN_STA_PREAUTH;
78
79                 ieee802_1x_new_station(hapd, sta);
80                 if (sta->eapol_sm == NULL) {
81                         ap_free_sta(hapd, sta);
82                         sta = NULL;
83                 } else {
84                         sta->eapol_sm->radius_identifier = -1;
85                         sta->eapol_sm->portValid = TRUE;
86                         sta->eapol_sm->flags |= EAPOL_SM_PREAUTH;
87                 }
88         }
89         if (sta == NULL)
90                 return;
91         sta->preauth_iface = piface;
92         ieee802_1x_receive(hapd, ethhdr->h_source, (u8 *) (ethhdr + 1),
93                            len - sizeof(*ethhdr));
94 }
95
96
97 static int rsn_preauth_iface_add(struct hostapd_data *hapd, const char *ifname)
98 {
99         struct rsn_preauth_interface *piface;
100
101         wpa_printf(MSG_DEBUG, "RSN pre-auth interface '%s'", ifname);
102
103         piface = os_zalloc(sizeof(*piface));
104         if (piface == NULL)
105                 return -1;
106         piface->hapd = hapd;
107
108         piface->ifname = os_strdup(ifname);
109         if (piface->ifname == NULL) {
110                 goto fail1;
111         }
112
113         piface->l2 = l2_packet_init(piface->ifname, NULL, ETH_P_PREAUTH,
114                                     rsn_preauth_receive, piface, 1);
115         if (piface->l2 == NULL) {
116                 wpa_printf(MSG_ERROR, "Failed to open register layer 2 access "
117                            "to ETH_P_PREAUTH");
118                 goto fail2;
119         }
120
121         piface->next = hapd->preauth_iface;
122         hapd->preauth_iface = piface;
123         return 0;
124
125 fail2:
126         os_free(piface->ifname);
127 fail1:
128         os_free(piface);
129         return -1;
130 }
131
132
133 void rsn_preauth_iface_deinit(struct hostapd_data *hapd)
134 {
135         struct rsn_preauth_interface *piface, *prev;
136
137         piface = hapd->preauth_iface;
138         hapd->preauth_iface = NULL;
139         while (piface) {
140                 prev = piface;
141                 piface = piface->next;
142                 l2_packet_deinit(prev->l2);
143                 os_free(prev->ifname);
144                 os_free(prev);
145         }
146 }
147
148
149 int rsn_preauth_iface_init(struct hostapd_data *hapd)
150 {
151         char *tmp, *start, *end;
152
153         if (hapd->conf->rsn_preauth_interfaces == NULL)
154                 return 0;
155
156         tmp = os_strdup(hapd->conf->rsn_preauth_interfaces);
157         if (tmp == NULL)
158                 return -1;
159         start = tmp;
160         for (;;) {
161                 while (*start == ' ')
162                         start++;
163                 if (*start == '\0')
164                         break;
165                 end = os_strchr(start, ' ');
166                 if (end)
167                         *end = '\0';
168
169                 if (rsn_preauth_iface_add(hapd, start)) {
170                         rsn_preauth_iface_deinit(hapd);
171                         os_free(tmp);
172                         return -1;
173                 }
174
175                 if (end)
176                         start = end + 1;
177                 else
178                         break;
179         }
180         os_free(tmp);
181         return 0;
182 }
183
184
185 static void rsn_preauth_finished_cb(void *eloop_ctx, void *timeout_ctx)
186 {
187         struct hostapd_data *hapd = eloop_ctx;
188         struct sta_info *sta = timeout_ctx;
189         wpa_printf(MSG_DEBUG, "RSN: Removing pre-authentication STA entry for "
190                    MACSTR, MAC2STR(sta->addr));
191         ap_free_sta(hapd, sta);
192 }
193
194
195 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         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
201                        HOSTAPD_LEVEL_INFO, "pre-authentication %s",
202                        success ? "succeeded" : "failed");
203
204         key = ieee802_1x_get_key(sta->eapol_sm, &len);
205         if (len > PMK_LEN)
206                 len = PMK_LEN;
207         if (success && key) {
208                 if (wpa_auth_pmksa_add_preauth(hapd->wpa_auth, key, len,
209                                                sta->addr,
210                                                dot11RSNAConfigPMKLifetime,
211                                                sta->eapol_sm) == 0) {
212                         hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_WPA,
213                                        HOSTAPD_LEVEL_DEBUG,
214                                        "added PMKSA cache entry (pre-auth)");
215                 } else {
216                         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         eloop_register_timeout(0, 0, rsn_preauth_finished_cb, hapd, sta);
228 }
229
230
231 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         piface = hapd->preauth_iface;
238         while (piface) {
239                 if (piface == sta->preauth_iface)
240                         break;
241                 piface = piface->next;
242         }
243
244         if (piface == NULL) {
245                 wpa_printf(MSG_DEBUG, "RSN: Could not find pre-authentication "
246                            "interface for " MACSTR, MAC2STR(sta->addr));
247                 return;
248         }
249
250         ethhdr = os_malloc(sizeof(*ethhdr) + len);
251         if (ethhdr == NULL)
252                 return;
253
254         os_memcpy(ethhdr->h_dest, sta->addr, ETH_ALEN);
255         os_memcpy(ethhdr->h_source, hapd->own_addr, ETH_ALEN);
256         ethhdr->h_proto = host_to_be16(ETH_P_PREAUTH);
257         os_memcpy(ethhdr + 1, buf, len);
258
259         if (l2_packet_send(piface->l2, sta->addr, ETH_P_PREAUTH, (u8 *) ethhdr,
260                            sizeof(*ethhdr) + len) < 0) {
261                 wpa_printf(MSG_ERROR, "Failed to send preauth packet using "
262                            "l2_packet_send\n");
263         }
264         os_free(ethhdr);
265 }
266
267
268 void rsn_preauth_free_station(struct hostapd_data *hapd, struct sta_info *sta)
269 {
270         eloop_cancel_timeout(rsn_preauth_finished_cb, hapd, sta);
271 }
272
273 #endif /* CONFIG_RSN_PREAUTH */