1 /*
2  * hostapd / Station table
3  * Copyright (c) 2002-2017, 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 #include "utils/common.h"
12 #include "utils/eloop.h"
13 #include "common/ieee802_11_defs.h"
14 #include "common/sae.h"
15 #include "crypto/crypto.h"
16 #include "hostapd.h"
17 #include "ieee802_1x.h"
18 #include "wpa_auth.h"
19 #include "ap_config.h"
20 #include "sta_info.h"
21 #include "esp_wps_i.h"
22 
23 static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx);
24 void hostapd_wps_eap_completed(struct hostapd_data *hapd);
25 
ap_for_each_sta(struct hostapd_data * hapd,int (* cb)(struct hostapd_data * hapd,struct sta_info * sta,void * ctx),void * ctx)26 int ap_for_each_sta(struct hostapd_data *hapd,
27 		    int (*cb)(struct hostapd_data *hapd, struct sta_info *sta,
28 			      void *ctx),
29 		    void *ctx)
30 {
31 	struct sta_info *sta;
32 
33 	for (sta = hapd->sta_list; sta; sta = sta->next) {
34 		if (cb(hapd, sta, ctx))
35 			return 1;
36 	}
37 
38 	return 0;
39 }
40 
41 
ap_get_sta(struct hostapd_data * hapd,const u8 * sta)42 struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta)
43 {
44 	struct sta_info *s;
45 
46 	s = hapd->sta_hash[STA_HASH(sta)];
47 	while (s != NULL && os_memcmp(s->addr, sta, 6) != 0)
48 		s = s->hnext;
49 	return s;
50 }
51 
52 
ap_sta_list_del(struct hostapd_data * hapd,struct sta_info * sta)53 static void ap_sta_list_del(struct hostapd_data *hapd, struct sta_info *sta)
54 {
55 	struct sta_info *tmp;
56 
57 	if (hapd->sta_list == sta) {
58 		hapd->sta_list = sta->next;
59 		return;
60 	}
61 
62 	tmp = hapd->sta_list;
63 	while (tmp != NULL && tmp->next != sta)
64 		tmp = tmp->next;
65 	if (tmp == NULL) {
66 		wpa_printf(MSG_DEBUG, "Could not remove STA " MACSTR " from "
67 			   "list.", MAC2STR(sta->addr));
68 	} else
69 		tmp->next = sta->next;
70 }
71 
72 
ap_sta_hash_add(struct hostapd_data * hapd,struct sta_info * sta)73 void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta)
74 {
75 	sta->hnext = hapd->sta_hash[STA_HASH(sta->addr)];
76 	hapd->sta_hash[STA_HASH(sta->addr)] = sta;
77 }
78 
79 
ap_sta_hash_del(struct hostapd_data * hapd,struct sta_info * sta)80 static void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta)
81 {
82 	struct sta_info *s;
83 
84 	s = hapd->sta_hash[STA_HASH(sta->addr)];
85 	if (s == NULL) return;
86 	if (os_memcmp(s->addr, sta->addr, 6) == 0) {
87 		hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext;
88 		return;
89 	}
90 
91 	while (s->hnext != NULL &&
92 	       os_memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0)
93 		s = s->hnext;
94 	if (s->hnext != NULL)
95 		s->hnext = s->hnext->hnext;
96 	else
97 		wpa_printf(MSG_DEBUG, "AP: could not remove STA " MACSTR
98 			   " from hash table", MAC2STR(sta->addr));
99 }
100 
ap_free_sta(struct hostapd_data * hapd,struct sta_info * sta)101 void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
102 {
103 	ap_sta_hash_del(hapd, sta);
104 	ap_sta_list_del(hapd, sta);
105 
106 	hapd->num_sta--;
107 
108 #ifdef CONFIG_SAE
109 	sae_clear_data(sta->sae);
110 	os_free(sta->sae);
111 	if (sta->lock) {
112 		os_semphr_give(sta->lock);
113 		os_mutex_delete(sta->lock);
114 		sta->lock = NULL;
115 	}
116 #endif /* CONFIG_SAE */
117 	wpa_auth_sta_deinit(sta->wpa_sm);
118 #ifdef CONFIG_WPS_REGISTRAR
119 	if (ap_sta_pending_delayed_1x_auth_fail_disconnect(hapd, sta))
120 		eloop_cancel_timeout(ap_sta_delayed_1x_auth_fail_cb, hapd, sta);
121 
122 	ieee802_1x_free_station(hapd, sta);
123 
124 	wpabuf_free(sta->wps_ie);
125 #endif
126 
127 	os_free(sta);
128 }
129 
130 
hostapd_free_stas(struct hostapd_data * hapd)131 void hostapd_free_stas(struct hostapd_data *hapd)
132 {
133 	struct sta_info *sta, *prev;
134 
135 	sta = hapd->sta_list;
136 
137 	while (sta) {
138 		prev = sta;
139 		sta = sta->next;
140 		wpa_printf(MSG_DEBUG, "Removing station " MACSTR,
141 			   MAC2STR(prev->addr));
142 		ap_free_sta(hapd, prev);
143 	}
144 }
145 
146 
ap_sta_add(struct hostapd_data * hapd,const u8 * addr)147 struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
148 {
149 	struct sta_info *sta;
150 
151 	sta = ap_get_sta(hapd, addr);
152 	if (sta)
153 		return sta;
154 
155 	wpa_printf(MSG_DEBUG, "  New STA");
156 	if (hapd->num_sta >= hapd->conf->max_num_sta) {
157 		/* FIX: might try to remove some old STAs first? */
158 		wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)",
159 			   hapd->num_sta, hapd->conf->max_num_sta);
160 		return NULL;
161 	}
162 
163 	sta = os_zalloc(sizeof(struct sta_info));
164 	if (sta == NULL) {
165 		wpa_printf(MSG_ERROR, "malloc failed");
166 		return NULL;
167 	}
168 
169 	/* initialize STA info data */
170 	os_memcpy(sta->addr, addr, ETH_ALEN);
171 	sta->next = hapd->sta_list;
172 	hapd->sta_list = sta;
173 	hapd->num_sta++;
174 	ap_sta_hash_add(hapd, sta);
175 #ifdef CONFIG_SAE
176 	sta->sae_commit_processing = false;
177 	sta->remove_pending = false;
178 	sta->lock = os_semphr_create(1, 1);
179 #endif /* CONFIG_SAE */
180 
181 	return sta;
182 }
183 
ap_sta_delayed_1x_auth_fail_cb(void * eloop_ctx,void * timeout_ctx)184 static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx)
185 {
186 	struct sta_info *sta = timeout_ctx;
187 	u16 reason;
188 
189 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
190 		"IEEE 802.1X: Scheduled disconnection of " MACSTR
191 		" after EAP-Failure", MAC2STR(sta->addr));
192 
193 	reason = WLAN_REASON_IEEE_802_1X_AUTH_FAILED;
194 	esp_wifi_ap_deauth_internal(sta->addr, reason);
195 }
196 
197 
ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data * hapd,struct sta_info * sta)198 void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
199 					    struct sta_info *sta)
200 {
201 	wpa_dbg(hapd->msg_ctx, MSG_DEBUG,
202 		"IEEE 802.1X: Force disconnection of " MACSTR
203 		" after EAP-Failure in 10 ms", MAC2STR(sta->addr));
204 
205 	/*
206 	 * Add a small sleep to increase likelihood of previously requested
207 	 * EAP-Failure TX getting out before this should the driver reorder
208 	 * operations.
209 	 */
210 	eloop_cancel_timeout(ap_sta_delayed_1x_auth_fail_cb, hapd, sta);
211 	eloop_register_timeout(0, 10000, ap_sta_delayed_1x_auth_fail_cb,
212 			       hapd, sta);
213 	if (wps_get_status() == WPS_STATUS_PENDING)
214 		wps_set_status(WPS_STATUS_SUCCESS);
215 }
216 
217 
ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data * hapd,struct sta_info * sta)218 int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
219 						   struct sta_info *sta)
220 {
221 	return eloop_is_timeout_registered(ap_sta_delayed_1x_auth_fail_cb,
222 					   hapd, sta);
223 }
224