xref: /freebsd/contrib/wpa/src/ap/preauth_auth.c (revision a90b9d0159070121c221b966469c3e36d912bf82)
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  
rsn_preauth_receive(void * ctx,const u8 * src_addr,const u8 * buf,size_t len)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 (!ether_addr_equal(ethhdr->h_dest, hapd->own_addr)) {
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), FRAME_ENCRYPTION_UNKNOWN);
94  }
95  
96  
rsn_preauth_iface_add(struct hostapd_data * hapd,const char * ifname)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  
rsn_preauth_iface_deinit(struct hostapd_data * hapd)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  
rsn_preauth_iface_init(struct hostapd_data * hapd)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  
rsn_preauth_finished_cb(void * eloop_ctx,void * timeout_ctx)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  
rsn_preauth_finished(struct hostapd_data * hapd,struct sta_info * sta,int success)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  
rsn_preauth_send(struct hostapd_data * hapd,struct sta_info * sta,u8 * buf,size_t len)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  
rsn_preauth_free_station(struct hostapd_data * hapd,struct sta_info * sta)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 */
274