blob: 28aca4660b9d71455d45e494c52fbf93fbd73521 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * hostapd / IEEE 802.11 Management
Dmitry Shmidt29333592017-01-09 12:27:11 -08003 * Copyright (c) 2002-2017, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "utils/includes.h"
10
11#ifndef CONFIG_NATIVE_WINDOWS
12
13#include "utils/common.h"
14#include "utils/eloop.h"
15#include "crypto/crypto.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080016#include "crypto/sha256.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070017#include "crypto/sha384.h"
18#include "crypto/sha512.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080019#include "crypto/random.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070020#include "common/ieee802_11_defs.h"
21#include "common/ieee802_11_common.h"
22#include "common/wpa_ctrl.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080023#include "common/sae.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070024#include "common/dpp.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080025#include "common/ocv.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070026#include "radius/radius.h"
27#include "radius/radius_client.h"
28#include "p2p/p2p.h"
29#include "wps/wps.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080030#include "fst/fst.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070031#include "hostapd.h"
32#include "beacon.h"
33#include "ieee802_11_auth.h"
34#include "sta_info.h"
35#include "ieee802_1x.h"
36#include "wpa_auth.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080037#include "pmksa_cache_auth.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070038#include "wmm.h"
39#include "ap_list.h"
40#include "accounting.h"
41#include "ap_config.h"
42#include "ap_mlme.h"
43#include "p2p_hostapd.h"
44#include "ap_drv_ops.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080045#include "wnm_ap.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080046#include "hw_features.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070047#include "ieee802_11.h"
Dmitry Shmidtf21452a2014-02-26 10:55:25 -080048#include "dfs.h"
Dmitry Shmidt57c2d392016-02-23 13:40:19 -080049#include "mbo_ap.h"
Dmitry Shmidt849734c2016-05-27 09:59:01 -070050#include "rrm.h"
Dmitry Shmidtaca489e2016-09-28 15:44:14 -070051#include "taxonomy.h"
Dmitry Shmidtebd93af2017-02-21 13:40:44 -080052#include "fils_hlp.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070053#include "dpp_hostapd.h"
54#include "gas_query_ap.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070055
56
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070057#ifdef CONFIG_FILS
58static struct wpabuf *
59prepare_auth_resp_fils(struct hostapd_data *hapd,
60 struct sta_info *sta, u16 *resp,
61 struct rsn_pmksa_cache_entry *pmksa,
62 struct wpabuf *erp_resp,
63 const u8 *msk, size_t msk_len,
64 int *is_pub);
65#endif /* CONFIG_FILS */
Hai Shalom021b0b52019-04-10 11:17:58 -070066static void handle_auth(struct hostapd_data *hapd,
67 const struct ieee80211_mgmt *mgmt, size_t len,
68 int rssi, int from_queue);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070069
Hai Shalom74f70d42019-02-11 14:42:39 -080070
71u8 * hostapd_eid_multi_ap(struct hostapd_data *hapd, u8 *eid)
72{
73 u8 multi_ap_val = 0;
74
75 if (!hapd->conf->multi_ap)
76 return eid;
77 if (hapd->conf->multi_ap & BACKHAUL_BSS)
78 multi_ap_val |= MULTI_AP_BACKHAUL_BSS;
79 if (hapd->conf->multi_ap & FRONTHAUL_BSS)
80 multi_ap_val |= MULTI_AP_FRONTHAUL_BSS;
81
82 return eid + add_multi_ap_ie(eid, 9, multi_ap_val);
83}
84
85
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070086u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
87{
88 u8 *pos = eid;
89 int i, num, count;
90
91 if (hapd->iface->current_rates == NULL)
92 return eid;
93
94 *pos++ = WLAN_EID_SUPP_RATES;
95 num = hapd->iface->num_rates;
96 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
97 num++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080098 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
99 num++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700100 if (num > 8) {
101 /* rest of the rates are encoded in Extended supported
102 * rates element */
103 num = 8;
104 }
105
106 *pos++ = num;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700107 for (i = 0, count = 0; i < hapd->iface->num_rates && count < num;
108 i++) {
109 count++;
110 *pos = hapd->iface->current_rates[i].rate / 5;
111 if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
112 *pos |= 0x80;
113 pos++;
114 }
115
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800116 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht && count < 8) {
117 count++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700118 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800119 }
120
121 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht && count < 8) {
122 count++;
123 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
124 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700125
126 return pos;
127}
128
129
130u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
131{
132 u8 *pos = eid;
133 int i, num, count;
134
135 if (hapd->iface->current_rates == NULL)
136 return eid;
137
138 num = hapd->iface->num_rates;
139 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
140 num++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800141 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
142 num++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700143 if (num <= 8)
144 return eid;
145 num -= 8;
146
147 *pos++ = WLAN_EID_EXT_SUPP_RATES;
148 *pos++ = num;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700149 for (i = 0, count = 0; i < hapd->iface->num_rates && count < num + 8;
150 i++) {
151 count++;
152 if (count <= 8)
153 continue; /* already in SuppRates IE */
154 *pos = hapd->iface->current_rates[i].rate / 5;
155 if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
156 *pos |= 0x80;
157 pos++;
158 }
159
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800160 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) {
161 count++;
162 if (count > 8)
163 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
164 }
165
166 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) {
167 count++;
168 if (count > 8)
169 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
170 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700171
172 return pos;
173}
174
175
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -0700176u16 hostapd_own_capab_info(struct hostapd_data *hapd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700177{
178 int capab = WLAN_CAPABILITY_ESS;
179 int privacy;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800180 int dfs;
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700181 int i;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800182
183 /* Check if any of configured channels require DFS */
184 dfs = hostapd_is_dfs_required(hapd->iface);
185 if (dfs < 0) {
186 wpa_printf(MSG_WARNING, "Failed to check if DFS is required; ret=%d",
187 dfs);
188 dfs = 0;
189 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700190
191 if (hapd->iface->num_sta_no_short_preamble == 0 &&
192 hapd->iconf->preamble == SHORT_PREAMBLE)
193 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
194
195 privacy = hapd->conf->ssid.wep.keys_set;
196
197 if (hapd->conf->ieee802_1x &&
198 (hapd->conf->default_wep_key_len ||
199 hapd->conf->individual_wep_key_len))
200 privacy = 1;
201
202 if (hapd->conf->wpa)
203 privacy = 1;
204
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800205#ifdef CONFIG_HS20
206 if (hapd->conf->osen)
207 privacy = 1;
208#endif /* CONFIG_HS20 */
209
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700210 if (privacy)
211 capab |= WLAN_CAPABILITY_PRIVACY;
212
213 if (hapd->iface->current_mode &&
214 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
215 hapd->iface->num_sta_no_short_slot_time == 0)
216 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
217
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800218 /*
219 * Currently, Spectrum Management capability bit is set when directly
220 * requested in configuration by spectrum_mgmt_required or when AP is
221 * running on DFS channel.
222 * TODO: Also consider driver support for TPC to set Spectrum Mgmt bit
223 */
224 if (hapd->iface->current_mode &&
225 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
226 (hapd->iconf->spectrum_mgmt_required || dfs))
227 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
228
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700229 for (i = 0; i < RRM_CAPABILITIES_IE_LEN; i++) {
230 if (hapd->conf->radio_measurements[i]) {
231 capab |= IEEE80211_CAP_RRM;
232 break;
233 }
234 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800235
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700236 return capab;
237}
238
239
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800240#ifndef CONFIG_NO_RC4
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700241static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
242 u16 auth_transaction, const u8 *challenge,
243 int iswep)
244{
245 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
246 HOSTAPD_LEVEL_DEBUG,
247 "authentication (shared key, transaction %d)",
248 auth_transaction);
249
250 if (auth_transaction == 1) {
251 if (!sta->challenge) {
252 /* Generate a pseudo-random challenge */
253 u8 key[8];
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800254
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700255 sta->challenge = os_zalloc(WLAN_AUTH_CHALLENGE_LEN);
256 if (sta->challenge == NULL)
257 return WLAN_STATUS_UNSPECIFIED_FAILURE;
258
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800259 if (os_get_random(key, sizeof(key)) < 0) {
260 os_free(sta->challenge);
261 sta->challenge = NULL;
262 return WLAN_STATUS_UNSPECIFIED_FAILURE;
263 }
264
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700265 rc4_skip(key, sizeof(key), 0,
266 sta->challenge, WLAN_AUTH_CHALLENGE_LEN);
267 }
268 return 0;
269 }
270
271 if (auth_transaction != 3)
272 return WLAN_STATUS_UNSPECIFIED_FAILURE;
273
274 /* Transaction 3 */
275 if (!iswep || !sta->challenge || !challenge ||
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700276 os_memcmp_const(sta->challenge, challenge,
277 WLAN_AUTH_CHALLENGE_LEN)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700278 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
279 HOSTAPD_LEVEL_INFO,
280 "shared key authentication - invalid "
281 "challenge-response");
282 return WLAN_STATUS_CHALLENGE_FAIL;
283 }
284
285 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
286 HOSTAPD_LEVEL_DEBUG,
287 "authentication OK (shared key)");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700288 sta->flags |= WLAN_STA_AUTH;
289 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700290 os_free(sta->challenge);
291 sta->challenge = NULL;
292
293 return 0;
294}
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800295#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700296
297
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800298static int send_auth_reply(struct hostapd_data *hapd,
299 const u8 *dst, const u8 *bssid,
300 u16 auth_alg, u16 auth_transaction, u16 resp,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700301 const u8 *ies, size_t ies_len, const char *dbg)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700302{
303 struct ieee80211_mgmt *reply;
304 u8 *buf;
305 size_t rlen;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800306 int reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700307
308 rlen = IEEE80211_HDRLEN + sizeof(reply->u.auth) + ies_len;
309 buf = os_zalloc(rlen);
310 if (buf == NULL)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800311 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700312
313 reply = (struct ieee80211_mgmt *) buf;
314 reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
315 WLAN_FC_STYPE_AUTH);
316 os_memcpy(reply->da, dst, ETH_ALEN);
317 os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
318 os_memcpy(reply->bssid, bssid, ETH_ALEN);
319
320 reply->u.auth.auth_alg = host_to_le16(auth_alg);
321 reply->u.auth.auth_transaction = host_to_le16(auth_transaction);
322 reply->u.auth.status_code = host_to_le16(resp);
323
324 if (ies && ies_len)
325 os_memcpy(reply->u.auth.variable, ies, ies_len);
326
327 wpa_printf(MSG_DEBUG, "authentication reply: STA=" MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700328 " auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu) (dbg=%s)",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700329 MAC2STR(dst), auth_alg, auth_transaction,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700330 resp, (unsigned long) ies_len, dbg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800331 if (hostapd_drv_send_mlme(hapd, reply, rlen, 0) < 0)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800332 wpa_printf(MSG_INFO, "send_auth_reply: send failed");
333 else
334 reply_res = WLAN_STATUS_SUCCESS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700335
336 os_free(buf);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800337
338 return reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700339}
340
341
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800342#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700343static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
344 u16 auth_transaction, u16 status,
345 const u8 *ies, size_t ies_len)
346{
347 struct hostapd_data *hapd = ctx;
348 struct sta_info *sta;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800349 int reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700350
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800351 reply_res = send_auth_reply(hapd, dst, bssid, WLAN_AUTH_FT,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700352 auth_transaction, status, ies, ies_len,
353 "auth-ft-finish");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700354
355 sta = ap_get_sta(hapd, dst);
356 if (sta == NULL)
357 return;
358
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800359 if (sta->added_unassoc && (reply_res != WLAN_STATUS_SUCCESS ||
360 status != WLAN_STATUS_SUCCESS)) {
361 hostapd_drv_sta_remove(hapd, sta->addr);
362 sta->added_unassoc = 0;
363 return;
364 }
365
366 if (status != WLAN_STATUS_SUCCESS)
367 return;
368
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700369 hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211,
370 HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)");
371 sta->flags |= WLAN_STA_AUTH;
372 mlme_authenticate_indication(hapd, sta);
373}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800374#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700375
376
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800377#ifdef CONFIG_SAE
378
Roshan Pius3a1667e2018-07-03 15:17:14 -0700379static void sae_set_state(struct sta_info *sta, enum sae_state state,
380 const char *reason)
381{
382 wpa_printf(MSG_DEBUG, "SAE: State %s -> %s for peer " MACSTR " (%s)",
383 sae_state_txt(sta->sae->state), sae_state_txt(state),
384 MAC2STR(sta->addr), reason);
385 sta->sae->state = state;
386}
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800387
388
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800389static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
390 struct sta_info *sta, int update)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800391{
392 struct wpabuf *buf;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700393 const char *password = NULL;
394 struct sae_password_entry *pw;
395 const char *rx_id = NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800396
Roshan Pius3a1667e2018-07-03 15:17:14 -0700397 if (sta->sae->tmp)
398 rx_id = sta->sae->tmp->pw_id;
399
400 for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
401 if (!is_broadcast_ether_addr(pw->peer_addr) &&
402 os_memcmp(pw->peer_addr, sta->addr, ETH_ALEN) != 0)
403 continue;
404 if ((rx_id && !pw->identifier) || (!rx_id && pw->identifier))
405 continue;
406 if (rx_id && pw->identifier &&
407 os_strcmp(rx_id, pw->identifier) != 0)
408 continue;
409 password = pw->password;
410 break;
411 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700412 if (!password)
413 password = hapd->conf->ssid.wpa_passphrase;
414 if (!password) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800415 wpa_printf(MSG_DEBUG, "SAE: No password available");
416 return NULL;
417 }
418
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800419 if (update &&
420 sae_prepare_commit(hapd->own_addr, sta->addr,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700421 (u8 *) password, os_strlen(password), rx_id,
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800422 sta->sae) < 0) {
423 wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
424 return NULL;
425 }
426
Hai Shalom021b0b52019-04-10 11:17:58 -0700427 if (pw && pw->vlan_id) {
428 if (!sta->sae->tmp) {
429 wpa_printf(MSG_INFO,
430 "SAE: No temporary data allocated - cannot store VLAN ID");
431 return NULL;
432 }
433 sta->sae->tmp->vlan_id = pw->vlan_id;
434 }
435
Roshan Pius3a1667e2018-07-03 15:17:14 -0700436 buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN +
437 (rx_id ? 3 + os_strlen(rx_id) : 0));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800438 if (buf == NULL)
439 return NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800440 sae_write_commit(sta->sae, buf, sta->sae->tmp ?
Roshan Pius3a1667e2018-07-03 15:17:14 -0700441 sta->sae->tmp->anti_clogging_token : NULL, rx_id);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800442
443 return buf;
444}
445
446
447static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
448 struct sta_info *sta)
449{
450 struct wpabuf *buf;
451
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800452 buf = wpabuf_alloc(SAE_CONFIRM_MAX_LEN);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800453 if (buf == NULL)
454 return NULL;
455
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800456 sae_write_confirm(sta->sae, buf);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800457
458 return buf;
459}
460
461
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800462static int auth_sae_send_commit(struct hostapd_data *hapd,
463 struct sta_info *sta,
464 const u8 *bssid, int update)
465{
466 struct wpabuf *data;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800467 int reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800468
469 data = auth_build_sae_commit(hapd, sta, update);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700470 if (!data && sta->sae->tmp && sta->sae->tmp->pw_id)
471 return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800472 if (data == NULL)
473 return WLAN_STATUS_UNSPECIFIED_FAILURE;
474
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800475 reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 1,
476 WLAN_STATUS_SUCCESS, wpabuf_head(data),
Roshan Pius3a1667e2018-07-03 15:17:14 -0700477 wpabuf_len(data), "sae-send-commit");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800478
479 wpabuf_free(data);
480
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800481 return reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800482}
483
484
485static int auth_sae_send_confirm(struct hostapd_data *hapd,
486 struct sta_info *sta,
487 const u8 *bssid)
488{
489 struct wpabuf *data;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800490 int reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800491
492 data = auth_build_sae_confirm(hapd, sta);
493 if (data == NULL)
494 return WLAN_STATUS_UNSPECIFIED_FAILURE;
495
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800496 reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 2,
497 WLAN_STATUS_SUCCESS, wpabuf_head(data),
Roshan Pius3a1667e2018-07-03 15:17:14 -0700498 wpabuf_len(data), "sae-send-confirm");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800499
500 wpabuf_free(data);
501
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800502 return reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800503}
504
505
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800506static int use_sae_anti_clogging(struct hostapd_data *hapd)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800507{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800508 struct sta_info *sta;
509 unsigned int open = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800510
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800511 if (hapd->conf->sae_anti_clogging_threshold == 0)
512 return 1;
513
514 for (sta = hapd->sta_list; sta; sta = sta->next) {
515 if (!sta->sae)
516 continue;
517 if (sta->sae->state != SAE_COMMITTED &&
518 sta->sae->state != SAE_CONFIRMED)
519 continue;
520 open++;
521 if (open >= hapd->conf->sae_anti_clogging_threshold)
522 return 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800523 }
524
Hai Shalom021b0b52019-04-10 11:17:58 -0700525 /* In addition to already existing open SAE sessions, check whether
526 * there are enough pending commit messages in the processing queue to
527 * potentially result in too many open sessions. */
528 if (open + dl_list_len(&hapd->sae_commit_queue) >=
529 hapd->conf->sae_anti_clogging_threshold)
530 return 1;
531
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800532 return 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800533}
534
535
Hai Shalom021b0b52019-04-10 11:17:58 -0700536static u8 sae_token_hash(struct hostapd_data *hapd, const u8 *addr)
537{
538 u8 hash[SHA256_MAC_LEN];
539
540 hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
541 addr, ETH_ALEN, hash);
542 return hash[0];
543}
544
545
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800546static int check_sae_token(struct hostapd_data *hapd, const u8 *addr,
547 const u8 *token, size_t token_len)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800548{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800549 u8 mac[SHA256_MAC_LEN];
Hai Shalom021b0b52019-04-10 11:17:58 -0700550 const u8 *addrs[2];
551 size_t len[2];
552 u16 token_idx;
553 u8 idx;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800554
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800555 if (token_len != SHA256_MAC_LEN)
556 return -1;
Hai Shalom021b0b52019-04-10 11:17:58 -0700557 idx = sae_token_hash(hapd, addr);
558 token_idx = hapd->sae_pending_token_idx[idx];
559 if (token_idx == 0 || token_idx != WPA_GET_BE16(token)) {
560 wpa_printf(MSG_DEBUG, "SAE: Invalid anti-clogging token from "
561 MACSTR " - token_idx 0x%04x, expected 0x%04x",
562 MAC2STR(addr), WPA_GET_BE16(token), token_idx);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800563 return -1;
Hai Shalom021b0b52019-04-10 11:17:58 -0700564 }
565
566 addrs[0] = addr;
567 len[0] = ETH_ALEN;
568 addrs[1] = token;
569 len[1] = 2;
570 if (hmac_sha256_vector(hapd->sae_token_key, sizeof(hapd->sae_token_key),
571 2, addrs, len, mac) < 0 ||
572 os_memcmp_const(token + 2, &mac[2], SHA256_MAC_LEN - 2) != 0)
573 return -1;
574
575 hapd->sae_pending_token_idx[idx] = 0; /* invalidate used token */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800576
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800577 return 0;
578}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800579
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800580
581static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800582 int group, const u8 *addr)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800583{
584 struct wpabuf *buf;
585 u8 *token;
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800586 struct os_reltime now;
Hai Shalom021b0b52019-04-10 11:17:58 -0700587 u8 idx[2];
588 const u8 *addrs[2];
589 size_t len[2];
590 u8 p_idx;
591 u16 token_idx;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800592
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800593 os_get_reltime(&now);
594 if (!os_reltime_initialized(&hapd->last_sae_token_key_update) ||
Hai Shalom021b0b52019-04-10 11:17:58 -0700595 os_reltime_expired(&now, &hapd->last_sae_token_key_update, 60) ||
596 hapd->sae_token_idx == 0xffff) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800597 if (random_get_bytes(hapd->sae_token_key,
598 sizeof(hapd->sae_token_key)) < 0)
599 return NULL;
600 wpa_hexdump(MSG_DEBUG, "SAE: Updated token key",
601 hapd->sae_token_key, sizeof(hapd->sae_token_key));
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800602 hapd->last_sae_token_key_update = now;
Hai Shalom021b0b52019-04-10 11:17:58 -0700603 hapd->sae_token_idx = 0;
604 os_memset(hapd->sae_pending_token_idx, 0,
605 sizeof(hapd->sae_pending_token_idx));
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800606 }
607
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800608 buf = wpabuf_alloc(sizeof(le16) + SHA256_MAC_LEN);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800609 if (buf == NULL)
610 return NULL;
611
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800612 wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
613
Hai Shalom021b0b52019-04-10 11:17:58 -0700614 p_idx = sae_token_hash(hapd, addr);
615 token_idx = hapd->sae_pending_token_idx[p_idx];
616 if (!token_idx) {
617 hapd->sae_token_idx++;
618 token_idx = hapd->sae_token_idx;
619 hapd->sae_pending_token_idx[p_idx] = token_idx;
620 }
621 WPA_PUT_BE16(idx, token_idx);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800622 token = wpabuf_put(buf, SHA256_MAC_LEN);
Hai Shalom021b0b52019-04-10 11:17:58 -0700623 addrs[0] = addr;
624 len[0] = ETH_ALEN;
625 addrs[1] = idx;
626 len[1] = sizeof(idx);
627 if (hmac_sha256_vector(hapd->sae_token_key, sizeof(hapd->sae_token_key),
628 2, addrs, len, token) < 0) {
629 wpabuf_free(buf);
630 return NULL;
631 }
632 WPA_PUT_BE16(token, token_idx);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800633
634 return buf;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800635}
636
637
Roshan Pius3a1667e2018-07-03 15:17:14 -0700638static int sae_check_big_sync(struct hostapd_data *hapd, struct sta_info *sta)
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800639{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700640 if (sta->sae->sync > hapd->conf->sae_sync) {
641 sae_set_state(sta, SAE_NOTHING, "Sync > dot11RSNASAESync");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800642 sta->sae->sync = 0;
643 return -1;
644 }
645 return 0;
646}
647
648
649static void auth_sae_retransmit_timer(void *eloop_ctx, void *eloop_data)
650{
651 struct hostapd_data *hapd = eloop_ctx;
652 struct sta_info *sta = eloop_data;
653 int ret;
654
Roshan Pius3a1667e2018-07-03 15:17:14 -0700655 if (sae_check_big_sync(hapd, sta))
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800656 return;
657 sta->sae->sync++;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700658 wpa_printf(MSG_DEBUG, "SAE: Auth SAE retransmit timer for " MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700659 " (sync=%d state=%s)",
660 MAC2STR(sta->addr), sta->sae->sync,
661 sae_state_txt(sta->sae->state));
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800662
663 switch (sta->sae->state) {
664 case SAE_COMMITTED:
665 ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800666 eloop_register_timeout(0,
667 hapd->dot11RSNASAERetransPeriod * 1000,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800668 auth_sae_retransmit_timer, hapd, sta);
669 break;
670 case SAE_CONFIRMED:
671 ret = auth_sae_send_confirm(hapd, sta, hapd->own_addr);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800672 eloop_register_timeout(0,
673 hapd->dot11RSNASAERetransPeriod * 1000,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800674 auth_sae_retransmit_timer, hapd, sta);
675 break;
676 default:
677 ret = -1;
678 break;
679 }
680
681 if (ret != WLAN_STATUS_SUCCESS)
682 wpa_printf(MSG_INFO, "SAE: Failed to retransmit: ret=%d", ret);
683}
684
685
686void sae_clear_retransmit_timer(struct hostapd_data *hapd, struct sta_info *sta)
687{
688 eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta);
689}
690
691
692static void sae_set_retransmit_timer(struct hostapd_data *hapd,
693 struct sta_info *sta)
694{
695 if (!(hapd->conf->mesh & MESH_ENABLED))
696 return;
697
698 eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800699 eloop_register_timeout(0, hapd->dot11RSNASAERetransPeriod * 1000,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800700 auth_sae_retransmit_timer, hapd, sta);
701}
702
703
Dmitry Shmidte4663042016-04-04 10:07:49 -0700704void sae_accept_sta(struct hostapd_data *hapd, struct sta_info *sta)
705{
Hai Shalom021b0b52019-04-10 11:17:58 -0700706#ifndef CONFIG_NO_VLAN
707 struct vlan_description vlan_desc;
708
709 if (sta->sae->tmp && sta->sae->tmp->vlan_id > 0) {
710 wpa_printf(MSG_DEBUG, "SAE: Assign STA " MACSTR
711 " to VLAN ID %d",
712 MAC2STR(sta->addr), sta->sae->tmp->vlan_id);
713
714 os_memset(&vlan_desc, 0, sizeof(vlan_desc));
715 vlan_desc.notempty = 1;
716 vlan_desc.untagged = sta->sae->tmp->vlan_id;
717 if (!hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) {
718 wpa_printf(MSG_INFO,
719 "Invalid VLAN ID %d in sae_password",
720 sta->sae->tmp->vlan_id);
721 return;
722 }
723
724 if (ap_sta_set_vlan(hapd, sta, &vlan_desc) < 0 ||
725 ap_sta_bind_vlan(hapd, sta) < 0) {
726 wpa_printf(MSG_INFO,
727 "Failed to assign VLAN ID %d from sae_password to "
728 MACSTR, sta->sae->tmp->vlan_id,
729 MAC2STR(sta->addr));
730 return;
731 }
732 }
733#endif /* CONFIG_NO_VLAN */
734
Dmitry Shmidte4663042016-04-04 10:07:49 -0700735 sta->flags |= WLAN_STA_AUTH;
736 sta->auth_alg = WLAN_AUTH_SAE;
737 mlme_authenticate_indication(hapd, sta);
738 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700739 sae_set_state(sta, SAE_ACCEPTED, "Accept Confirm");
Dmitry Shmidte4663042016-04-04 10:07:49 -0700740 wpa_auth_pmksa_add_sae(hapd->wpa_auth, sta->addr,
741 sta->sae->pmk, sta->sae->pmkid);
742}
743
744
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800745static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
Hai Shalom021b0b52019-04-10 11:17:58 -0700746 const u8 *bssid, u8 auth_transaction, int allow_reuse)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800747{
748 int ret;
749
750 if (auth_transaction != 1 && auth_transaction != 2)
751 return WLAN_STATUS_UNSPECIFIED_FAILURE;
752
Roshan Pius3a1667e2018-07-03 15:17:14 -0700753 wpa_printf(MSG_DEBUG, "SAE: Peer " MACSTR " state=%s auth_trans=%u",
754 MAC2STR(sta->addr), sae_state_txt(sta->sae->state),
755 auth_transaction);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800756 switch (sta->sae->state) {
757 case SAE_NOTHING:
758 if (auth_transaction == 1) {
Hai Shalom021b0b52019-04-10 11:17:58 -0700759 ret = auth_sae_send_commit(hapd, sta, bssid,
760 !allow_reuse);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800761 if (ret)
762 return ret;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700763 sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800764
765 if (sae_process_commit(sta->sae) < 0)
766 return WLAN_STATUS_UNSPECIFIED_FAILURE;
767
768 /*
769 * In mesh case, both Commit and Confirm can be sent
770 * immediately. In infrastructure BSS, only a single
771 * Authentication frame (Commit) is expected from the AP
772 * here and the second one (Confirm) will be sent once
773 * the STA has sent its second Authentication frame
774 * (Confirm).
775 */
776 if (hapd->conf->mesh & MESH_ENABLED) {
777 /*
778 * Send both Commit and Confirm immediately
779 * based on SAE finite state machine
780 * Nothing -> Confirm transition.
781 */
782 ret = auth_sae_send_confirm(hapd, sta, bssid);
783 if (ret)
784 return ret;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700785 sae_set_state(sta, SAE_CONFIRMED,
786 "Sent Confirm (mesh)");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800787 } else {
788 /*
789 * For infrastructure BSS, send only the Commit
790 * message now to get alternating sequence of
791 * Authentication frames between the AP and STA.
792 * Confirm will be sent in
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800793 * Committed -> Confirmed/Accepted transition
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800794 * when receiving Confirm from STA.
795 */
796 }
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800797 sta->sae->sync = 0;
798 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800799 } else {
800 hostapd_logger(hapd, sta->addr,
801 HOSTAPD_MODULE_IEEE80211,
802 HOSTAPD_LEVEL_DEBUG,
803 "SAE confirm before commit");
804 }
805 break;
806 case SAE_COMMITTED:
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800807 sae_clear_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800808 if (auth_transaction == 1) {
809 if (sae_process_commit(sta->sae) < 0)
810 return WLAN_STATUS_UNSPECIFIED_FAILURE;
811
812 ret = auth_sae_send_confirm(hapd, sta, bssid);
813 if (ret)
814 return ret;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700815 sae_set_state(sta, SAE_CONFIRMED, "Sent Confirm");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800816 sta->sae->sync = 0;
817 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800818 } else if (hapd->conf->mesh & MESH_ENABLED) {
819 /*
820 * In mesh case, follow SAE finite state machine and
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800821 * send Commit now, if sync count allows.
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800822 */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700823 if (sae_check_big_sync(hapd, sta))
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800824 return WLAN_STATUS_SUCCESS;
825 sta->sae->sync++;
826
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700827 ret = auth_sae_send_commit(hapd, sta, bssid, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800828 if (ret)
829 return ret;
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800830
831 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800832 } else {
833 /*
834 * For instructure BSS, send the postponed Confirm from
835 * Nothing -> Confirmed transition that was reduced to
836 * Nothing -> Committed above.
837 */
838 ret = auth_sae_send_confirm(hapd, sta, bssid);
839 if (ret)
840 return ret;
841
Roshan Pius3a1667e2018-07-03 15:17:14 -0700842 sae_set_state(sta, SAE_CONFIRMED, "Sent Confirm");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800843
844 /*
845 * Since this was triggered on Confirm RX, run another
846 * step to get to Accepted without waiting for
847 * additional events.
848 */
Hai Shalom021b0b52019-04-10 11:17:58 -0700849 return sae_sm_step(hapd, sta, bssid, auth_transaction,
850 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800851 }
852 break;
853 case SAE_CONFIRMED:
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800854 sae_clear_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800855 if (auth_transaction == 1) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700856 if (sae_check_big_sync(hapd, sta))
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800857 return WLAN_STATUS_SUCCESS;
858 sta->sae->sync++;
859
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800860 ret = auth_sae_send_commit(hapd, sta, bssid, 1);
861 if (ret)
862 return ret;
863
864 if (sae_process_commit(sta->sae) < 0)
865 return WLAN_STATUS_UNSPECIFIED_FAILURE;
866
867 ret = auth_sae_send_confirm(hapd, sta, bssid);
868 if (ret)
869 return ret;
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800870
871 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800872 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700873 sta->sae->send_confirm = 0xffff;
Dmitry Shmidte4663042016-04-04 10:07:49 -0700874 sae_accept_sta(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800875 }
876 break;
877 case SAE_ACCEPTED:
Roshan Pius3a1667e2018-07-03 15:17:14 -0700878 if (auth_transaction == 1 &&
879 (hapd->conf->mesh & MESH_ENABLED)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800880 wpa_printf(MSG_DEBUG, "SAE: remove the STA (" MACSTR
881 ") doing reauthentication",
882 MAC2STR(sta->addr));
883 ap_free_sta(hapd, sta);
Dmitry Shmidte4663042016-04-04 10:07:49 -0700884 wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700885 } else if (auth_transaction == 1) {
886 wpa_printf(MSG_DEBUG, "SAE: Start reauthentication");
887 ret = auth_sae_send_commit(hapd, sta, bssid, 1);
888 if (ret)
889 return ret;
890 sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
891
892 if (sae_process_commit(sta->sae) < 0)
893 return WLAN_STATUS_UNSPECIFIED_FAILURE;
894 sta->sae->sync = 0;
895 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800896 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700897 if (sae_check_big_sync(hapd, sta))
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800898 return WLAN_STATUS_SUCCESS;
899 sta->sae->sync++;
900
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800901 ret = auth_sae_send_confirm(hapd, sta, bssid);
902 sae_clear_temp_data(sta->sae);
903 if (ret)
904 return ret;
905 }
906 break;
907 default:
908 wpa_printf(MSG_ERROR, "SAE: invalid state %d",
909 sta->sae->state);
910 return WLAN_STATUS_UNSPECIFIED_FAILURE;
911 }
912 return WLAN_STATUS_SUCCESS;
913}
914
915
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700916static void sae_pick_next_group(struct hostapd_data *hapd, struct sta_info *sta)
917{
918 struct sae_data *sae = sta->sae;
919 int i, *groups = hapd->conf->sae_groups;
Hai Shalom021b0b52019-04-10 11:17:58 -0700920 int default_groups[] = { 19, 0 };
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700921
922 if (sae->state != SAE_COMMITTED)
923 return;
924
925 wpa_printf(MSG_DEBUG, "SAE: Previously selected group: %d", sae->group);
926
Hai Shalom021b0b52019-04-10 11:17:58 -0700927 if (!groups)
928 groups = default_groups;
929 for (i = 0; groups[i] > 0; i++) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700930 if (sae->group == groups[i])
931 break;
932 }
933
Hai Shalom021b0b52019-04-10 11:17:58 -0700934 if (groups[i] <= 0) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700935 wpa_printf(MSG_DEBUG,
936 "SAE: Previously selected group not found from the current configuration");
937 return;
938 }
939
940 for (;;) {
941 i++;
942 if (groups[i] <= 0) {
943 wpa_printf(MSG_DEBUG,
944 "SAE: No alternative group enabled");
945 return;
946 }
947
948 if (sae_set_group(sae, groups[i]) < 0)
949 continue;
950
951 break;
952 }
953 wpa_printf(MSG_DEBUG, "SAE: Selected new group: %d", groups[i]);
954}
955
956
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800957static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
958 const struct ieee80211_mgmt *mgmt, size_t len,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800959 u16 auth_transaction, u16 status_code)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800960{
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800961 int resp = WLAN_STATUS_SUCCESS;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800962 struct wpabuf *data = NULL;
Hai Shalom021b0b52019-04-10 11:17:58 -0700963 int *groups = hapd->conf->sae_groups;
964 int default_groups[] = { 19, 0 };
965 const u8 *pos, *end;
966
967 if (!groups)
968 groups = default_groups;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800969
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700970#ifdef CONFIG_TESTING_OPTIONS
971 if (hapd->conf->sae_reflection_attack && auth_transaction == 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700972 wpa_printf(MSG_DEBUG, "SAE: TESTING - reflection attack");
973 pos = mgmt->u.auth.variable;
974 end = ((const u8 *) mgmt) + len;
975 send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700976 auth_transaction, resp, pos, end - pos,
977 "auth-sae-reflection-attack");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700978 goto remove_sta;
979 }
980
981 if (hapd->conf->sae_commit_override && auth_transaction == 1) {
982 wpa_printf(MSG_DEBUG, "SAE: TESTING - commit override");
983 send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
984 auth_transaction, resp,
985 wpabuf_head(hapd->conf->sae_commit_override),
Roshan Pius3a1667e2018-07-03 15:17:14 -0700986 wpabuf_len(hapd->conf->sae_commit_override),
987 "sae-commit-override");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700988 goto remove_sta;
989 }
990#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800991 if (!sta->sae) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800992 if (auth_transaction != 1 ||
993 status_code != WLAN_STATUS_SUCCESS) {
994 resp = -1;
995 goto remove_sta;
996 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800997 sta->sae = os_zalloc(sizeof(*sta->sae));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800998 if (!sta->sae) {
999 resp = -1;
1000 goto remove_sta;
1001 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001002 sae_set_state(sta, SAE_NOTHING, "Init");
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001003 sta->sae->sync = 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001004 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001005
Dmitry Shmidte4663042016-04-04 10:07:49 -07001006 if (sta->mesh_sae_pmksa_caching) {
1007 wpa_printf(MSG_DEBUG,
1008 "SAE: Cancel use of mesh PMKSA caching because peer starts SAE authentication");
1009 wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
1010 sta->mesh_sae_pmksa_caching = 0;
1011 }
1012
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001013 if (auth_transaction == 1) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001014 const u8 *token = NULL;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001015 size_t token_len = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001016 int allow_reuse = 0;
1017
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001018 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1019 HOSTAPD_LEVEL_DEBUG,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001020 "start SAE authentication (RX commit, status=%u)",
1021 status_code);
1022
1023 if ((hapd->conf->mesh & MESH_ENABLED) &&
1024 status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
1025 sta->sae->tmp) {
1026 pos = mgmt->u.auth.variable;
1027 end = ((const u8 *) mgmt) + len;
1028 if (pos + sizeof(le16) > end) {
1029 wpa_printf(MSG_ERROR,
1030 "SAE: Too short anti-clogging token request");
1031 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1032 goto reply;
1033 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001034 resp = sae_group_allowed(sta->sae, groups,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001035 WPA_GET_LE16(pos));
1036 if (resp != WLAN_STATUS_SUCCESS) {
1037 wpa_printf(MSG_ERROR,
1038 "SAE: Invalid group in anti-clogging token request");
1039 goto reply;
1040 }
1041 pos += sizeof(le16);
1042
1043 wpabuf_free(sta->sae->tmp->anti_clogging_token);
1044 sta->sae->tmp->anti_clogging_token =
1045 wpabuf_alloc_copy(pos, end - pos);
1046 if (sta->sae->tmp->anti_clogging_token == NULL) {
1047 wpa_printf(MSG_ERROR,
1048 "SAE: Failed to alloc for anti-clogging token");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001049 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1050 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001051 }
1052
1053 /*
1054 * IEEE Std 802.11-2012, 11.3.8.6.4: If the Status code
1055 * is 76, a new Commit Message shall be constructed
1056 * with the Anti-Clogging Token from the received
1057 * Authentication frame, and the commit-scalar and
1058 * COMMIT-ELEMENT previously sent.
1059 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001060 resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 0);
1061 if (resp != WLAN_STATUS_SUCCESS) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001062 wpa_printf(MSG_ERROR,
1063 "SAE: Failed to send commit message");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001064 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001065 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001066 sae_set_state(sta, SAE_COMMITTED,
1067 "Sent Commit (anti-clogging token case in mesh)");
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001068 sta->sae->sync = 0;
1069 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001070 return;
1071 }
1072
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07001073 if ((hapd->conf->mesh & MESH_ENABLED) &&
1074 status_code ==
1075 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
1076 sta->sae->tmp) {
1077 wpa_printf(MSG_DEBUG,
1078 "SAE: Peer did not accept our SAE group");
1079 sae_pick_next_group(hapd, sta);
1080 goto remove_sta;
1081 }
1082
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001083 if (status_code != WLAN_STATUS_SUCCESS)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001084 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001085
Roshan Pius3a1667e2018-07-03 15:17:14 -07001086 if (!(hapd->conf->mesh & MESH_ENABLED) &&
1087 sta->sae->state == SAE_COMMITTED) {
1088 /* This is needed in the infrastructure BSS case to
1089 * address a sequence where a STA entry may remain in
1090 * hostapd across two attempts to do SAE authentication
1091 * by the same STA. The second attempt may end up trying
1092 * to use a different group and that would not be
1093 * allowed if we remain in Committed state with the
1094 * previously set parameters. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001095 pos = mgmt->u.auth.variable;
1096 end = ((const u8 *) mgmt) + len;
1097 if (end - pos >= (int) sizeof(le16) &&
1098 sae_group_allowed(sta->sae, groups,
1099 WPA_GET_LE16(pos)) ==
1100 WLAN_STATUS_SUCCESS) {
1101 /* Do not waste resources deriving the same PWE
1102 * again since the same group is reused. */
1103 sae_set_state(sta, SAE_NOTHING,
1104 "Allow previous PWE to be reused");
1105 allow_reuse = 1;
1106 } else {
1107 sae_set_state(sta, SAE_NOTHING,
1108 "Clear existing state to allow restart");
1109 sae_clear_data(sta->sae);
1110 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001111 }
1112
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001113 resp = sae_parse_commit(sta->sae, mgmt->u.auth.variable,
1114 ((const u8 *) mgmt) + len -
1115 mgmt->u.auth.variable, &token,
Hai Shalom021b0b52019-04-10 11:17:58 -07001116 &token_len, groups);
Dmitry Shmidt41712582015-06-29 11:02:15 -07001117 if (resp == SAE_SILENTLY_DISCARD) {
1118 wpa_printf(MSG_DEBUG,
1119 "SAE: Drop commit message from " MACSTR " due to reflection attack",
1120 MAC2STR(sta->addr));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001121 goto remove_sta;
Dmitry Shmidt41712582015-06-29 11:02:15 -07001122 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001123
1124 if (resp == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER) {
1125 wpa_msg(hapd->msg_ctx, MSG_INFO,
1126 WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER
1127 MACSTR, MAC2STR(sta->addr));
1128 sae_clear_retransmit_timer(hapd, sta);
1129 sae_set_state(sta, SAE_NOTHING,
1130 "Unknown Password Identifier");
1131 goto remove_sta;
1132 }
1133
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001134 if (token && check_sae_token(hapd, sta->addr, token, token_len)
1135 < 0) {
1136 wpa_printf(MSG_DEBUG, "SAE: Drop commit message with "
1137 "incorrect token from " MACSTR,
1138 MAC2STR(sta->addr));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001139 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1140 goto remove_sta;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001141 }
1142
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001143 if (resp != WLAN_STATUS_SUCCESS)
1144 goto reply;
1145
Hai Shalom021b0b52019-04-10 11:17:58 -07001146 if (!token && use_sae_anti_clogging(hapd) && !allow_reuse) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001147 wpa_printf(MSG_DEBUG,
1148 "SAE: Request anti-clogging token from "
1149 MACSTR, MAC2STR(sta->addr));
1150 data = auth_build_token_req(hapd, sta->sae->group,
1151 sta->addr);
1152 resp = WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ;
1153 if (hapd->conf->mesh & MESH_ENABLED)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001154 sae_set_state(sta, SAE_NOTHING,
1155 "Request anti-clogging token case in mesh");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001156 goto reply;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001157 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001158
Hai Shalom021b0b52019-04-10 11:17:58 -07001159 resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction,
1160 allow_reuse);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001161 } else if (auth_transaction == 2) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001162 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1163 HOSTAPD_LEVEL_DEBUG,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001164 "SAE authentication (RX confirm, status=%u)",
1165 status_code);
1166 if (status_code != WLAN_STATUS_SUCCESS)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001167 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001168 if (sta->sae->state >= SAE_CONFIRMED ||
1169 !(hapd->conf->mesh & MESH_ENABLED)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001170 const u8 *var;
1171 size_t var_len;
1172 u16 peer_send_confirm;
1173
1174 var = mgmt->u.auth.variable;
1175 var_len = ((u8 *) mgmt) + len - mgmt->u.auth.variable;
1176 if (var_len < 2) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001177 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001178 goto reply;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001179 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001180
1181 peer_send_confirm = WPA_GET_LE16(var);
1182
1183 if (sta->sae->state == SAE_ACCEPTED &&
1184 (peer_send_confirm <= sta->sae->rc ||
1185 peer_send_confirm == 0xffff)) {
1186 wpa_printf(MSG_DEBUG,
1187 "SAE: Silently ignore unexpected Confirm from peer "
1188 MACSTR
1189 " (peer-send-confirm=%u Rc=%u)",
1190 MAC2STR(sta->addr),
1191 peer_send_confirm, sta->sae->rc);
1192 return;
1193 }
1194
1195 if (sae_check_confirm(sta->sae, var, var_len) < 0) {
1196 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1197 goto reply;
1198 }
1199 sta->sae->rc = peer_send_confirm;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001200 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001201 resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction, 0);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001202 } else {
1203 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1204 HOSTAPD_LEVEL_DEBUG,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001205 "unexpected SAE authentication transaction %u (status=%u)",
1206 auth_transaction, status_code);
1207 if (status_code != WLAN_STATUS_SUCCESS)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001208 goto remove_sta;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001209 resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1210 }
1211
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001212reply:
1213 if (resp != WLAN_STATUS_SUCCESS) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001214 pos = mgmt->u.auth.variable;
1215 end = ((const u8 *) mgmt) + len;
1216
1217 /* Copy the Finite Cyclic Group field from the request if we
1218 * rejected it as unsupported group. */
1219 if (resp == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
1220 !data && end - pos >= 2)
1221 data = wpabuf_alloc_copy(pos, 2);
1222
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001223 send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
1224 auth_transaction, resp,
1225 data ? wpabuf_head(data) : (u8 *) "",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001226 data ? wpabuf_len(data) : 0, "auth-sae");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001227 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001228
1229remove_sta:
1230 if (sta->added_unassoc && (resp != WLAN_STATUS_SUCCESS ||
1231 status_code != WLAN_STATUS_SUCCESS)) {
1232 hostapd_drv_sta_remove(hapd, sta->addr);
1233 sta->added_unassoc = 0;
1234 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001235 wpabuf_free(data);
1236}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001237
1238
1239/**
1240 * auth_sae_init_committed - Send COMMIT and start SAE in committed state
1241 * @hapd: BSS data for the device initiating the authentication
1242 * @sta: the peer to which commit authentication frame is sent
1243 *
1244 * This function implements Init event handling (IEEE Std 802.11-2012,
1245 * 11.3.8.6.3) in which initial COMMIT message is sent. Prior to calling, the
1246 * sta->sae structure should be initialized appropriately via a call to
1247 * sae_prepare_commit().
1248 */
1249int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta)
1250{
1251 int ret;
1252
1253 if (!sta->sae || !sta->sae->tmp)
1254 return -1;
1255
1256 if (sta->sae->state != SAE_NOTHING)
1257 return -1;
1258
1259 ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
1260 if (ret)
1261 return -1;
1262
Roshan Pius3a1667e2018-07-03 15:17:14 -07001263 sae_set_state(sta, SAE_COMMITTED, "Init and sent commit");
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001264 sta->sae->sync = 0;
1265 sae_set_retransmit_timer(hapd, sta);
1266
1267 return 0;
1268}
1269
Hai Shalom021b0b52019-04-10 11:17:58 -07001270
1271void auth_sae_process_commit(void *eloop_ctx, void *user_ctx)
1272{
1273 struct hostapd_data *hapd = eloop_ctx;
1274 struct hostapd_sae_commit_queue *q;
1275 unsigned int queue_len;
1276
1277 q = dl_list_first(&hapd->sae_commit_queue,
1278 struct hostapd_sae_commit_queue, list);
1279 if (!q)
1280 return;
1281 wpa_printf(MSG_DEBUG,
1282 "SAE: Process next available message from queue");
1283 dl_list_del(&q->list);
1284 handle_auth(hapd, (const struct ieee80211_mgmt *) q->msg, q->len,
1285 q->rssi, 1);
1286 os_free(q);
1287
1288 if (eloop_is_timeout_registered(auth_sae_process_commit, hapd, NULL))
1289 return;
1290 queue_len = dl_list_len(&hapd->sae_commit_queue);
1291 eloop_register_timeout(0, queue_len * 10000, auth_sae_process_commit,
1292 hapd, NULL);
1293}
1294
1295
1296static void auth_sae_queue(struct hostapd_data *hapd,
1297 const struct ieee80211_mgmt *mgmt, size_t len,
1298 int rssi)
1299{
1300 struct hostapd_sae_commit_queue *q, *q2;
1301 unsigned int queue_len;
1302 const struct ieee80211_mgmt *mgmt2;
1303
1304 queue_len = dl_list_len(&hapd->sae_commit_queue);
1305 if (queue_len >= 15) {
1306 wpa_printf(MSG_DEBUG,
1307 "SAE: No more room in message queue - drop the new frame from "
1308 MACSTR, MAC2STR(mgmt->sa));
1309 return;
1310 }
1311
1312 wpa_printf(MSG_DEBUG, "SAE: Queue Authentication message from "
1313 MACSTR " for processing (queue_len %u)", MAC2STR(mgmt->sa),
1314 queue_len);
1315 q = os_zalloc(sizeof(*q) + len);
1316 if (!q)
1317 return;
1318 q->rssi = rssi;
1319 q->len = len;
1320 os_memcpy(q->msg, mgmt, len);
1321
1322 /* Check whether there is already a queued Authentication frame from the
1323 * same station with the same transaction number and if so, replace that
1324 * queue entry with the new one. This avoids issues with a peer that
1325 * sends multiple times (e.g., due to frequent SAE retries). There is no
1326 * point in us trying to process the old attempts after a new one has
1327 * obsoleted them. */
1328 dl_list_for_each(q2, &hapd->sae_commit_queue,
1329 struct hostapd_sae_commit_queue, list) {
1330 mgmt2 = (const struct ieee80211_mgmt *) q2->msg;
1331 if (os_memcmp(mgmt->sa, mgmt2->sa, ETH_ALEN) == 0 &&
1332 mgmt->u.auth.auth_transaction ==
1333 mgmt2->u.auth.auth_transaction) {
1334 wpa_printf(MSG_DEBUG,
1335 "SAE: Replace queued message from same STA with same transaction number");
1336 dl_list_add(&q2->list, &q->list);
1337 dl_list_del(&q2->list);
1338 os_free(q2);
1339 goto queued;
1340 }
1341 }
1342
1343 /* No pending identical entry, so add to the end of the queue */
1344 dl_list_add_tail(&hapd->sae_commit_queue, &q->list);
1345
1346queued:
1347 if (eloop_is_timeout_registered(auth_sae_process_commit, hapd, NULL))
1348 return;
1349 eloop_register_timeout(0, queue_len * 10000, auth_sae_process_commit,
1350 hapd, NULL);
1351}
1352
1353
1354static int auth_sae_queued_addr(struct hostapd_data *hapd, const u8 *addr)
1355{
1356 struct hostapd_sae_commit_queue *q;
1357 const struct ieee80211_mgmt *mgmt;
1358
1359 dl_list_for_each(q, &hapd->sae_commit_queue,
1360 struct hostapd_sae_commit_queue, list) {
1361 mgmt = (const struct ieee80211_mgmt *) q->msg;
1362 if (os_memcmp(addr, mgmt->sa, ETH_ALEN) == 0)
1363 return 1;
1364 }
1365
1366 return 0;
1367}
1368
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001369#endif /* CONFIG_SAE */
1370
1371
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001372static u16 wpa_res_to_status_code(int res)
1373{
1374 if (res == WPA_INVALID_GROUP)
1375 return WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1376 if (res == WPA_INVALID_PAIRWISE)
1377 return WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1378 if (res == WPA_INVALID_AKMP)
1379 return WLAN_STATUS_AKMP_NOT_VALID;
1380 if (res == WPA_ALLOC_FAIL)
1381 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1382#ifdef CONFIG_IEEE80211W
1383 if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
1384 return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
1385 if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001386 return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001387#endif /* CONFIG_IEEE80211W */
1388 if (res == WPA_INVALID_MDIE)
1389 return WLAN_STATUS_INVALID_MDIE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001390 if (res == WPA_INVALID_PMKID)
1391 return WLAN_STATUS_INVALID_PMKID;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001392 if (res != WPA_IE_OK)
1393 return WLAN_STATUS_INVALID_IE;
1394 return WLAN_STATUS_SUCCESS;
1395}
1396
1397
1398#ifdef CONFIG_FILS
1399
1400static void handle_auth_fils_finish(struct hostapd_data *hapd,
1401 struct sta_info *sta, u16 resp,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001402 struct wpabuf *data, int pub);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001403
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001404void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
1405 const u8 *pos, size_t len, u16 auth_alg,
1406 u16 auth_transaction, u16 status_code,
1407 void (*cb)(struct hostapd_data *hapd,
1408 struct sta_info *sta, u16 resp,
1409 struct wpabuf *data, int pub))
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001410{
1411 u16 resp = WLAN_STATUS_SUCCESS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001412 const u8 *end;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001413 struct ieee802_11_elems elems;
1414 int res;
1415 struct wpa_ie_data rsn;
1416 struct rsn_pmksa_cache_entry *pmksa = NULL;
1417
1418 if (auth_transaction != 1 || status_code != WLAN_STATUS_SUCCESS)
1419 return;
1420
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001421 end = pos + len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001422
1423 wpa_hexdump(MSG_DEBUG, "FILS: Authentication frame fields",
1424 pos, end - pos);
1425
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001426 /* TODO: FILS PK */
1427#ifdef CONFIG_FILS_SK_PFS
1428 if (auth_alg == WLAN_AUTH_FILS_SK_PFS) {
1429 u16 group;
1430 struct wpabuf *pub;
1431 size_t elem_len;
1432
1433 /* Using FILS PFS */
1434
1435 /* Finite Cyclic Group */
1436 if (end - pos < 2) {
1437 wpa_printf(MSG_DEBUG,
1438 "FILS: No room for Finite Cyclic Group");
1439 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1440 goto fail;
1441 }
1442 group = WPA_GET_LE16(pos);
1443 pos += 2;
1444 if (group != hapd->conf->fils_dh_group) {
1445 wpa_printf(MSG_DEBUG,
1446 "FILS: Unsupported Finite Cyclic Group: %u (expected %u)",
1447 group, hapd->conf->fils_dh_group);
1448 resp = WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1449 goto fail;
1450 }
1451
1452 crypto_ecdh_deinit(sta->fils_ecdh);
1453 sta->fils_ecdh = crypto_ecdh_init(group);
1454 if (!sta->fils_ecdh) {
1455 wpa_printf(MSG_INFO,
1456 "FILS: Could not initialize ECDH with group %d",
1457 group);
1458 resp = WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1459 goto fail;
1460 }
1461
1462 pub = crypto_ecdh_get_pubkey(sta->fils_ecdh, 1);
1463 if (!pub) {
1464 wpa_printf(MSG_DEBUG,
1465 "FILS: Failed to derive ECDH public key");
1466 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1467 goto fail;
1468 }
1469 elem_len = wpabuf_len(pub);
1470 wpabuf_free(pub);
1471
1472 /* Element */
1473 if ((size_t) (end - pos) < elem_len) {
1474 wpa_printf(MSG_DEBUG, "FILS: No room for Element");
1475 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1476 goto fail;
1477 }
1478
1479 wpabuf_free(sta->fils_g_sta);
1480 sta->fils_g_sta = wpabuf_alloc_copy(pos, elem_len);
1481 wpabuf_clear_free(sta->fils_dh_ss);
1482 sta->fils_dh_ss = crypto_ecdh_set_peerkey(sta->fils_ecdh, 1,
1483 pos, elem_len);
1484 if (!sta->fils_dh_ss) {
1485 wpa_printf(MSG_DEBUG, "FILS: ECDH operation failed");
1486 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1487 goto fail;
1488 }
1489 wpa_hexdump_buf_key(MSG_DEBUG, "FILS: DH_SS", sta->fils_dh_ss);
1490 pos += elem_len;
1491 } else {
1492 crypto_ecdh_deinit(sta->fils_ecdh);
1493 sta->fils_ecdh = NULL;
1494 wpabuf_clear_free(sta->fils_dh_ss);
1495 sta->fils_dh_ss = NULL;
1496 }
1497#endif /* CONFIG_FILS_SK_PFS */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001498
1499 wpa_hexdump(MSG_DEBUG, "FILS: Remaining IEs", pos, end - pos);
1500 if (ieee802_11_parse_elems(pos, end - pos, &elems, 1) == ParseFailed) {
1501 wpa_printf(MSG_DEBUG, "FILS: Could not parse elements");
1502 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1503 goto fail;
1504 }
1505
1506 /* RSNE */
1507 wpa_hexdump(MSG_DEBUG, "FILS: RSN element",
1508 elems.rsn_ie, elems.rsn_ie_len);
1509 if (!elems.rsn_ie ||
1510 wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
1511 &rsn) < 0) {
1512 wpa_printf(MSG_DEBUG, "FILS: No valid RSN element");
1513 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1514 goto fail;
1515 }
1516
1517 if (!sta->wpa_sm)
1518 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr,
1519 NULL);
1520 if (!sta->wpa_sm) {
1521 wpa_printf(MSG_DEBUG,
1522 "FILS: Failed to initialize RSN state machine");
1523 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1524 goto fail;
1525 }
1526
1527 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
Hai Shalom021b0b52019-04-10 11:17:58 -07001528 hapd->iface->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001529 elems.rsn_ie - 2, elems.rsn_ie_len + 2,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001530 elems.mdie, elems.mdie_len, NULL, 0);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001531 resp = wpa_res_to_status_code(res);
1532 if (resp != WLAN_STATUS_SUCCESS)
1533 goto fail;
1534
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001535 if (!elems.fils_nonce) {
1536 wpa_printf(MSG_DEBUG, "FILS: No FILS Nonce field");
1537 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1538 goto fail;
1539 }
1540 wpa_hexdump(MSG_DEBUG, "FILS: SNonce", elems.fils_nonce,
1541 FILS_NONCE_LEN);
1542 os_memcpy(sta->fils_snonce, elems.fils_nonce, FILS_NONCE_LEN);
1543
1544 /* PMKID List */
1545 if (rsn.pmkid && rsn.num_pmkid > 0) {
1546 u8 num;
1547 const u8 *pmkid;
1548
1549 wpa_hexdump(MSG_DEBUG, "FILS: PMKID List",
1550 rsn.pmkid, rsn.num_pmkid * PMKID_LEN);
1551
1552 pmkid = rsn.pmkid;
1553 num = rsn.num_pmkid;
1554 while (num) {
1555 wpa_hexdump(MSG_DEBUG, "FILS: PMKID", pmkid, PMKID_LEN);
1556 pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr,
1557 pmkid);
1558 if (pmksa)
1559 break;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001560 pmksa = wpa_auth_pmksa_get_fils_cache_id(hapd->wpa_auth,
1561 sta->addr,
1562 pmkid);
1563 if (pmksa)
1564 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001565 pmkid += PMKID_LEN;
1566 num--;
1567 }
1568 }
1569 if (pmksa && wpa_auth_sta_key_mgmt(sta->wpa_sm) != pmksa->akmp) {
1570 wpa_printf(MSG_DEBUG,
1571 "FILS: Matching PMKSA cache entry has different AKMP (0x%x != 0x%x) - ignore",
1572 wpa_auth_sta_key_mgmt(sta->wpa_sm), pmksa->akmp);
1573 pmksa = NULL;
1574 }
1575 if (pmksa)
1576 wpa_printf(MSG_DEBUG, "FILS: Found matching PMKSA cache entry");
1577
1578 /* FILS Session */
1579 if (!elems.fils_session) {
1580 wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
1581 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1582 goto fail;
1583 }
1584 wpa_hexdump(MSG_DEBUG, "FILS: FILS Session", elems.fils_session,
1585 FILS_SESSION_LEN);
1586 os_memcpy(sta->fils_session, elems.fils_session, FILS_SESSION_LEN);
1587
1588 /* FILS Wrapped Data */
1589 if (elems.fils_wrapped_data) {
1590 wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data",
1591 elems.fils_wrapped_data,
1592 elems.fils_wrapped_data_len);
1593 if (!pmksa) {
1594#ifndef CONFIG_NO_RADIUS
1595 if (!sta->eapol_sm) {
1596 sta->eapol_sm =
1597 ieee802_1x_alloc_eapol_sm(hapd, sta);
1598 }
1599 wpa_printf(MSG_DEBUG,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001600 "FILS: Forward EAP-Initiate/Re-auth to authentication server");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001601 ieee802_1x_encapsulate_radius(
1602 hapd, sta, elems.fils_wrapped_data,
1603 elems.fils_wrapped_data_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001604 sta->fils_pending_cb = cb;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001605 wpa_printf(MSG_DEBUG,
1606 "FILS: Will send Authentication frame once the response from authentication server is available");
1607 sta->flags |= WLAN_STA_PENDING_FILS_ERP;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001608 /* Calculate pending PMKID here so that we do not need
1609 * to maintain a copy of the EAP-Initiate/Reauth
1610 * message. */
1611 if (fils_pmkid_erp(wpa_auth_sta_key_mgmt(sta->wpa_sm),
1612 elems.fils_wrapped_data,
1613 elems.fils_wrapped_data_len,
1614 sta->fils_erp_pmkid) == 0)
1615 sta->fils_erp_pmkid_set = 1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001616 return;
1617#else /* CONFIG_NO_RADIUS */
1618 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1619 goto fail;
1620#endif /* CONFIG_NO_RADIUS */
1621 }
1622 }
1623
1624fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001625 if (cb) {
1626 struct wpabuf *data;
1627 int pub = 0;
1628
1629 data = prepare_auth_resp_fils(hapd, sta, &resp, pmksa, NULL,
1630 NULL, 0, &pub);
1631 if (!data) {
1632 wpa_printf(MSG_DEBUG,
1633 "%s: prepare_auth_resp_fils() returned failure",
1634 __func__);
1635 }
1636
1637 cb(hapd, sta, resp, data, pub);
1638 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001639}
1640
1641
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001642static struct wpabuf *
1643prepare_auth_resp_fils(struct hostapd_data *hapd,
1644 struct sta_info *sta, u16 *resp,
1645 struct rsn_pmksa_cache_entry *pmksa,
1646 struct wpabuf *erp_resp,
1647 const u8 *msk, size_t msk_len,
1648 int *is_pub)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001649{
1650 u8 fils_nonce[FILS_NONCE_LEN];
1651 size_t ielen;
1652 struct wpabuf *data = NULL;
1653 const u8 *ie;
1654 u8 *ie_buf = NULL;
1655 const u8 *pmk = NULL;
1656 size_t pmk_len = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08001657 u8 pmk_buf[PMK_LEN_MAX];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001658 struct wpabuf *pub = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001659
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001660 if (*resp != WLAN_STATUS_SUCCESS)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001661 goto fail;
1662
1663 ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen);
1664 if (!ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001665 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001666 goto fail;
1667 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001668
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001669 if (pmksa) {
1670 /* Add PMKID of the selected PMKSA into RSNE */
1671 ie_buf = os_malloc(ielen + 2 + 2 + PMKID_LEN);
1672 if (!ie_buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001673 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001674 goto fail;
1675 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001676
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001677 os_memcpy(ie_buf, ie, ielen);
1678 if (wpa_insert_pmkid(ie_buf, &ielen, pmksa->pmkid) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001679 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001680 goto fail;
1681 }
1682 ie = ie_buf;
1683 }
1684
1685 if (random_get_bytes(fils_nonce, FILS_NONCE_LEN) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001686 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001687 goto fail;
1688 }
1689 wpa_hexdump(MSG_DEBUG, "RSN: Generated FILS Nonce",
1690 fils_nonce, FILS_NONCE_LEN);
1691
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001692#ifdef CONFIG_FILS_SK_PFS
1693 if (sta->fils_dh_ss && sta->fils_ecdh) {
1694 pub = crypto_ecdh_get_pubkey(sta->fils_ecdh, 1);
1695 if (!pub) {
1696 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1697 goto fail;
1698 }
1699 }
1700#endif /* CONFIG_FILS_SK_PFS */
1701
1702 data = wpabuf_alloc(1000 + ielen + (pub ? wpabuf_len(pub) : 0));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001703 if (!data) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001704 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001705 goto fail;
1706 }
1707
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001708 /* TODO: FILS PK */
1709#ifdef CONFIG_FILS_SK_PFS
1710 if (pub) {
1711 /* Finite Cyclic Group */
1712 wpabuf_put_le16(data, hapd->conf->fils_dh_group);
1713
1714 /* Element */
1715 wpabuf_put_buf(data, pub);
1716 }
1717#endif /* CONFIG_FILS_SK_PFS */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001718
1719 /* RSNE */
1720 wpabuf_put_data(data, ie, ielen);
1721
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001722 /* MDE when using FILS+FT (already included in ie,ielen with RSNE) */
1723
1724#ifdef CONFIG_IEEE80211R_AP
1725 if (wpa_key_mgmt_ft(wpa_auth_sta_key_mgmt(sta->wpa_sm))) {
1726 /* FTE[R1KH-ID,R0KH-ID] when using FILS+FT */
1727 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001728 int use_sha384 = wpa_key_mgmt_sha384(
1729 wpa_auth_sta_key_mgmt(sta->wpa_sm));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001730
Roshan Pius3a1667e2018-07-03 15:17:14 -07001731 res = wpa_auth_write_fte(hapd->wpa_auth, use_sha384,
1732 wpabuf_put(data, 0),
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001733 wpabuf_tailroom(data));
1734 if (res < 0) {
1735 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1736 goto fail;
1737 }
1738 wpabuf_put(data, res);
1739 }
1740#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001741
1742 /* FILS Nonce */
1743 wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
1744 wpabuf_put_u8(data, 1 + FILS_NONCE_LEN); /* Length */
1745 /* Element ID Extension */
1746 wpabuf_put_u8(data, WLAN_EID_EXT_FILS_NONCE);
1747 wpabuf_put_data(data, fils_nonce, FILS_NONCE_LEN);
1748
1749 /* FILS Session */
1750 wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
1751 wpabuf_put_u8(data, 1 + FILS_SESSION_LEN); /* Length */
1752 /* Element ID Extension */
1753 wpabuf_put_u8(data, WLAN_EID_EXT_FILS_SESSION);
1754 wpabuf_put_data(data, sta->fils_session, FILS_SESSION_LEN);
1755
1756 /* FILS Wrapped Data */
1757 if (!pmksa && erp_resp) {
1758 wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
1759 wpabuf_put_u8(data, 1 + wpabuf_len(erp_resp)); /* Length */
1760 /* Element ID Extension */
1761 wpabuf_put_u8(data, WLAN_EID_EXT_FILS_WRAPPED_DATA);
1762 wpabuf_put_buf(data, erp_resp);
1763
Paul Stewart092955c2017-02-06 09:13:09 -08001764 if (fils_rmsk_to_pmk(wpa_auth_sta_key_mgmt(sta->wpa_sm),
1765 msk, msk_len, sta->fils_snonce, fils_nonce,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001766 sta->fils_dh_ss ?
1767 wpabuf_head(sta->fils_dh_ss) : NULL,
1768 sta->fils_dh_ss ?
1769 wpabuf_len(sta->fils_dh_ss) : 0,
1770 pmk_buf, &pmk_len)) {
Paul Stewart092955c2017-02-06 09:13:09 -08001771 wpa_printf(MSG_DEBUG, "FILS: Failed to derive PMK");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001772 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Paul Stewart092955c2017-02-06 09:13:09 -08001773 wpabuf_free(data);
1774 data = NULL;
1775 goto fail;
1776 }
1777 pmk = pmk_buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001778
1779 /* Don't use DHss in PTK derivation if PMKSA caching is not
1780 * used. */
1781 wpabuf_clear_free(sta->fils_dh_ss);
1782 sta->fils_dh_ss = NULL;
1783
1784 if (sta->fils_erp_pmkid_set) {
1785 /* TODO: get PMKLifetime from WPA parameters */
1786 unsigned int dot11RSNAConfigPMKLifetime = 43200;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001787 int session_timeout;
1788
1789 session_timeout = dot11RSNAConfigPMKLifetime;
1790 if (sta->session_timeout_set) {
1791 struct os_reltime now, diff;
1792
1793 os_get_reltime(&now);
1794 os_reltime_sub(&sta->session_timeout, &now,
1795 &diff);
1796 session_timeout = diff.sec;
1797 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001798
1799 sta->fils_erp_pmkid_set = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001800 if (!hapd->conf->disable_pmksa_caching &&
1801 wpa_auth_pmksa_add2(
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001802 hapd->wpa_auth, sta->addr,
1803 pmk, pmk_len,
1804 sta->fils_erp_pmkid,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001805 session_timeout,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001806 wpa_auth_sta_key_mgmt(sta->wpa_sm)) < 0) {
1807 wpa_printf(MSG_ERROR,
1808 "FILS: Failed to add PMKSA cache entry based on ERP");
1809 }
1810 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001811 } else if (pmksa) {
1812 pmk = pmksa->pmk;
1813 pmk_len = pmksa->pmk_len;
1814 }
1815
1816 if (!pmk) {
1817 wpa_printf(MSG_DEBUG, "FILS: No PMK available");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001818 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001819 wpabuf_free(data);
1820 data = NULL;
1821 goto fail;
1822 }
1823
1824 if (fils_auth_pmk_to_ptk(sta->wpa_sm, pmk, pmk_len,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001825 sta->fils_snonce, fils_nonce,
1826 sta->fils_dh_ss ?
1827 wpabuf_head(sta->fils_dh_ss) : NULL,
1828 sta->fils_dh_ss ?
1829 wpabuf_len(sta->fils_dh_ss) : 0,
1830 sta->fils_g_sta, pub) < 0) {
1831 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001832 wpabuf_free(data);
1833 data = NULL;
1834 goto fail;
1835 }
1836
1837fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001838 if (is_pub)
1839 *is_pub = pub != NULL;
1840 os_free(ie_buf);
1841 wpabuf_free(pub);
1842 wpabuf_clear_free(sta->fils_dh_ss);
1843 sta->fils_dh_ss = NULL;
1844#ifdef CONFIG_FILS_SK_PFS
1845 crypto_ecdh_deinit(sta->fils_ecdh);
1846 sta->fils_ecdh = NULL;
1847#endif /* CONFIG_FILS_SK_PFS */
1848 return data;
1849}
1850
1851
1852static void handle_auth_fils_finish(struct hostapd_data *hapd,
1853 struct sta_info *sta, u16 resp,
1854 struct wpabuf *data, int pub)
1855{
1856 u16 auth_alg;
1857
1858 auth_alg = (pub ||
1859 resp == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) ?
1860 WLAN_AUTH_FILS_SK_PFS : WLAN_AUTH_FILS_SK;
1861 send_auth_reply(hapd, sta->addr, hapd->own_addr, auth_alg, 2, resp,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001862 data ? wpabuf_head(data) : (u8 *) "",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001863 data ? wpabuf_len(data) : 0, "auth-fils-finish");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001864 wpabuf_free(data);
1865
1866 if (resp == WLAN_STATUS_SUCCESS) {
1867 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1868 HOSTAPD_LEVEL_DEBUG,
1869 "authentication OK (FILS)");
1870 sta->flags |= WLAN_STA_AUTH;
1871 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001872 sta->auth_alg = pub ? WLAN_AUTH_FILS_SK_PFS : WLAN_AUTH_FILS_SK;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001873 mlme_authenticate_indication(hapd, sta);
1874 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001875}
1876
1877
1878void ieee802_11_finish_fils_auth(struct hostapd_data *hapd,
1879 struct sta_info *sta, int success,
1880 struct wpabuf *erp_resp,
1881 const u8 *msk, size_t msk_len)
1882{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001883 struct wpabuf *data;
1884 int pub = 0;
1885 u16 resp;
1886
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001887 sta->flags &= ~WLAN_STA_PENDING_FILS_ERP;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001888
1889 if (!sta->fils_pending_cb)
1890 return;
1891 resp = success ? WLAN_STATUS_SUCCESS : WLAN_STATUS_UNSPECIFIED_FAILURE;
1892 data = prepare_auth_resp_fils(hapd, sta, &resp, NULL, erp_resp,
1893 msk, msk_len, &pub);
1894 if (!data) {
1895 wpa_printf(MSG_DEBUG,
1896 "%s: prepare_auth_resp_fils() returned failure",
1897 __func__);
1898 }
1899 sta->fils_pending_cb(hapd, sta, resp, data, pub);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001900}
1901
1902#endif /* CONFIG_FILS */
1903
1904
Roshan Pius3a1667e2018-07-03 15:17:14 -07001905int
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001906ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
1907 const u8 *msg, size_t len, u32 *session_timeout,
1908 u32 *acct_interim_interval,
1909 struct vlan_description *vlan_id,
1910 struct hostapd_sta_wpa_psk_short **psk,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001911 char **identity, char **radius_cui, int is_probe_req)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001912{
1913 int res;
1914
1915 os_memset(vlan_id, 0, sizeof(*vlan_id));
1916 res = hostapd_allowed_address(hapd, addr, msg, len,
1917 session_timeout, acct_interim_interval,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001918 vlan_id, psk, identity, radius_cui,
1919 is_probe_req);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001920
1921 if (res == HOSTAPD_ACL_REJECT) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001922 if (!is_probe_req)
1923 wpa_printf(MSG_DEBUG,
1924 "Station " MACSTR
1925 " not allowed to authenticate",
1926 MAC2STR(addr));
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001927 return HOSTAPD_ACL_REJECT;
1928 }
1929
1930 if (res == HOSTAPD_ACL_PENDING) {
1931 wpa_printf(MSG_DEBUG, "Authentication frame from " MACSTR
1932 " waiting for an external authentication",
1933 MAC2STR(addr));
1934 /* Authentication code will re-send the authentication frame
1935 * after it has received (and cached) information from the
1936 * external source. */
1937 return HOSTAPD_ACL_PENDING;
1938 }
1939
1940 return res;
1941}
1942
1943
1944static int
1945ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
1946 int res, u32 session_timeout,
1947 u32 acct_interim_interval,
1948 struct vlan_description *vlan_id,
1949 struct hostapd_sta_wpa_psk_short **psk,
1950 char **identity, char **radius_cui)
1951{
1952 if (vlan_id->notempty &&
1953 !hostapd_vlan_valid(hapd->conf->vlan, vlan_id)) {
1954 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
1955 HOSTAPD_LEVEL_INFO,
1956 "Invalid VLAN %d%s received from RADIUS server",
1957 vlan_id->untagged,
1958 vlan_id->tagged[0] ? "+" : "");
1959 return -1;
1960 }
1961 if (ap_sta_set_vlan(hapd, sta, vlan_id) < 0)
1962 return -1;
1963 if (sta->vlan_id)
1964 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
1965 HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
1966
1967 hostapd_free_psk_list(sta->psk);
1968 if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
1969 sta->psk = *psk;
1970 *psk = NULL;
1971 } else {
1972 sta->psk = NULL;
1973 }
1974
Roshan Pius3a1667e2018-07-03 15:17:14 -07001975 os_free(sta->identity);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001976 sta->identity = *identity;
1977 *identity = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001978
1979 os_free(sta->radius_cui);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001980 sta->radius_cui = *radius_cui;
1981 *radius_cui = NULL;
1982
1983 if (hapd->conf->acct_interim_interval == 0 && acct_interim_interval)
1984 sta->acct_interim_interval = acct_interim_interval;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001985 if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT) {
1986 sta->session_timeout_set = 1;
1987 os_get_reltime(&sta->session_timeout);
1988 sta->session_timeout.sec += session_timeout;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001989 ap_sta_session_timeout(hapd, sta, session_timeout);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001990 } else {
1991 sta->session_timeout_set = 0;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001992 ap_sta_no_session_timeout(hapd, sta);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001993 }
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001994
1995 return 0;
1996}
1997
1998
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001999static void handle_auth(struct hostapd_data *hapd,
Hai Shalom74f70d42019-02-11 14:42:39 -08002000 const struct ieee80211_mgmt *mgmt, size_t len,
Hai Shalom021b0b52019-04-10 11:17:58 -07002001 int rssi, int from_queue)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002002{
2003 u16 auth_alg, auth_transaction, status_code;
2004 u16 resp = WLAN_STATUS_SUCCESS;
2005 struct sta_info *sta = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002006 int res, reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002007 u16 fc;
2008 const u8 *challenge = NULL;
2009 u32 session_timeout, acct_interim_interval;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002010 struct vlan_description vlan_id;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002011 struct hostapd_sta_wpa_psk_short *psk = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002012 u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
2013 size_t resp_ies_len = 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002014 char *identity = NULL;
2015 char *radius_cui = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002016 u16 seq_ctrl;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002017
2018 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002019 wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
2020 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002021 return;
2022 }
2023
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002024#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07002025 if (hapd->iconf->ignore_auth_probability > 0.0 &&
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002026 drand48() < hapd->iconf->ignore_auth_probability) {
2027 wpa_printf(MSG_INFO,
2028 "TESTING: ignoring auth frame from " MACSTR,
2029 MAC2STR(mgmt->sa));
2030 return;
2031 }
2032#endif /* CONFIG_TESTING_OPTIONS */
2033
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002034 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
2035 auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
2036 status_code = le_to_host16(mgmt->u.auth.status_code);
2037 fc = le_to_host16(mgmt->frame_control);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002038 seq_ctrl = le_to_host16(mgmt->seq_ctrl);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002039
2040 if (len >= IEEE80211_HDRLEN + sizeof(mgmt->u.auth) +
2041 2 + WLAN_AUTH_CHALLENGE_LEN &&
2042 mgmt->u.auth.variable[0] == WLAN_EID_CHALLENGE &&
2043 mgmt->u.auth.variable[1] == WLAN_AUTH_CHALLENGE_LEN)
2044 challenge = &mgmt->u.auth.variable[2];
2045
2046 wpa_printf(MSG_DEBUG, "authentication: STA=" MACSTR " auth_alg=%d "
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002047 "auth_transaction=%d status_code=%d wep=%d%s "
Hai Shalom021b0b52019-04-10 11:17:58 -07002048 "seq_ctrl=0x%x%s%s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002049 MAC2STR(mgmt->sa), auth_alg, auth_transaction,
2050 status_code, !!(fc & WLAN_FC_ISWEP),
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002051 challenge ? " challenge" : "",
Hai Shalom021b0b52019-04-10 11:17:58 -07002052 seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "",
2053 from_queue ? " (from queue)" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002054
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002055#ifdef CONFIG_NO_RC4
2056 if (auth_alg == WLAN_AUTH_SHARED_KEY) {
2057 wpa_printf(MSG_INFO,
2058 "Unsupported authentication algorithm (%d)",
2059 auth_alg);
2060 resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
2061 goto fail;
2062 }
2063#endif /* CONFIG_NO_RC4 */
2064
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002065 if (hapd->tkip_countermeasures) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002066 wpa_printf(MSG_DEBUG,
2067 "Ongoing TKIP countermeasures (Michael MIC failure) - reject authentication");
2068 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002069 goto fail;
2070 }
2071
2072 if (!(((hapd->conf->auth_algs & WPA_AUTH_ALG_OPEN) &&
2073 auth_alg == WLAN_AUTH_OPEN) ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002074#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002075 (hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002076 auth_alg == WLAN_AUTH_FT) ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002077#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002078#ifdef CONFIG_SAE
2079 (hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
2080 auth_alg == WLAN_AUTH_SAE) ||
2081#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002082#ifdef CONFIG_FILS
2083 (hapd->conf->wpa && wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt) &&
2084 auth_alg == WLAN_AUTH_FILS_SK) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002085 (hapd->conf->wpa && wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt) &&
2086 hapd->conf->fils_dh_group &&
2087 auth_alg == WLAN_AUTH_FILS_SK_PFS) ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002088#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002089 ((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) &&
2090 auth_alg == WLAN_AUTH_SHARED_KEY))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002091 wpa_printf(MSG_INFO, "Unsupported authentication algorithm (%d)",
2092 auth_alg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002093 resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
2094 goto fail;
2095 }
2096
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002097 if (!(auth_transaction == 1 || auth_alg == WLAN_AUTH_SAE ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002098 (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002099 wpa_printf(MSG_INFO, "Unknown authentication transaction number (%d)",
2100 auth_transaction);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002101 resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
2102 goto fail;
2103 }
2104
2105 if (os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002106 wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to authenticate",
2107 MAC2STR(mgmt->sa));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002108 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
2109 goto fail;
2110 }
2111
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002112 if (hapd->conf->no_auth_if_seen_on) {
2113 struct hostapd_data *other;
2114
2115 other = sta_track_seen_on(hapd->iface, mgmt->sa,
2116 hapd->conf->no_auth_if_seen_on);
2117 if (other) {
2118 u8 *pos;
2119 u32 info;
2120 u8 op_class, channel, phytype;
2121
2122 wpa_printf(MSG_DEBUG, "%s: Reject authentication from "
2123 MACSTR " since STA has been seen on %s",
2124 hapd->conf->iface, MAC2STR(mgmt->sa),
2125 hapd->conf->no_auth_if_seen_on);
2126
2127 resp = WLAN_STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION;
2128 pos = &resp_ies[0];
2129 *pos++ = WLAN_EID_NEIGHBOR_REPORT;
2130 *pos++ = 13;
2131 os_memcpy(pos, other->own_addr, ETH_ALEN);
2132 pos += ETH_ALEN;
2133 info = 0; /* TODO: BSSID Information */
2134 WPA_PUT_LE32(pos, info);
2135 pos += 4;
2136 if (other->iconf->hw_mode == HOSTAPD_MODE_IEEE80211AD)
2137 phytype = 8; /* dmg */
2138 else if (other->iconf->ieee80211ac)
2139 phytype = 9; /* vht */
2140 else if (other->iconf->ieee80211n)
2141 phytype = 7; /* ht */
2142 else if (other->iconf->hw_mode ==
2143 HOSTAPD_MODE_IEEE80211A)
2144 phytype = 4; /* ofdm */
2145 else if (other->iconf->hw_mode ==
2146 HOSTAPD_MODE_IEEE80211G)
2147 phytype = 6; /* erp */
2148 else
2149 phytype = 5; /* hrdsss */
2150 if (ieee80211_freq_to_channel_ext(
2151 hostapd_hw_get_freq(other,
2152 other->iconf->channel),
2153 other->iconf->secondary_channel,
2154 other->iconf->ieee80211ac,
2155 &op_class, &channel) == NUM_HOSTAPD_MODES) {
2156 op_class = 0;
2157 channel = other->iconf->channel;
2158 }
2159 *pos++ = op_class;
2160 *pos++ = channel;
2161 *pos++ = phytype;
2162 resp_ies_len = pos - &resp_ies[0];
2163 goto fail;
2164 }
2165 }
2166
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002167 res = ieee802_11_allowed_address(
2168 hapd, mgmt->sa, (const u8 *) mgmt, len, &session_timeout,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002169 &acct_interim_interval, &vlan_id, &psk, &identity, &radius_cui,
2170 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002171 if (res == HOSTAPD_ACL_REJECT) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002172 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
2173 "Ignore Authentication frame from " MACSTR
2174 " due to ACL reject", MAC2STR(mgmt->sa));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002175 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
2176 goto fail;
2177 }
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002178 if (res == HOSTAPD_ACL_PENDING)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002179 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002180
Hai Shalom021b0b52019-04-10 11:17:58 -07002181#ifdef CONFIG_SAE
2182 if (auth_alg == WLAN_AUTH_SAE && !from_queue &&
2183 (auth_transaction == 1 ||
2184 (auth_transaction == 2 && auth_sae_queued_addr(hapd, mgmt->sa)))) {
2185 /* Handle SAE Authentication commit message through a queue to
2186 * provide more control for postponing the needed heavy
2187 * processing under a possible DoS attack scenario. In addition,
2188 * queue SAE Authentication confirm message if there happens to
2189 * be a queued commit message from the same peer. This is needed
2190 * to avoid reordering Authentication frames within the same
2191 * SAE exchange. */
2192 auth_sae_queue(hapd, mgmt, len, rssi);
2193 return;
2194 }
2195#endif /* CONFIG_SAE */
2196
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002197 sta = ap_get_sta(hapd, mgmt->sa);
2198 if (sta) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002199 sta->flags &= ~WLAN_STA_PENDING_FILS_ERP;
Hai Shalom74f70d42019-02-11 14:42:39 -08002200 sta->ft_over_ds = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002201 if ((fc & WLAN_FC_RETRY) &&
2202 sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ &&
2203 sta->last_seq_ctrl == seq_ctrl &&
2204 sta->last_subtype == WLAN_FC_STYPE_AUTH) {
2205 hostapd_logger(hapd, sta->addr,
2206 HOSTAPD_MODULE_IEEE80211,
2207 HOSTAPD_LEVEL_DEBUG,
2208 "Drop repeated authentication frame seq_ctrl=0x%x",
2209 seq_ctrl);
2210 return;
2211 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002212#ifdef CONFIG_MESH
2213 if ((hapd->conf->mesh & MESH_ENABLED) &&
2214 sta->plink_state == PLINK_BLOCKED) {
2215 wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
2216 " is blocked - drop Authentication frame",
2217 MAC2STR(mgmt->sa));
2218 return;
2219 }
2220#endif /* CONFIG_MESH */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002221 } else {
2222#ifdef CONFIG_MESH
2223 if (hapd->conf->mesh & MESH_ENABLED) {
2224 /* if the mesh peer is not available, we don't do auth.
2225 */
2226 wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002227 " not yet known - drop Authentication frame",
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002228 MAC2STR(mgmt->sa));
2229 /*
2230 * Save a copy of the frame so that it can be processed
2231 * if a new peer entry is added shortly after this.
2232 */
2233 wpabuf_free(hapd->mesh_pending_auth);
2234 hapd->mesh_pending_auth = wpabuf_alloc_copy(mgmt, len);
2235 os_get_reltime(&hapd->mesh_pending_auth_time);
2236 return;
2237 }
2238#endif /* CONFIG_MESH */
2239
2240 sta = ap_sta_add(hapd, mgmt->sa);
2241 if (!sta) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002242 wpa_printf(MSG_DEBUG, "ap_sta_add() failed");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002243 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
2244 goto fail;
2245 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002246 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002247 sta->last_seq_ctrl = seq_ctrl;
2248 sta->last_subtype = WLAN_FC_STYPE_AUTH;
Hai Shalom74f70d42019-02-11 14:42:39 -08002249#ifdef CONFIG_MBO
2250 sta->auth_rssi = rssi;
2251#endif /* CONFIG_MBO */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002252
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002253 res = ieee802_11_set_radius_info(
2254 hapd, sta, res, session_timeout, acct_interim_interval,
2255 &vlan_id, &psk, &identity, &radius_cui);
2256 if (res) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002257 wpa_printf(MSG_DEBUG, "ieee802_11_set_radius_info() failed");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002258 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
2259 goto fail;
2260 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002261
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002262 sta->flags &= ~WLAN_STA_PREAUTH;
2263 ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
2264
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002265 /*
2266 * If the driver supports full AP client state, add a station to the
2267 * driver before sending authentication reply to make sure the driver
2268 * has resources, and not to go through the entire authentication and
2269 * association handshake, and fail it at the end.
2270 *
2271 * If this is not the first transaction, in a multi-step authentication
2272 * algorithm, the station already exists in the driver
2273 * (sta->added_unassoc = 1) so skip it.
2274 *
2275 * In mesh mode, the station was already added to the driver when the
2276 * NEW_PEER_CANDIDATE event is received.
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08002277 *
2278 * If PMF was negotiated for the existing association, skip this to
2279 * avoid dropping the STA entry and the associated keys. This is needed
2280 * to allow the original connection work until the attempt can complete
2281 * (re)association, so that unprotected Authentication frame cannot be
2282 * used to bypass PMF protection.
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002283 */
2284 if (FULL_AP_CLIENT_STATE_SUPP(hapd->iface->drv_flags) &&
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08002285 (!(sta->flags & WLAN_STA_MFP) || !ap_sta_is_authorized(sta)) &&
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002286 !(hapd->conf->mesh & MESH_ENABLED) &&
2287 !(sta->added_unassoc)) {
2288 /*
2289 * If a station that is already associated to the AP, is trying
2290 * to authenticate again, remove the STA entry, in order to make
2291 * sure the STA PS state gets cleared and configuration gets
2292 * updated. To handle this, station's added_unassoc flag is
2293 * cleared once the station has completed association.
2294 */
Hai Shalomce48b4a2018-09-05 11:41:35 -07002295 ap_sta_set_authorized(hapd, sta, 0);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002296 hostapd_drv_sta_remove(hapd, sta->addr);
2297 sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_AUTH |
2298 WLAN_STA_AUTHORIZED);
2299
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07002300 if (hostapd_sta_add(hapd, sta->addr, 0, 0, NULL, 0, 0,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002301 NULL, NULL, sta->flags, 0, 0, 0, 0)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002302 hostapd_logger(hapd, sta->addr,
2303 HOSTAPD_MODULE_IEEE80211,
2304 HOSTAPD_LEVEL_NOTICE,
2305 "Could not add STA to kernel driver");
2306 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
2307 goto fail;
2308 }
2309
2310 sta->added_unassoc = 1;
2311 }
2312
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002313 switch (auth_alg) {
2314 case WLAN_AUTH_OPEN:
2315 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2316 HOSTAPD_LEVEL_DEBUG,
2317 "authentication OK (open system)");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002318 sta->flags |= WLAN_STA_AUTH;
2319 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
2320 sta->auth_alg = WLAN_AUTH_OPEN;
2321 mlme_authenticate_indication(hapd, sta);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002322 break;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002323#ifndef CONFIG_NO_RC4
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002324 case WLAN_AUTH_SHARED_KEY:
2325 resp = auth_shared_key(hapd, sta, auth_transaction, challenge,
2326 fc & WLAN_FC_ISWEP);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002327 if (resp != 0)
2328 wpa_printf(MSG_DEBUG,
2329 "auth_shared_key() failed: status=%d", resp);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002330 sta->auth_alg = WLAN_AUTH_SHARED_KEY;
2331 mlme_authenticate_indication(hapd, sta);
2332 if (sta->challenge && auth_transaction == 1) {
2333 resp_ies[0] = WLAN_EID_CHALLENGE;
2334 resp_ies[1] = WLAN_AUTH_CHALLENGE_LEN;
2335 os_memcpy(resp_ies + 2, sta->challenge,
2336 WLAN_AUTH_CHALLENGE_LEN);
2337 resp_ies_len = 2 + WLAN_AUTH_CHALLENGE_LEN;
2338 }
2339 break;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002340#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002341#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002342 case WLAN_AUTH_FT:
2343 sta->auth_alg = WLAN_AUTH_FT;
2344 if (sta->wpa_sm == NULL)
2345 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002346 sta->addr, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002347 if (sta->wpa_sm == NULL) {
2348 wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA "
2349 "state machine");
2350 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
2351 goto fail;
2352 }
2353 wpa_ft_process_auth(sta->wpa_sm, mgmt->bssid,
2354 auth_transaction, mgmt->u.auth.variable,
2355 len - IEEE80211_HDRLEN -
2356 sizeof(mgmt->u.auth),
2357 handle_auth_ft_finish, hapd);
2358 /* handle_auth_ft_finish() callback will complete auth. */
2359 return;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002360#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002361#ifdef CONFIG_SAE
2362 case WLAN_AUTH_SAE:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002363#ifdef CONFIG_MESH
2364 if (status_code == WLAN_STATUS_SUCCESS &&
2365 hapd->conf->mesh & MESH_ENABLED) {
2366 if (sta->wpa_sm == NULL)
2367 sta->wpa_sm =
2368 wpa_auth_sta_init(hapd->wpa_auth,
2369 sta->addr, NULL);
2370 if (sta->wpa_sm == NULL) {
2371 wpa_printf(MSG_DEBUG,
2372 "SAE: Failed to initialize WPA state machine");
2373 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
2374 goto fail;
2375 }
2376 }
2377#endif /* CONFIG_MESH */
2378 handle_auth_sae(hapd, sta, mgmt, len, auth_transaction,
2379 status_code);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002380 return;
2381#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002382#ifdef CONFIG_FILS
2383 case WLAN_AUTH_FILS_SK:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002384 case WLAN_AUTH_FILS_SK_PFS:
2385 handle_auth_fils(hapd, sta, mgmt->u.auth.variable,
2386 len - IEEE80211_HDRLEN - sizeof(mgmt->u.auth),
2387 auth_alg, auth_transaction, status_code,
2388 handle_auth_fils_finish);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002389 return;
2390#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002391 }
2392
2393 fail:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002394 os_free(identity);
2395 os_free(radius_cui);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002396 hostapd_free_psk_list(psk);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002397
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002398 reply_res = send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
2399 auth_transaction + 1, resp, resp_ies,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002400 resp_ies_len, "handle-auth");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002401
2402 if (sta && sta->added_unassoc && (resp != WLAN_STATUS_SUCCESS ||
2403 reply_res != WLAN_STATUS_SUCCESS)) {
2404 hostapd_drv_sta_remove(hapd, sta->addr);
2405 sta->added_unassoc = 0;
2406 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002407}
2408
2409
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002410int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002411{
2412 int i, j = 32, aid;
2413
2414 /* get a unique AID */
2415 if (sta->aid > 0) {
2416 wpa_printf(MSG_DEBUG, " old AID %d", sta->aid);
2417 return 0;
2418 }
2419
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002420 if (TEST_FAIL())
2421 return -1;
2422
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002423 for (i = 0; i < AID_WORDS; i++) {
2424 if (hapd->sta_aid[i] == (u32) -1)
2425 continue;
2426 for (j = 0; j < 32; j++) {
2427 if (!(hapd->sta_aid[i] & BIT(j)))
2428 break;
2429 }
2430 if (j < 32)
2431 break;
2432 }
2433 if (j == 32)
2434 return -1;
2435 aid = i * 32 + j + 1;
2436 if (aid > 2007)
2437 return -1;
2438
2439 sta->aid = aid;
2440 hapd->sta_aid[i] |= BIT(j);
2441 wpa_printf(MSG_DEBUG, " new AID %d", sta->aid);
2442 return 0;
2443}
2444
2445
2446static u16 check_ssid(struct hostapd_data *hapd, struct sta_info *sta,
2447 const u8 *ssid_ie, size_t ssid_ie_len)
2448{
2449 if (ssid_ie == NULL)
2450 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2451
2452 if (ssid_ie_len != hapd->conf->ssid.ssid_len ||
2453 os_memcmp(ssid_ie, hapd->conf->ssid.ssid, ssid_ie_len) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002454 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2455 HOSTAPD_LEVEL_INFO,
2456 "Station tried to associate with unknown SSID "
Dmitry Shmidt3c479372014-02-04 10:50:36 -08002457 "'%s'", wpa_ssid_txt(ssid_ie, ssid_ie_len));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002458 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2459 }
2460
2461 return WLAN_STATUS_SUCCESS;
2462}
2463
2464
2465static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta,
2466 const u8 *wmm_ie, size_t wmm_ie_len)
2467{
2468 sta->flags &= ~WLAN_STA_WMM;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002469 sta->qosinfo = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002470 if (wmm_ie && hapd->conf->wmm_enabled) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002471 struct wmm_information_element *wmm;
2472
2473 if (!hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002474 hostapd_logger(hapd, sta->addr,
2475 HOSTAPD_MODULE_WPA,
2476 HOSTAPD_LEVEL_DEBUG,
2477 "invalid WMM element in association "
2478 "request");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002479 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2480 }
2481
2482 sta->flags |= WLAN_STA_WMM;
2483 wmm = (struct wmm_information_element *) wmm_ie;
2484 sta->qosinfo = wmm->qos_info;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002485 }
2486 return WLAN_STATUS_SUCCESS;
2487}
2488
Hai Shalom74f70d42019-02-11 14:42:39 -08002489static u16 check_multi_ap(struct hostapd_data *hapd, struct sta_info *sta,
2490 const u8 *multi_ap_ie, size_t multi_ap_len)
2491{
2492 u8 multi_ap_value = 0;
2493
2494 sta->flags &= ~WLAN_STA_MULTI_AP;
2495
2496 if (!hapd->conf->multi_ap)
2497 return WLAN_STATUS_SUCCESS;
2498
2499 if (multi_ap_ie) {
2500 const u8 *multi_ap_subelem;
2501
2502 multi_ap_subelem = get_ie(multi_ap_ie + 4,
2503 multi_ap_len - 4,
2504 MULTI_AP_SUB_ELEM_TYPE);
2505 if (multi_ap_subelem && multi_ap_subelem[1] == 1) {
2506 multi_ap_value = multi_ap_subelem[2];
2507 } else {
2508 hostapd_logger(hapd, sta->addr,
2509 HOSTAPD_MODULE_IEEE80211,
2510 HOSTAPD_LEVEL_INFO,
2511 "Multi-AP IE has missing or invalid Multi-AP subelement");
2512 return WLAN_STATUS_INVALID_IE;
2513 }
2514 }
2515
Hai Shalom021b0b52019-04-10 11:17:58 -07002516 if (multi_ap_value && multi_ap_value != MULTI_AP_BACKHAUL_STA)
2517 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2518 HOSTAPD_LEVEL_INFO,
2519 "Multi-AP IE with unexpected value 0x%02x",
2520 multi_ap_value);
Hai Shalom74f70d42019-02-11 14:42:39 -08002521
Hai Shalom021b0b52019-04-10 11:17:58 -07002522 if (!(multi_ap_value & MULTI_AP_BACKHAUL_STA)) {
2523 if (hapd->conf->multi_ap & FRONTHAUL_BSS)
2524 return WLAN_STATUS_SUCCESS;
Hai Shalom74f70d42019-02-11 14:42:39 -08002525
Hai Shalom021b0b52019-04-10 11:17:58 -07002526 hostapd_logger(hapd, sta->addr,
2527 HOSTAPD_MODULE_IEEE80211,
2528 HOSTAPD_LEVEL_INFO,
2529 "Non-Multi-AP STA tries to associate with backhaul-only BSS");
2530 return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
Hai Shalom74f70d42019-02-11 14:42:39 -08002531 }
2532
Hai Shalom021b0b52019-04-10 11:17:58 -07002533 if (!(hapd->conf->multi_ap & BACKHAUL_BSS))
2534 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2535 HOSTAPD_LEVEL_DEBUG,
2536 "Backhaul STA tries to associate with fronthaul-only BSS");
2537
2538 sta->flags |= WLAN_STA_MULTI_AP;
2539 return WLAN_STATUS_SUCCESS;
Hai Shalom74f70d42019-02-11 14:42:39 -08002540}
2541
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002542
2543static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
2544 struct ieee802_11_elems *elems)
2545{
Dmitry Shmidt29333592017-01-09 12:27:11 -08002546 /* Supported rates not used in IEEE 802.11ad/DMG */
2547 if (hapd->iface->current_mode &&
2548 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD)
2549 return WLAN_STATUS_SUCCESS;
2550
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002551 if (!elems->supp_rates) {
2552 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2553 HOSTAPD_LEVEL_DEBUG,
2554 "No supported rates element in AssocReq");
2555 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2556 }
2557
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002558 if (elems->supp_rates_len + elems->ext_supp_rates_len >
2559 sizeof(sta->supported_rates)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002560 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2561 HOSTAPD_LEVEL_DEBUG,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002562 "Invalid supported rates element length %d+%d",
2563 elems->supp_rates_len,
2564 elems->ext_supp_rates_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002565 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2566 }
2567
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002568 sta->supported_rates_len = merge_byte_arrays(
2569 sta->supported_rates, sizeof(sta->supported_rates),
2570 elems->supp_rates, elems->supp_rates_len,
2571 elems->ext_supp_rates, elems->ext_supp_rates_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002572
2573 return WLAN_STATUS_SUCCESS;
2574}
2575
2576
Dmitry Shmidt051af732013-10-22 13:52:46 -07002577static u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
2578 const u8 *ext_capab_ie, size_t ext_capab_ie_len)
2579{
2580#ifdef CONFIG_INTERWORKING
2581 /* check for QoS Map support */
2582 if (ext_capab_ie_len >= 5) {
2583 if (ext_capab_ie[4] & 0x01)
2584 sta->qos_map_enabled = 1;
2585 }
2586#endif /* CONFIG_INTERWORKING */
2587
Roshan Pius3a1667e2018-07-03 15:17:14 -07002588 if (ext_capab_ie_len > 0) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002589 sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2));
Roshan Pius3a1667e2018-07-03 15:17:14 -07002590 os_free(sta->ext_capability);
2591 sta->ext_capability = os_malloc(1 + ext_capab_ie_len);
2592 if (sta->ext_capability) {
2593 sta->ext_capability[0] = ext_capab_ie_len;
2594 os_memcpy(sta->ext_capability + 1, ext_capab_ie,
2595 ext_capab_ie_len);
2596 }
2597 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002598
Dmitry Shmidt051af732013-10-22 13:52:46 -07002599 return WLAN_STATUS_SUCCESS;
2600}
2601
2602
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002603#ifdef CONFIG_OWE
2604
2605static int owe_group_supported(struct hostapd_data *hapd, u16 group)
2606{
2607 int i;
2608 int *groups = hapd->conf->owe_groups;
2609
2610 if (group != 19 && group != 20 && group != 21)
2611 return 0;
2612
2613 if (!groups)
2614 return 1;
2615
2616 for (i = 0; groups[i] > 0; i++) {
2617 if (groups[i] == group)
2618 return 1;
2619 }
2620
2621 return 0;
2622}
2623
2624
2625static u16 owe_process_assoc_req(struct hostapd_data *hapd,
2626 struct sta_info *sta, const u8 *owe_dh,
2627 u8 owe_dh_len)
2628{
2629 struct wpabuf *secret, *pub, *hkey;
2630 int res;
2631 u8 prk[SHA512_MAC_LEN], pmkid[SHA512_MAC_LEN];
2632 const char *info = "OWE Key Generation";
2633 const u8 *addr[2];
2634 size_t len[2];
2635 u16 group;
2636 size_t hash_len, prime_len;
2637
2638 if (wpa_auth_sta_get_pmksa(sta->wpa_sm)) {
2639 wpa_printf(MSG_DEBUG, "OWE: Using PMKSA caching");
2640 return WLAN_STATUS_SUCCESS;
2641 }
2642
2643 group = WPA_GET_LE16(owe_dh);
2644 if (!owe_group_supported(hapd, group)) {
2645 wpa_printf(MSG_DEBUG, "OWE: Unsupported DH group %u", group);
2646 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
2647 }
2648 if (group == 19)
2649 prime_len = 32;
2650 else if (group == 20)
2651 prime_len = 48;
2652 else if (group == 21)
2653 prime_len = 66;
2654 else
2655 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
2656
2657 crypto_ecdh_deinit(sta->owe_ecdh);
2658 sta->owe_ecdh = crypto_ecdh_init(group);
2659 if (!sta->owe_ecdh)
2660 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
2661 sta->owe_group = group;
2662
2663 secret = crypto_ecdh_set_peerkey(sta->owe_ecdh, 0, owe_dh + 2,
2664 owe_dh_len - 2);
2665 secret = wpabuf_zeropad(secret, prime_len);
2666 if (!secret) {
2667 wpa_printf(MSG_DEBUG, "OWE: Invalid peer DH public key");
2668 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2669 }
2670 wpa_hexdump_buf_key(MSG_DEBUG, "OWE: DH shared secret", secret);
2671
2672 /* prk = HKDF-extract(C | A | group, z) */
2673
2674 pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
2675 if (!pub) {
2676 wpabuf_clear_free(secret);
2677 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2678 }
2679
2680 /* PMKID = Truncate-128(Hash(C | A)) */
2681 addr[0] = owe_dh + 2;
2682 len[0] = owe_dh_len - 2;
2683 addr[1] = wpabuf_head(pub);
2684 len[1] = wpabuf_len(pub);
2685 if (group == 19) {
2686 res = sha256_vector(2, addr, len, pmkid);
2687 hash_len = SHA256_MAC_LEN;
2688 } else if (group == 20) {
2689 res = sha384_vector(2, addr, len, pmkid);
2690 hash_len = SHA384_MAC_LEN;
2691 } else if (group == 21) {
2692 res = sha512_vector(2, addr, len, pmkid);
2693 hash_len = SHA512_MAC_LEN;
2694 } else {
2695 wpabuf_free(pub);
2696 wpabuf_clear_free(secret);
2697 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2698 }
2699 pub = wpabuf_zeropad(pub, prime_len);
2700 if (res < 0 || !pub) {
2701 wpabuf_free(pub);
2702 wpabuf_clear_free(secret);
2703 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2704 }
2705
2706 hkey = wpabuf_alloc(owe_dh_len - 2 + wpabuf_len(pub) + 2);
2707 if (!hkey) {
2708 wpabuf_free(pub);
2709 wpabuf_clear_free(secret);
2710 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2711 }
2712
2713 wpabuf_put_data(hkey, owe_dh + 2, owe_dh_len - 2); /* C */
2714 wpabuf_put_buf(hkey, pub); /* A */
2715 wpabuf_free(pub);
2716 wpabuf_put_le16(hkey, group); /* group */
2717 if (group == 19)
2718 res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey),
2719 wpabuf_head(secret), wpabuf_len(secret), prk);
2720 else if (group == 20)
2721 res = hmac_sha384(wpabuf_head(hkey), wpabuf_len(hkey),
2722 wpabuf_head(secret), wpabuf_len(secret), prk);
2723 else if (group == 21)
2724 res = hmac_sha512(wpabuf_head(hkey), wpabuf_len(hkey),
2725 wpabuf_head(secret), wpabuf_len(secret), prk);
2726 wpabuf_clear_free(hkey);
2727 wpabuf_clear_free(secret);
2728 if (res < 0)
2729 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2730
2731 wpa_hexdump_key(MSG_DEBUG, "OWE: prk", prk, hash_len);
2732
2733 /* PMK = HKDF-expand(prk, "OWE Key Generation", n) */
2734
2735 os_free(sta->owe_pmk);
2736 sta->owe_pmk = os_malloc(hash_len);
2737 if (!sta->owe_pmk) {
2738 os_memset(prk, 0, SHA512_MAC_LEN);
2739 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2740 }
2741
2742 if (group == 19)
2743 res = hmac_sha256_kdf(prk, hash_len, NULL, (const u8 *) info,
2744 os_strlen(info), sta->owe_pmk, hash_len);
2745 else if (group == 20)
2746 res = hmac_sha384_kdf(prk, hash_len, NULL, (const u8 *) info,
2747 os_strlen(info), sta->owe_pmk, hash_len);
2748 else if (group == 21)
2749 res = hmac_sha512_kdf(prk, hash_len, NULL, (const u8 *) info,
2750 os_strlen(info), sta->owe_pmk, hash_len);
2751 os_memset(prk, 0, SHA512_MAC_LEN);
2752 if (res < 0) {
2753 os_free(sta->owe_pmk);
2754 sta->owe_pmk = NULL;
2755 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2756 }
2757 sta->owe_pmk_len = hash_len;
2758
2759 wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sta->owe_pmk, sta->owe_pmk_len);
2760 wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, PMKID_LEN);
2761 wpa_auth_pmksa_add2(hapd->wpa_auth, sta->addr, sta->owe_pmk,
2762 sta->owe_pmk_len, pmkid, 0, WPA_KEY_MGMT_OWE);
2763
2764 return WLAN_STATUS_SUCCESS;
2765}
2766
2767#endif /* CONFIG_OWE */
2768
2769
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002770static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
2771 const u8 *ies, size_t ies_len, int reassoc)
2772{
2773 struct ieee802_11_elems elems;
2774 u16 resp;
2775 const u8 *wpa_ie;
2776 size_t wpa_ie_len;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002777 const u8 *p2p_dev_addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002778
2779 if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
2780 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2781 HOSTAPD_LEVEL_INFO, "Station sent an invalid "
2782 "association request");
2783 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2784 }
2785
2786 resp = check_ssid(hapd, sta, elems.ssid, elems.ssid_len);
2787 if (resp != WLAN_STATUS_SUCCESS)
2788 return resp;
2789 resp = check_wmm(hapd, sta, elems.wmm, elems.wmm_len);
2790 if (resp != WLAN_STATUS_SUCCESS)
2791 return resp;
Dmitry Shmidt051af732013-10-22 13:52:46 -07002792 resp = check_ext_capab(hapd, sta, elems.ext_capab, elems.ext_capab_len);
2793 if (resp != WLAN_STATUS_SUCCESS)
2794 return resp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002795 resp = copy_supp_rates(hapd, sta, &elems);
2796 if (resp != WLAN_STATUS_SUCCESS)
2797 return resp;
Hai Shalom74f70d42019-02-11 14:42:39 -08002798
2799 resp = check_multi_ap(hapd, sta, elems.multi_ap, elems.multi_ap_len);
2800 if (resp != WLAN_STATUS_SUCCESS)
2801 return resp;
2802
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002803#ifdef CONFIG_IEEE80211N
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07002804 resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002805 if (resp != WLAN_STATUS_SUCCESS)
2806 return resp;
2807 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
2808 !(sta->flags & WLAN_STA_HT)) {
2809 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2810 HOSTAPD_LEVEL_INFO, "Station does not support "
2811 "mandatory HT PHY - reject association");
2812 return WLAN_STATUS_ASSOC_DENIED_NO_HT;
2813 }
2814#endif /* CONFIG_IEEE80211N */
2815
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002816#ifdef CONFIG_IEEE80211AC
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002817 if (hapd->iconf->ieee80211ac) {
2818 resp = copy_sta_vht_capab(hapd, sta, elems.vht_capabilities);
2819 if (resp != WLAN_STATUS_SUCCESS)
2820 return resp;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002821
Hai Shalom74f70d42019-02-11 14:42:39 -08002822 resp = copy_sta_vht_oper(hapd, sta, elems.vht_operation);
2823 if (resp != WLAN_STATUS_SUCCESS)
2824 return resp;
2825
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002826 resp = set_sta_vht_opmode(hapd, sta, elems.vht_opmode_notif);
2827 if (resp != WLAN_STATUS_SUCCESS)
2828 return resp;
2829 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002830
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002831 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht &&
2832 !(sta->flags & WLAN_STA_VHT)) {
2833 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2834 HOSTAPD_LEVEL_INFO, "Station does not support "
2835 "mandatory VHT PHY - reject association");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002836 return WLAN_STATUS_ASSOC_DENIED_NO_VHT;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002837 }
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002838
2839 if (hapd->conf->vendor_vht && !elems.vht_capabilities) {
2840 resp = copy_sta_vendor_vht(hapd, sta, elems.vendor_vht,
2841 elems.vendor_vht_len);
2842 if (resp != WLAN_STATUS_SUCCESS)
2843 return resp;
2844 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002845#endif /* CONFIG_IEEE80211AC */
2846
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002847#ifdef CONFIG_P2P
2848 if (elems.p2p) {
2849 wpabuf_free(sta->p2p_ie);
2850 sta->p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
2851 P2P_IE_VENDOR_TYPE);
2852 if (sta->p2p_ie)
2853 p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie);
2854 } else {
2855 wpabuf_free(sta->p2p_ie);
2856 sta->p2p_ie = NULL;
2857 }
2858#endif /* CONFIG_P2P */
2859
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002860 if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) {
2861 wpa_ie = elems.rsn_ie;
2862 wpa_ie_len = elems.rsn_ie_len;
2863 } else if ((hapd->conf->wpa & WPA_PROTO_WPA) &&
2864 elems.wpa_ie) {
2865 wpa_ie = elems.wpa_ie;
2866 wpa_ie_len = elems.wpa_ie_len;
2867 } else {
2868 wpa_ie = NULL;
2869 wpa_ie_len = 0;
2870 }
2871
2872#ifdef CONFIG_WPS
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002873 sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002874 if (hapd->conf->wps_state && elems.wps_ie) {
2875 wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association "
2876 "Request - assume WPS is used");
2877 sta->flags |= WLAN_STA_WPS;
2878 wpabuf_free(sta->wps_ie);
2879 sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
2880 WPS_IE_VENDOR_TYPE);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002881 if (sta->wps_ie && wps_is_20(sta->wps_ie)) {
2882 wpa_printf(MSG_DEBUG, "WPS: STA supports WPS 2.0");
2883 sta->flags |= WLAN_STA_WPS2;
2884 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002885 wpa_ie = NULL;
2886 wpa_ie_len = 0;
2887 if (sta->wps_ie && wps_validate_assoc_req(sta->wps_ie) < 0) {
2888 wpa_printf(MSG_DEBUG, "WPS: Invalid WPS IE in "
2889 "(Re)Association Request - reject");
2890 return WLAN_STATUS_INVALID_IE;
2891 }
2892 } else if (hapd->conf->wps_state && wpa_ie == NULL) {
2893 wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE in "
2894 "(Re)Association Request - possible WPS use");
2895 sta->flags |= WLAN_STA_MAYBE_WPS;
2896 } else
2897#endif /* CONFIG_WPS */
2898 if (hapd->conf->wpa && wpa_ie == NULL) {
2899 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2900 HOSTAPD_LEVEL_INFO,
2901 "No WPA/RSN IE in association request");
2902 return WLAN_STATUS_INVALID_IE;
2903 }
2904
2905 if (hapd->conf->wpa && wpa_ie) {
2906 int res;
2907 wpa_ie -= 2;
2908 wpa_ie_len += 2;
2909 if (sta->wpa_sm == NULL)
2910 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002911 sta->addr,
2912 p2p_dev_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002913 if (sta->wpa_sm == NULL) {
2914 wpa_printf(MSG_WARNING, "Failed to initialize WPA "
2915 "state machine");
2916 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2917 }
Hai Shalom021b0b52019-04-10 11:17:58 -07002918 wpa_auth_set_auth_alg(sta->wpa_sm, sta->auth_alg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002919 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
Hai Shalom021b0b52019-04-10 11:17:58 -07002920 hapd->iface->freq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002921 wpa_ie, wpa_ie_len,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002922 elems.mdie, elems.mdie_len,
2923 elems.owe_dh, elems.owe_dh_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002924 resp = wpa_res_to_status_code(res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002925 if (resp != WLAN_STATUS_SUCCESS)
2926 return resp;
2927#ifdef CONFIG_IEEE80211W
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002928 if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
2929 (WLAN_STA_ASSOC | WLAN_STA_MFP) &&
2930 !sta->sa_query_timed_out &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002931 sta->sa_query_count > 0)
2932 ap_check_sa_query_timeout(hapd, sta);
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002933 if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
2934 (WLAN_STA_ASSOC | WLAN_STA_MFP) &&
2935 !sta->sa_query_timed_out &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002936 (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) {
2937 /*
2938 * STA has already been associated with MFP and SA
2939 * Query timeout has not been reached. Reject the
2940 * association attempt temporarily and start SA Query,
2941 * if one is not pending.
2942 */
2943
2944 if (sta->sa_query_count == 0)
2945 ap_sta_start_sa_query(hapd, sta);
2946
2947 return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
2948 }
2949
2950 if (wpa_auth_uses_mfp(sta->wpa_sm))
2951 sta->flags |= WLAN_STA_MFP;
2952 else
2953 sta->flags &= ~WLAN_STA_MFP;
2954#endif /* CONFIG_IEEE80211W */
2955
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002956#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002957 if (sta->auth_alg == WLAN_AUTH_FT) {
2958 if (!reassoc) {
2959 wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried "
2960 "to use association (not "
2961 "re-association) with FT auth_alg",
2962 MAC2STR(sta->addr));
2963 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2964 }
2965
2966 resp = wpa_ft_validate_reassoc(sta->wpa_sm, ies,
2967 ies_len);
2968 if (resp != WLAN_STATUS_SUCCESS)
2969 return resp;
2970 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002971#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002972
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002973#ifdef CONFIG_SAE
Roshan Pius3a1667e2018-07-03 15:17:14 -07002974 if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae &&
2975 sta->sae->state == SAE_ACCEPTED)
2976 wpa_auth_add_sae_pmkid(sta->wpa_sm, sta->sae->pmkid);
2977
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002978 if (wpa_auth_uses_sae(sta->wpa_sm) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002979 sta->auth_alg == WLAN_AUTH_OPEN) {
2980 struct rsn_pmksa_cache_entry *sa;
2981 sa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
2982 if (!sa || sa->akmp != WPA_KEY_MGMT_SAE) {
2983 wpa_printf(MSG_DEBUG,
2984 "SAE: No PMKSA cache entry found for "
2985 MACSTR, MAC2STR(sta->addr));
2986 return WLAN_STATUS_INVALID_PMKID;
2987 }
2988 wpa_printf(MSG_DEBUG, "SAE: " MACSTR
2989 " using PMKSA caching", MAC2STR(sta->addr));
2990 } else if (wpa_auth_uses_sae(sta->wpa_sm) &&
2991 sta->auth_alg != WLAN_AUTH_SAE &&
2992 !(sta->auth_alg == WLAN_AUTH_FT &&
2993 wpa_auth_uses_ft_sae(sta->wpa_sm))) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002994 wpa_printf(MSG_DEBUG, "SAE: " MACSTR " tried to use "
2995 "SAE AKM after non-SAE auth_alg %u",
2996 MAC2STR(sta->addr), sta->auth_alg);
2997 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
2998 }
2999#endif /* CONFIG_SAE */
3000
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003001#ifdef CONFIG_OWE
3002 if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
3003 wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE &&
3004 elems.owe_dh) {
3005 resp = owe_process_assoc_req(hapd, sta, elems.owe_dh,
3006 elems.owe_dh_len);
3007 if (resp != WLAN_STATUS_SUCCESS)
3008 return resp;
3009 }
3010#endif /* CONFIG_OWE */
3011
Hai Shalom021b0b52019-04-10 11:17:58 -07003012#ifdef CONFIG_DPP2
3013 dpp_pfs_free(sta->dpp_pfs);
3014 sta->dpp_pfs = NULL;
3015
3016 if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) &&
3017 hapd->conf->dpp_netaccesskey && sta->wpa_sm &&
3018 wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP &&
3019 elems.owe_dh) {
3020 sta->dpp_pfs = dpp_pfs_init(
3021 wpabuf_head(hapd->conf->dpp_netaccesskey),
3022 wpabuf_len(hapd->conf->dpp_netaccesskey));
3023 if (!sta->dpp_pfs) {
3024 wpa_printf(MSG_DEBUG,
3025 "DPP: Could not initialize PFS");
3026 /* Try to continue without PFS */
3027 goto pfs_fail;
3028 }
3029
3030 if (dpp_pfs_process(sta->dpp_pfs, elems.owe_dh,
3031 elems.owe_dh_len) < 0) {
3032 dpp_pfs_free(sta->dpp_pfs);
3033 sta->dpp_pfs = NULL;
3034 return WLAN_STATUS_UNSPECIFIED_FAILURE;
3035 }
3036 }
3037
3038 wpa_auth_set_dpp_z(sta->wpa_sm, sta->dpp_pfs ?
3039 sta->dpp_pfs->secret : NULL);
3040 pfs_fail:
3041#endif /* CONFIG_DPP2 */
3042
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003043#ifdef CONFIG_IEEE80211N
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003044 if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003045 wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
3046 hostapd_logger(hapd, sta->addr,
3047 HOSTAPD_MODULE_IEEE80211,
3048 HOSTAPD_LEVEL_INFO,
3049 "Station tried to use TKIP with HT "
3050 "association");
3051 return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
3052 }
3053#endif /* CONFIG_IEEE80211N */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003054#ifdef CONFIG_HS20
3055 } else if (hapd->conf->osen) {
3056 if (elems.osen == NULL) {
3057 hostapd_logger(
3058 hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3059 HOSTAPD_LEVEL_INFO,
3060 "No HS 2.0 OSEN element in association request");
3061 return WLAN_STATUS_INVALID_IE;
3062 }
3063
3064 wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association");
3065 if (sta->wpa_sm == NULL)
3066 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
3067 sta->addr, NULL);
3068 if (sta->wpa_sm == NULL) {
3069 wpa_printf(MSG_WARNING, "Failed to initialize WPA "
3070 "state machine");
3071 return WLAN_STATUS_UNSPECIFIED_FAILURE;
3072 }
3073 if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm,
3074 elems.osen - 2, elems.osen_len + 2) < 0)
3075 return WLAN_STATUS_INVALID_IE;
3076#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003077 } else
3078 wpa_auth_sta_no_wpa(sta->wpa_sm);
3079
3080#ifdef CONFIG_P2P
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003081 p2p_group_notif_assoc(hapd->p2p_group, sta->addr, ies, ies_len);
3082#endif /* CONFIG_P2P */
3083
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003084#ifdef CONFIG_HS20
3085 wpabuf_free(sta->hs20_ie);
3086 if (elems.hs20 && elems.hs20_len > 4) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003087 int release;
3088
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003089 sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
3090 elems.hs20_len - 4);
Hai Shalom74f70d42019-02-11 14:42:39 -08003091 release = ((elems.hs20[4] >> 4) & 0x0f) + 1;
3092 if (release >= 2 && !wpa_auth_uses_mfp(sta->wpa_sm)) {
3093 wpa_printf(MSG_DEBUG,
3094 "HS 2.0: PMF not negotiated by release %d station "
3095 MACSTR, release, MAC2STR(sta->addr));
3096 return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
3097 }
3098 } else {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003099 sta->hs20_ie = NULL;
Hai Shalom74f70d42019-02-11 14:42:39 -08003100 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003101
3102 wpabuf_free(sta->roaming_consortium);
3103 if (elems.roaming_cons_sel)
3104 sta->roaming_consortium = wpabuf_alloc_copy(
3105 elems.roaming_cons_sel + 4,
3106 elems.roaming_cons_sel_len - 4);
3107 else
3108 sta->roaming_consortium = NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003109#endif /* CONFIG_HS20 */
3110
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003111#ifdef CONFIG_FST
3112 wpabuf_free(sta->mb_ies);
3113 if (hapd->iface->fst)
3114 sta->mb_ies = mb_ies_by_info(&elems.mb_ies);
3115 else
3116 sta->mb_ies = NULL;
3117#endif /* CONFIG_FST */
3118
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003119#ifdef CONFIG_MBO
3120 mbo_ap_check_sta_assoc(hapd, sta, &elems);
3121
3122 if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) &&
3123 elems.mbo && sta->cell_capa && !(sta->flags & WLAN_STA_MFP) &&
3124 hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
3125 wpa_printf(MSG_INFO,
3126 "MBO: Reject WPA2 association without PMF");
3127 return WLAN_STATUS_UNSPECIFIED_FAILURE;
3128 }
3129#endif /* CONFIG_MBO */
3130
Hai Shalom74f70d42019-02-11 14:42:39 -08003131#if defined(CONFIG_FILS) && defined(CONFIG_OCV)
3132 if (wpa_auth_uses_ocv(sta->wpa_sm) &&
3133 (sta->auth_alg == WLAN_AUTH_FILS_SK ||
3134 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
3135 sta->auth_alg == WLAN_AUTH_FILS_PK)) {
3136 struct wpa_channel_info ci;
3137 int tx_chanwidth;
3138 int tx_seg1_idx;
3139
3140 if (hostapd_drv_channel_info(hapd, &ci) != 0) {
3141 wpa_printf(MSG_WARNING,
3142 "Failed to get channel info to validate received OCI in FILS (Re)Association Request frame");
3143 return WLAN_STATUS_UNSPECIFIED_FAILURE;
3144 }
3145
3146 if (get_sta_tx_parameters(sta->wpa_sm,
3147 channel_width_to_int(ci.chanwidth),
3148 ci.seg1_idx, &tx_chanwidth,
3149 &tx_seg1_idx) < 0)
3150 return WLAN_STATUS_UNSPECIFIED_FAILURE;
3151
3152 if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
3153 tx_chanwidth, tx_seg1_idx) != 0) {
3154 wpa_printf(MSG_WARNING, "FILS: %s", ocv_errorstr);
3155 return WLAN_STATUS_UNSPECIFIED_FAILURE;
3156 }
3157 }
3158#endif /* CONFIG_FILS && CONFIG_OCV */
3159
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003160 ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes,
3161 elems.supp_op_classes_len);
3162
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003163 if ((sta->capability & WLAN_CAPABILITY_RADIO_MEASUREMENT) &&
3164 elems.rrm_enabled &&
3165 elems.rrm_enabled_len >= sizeof(sta->rrm_enabled_capa))
3166 os_memcpy(sta->rrm_enabled_capa, elems.rrm_enabled,
3167 sizeof(sta->rrm_enabled_capa));
3168
Roshan Pius3a1667e2018-07-03 15:17:14 -07003169 if (elems.power_capab) {
3170 sta->min_tx_power = elems.power_capab[0];
3171 sta->max_tx_power = elems.power_capab[1];
3172 sta->power_capab = 1;
3173 } else {
3174 sta->power_capab = 0;
3175 }
3176
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003177 return WLAN_STATUS_SUCCESS;
3178}
3179
3180
3181static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
3182 u16 reason_code)
3183{
3184 int send_len;
3185 struct ieee80211_mgmt reply;
3186
3187 os_memset(&reply, 0, sizeof(reply));
3188 reply.frame_control =
3189 IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DEAUTH);
3190 os_memcpy(reply.da, addr, ETH_ALEN);
3191 os_memcpy(reply.sa, hapd->own_addr, ETH_ALEN);
3192 os_memcpy(reply.bssid, hapd->own_addr, ETH_ALEN);
3193
3194 send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth);
3195 reply.u.deauth.reason_code = host_to_le16(reason_code);
3196
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003197 if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003198 wpa_printf(MSG_INFO, "Failed to send deauth: %s",
3199 strerror(errno));
3200}
3201
3202
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003203static int add_associated_sta(struct hostapd_data *hapd,
Hai Shalom74f70d42019-02-11 14:42:39 -08003204 struct sta_info *sta, int reassoc)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003205{
3206 struct ieee80211_ht_capabilities ht_cap;
3207 struct ieee80211_vht_capabilities vht_cap;
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02003208 int set = 1;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003209
3210 /*
3211 * Remove the STA entry to ensure the STA PS state gets cleared and
3212 * configuration gets updated. This is relevant for cases, such as
3213 * FT-over-the-DS, where a station re-associates back to the same AP but
3214 * skips the authentication flow, or if working with a driver that
3215 * does not support full AP client state.
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02003216 *
3217 * Skip this if the STA has already completed FT reassociation and the
3218 * TK has been configured since the TX/RX PN must not be reset to 0 for
3219 * the same key.
Hai Shalom74f70d42019-02-11 14:42:39 -08003220 *
3221 * FT-over-the-DS has a special case where the STA entry (and as such,
3222 * the TK) has not yet been configured to the driver depending on which
3223 * driver interface is used. For that case, allow add-STA operation to
3224 * be used (instead of set-STA). This is needed to allow mac80211-based
3225 * drivers to accept the STA parameter configuration. Since this is
3226 * after a new FT-over-DS exchange, a new TK has been derived, so key
3227 * reinstallation is not a concern for this case.
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003228 */
Hai Shalom74f70d42019-02-11 14:42:39 -08003229 wpa_printf(MSG_DEBUG, "Add associated STA " MACSTR
3230 " (added_unassoc=%d auth_alg=%u ft_over_ds=%u reassoc=%d authorized=%d ft_tk=%d fils_tk=%d)",
3231 MAC2STR(sta->addr), sta->added_unassoc, sta->auth_alg,
3232 sta->ft_over_ds, reassoc,
3233 !!(sta->flags & WLAN_STA_AUTHORIZED),
3234 wpa_auth_sta_ft_tk_already_set(sta->wpa_sm),
3235 wpa_auth_sta_fils_tk_already_set(sta->wpa_sm));
3236
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02003237 if (!sta->added_unassoc &&
3238 (!(sta->flags & WLAN_STA_AUTHORIZED) ||
Hai Shalom74f70d42019-02-11 14:42:39 -08003239 (reassoc && sta->ft_over_ds && sta->auth_alg == WLAN_AUTH_FT) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003240 (!wpa_auth_sta_ft_tk_already_set(sta->wpa_sm) &&
3241 !wpa_auth_sta_fils_tk_already_set(sta->wpa_sm)))) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003242 hostapd_drv_sta_remove(hapd, sta->addr);
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02003243 wpa_auth_sm_event(sta->wpa_sm, WPA_DRV_STA_REMOVED);
3244 set = 0;
Hai Shalom74f70d42019-02-11 14:42:39 -08003245
3246 /* Do not allow the FT-over-DS exception to be used more than
3247 * once per authentication exchange to guarantee a new TK is
3248 * used here */
3249 sta->ft_over_ds = 0;
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02003250 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003251
3252#ifdef CONFIG_IEEE80211N
3253 if (sta->flags & WLAN_STA_HT)
3254 hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
3255#endif /* CONFIG_IEEE80211N */
3256#ifdef CONFIG_IEEE80211AC
3257 if (sta->flags & WLAN_STA_VHT)
3258 hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
3259#endif /* CONFIG_IEEE80211AC */
3260
3261 /*
3262 * Add the station with forced WLAN_STA_ASSOC flag. The sta->flags
3263 * will be set when the ACK frame for the (Re)Association Response frame
3264 * is processed (TX status driver event).
3265 */
3266 if (hostapd_sta_add(hapd, sta->addr, sta->aid, sta->capability,
3267 sta->supported_rates, sta->supported_rates_len,
3268 sta->listen_interval,
3269 sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
3270 sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
3271 sta->flags | WLAN_STA_ASSOC, sta->qosinfo,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003272 sta->vht_opmode, sta->p2p_ie ? 1 : 0,
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02003273 set)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003274 hostapd_logger(hapd, sta->addr,
3275 HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE,
3276 "Could not %s STA to kernel driver",
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02003277 set ? "set" : "add");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003278
3279 if (sta->added_unassoc) {
3280 hostapd_drv_sta_remove(hapd, sta->addr);
3281 sta->added_unassoc = 0;
3282 }
3283
3284 return -1;
3285 }
3286
3287 sta->added_unassoc = 0;
3288
3289 return 0;
3290}
3291
3292
3293static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
Dmitry Shmidt29333592017-01-09 12:27:11 -08003294 const u8 *addr, u16 status_code, int reassoc,
Hai Shalom74f70d42019-02-11 14:42:39 -08003295 const u8 *ies, size_t ies_len, int rssi)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003296{
3297 int send_len;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003298 u8 *buf;
3299 size_t buflen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003300 struct ieee80211_mgmt *reply;
3301 u8 *p;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003302 u16 res = WLAN_STATUS_SUCCESS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003303
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003304 buflen = sizeof(struct ieee80211_mgmt) + 1024;
3305#ifdef CONFIG_FILS
3306 if (sta && sta->fils_hlp_resp)
3307 buflen += wpabuf_len(sta->fils_hlp_resp);
3308#endif /* CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003309#ifdef CONFIG_OWE
3310 if (sta && (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE))
3311 buflen += 150;
3312#endif /* CONFIG_OWE */
Hai Shalom021b0b52019-04-10 11:17:58 -07003313#ifdef CONFIG_DPP2
3314 if (sta && sta->dpp_pfs)
3315 buflen += 5 + sta->dpp_pfs->curve->prime_len;
3316#endif /* CONFIG_DPP2 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003317 buf = os_zalloc(buflen);
3318 if (!buf) {
3319 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3320 goto done;
3321 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003322 reply = (struct ieee80211_mgmt *) buf;
3323 reply->frame_control =
3324 IEEE80211_FC(WLAN_FC_TYPE_MGMT,
3325 (reassoc ? WLAN_FC_STYPE_REASSOC_RESP :
3326 WLAN_FC_STYPE_ASSOC_RESP));
Dmitry Shmidt29333592017-01-09 12:27:11 -08003327 os_memcpy(reply->da, addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003328 os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
3329 os_memcpy(reply->bssid, hapd->own_addr, ETH_ALEN);
3330
3331 send_len = IEEE80211_HDRLEN;
3332 send_len += sizeof(reply->u.assoc_resp);
3333 reply->u.assoc_resp.capab_info =
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003334 host_to_le16(hostapd_own_capab_info(hapd));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003335 reply->u.assoc_resp.status_code = host_to_le16(status_code);
Dmitry Shmidt29333592017-01-09 12:27:11 -08003336
3337 reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0) |
3338 BIT(14) | BIT(15));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003339 /* Supported rates */
3340 p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable);
3341 /* Extended supported rates */
3342 p = hostapd_eid_ext_supp_rates(hapd, p);
3343
Hai Shalom74f70d42019-02-11 14:42:39 -08003344#ifdef CONFIG_MBO
3345 if (status_code == WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS &&
3346 rssi != 0) {
3347 int delta = hapd->iconf->rssi_reject_assoc_rssi - rssi;
3348
3349 p = hostapd_eid_mbo_rssi_assoc_rej(hapd, p, buf + buflen - p,
3350 delta);
3351 }
3352#endif /* CONFIG_MBO */
3353
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003354#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt29333592017-01-09 12:27:11 -08003355 if (sta && status_code == WLAN_STATUS_SUCCESS) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003356 /* IEEE 802.11r: Mobility Domain Information, Fast BSS
3357 * Transition Information, RSN, [RIC Response] */
3358 p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003359 buf + buflen - p,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003360 sta->auth_alg, ies, ies_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003361 if (!p) {
3362 wpa_printf(MSG_DEBUG,
3363 "FT: Failed to write AssocResp IEs");
3364 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3365 goto done;
3366 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003367 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003368#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003369
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003370#ifdef CONFIG_OWE
Hai Shalom74f70d42019-02-11 14:42:39 -08003371 if (sta && status_code == WLAN_STATUS_SUCCESS &&
3372 (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003373 p = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, p,
3374 buf + buflen - p,
3375 ies, ies_len);
3376#endif /* CONFIG_OWE */
3377
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003378#ifdef CONFIG_IEEE80211W
Dmitry Shmidt29333592017-01-09 12:27:11 -08003379 if (sta && status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003380 p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
3381#endif /* CONFIG_IEEE80211W */
3382
3383#ifdef CONFIG_IEEE80211N
3384 p = hostapd_eid_ht_capabilities(hapd, p);
3385 p = hostapd_eid_ht_operation(hapd, p);
3386#endif /* CONFIG_IEEE80211N */
3387
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003388#ifdef CONFIG_IEEE80211AC
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003389 if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
Dmitry Shmidt7d175302016-09-06 13:11:34 -07003390 u32 nsts = 0, sta_nsts;
3391
Dmitry Shmidt29333592017-01-09 12:27:11 -08003392 if (sta && hapd->conf->use_sta_nsts && sta->vht_capabilities) {
Dmitry Shmidt7d175302016-09-06 13:11:34 -07003393 struct ieee80211_vht_capabilities *capa;
3394
3395 nsts = (hapd->iface->conf->vht_capab >>
3396 VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7;
3397 capa = sta->vht_capabilities;
3398 sta_nsts = (le_to_host32(capa->vht_capabilities_info) >>
3399 VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7;
3400
3401 if (nsts < sta_nsts)
3402 nsts = 0;
3403 else
3404 nsts = sta_nsts;
3405 }
3406 p = hostapd_eid_vht_capabilities(hapd, p, nsts);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003407 p = hostapd_eid_vht_operation(hapd, p);
3408 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003409#endif /* CONFIG_IEEE80211AC */
3410
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003411 p = hostapd_eid_ext_capab(hapd, p);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003412 p = hostapd_eid_bss_max_idle_period(hapd, p);
Dmitry Shmidt29333592017-01-09 12:27:11 -08003413 if (sta && sta->qos_map_enabled)
Dmitry Shmidt051af732013-10-22 13:52:46 -07003414 p = hostapd_eid_qos_map_set(hapd, p);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003415
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003416#ifdef CONFIG_FST
3417 if (hapd->iface->fst_ies) {
3418 os_memcpy(p, wpabuf_head(hapd->iface->fst_ies),
3419 wpabuf_len(hapd->iface->fst_ies));
3420 p += wpabuf_len(hapd->iface->fst_ies);
3421 }
3422#endif /* CONFIG_FST */
3423
Hai Shalom021b0b52019-04-10 11:17:58 -07003424#ifdef CONFIG_OWE
3425 if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
3426 sta && sta->owe_ecdh && status_code == WLAN_STATUS_SUCCESS &&
3427 wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE) {
3428 struct wpabuf *pub;
3429
3430 pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
3431 if (!pub) {
3432 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3433 goto done;
3434 }
3435 /* OWE Diffie-Hellman Parameter element */
3436 *p++ = WLAN_EID_EXTENSION; /* Element ID */
3437 *p++ = 1 + 2 + wpabuf_len(pub); /* Length */
3438 *p++ = WLAN_EID_EXT_OWE_DH_PARAM; /* Element ID Extension */
3439 WPA_PUT_LE16(p, sta->owe_group);
3440 p += 2;
3441 os_memcpy(p, wpabuf_head(pub), wpabuf_len(pub));
3442 p += wpabuf_len(pub);
3443 wpabuf_free(pub);
3444 }
3445#endif /* CONFIG_OWE */
3446
3447#ifdef CONFIG_DPP2
3448 if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) &&
3449 sta && sta->dpp_pfs && status_code == WLAN_STATUS_SUCCESS &&
3450 wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP) {
3451 os_memcpy(p, wpabuf_head(sta->dpp_pfs->ie),
3452 wpabuf_len(sta->dpp_pfs->ie));
3453 p += wpabuf_len(sta->dpp_pfs->ie);
3454 }
3455#endif /* CONFIG_DPP2 */
3456
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003457#ifdef CONFIG_IEEE80211AC
Dmitry Shmidt29333592017-01-09 12:27:11 -08003458 if (sta && hapd->conf->vendor_vht && (sta->flags & WLAN_STA_VENDOR_VHT))
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003459 p = hostapd_eid_vendor_vht(hapd, p);
3460#endif /* CONFIG_IEEE80211AC */
3461
Dmitry Shmidt29333592017-01-09 12:27:11 -08003462 if (sta && (sta->flags & WLAN_STA_WMM))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003463 p = hostapd_eid_wmm(hapd, p);
3464
3465#ifdef CONFIG_WPS
Dmitry Shmidt29333592017-01-09 12:27:11 -08003466 if (sta &&
3467 ((sta->flags & WLAN_STA_WPS) ||
3468 ((sta->flags & WLAN_STA_MAYBE_WPS) && hapd->conf->wpa))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003469 struct wpabuf *wps = wps_build_assoc_resp_ie();
3470 if (wps) {
3471 os_memcpy(p, wpabuf_head(wps), wpabuf_len(wps));
3472 p += wpabuf_len(wps);
3473 wpabuf_free(wps);
3474 }
3475 }
3476#endif /* CONFIG_WPS */
3477
Hai Shalom74f70d42019-02-11 14:42:39 -08003478 if (sta && (sta->flags & WLAN_STA_MULTI_AP))
3479 p = hostapd_eid_multi_ap(hapd, p);
3480
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003481#ifdef CONFIG_P2P
Dmitry Shmidt29333592017-01-09 12:27:11 -08003482 if (sta && sta->p2p_ie && hapd->p2p_group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003483 struct wpabuf *p2p_resp_ie;
3484 enum p2p_status_code status;
3485 switch (status_code) {
3486 case WLAN_STATUS_SUCCESS:
3487 status = P2P_SC_SUCCESS;
3488 break;
3489 case WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA:
3490 status = P2P_SC_FAIL_LIMIT_REACHED;
3491 break;
3492 default:
3493 status = P2P_SC_FAIL_INVALID_PARAMS;
3494 break;
3495 }
3496 p2p_resp_ie = p2p_group_assoc_resp_ie(hapd->p2p_group, status);
3497 if (p2p_resp_ie) {
3498 os_memcpy(p, wpabuf_head(p2p_resp_ie),
3499 wpabuf_len(p2p_resp_ie));
3500 p += wpabuf_len(p2p_resp_ie);
3501 wpabuf_free(p2p_resp_ie);
3502 }
3503 }
3504#endif /* CONFIG_P2P */
3505
3506#ifdef CONFIG_P2P_MANAGER
3507 if (hapd->conf->p2p & P2P_MANAGE)
3508 p = hostapd_eid_p2p_manage(hapd, p);
3509#endif /* CONFIG_P2P_MANAGER */
3510
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003511 p = hostapd_eid_mbo(hapd, p, buf + buflen - p);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003512
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003513 if (hapd->conf->assocresp_elements &&
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003514 (size_t) (buf + buflen - p) >=
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003515 wpabuf_len(hapd->conf->assocresp_elements)) {
3516 os_memcpy(p, wpabuf_head(hapd->conf->assocresp_elements),
3517 wpabuf_len(hapd->conf->assocresp_elements));
3518 p += wpabuf_len(hapd->conf->assocresp_elements);
3519 }
3520
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003521 send_len += p - reply->u.assoc_resp.variable;
3522
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003523#ifdef CONFIG_FILS
Dmitry Shmidt29333592017-01-09 12:27:11 -08003524 if (sta &&
3525 (sta->auth_alg == WLAN_AUTH_FILS_SK ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003526 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
3527 sta->auth_alg == WLAN_AUTH_FILS_PK) &&
3528 status_code == WLAN_STATUS_SUCCESS) {
3529 struct ieee802_11_elems elems;
3530
3531 if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) ==
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003532 ParseFailed || !elems.fils_session) {
3533 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3534 goto done;
3535 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003536
3537 /* FILS Session */
3538 *p++ = WLAN_EID_EXTENSION; /* Element ID */
3539 *p++ = 1 + FILS_SESSION_LEN; /* Length */
3540 *p++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */
3541 os_memcpy(p, elems.fils_session, FILS_SESSION_LEN);
3542 send_len += 2 + 1 + FILS_SESSION_LEN;
3543
3544 send_len = fils_encrypt_assoc(sta->wpa_sm, buf, send_len,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003545 buflen, sta->fils_hlp_resp);
3546 if (send_len < 0) {
3547 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3548 goto done;
3549 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003550 }
3551#endif /* CONFIG_FILS */
3552
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003553 if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003554 wpa_printf(MSG_INFO, "Failed to send assoc resp: %s",
3555 strerror(errno));
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003556 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003557 }
3558
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003559done:
3560 os_free(buf);
3561 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003562}
3563
3564
Roshan Pius3a1667e2018-07-03 15:17:14 -07003565#ifdef CONFIG_OWE
3566u8 * owe_assoc_req_process(struct hostapd_data *hapd, struct sta_info *sta,
3567 const u8 *owe_dh, u8 owe_dh_len,
3568 u8 *owe_buf, size_t owe_buf_len, u16 *reason)
3569{
3570#ifdef CONFIG_TESTING_OPTIONS
3571 if (hapd->conf->own_ie_override) {
3572 wpa_printf(MSG_DEBUG, "OWE: Using IE override");
3573 *reason = WLAN_STATUS_SUCCESS;
3574 return wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
3575 owe_buf_len, NULL, 0);
3576 }
3577#endif /* CONFIG_TESTING_OPTIONS */
3578
3579 if (wpa_auth_sta_get_pmksa(sta->wpa_sm)) {
3580 wpa_printf(MSG_DEBUG, "OWE: Using PMKSA caching");
3581 owe_buf = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
3582 owe_buf_len, NULL, 0);
3583 *reason = WLAN_STATUS_SUCCESS;
3584 return owe_buf;
3585 }
3586
3587 *reason = owe_process_assoc_req(hapd, sta, owe_dh, owe_dh_len);
3588 if (*reason != WLAN_STATUS_SUCCESS)
3589 return NULL;
3590
3591 owe_buf = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
3592 owe_buf_len, NULL, 0);
3593
3594 if (sta->owe_ecdh && owe_buf) {
3595 struct wpabuf *pub;
3596
3597 pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
3598 if (!pub) {
3599 *reason = WLAN_STATUS_UNSPECIFIED_FAILURE;
3600 return owe_buf;
3601 }
3602
3603 /* OWE Diffie-Hellman Parameter element */
3604 *owe_buf++ = WLAN_EID_EXTENSION; /* Element ID */
3605 *owe_buf++ = 1 + 2 + wpabuf_len(pub); /* Length */
3606 *owe_buf++ = WLAN_EID_EXT_OWE_DH_PARAM; /* Element ID Extension
3607 */
3608 WPA_PUT_LE16(owe_buf, sta->owe_group);
3609 owe_buf += 2;
3610 os_memcpy(owe_buf, wpabuf_head(pub), wpabuf_len(pub));
3611 owe_buf += wpabuf_len(pub);
3612 wpabuf_free(pub);
3613 }
3614
3615 return owe_buf;
3616}
3617#endif /* CONFIG_OWE */
3618
3619
Paul Stewart092955c2017-02-06 09:13:09 -08003620#ifdef CONFIG_FILS
3621
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003622void fils_hlp_finish_assoc(struct hostapd_data *hapd, struct sta_info *sta)
Paul Stewart092955c2017-02-06 09:13:09 -08003623{
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003624 u16 reply_res;
Paul Stewart092955c2017-02-06 09:13:09 -08003625
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003626 wpa_printf(MSG_DEBUG, "FILS: Finish association with " MACSTR,
3627 MAC2STR(sta->addr));
3628 eloop_cancel_timeout(fils_hlp_timeout, hapd, sta);
3629 if (!sta->fils_pending_assoc_req)
Paul Stewart092955c2017-02-06 09:13:09 -08003630 return;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003631 reply_res = send_assoc_resp(hapd, sta, sta->addr, WLAN_STATUS_SUCCESS,
3632 sta->fils_pending_assoc_is_reassoc,
3633 sta->fils_pending_assoc_req,
Hai Shalom74f70d42019-02-11 14:42:39 -08003634 sta->fils_pending_assoc_req_len, 0);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003635 os_free(sta->fils_pending_assoc_req);
3636 sta->fils_pending_assoc_req = NULL;
3637 sta->fils_pending_assoc_req_len = 0;
3638 wpabuf_free(sta->fils_hlp_resp);
3639 sta->fils_hlp_resp = NULL;
3640 wpabuf_free(sta->hlp_dhcp_discover);
3641 sta->hlp_dhcp_discover = NULL;
Paul Stewart092955c2017-02-06 09:13:09 -08003642
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003643 /*
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003644 * Remove the station in case transmission of a success response fails.
3645 * At this point the station was already added associated to the driver.
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003646 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003647 if (reply_res != WLAN_STATUS_SUCCESS)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003648 hostapd_drv_sta_remove(hapd, sta->addr);
Paul Stewart092955c2017-02-06 09:13:09 -08003649}
3650
3651
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003652void fils_hlp_timeout(void *eloop_ctx, void *eloop_data)
Paul Stewart092955c2017-02-06 09:13:09 -08003653{
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003654 struct hostapd_data *hapd = eloop_ctx;
3655 struct sta_info *sta = eloop_data;
Paul Stewart092955c2017-02-06 09:13:09 -08003656
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003657 wpa_printf(MSG_DEBUG,
3658 "FILS: HLP response timeout - continue with association response for "
3659 MACSTR, MAC2STR(sta->addr));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003660 if (sta->fils_drv_assoc_finish)
3661 hostapd_notify_assoc_fils_finish(hapd, sta);
3662 else
3663 fils_hlp_finish_assoc(hapd, sta);
Paul Stewart092955c2017-02-06 09:13:09 -08003664}
3665
3666#endif /* CONFIG_FILS */
3667
3668
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003669static void handle_assoc(struct hostapd_data *hapd,
3670 const struct ieee80211_mgmt *mgmt, size_t len,
Hai Shalom74f70d42019-02-11 14:42:39 -08003671 int reassoc, int rssi)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003672{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003673 u16 capab_info, listen_interval, seq_ctrl, fc;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003674 u16 resp = WLAN_STATUS_SUCCESS, reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003675 const u8 *pos;
3676 int left, i;
3677 struct sta_info *sta;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003678 u8 *tmp = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003679 struct hostapd_sta_wpa_psk_short *psk = NULL;
3680 char *identity = NULL;
3681 char *radius_cui = NULL;
3682#ifdef CONFIG_FILS
3683 int delay_assoc = 0;
3684#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003685
3686 if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
3687 sizeof(mgmt->u.assoc_req))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003688 wpa_printf(MSG_INFO, "handle_assoc(reassoc=%d) - too short payload (len=%lu)",
3689 reassoc, (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003690 return;
3691 }
3692
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003693#ifdef CONFIG_TESTING_OPTIONS
3694 if (reassoc) {
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07003695 if (hapd->iconf->ignore_reassoc_probability > 0.0 &&
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003696 drand48() < hapd->iconf->ignore_reassoc_probability) {
3697 wpa_printf(MSG_INFO,
3698 "TESTING: ignoring reassoc request from "
3699 MACSTR, MAC2STR(mgmt->sa));
3700 return;
3701 }
3702 } else {
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07003703 if (hapd->iconf->ignore_assoc_probability > 0.0 &&
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003704 drand48() < hapd->iconf->ignore_assoc_probability) {
3705 wpa_printf(MSG_INFO,
3706 "TESTING: ignoring assoc request from "
3707 MACSTR, MAC2STR(mgmt->sa));
3708 return;
3709 }
3710 }
3711#endif /* CONFIG_TESTING_OPTIONS */
3712
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003713 fc = le_to_host16(mgmt->frame_control);
3714 seq_ctrl = le_to_host16(mgmt->seq_ctrl);
3715
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003716 if (reassoc) {
3717 capab_info = le_to_host16(mgmt->u.reassoc_req.capab_info);
3718 listen_interval = le_to_host16(
3719 mgmt->u.reassoc_req.listen_interval);
3720 wpa_printf(MSG_DEBUG, "reassociation request: STA=" MACSTR
3721 " capab_info=0x%02x listen_interval=%d current_ap="
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003722 MACSTR " seq_ctrl=0x%x%s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003723 MAC2STR(mgmt->sa), capab_info, listen_interval,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003724 MAC2STR(mgmt->u.reassoc_req.current_ap),
3725 seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003726 left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.reassoc_req));
3727 pos = mgmt->u.reassoc_req.variable;
3728 } else {
3729 capab_info = le_to_host16(mgmt->u.assoc_req.capab_info);
3730 listen_interval = le_to_host16(
3731 mgmt->u.assoc_req.listen_interval);
3732 wpa_printf(MSG_DEBUG, "association request: STA=" MACSTR
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003733 " capab_info=0x%02x listen_interval=%d "
3734 "seq_ctrl=0x%x%s",
3735 MAC2STR(mgmt->sa), capab_info, listen_interval,
3736 seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003737 left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req));
3738 pos = mgmt->u.assoc_req.variable;
3739 }
3740
3741 sta = ap_get_sta(hapd, mgmt->sa);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003742#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003743 if (sta && sta->auth_alg == WLAN_AUTH_FT &&
3744 (sta->flags & WLAN_STA_AUTH) == 0) {
3745 wpa_printf(MSG_DEBUG, "FT: Allow STA " MACSTR " to associate "
3746 "prior to authentication since it is using "
3747 "over-the-DS FT", MAC2STR(mgmt->sa));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003748
3749 /*
3750 * Mark station as authenticated, to avoid adding station
3751 * entry in the driver as associated and not authenticated
3752 */
3753 sta->flags |= WLAN_STA_AUTH;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003754 } else
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003755#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003756 if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) {
Dmitry Shmidt29333592017-01-09 12:27:11 -08003757 if (hapd->iface->current_mode &&
3758 hapd->iface->current_mode->mode ==
3759 HOSTAPD_MODE_IEEE80211AD) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003760 int acl_res;
3761 u32 session_timeout, acct_interim_interval;
3762 struct vlan_description vlan_id;
3763
3764 acl_res = ieee802_11_allowed_address(
3765 hapd, mgmt->sa, (const u8 *) mgmt, len,
3766 &session_timeout, &acct_interim_interval,
Roshan Pius3a1667e2018-07-03 15:17:14 -07003767 &vlan_id, &psk, &identity, &radius_cui, 0);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003768 if (acl_res == HOSTAPD_ACL_REJECT) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003769 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
3770 "Ignore Association Request frame from "
3771 MACSTR " due to ACL reject",
3772 MAC2STR(mgmt->sa));
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003773 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
3774 goto fail;
3775 }
3776 if (acl_res == HOSTAPD_ACL_PENDING)
3777 return;
3778
Dmitry Shmidt29333592017-01-09 12:27:11 -08003779 /* DMG/IEEE 802.11ad does not use authentication.
3780 * Allocate sta entry upon association. */
3781 sta = ap_sta_add(hapd, mgmt->sa);
3782 if (!sta) {
3783 hostapd_logger(hapd, mgmt->sa,
3784 HOSTAPD_MODULE_IEEE80211,
3785 HOSTAPD_LEVEL_INFO,
3786 "Failed to add STA");
3787 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
3788 goto fail;
3789 }
3790
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003791 acl_res = ieee802_11_set_radius_info(
3792 hapd, sta, acl_res, session_timeout,
3793 acct_interim_interval, &vlan_id, &psk,
3794 &identity, &radius_cui);
3795 if (acl_res) {
3796 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
3797 goto fail;
3798 }
3799
Dmitry Shmidt29333592017-01-09 12:27:11 -08003800 hostapd_logger(hapd, sta->addr,
3801 HOSTAPD_MODULE_IEEE80211,
3802 HOSTAPD_LEVEL_DEBUG,
3803 "Skip authentication for DMG/IEEE 802.11ad");
3804 sta->flags |= WLAN_STA_AUTH;
3805 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
3806 sta->auth_alg = WLAN_AUTH_OPEN;
3807 } else {
3808 hostapd_logger(hapd, mgmt->sa,
3809 HOSTAPD_MODULE_IEEE80211,
3810 HOSTAPD_LEVEL_INFO,
3811 "Station tried to associate before authentication (aid=%d flags=0x%x)",
3812 sta ? sta->aid : -1,
3813 sta ? sta->flags : 0);
3814 send_deauth(hapd, mgmt->sa,
3815 WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
3816 return;
3817 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003818 }
3819
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003820 if ((fc & WLAN_FC_RETRY) &&
3821 sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ &&
3822 sta->last_seq_ctrl == seq_ctrl &&
Paul Stewart092955c2017-02-06 09:13:09 -08003823 sta->last_subtype == (reassoc ? WLAN_FC_STYPE_REASSOC_REQ :
3824 WLAN_FC_STYPE_ASSOC_REQ)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003825 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3826 HOSTAPD_LEVEL_DEBUG,
3827 "Drop repeated association frame seq_ctrl=0x%x",
3828 seq_ctrl);
3829 return;
3830 }
3831 sta->last_seq_ctrl = seq_ctrl;
3832 sta->last_subtype = reassoc ? WLAN_FC_STYPE_REASSOC_REQ :
3833 WLAN_FC_STYPE_ASSOC_REQ;
3834
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003835 if (hapd->tkip_countermeasures) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003836 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003837 goto fail;
3838 }
3839
3840 if (listen_interval > hapd->conf->max_listen_interval) {
3841 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
3842 HOSTAPD_LEVEL_DEBUG,
3843 "Too large Listen Interval (%d)",
3844 listen_interval);
3845 resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE;
3846 goto fail;
3847 }
3848
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003849#ifdef CONFIG_MBO
3850 if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) {
3851 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
3852 goto fail;
3853 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003854
3855 if (hapd->iconf->rssi_reject_assoc_rssi && rssi &&
3856 rssi < hapd->iconf->rssi_reject_assoc_rssi &&
3857 (sta->auth_rssi == 0 ||
3858 sta->auth_rssi < hapd->iconf->rssi_reject_assoc_rssi)) {
3859 resp = WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS;
3860 goto fail;
3861 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003862#endif /* CONFIG_MBO */
3863
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003864 /*
3865 * sta->capability is used in check_assoc_ies() for RRM enabled
3866 * capability element.
3867 */
3868 sta->capability = capab_info;
3869
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003870#ifdef CONFIG_FILS
3871 if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
3872 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
3873 sta->auth_alg == WLAN_AUTH_FILS_PK) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003874 int res;
3875
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003876 /* The end of the payload is encrypted. Need to decrypt it
3877 * before parsing. */
3878
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003879 tmp = os_memdup(pos, left);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003880 if (!tmp) {
3881 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
3882 goto fail;
3883 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003884
Roshan Pius3a1667e2018-07-03 15:17:14 -07003885 res = fils_decrypt_assoc(sta->wpa_sm, sta->fils_session, mgmt,
3886 len, tmp, left);
3887 if (res < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003888 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
3889 goto fail;
3890 }
3891 pos = tmp;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003892 left = res;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003893 }
3894#endif /* CONFIG_FILS */
3895
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003896 /* followed by SSID and Supported rates; and HT capabilities if 802.11n
3897 * is used */
3898 resp = check_assoc_ies(hapd, sta, pos, left, reassoc);
3899 if (resp != WLAN_STATUS_SUCCESS)
3900 goto fail;
3901
3902 if (hostapd_get_aid(hapd, sta) < 0) {
3903 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
3904 HOSTAPD_LEVEL_INFO, "No room for more AIDs");
3905 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
3906 goto fail;
3907 }
3908
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003909 sta->listen_interval = listen_interval;
3910
Roshan Pius3a1667e2018-07-03 15:17:14 -07003911 if (hapd->iface->current_mode &&
3912 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003913 sta->flags |= WLAN_STA_NONERP;
3914 for (i = 0; i < sta->supported_rates_len; i++) {
3915 if ((sta->supported_rates[i] & 0x7f) > 22) {
3916 sta->flags &= ~WLAN_STA_NONERP;
3917 break;
3918 }
3919 }
3920 if (sta->flags & WLAN_STA_NONERP && !sta->nonerp_set) {
3921 sta->nonerp_set = 1;
3922 hapd->iface->num_sta_non_erp++;
3923 if (hapd->iface->num_sta_non_erp == 1)
3924 ieee802_11_set_beacons(hapd->iface);
3925 }
3926
3927 if (!(sta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) &&
3928 !sta->no_short_slot_time_set) {
3929 sta->no_short_slot_time_set = 1;
3930 hapd->iface->num_sta_no_short_slot_time++;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003931 if (hapd->iface->current_mode &&
3932 hapd->iface->current_mode->mode ==
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003933 HOSTAPD_MODE_IEEE80211G &&
3934 hapd->iface->num_sta_no_short_slot_time == 1)
3935 ieee802_11_set_beacons(hapd->iface);
3936 }
3937
3938 if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
3939 sta->flags |= WLAN_STA_SHORT_PREAMBLE;
3940 else
3941 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
3942
3943 if (!(sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
3944 !sta->no_short_preamble_set) {
3945 sta->no_short_preamble_set = 1;
3946 hapd->iface->num_sta_no_short_preamble++;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003947 if (hapd->iface->current_mode &&
3948 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003949 && hapd->iface->num_sta_no_short_preamble == 1)
3950 ieee802_11_set_beacons(hapd->iface);
3951 }
3952
3953#ifdef CONFIG_IEEE80211N
3954 update_ht_state(hapd, sta);
3955#endif /* CONFIG_IEEE80211N */
3956
3957 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3958 HOSTAPD_LEVEL_DEBUG,
3959 "association OK (aid %d)", sta->aid);
3960 /* Station will be marked associated, after it acknowledges AssocResp
3961 */
3962 sta->flags |= WLAN_STA_ASSOC_REQ_OK;
3963
3964#ifdef CONFIG_IEEE80211W
3965 if ((sta->flags & WLAN_STA_MFP) && sta->sa_query_timed_out) {
3966 wpa_printf(MSG_DEBUG, "Allowing %sassociation after timed out "
3967 "SA Query procedure", reassoc ? "re" : "");
3968 /* TODO: Send a protected Disassociate frame to the STA using
3969 * the old key and Reason Code "Previous Authentication no
3970 * longer valid". Make sure this is only sent protected since
3971 * unprotected frame would be received by the STA that is now
3972 * trying to associate.
3973 */
3974 }
3975#endif /* CONFIG_IEEE80211W */
3976
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003977 /* Make sure that the previously registered inactivity timer will not
3978 * remove the STA immediately. */
3979 sta->timeout_next = STA_NULLFUNC;
3980
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003981#ifdef CONFIG_TAXONOMY
3982 taxonomy_sta_info_assoc_req(hapd, sta, pos, left);
3983#endif /* CONFIG_TAXONOMY */
3984
Dmitry Shmidt29333592017-01-09 12:27:11 -08003985 sta->pending_wds_enable = 0;
3986
Paul Stewart092955c2017-02-06 09:13:09 -08003987#ifdef CONFIG_FILS
3988 if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
3989 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003990 sta->auth_alg == WLAN_AUTH_FILS_PK) {
3991 if (fils_process_hlp(hapd, sta, pos, left) > 0)
3992 delay_assoc = 1;
3993 }
Paul Stewart092955c2017-02-06 09:13:09 -08003994#endif /* CONFIG_FILS */
3995
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003996 fail:
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003997 os_free(identity);
3998 os_free(radius_cui);
3999 hostapd_free_psk_list(psk);
4000
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004001 /*
4002 * In case of a successful response, add the station to the driver.
4003 * Otherwise, the kernel may ignore Data frames before we process the
4004 * ACK frame (TX status). In case of a failure, this station will be
4005 * removed.
4006 *
4007 * Note that this is not compliant with the IEEE 802.11 standard that
4008 * states that a non-AP station should transition into the
4009 * authenticated/associated state only after the station acknowledges
4010 * the (Re)Association Response frame. However, still do this as:
4011 *
4012 * 1. In case the station does not acknowledge the (Re)Association
4013 * Response frame, it will be removed.
4014 * 2. Data frames will be dropped in the kernel until the station is
4015 * set into authorized state, and there are no significant known
4016 * issues with processing other non-Data Class 3 frames during this
4017 * window.
4018 */
Hai Shalom74f70d42019-02-11 14:42:39 -08004019 if (resp == WLAN_STATUS_SUCCESS && sta &&
4020 add_associated_sta(hapd, sta, reassoc))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004021 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
4022
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004023#ifdef CONFIG_FILS
Hai Shalom74f70d42019-02-11 14:42:39 -08004024 if (sta && delay_assoc && resp == WLAN_STATUS_SUCCESS &&
4025 eloop_is_timeout_registered(fils_hlp_timeout, hapd, sta) &&
4026 sta->fils_pending_assoc_req) {
4027 /* Do not reschedule fils_hlp_timeout in case the station
4028 * retransmits (Re)Association Request frame while waiting for
4029 * the previously started FILS HLP wait, so that the timeout can
4030 * be determined from the first pending attempt. */
4031 wpa_printf(MSG_DEBUG,
4032 "FILS: Continue waiting for HLP processing before sending (Re)Association Response frame to "
4033 MACSTR, MAC2STR(sta->addr));
4034 os_free(tmp);
4035 return;
4036 }
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004037 if (sta) {
4038 eloop_cancel_timeout(fils_hlp_timeout, hapd, sta);
4039 os_free(sta->fils_pending_assoc_req);
4040 sta->fils_pending_assoc_req = NULL;
4041 sta->fils_pending_assoc_req_len = 0;
4042 wpabuf_free(sta->fils_hlp_resp);
4043 sta->fils_hlp_resp = NULL;
4044 }
4045 if (sta && delay_assoc && resp == WLAN_STATUS_SUCCESS) {
4046 sta->fils_pending_assoc_req = tmp;
4047 sta->fils_pending_assoc_req_len = left;
4048 sta->fils_pending_assoc_is_reassoc = reassoc;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004049 sta->fils_drv_assoc_finish = 0;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004050 wpa_printf(MSG_DEBUG,
4051 "FILS: Waiting for HLP processing before sending (Re)Association Response frame to "
4052 MACSTR, MAC2STR(sta->addr));
4053 eloop_cancel_timeout(fils_hlp_timeout, hapd, sta);
4054 eloop_register_timeout(0, hapd->conf->fils_hlp_wait_time * 1024,
4055 fils_hlp_timeout, hapd, sta);
4056 return;
4057 }
4058#endif /* CONFIG_FILS */
4059
Dmitry Shmidt29333592017-01-09 12:27:11 -08004060 reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc, pos,
Hai Shalom74f70d42019-02-11 14:42:39 -08004061 left, rssi);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004062 os_free(tmp);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004063
4064 /*
4065 * Remove the station in case tranmission of a success response fails
4066 * (the STA was added associated to the driver) or if the station was
4067 * previously added unassociated.
4068 */
Dmitry Shmidt29333592017-01-09 12:27:11 -08004069 if (sta && ((reply_res != WLAN_STATUS_SUCCESS &&
4070 resp == WLAN_STATUS_SUCCESS) || sta->added_unassoc)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004071 hostapd_drv_sta_remove(hapd, sta->addr);
4072 sta->added_unassoc = 0;
4073 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004074}
4075
4076
4077static void handle_disassoc(struct hostapd_data *hapd,
4078 const struct ieee80211_mgmt *mgmt, size_t len)
4079{
4080 struct sta_info *sta;
4081
4082 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004083 wpa_printf(MSG_INFO, "handle_disassoc - too short payload (len=%lu)",
4084 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004085 return;
4086 }
4087
4088 wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d",
4089 MAC2STR(mgmt->sa),
4090 le_to_host16(mgmt->u.disassoc.reason_code));
4091
4092 sta = ap_get_sta(hapd, mgmt->sa);
4093 if (sta == NULL) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004094 wpa_printf(MSG_INFO, "Station " MACSTR " trying to disassociate, but it is not associated",
4095 MAC2STR(mgmt->sa));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004096 return;
4097 }
4098
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004099 ap_sta_set_authorized(hapd, sta, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004100 sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004101 sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004102 wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
4103 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4104 HOSTAPD_LEVEL_INFO, "disassociated");
4105 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
4106 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
4107 /* Stop Accounting and IEEE 802.1X sessions, but leave the STA
4108 * authenticated. */
4109 accounting_sta_stop(hapd, sta);
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004110 ieee802_1x_free_station(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004111 if (sta->ipaddr)
4112 hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
4113 ap_sta_ip6addr_del(hapd, sta);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004114 hostapd_drv_sta_remove(hapd, sta->addr);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004115 sta->added_unassoc = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004116
4117 if (sta->timeout_next == STA_NULLFUNC ||
4118 sta->timeout_next == STA_DISASSOC) {
4119 sta->timeout_next = STA_DEAUTH;
4120 eloop_cancel_timeout(ap_handle_timer, hapd, sta);
4121 eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
4122 hapd, sta);
4123 }
4124
4125 mlme_disassociate_indication(
4126 hapd, sta, le_to_host16(mgmt->u.disassoc.reason_code));
Dmitry Shmidt29333592017-01-09 12:27:11 -08004127
4128 /* DMG/IEEE 802.11ad does not use deauthication. Deallocate sta upon
4129 * disassociation. */
4130 if (hapd->iface->current_mode &&
4131 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD) {
4132 sta->flags &= ~WLAN_STA_AUTH;
4133 wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
4134 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4135 HOSTAPD_LEVEL_DEBUG, "deauthenticated");
4136 ap_free_sta(hapd, sta);
4137 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004138}
4139
4140
4141static void handle_deauth(struct hostapd_data *hapd,
4142 const struct ieee80211_mgmt *mgmt, size_t len)
4143{
4144 struct sta_info *sta;
4145
4146 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004147 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "handle_deauth - too short "
4148 "payload (len=%lu)", (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004149 return;
4150 }
4151
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004152 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "deauthentication: STA=" MACSTR
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004153 " reason_code=%d",
4154 MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code));
4155
4156 sta = ap_get_sta(hapd, mgmt->sa);
4157 if (sta == NULL) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004158 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying "
4159 "to deauthenticate, but it is not authenticated",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004160 MAC2STR(mgmt->sa));
4161 return;
4162 }
4163
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004164 ap_sta_set_authorized(hapd, sta, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004165 sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004166 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
4167 WLAN_STA_ASSOC_REQ_OK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004168 wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
4169 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4170 HOSTAPD_LEVEL_DEBUG, "deauthenticated");
4171 mlme_deauthenticate_indication(
4172 hapd, sta, le_to_host16(mgmt->u.deauth.reason_code));
4173 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
4174 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
4175 ap_free_sta(hapd, sta);
4176}
4177
4178
4179static void handle_beacon(struct hostapd_data *hapd,
4180 const struct ieee80211_mgmt *mgmt, size_t len,
4181 struct hostapd_frame_info *fi)
4182{
4183 struct ieee802_11_elems elems;
4184
4185 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.beacon)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004186 wpa_printf(MSG_INFO, "handle_beacon - too short payload (len=%lu)",
4187 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004188 return;
4189 }
4190
4191 (void) ieee802_11_parse_elems(mgmt->u.beacon.variable,
4192 len - (IEEE80211_HDRLEN +
4193 sizeof(mgmt->u.beacon)), &elems,
4194 0);
4195
4196 ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);
4197}
4198
4199
4200#ifdef CONFIG_IEEE80211W
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004201static int robust_action_frame(u8 category)
4202{
4203 return category != WLAN_ACTION_PUBLIC &&
4204 category != WLAN_ACTION_HT;
4205}
4206#endif /* CONFIG_IEEE80211W */
4207
4208
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004209static int handle_action(struct hostapd_data *hapd,
Roshan Pius3a1667e2018-07-03 15:17:14 -07004210 const struct ieee80211_mgmt *mgmt, size_t len,
4211 unsigned int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004212{
4213 struct sta_info *sta;
Hai Shalom74f70d42019-02-11 14:42:39 -08004214 u8 *action __maybe_unused;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004215
Hai Shalom74f70d42019-02-11 14:42:39 -08004216 if (len < IEEE80211_HDRLEN + 2 + 1) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004217 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
4218 HOSTAPD_LEVEL_DEBUG,
4219 "handle_action - too short payload (len=%lu)",
4220 (unsigned long) len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004221 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004222 }
4223
Hai Shalom74f70d42019-02-11 14:42:39 -08004224 action = (u8 *) &mgmt->u.action.u;
4225 wpa_printf(MSG_DEBUG, "RX_ACTION category %u action %u sa " MACSTR
4226 " da " MACSTR " len %d freq %u",
4227 mgmt->u.action.category, *action,
4228 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), (int) len, freq);
4229
4230 sta = ap_get_sta(hapd, mgmt->sa);
4231
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004232 if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
4233 (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))) {
4234 wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored Action "
4235 "frame (category=%u) from unassociated STA " MACSTR,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004236 mgmt->u.action.category, MAC2STR(mgmt->sa));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004237 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004238 }
4239
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004240#ifdef CONFIG_IEEE80211W
4241 if (sta && (sta->flags & WLAN_STA_MFP) &&
Dmitry Shmidt18463232014-01-24 12:29:41 -08004242 !(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP)) &&
4243 robust_action_frame(mgmt->u.action.category)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004244 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
4245 HOSTAPD_LEVEL_DEBUG,
4246 "Dropped unprotected Robust Action frame from "
4247 "an MFP STA");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004248 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004249 }
4250#endif /* CONFIG_IEEE80211W */
4251
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004252 if (sta) {
4253 u16 fc = le_to_host16(mgmt->frame_control);
4254 u16 seq_ctrl = le_to_host16(mgmt->seq_ctrl);
4255
4256 if ((fc & WLAN_FC_RETRY) &&
4257 sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ &&
4258 sta->last_seq_ctrl == seq_ctrl &&
4259 sta->last_subtype == WLAN_FC_STYPE_ACTION) {
4260 hostapd_logger(hapd, sta->addr,
4261 HOSTAPD_MODULE_IEEE80211,
4262 HOSTAPD_LEVEL_DEBUG,
4263 "Drop repeated action frame seq_ctrl=0x%x",
4264 seq_ctrl);
4265 return 1;
4266 }
4267
4268 sta->last_seq_ctrl = seq_ctrl;
4269 sta->last_subtype = WLAN_FC_STYPE_ACTION;
4270 }
4271
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004272 switch (mgmt->u.action.category) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004273#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004274 case WLAN_ACTION_FT:
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004275 if (!sta ||
4276 wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004277 len - IEEE80211_HDRLEN))
4278 break;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004279 return 1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004280#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004281 case WLAN_ACTION_WMM:
4282 hostapd_wmm_action(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004283 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004284#ifdef CONFIG_IEEE80211W
4285 case WLAN_ACTION_SA_QUERY:
Hai Shalom021b0b52019-04-10 11:17:58 -07004286 ieee802_11_sa_query_action(hapd, mgmt, len);
4287 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004288#endif /* CONFIG_IEEE80211W */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004289#ifdef CONFIG_WNM_AP
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004290 case WLAN_ACTION_WNM:
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004291 ieee802_11_rx_wnm_action_ap(hapd, mgmt, len);
4292 return 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004293#endif /* CONFIG_WNM_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004294#ifdef CONFIG_FST
4295 case WLAN_ACTION_FST:
4296 if (hapd->iface->fst)
4297 fst_rx_action(hapd->iface->fst, mgmt, len);
4298 else
4299 wpa_printf(MSG_DEBUG,
4300 "FST: Ignore FST Action frame - no FST attached");
4301 return 1;
4302#endif /* CONFIG_FST */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004303 case WLAN_ACTION_PUBLIC:
Dmitry Shmidt18463232014-01-24 12:29:41 -08004304 case WLAN_ACTION_PROTECTED_DUAL:
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004305#ifdef CONFIG_IEEE80211N
Dmitry Shmidtcc00d5d2015-05-04 10:34:12 -07004306 if (len >= IEEE80211_HDRLEN + 2 &&
4307 mgmt->u.action.u.public_action.action ==
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004308 WLAN_PA_20_40_BSS_COEX) {
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004309 hostapd_2040_coex_action(hapd, mgmt, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004310 return 1;
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004311 }
4312#endif /* CONFIG_IEEE80211N */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004313#ifdef CONFIG_DPP
4314 if (len >= IEEE80211_HDRLEN + 6 &&
4315 mgmt->u.action.u.vs_public_action.action ==
4316 WLAN_PA_VENDOR_SPECIFIC &&
4317 WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) ==
4318 OUI_WFA &&
4319 mgmt->u.action.u.vs_public_action.variable[0] ==
4320 DPP_OUI_TYPE) {
4321 const u8 *pos, *end;
4322
4323 pos = mgmt->u.action.u.vs_public_action.oui;
4324 end = ((const u8 *) mgmt) + len;
4325 hostapd_dpp_rx_action(hapd, mgmt->sa, pos, end - pos,
Roshan Pius3a1667e2018-07-03 15:17:14 -07004326 freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004327 return 1;
4328 }
4329 if (len >= IEEE80211_HDRLEN + 2 &&
4330 (mgmt->u.action.u.public_action.action ==
4331 WLAN_PA_GAS_INITIAL_RESP ||
4332 mgmt->u.action.u.public_action.action ==
4333 WLAN_PA_GAS_COMEBACK_RESP)) {
4334 const u8 *pos, *end;
4335
4336 pos = &mgmt->u.action.u.public_action.action;
4337 end = ((const u8 *) mgmt) + len;
4338 gas_query_ap_rx(hapd->gas, mgmt->sa,
4339 mgmt->u.action.category,
4340 pos, end - pos, hapd->iface->freq);
4341 return 1;
4342 }
4343#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004344 if (hapd->public_action_cb) {
4345 hapd->public_action_cb(hapd->public_action_cb_ctx,
4346 (u8 *) mgmt, len,
4347 hapd->iface->freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004348 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004349 if (hapd->public_action_cb2) {
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004350 hapd->public_action_cb2(hapd->public_action_cb2_ctx,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004351 (u8 *) mgmt, len,
4352 hapd->iface->freq);
4353 }
4354 if (hapd->public_action_cb || hapd->public_action_cb2)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004355 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004356 break;
4357 case WLAN_ACTION_VENDOR_SPECIFIC:
4358 if (hapd->vendor_action_cb) {
4359 if (hapd->vendor_action_cb(hapd->vendor_action_cb_ctx,
4360 (u8 *) mgmt, len,
4361 hapd->iface->freq) == 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004362 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004363 }
4364 break;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004365 case WLAN_ACTION_RADIO_MEASUREMENT:
4366 hostapd_handle_radio_measurement(hapd, (const u8 *) mgmt, len);
4367 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004368 }
4369
4370 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
4371 HOSTAPD_LEVEL_DEBUG,
4372 "handle_action - unknown action category %d or invalid "
4373 "frame",
4374 mgmt->u.action.category);
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07004375 if (!is_multicast_ether_addr(mgmt->da) &&
4376 !(mgmt->u.action.category & 0x80) &&
4377 !is_multicast_ether_addr(mgmt->sa)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004378 struct ieee80211_mgmt *resp;
4379
4380 /*
4381 * IEEE 802.11-REVma/D9.0 - 7.3.1.11
4382 * Return the Action frame to the source without change
4383 * except that MSB of the Category set to 1.
4384 */
4385 wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action "
4386 "frame back to sender");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004387 resp = os_memdup(mgmt, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004388 if (resp == NULL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004389 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004390 os_memcpy(resp->da, resp->sa, ETH_ALEN);
4391 os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
4392 os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
4393 resp->u.action.category |= 0x80;
4394
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004395 if (hostapd_drv_send_mlme(hapd, resp, len, 0) < 0) {
4396 wpa_printf(MSG_ERROR, "IEEE 802.11: Failed to send "
4397 "Action frame");
4398 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004399 os_free(resp);
4400 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004401
4402 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004403}
4404
4405
4406/**
4407 * ieee802_11_mgmt - process incoming IEEE 802.11 management frames
4408 * @hapd: hostapd BSS data structure (the BSS to which the management frame was
4409 * sent to)
4410 * @buf: management frame data (starting from IEEE 802.11 header)
4411 * @len: length of frame data in octets
4412 * @fi: meta data about received frame (signal level, etc.)
4413 *
4414 * Process all incoming IEEE 802.11 management frames. This will be called for
4415 * each frame received from the kernel driver through wlan#ap interface. In
4416 * addition, it can be called to re-inserted pending frames (e.g., when using
4417 * external RADIUS server as an MAC ACL).
4418 */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004419int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
4420 struct hostapd_frame_info *fi)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004421{
4422 struct ieee80211_mgmt *mgmt;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004423 u16 fc, stype;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004424 int ret = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004425 unsigned int freq;
4426 int ssi_signal = fi ? fi->ssi_signal : 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004427
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004428 if (len < 24)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004429 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004430
Roshan Pius3a1667e2018-07-03 15:17:14 -07004431 if (fi && fi->freq)
4432 freq = fi->freq;
4433 else
4434 freq = hapd->iface->freq;
4435
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004436 mgmt = (struct ieee80211_mgmt *) buf;
4437 fc = le_to_host16(mgmt->frame_control);
4438 stype = WLAN_FC_GET_STYPE(fc);
4439
4440 if (stype == WLAN_FC_STYPE_BEACON) {
4441 handle_beacon(hapd, mgmt, len, fi);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004442 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004443 }
4444
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07004445 if (!is_broadcast_ether_addr(mgmt->bssid) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004446#ifdef CONFIG_P2P
4447 /* Invitation responses can be sent with the peer MAC as BSSID */
4448 !((hapd->conf->p2p & P2P_GROUP_OWNER) &&
4449 stype == WLAN_FC_STYPE_ACTION) &&
4450#endif /* CONFIG_P2P */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004451#ifdef CONFIG_MESH
4452 !(hapd->conf->mesh & MESH_ENABLED) &&
4453#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004454 os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004455 wpa_printf(MSG_INFO, "MGMT: BSSID=" MACSTR " not our address",
4456 MAC2STR(mgmt->bssid));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004457 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004458 }
4459
4460
4461 if (stype == WLAN_FC_STYPE_PROBE_REQ) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07004462 handle_probe_req(hapd, mgmt, len, ssi_signal);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004463 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004464 }
4465
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004466 if ((!is_broadcast_ether_addr(mgmt->da) ||
4467 stype != WLAN_FC_STYPE_ACTION) &&
4468 os_memcmp(mgmt->da, hapd->own_addr, ETH_ALEN) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004469 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
4470 HOSTAPD_LEVEL_DEBUG,
4471 "MGMT: DA=" MACSTR " not our address",
4472 MAC2STR(mgmt->da));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004473 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004474 }
4475
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004476 if (hapd->iconf->track_sta_max_num)
Roshan Pius3a1667e2018-07-03 15:17:14 -07004477 sta_track_add(hapd->iface, mgmt->sa, ssi_signal);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004478
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004479 switch (stype) {
4480 case WLAN_FC_STYPE_AUTH:
4481 wpa_printf(MSG_DEBUG, "mgmt::auth");
Hai Shalom021b0b52019-04-10 11:17:58 -07004482 handle_auth(hapd, mgmt, len, ssi_signal, 0);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004483 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004484 break;
4485 case WLAN_FC_STYPE_ASSOC_REQ:
4486 wpa_printf(MSG_DEBUG, "mgmt::assoc_req");
Hai Shalom74f70d42019-02-11 14:42:39 -08004487 handle_assoc(hapd, mgmt, len, 0, ssi_signal);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004488 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004489 break;
4490 case WLAN_FC_STYPE_REASSOC_REQ:
4491 wpa_printf(MSG_DEBUG, "mgmt::reassoc_req");
Hai Shalom74f70d42019-02-11 14:42:39 -08004492 handle_assoc(hapd, mgmt, len, 1, ssi_signal);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004493 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004494 break;
4495 case WLAN_FC_STYPE_DISASSOC:
4496 wpa_printf(MSG_DEBUG, "mgmt::disassoc");
4497 handle_disassoc(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004498 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004499 break;
4500 case WLAN_FC_STYPE_DEAUTH:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004501 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "mgmt::deauth");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004502 handle_deauth(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004503 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004504 break;
4505 case WLAN_FC_STYPE_ACTION:
4506 wpa_printf(MSG_DEBUG, "mgmt::action");
Roshan Pius3a1667e2018-07-03 15:17:14 -07004507 ret = handle_action(hapd, mgmt, len, freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004508 break;
4509 default:
4510 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
4511 HOSTAPD_LEVEL_DEBUG,
4512 "unknown mgmt frame subtype %d", stype);
4513 break;
4514 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004515
4516 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004517}
4518
4519
4520static void handle_auth_cb(struct hostapd_data *hapd,
4521 const struct ieee80211_mgmt *mgmt,
4522 size_t len, int ok)
4523{
4524 u16 auth_alg, auth_transaction, status_code;
4525 struct sta_info *sta;
4526
Hai Shalome5e28bb2019-01-28 14:51:04 -08004527 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
4528 wpa_printf(MSG_INFO, "handle_auth_cb - too short payload (len=%lu)",
4529 (unsigned long) len);
4530
4531 /*
4532 * Initialize status_code here because we are not able to read
4533 * it from the short payload.
4534 */
4535 status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
4536 goto fail;
4537 }
4538
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004539 sta = ap_get_sta(hapd, mgmt->da);
4540 if (!sta) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004541 wpa_printf(MSG_DEBUG, "handle_auth_cb: STA " MACSTR
4542 " not found",
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004543 MAC2STR(mgmt->da));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004544 return;
4545 }
4546
4547 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
4548 auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
4549 status_code = le_to_host16(mgmt->u.auth.status_code);
4550
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004551 if (!ok) {
4552 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
4553 HOSTAPD_LEVEL_NOTICE,
4554 "did not acknowledge authentication response");
4555 goto fail;
4556 }
4557
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004558 if (status_code == WLAN_STATUS_SUCCESS &&
4559 ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) ||
4560 (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) {
4561 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4562 HOSTAPD_LEVEL_INFO, "authenticated");
4563 sta->flags |= WLAN_STA_AUTH;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004564 if (sta->added_unassoc)
4565 hostapd_set_sta_flags(hapd, sta);
4566 return;
4567 }
4568
4569fail:
4570 if (status_code != WLAN_STATUS_SUCCESS && sta->added_unassoc) {
4571 hostapd_drv_sta_remove(hapd, sta->addr);
4572 sta->added_unassoc = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004573 }
4574}
4575
4576
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004577static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
4578 struct sta_info *sta,
4579 char *ifname_wds)
4580{
4581 int i;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004582 struct hostapd_ssid *ssid = &hapd->conf->ssid;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004583
4584 if (hapd->conf->ieee802_1x || hapd->conf->wpa)
4585 return;
4586
4587 for (i = 0; i < 4; i++) {
4588 if (ssid->wep.key[i] &&
4589 hostapd_drv_set_key(ifname_wds, hapd, WPA_ALG_WEP, NULL, i,
4590 i == ssid->wep.idx, NULL, 0,
4591 ssid->wep.key[i], ssid->wep.len[i])) {
4592 wpa_printf(MSG_WARNING,
4593 "Could not set WEP keys for WDS interface; %s",
4594 ifname_wds);
4595 break;
4596 }
4597 }
4598}
4599
4600
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004601static void handle_assoc_cb(struct hostapd_data *hapd,
4602 const struct ieee80211_mgmt *mgmt,
4603 size_t len, int reassoc, int ok)
4604{
4605 u16 status;
4606 struct sta_info *sta;
4607 int new_assoc = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004608
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004609 sta = ap_get_sta(hapd, mgmt->da);
4610 if (!sta) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004611 wpa_printf(MSG_INFO, "handle_assoc_cb: STA " MACSTR " not found",
4612 MAC2STR(mgmt->da));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004613 return;
4614 }
4615
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004616 if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) :
4617 sizeof(mgmt->u.assoc_resp))) {
4618 wpa_printf(MSG_INFO,
4619 "handle_assoc_cb(reassoc=%d) - too short payload (len=%lu)",
4620 reassoc, (unsigned long) len);
4621 hostapd_drv_sta_remove(hapd, sta->addr);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07004622 return;
4623 }
4624
4625 if (reassoc)
4626 status = le_to_host16(mgmt->u.reassoc_resp.status_code);
4627 else
4628 status = le_to_host16(mgmt->u.assoc_resp.status_code);
4629
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004630 if (!ok) {
4631 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
4632 HOSTAPD_LEVEL_DEBUG,
4633 "did not acknowledge association response");
4634 sta->flags &= ~WLAN_STA_ASSOC_REQ_OK;
4635 /* The STA is added only in case of SUCCESS */
4636 if (status == WLAN_STATUS_SUCCESS)
4637 hostapd_drv_sta_remove(hapd, sta->addr);
4638
4639 return;
4640 }
4641
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004642 if (status != WLAN_STATUS_SUCCESS)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004643 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004644
4645 /* Stop previous accounting session, if one is started, and allocate
4646 * new session id for the new session. */
4647 accounting_sta_stop(hapd, sta);
4648
4649 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4650 HOSTAPD_LEVEL_INFO,
4651 "associated (aid %d)",
4652 sta->aid);
4653
4654 if (sta->flags & WLAN_STA_ASSOC)
4655 new_assoc = 0;
4656 sta->flags |= WLAN_STA_ASSOC;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004657 sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004658 if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
4659 !hapd->conf->osen) ||
4660 sta->auth_alg == WLAN_AUTH_FILS_SK ||
4661 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
4662 sta->auth_alg == WLAN_AUTH_FILS_PK ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004663 sta->auth_alg == WLAN_AUTH_FT) {
4664 /*
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004665 * Open, static WEP, FT protocol, or FILS; no separate
4666 * authorization step.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004667 */
4668 ap_sta_set_authorized(hapd, sta, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004669 }
4670
4671 if (reassoc)
4672 mlme_reassociate_indication(hapd, sta);
4673 else
4674 mlme_associate_indication(hapd, sta);
4675
4676#ifdef CONFIG_IEEE80211W
4677 sta->sa_query_timed_out = 0;
4678#endif /* CONFIG_IEEE80211W */
4679
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004680 if (sta->eapol_sm == NULL) {
4681 /*
4682 * This STA does not use RADIUS server for EAP authentication,
4683 * so bind it to the selected VLAN interface now, since the
4684 * interface selection is not going to change anymore.
4685 */
Dmitry Shmidt83474442015-04-15 13:47:09 -07004686 if (ap_sta_bind_vlan(hapd, sta) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004687 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004688 } else if (sta->vlan_id) {
4689 /* VLAN ID already set (e.g., by PMKSA caching), so bind STA */
Dmitry Shmidt83474442015-04-15 13:47:09 -07004690 if (ap_sta_bind_vlan(hapd, sta) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004691 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004692 }
4693
4694 hostapd_set_sta_flags(hapd, sta);
4695
Dmitry Shmidt29333592017-01-09 12:27:11 -08004696 if (!(sta->flags & WLAN_STA_WDS) && sta->pending_wds_enable) {
4697 wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for STA "
4698 MACSTR " based on pending request",
4699 MAC2STR(sta->addr));
4700 sta->pending_wds_enable = 0;
4701 sta->flags |= WLAN_STA_WDS;
4702 }
4703
Hai Shalom74f70d42019-02-11 14:42:39 -08004704 if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP)) {
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08004705 int ret;
4706 char ifname_wds[IFNAMSIZ + 1];
4707
4708 wpa_printf(MSG_DEBUG, "Reenable 4-address WDS mode for STA "
4709 MACSTR " (aid %u)",
4710 MAC2STR(sta->addr), sta->aid);
4711 ret = hostapd_set_wds_sta(hapd, ifname_wds, sta->addr,
4712 sta->aid, 1);
4713 if (!ret)
4714 hostapd_set_wds_encryption(hapd, sta, ifname_wds);
4715 }
4716
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004717 if (sta->auth_alg == WLAN_AUTH_FT)
4718 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
4719 else
4720 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
4721 hapd->new_assoc_sta_cb(hapd, sta, !new_assoc);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004722 ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08004723
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004724#ifdef CONFIG_FILS
4725 if ((sta->auth_alg == WLAN_AUTH_FILS_SK ||
4726 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
4727 sta->auth_alg == WLAN_AUTH_FILS_PK) &&
4728 fils_set_tk(sta->wpa_sm) < 0) {
4729 wpa_printf(MSG_DEBUG, "FILS: TK configuration failed");
4730 ap_sta_disconnect(hapd, sta, sta->addr,
4731 WLAN_REASON_UNSPECIFIED);
4732 return;
4733 }
4734#endif /* CONFIG_FILS */
4735
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08004736 if (sta->pending_eapol_rx) {
4737 struct os_reltime now, age;
4738
4739 os_get_reltime(&now);
4740 os_reltime_sub(&now, &sta->pending_eapol_rx->rx_time, &age);
4741 if (age.sec == 0 && age.usec < 200000) {
4742 wpa_printf(MSG_DEBUG,
4743 "Process pending EAPOL frame that was received from " MACSTR " just before association notification",
4744 MAC2STR(sta->addr));
4745 ieee802_1x_receive(
4746 hapd, mgmt->da,
4747 wpabuf_head(sta->pending_eapol_rx->buf),
4748 wpabuf_len(sta->pending_eapol_rx->buf));
4749 }
4750 wpabuf_free(sta->pending_eapol_rx->buf);
4751 os_free(sta->pending_eapol_rx);
4752 sta->pending_eapol_rx = NULL;
4753 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004754}
4755
4756
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004757static void handle_deauth_cb(struct hostapd_data *hapd,
4758 const struct ieee80211_mgmt *mgmt,
4759 size_t len, int ok)
4760{
4761 struct sta_info *sta;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07004762 if (is_multicast_ether_addr(mgmt->da))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004763 return;
4764 sta = ap_get_sta(hapd, mgmt->da);
4765 if (!sta) {
4766 wpa_printf(MSG_DEBUG, "handle_deauth_cb: STA " MACSTR
4767 " not found", MAC2STR(mgmt->da));
4768 return;
4769 }
4770 if (ok)
4771 wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged deauth",
4772 MAC2STR(sta->addr));
4773 else
4774 wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
4775 "deauth", MAC2STR(sta->addr));
4776
4777 ap_sta_deauth_cb(hapd, sta);
4778}
4779
4780
4781static void handle_disassoc_cb(struct hostapd_data *hapd,
4782 const struct ieee80211_mgmt *mgmt,
4783 size_t len, int ok)
4784{
4785 struct sta_info *sta;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07004786 if (is_multicast_ether_addr(mgmt->da))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004787 return;
4788 sta = ap_get_sta(hapd, mgmt->da);
4789 if (!sta) {
4790 wpa_printf(MSG_DEBUG, "handle_disassoc_cb: STA " MACSTR
4791 " not found", MAC2STR(mgmt->da));
4792 return;
4793 }
4794 if (ok)
4795 wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged disassoc",
4796 MAC2STR(sta->addr));
4797 else
4798 wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
4799 "disassoc", MAC2STR(sta->addr));
4800
4801 ap_sta_disassoc_cb(hapd, sta);
4802}
4803
4804
Dmitry Shmidt29333592017-01-09 12:27:11 -08004805static void handle_action_cb(struct hostapd_data *hapd,
4806 const struct ieee80211_mgmt *mgmt,
4807 size_t len, int ok)
4808{
4809 struct sta_info *sta;
Paul Stewart092955c2017-02-06 09:13:09 -08004810 const struct rrm_measurement_report_element *report;
Dmitry Shmidt29333592017-01-09 12:27:11 -08004811
4812 if (is_multicast_ether_addr(mgmt->da))
4813 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004814#ifdef CONFIG_DPP
4815 if (len >= IEEE80211_HDRLEN + 6 &&
4816 mgmt->u.action.category == WLAN_ACTION_PUBLIC &&
4817 mgmt->u.action.u.vs_public_action.action ==
4818 WLAN_PA_VENDOR_SPECIFIC &&
4819 WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) ==
4820 OUI_WFA &&
4821 mgmt->u.action.u.vs_public_action.variable[0] ==
4822 DPP_OUI_TYPE) {
4823 const u8 *pos, *end;
4824
4825 pos = &mgmt->u.action.u.vs_public_action.variable[1];
4826 end = ((const u8 *) mgmt) + len;
4827 hostapd_dpp_tx_status(hapd, mgmt->da, pos, end - pos, ok);
4828 return;
4829 }
4830 if (len >= IEEE80211_HDRLEN + 2 &&
4831 mgmt->u.action.category == WLAN_ACTION_PUBLIC &&
4832 (mgmt->u.action.u.public_action.action ==
4833 WLAN_PA_GAS_INITIAL_REQ ||
4834 mgmt->u.action.u.public_action.action ==
4835 WLAN_PA_GAS_COMEBACK_REQ)) {
4836 const u8 *pos, *end;
4837
4838 pos = mgmt->u.action.u.public_action.variable;
4839 end = ((const u8 *) mgmt) + len;
4840 gas_query_ap_tx_status(hapd->gas, mgmt->da, pos, end - pos, ok);
4841 return;
4842 }
4843#endif /* CONFIG_DPP */
Dmitry Shmidt29333592017-01-09 12:27:11 -08004844 sta = ap_get_sta(hapd, mgmt->da);
4845 if (!sta) {
4846 wpa_printf(MSG_DEBUG, "handle_action_cb: STA " MACSTR
4847 " not found", MAC2STR(mgmt->da));
4848 return;
4849 }
4850
Paul Stewart092955c2017-02-06 09:13:09 -08004851 if (len < 24 + 5 + sizeof(*report))
Dmitry Shmidt29333592017-01-09 12:27:11 -08004852 return;
Paul Stewart092955c2017-02-06 09:13:09 -08004853 report = (const struct rrm_measurement_report_element *)
4854 &mgmt->u.action.u.rrm.variable[2];
Dmitry Shmidt29333592017-01-09 12:27:11 -08004855 if (mgmt->u.action.category == WLAN_ACTION_RADIO_MEASUREMENT &&
Paul Stewart092955c2017-02-06 09:13:09 -08004856 mgmt->u.action.u.rrm.action == WLAN_RRM_RADIO_MEASUREMENT_REQUEST &&
4857 report->eid == WLAN_EID_MEASURE_REQUEST &&
4858 report->len >= 3 &&
4859 report->type == MEASURE_TYPE_BEACON)
Dmitry Shmidt29333592017-01-09 12:27:11 -08004860 hostapd_rrm_beacon_req_tx_status(hapd, mgmt, len, ok);
4861}
4862
4863
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004864/**
4865 * ieee802_11_mgmt_cb - Process management frame TX status callback
4866 * @hapd: hostapd BSS data structure (the BSS from which the management frame
4867 * was sent from)
4868 * @buf: management frame data (starting from IEEE 802.11 header)
4869 * @len: length of frame data in octets
4870 * @stype: management frame subtype from frame control field
4871 * @ok: Whether the frame was ACK'ed
4872 */
4873void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len,
4874 u16 stype, int ok)
4875{
4876 const struct ieee80211_mgmt *mgmt;
4877 mgmt = (const struct ieee80211_mgmt *) buf;
4878
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004879#ifdef CONFIG_TESTING_OPTIONS
4880 if (hapd->ext_mgmt_frame_handling) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004881 size_t hex_len = 2 * len + 1;
4882 char *hex = os_malloc(hex_len);
4883
4884 if (hex) {
4885 wpa_snprintf_hex(hex, hex_len, buf, len);
4886 wpa_msg(hapd->msg_ctx, MSG_INFO,
4887 "MGMT-TX-STATUS stype=%u ok=%d buf=%s",
4888 stype, ok, hex);
4889 os_free(hex);
4890 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004891 return;
4892 }
4893#endif /* CONFIG_TESTING_OPTIONS */
4894
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004895 switch (stype) {
4896 case WLAN_FC_STYPE_AUTH:
4897 wpa_printf(MSG_DEBUG, "mgmt::auth cb");
4898 handle_auth_cb(hapd, mgmt, len, ok);
4899 break;
4900 case WLAN_FC_STYPE_ASSOC_RESP:
4901 wpa_printf(MSG_DEBUG, "mgmt::assoc_resp cb");
4902 handle_assoc_cb(hapd, mgmt, len, 0, ok);
4903 break;
4904 case WLAN_FC_STYPE_REASSOC_RESP:
4905 wpa_printf(MSG_DEBUG, "mgmt::reassoc_resp cb");
4906 handle_assoc_cb(hapd, mgmt, len, 1, ok);
4907 break;
4908 case WLAN_FC_STYPE_PROBE_RESP:
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004909 wpa_printf(MSG_EXCESSIVE, "mgmt::proberesp cb ok=%d", ok);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004910 break;
4911 case WLAN_FC_STYPE_DEAUTH:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004912 wpa_printf(MSG_DEBUG, "mgmt::deauth cb");
4913 handle_deauth_cb(hapd, mgmt, len, ok);
4914 break;
4915 case WLAN_FC_STYPE_DISASSOC:
4916 wpa_printf(MSG_DEBUG, "mgmt::disassoc cb");
4917 handle_disassoc_cb(hapd, mgmt, len, ok);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004918 break;
4919 case WLAN_FC_STYPE_ACTION:
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004920 wpa_printf(MSG_DEBUG, "mgmt::action cb ok=%d", ok);
Dmitry Shmidt29333592017-01-09 12:27:11 -08004921 handle_action_cb(hapd, mgmt, len, ok);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004922 break;
4923 default:
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004924 wpa_printf(MSG_INFO, "unknown mgmt cb frame subtype %d", stype);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004925 break;
4926 }
4927}
4928
4929
4930int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
4931{
4932 /* TODO */
4933 return 0;
4934}
4935
4936
4937int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
4938 char *buf, size_t buflen)
4939{
4940 /* TODO */
4941 return 0;
4942}
4943
4944
4945void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
4946 const u8 *buf, size_t len, int ack)
4947{
4948 struct sta_info *sta;
4949 struct hostapd_iface *iface = hapd->iface;
4950
4951 sta = ap_get_sta(hapd, addr);
4952 if (sta == NULL && iface->num_bss > 1) {
4953 size_t j;
4954 for (j = 0; j < iface->num_bss; j++) {
4955 hapd = iface->bss[j];
4956 sta = ap_get_sta(hapd, addr);
4957 if (sta)
4958 break;
4959 }
4960 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004961 if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004962 return;
4963 if (sta->flags & WLAN_STA_PENDING_POLL) {
4964 wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending "
4965 "activity poll", MAC2STR(sta->addr),
4966 ack ? "ACKed" : "did not ACK");
4967 if (ack)
4968 sta->flags &= ~WLAN_STA_PENDING_POLL;
4969 }
4970
4971 ieee802_1x_tx_status(hapd, sta, buf, len, ack);
4972}
4973
4974
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004975void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
4976 const u8 *data, size_t len, int ack)
4977{
4978 struct sta_info *sta;
4979 struct hostapd_iface *iface = hapd->iface;
4980
4981 sta = ap_get_sta(hapd, dst);
4982 if (sta == NULL && iface->num_bss > 1) {
4983 size_t j;
4984 for (j = 0; j < iface->num_bss; j++) {
4985 hapd = iface->bss[j];
4986 sta = ap_get_sta(hapd, dst);
4987 if (sta)
4988 break;
4989 }
4990 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004991 if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
4992 wpa_printf(MSG_DEBUG, "Ignore TX status for Data frame to STA "
4993 MACSTR " that is not currently associated",
4994 MAC2STR(dst));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004995 return;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004996 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004997
4998 ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack);
4999}
5000
5001
5002void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr)
5003{
5004 struct sta_info *sta;
5005 struct hostapd_iface *iface = hapd->iface;
5006
5007 sta = ap_get_sta(hapd, addr);
5008 if (sta == NULL && iface->num_bss > 1) {
5009 size_t j;
5010 for (j = 0; j < iface->num_bss; j++) {
5011 hapd = iface->bss[j];
5012 sta = ap_get_sta(hapd, addr);
5013 if (sta)
5014 break;
5015 }
5016 }
5017 if (sta == NULL)
5018 return;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07005019 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POLL_OK MACSTR,
5020 MAC2STR(sta->addr));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005021 if (!(sta->flags & WLAN_STA_PENDING_POLL))
5022 return;
5023
5024 wpa_printf(MSG_DEBUG, "STA " MACSTR " ACKed pending "
5025 "activity poll", MAC2STR(sta->addr));
5026 sta->flags &= ~WLAN_STA_PENDING_POLL;
5027}
5028
5029
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005030void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
5031 int wds)
5032{
5033 struct sta_info *sta;
5034
5035 sta = ap_get_sta(hapd, src);
Dmitry Shmidt29333592017-01-09 12:27:11 -08005036 if (sta &&
5037 ((sta->flags & WLAN_STA_ASSOC) ||
5038 ((sta->flags & WLAN_STA_ASSOC_REQ_OK) && wds))) {
Dmitry Shmidtaa532512012-09-24 10:35:31 -07005039 if (!hapd->conf->wds_sta)
5040 return;
5041
Dmitry Shmidt29333592017-01-09 12:27:11 -08005042 if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK)) ==
5043 WLAN_STA_ASSOC_REQ_OK) {
5044 wpa_printf(MSG_DEBUG,
5045 "Postpone 4-address WDS mode enabling for STA "
5046 MACSTR " since TX status for AssocResp is not yet known",
5047 MAC2STR(sta->addr));
5048 sta->pending_wds_enable = 1;
5049 return;
5050 }
5051
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005052 if (wds && !(sta->flags & WLAN_STA_WDS)) {
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005053 int ret;
5054 char ifname_wds[IFNAMSIZ + 1];
5055
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005056 wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for "
5057 "STA " MACSTR " (aid %u)",
5058 MAC2STR(sta->addr), sta->aid);
5059 sta->flags |= WLAN_STA_WDS;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005060 ret = hostapd_set_wds_sta(hapd, ifname_wds,
5061 sta->addr, sta->aid, 1);
5062 if (!ret)
5063 hostapd_set_wds_encryption(hapd, sta,
5064 ifname_wds);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005065 }
5066 return;
5067 }
5068
5069 wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA "
5070 MACSTR, MAC2STR(src));
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07005071 if (is_multicast_ether_addr(src)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005072 /* Broadcast bit set in SA?! Ignore the frame silently. */
5073 return;
5074 }
5075
5076 if (sta && (sta->flags & WLAN_STA_ASSOC_REQ_OK)) {
5077 wpa_printf(MSG_DEBUG, "Association Response to the STA has "
5078 "already been sent, but no TX status yet known - "
5079 "ignore Class 3 frame issue with " MACSTR,
5080 MAC2STR(src));
5081 return;
5082 }
5083
5084 if (sta && (sta->flags & WLAN_STA_AUTH))
5085 hostapd_drv_sta_disassoc(
5086 hapd, src,
5087 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
5088 else
5089 hostapd_drv_sta_deauth(
5090 hapd, src,
5091 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
5092}
5093
5094
5095#endif /* CONFIG_NATIVE_WINDOWS */