blob: 376bbd82cee2ae68a650a973c017069217b42512 [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 Shalom74f70d42019-02-11 14:42:39 -080024#include "common/ocv.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070025#include "radius/radius.h"
26#include "radius/radius_client.h"
27#include "p2p/p2p.h"
28#include "wps/wps.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080029#include "fst/fst.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070030#include "hostapd.h"
31#include "beacon.h"
32#include "ieee802_11_auth.h"
33#include "sta_info.h"
34#include "ieee802_1x.h"
35#include "wpa_auth.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080036#include "pmksa_cache_auth.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037#include "wmm.h"
38#include "ap_list.h"
39#include "accounting.h"
40#include "ap_config.h"
41#include "ap_mlme.h"
42#include "p2p_hostapd.h"
43#include "ap_drv_ops.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080044#include "wnm_ap.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080045#include "hw_features.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070046#include "ieee802_11.h"
Dmitry Shmidtf21452a2014-02-26 10:55:25 -080047#include "dfs.h"
Dmitry Shmidt57c2d392016-02-23 13:40:19 -080048#include "mbo_ap.h"
Dmitry Shmidt849734c2016-05-27 09:59:01 -070049#include "rrm.h"
Dmitry Shmidtaca489e2016-09-28 15:44:14 -070050#include "taxonomy.h"
Dmitry Shmidtebd93af2017-02-21 13:40:44 -080051#include "fils_hlp.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070052#include "dpp_hostapd.h"
53#include "gas_query_ap.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070054
55
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070056#ifdef CONFIG_FILS
57static struct wpabuf *
58prepare_auth_resp_fils(struct hostapd_data *hapd,
59 struct sta_info *sta, u16 *resp,
60 struct rsn_pmksa_cache_entry *pmksa,
61 struct wpabuf *erp_resp,
62 const u8 *msk, size_t msk_len,
63 int *is_pub);
64#endif /* CONFIG_FILS */
65
Hai Shalom74f70d42019-02-11 14:42:39 -080066
67u8 * hostapd_eid_multi_ap(struct hostapd_data *hapd, u8 *eid)
68{
69 u8 multi_ap_val = 0;
70
71 if (!hapd->conf->multi_ap)
72 return eid;
73 if (hapd->conf->multi_ap & BACKHAUL_BSS)
74 multi_ap_val |= MULTI_AP_BACKHAUL_BSS;
75 if (hapd->conf->multi_ap & FRONTHAUL_BSS)
76 multi_ap_val |= MULTI_AP_FRONTHAUL_BSS;
77
78 return eid + add_multi_ap_ie(eid, 9, multi_ap_val);
79}
80
81
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070082u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
83{
84 u8 *pos = eid;
85 int i, num, count;
86
87 if (hapd->iface->current_rates == NULL)
88 return eid;
89
90 *pos++ = WLAN_EID_SUPP_RATES;
91 num = hapd->iface->num_rates;
92 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
93 num++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080094 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
95 num++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096 if (num > 8) {
97 /* rest of the rates are encoded in Extended supported
98 * rates element */
99 num = 8;
100 }
101
102 *pos++ = num;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700103 for (i = 0, count = 0; i < hapd->iface->num_rates && count < num;
104 i++) {
105 count++;
106 *pos = hapd->iface->current_rates[i].rate / 5;
107 if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
108 *pos |= 0x80;
109 pos++;
110 }
111
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800112 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht && count < 8) {
113 count++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700114 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800115 }
116
117 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht && count < 8) {
118 count++;
119 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
120 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700121
122 return pos;
123}
124
125
126u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
127{
128 u8 *pos = eid;
129 int i, num, count;
130
131 if (hapd->iface->current_rates == NULL)
132 return eid;
133
134 num = hapd->iface->num_rates;
135 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
136 num++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800137 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
138 num++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700139 if (num <= 8)
140 return eid;
141 num -= 8;
142
143 *pos++ = WLAN_EID_EXT_SUPP_RATES;
144 *pos++ = num;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700145 for (i = 0, count = 0; i < hapd->iface->num_rates && count < num + 8;
146 i++) {
147 count++;
148 if (count <= 8)
149 continue; /* already in SuppRates IE */
150 *pos = hapd->iface->current_rates[i].rate / 5;
151 if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
152 *pos |= 0x80;
153 pos++;
154 }
155
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800156 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) {
157 count++;
158 if (count > 8)
159 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
160 }
161
162 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) {
163 count++;
164 if (count > 8)
165 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
166 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700167
168 return pos;
169}
170
171
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -0700172u16 hostapd_own_capab_info(struct hostapd_data *hapd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700173{
174 int capab = WLAN_CAPABILITY_ESS;
175 int privacy;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800176 int dfs;
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700177 int i;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800178
179 /* Check if any of configured channels require DFS */
180 dfs = hostapd_is_dfs_required(hapd->iface);
181 if (dfs < 0) {
182 wpa_printf(MSG_WARNING, "Failed to check if DFS is required; ret=%d",
183 dfs);
184 dfs = 0;
185 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700186
187 if (hapd->iface->num_sta_no_short_preamble == 0 &&
188 hapd->iconf->preamble == SHORT_PREAMBLE)
189 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
190
191 privacy = hapd->conf->ssid.wep.keys_set;
192
193 if (hapd->conf->ieee802_1x &&
194 (hapd->conf->default_wep_key_len ||
195 hapd->conf->individual_wep_key_len))
196 privacy = 1;
197
198 if (hapd->conf->wpa)
199 privacy = 1;
200
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800201#ifdef CONFIG_HS20
202 if (hapd->conf->osen)
203 privacy = 1;
204#endif /* CONFIG_HS20 */
205
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700206 if (privacy)
207 capab |= WLAN_CAPABILITY_PRIVACY;
208
209 if (hapd->iface->current_mode &&
210 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
211 hapd->iface->num_sta_no_short_slot_time == 0)
212 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
213
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800214 /*
215 * Currently, Spectrum Management capability bit is set when directly
216 * requested in configuration by spectrum_mgmt_required or when AP is
217 * running on DFS channel.
218 * TODO: Also consider driver support for TPC to set Spectrum Mgmt bit
219 */
220 if (hapd->iface->current_mode &&
221 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
222 (hapd->iconf->spectrum_mgmt_required || dfs))
223 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
224
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700225 for (i = 0; i < RRM_CAPABILITIES_IE_LEN; i++) {
226 if (hapd->conf->radio_measurements[i]) {
227 capab |= IEEE80211_CAP_RRM;
228 break;
229 }
230 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800231
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700232 return capab;
233}
234
235
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800236#ifndef CONFIG_NO_RC4
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700237static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
238 u16 auth_transaction, const u8 *challenge,
239 int iswep)
240{
241 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
242 HOSTAPD_LEVEL_DEBUG,
243 "authentication (shared key, transaction %d)",
244 auth_transaction);
245
246 if (auth_transaction == 1) {
247 if (!sta->challenge) {
248 /* Generate a pseudo-random challenge */
249 u8 key[8];
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800250
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700251 sta->challenge = os_zalloc(WLAN_AUTH_CHALLENGE_LEN);
252 if (sta->challenge == NULL)
253 return WLAN_STATUS_UNSPECIFIED_FAILURE;
254
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800255 if (os_get_random(key, sizeof(key)) < 0) {
256 os_free(sta->challenge);
257 sta->challenge = NULL;
258 return WLAN_STATUS_UNSPECIFIED_FAILURE;
259 }
260
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700261 rc4_skip(key, sizeof(key), 0,
262 sta->challenge, WLAN_AUTH_CHALLENGE_LEN);
263 }
264 return 0;
265 }
266
267 if (auth_transaction != 3)
268 return WLAN_STATUS_UNSPECIFIED_FAILURE;
269
270 /* Transaction 3 */
271 if (!iswep || !sta->challenge || !challenge ||
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700272 os_memcmp_const(sta->challenge, challenge,
273 WLAN_AUTH_CHALLENGE_LEN)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700274 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
275 HOSTAPD_LEVEL_INFO,
276 "shared key authentication - invalid "
277 "challenge-response");
278 return WLAN_STATUS_CHALLENGE_FAIL;
279 }
280
281 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
282 HOSTAPD_LEVEL_DEBUG,
283 "authentication OK (shared key)");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700284 sta->flags |= WLAN_STA_AUTH;
285 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700286 os_free(sta->challenge);
287 sta->challenge = NULL;
288
289 return 0;
290}
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800291#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700292
293
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800294static int send_auth_reply(struct hostapd_data *hapd,
295 const u8 *dst, const u8 *bssid,
296 u16 auth_alg, u16 auth_transaction, u16 resp,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700297 const u8 *ies, size_t ies_len, const char *dbg)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700298{
299 struct ieee80211_mgmt *reply;
300 u8 *buf;
301 size_t rlen;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800302 int reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700303
304 rlen = IEEE80211_HDRLEN + sizeof(reply->u.auth) + ies_len;
305 buf = os_zalloc(rlen);
306 if (buf == NULL)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800307 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700308
309 reply = (struct ieee80211_mgmt *) buf;
310 reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
311 WLAN_FC_STYPE_AUTH);
312 os_memcpy(reply->da, dst, ETH_ALEN);
313 os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
314 os_memcpy(reply->bssid, bssid, ETH_ALEN);
315
316 reply->u.auth.auth_alg = host_to_le16(auth_alg);
317 reply->u.auth.auth_transaction = host_to_le16(auth_transaction);
318 reply->u.auth.status_code = host_to_le16(resp);
319
320 if (ies && ies_len)
321 os_memcpy(reply->u.auth.variable, ies, ies_len);
322
323 wpa_printf(MSG_DEBUG, "authentication reply: STA=" MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700324 " auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu) (dbg=%s)",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700325 MAC2STR(dst), auth_alg, auth_transaction,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700326 resp, (unsigned long) ies_len, dbg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800327 if (hostapd_drv_send_mlme(hapd, reply, rlen, 0) < 0)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800328 wpa_printf(MSG_INFO, "send_auth_reply: send failed");
329 else
330 reply_res = WLAN_STATUS_SUCCESS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700331
332 os_free(buf);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800333
334 return reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700335}
336
337
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800338#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700339static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
340 u16 auth_transaction, u16 status,
341 const u8 *ies, size_t ies_len)
342{
343 struct hostapd_data *hapd = ctx;
344 struct sta_info *sta;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800345 int reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700346
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800347 reply_res = send_auth_reply(hapd, dst, bssid, WLAN_AUTH_FT,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700348 auth_transaction, status, ies, ies_len,
349 "auth-ft-finish");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700350
351 sta = ap_get_sta(hapd, dst);
352 if (sta == NULL)
353 return;
354
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800355 if (sta->added_unassoc && (reply_res != WLAN_STATUS_SUCCESS ||
356 status != WLAN_STATUS_SUCCESS)) {
357 hostapd_drv_sta_remove(hapd, sta->addr);
358 sta->added_unassoc = 0;
359 return;
360 }
361
362 if (status != WLAN_STATUS_SUCCESS)
363 return;
364
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700365 hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211,
366 HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)");
367 sta->flags |= WLAN_STA_AUTH;
368 mlme_authenticate_indication(hapd, sta);
369}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800370#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700371
372
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800373#ifdef CONFIG_SAE
374
Roshan Pius3a1667e2018-07-03 15:17:14 -0700375static void sae_set_state(struct sta_info *sta, enum sae_state state,
376 const char *reason)
377{
378 wpa_printf(MSG_DEBUG, "SAE: State %s -> %s for peer " MACSTR " (%s)",
379 sae_state_txt(sta->sae->state), sae_state_txt(state),
380 MAC2STR(sta->addr), reason);
381 sta->sae->state = state;
382}
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800383
384
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800385static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
386 struct sta_info *sta, int update)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800387{
388 struct wpabuf *buf;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700389 const char *password = NULL;
390 struct sae_password_entry *pw;
391 const char *rx_id = NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800392
Roshan Pius3a1667e2018-07-03 15:17:14 -0700393 if (sta->sae->tmp)
394 rx_id = sta->sae->tmp->pw_id;
395
396 for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
397 if (!is_broadcast_ether_addr(pw->peer_addr) &&
398 os_memcmp(pw->peer_addr, sta->addr, ETH_ALEN) != 0)
399 continue;
400 if ((rx_id && !pw->identifier) || (!rx_id && pw->identifier))
401 continue;
402 if (rx_id && pw->identifier &&
403 os_strcmp(rx_id, pw->identifier) != 0)
404 continue;
405 password = pw->password;
406 break;
407 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700408 if (!password)
409 password = hapd->conf->ssid.wpa_passphrase;
410 if (!password) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800411 wpa_printf(MSG_DEBUG, "SAE: No password available");
412 return NULL;
413 }
414
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800415 if (update &&
416 sae_prepare_commit(hapd->own_addr, sta->addr,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700417 (u8 *) password, os_strlen(password), rx_id,
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800418 sta->sae) < 0) {
419 wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
420 return NULL;
421 }
422
Roshan Pius3a1667e2018-07-03 15:17:14 -0700423 buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN +
424 (rx_id ? 3 + os_strlen(rx_id) : 0));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800425 if (buf == NULL)
426 return NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800427 sae_write_commit(sta->sae, buf, sta->sae->tmp ?
Roshan Pius3a1667e2018-07-03 15:17:14 -0700428 sta->sae->tmp->anti_clogging_token : NULL, rx_id);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800429
430 return buf;
431}
432
433
434static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
435 struct sta_info *sta)
436{
437 struct wpabuf *buf;
438
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800439 buf = wpabuf_alloc(SAE_CONFIRM_MAX_LEN);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800440 if (buf == NULL)
441 return NULL;
442
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800443 sae_write_confirm(sta->sae, buf);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800444
445 return buf;
446}
447
448
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800449static int auth_sae_send_commit(struct hostapd_data *hapd,
450 struct sta_info *sta,
451 const u8 *bssid, int update)
452{
453 struct wpabuf *data;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800454 int reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800455
456 data = auth_build_sae_commit(hapd, sta, update);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700457 if (!data && sta->sae->tmp && sta->sae->tmp->pw_id)
458 return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800459 if (data == NULL)
460 return WLAN_STATUS_UNSPECIFIED_FAILURE;
461
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800462 reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 1,
463 WLAN_STATUS_SUCCESS, wpabuf_head(data),
Roshan Pius3a1667e2018-07-03 15:17:14 -0700464 wpabuf_len(data), "sae-send-commit");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800465
466 wpabuf_free(data);
467
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800468 return reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800469}
470
471
472static int auth_sae_send_confirm(struct hostapd_data *hapd,
473 struct sta_info *sta,
474 const u8 *bssid)
475{
476 struct wpabuf *data;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800477 int reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800478
479 data = auth_build_sae_confirm(hapd, sta);
480 if (data == NULL)
481 return WLAN_STATUS_UNSPECIFIED_FAILURE;
482
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800483 reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 2,
484 WLAN_STATUS_SUCCESS, wpabuf_head(data),
Roshan Pius3a1667e2018-07-03 15:17:14 -0700485 wpabuf_len(data), "sae-send-confirm");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800486
487 wpabuf_free(data);
488
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800489 return reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800490}
491
492
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800493static int use_sae_anti_clogging(struct hostapd_data *hapd)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800494{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800495 struct sta_info *sta;
496 unsigned int open = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800497
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800498 if (hapd->conf->sae_anti_clogging_threshold == 0)
499 return 1;
500
501 for (sta = hapd->sta_list; sta; sta = sta->next) {
502 if (!sta->sae)
503 continue;
504 if (sta->sae->state != SAE_COMMITTED &&
505 sta->sae->state != SAE_CONFIRMED)
506 continue;
507 open++;
508 if (open >= hapd->conf->sae_anti_clogging_threshold)
509 return 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800510 }
511
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800512 return 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800513}
514
515
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800516static int check_sae_token(struct hostapd_data *hapd, const u8 *addr,
517 const u8 *token, size_t token_len)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800518{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800519 u8 mac[SHA256_MAC_LEN];
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800520
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800521 if (token_len != SHA256_MAC_LEN)
522 return -1;
523 if (hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
524 addr, ETH_ALEN, mac) < 0 ||
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700525 os_memcmp_const(token, mac, SHA256_MAC_LEN) != 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800526 return -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800527
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800528 return 0;
529}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800530
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800531
532static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800533 int group, const u8 *addr)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800534{
535 struct wpabuf *buf;
536 u8 *token;
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800537 struct os_reltime now;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800538
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800539 os_get_reltime(&now);
540 if (!os_reltime_initialized(&hapd->last_sae_token_key_update) ||
541 os_reltime_expired(&now, &hapd->last_sae_token_key_update, 60)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800542 if (random_get_bytes(hapd->sae_token_key,
543 sizeof(hapd->sae_token_key)) < 0)
544 return NULL;
545 wpa_hexdump(MSG_DEBUG, "SAE: Updated token key",
546 hapd->sae_token_key, sizeof(hapd->sae_token_key));
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800547 hapd->last_sae_token_key_update = now;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800548 }
549
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800550 buf = wpabuf_alloc(sizeof(le16) + SHA256_MAC_LEN);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800551 if (buf == NULL)
552 return NULL;
553
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800554 wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
555
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800556 token = wpabuf_put(buf, SHA256_MAC_LEN);
557 hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
558 addr, ETH_ALEN, token);
559
560 return buf;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800561}
562
563
Roshan Pius3a1667e2018-07-03 15:17:14 -0700564static int sae_check_big_sync(struct hostapd_data *hapd, struct sta_info *sta)
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800565{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700566 if (sta->sae->sync > hapd->conf->sae_sync) {
567 sae_set_state(sta, SAE_NOTHING, "Sync > dot11RSNASAESync");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800568 sta->sae->sync = 0;
569 return -1;
570 }
571 return 0;
572}
573
574
575static void auth_sae_retransmit_timer(void *eloop_ctx, void *eloop_data)
576{
577 struct hostapd_data *hapd = eloop_ctx;
578 struct sta_info *sta = eloop_data;
579 int ret;
580
Roshan Pius3a1667e2018-07-03 15:17:14 -0700581 if (sae_check_big_sync(hapd, sta))
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800582 return;
583 sta->sae->sync++;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700584 wpa_printf(MSG_DEBUG, "SAE: Auth SAE retransmit timer for " MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700585 " (sync=%d state=%s)",
586 MAC2STR(sta->addr), sta->sae->sync,
587 sae_state_txt(sta->sae->state));
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800588
589 switch (sta->sae->state) {
590 case SAE_COMMITTED:
591 ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800592 eloop_register_timeout(0,
593 hapd->dot11RSNASAERetransPeriod * 1000,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800594 auth_sae_retransmit_timer, hapd, sta);
595 break;
596 case SAE_CONFIRMED:
597 ret = auth_sae_send_confirm(hapd, sta, hapd->own_addr);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800598 eloop_register_timeout(0,
599 hapd->dot11RSNASAERetransPeriod * 1000,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800600 auth_sae_retransmit_timer, hapd, sta);
601 break;
602 default:
603 ret = -1;
604 break;
605 }
606
607 if (ret != WLAN_STATUS_SUCCESS)
608 wpa_printf(MSG_INFO, "SAE: Failed to retransmit: ret=%d", ret);
609}
610
611
612void sae_clear_retransmit_timer(struct hostapd_data *hapd, struct sta_info *sta)
613{
614 eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta);
615}
616
617
618static void sae_set_retransmit_timer(struct hostapd_data *hapd,
619 struct sta_info *sta)
620{
621 if (!(hapd->conf->mesh & MESH_ENABLED))
622 return;
623
624 eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800625 eloop_register_timeout(0, hapd->dot11RSNASAERetransPeriod * 1000,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800626 auth_sae_retransmit_timer, hapd, sta);
627}
628
629
Dmitry Shmidte4663042016-04-04 10:07:49 -0700630void sae_accept_sta(struct hostapd_data *hapd, struct sta_info *sta)
631{
632 sta->flags |= WLAN_STA_AUTH;
633 sta->auth_alg = WLAN_AUTH_SAE;
634 mlme_authenticate_indication(hapd, sta);
635 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700636 sae_set_state(sta, SAE_ACCEPTED, "Accept Confirm");
Dmitry Shmidte4663042016-04-04 10:07:49 -0700637 wpa_auth_pmksa_add_sae(hapd->wpa_auth, sta->addr,
638 sta->sae->pmk, sta->sae->pmkid);
639}
640
641
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800642static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
643 const u8 *bssid, u8 auth_transaction)
644{
645 int ret;
646
647 if (auth_transaction != 1 && auth_transaction != 2)
648 return WLAN_STATUS_UNSPECIFIED_FAILURE;
649
Roshan Pius3a1667e2018-07-03 15:17:14 -0700650 wpa_printf(MSG_DEBUG, "SAE: Peer " MACSTR " state=%s auth_trans=%u",
651 MAC2STR(sta->addr), sae_state_txt(sta->sae->state),
652 auth_transaction);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800653 switch (sta->sae->state) {
654 case SAE_NOTHING:
655 if (auth_transaction == 1) {
656 ret = auth_sae_send_commit(hapd, sta, bssid, 1);
657 if (ret)
658 return ret;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700659 sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800660
661 if (sae_process_commit(sta->sae) < 0)
662 return WLAN_STATUS_UNSPECIFIED_FAILURE;
663
664 /*
665 * In mesh case, both Commit and Confirm can be sent
666 * immediately. In infrastructure BSS, only a single
667 * Authentication frame (Commit) is expected from the AP
668 * here and the second one (Confirm) will be sent once
669 * the STA has sent its second Authentication frame
670 * (Confirm).
671 */
672 if (hapd->conf->mesh & MESH_ENABLED) {
673 /*
674 * Send both Commit and Confirm immediately
675 * based on SAE finite state machine
676 * Nothing -> Confirm transition.
677 */
678 ret = auth_sae_send_confirm(hapd, sta, bssid);
679 if (ret)
680 return ret;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700681 sae_set_state(sta, SAE_CONFIRMED,
682 "Sent Confirm (mesh)");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800683 } else {
684 /*
685 * For infrastructure BSS, send only the Commit
686 * message now to get alternating sequence of
687 * Authentication frames between the AP and STA.
688 * Confirm will be sent in
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800689 * Committed -> Confirmed/Accepted transition
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800690 * when receiving Confirm from STA.
691 */
692 }
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800693 sta->sae->sync = 0;
694 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800695 } else {
696 hostapd_logger(hapd, sta->addr,
697 HOSTAPD_MODULE_IEEE80211,
698 HOSTAPD_LEVEL_DEBUG,
699 "SAE confirm before commit");
700 }
701 break;
702 case SAE_COMMITTED:
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800703 sae_clear_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800704 if (auth_transaction == 1) {
705 if (sae_process_commit(sta->sae) < 0)
706 return WLAN_STATUS_UNSPECIFIED_FAILURE;
707
708 ret = auth_sae_send_confirm(hapd, sta, bssid);
709 if (ret)
710 return ret;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700711 sae_set_state(sta, SAE_CONFIRMED, "Sent Confirm");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800712 sta->sae->sync = 0;
713 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800714 } else if (hapd->conf->mesh & MESH_ENABLED) {
715 /*
716 * In mesh case, follow SAE finite state machine and
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800717 * send Commit now, if sync count allows.
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800718 */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700719 if (sae_check_big_sync(hapd, sta))
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800720 return WLAN_STATUS_SUCCESS;
721 sta->sae->sync++;
722
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700723 ret = auth_sae_send_commit(hapd, sta, bssid, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800724 if (ret)
725 return ret;
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800726
727 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800728 } else {
729 /*
730 * For instructure BSS, send the postponed Confirm from
731 * Nothing -> Confirmed transition that was reduced to
732 * Nothing -> Committed above.
733 */
734 ret = auth_sae_send_confirm(hapd, sta, bssid);
735 if (ret)
736 return ret;
737
Roshan Pius3a1667e2018-07-03 15:17:14 -0700738 sae_set_state(sta, SAE_CONFIRMED, "Sent Confirm");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800739
740 /*
741 * Since this was triggered on Confirm RX, run another
742 * step to get to Accepted without waiting for
743 * additional events.
744 */
745 return sae_sm_step(hapd, sta, bssid, auth_transaction);
746 }
747 break;
748 case SAE_CONFIRMED:
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800749 sae_clear_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800750 if (auth_transaction == 1) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700751 if (sae_check_big_sync(hapd, sta))
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800752 return WLAN_STATUS_SUCCESS;
753 sta->sae->sync++;
754
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800755 ret = auth_sae_send_commit(hapd, sta, bssid, 1);
756 if (ret)
757 return ret;
758
759 if (sae_process_commit(sta->sae) < 0)
760 return WLAN_STATUS_UNSPECIFIED_FAILURE;
761
762 ret = auth_sae_send_confirm(hapd, sta, bssid);
763 if (ret)
764 return ret;
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800765
766 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800767 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700768 sta->sae->send_confirm = 0xffff;
Dmitry Shmidte4663042016-04-04 10:07:49 -0700769 sae_accept_sta(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800770 }
771 break;
772 case SAE_ACCEPTED:
Roshan Pius3a1667e2018-07-03 15:17:14 -0700773 if (auth_transaction == 1 &&
774 (hapd->conf->mesh & MESH_ENABLED)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800775 wpa_printf(MSG_DEBUG, "SAE: remove the STA (" MACSTR
776 ") doing reauthentication",
777 MAC2STR(sta->addr));
778 ap_free_sta(hapd, sta);
Dmitry Shmidte4663042016-04-04 10:07:49 -0700779 wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700780 } else if (auth_transaction == 1) {
781 wpa_printf(MSG_DEBUG, "SAE: Start reauthentication");
782 ret = auth_sae_send_commit(hapd, sta, bssid, 1);
783 if (ret)
784 return ret;
785 sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
786
787 if (sae_process_commit(sta->sae) < 0)
788 return WLAN_STATUS_UNSPECIFIED_FAILURE;
789 sta->sae->sync = 0;
790 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800791 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700792 if (sae_check_big_sync(hapd, sta))
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800793 return WLAN_STATUS_SUCCESS;
794 sta->sae->sync++;
795
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800796 ret = auth_sae_send_confirm(hapd, sta, bssid);
797 sae_clear_temp_data(sta->sae);
798 if (ret)
799 return ret;
800 }
801 break;
802 default:
803 wpa_printf(MSG_ERROR, "SAE: invalid state %d",
804 sta->sae->state);
805 return WLAN_STATUS_UNSPECIFIED_FAILURE;
806 }
807 return WLAN_STATUS_SUCCESS;
808}
809
810
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700811static void sae_pick_next_group(struct hostapd_data *hapd, struct sta_info *sta)
812{
813 struct sae_data *sae = sta->sae;
814 int i, *groups = hapd->conf->sae_groups;
815
816 if (sae->state != SAE_COMMITTED)
817 return;
818
819 wpa_printf(MSG_DEBUG, "SAE: Previously selected group: %d", sae->group);
820
821 for (i = 0; groups && groups[i] > 0; i++) {
822 if (sae->group == groups[i])
823 break;
824 }
825
826 if (!groups || groups[i] <= 0) {
827 wpa_printf(MSG_DEBUG,
828 "SAE: Previously selected group not found from the current configuration");
829 return;
830 }
831
832 for (;;) {
833 i++;
834 if (groups[i] <= 0) {
835 wpa_printf(MSG_DEBUG,
836 "SAE: No alternative group enabled");
837 return;
838 }
839
840 if (sae_set_group(sae, groups[i]) < 0)
841 continue;
842
843 break;
844 }
845 wpa_printf(MSG_DEBUG, "SAE: Selected new group: %d", groups[i]);
846}
847
848
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800849static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
850 const struct ieee80211_mgmt *mgmt, size_t len,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800851 u16 auth_transaction, u16 status_code)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800852{
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800853 int resp = WLAN_STATUS_SUCCESS;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800854 struct wpabuf *data = NULL;
855
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700856#ifdef CONFIG_TESTING_OPTIONS
857 if (hapd->conf->sae_reflection_attack && auth_transaction == 1) {
858 const u8 *pos, *end;
859
860 wpa_printf(MSG_DEBUG, "SAE: TESTING - reflection attack");
861 pos = mgmt->u.auth.variable;
862 end = ((const u8 *) mgmt) + len;
863 send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700864 auth_transaction, resp, pos, end - pos,
865 "auth-sae-reflection-attack");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700866 goto remove_sta;
867 }
868
869 if (hapd->conf->sae_commit_override && auth_transaction == 1) {
870 wpa_printf(MSG_DEBUG, "SAE: TESTING - commit override");
871 send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
872 auth_transaction, resp,
873 wpabuf_head(hapd->conf->sae_commit_override),
Roshan Pius3a1667e2018-07-03 15:17:14 -0700874 wpabuf_len(hapd->conf->sae_commit_override),
875 "sae-commit-override");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700876 goto remove_sta;
877 }
878#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800879 if (!sta->sae) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800880 if (auth_transaction != 1 ||
881 status_code != WLAN_STATUS_SUCCESS) {
882 resp = -1;
883 goto remove_sta;
884 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800885 sta->sae = os_zalloc(sizeof(*sta->sae));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800886 if (!sta->sae) {
887 resp = -1;
888 goto remove_sta;
889 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700890 sae_set_state(sta, SAE_NOTHING, "Init");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800891 sta->sae->sync = 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800892 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800893
Dmitry Shmidte4663042016-04-04 10:07:49 -0700894 if (sta->mesh_sae_pmksa_caching) {
895 wpa_printf(MSG_DEBUG,
896 "SAE: Cancel use of mesh PMKSA caching because peer starts SAE authentication");
897 wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
898 sta->mesh_sae_pmksa_caching = 0;
899 }
900
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800901 if (auth_transaction == 1) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800902 const u8 *token = NULL, *pos, *end;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800903 size_t token_len = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800904 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
905 HOSTAPD_LEVEL_DEBUG,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800906 "start SAE authentication (RX commit, status=%u)",
907 status_code);
908
909 if ((hapd->conf->mesh & MESH_ENABLED) &&
910 status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
911 sta->sae->tmp) {
912 pos = mgmt->u.auth.variable;
913 end = ((const u8 *) mgmt) + len;
914 if (pos + sizeof(le16) > end) {
915 wpa_printf(MSG_ERROR,
916 "SAE: Too short anti-clogging token request");
917 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
918 goto reply;
919 }
920 resp = sae_group_allowed(sta->sae,
921 hapd->conf->sae_groups,
922 WPA_GET_LE16(pos));
923 if (resp != WLAN_STATUS_SUCCESS) {
924 wpa_printf(MSG_ERROR,
925 "SAE: Invalid group in anti-clogging token request");
926 goto reply;
927 }
928 pos += sizeof(le16);
929
930 wpabuf_free(sta->sae->tmp->anti_clogging_token);
931 sta->sae->tmp->anti_clogging_token =
932 wpabuf_alloc_copy(pos, end - pos);
933 if (sta->sae->tmp->anti_clogging_token == NULL) {
934 wpa_printf(MSG_ERROR,
935 "SAE: Failed to alloc for anti-clogging token");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800936 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
937 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800938 }
939
940 /*
941 * IEEE Std 802.11-2012, 11.3.8.6.4: If the Status code
942 * is 76, a new Commit Message shall be constructed
943 * with the Anti-Clogging Token from the received
944 * Authentication frame, and the commit-scalar and
945 * COMMIT-ELEMENT previously sent.
946 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800947 resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 0);
948 if (resp != WLAN_STATUS_SUCCESS) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800949 wpa_printf(MSG_ERROR,
950 "SAE: Failed to send commit message");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800951 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800952 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700953 sae_set_state(sta, SAE_COMMITTED,
954 "Sent Commit (anti-clogging token case in mesh)");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800955 sta->sae->sync = 0;
956 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800957 return;
958 }
959
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700960 if ((hapd->conf->mesh & MESH_ENABLED) &&
961 status_code ==
962 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
963 sta->sae->tmp) {
964 wpa_printf(MSG_DEBUG,
965 "SAE: Peer did not accept our SAE group");
966 sae_pick_next_group(hapd, sta);
967 goto remove_sta;
968 }
969
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800970 if (status_code != WLAN_STATUS_SUCCESS)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800971 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800972
Roshan Pius3a1667e2018-07-03 15:17:14 -0700973 if (!(hapd->conf->mesh & MESH_ENABLED) &&
974 sta->sae->state == SAE_COMMITTED) {
975 /* This is needed in the infrastructure BSS case to
976 * address a sequence where a STA entry may remain in
977 * hostapd across two attempts to do SAE authentication
978 * by the same STA. The second attempt may end up trying
979 * to use a different group and that would not be
980 * allowed if we remain in Committed state with the
981 * previously set parameters. */
982 sae_set_state(sta, SAE_NOTHING,
983 "Clear existing state to allow restart");
984 sae_clear_data(sta->sae);
985 }
986
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800987 resp = sae_parse_commit(sta->sae, mgmt->u.auth.variable,
988 ((const u8 *) mgmt) + len -
989 mgmt->u.auth.variable, &token,
990 &token_len, hapd->conf->sae_groups);
Dmitry Shmidt41712582015-06-29 11:02:15 -0700991 if (resp == SAE_SILENTLY_DISCARD) {
992 wpa_printf(MSG_DEBUG,
993 "SAE: Drop commit message from " MACSTR " due to reflection attack",
994 MAC2STR(sta->addr));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800995 goto remove_sta;
Dmitry Shmidt41712582015-06-29 11:02:15 -0700996 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700997
998 if (resp == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER) {
999 wpa_msg(hapd->msg_ctx, MSG_INFO,
1000 WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER
1001 MACSTR, MAC2STR(sta->addr));
1002 sae_clear_retransmit_timer(hapd, sta);
1003 sae_set_state(sta, SAE_NOTHING,
1004 "Unknown Password Identifier");
1005 goto remove_sta;
1006 }
1007
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001008 if (token && check_sae_token(hapd, sta->addr, token, token_len)
1009 < 0) {
1010 wpa_printf(MSG_DEBUG, "SAE: Drop commit message with "
1011 "incorrect token from " MACSTR,
1012 MAC2STR(sta->addr));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001013 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1014 goto remove_sta;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001015 }
1016
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001017 if (resp != WLAN_STATUS_SUCCESS)
1018 goto reply;
1019
1020 if (!token && use_sae_anti_clogging(hapd)) {
1021 wpa_printf(MSG_DEBUG,
1022 "SAE: Request anti-clogging token from "
1023 MACSTR, MAC2STR(sta->addr));
1024 data = auth_build_token_req(hapd, sta->sae->group,
1025 sta->addr);
1026 resp = WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ;
1027 if (hapd->conf->mesh & MESH_ENABLED)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001028 sae_set_state(sta, SAE_NOTHING,
1029 "Request anti-clogging token case in mesh");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001030 goto reply;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001031 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001032
1033 resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001034 } else if (auth_transaction == 2) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001035 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1036 HOSTAPD_LEVEL_DEBUG,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001037 "SAE authentication (RX confirm, status=%u)",
1038 status_code);
1039 if (status_code != WLAN_STATUS_SUCCESS)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001040 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001041 if (sta->sae->state >= SAE_CONFIRMED ||
1042 !(hapd->conf->mesh & MESH_ENABLED)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001043 const u8 *var;
1044 size_t var_len;
1045 u16 peer_send_confirm;
1046
1047 var = mgmt->u.auth.variable;
1048 var_len = ((u8 *) mgmt) + len - mgmt->u.auth.variable;
1049 if (var_len < 2) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001050 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001051 goto reply;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001052 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001053
1054 peer_send_confirm = WPA_GET_LE16(var);
1055
1056 if (sta->sae->state == SAE_ACCEPTED &&
1057 (peer_send_confirm <= sta->sae->rc ||
1058 peer_send_confirm == 0xffff)) {
1059 wpa_printf(MSG_DEBUG,
1060 "SAE: Silently ignore unexpected Confirm from peer "
1061 MACSTR
1062 " (peer-send-confirm=%u Rc=%u)",
1063 MAC2STR(sta->addr),
1064 peer_send_confirm, sta->sae->rc);
1065 return;
1066 }
1067
1068 if (sae_check_confirm(sta->sae, var, var_len) < 0) {
1069 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1070 goto reply;
1071 }
1072 sta->sae->rc = peer_send_confirm;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001073 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001074 resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001075 } else {
1076 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1077 HOSTAPD_LEVEL_DEBUG,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001078 "unexpected SAE authentication transaction %u (status=%u)",
1079 auth_transaction, status_code);
1080 if (status_code != WLAN_STATUS_SUCCESS)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001081 goto remove_sta;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001082 resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1083 }
1084
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001085reply:
1086 if (resp != WLAN_STATUS_SUCCESS) {
1087 send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
1088 auth_transaction, resp,
1089 data ? wpabuf_head(data) : (u8 *) "",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001090 data ? wpabuf_len(data) : 0, "auth-sae");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001091 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001092
1093remove_sta:
1094 if (sta->added_unassoc && (resp != WLAN_STATUS_SUCCESS ||
1095 status_code != WLAN_STATUS_SUCCESS)) {
1096 hostapd_drv_sta_remove(hapd, sta->addr);
1097 sta->added_unassoc = 0;
1098 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001099 wpabuf_free(data);
1100}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001101
1102
1103/**
1104 * auth_sae_init_committed - Send COMMIT and start SAE in committed state
1105 * @hapd: BSS data for the device initiating the authentication
1106 * @sta: the peer to which commit authentication frame is sent
1107 *
1108 * This function implements Init event handling (IEEE Std 802.11-2012,
1109 * 11.3.8.6.3) in which initial COMMIT message is sent. Prior to calling, the
1110 * sta->sae structure should be initialized appropriately via a call to
1111 * sae_prepare_commit().
1112 */
1113int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta)
1114{
1115 int ret;
1116
1117 if (!sta->sae || !sta->sae->tmp)
1118 return -1;
1119
1120 if (sta->sae->state != SAE_NOTHING)
1121 return -1;
1122
1123 ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
1124 if (ret)
1125 return -1;
1126
Roshan Pius3a1667e2018-07-03 15:17:14 -07001127 sae_set_state(sta, SAE_COMMITTED, "Init and sent commit");
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001128 sta->sae->sync = 0;
1129 sae_set_retransmit_timer(hapd, sta);
1130
1131 return 0;
1132}
1133
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001134#endif /* CONFIG_SAE */
1135
1136
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001137static u16 wpa_res_to_status_code(int res)
1138{
1139 if (res == WPA_INVALID_GROUP)
1140 return WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1141 if (res == WPA_INVALID_PAIRWISE)
1142 return WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1143 if (res == WPA_INVALID_AKMP)
1144 return WLAN_STATUS_AKMP_NOT_VALID;
1145 if (res == WPA_ALLOC_FAIL)
1146 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1147#ifdef CONFIG_IEEE80211W
1148 if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
1149 return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
1150 if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001151 return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001152#endif /* CONFIG_IEEE80211W */
1153 if (res == WPA_INVALID_MDIE)
1154 return WLAN_STATUS_INVALID_MDIE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001155 if (res == WPA_INVALID_PMKID)
1156 return WLAN_STATUS_INVALID_PMKID;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001157 if (res != WPA_IE_OK)
1158 return WLAN_STATUS_INVALID_IE;
1159 return WLAN_STATUS_SUCCESS;
1160}
1161
1162
1163#ifdef CONFIG_FILS
1164
1165static void handle_auth_fils_finish(struct hostapd_data *hapd,
1166 struct sta_info *sta, u16 resp,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001167 struct wpabuf *data, int pub);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001168
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001169void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
1170 const u8 *pos, size_t len, u16 auth_alg,
1171 u16 auth_transaction, u16 status_code,
1172 void (*cb)(struct hostapd_data *hapd,
1173 struct sta_info *sta, u16 resp,
1174 struct wpabuf *data, int pub))
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001175{
1176 u16 resp = WLAN_STATUS_SUCCESS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001177 const u8 *end;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001178 struct ieee802_11_elems elems;
1179 int res;
1180 struct wpa_ie_data rsn;
1181 struct rsn_pmksa_cache_entry *pmksa = NULL;
1182
1183 if (auth_transaction != 1 || status_code != WLAN_STATUS_SUCCESS)
1184 return;
1185
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001186 end = pos + len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001187
1188 wpa_hexdump(MSG_DEBUG, "FILS: Authentication frame fields",
1189 pos, end - pos);
1190
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001191 /* TODO: FILS PK */
1192#ifdef CONFIG_FILS_SK_PFS
1193 if (auth_alg == WLAN_AUTH_FILS_SK_PFS) {
1194 u16 group;
1195 struct wpabuf *pub;
1196 size_t elem_len;
1197
1198 /* Using FILS PFS */
1199
1200 /* Finite Cyclic Group */
1201 if (end - pos < 2) {
1202 wpa_printf(MSG_DEBUG,
1203 "FILS: No room for Finite Cyclic Group");
1204 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1205 goto fail;
1206 }
1207 group = WPA_GET_LE16(pos);
1208 pos += 2;
1209 if (group != hapd->conf->fils_dh_group) {
1210 wpa_printf(MSG_DEBUG,
1211 "FILS: Unsupported Finite Cyclic Group: %u (expected %u)",
1212 group, hapd->conf->fils_dh_group);
1213 resp = WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1214 goto fail;
1215 }
1216
1217 crypto_ecdh_deinit(sta->fils_ecdh);
1218 sta->fils_ecdh = crypto_ecdh_init(group);
1219 if (!sta->fils_ecdh) {
1220 wpa_printf(MSG_INFO,
1221 "FILS: Could not initialize ECDH with group %d",
1222 group);
1223 resp = WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1224 goto fail;
1225 }
1226
1227 pub = crypto_ecdh_get_pubkey(sta->fils_ecdh, 1);
1228 if (!pub) {
1229 wpa_printf(MSG_DEBUG,
1230 "FILS: Failed to derive ECDH public key");
1231 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1232 goto fail;
1233 }
1234 elem_len = wpabuf_len(pub);
1235 wpabuf_free(pub);
1236
1237 /* Element */
1238 if ((size_t) (end - pos) < elem_len) {
1239 wpa_printf(MSG_DEBUG, "FILS: No room for Element");
1240 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1241 goto fail;
1242 }
1243
1244 wpabuf_free(sta->fils_g_sta);
1245 sta->fils_g_sta = wpabuf_alloc_copy(pos, elem_len);
1246 wpabuf_clear_free(sta->fils_dh_ss);
1247 sta->fils_dh_ss = crypto_ecdh_set_peerkey(sta->fils_ecdh, 1,
1248 pos, elem_len);
1249 if (!sta->fils_dh_ss) {
1250 wpa_printf(MSG_DEBUG, "FILS: ECDH operation failed");
1251 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1252 goto fail;
1253 }
1254 wpa_hexdump_buf_key(MSG_DEBUG, "FILS: DH_SS", sta->fils_dh_ss);
1255 pos += elem_len;
1256 } else {
1257 crypto_ecdh_deinit(sta->fils_ecdh);
1258 sta->fils_ecdh = NULL;
1259 wpabuf_clear_free(sta->fils_dh_ss);
1260 sta->fils_dh_ss = NULL;
1261 }
1262#endif /* CONFIG_FILS_SK_PFS */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001263
1264 wpa_hexdump(MSG_DEBUG, "FILS: Remaining IEs", pos, end - pos);
1265 if (ieee802_11_parse_elems(pos, end - pos, &elems, 1) == ParseFailed) {
1266 wpa_printf(MSG_DEBUG, "FILS: Could not parse elements");
1267 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1268 goto fail;
1269 }
1270
1271 /* RSNE */
1272 wpa_hexdump(MSG_DEBUG, "FILS: RSN element",
1273 elems.rsn_ie, elems.rsn_ie_len);
1274 if (!elems.rsn_ie ||
1275 wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
1276 &rsn) < 0) {
1277 wpa_printf(MSG_DEBUG, "FILS: No valid RSN element");
1278 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1279 goto fail;
1280 }
1281
1282 if (!sta->wpa_sm)
1283 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr,
1284 NULL);
1285 if (!sta->wpa_sm) {
1286 wpa_printf(MSG_DEBUG,
1287 "FILS: Failed to initialize RSN state machine");
1288 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1289 goto fail;
1290 }
1291
1292 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
1293 elems.rsn_ie - 2, elems.rsn_ie_len + 2,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001294 elems.mdie, elems.mdie_len, NULL, 0);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001295 resp = wpa_res_to_status_code(res);
1296 if (resp != WLAN_STATUS_SUCCESS)
1297 goto fail;
1298
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001299 if (!elems.fils_nonce) {
1300 wpa_printf(MSG_DEBUG, "FILS: No FILS Nonce field");
1301 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1302 goto fail;
1303 }
1304 wpa_hexdump(MSG_DEBUG, "FILS: SNonce", elems.fils_nonce,
1305 FILS_NONCE_LEN);
1306 os_memcpy(sta->fils_snonce, elems.fils_nonce, FILS_NONCE_LEN);
1307
1308 /* PMKID List */
1309 if (rsn.pmkid && rsn.num_pmkid > 0) {
1310 u8 num;
1311 const u8 *pmkid;
1312
1313 wpa_hexdump(MSG_DEBUG, "FILS: PMKID List",
1314 rsn.pmkid, rsn.num_pmkid * PMKID_LEN);
1315
1316 pmkid = rsn.pmkid;
1317 num = rsn.num_pmkid;
1318 while (num) {
1319 wpa_hexdump(MSG_DEBUG, "FILS: PMKID", pmkid, PMKID_LEN);
1320 pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr,
1321 pmkid);
1322 if (pmksa)
1323 break;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001324 pmksa = wpa_auth_pmksa_get_fils_cache_id(hapd->wpa_auth,
1325 sta->addr,
1326 pmkid);
1327 if (pmksa)
1328 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001329 pmkid += PMKID_LEN;
1330 num--;
1331 }
1332 }
1333 if (pmksa && wpa_auth_sta_key_mgmt(sta->wpa_sm) != pmksa->akmp) {
1334 wpa_printf(MSG_DEBUG,
1335 "FILS: Matching PMKSA cache entry has different AKMP (0x%x != 0x%x) - ignore",
1336 wpa_auth_sta_key_mgmt(sta->wpa_sm), pmksa->akmp);
1337 pmksa = NULL;
1338 }
1339 if (pmksa)
1340 wpa_printf(MSG_DEBUG, "FILS: Found matching PMKSA cache entry");
1341
1342 /* FILS Session */
1343 if (!elems.fils_session) {
1344 wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
1345 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1346 goto fail;
1347 }
1348 wpa_hexdump(MSG_DEBUG, "FILS: FILS Session", elems.fils_session,
1349 FILS_SESSION_LEN);
1350 os_memcpy(sta->fils_session, elems.fils_session, FILS_SESSION_LEN);
1351
1352 /* FILS Wrapped Data */
1353 if (elems.fils_wrapped_data) {
1354 wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data",
1355 elems.fils_wrapped_data,
1356 elems.fils_wrapped_data_len);
1357 if (!pmksa) {
1358#ifndef CONFIG_NO_RADIUS
1359 if (!sta->eapol_sm) {
1360 sta->eapol_sm =
1361 ieee802_1x_alloc_eapol_sm(hapd, sta);
1362 }
1363 wpa_printf(MSG_DEBUG,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001364 "FILS: Forward EAP-Initiate/Re-auth to authentication server");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001365 ieee802_1x_encapsulate_radius(
1366 hapd, sta, elems.fils_wrapped_data,
1367 elems.fils_wrapped_data_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001368 sta->fils_pending_cb = cb;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001369 wpa_printf(MSG_DEBUG,
1370 "FILS: Will send Authentication frame once the response from authentication server is available");
1371 sta->flags |= WLAN_STA_PENDING_FILS_ERP;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001372 /* Calculate pending PMKID here so that we do not need
1373 * to maintain a copy of the EAP-Initiate/Reauth
1374 * message. */
1375 if (fils_pmkid_erp(wpa_auth_sta_key_mgmt(sta->wpa_sm),
1376 elems.fils_wrapped_data,
1377 elems.fils_wrapped_data_len,
1378 sta->fils_erp_pmkid) == 0)
1379 sta->fils_erp_pmkid_set = 1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001380 return;
1381#else /* CONFIG_NO_RADIUS */
1382 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1383 goto fail;
1384#endif /* CONFIG_NO_RADIUS */
1385 }
1386 }
1387
1388fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001389 if (cb) {
1390 struct wpabuf *data;
1391 int pub = 0;
1392
1393 data = prepare_auth_resp_fils(hapd, sta, &resp, pmksa, NULL,
1394 NULL, 0, &pub);
1395 if (!data) {
1396 wpa_printf(MSG_DEBUG,
1397 "%s: prepare_auth_resp_fils() returned failure",
1398 __func__);
1399 }
1400
1401 cb(hapd, sta, resp, data, pub);
1402 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001403}
1404
1405
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001406static struct wpabuf *
1407prepare_auth_resp_fils(struct hostapd_data *hapd,
1408 struct sta_info *sta, u16 *resp,
1409 struct rsn_pmksa_cache_entry *pmksa,
1410 struct wpabuf *erp_resp,
1411 const u8 *msk, size_t msk_len,
1412 int *is_pub)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001413{
1414 u8 fils_nonce[FILS_NONCE_LEN];
1415 size_t ielen;
1416 struct wpabuf *data = NULL;
1417 const u8 *ie;
1418 u8 *ie_buf = NULL;
1419 const u8 *pmk = NULL;
1420 size_t pmk_len = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08001421 u8 pmk_buf[PMK_LEN_MAX];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001422 struct wpabuf *pub = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001423
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001424 if (*resp != WLAN_STATUS_SUCCESS)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001425 goto fail;
1426
1427 ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen);
1428 if (!ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001429 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001430 goto fail;
1431 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001432
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001433 if (pmksa) {
1434 /* Add PMKID of the selected PMKSA into RSNE */
1435 ie_buf = os_malloc(ielen + 2 + 2 + PMKID_LEN);
1436 if (!ie_buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001437 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001438 goto fail;
1439 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001440
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001441 os_memcpy(ie_buf, ie, ielen);
1442 if (wpa_insert_pmkid(ie_buf, &ielen, pmksa->pmkid) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001443 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001444 goto fail;
1445 }
1446 ie = ie_buf;
1447 }
1448
1449 if (random_get_bytes(fils_nonce, FILS_NONCE_LEN) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001450 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001451 goto fail;
1452 }
1453 wpa_hexdump(MSG_DEBUG, "RSN: Generated FILS Nonce",
1454 fils_nonce, FILS_NONCE_LEN);
1455
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001456#ifdef CONFIG_FILS_SK_PFS
1457 if (sta->fils_dh_ss && sta->fils_ecdh) {
1458 pub = crypto_ecdh_get_pubkey(sta->fils_ecdh, 1);
1459 if (!pub) {
1460 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1461 goto fail;
1462 }
1463 }
1464#endif /* CONFIG_FILS_SK_PFS */
1465
1466 data = wpabuf_alloc(1000 + ielen + (pub ? wpabuf_len(pub) : 0));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001467 if (!data) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001468 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001469 goto fail;
1470 }
1471
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001472 /* TODO: FILS PK */
1473#ifdef CONFIG_FILS_SK_PFS
1474 if (pub) {
1475 /* Finite Cyclic Group */
1476 wpabuf_put_le16(data, hapd->conf->fils_dh_group);
1477
1478 /* Element */
1479 wpabuf_put_buf(data, pub);
1480 }
1481#endif /* CONFIG_FILS_SK_PFS */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001482
1483 /* RSNE */
1484 wpabuf_put_data(data, ie, ielen);
1485
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001486 /* MDE when using FILS+FT (already included in ie,ielen with RSNE) */
1487
1488#ifdef CONFIG_IEEE80211R_AP
1489 if (wpa_key_mgmt_ft(wpa_auth_sta_key_mgmt(sta->wpa_sm))) {
1490 /* FTE[R1KH-ID,R0KH-ID] when using FILS+FT */
1491 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001492 int use_sha384 = wpa_key_mgmt_sha384(
1493 wpa_auth_sta_key_mgmt(sta->wpa_sm));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001494
Roshan Pius3a1667e2018-07-03 15:17:14 -07001495 res = wpa_auth_write_fte(hapd->wpa_auth, use_sha384,
1496 wpabuf_put(data, 0),
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001497 wpabuf_tailroom(data));
1498 if (res < 0) {
1499 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1500 goto fail;
1501 }
1502 wpabuf_put(data, res);
1503 }
1504#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001505
1506 /* FILS Nonce */
1507 wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
1508 wpabuf_put_u8(data, 1 + FILS_NONCE_LEN); /* Length */
1509 /* Element ID Extension */
1510 wpabuf_put_u8(data, WLAN_EID_EXT_FILS_NONCE);
1511 wpabuf_put_data(data, fils_nonce, FILS_NONCE_LEN);
1512
1513 /* FILS Session */
1514 wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
1515 wpabuf_put_u8(data, 1 + FILS_SESSION_LEN); /* Length */
1516 /* Element ID Extension */
1517 wpabuf_put_u8(data, WLAN_EID_EXT_FILS_SESSION);
1518 wpabuf_put_data(data, sta->fils_session, FILS_SESSION_LEN);
1519
1520 /* FILS Wrapped Data */
1521 if (!pmksa && erp_resp) {
1522 wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
1523 wpabuf_put_u8(data, 1 + wpabuf_len(erp_resp)); /* Length */
1524 /* Element ID Extension */
1525 wpabuf_put_u8(data, WLAN_EID_EXT_FILS_WRAPPED_DATA);
1526 wpabuf_put_buf(data, erp_resp);
1527
Paul Stewart092955c2017-02-06 09:13:09 -08001528 if (fils_rmsk_to_pmk(wpa_auth_sta_key_mgmt(sta->wpa_sm),
1529 msk, msk_len, sta->fils_snonce, fils_nonce,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001530 sta->fils_dh_ss ?
1531 wpabuf_head(sta->fils_dh_ss) : NULL,
1532 sta->fils_dh_ss ?
1533 wpabuf_len(sta->fils_dh_ss) : 0,
1534 pmk_buf, &pmk_len)) {
Paul Stewart092955c2017-02-06 09:13:09 -08001535 wpa_printf(MSG_DEBUG, "FILS: Failed to derive PMK");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001536 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Paul Stewart092955c2017-02-06 09:13:09 -08001537 wpabuf_free(data);
1538 data = NULL;
1539 goto fail;
1540 }
1541 pmk = pmk_buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001542
1543 /* Don't use DHss in PTK derivation if PMKSA caching is not
1544 * used. */
1545 wpabuf_clear_free(sta->fils_dh_ss);
1546 sta->fils_dh_ss = NULL;
1547
1548 if (sta->fils_erp_pmkid_set) {
1549 /* TODO: get PMKLifetime from WPA parameters */
1550 unsigned int dot11RSNAConfigPMKLifetime = 43200;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001551 int session_timeout;
1552
1553 session_timeout = dot11RSNAConfigPMKLifetime;
1554 if (sta->session_timeout_set) {
1555 struct os_reltime now, diff;
1556
1557 os_get_reltime(&now);
1558 os_reltime_sub(&sta->session_timeout, &now,
1559 &diff);
1560 session_timeout = diff.sec;
1561 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001562
1563 sta->fils_erp_pmkid_set = 0;
1564 if (wpa_auth_pmksa_add2(
1565 hapd->wpa_auth, sta->addr,
1566 pmk, pmk_len,
1567 sta->fils_erp_pmkid,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001568 session_timeout,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001569 wpa_auth_sta_key_mgmt(sta->wpa_sm)) < 0) {
1570 wpa_printf(MSG_ERROR,
1571 "FILS: Failed to add PMKSA cache entry based on ERP");
1572 }
1573 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001574 } else if (pmksa) {
1575 pmk = pmksa->pmk;
1576 pmk_len = pmksa->pmk_len;
1577 }
1578
1579 if (!pmk) {
1580 wpa_printf(MSG_DEBUG, "FILS: No PMK available");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001581 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001582 wpabuf_free(data);
1583 data = NULL;
1584 goto fail;
1585 }
1586
1587 if (fils_auth_pmk_to_ptk(sta->wpa_sm, pmk, pmk_len,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001588 sta->fils_snonce, fils_nonce,
1589 sta->fils_dh_ss ?
1590 wpabuf_head(sta->fils_dh_ss) : NULL,
1591 sta->fils_dh_ss ?
1592 wpabuf_len(sta->fils_dh_ss) : 0,
1593 sta->fils_g_sta, pub) < 0) {
1594 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001595 wpabuf_free(data);
1596 data = NULL;
1597 goto fail;
1598 }
1599
1600fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001601 if (is_pub)
1602 *is_pub = pub != NULL;
1603 os_free(ie_buf);
1604 wpabuf_free(pub);
1605 wpabuf_clear_free(sta->fils_dh_ss);
1606 sta->fils_dh_ss = NULL;
1607#ifdef CONFIG_FILS_SK_PFS
1608 crypto_ecdh_deinit(sta->fils_ecdh);
1609 sta->fils_ecdh = NULL;
1610#endif /* CONFIG_FILS_SK_PFS */
1611 return data;
1612}
1613
1614
1615static void handle_auth_fils_finish(struct hostapd_data *hapd,
1616 struct sta_info *sta, u16 resp,
1617 struct wpabuf *data, int pub)
1618{
1619 u16 auth_alg;
1620
1621 auth_alg = (pub ||
1622 resp == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) ?
1623 WLAN_AUTH_FILS_SK_PFS : WLAN_AUTH_FILS_SK;
1624 send_auth_reply(hapd, sta->addr, hapd->own_addr, auth_alg, 2, resp,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001625 data ? wpabuf_head(data) : (u8 *) "",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001626 data ? wpabuf_len(data) : 0, "auth-fils-finish");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001627 wpabuf_free(data);
1628
1629 if (resp == WLAN_STATUS_SUCCESS) {
1630 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1631 HOSTAPD_LEVEL_DEBUG,
1632 "authentication OK (FILS)");
1633 sta->flags |= WLAN_STA_AUTH;
1634 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001635 sta->auth_alg = pub ? WLAN_AUTH_FILS_SK_PFS : WLAN_AUTH_FILS_SK;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001636 mlme_authenticate_indication(hapd, sta);
1637 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001638}
1639
1640
1641void ieee802_11_finish_fils_auth(struct hostapd_data *hapd,
1642 struct sta_info *sta, int success,
1643 struct wpabuf *erp_resp,
1644 const u8 *msk, size_t msk_len)
1645{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001646 struct wpabuf *data;
1647 int pub = 0;
1648 u16 resp;
1649
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001650 sta->flags &= ~WLAN_STA_PENDING_FILS_ERP;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001651
1652 if (!sta->fils_pending_cb)
1653 return;
1654 resp = success ? WLAN_STATUS_SUCCESS : WLAN_STATUS_UNSPECIFIED_FAILURE;
1655 data = prepare_auth_resp_fils(hapd, sta, &resp, NULL, erp_resp,
1656 msk, msk_len, &pub);
1657 if (!data) {
1658 wpa_printf(MSG_DEBUG,
1659 "%s: prepare_auth_resp_fils() returned failure",
1660 __func__);
1661 }
1662 sta->fils_pending_cb(hapd, sta, resp, data, pub);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001663}
1664
1665#endif /* CONFIG_FILS */
1666
1667
Roshan Pius3a1667e2018-07-03 15:17:14 -07001668int
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001669ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
1670 const u8 *msg, size_t len, u32 *session_timeout,
1671 u32 *acct_interim_interval,
1672 struct vlan_description *vlan_id,
1673 struct hostapd_sta_wpa_psk_short **psk,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001674 char **identity, char **radius_cui, int is_probe_req)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001675{
1676 int res;
1677
1678 os_memset(vlan_id, 0, sizeof(*vlan_id));
1679 res = hostapd_allowed_address(hapd, addr, msg, len,
1680 session_timeout, acct_interim_interval,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001681 vlan_id, psk, identity, radius_cui,
1682 is_probe_req);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001683
1684 if (res == HOSTAPD_ACL_REJECT) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08001685 if (!is_probe_req)
1686 wpa_printf(MSG_DEBUG,
1687 "Station " MACSTR
1688 " not allowed to authenticate",
1689 MAC2STR(addr));
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001690 return HOSTAPD_ACL_REJECT;
1691 }
1692
1693 if (res == HOSTAPD_ACL_PENDING) {
1694 wpa_printf(MSG_DEBUG, "Authentication frame from " MACSTR
1695 " waiting for an external authentication",
1696 MAC2STR(addr));
1697 /* Authentication code will re-send the authentication frame
1698 * after it has received (and cached) information from the
1699 * external source. */
1700 return HOSTAPD_ACL_PENDING;
1701 }
1702
1703 return res;
1704}
1705
1706
1707static int
1708ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
1709 int res, u32 session_timeout,
1710 u32 acct_interim_interval,
1711 struct vlan_description *vlan_id,
1712 struct hostapd_sta_wpa_psk_short **psk,
1713 char **identity, char **radius_cui)
1714{
1715 if (vlan_id->notempty &&
1716 !hostapd_vlan_valid(hapd->conf->vlan, vlan_id)) {
1717 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
1718 HOSTAPD_LEVEL_INFO,
1719 "Invalid VLAN %d%s received from RADIUS server",
1720 vlan_id->untagged,
1721 vlan_id->tagged[0] ? "+" : "");
1722 return -1;
1723 }
1724 if (ap_sta_set_vlan(hapd, sta, vlan_id) < 0)
1725 return -1;
1726 if (sta->vlan_id)
1727 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
1728 HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
1729
1730 hostapd_free_psk_list(sta->psk);
1731 if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
1732 sta->psk = *psk;
1733 *psk = NULL;
1734 } else {
1735 sta->psk = NULL;
1736 }
1737
Roshan Pius3a1667e2018-07-03 15:17:14 -07001738 os_free(sta->identity);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001739 sta->identity = *identity;
1740 *identity = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001741
1742 os_free(sta->radius_cui);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001743 sta->radius_cui = *radius_cui;
1744 *radius_cui = NULL;
1745
1746 if (hapd->conf->acct_interim_interval == 0 && acct_interim_interval)
1747 sta->acct_interim_interval = acct_interim_interval;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001748 if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT) {
1749 sta->session_timeout_set = 1;
1750 os_get_reltime(&sta->session_timeout);
1751 sta->session_timeout.sec += session_timeout;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001752 ap_sta_session_timeout(hapd, sta, session_timeout);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001753 } else {
1754 sta->session_timeout_set = 0;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001755 ap_sta_no_session_timeout(hapd, sta);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001756 }
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001757
1758 return 0;
1759}
1760
1761
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001762static void handle_auth(struct hostapd_data *hapd,
Hai Shalom74f70d42019-02-11 14:42:39 -08001763 const struct ieee80211_mgmt *mgmt, size_t len,
1764 int rssi)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001765{
1766 u16 auth_alg, auth_transaction, status_code;
1767 u16 resp = WLAN_STATUS_SUCCESS;
1768 struct sta_info *sta = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001769 int res, reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001770 u16 fc;
1771 const u8 *challenge = NULL;
1772 u32 session_timeout, acct_interim_interval;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001773 struct vlan_description vlan_id;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001774 struct hostapd_sta_wpa_psk_short *psk = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001775 u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
1776 size_t resp_ies_len = 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001777 char *identity = NULL;
1778 char *radius_cui = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001779 u16 seq_ctrl;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001780
1781 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001782 wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
1783 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001784 return;
1785 }
1786
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001787#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07001788 if (hapd->iconf->ignore_auth_probability > 0.0 &&
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001789 drand48() < hapd->iconf->ignore_auth_probability) {
1790 wpa_printf(MSG_INFO,
1791 "TESTING: ignoring auth frame from " MACSTR,
1792 MAC2STR(mgmt->sa));
1793 return;
1794 }
1795#endif /* CONFIG_TESTING_OPTIONS */
1796
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001797 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
1798 auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
1799 status_code = le_to_host16(mgmt->u.auth.status_code);
1800 fc = le_to_host16(mgmt->frame_control);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001801 seq_ctrl = le_to_host16(mgmt->seq_ctrl);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001802
1803 if (len >= IEEE80211_HDRLEN + sizeof(mgmt->u.auth) +
1804 2 + WLAN_AUTH_CHALLENGE_LEN &&
1805 mgmt->u.auth.variable[0] == WLAN_EID_CHALLENGE &&
1806 mgmt->u.auth.variable[1] == WLAN_AUTH_CHALLENGE_LEN)
1807 challenge = &mgmt->u.auth.variable[2];
1808
1809 wpa_printf(MSG_DEBUG, "authentication: STA=" MACSTR " auth_alg=%d "
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001810 "auth_transaction=%d status_code=%d wep=%d%s "
1811 "seq_ctrl=0x%x%s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001812 MAC2STR(mgmt->sa), auth_alg, auth_transaction,
1813 status_code, !!(fc & WLAN_FC_ISWEP),
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001814 challenge ? " challenge" : "",
1815 seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001816
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001817#ifdef CONFIG_NO_RC4
1818 if (auth_alg == WLAN_AUTH_SHARED_KEY) {
1819 wpa_printf(MSG_INFO,
1820 "Unsupported authentication algorithm (%d)",
1821 auth_alg);
1822 resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1823 goto fail;
1824 }
1825#endif /* CONFIG_NO_RC4 */
1826
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001827 if (hapd->tkip_countermeasures) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001828 wpa_printf(MSG_DEBUG,
1829 "Ongoing TKIP countermeasures (Michael MIC failure) - reject authentication");
1830 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001831 goto fail;
1832 }
1833
1834 if (!(((hapd->conf->auth_algs & WPA_AUTH_ALG_OPEN) &&
1835 auth_alg == WLAN_AUTH_OPEN) ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001836#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001837 (hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001838 auth_alg == WLAN_AUTH_FT) ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001839#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001840#ifdef CONFIG_SAE
1841 (hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
1842 auth_alg == WLAN_AUTH_SAE) ||
1843#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001844#ifdef CONFIG_FILS
1845 (hapd->conf->wpa && wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt) &&
1846 auth_alg == WLAN_AUTH_FILS_SK) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001847 (hapd->conf->wpa && wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt) &&
1848 hapd->conf->fils_dh_group &&
1849 auth_alg == WLAN_AUTH_FILS_SK_PFS) ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001850#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001851 ((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) &&
1852 auth_alg == WLAN_AUTH_SHARED_KEY))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001853 wpa_printf(MSG_INFO, "Unsupported authentication algorithm (%d)",
1854 auth_alg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001855 resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1856 goto fail;
1857 }
1858
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001859 if (!(auth_transaction == 1 || auth_alg == WLAN_AUTH_SAE ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001860 (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001861 wpa_printf(MSG_INFO, "Unknown authentication transaction number (%d)",
1862 auth_transaction);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001863 resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1864 goto fail;
1865 }
1866
1867 if (os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001868 wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to authenticate",
1869 MAC2STR(mgmt->sa));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001870 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1871 goto fail;
1872 }
1873
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001874 if (hapd->conf->no_auth_if_seen_on) {
1875 struct hostapd_data *other;
1876
1877 other = sta_track_seen_on(hapd->iface, mgmt->sa,
1878 hapd->conf->no_auth_if_seen_on);
1879 if (other) {
1880 u8 *pos;
1881 u32 info;
1882 u8 op_class, channel, phytype;
1883
1884 wpa_printf(MSG_DEBUG, "%s: Reject authentication from "
1885 MACSTR " since STA has been seen on %s",
1886 hapd->conf->iface, MAC2STR(mgmt->sa),
1887 hapd->conf->no_auth_if_seen_on);
1888
1889 resp = WLAN_STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION;
1890 pos = &resp_ies[0];
1891 *pos++ = WLAN_EID_NEIGHBOR_REPORT;
1892 *pos++ = 13;
1893 os_memcpy(pos, other->own_addr, ETH_ALEN);
1894 pos += ETH_ALEN;
1895 info = 0; /* TODO: BSSID Information */
1896 WPA_PUT_LE32(pos, info);
1897 pos += 4;
1898 if (other->iconf->hw_mode == HOSTAPD_MODE_IEEE80211AD)
1899 phytype = 8; /* dmg */
1900 else if (other->iconf->ieee80211ac)
1901 phytype = 9; /* vht */
1902 else if (other->iconf->ieee80211n)
1903 phytype = 7; /* ht */
1904 else if (other->iconf->hw_mode ==
1905 HOSTAPD_MODE_IEEE80211A)
1906 phytype = 4; /* ofdm */
1907 else if (other->iconf->hw_mode ==
1908 HOSTAPD_MODE_IEEE80211G)
1909 phytype = 6; /* erp */
1910 else
1911 phytype = 5; /* hrdsss */
1912 if (ieee80211_freq_to_channel_ext(
1913 hostapd_hw_get_freq(other,
1914 other->iconf->channel),
1915 other->iconf->secondary_channel,
1916 other->iconf->ieee80211ac,
1917 &op_class, &channel) == NUM_HOSTAPD_MODES) {
1918 op_class = 0;
1919 channel = other->iconf->channel;
1920 }
1921 *pos++ = op_class;
1922 *pos++ = channel;
1923 *pos++ = phytype;
1924 resp_ies_len = pos - &resp_ies[0];
1925 goto fail;
1926 }
1927 }
1928
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001929 res = ieee802_11_allowed_address(
1930 hapd, mgmt->sa, (const u8 *) mgmt, len, &session_timeout,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001931 &acct_interim_interval, &vlan_id, &psk, &identity, &radius_cui,
1932 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001933 if (res == HOSTAPD_ACL_REJECT) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001934 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
1935 "Ignore Authentication frame from " MACSTR
1936 " due to ACL reject", MAC2STR(mgmt->sa));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001937 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1938 goto fail;
1939 }
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001940 if (res == HOSTAPD_ACL_PENDING)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001941 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001942
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001943 sta = ap_get_sta(hapd, mgmt->sa);
1944 if (sta) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001945 sta->flags &= ~WLAN_STA_PENDING_FILS_ERP;
Hai Shalom74f70d42019-02-11 14:42:39 -08001946 sta->ft_over_ds = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001947 if ((fc & WLAN_FC_RETRY) &&
1948 sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ &&
1949 sta->last_seq_ctrl == seq_ctrl &&
1950 sta->last_subtype == WLAN_FC_STYPE_AUTH) {
1951 hostapd_logger(hapd, sta->addr,
1952 HOSTAPD_MODULE_IEEE80211,
1953 HOSTAPD_LEVEL_DEBUG,
1954 "Drop repeated authentication frame seq_ctrl=0x%x",
1955 seq_ctrl);
1956 return;
1957 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001958#ifdef CONFIG_MESH
1959 if ((hapd->conf->mesh & MESH_ENABLED) &&
1960 sta->plink_state == PLINK_BLOCKED) {
1961 wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
1962 " is blocked - drop Authentication frame",
1963 MAC2STR(mgmt->sa));
1964 return;
1965 }
1966#endif /* CONFIG_MESH */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001967 } else {
1968#ifdef CONFIG_MESH
1969 if (hapd->conf->mesh & MESH_ENABLED) {
1970 /* if the mesh peer is not available, we don't do auth.
1971 */
1972 wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001973 " not yet known - drop Authentication frame",
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001974 MAC2STR(mgmt->sa));
1975 /*
1976 * Save a copy of the frame so that it can be processed
1977 * if a new peer entry is added shortly after this.
1978 */
1979 wpabuf_free(hapd->mesh_pending_auth);
1980 hapd->mesh_pending_auth = wpabuf_alloc_copy(mgmt, len);
1981 os_get_reltime(&hapd->mesh_pending_auth_time);
1982 return;
1983 }
1984#endif /* CONFIG_MESH */
1985
1986 sta = ap_sta_add(hapd, mgmt->sa);
1987 if (!sta) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001988 wpa_printf(MSG_DEBUG, "ap_sta_add() failed");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001989 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1990 goto fail;
1991 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001992 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001993 sta->last_seq_ctrl = seq_ctrl;
1994 sta->last_subtype = WLAN_FC_STYPE_AUTH;
Hai Shalom74f70d42019-02-11 14:42:39 -08001995#ifdef CONFIG_MBO
1996 sta->auth_rssi = rssi;
1997#endif /* CONFIG_MBO */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001998
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001999 res = ieee802_11_set_radius_info(
2000 hapd, sta, res, session_timeout, acct_interim_interval,
2001 &vlan_id, &psk, &identity, &radius_cui);
2002 if (res) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002003 wpa_printf(MSG_DEBUG, "ieee802_11_set_radius_info() failed");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002004 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
2005 goto fail;
2006 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002007
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002008 sta->flags &= ~WLAN_STA_PREAUTH;
2009 ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
2010
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002011 /*
2012 * If the driver supports full AP client state, add a station to the
2013 * driver before sending authentication reply to make sure the driver
2014 * has resources, and not to go through the entire authentication and
2015 * association handshake, and fail it at the end.
2016 *
2017 * If this is not the first transaction, in a multi-step authentication
2018 * algorithm, the station already exists in the driver
2019 * (sta->added_unassoc = 1) so skip it.
2020 *
2021 * In mesh mode, the station was already added to the driver when the
2022 * NEW_PEER_CANDIDATE event is received.
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08002023 *
2024 * If PMF was negotiated for the existing association, skip this to
2025 * avoid dropping the STA entry and the associated keys. This is needed
2026 * to allow the original connection work until the attempt can complete
2027 * (re)association, so that unprotected Authentication frame cannot be
2028 * used to bypass PMF protection.
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002029 */
2030 if (FULL_AP_CLIENT_STATE_SUPP(hapd->iface->drv_flags) &&
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08002031 (!(sta->flags & WLAN_STA_MFP) || !ap_sta_is_authorized(sta)) &&
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002032 !(hapd->conf->mesh & MESH_ENABLED) &&
2033 !(sta->added_unassoc)) {
2034 /*
2035 * If a station that is already associated to the AP, is trying
2036 * to authenticate again, remove the STA entry, in order to make
2037 * sure the STA PS state gets cleared and configuration gets
2038 * updated. To handle this, station's added_unassoc flag is
2039 * cleared once the station has completed association.
2040 */
Hai Shalomce48b4a2018-09-05 11:41:35 -07002041 ap_sta_set_authorized(hapd, sta, 0);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002042 hostapd_drv_sta_remove(hapd, sta->addr);
2043 sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_AUTH |
2044 WLAN_STA_AUTHORIZED);
2045
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07002046 if (hostapd_sta_add(hapd, sta->addr, 0, 0, NULL, 0, 0,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002047 NULL, NULL, sta->flags, 0, 0, 0, 0)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002048 hostapd_logger(hapd, sta->addr,
2049 HOSTAPD_MODULE_IEEE80211,
2050 HOSTAPD_LEVEL_NOTICE,
2051 "Could not add STA to kernel driver");
2052 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
2053 goto fail;
2054 }
2055
2056 sta->added_unassoc = 1;
2057 }
2058
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002059 switch (auth_alg) {
2060 case WLAN_AUTH_OPEN:
2061 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2062 HOSTAPD_LEVEL_DEBUG,
2063 "authentication OK (open system)");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002064 sta->flags |= WLAN_STA_AUTH;
2065 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
2066 sta->auth_alg = WLAN_AUTH_OPEN;
2067 mlme_authenticate_indication(hapd, sta);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002068 break;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002069#ifndef CONFIG_NO_RC4
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002070 case WLAN_AUTH_SHARED_KEY:
2071 resp = auth_shared_key(hapd, sta, auth_transaction, challenge,
2072 fc & WLAN_FC_ISWEP);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002073 if (resp != 0)
2074 wpa_printf(MSG_DEBUG,
2075 "auth_shared_key() failed: status=%d", resp);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002076 sta->auth_alg = WLAN_AUTH_SHARED_KEY;
2077 mlme_authenticate_indication(hapd, sta);
2078 if (sta->challenge && auth_transaction == 1) {
2079 resp_ies[0] = WLAN_EID_CHALLENGE;
2080 resp_ies[1] = WLAN_AUTH_CHALLENGE_LEN;
2081 os_memcpy(resp_ies + 2, sta->challenge,
2082 WLAN_AUTH_CHALLENGE_LEN);
2083 resp_ies_len = 2 + WLAN_AUTH_CHALLENGE_LEN;
2084 }
2085 break;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002086#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002087#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002088 case WLAN_AUTH_FT:
2089 sta->auth_alg = WLAN_AUTH_FT;
2090 if (sta->wpa_sm == NULL)
2091 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002092 sta->addr, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002093 if (sta->wpa_sm == NULL) {
2094 wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA "
2095 "state machine");
2096 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
2097 goto fail;
2098 }
2099 wpa_ft_process_auth(sta->wpa_sm, mgmt->bssid,
2100 auth_transaction, mgmt->u.auth.variable,
2101 len - IEEE80211_HDRLEN -
2102 sizeof(mgmt->u.auth),
2103 handle_auth_ft_finish, hapd);
2104 /* handle_auth_ft_finish() callback will complete auth. */
2105 return;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002106#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002107#ifdef CONFIG_SAE
2108 case WLAN_AUTH_SAE:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002109#ifdef CONFIG_MESH
2110 if (status_code == WLAN_STATUS_SUCCESS &&
2111 hapd->conf->mesh & MESH_ENABLED) {
2112 if (sta->wpa_sm == NULL)
2113 sta->wpa_sm =
2114 wpa_auth_sta_init(hapd->wpa_auth,
2115 sta->addr, NULL);
2116 if (sta->wpa_sm == NULL) {
2117 wpa_printf(MSG_DEBUG,
2118 "SAE: Failed to initialize WPA state machine");
2119 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
2120 goto fail;
2121 }
2122 }
2123#endif /* CONFIG_MESH */
2124 handle_auth_sae(hapd, sta, mgmt, len, auth_transaction,
2125 status_code);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002126 return;
2127#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002128#ifdef CONFIG_FILS
2129 case WLAN_AUTH_FILS_SK:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002130 case WLAN_AUTH_FILS_SK_PFS:
2131 handle_auth_fils(hapd, sta, mgmt->u.auth.variable,
2132 len - IEEE80211_HDRLEN - sizeof(mgmt->u.auth),
2133 auth_alg, auth_transaction, status_code,
2134 handle_auth_fils_finish);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002135 return;
2136#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002137 }
2138
2139 fail:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002140 os_free(identity);
2141 os_free(radius_cui);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002142 hostapd_free_psk_list(psk);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002143
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002144 reply_res = send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
2145 auth_transaction + 1, resp, resp_ies,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002146 resp_ies_len, "handle-auth");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002147
2148 if (sta && sta->added_unassoc && (resp != WLAN_STATUS_SUCCESS ||
2149 reply_res != WLAN_STATUS_SUCCESS)) {
2150 hostapd_drv_sta_remove(hapd, sta->addr);
2151 sta->added_unassoc = 0;
2152 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002153}
2154
2155
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002156int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002157{
2158 int i, j = 32, aid;
2159
2160 /* get a unique AID */
2161 if (sta->aid > 0) {
2162 wpa_printf(MSG_DEBUG, " old AID %d", sta->aid);
2163 return 0;
2164 }
2165
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002166 if (TEST_FAIL())
2167 return -1;
2168
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002169 for (i = 0; i < AID_WORDS; i++) {
2170 if (hapd->sta_aid[i] == (u32) -1)
2171 continue;
2172 for (j = 0; j < 32; j++) {
2173 if (!(hapd->sta_aid[i] & BIT(j)))
2174 break;
2175 }
2176 if (j < 32)
2177 break;
2178 }
2179 if (j == 32)
2180 return -1;
2181 aid = i * 32 + j + 1;
2182 if (aid > 2007)
2183 return -1;
2184
2185 sta->aid = aid;
2186 hapd->sta_aid[i] |= BIT(j);
2187 wpa_printf(MSG_DEBUG, " new AID %d", sta->aid);
2188 return 0;
2189}
2190
2191
2192static u16 check_ssid(struct hostapd_data *hapd, struct sta_info *sta,
2193 const u8 *ssid_ie, size_t ssid_ie_len)
2194{
2195 if (ssid_ie == NULL)
2196 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2197
2198 if (ssid_ie_len != hapd->conf->ssid.ssid_len ||
2199 os_memcmp(ssid_ie, hapd->conf->ssid.ssid, ssid_ie_len) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002200 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2201 HOSTAPD_LEVEL_INFO,
2202 "Station tried to associate with unknown SSID "
Dmitry Shmidt3c479372014-02-04 10:50:36 -08002203 "'%s'", wpa_ssid_txt(ssid_ie, ssid_ie_len));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002204 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2205 }
2206
2207 return WLAN_STATUS_SUCCESS;
2208}
2209
2210
2211static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta,
2212 const u8 *wmm_ie, size_t wmm_ie_len)
2213{
2214 sta->flags &= ~WLAN_STA_WMM;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002215 sta->qosinfo = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002216 if (wmm_ie && hapd->conf->wmm_enabled) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002217 struct wmm_information_element *wmm;
2218
2219 if (!hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002220 hostapd_logger(hapd, sta->addr,
2221 HOSTAPD_MODULE_WPA,
2222 HOSTAPD_LEVEL_DEBUG,
2223 "invalid WMM element in association "
2224 "request");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002225 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2226 }
2227
2228 sta->flags |= WLAN_STA_WMM;
2229 wmm = (struct wmm_information_element *) wmm_ie;
2230 sta->qosinfo = wmm->qos_info;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002231 }
2232 return WLAN_STATUS_SUCCESS;
2233}
2234
Hai Shalom74f70d42019-02-11 14:42:39 -08002235static u16 check_multi_ap(struct hostapd_data *hapd, struct sta_info *sta,
2236 const u8 *multi_ap_ie, size_t multi_ap_len)
2237{
2238 u8 multi_ap_value = 0;
2239
2240 sta->flags &= ~WLAN_STA_MULTI_AP;
2241
2242 if (!hapd->conf->multi_ap)
2243 return WLAN_STATUS_SUCCESS;
2244
2245 if (multi_ap_ie) {
2246 const u8 *multi_ap_subelem;
2247
2248 multi_ap_subelem = get_ie(multi_ap_ie + 4,
2249 multi_ap_len - 4,
2250 MULTI_AP_SUB_ELEM_TYPE);
2251 if (multi_ap_subelem && multi_ap_subelem[1] == 1) {
2252 multi_ap_value = multi_ap_subelem[2];
2253 } else {
2254 hostapd_logger(hapd, sta->addr,
2255 HOSTAPD_MODULE_IEEE80211,
2256 HOSTAPD_LEVEL_INFO,
2257 "Multi-AP IE has missing or invalid Multi-AP subelement");
2258 return WLAN_STATUS_INVALID_IE;
2259 }
2260 }
2261
2262 if (multi_ap_value == MULTI_AP_BACKHAUL_STA)
2263 sta->flags |= WLAN_STA_MULTI_AP;
2264
2265 if ((hapd->conf->multi_ap & BACKHAUL_BSS) &&
2266 multi_ap_value == MULTI_AP_BACKHAUL_STA)
2267 return WLAN_STATUS_SUCCESS;
2268
2269 if (hapd->conf->multi_ap & FRONTHAUL_BSS) {
2270 if (multi_ap_value == MULTI_AP_BACKHAUL_STA) {
2271 hostapd_logger(hapd, sta->addr,
2272 HOSTAPD_MODULE_IEEE80211,
2273 HOSTAPD_LEVEL_INFO,
2274 "Backhaul STA tries to associate with fronthaul-only BSS");
2275 return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
2276 }
2277 return WLAN_STATUS_SUCCESS;
2278 }
2279
2280 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2281 HOSTAPD_LEVEL_INFO,
2282 "Non-Multi-AP STA tries to associate with backhaul-only BSS");
2283 return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
2284}
2285
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002286
2287static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
2288 struct ieee802_11_elems *elems)
2289{
Dmitry Shmidt29333592017-01-09 12:27:11 -08002290 /* Supported rates not used in IEEE 802.11ad/DMG */
2291 if (hapd->iface->current_mode &&
2292 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD)
2293 return WLAN_STATUS_SUCCESS;
2294
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002295 if (!elems->supp_rates) {
2296 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2297 HOSTAPD_LEVEL_DEBUG,
2298 "No supported rates element in AssocReq");
2299 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2300 }
2301
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002302 if (elems->supp_rates_len + elems->ext_supp_rates_len >
2303 sizeof(sta->supported_rates)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002304 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2305 HOSTAPD_LEVEL_DEBUG,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002306 "Invalid supported rates element length %d+%d",
2307 elems->supp_rates_len,
2308 elems->ext_supp_rates_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002309 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2310 }
2311
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002312 sta->supported_rates_len = merge_byte_arrays(
2313 sta->supported_rates, sizeof(sta->supported_rates),
2314 elems->supp_rates, elems->supp_rates_len,
2315 elems->ext_supp_rates, elems->ext_supp_rates_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002316
2317 return WLAN_STATUS_SUCCESS;
2318}
2319
2320
Dmitry Shmidt051af732013-10-22 13:52:46 -07002321static u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
2322 const u8 *ext_capab_ie, size_t ext_capab_ie_len)
2323{
2324#ifdef CONFIG_INTERWORKING
2325 /* check for QoS Map support */
2326 if (ext_capab_ie_len >= 5) {
2327 if (ext_capab_ie[4] & 0x01)
2328 sta->qos_map_enabled = 1;
2329 }
2330#endif /* CONFIG_INTERWORKING */
2331
Roshan Pius3a1667e2018-07-03 15:17:14 -07002332 if (ext_capab_ie_len > 0) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002333 sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2));
Roshan Pius3a1667e2018-07-03 15:17:14 -07002334 os_free(sta->ext_capability);
2335 sta->ext_capability = os_malloc(1 + ext_capab_ie_len);
2336 if (sta->ext_capability) {
2337 sta->ext_capability[0] = ext_capab_ie_len;
2338 os_memcpy(sta->ext_capability + 1, ext_capab_ie,
2339 ext_capab_ie_len);
2340 }
2341 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002342
Dmitry Shmidt051af732013-10-22 13:52:46 -07002343 return WLAN_STATUS_SUCCESS;
2344}
2345
2346
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002347#ifdef CONFIG_OWE
2348
2349static int owe_group_supported(struct hostapd_data *hapd, u16 group)
2350{
2351 int i;
2352 int *groups = hapd->conf->owe_groups;
2353
2354 if (group != 19 && group != 20 && group != 21)
2355 return 0;
2356
2357 if (!groups)
2358 return 1;
2359
2360 for (i = 0; groups[i] > 0; i++) {
2361 if (groups[i] == group)
2362 return 1;
2363 }
2364
2365 return 0;
2366}
2367
2368
2369static u16 owe_process_assoc_req(struct hostapd_data *hapd,
2370 struct sta_info *sta, const u8 *owe_dh,
2371 u8 owe_dh_len)
2372{
2373 struct wpabuf *secret, *pub, *hkey;
2374 int res;
2375 u8 prk[SHA512_MAC_LEN], pmkid[SHA512_MAC_LEN];
2376 const char *info = "OWE Key Generation";
2377 const u8 *addr[2];
2378 size_t len[2];
2379 u16 group;
2380 size_t hash_len, prime_len;
2381
2382 if (wpa_auth_sta_get_pmksa(sta->wpa_sm)) {
2383 wpa_printf(MSG_DEBUG, "OWE: Using PMKSA caching");
2384 return WLAN_STATUS_SUCCESS;
2385 }
2386
2387 group = WPA_GET_LE16(owe_dh);
2388 if (!owe_group_supported(hapd, group)) {
2389 wpa_printf(MSG_DEBUG, "OWE: Unsupported DH group %u", group);
2390 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
2391 }
2392 if (group == 19)
2393 prime_len = 32;
2394 else if (group == 20)
2395 prime_len = 48;
2396 else if (group == 21)
2397 prime_len = 66;
2398 else
2399 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
2400
2401 crypto_ecdh_deinit(sta->owe_ecdh);
2402 sta->owe_ecdh = crypto_ecdh_init(group);
2403 if (!sta->owe_ecdh)
2404 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
2405 sta->owe_group = group;
2406
2407 secret = crypto_ecdh_set_peerkey(sta->owe_ecdh, 0, owe_dh + 2,
2408 owe_dh_len - 2);
2409 secret = wpabuf_zeropad(secret, prime_len);
2410 if (!secret) {
2411 wpa_printf(MSG_DEBUG, "OWE: Invalid peer DH public key");
2412 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2413 }
2414 wpa_hexdump_buf_key(MSG_DEBUG, "OWE: DH shared secret", secret);
2415
2416 /* prk = HKDF-extract(C | A | group, z) */
2417
2418 pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
2419 if (!pub) {
2420 wpabuf_clear_free(secret);
2421 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2422 }
2423
2424 /* PMKID = Truncate-128(Hash(C | A)) */
2425 addr[0] = owe_dh + 2;
2426 len[0] = owe_dh_len - 2;
2427 addr[1] = wpabuf_head(pub);
2428 len[1] = wpabuf_len(pub);
2429 if (group == 19) {
2430 res = sha256_vector(2, addr, len, pmkid);
2431 hash_len = SHA256_MAC_LEN;
2432 } else if (group == 20) {
2433 res = sha384_vector(2, addr, len, pmkid);
2434 hash_len = SHA384_MAC_LEN;
2435 } else if (group == 21) {
2436 res = sha512_vector(2, addr, len, pmkid);
2437 hash_len = SHA512_MAC_LEN;
2438 } else {
2439 wpabuf_free(pub);
2440 wpabuf_clear_free(secret);
2441 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2442 }
2443 pub = wpabuf_zeropad(pub, prime_len);
2444 if (res < 0 || !pub) {
2445 wpabuf_free(pub);
2446 wpabuf_clear_free(secret);
2447 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2448 }
2449
2450 hkey = wpabuf_alloc(owe_dh_len - 2 + wpabuf_len(pub) + 2);
2451 if (!hkey) {
2452 wpabuf_free(pub);
2453 wpabuf_clear_free(secret);
2454 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2455 }
2456
2457 wpabuf_put_data(hkey, owe_dh + 2, owe_dh_len - 2); /* C */
2458 wpabuf_put_buf(hkey, pub); /* A */
2459 wpabuf_free(pub);
2460 wpabuf_put_le16(hkey, group); /* group */
2461 if (group == 19)
2462 res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey),
2463 wpabuf_head(secret), wpabuf_len(secret), prk);
2464 else if (group == 20)
2465 res = hmac_sha384(wpabuf_head(hkey), wpabuf_len(hkey),
2466 wpabuf_head(secret), wpabuf_len(secret), prk);
2467 else if (group == 21)
2468 res = hmac_sha512(wpabuf_head(hkey), wpabuf_len(hkey),
2469 wpabuf_head(secret), wpabuf_len(secret), prk);
2470 wpabuf_clear_free(hkey);
2471 wpabuf_clear_free(secret);
2472 if (res < 0)
2473 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2474
2475 wpa_hexdump_key(MSG_DEBUG, "OWE: prk", prk, hash_len);
2476
2477 /* PMK = HKDF-expand(prk, "OWE Key Generation", n) */
2478
2479 os_free(sta->owe_pmk);
2480 sta->owe_pmk = os_malloc(hash_len);
2481 if (!sta->owe_pmk) {
2482 os_memset(prk, 0, SHA512_MAC_LEN);
2483 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2484 }
2485
2486 if (group == 19)
2487 res = hmac_sha256_kdf(prk, hash_len, NULL, (const u8 *) info,
2488 os_strlen(info), sta->owe_pmk, hash_len);
2489 else if (group == 20)
2490 res = hmac_sha384_kdf(prk, hash_len, NULL, (const u8 *) info,
2491 os_strlen(info), sta->owe_pmk, hash_len);
2492 else if (group == 21)
2493 res = hmac_sha512_kdf(prk, hash_len, NULL, (const u8 *) info,
2494 os_strlen(info), sta->owe_pmk, hash_len);
2495 os_memset(prk, 0, SHA512_MAC_LEN);
2496 if (res < 0) {
2497 os_free(sta->owe_pmk);
2498 sta->owe_pmk = NULL;
2499 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2500 }
2501 sta->owe_pmk_len = hash_len;
2502
2503 wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sta->owe_pmk, sta->owe_pmk_len);
2504 wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, PMKID_LEN);
2505 wpa_auth_pmksa_add2(hapd->wpa_auth, sta->addr, sta->owe_pmk,
2506 sta->owe_pmk_len, pmkid, 0, WPA_KEY_MGMT_OWE);
2507
2508 return WLAN_STATUS_SUCCESS;
2509}
2510
2511#endif /* CONFIG_OWE */
2512
2513
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002514static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
2515 const u8 *ies, size_t ies_len, int reassoc)
2516{
2517 struct ieee802_11_elems elems;
2518 u16 resp;
2519 const u8 *wpa_ie;
2520 size_t wpa_ie_len;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002521 const u8 *p2p_dev_addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002522
2523 if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
2524 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2525 HOSTAPD_LEVEL_INFO, "Station sent an invalid "
2526 "association request");
2527 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2528 }
2529
2530 resp = check_ssid(hapd, sta, elems.ssid, elems.ssid_len);
2531 if (resp != WLAN_STATUS_SUCCESS)
2532 return resp;
2533 resp = check_wmm(hapd, sta, elems.wmm, elems.wmm_len);
2534 if (resp != WLAN_STATUS_SUCCESS)
2535 return resp;
Dmitry Shmidt051af732013-10-22 13:52:46 -07002536 resp = check_ext_capab(hapd, sta, elems.ext_capab, elems.ext_capab_len);
2537 if (resp != WLAN_STATUS_SUCCESS)
2538 return resp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002539 resp = copy_supp_rates(hapd, sta, &elems);
2540 if (resp != WLAN_STATUS_SUCCESS)
2541 return resp;
Hai Shalom74f70d42019-02-11 14:42:39 -08002542
2543 resp = check_multi_ap(hapd, sta, elems.multi_ap, elems.multi_ap_len);
2544 if (resp != WLAN_STATUS_SUCCESS)
2545 return resp;
2546
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002547#ifdef CONFIG_IEEE80211N
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07002548 resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002549 if (resp != WLAN_STATUS_SUCCESS)
2550 return resp;
2551 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
2552 !(sta->flags & WLAN_STA_HT)) {
2553 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2554 HOSTAPD_LEVEL_INFO, "Station does not support "
2555 "mandatory HT PHY - reject association");
2556 return WLAN_STATUS_ASSOC_DENIED_NO_HT;
2557 }
2558#endif /* CONFIG_IEEE80211N */
2559
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002560#ifdef CONFIG_IEEE80211AC
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002561 if (hapd->iconf->ieee80211ac) {
2562 resp = copy_sta_vht_capab(hapd, sta, elems.vht_capabilities);
2563 if (resp != WLAN_STATUS_SUCCESS)
2564 return resp;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002565
Hai Shalom74f70d42019-02-11 14:42:39 -08002566 resp = copy_sta_vht_oper(hapd, sta, elems.vht_operation);
2567 if (resp != WLAN_STATUS_SUCCESS)
2568 return resp;
2569
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002570 resp = set_sta_vht_opmode(hapd, sta, elems.vht_opmode_notif);
2571 if (resp != WLAN_STATUS_SUCCESS)
2572 return resp;
2573 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002574
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002575 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht &&
2576 !(sta->flags & WLAN_STA_VHT)) {
2577 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2578 HOSTAPD_LEVEL_INFO, "Station does not support "
2579 "mandatory VHT PHY - reject association");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002580 return WLAN_STATUS_ASSOC_DENIED_NO_VHT;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002581 }
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002582
2583 if (hapd->conf->vendor_vht && !elems.vht_capabilities) {
2584 resp = copy_sta_vendor_vht(hapd, sta, elems.vendor_vht,
2585 elems.vendor_vht_len);
2586 if (resp != WLAN_STATUS_SUCCESS)
2587 return resp;
2588 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002589#endif /* CONFIG_IEEE80211AC */
2590
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002591#ifdef CONFIG_P2P
2592 if (elems.p2p) {
2593 wpabuf_free(sta->p2p_ie);
2594 sta->p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
2595 P2P_IE_VENDOR_TYPE);
2596 if (sta->p2p_ie)
2597 p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie);
2598 } else {
2599 wpabuf_free(sta->p2p_ie);
2600 sta->p2p_ie = NULL;
2601 }
2602#endif /* CONFIG_P2P */
2603
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002604 if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) {
2605 wpa_ie = elems.rsn_ie;
2606 wpa_ie_len = elems.rsn_ie_len;
2607 } else if ((hapd->conf->wpa & WPA_PROTO_WPA) &&
2608 elems.wpa_ie) {
2609 wpa_ie = elems.wpa_ie;
2610 wpa_ie_len = elems.wpa_ie_len;
2611 } else {
2612 wpa_ie = NULL;
2613 wpa_ie_len = 0;
2614 }
2615
2616#ifdef CONFIG_WPS
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002617 sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002618 if (hapd->conf->wps_state && elems.wps_ie) {
2619 wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association "
2620 "Request - assume WPS is used");
2621 sta->flags |= WLAN_STA_WPS;
2622 wpabuf_free(sta->wps_ie);
2623 sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
2624 WPS_IE_VENDOR_TYPE);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002625 if (sta->wps_ie && wps_is_20(sta->wps_ie)) {
2626 wpa_printf(MSG_DEBUG, "WPS: STA supports WPS 2.0");
2627 sta->flags |= WLAN_STA_WPS2;
2628 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002629 wpa_ie = NULL;
2630 wpa_ie_len = 0;
2631 if (sta->wps_ie && wps_validate_assoc_req(sta->wps_ie) < 0) {
2632 wpa_printf(MSG_DEBUG, "WPS: Invalid WPS IE in "
2633 "(Re)Association Request - reject");
2634 return WLAN_STATUS_INVALID_IE;
2635 }
2636 } else if (hapd->conf->wps_state && wpa_ie == NULL) {
2637 wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE in "
2638 "(Re)Association Request - possible WPS use");
2639 sta->flags |= WLAN_STA_MAYBE_WPS;
2640 } else
2641#endif /* CONFIG_WPS */
2642 if (hapd->conf->wpa && wpa_ie == NULL) {
2643 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2644 HOSTAPD_LEVEL_INFO,
2645 "No WPA/RSN IE in association request");
2646 return WLAN_STATUS_INVALID_IE;
2647 }
2648
2649 if (hapd->conf->wpa && wpa_ie) {
2650 int res;
2651 wpa_ie -= 2;
2652 wpa_ie_len += 2;
2653 if (sta->wpa_sm == NULL)
2654 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002655 sta->addr,
2656 p2p_dev_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002657 if (sta->wpa_sm == NULL) {
2658 wpa_printf(MSG_WARNING, "Failed to initialize WPA "
2659 "state machine");
2660 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2661 }
2662 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
2663 wpa_ie, wpa_ie_len,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002664 elems.mdie, elems.mdie_len,
2665 elems.owe_dh, elems.owe_dh_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002666 resp = wpa_res_to_status_code(res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002667 if (resp != WLAN_STATUS_SUCCESS)
2668 return resp;
2669#ifdef CONFIG_IEEE80211W
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002670 if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
2671 (WLAN_STA_ASSOC | WLAN_STA_MFP) &&
2672 !sta->sa_query_timed_out &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002673 sta->sa_query_count > 0)
2674 ap_check_sa_query_timeout(hapd, sta);
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002675 if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
2676 (WLAN_STA_ASSOC | WLAN_STA_MFP) &&
2677 !sta->sa_query_timed_out &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002678 (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) {
2679 /*
2680 * STA has already been associated with MFP and SA
2681 * Query timeout has not been reached. Reject the
2682 * association attempt temporarily and start SA Query,
2683 * if one is not pending.
2684 */
2685
2686 if (sta->sa_query_count == 0)
2687 ap_sta_start_sa_query(hapd, sta);
2688
2689 return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
2690 }
2691
2692 if (wpa_auth_uses_mfp(sta->wpa_sm))
2693 sta->flags |= WLAN_STA_MFP;
2694 else
2695 sta->flags &= ~WLAN_STA_MFP;
2696#endif /* CONFIG_IEEE80211W */
2697
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002698#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002699 if (sta->auth_alg == WLAN_AUTH_FT) {
2700 if (!reassoc) {
2701 wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried "
2702 "to use association (not "
2703 "re-association) with FT auth_alg",
2704 MAC2STR(sta->addr));
2705 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2706 }
2707
2708 resp = wpa_ft_validate_reassoc(sta->wpa_sm, ies,
2709 ies_len);
2710 if (resp != WLAN_STATUS_SUCCESS)
2711 return resp;
2712 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002713#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002714
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002715#ifdef CONFIG_SAE
Roshan Pius3a1667e2018-07-03 15:17:14 -07002716 if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae &&
2717 sta->sae->state == SAE_ACCEPTED)
2718 wpa_auth_add_sae_pmkid(sta->wpa_sm, sta->sae->pmkid);
2719
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002720 if (wpa_auth_uses_sae(sta->wpa_sm) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002721 sta->auth_alg == WLAN_AUTH_OPEN) {
2722 struct rsn_pmksa_cache_entry *sa;
2723 sa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
2724 if (!sa || sa->akmp != WPA_KEY_MGMT_SAE) {
2725 wpa_printf(MSG_DEBUG,
2726 "SAE: No PMKSA cache entry found for "
2727 MACSTR, MAC2STR(sta->addr));
2728 return WLAN_STATUS_INVALID_PMKID;
2729 }
2730 wpa_printf(MSG_DEBUG, "SAE: " MACSTR
2731 " using PMKSA caching", MAC2STR(sta->addr));
2732 } else if (wpa_auth_uses_sae(sta->wpa_sm) &&
2733 sta->auth_alg != WLAN_AUTH_SAE &&
2734 !(sta->auth_alg == WLAN_AUTH_FT &&
2735 wpa_auth_uses_ft_sae(sta->wpa_sm))) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002736 wpa_printf(MSG_DEBUG, "SAE: " MACSTR " tried to use "
2737 "SAE AKM after non-SAE auth_alg %u",
2738 MAC2STR(sta->addr), sta->auth_alg);
2739 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
2740 }
2741#endif /* CONFIG_SAE */
2742
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002743#ifdef CONFIG_OWE
2744 if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
2745 wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE &&
2746 elems.owe_dh) {
2747 resp = owe_process_assoc_req(hapd, sta, elems.owe_dh,
2748 elems.owe_dh_len);
2749 if (resp != WLAN_STATUS_SUCCESS)
2750 return resp;
2751 }
2752#endif /* CONFIG_OWE */
2753
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002754#ifdef CONFIG_IEEE80211N
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002755 if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002756 wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
2757 hostapd_logger(hapd, sta->addr,
2758 HOSTAPD_MODULE_IEEE80211,
2759 HOSTAPD_LEVEL_INFO,
2760 "Station tried to use TKIP with HT "
2761 "association");
2762 return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
2763 }
2764#endif /* CONFIG_IEEE80211N */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002765#ifdef CONFIG_HS20
2766 } else if (hapd->conf->osen) {
2767 if (elems.osen == NULL) {
2768 hostapd_logger(
2769 hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2770 HOSTAPD_LEVEL_INFO,
2771 "No HS 2.0 OSEN element in association request");
2772 return WLAN_STATUS_INVALID_IE;
2773 }
2774
2775 wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association");
2776 if (sta->wpa_sm == NULL)
2777 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
2778 sta->addr, NULL);
2779 if (sta->wpa_sm == NULL) {
2780 wpa_printf(MSG_WARNING, "Failed to initialize WPA "
2781 "state machine");
2782 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2783 }
2784 if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm,
2785 elems.osen - 2, elems.osen_len + 2) < 0)
2786 return WLAN_STATUS_INVALID_IE;
2787#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002788 } else
2789 wpa_auth_sta_no_wpa(sta->wpa_sm);
2790
2791#ifdef CONFIG_P2P
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002792 p2p_group_notif_assoc(hapd->p2p_group, sta->addr, ies, ies_len);
2793#endif /* CONFIG_P2P */
2794
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002795#ifdef CONFIG_HS20
2796 wpabuf_free(sta->hs20_ie);
2797 if (elems.hs20 && elems.hs20_len > 4) {
Hai Shalom74f70d42019-02-11 14:42:39 -08002798 int release;
2799
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002800 sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
2801 elems.hs20_len - 4);
Hai Shalom74f70d42019-02-11 14:42:39 -08002802 release = ((elems.hs20[4] >> 4) & 0x0f) + 1;
2803 if (release >= 2 && !wpa_auth_uses_mfp(sta->wpa_sm)) {
2804 wpa_printf(MSG_DEBUG,
2805 "HS 2.0: PMF not negotiated by release %d station "
2806 MACSTR, release, MAC2STR(sta->addr));
2807 return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
2808 }
2809 } else {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002810 sta->hs20_ie = NULL;
Hai Shalom74f70d42019-02-11 14:42:39 -08002811 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07002812
2813 wpabuf_free(sta->roaming_consortium);
2814 if (elems.roaming_cons_sel)
2815 sta->roaming_consortium = wpabuf_alloc_copy(
2816 elems.roaming_cons_sel + 4,
2817 elems.roaming_cons_sel_len - 4);
2818 else
2819 sta->roaming_consortium = NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002820#endif /* CONFIG_HS20 */
2821
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002822#ifdef CONFIG_FST
2823 wpabuf_free(sta->mb_ies);
2824 if (hapd->iface->fst)
2825 sta->mb_ies = mb_ies_by_info(&elems.mb_ies);
2826 else
2827 sta->mb_ies = NULL;
2828#endif /* CONFIG_FST */
2829
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002830#ifdef CONFIG_MBO
2831 mbo_ap_check_sta_assoc(hapd, sta, &elems);
2832
2833 if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) &&
2834 elems.mbo && sta->cell_capa && !(sta->flags & WLAN_STA_MFP) &&
2835 hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
2836 wpa_printf(MSG_INFO,
2837 "MBO: Reject WPA2 association without PMF");
2838 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2839 }
2840#endif /* CONFIG_MBO */
2841
Hai Shalom74f70d42019-02-11 14:42:39 -08002842#if defined(CONFIG_FILS) && defined(CONFIG_OCV)
2843 if (wpa_auth_uses_ocv(sta->wpa_sm) &&
2844 (sta->auth_alg == WLAN_AUTH_FILS_SK ||
2845 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
2846 sta->auth_alg == WLAN_AUTH_FILS_PK)) {
2847 struct wpa_channel_info ci;
2848 int tx_chanwidth;
2849 int tx_seg1_idx;
2850
2851 if (hostapd_drv_channel_info(hapd, &ci) != 0) {
2852 wpa_printf(MSG_WARNING,
2853 "Failed to get channel info to validate received OCI in FILS (Re)Association Request frame");
2854 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2855 }
2856
2857 if (get_sta_tx_parameters(sta->wpa_sm,
2858 channel_width_to_int(ci.chanwidth),
2859 ci.seg1_idx, &tx_chanwidth,
2860 &tx_seg1_idx) < 0)
2861 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2862
2863 if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
2864 tx_chanwidth, tx_seg1_idx) != 0) {
2865 wpa_printf(MSG_WARNING, "FILS: %s", ocv_errorstr);
2866 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2867 }
2868 }
2869#endif /* CONFIG_FILS && CONFIG_OCV */
2870
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002871 ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes,
2872 elems.supp_op_classes_len);
2873
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002874 if ((sta->capability & WLAN_CAPABILITY_RADIO_MEASUREMENT) &&
2875 elems.rrm_enabled &&
2876 elems.rrm_enabled_len >= sizeof(sta->rrm_enabled_capa))
2877 os_memcpy(sta->rrm_enabled_capa, elems.rrm_enabled,
2878 sizeof(sta->rrm_enabled_capa));
2879
Roshan Pius3a1667e2018-07-03 15:17:14 -07002880 if (elems.power_capab) {
2881 sta->min_tx_power = elems.power_capab[0];
2882 sta->max_tx_power = elems.power_capab[1];
2883 sta->power_capab = 1;
2884 } else {
2885 sta->power_capab = 0;
2886 }
2887
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002888 return WLAN_STATUS_SUCCESS;
2889}
2890
2891
2892static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
2893 u16 reason_code)
2894{
2895 int send_len;
2896 struct ieee80211_mgmt reply;
2897
2898 os_memset(&reply, 0, sizeof(reply));
2899 reply.frame_control =
2900 IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DEAUTH);
2901 os_memcpy(reply.da, addr, ETH_ALEN);
2902 os_memcpy(reply.sa, hapd->own_addr, ETH_ALEN);
2903 os_memcpy(reply.bssid, hapd->own_addr, ETH_ALEN);
2904
2905 send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth);
2906 reply.u.deauth.reason_code = host_to_le16(reason_code);
2907
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002908 if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002909 wpa_printf(MSG_INFO, "Failed to send deauth: %s",
2910 strerror(errno));
2911}
2912
2913
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002914static int add_associated_sta(struct hostapd_data *hapd,
Hai Shalom74f70d42019-02-11 14:42:39 -08002915 struct sta_info *sta, int reassoc)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002916{
2917 struct ieee80211_ht_capabilities ht_cap;
2918 struct ieee80211_vht_capabilities vht_cap;
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02002919 int set = 1;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002920
2921 /*
2922 * Remove the STA entry to ensure the STA PS state gets cleared and
2923 * configuration gets updated. This is relevant for cases, such as
2924 * FT-over-the-DS, where a station re-associates back to the same AP but
2925 * skips the authentication flow, or if working with a driver that
2926 * does not support full AP client state.
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02002927 *
2928 * Skip this if the STA has already completed FT reassociation and the
2929 * TK has been configured since the TX/RX PN must not be reset to 0 for
2930 * the same key.
Hai Shalom74f70d42019-02-11 14:42:39 -08002931 *
2932 * FT-over-the-DS has a special case where the STA entry (and as such,
2933 * the TK) has not yet been configured to the driver depending on which
2934 * driver interface is used. For that case, allow add-STA operation to
2935 * be used (instead of set-STA). This is needed to allow mac80211-based
2936 * drivers to accept the STA parameter configuration. Since this is
2937 * after a new FT-over-DS exchange, a new TK has been derived, so key
2938 * reinstallation is not a concern for this case.
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002939 */
Hai Shalom74f70d42019-02-11 14:42:39 -08002940 wpa_printf(MSG_DEBUG, "Add associated STA " MACSTR
2941 " (added_unassoc=%d auth_alg=%u ft_over_ds=%u reassoc=%d authorized=%d ft_tk=%d fils_tk=%d)",
2942 MAC2STR(sta->addr), sta->added_unassoc, sta->auth_alg,
2943 sta->ft_over_ds, reassoc,
2944 !!(sta->flags & WLAN_STA_AUTHORIZED),
2945 wpa_auth_sta_ft_tk_already_set(sta->wpa_sm),
2946 wpa_auth_sta_fils_tk_already_set(sta->wpa_sm));
2947
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02002948 if (!sta->added_unassoc &&
2949 (!(sta->flags & WLAN_STA_AUTHORIZED) ||
Hai Shalom74f70d42019-02-11 14:42:39 -08002950 (reassoc && sta->ft_over_ds && sta->auth_alg == WLAN_AUTH_FT) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002951 (!wpa_auth_sta_ft_tk_already_set(sta->wpa_sm) &&
2952 !wpa_auth_sta_fils_tk_already_set(sta->wpa_sm)))) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002953 hostapd_drv_sta_remove(hapd, sta->addr);
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02002954 wpa_auth_sm_event(sta->wpa_sm, WPA_DRV_STA_REMOVED);
2955 set = 0;
Hai Shalom74f70d42019-02-11 14:42:39 -08002956
2957 /* Do not allow the FT-over-DS exception to be used more than
2958 * once per authentication exchange to guarantee a new TK is
2959 * used here */
2960 sta->ft_over_ds = 0;
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02002961 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002962
2963#ifdef CONFIG_IEEE80211N
2964 if (sta->flags & WLAN_STA_HT)
2965 hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
2966#endif /* CONFIG_IEEE80211N */
2967#ifdef CONFIG_IEEE80211AC
2968 if (sta->flags & WLAN_STA_VHT)
2969 hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
2970#endif /* CONFIG_IEEE80211AC */
2971
2972 /*
2973 * Add the station with forced WLAN_STA_ASSOC flag. The sta->flags
2974 * will be set when the ACK frame for the (Re)Association Response frame
2975 * is processed (TX status driver event).
2976 */
2977 if (hostapd_sta_add(hapd, sta->addr, sta->aid, sta->capability,
2978 sta->supported_rates, sta->supported_rates_len,
2979 sta->listen_interval,
2980 sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
2981 sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
2982 sta->flags | WLAN_STA_ASSOC, sta->qosinfo,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002983 sta->vht_opmode, sta->p2p_ie ? 1 : 0,
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02002984 set)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002985 hostapd_logger(hapd, sta->addr,
2986 HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE,
2987 "Could not %s STA to kernel driver",
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02002988 set ? "set" : "add");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002989
2990 if (sta->added_unassoc) {
2991 hostapd_drv_sta_remove(hapd, sta->addr);
2992 sta->added_unassoc = 0;
2993 }
2994
2995 return -1;
2996 }
2997
2998 sta->added_unassoc = 0;
2999
3000 return 0;
3001}
3002
3003
3004static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
Dmitry Shmidt29333592017-01-09 12:27:11 -08003005 const u8 *addr, u16 status_code, int reassoc,
Hai Shalom74f70d42019-02-11 14:42:39 -08003006 const u8 *ies, size_t ies_len, int rssi)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003007{
3008 int send_len;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003009 u8 *buf;
3010 size_t buflen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003011 struct ieee80211_mgmt *reply;
3012 u8 *p;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003013 u16 res = WLAN_STATUS_SUCCESS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003014
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003015 buflen = sizeof(struct ieee80211_mgmt) + 1024;
3016#ifdef CONFIG_FILS
3017 if (sta && sta->fils_hlp_resp)
3018 buflen += wpabuf_len(sta->fils_hlp_resp);
3019#endif /* CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003020#ifdef CONFIG_OWE
3021 if (sta && (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE))
3022 buflen += 150;
3023#endif /* CONFIG_OWE */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003024 buf = os_zalloc(buflen);
3025 if (!buf) {
3026 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3027 goto done;
3028 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003029 reply = (struct ieee80211_mgmt *) buf;
3030 reply->frame_control =
3031 IEEE80211_FC(WLAN_FC_TYPE_MGMT,
3032 (reassoc ? WLAN_FC_STYPE_REASSOC_RESP :
3033 WLAN_FC_STYPE_ASSOC_RESP));
Dmitry Shmidt29333592017-01-09 12:27:11 -08003034 os_memcpy(reply->da, addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003035 os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
3036 os_memcpy(reply->bssid, hapd->own_addr, ETH_ALEN);
3037
3038 send_len = IEEE80211_HDRLEN;
3039 send_len += sizeof(reply->u.assoc_resp);
3040 reply->u.assoc_resp.capab_info =
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003041 host_to_le16(hostapd_own_capab_info(hapd));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003042 reply->u.assoc_resp.status_code = host_to_le16(status_code);
Dmitry Shmidt29333592017-01-09 12:27:11 -08003043
3044 reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0) |
3045 BIT(14) | BIT(15));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003046 /* Supported rates */
3047 p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable);
3048 /* Extended supported rates */
3049 p = hostapd_eid_ext_supp_rates(hapd, p);
3050
Hai Shalom74f70d42019-02-11 14:42:39 -08003051#ifdef CONFIG_MBO
3052 if (status_code == WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS &&
3053 rssi != 0) {
3054 int delta = hapd->iconf->rssi_reject_assoc_rssi - rssi;
3055
3056 p = hostapd_eid_mbo_rssi_assoc_rej(hapd, p, buf + buflen - p,
3057 delta);
3058 }
3059#endif /* CONFIG_MBO */
3060
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003061#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt29333592017-01-09 12:27:11 -08003062 if (sta && status_code == WLAN_STATUS_SUCCESS) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003063 /* IEEE 802.11r: Mobility Domain Information, Fast BSS
3064 * Transition Information, RSN, [RIC Response] */
3065 p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003066 buf + buflen - p,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003067 sta->auth_alg, ies, ies_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003068 if (!p) {
3069 wpa_printf(MSG_DEBUG,
3070 "FT: Failed to write AssocResp IEs");
3071 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3072 goto done;
3073 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003074 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003075#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003076
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003077#ifdef CONFIG_OWE
Hai Shalom74f70d42019-02-11 14:42:39 -08003078 if (sta && status_code == WLAN_STATUS_SUCCESS &&
3079 (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003080 p = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, p,
3081 buf + buflen - p,
3082 ies, ies_len);
3083#endif /* CONFIG_OWE */
3084
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003085#ifdef CONFIG_IEEE80211W
Dmitry Shmidt29333592017-01-09 12:27:11 -08003086 if (sta && status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003087 p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
3088#endif /* CONFIG_IEEE80211W */
3089
3090#ifdef CONFIG_IEEE80211N
3091 p = hostapd_eid_ht_capabilities(hapd, p);
3092 p = hostapd_eid_ht_operation(hapd, p);
3093#endif /* CONFIG_IEEE80211N */
3094
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003095#ifdef CONFIG_IEEE80211AC
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003096 if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
Dmitry Shmidt7d175302016-09-06 13:11:34 -07003097 u32 nsts = 0, sta_nsts;
3098
Dmitry Shmidt29333592017-01-09 12:27:11 -08003099 if (sta && hapd->conf->use_sta_nsts && sta->vht_capabilities) {
Dmitry Shmidt7d175302016-09-06 13:11:34 -07003100 struct ieee80211_vht_capabilities *capa;
3101
3102 nsts = (hapd->iface->conf->vht_capab >>
3103 VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7;
3104 capa = sta->vht_capabilities;
3105 sta_nsts = (le_to_host32(capa->vht_capabilities_info) >>
3106 VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7;
3107
3108 if (nsts < sta_nsts)
3109 nsts = 0;
3110 else
3111 nsts = sta_nsts;
3112 }
3113 p = hostapd_eid_vht_capabilities(hapd, p, nsts);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003114 p = hostapd_eid_vht_operation(hapd, p);
3115 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003116#endif /* CONFIG_IEEE80211AC */
3117
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003118 p = hostapd_eid_ext_capab(hapd, p);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003119 p = hostapd_eid_bss_max_idle_period(hapd, p);
Dmitry Shmidt29333592017-01-09 12:27:11 -08003120 if (sta && sta->qos_map_enabled)
Dmitry Shmidt051af732013-10-22 13:52:46 -07003121 p = hostapd_eid_qos_map_set(hapd, p);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003122
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003123#ifdef CONFIG_FST
3124 if (hapd->iface->fst_ies) {
3125 os_memcpy(p, wpabuf_head(hapd->iface->fst_ies),
3126 wpabuf_len(hapd->iface->fst_ies));
3127 p += wpabuf_len(hapd->iface->fst_ies);
3128 }
3129#endif /* CONFIG_FST */
3130
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003131#ifdef CONFIG_IEEE80211AC
Dmitry Shmidt29333592017-01-09 12:27:11 -08003132 if (sta && hapd->conf->vendor_vht && (sta->flags & WLAN_STA_VENDOR_VHT))
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003133 p = hostapd_eid_vendor_vht(hapd, p);
3134#endif /* CONFIG_IEEE80211AC */
3135
Dmitry Shmidt29333592017-01-09 12:27:11 -08003136 if (sta && (sta->flags & WLAN_STA_WMM))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003137 p = hostapd_eid_wmm(hapd, p);
3138
3139#ifdef CONFIG_WPS
Dmitry Shmidt29333592017-01-09 12:27:11 -08003140 if (sta &&
3141 ((sta->flags & WLAN_STA_WPS) ||
3142 ((sta->flags & WLAN_STA_MAYBE_WPS) && hapd->conf->wpa))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003143 struct wpabuf *wps = wps_build_assoc_resp_ie();
3144 if (wps) {
3145 os_memcpy(p, wpabuf_head(wps), wpabuf_len(wps));
3146 p += wpabuf_len(wps);
3147 wpabuf_free(wps);
3148 }
3149 }
3150#endif /* CONFIG_WPS */
3151
Hai Shalom74f70d42019-02-11 14:42:39 -08003152 if (sta && (sta->flags & WLAN_STA_MULTI_AP))
3153 p = hostapd_eid_multi_ap(hapd, p);
3154
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003155#ifdef CONFIG_P2P
Dmitry Shmidt29333592017-01-09 12:27:11 -08003156 if (sta && sta->p2p_ie && hapd->p2p_group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003157 struct wpabuf *p2p_resp_ie;
3158 enum p2p_status_code status;
3159 switch (status_code) {
3160 case WLAN_STATUS_SUCCESS:
3161 status = P2P_SC_SUCCESS;
3162 break;
3163 case WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA:
3164 status = P2P_SC_FAIL_LIMIT_REACHED;
3165 break;
3166 default:
3167 status = P2P_SC_FAIL_INVALID_PARAMS;
3168 break;
3169 }
3170 p2p_resp_ie = p2p_group_assoc_resp_ie(hapd->p2p_group, status);
3171 if (p2p_resp_ie) {
3172 os_memcpy(p, wpabuf_head(p2p_resp_ie),
3173 wpabuf_len(p2p_resp_ie));
3174 p += wpabuf_len(p2p_resp_ie);
3175 wpabuf_free(p2p_resp_ie);
3176 }
3177 }
3178#endif /* CONFIG_P2P */
3179
3180#ifdef CONFIG_P2P_MANAGER
3181 if (hapd->conf->p2p & P2P_MANAGE)
3182 p = hostapd_eid_p2p_manage(hapd, p);
3183#endif /* CONFIG_P2P_MANAGER */
3184
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003185 p = hostapd_eid_mbo(hapd, p, buf + buflen - p);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003186
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003187 if (hapd->conf->assocresp_elements &&
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003188 (size_t) (buf + buflen - p) >=
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003189 wpabuf_len(hapd->conf->assocresp_elements)) {
3190 os_memcpy(p, wpabuf_head(hapd->conf->assocresp_elements),
3191 wpabuf_len(hapd->conf->assocresp_elements));
3192 p += wpabuf_len(hapd->conf->assocresp_elements);
3193 }
3194
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003195 send_len += p - reply->u.assoc_resp.variable;
3196
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003197#ifdef CONFIG_FILS
Dmitry Shmidt29333592017-01-09 12:27:11 -08003198 if (sta &&
3199 (sta->auth_alg == WLAN_AUTH_FILS_SK ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003200 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
3201 sta->auth_alg == WLAN_AUTH_FILS_PK) &&
3202 status_code == WLAN_STATUS_SUCCESS) {
3203 struct ieee802_11_elems elems;
3204
3205 if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) ==
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003206 ParseFailed || !elems.fils_session) {
3207 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3208 goto done;
3209 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003210
3211 /* FILS Session */
3212 *p++ = WLAN_EID_EXTENSION; /* Element ID */
3213 *p++ = 1 + FILS_SESSION_LEN; /* Length */
3214 *p++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */
3215 os_memcpy(p, elems.fils_session, FILS_SESSION_LEN);
3216 send_len += 2 + 1 + FILS_SESSION_LEN;
3217
3218 send_len = fils_encrypt_assoc(sta->wpa_sm, buf, send_len,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003219 buflen, sta->fils_hlp_resp);
3220 if (send_len < 0) {
3221 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3222 goto done;
3223 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003224 }
3225#endif /* CONFIG_FILS */
3226
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003227#ifdef CONFIG_OWE
3228 if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
Hai Shalom74f70d42019-02-11 14:42:39 -08003229 sta && sta->owe_ecdh && status_code == WLAN_STATUS_SUCCESS &&
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003230 wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE) {
3231 struct wpabuf *pub;
3232
3233 pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
3234 if (!pub) {
3235 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3236 goto done;
3237 }
3238 /* OWE Diffie-Hellman Parameter element */
3239 *p++ = WLAN_EID_EXTENSION; /* Element ID */
3240 *p++ = 1 + 2 + wpabuf_len(pub); /* Length */
3241 *p++ = WLAN_EID_EXT_OWE_DH_PARAM; /* Element ID Extension */
3242 WPA_PUT_LE16(p, sta->owe_group);
3243 p += 2;
3244 os_memcpy(p, wpabuf_head(pub), wpabuf_len(pub));
3245 p += wpabuf_len(pub);
3246 send_len += 3 + 2 + wpabuf_len(pub);
3247 wpabuf_free(pub);
3248 }
3249#endif /* CONFIG_OWE */
3250
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003251 if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003252 wpa_printf(MSG_INFO, "Failed to send assoc resp: %s",
3253 strerror(errno));
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003254 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003255 }
3256
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003257done:
3258 os_free(buf);
3259 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003260}
3261
3262
Roshan Pius3a1667e2018-07-03 15:17:14 -07003263#ifdef CONFIG_OWE
3264u8 * owe_assoc_req_process(struct hostapd_data *hapd, struct sta_info *sta,
3265 const u8 *owe_dh, u8 owe_dh_len,
3266 u8 *owe_buf, size_t owe_buf_len, u16 *reason)
3267{
3268#ifdef CONFIG_TESTING_OPTIONS
3269 if (hapd->conf->own_ie_override) {
3270 wpa_printf(MSG_DEBUG, "OWE: Using IE override");
3271 *reason = WLAN_STATUS_SUCCESS;
3272 return wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
3273 owe_buf_len, NULL, 0);
3274 }
3275#endif /* CONFIG_TESTING_OPTIONS */
3276
3277 if (wpa_auth_sta_get_pmksa(sta->wpa_sm)) {
3278 wpa_printf(MSG_DEBUG, "OWE: Using PMKSA caching");
3279 owe_buf = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
3280 owe_buf_len, NULL, 0);
3281 *reason = WLAN_STATUS_SUCCESS;
3282 return owe_buf;
3283 }
3284
3285 *reason = owe_process_assoc_req(hapd, sta, owe_dh, owe_dh_len);
3286 if (*reason != WLAN_STATUS_SUCCESS)
3287 return NULL;
3288
3289 owe_buf = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
3290 owe_buf_len, NULL, 0);
3291
3292 if (sta->owe_ecdh && owe_buf) {
3293 struct wpabuf *pub;
3294
3295 pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
3296 if (!pub) {
3297 *reason = WLAN_STATUS_UNSPECIFIED_FAILURE;
3298 return owe_buf;
3299 }
3300
3301 /* OWE Diffie-Hellman Parameter element */
3302 *owe_buf++ = WLAN_EID_EXTENSION; /* Element ID */
3303 *owe_buf++ = 1 + 2 + wpabuf_len(pub); /* Length */
3304 *owe_buf++ = WLAN_EID_EXT_OWE_DH_PARAM; /* Element ID Extension
3305 */
3306 WPA_PUT_LE16(owe_buf, sta->owe_group);
3307 owe_buf += 2;
3308 os_memcpy(owe_buf, wpabuf_head(pub), wpabuf_len(pub));
3309 owe_buf += wpabuf_len(pub);
3310 wpabuf_free(pub);
3311 }
3312
3313 return owe_buf;
3314}
3315#endif /* CONFIG_OWE */
3316
3317
Paul Stewart092955c2017-02-06 09:13:09 -08003318#ifdef CONFIG_FILS
3319
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003320void fils_hlp_finish_assoc(struct hostapd_data *hapd, struct sta_info *sta)
Paul Stewart092955c2017-02-06 09:13:09 -08003321{
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003322 u16 reply_res;
Paul Stewart092955c2017-02-06 09:13:09 -08003323
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003324 wpa_printf(MSG_DEBUG, "FILS: Finish association with " MACSTR,
3325 MAC2STR(sta->addr));
3326 eloop_cancel_timeout(fils_hlp_timeout, hapd, sta);
3327 if (!sta->fils_pending_assoc_req)
Paul Stewart092955c2017-02-06 09:13:09 -08003328 return;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003329 reply_res = send_assoc_resp(hapd, sta, sta->addr, WLAN_STATUS_SUCCESS,
3330 sta->fils_pending_assoc_is_reassoc,
3331 sta->fils_pending_assoc_req,
Hai Shalom74f70d42019-02-11 14:42:39 -08003332 sta->fils_pending_assoc_req_len, 0);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003333 os_free(sta->fils_pending_assoc_req);
3334 sta->fils_pending_assoc_req = NULL;
3335 sta->fils_pending_assoc_req_len = 0;
3336 wpabuf_free(sta->fils_hlp_resp);
3337 sta->fils_hlp_resp = NULL;
3338 wpabuf_free(sta->hlp_dhcp_discover);
3339 sta->hlp_dhcp_discover = NULL;
Paul Stewart092955c2017-02-06 09:13:09 -08003340
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003341 /*
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003342 * Remove the station in case transmission of a success response fails.
3343 * At this point the station was already added associated to the driver.
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003344 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003345 if (reply_res != WLAN_STATUS_SUCCESS)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003346 hostapd_drv_sta_remove(hapd, sta->addr);
Paul Stewart092955c2017-02-06 09:13:09 -08003347}
3348
3349
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003350void fils_hlp_timeout(void *eloop_ctx, void *eloop_data)
Paul Stewart092955c2017-02-06 09:13:09 -08003351{
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003352 struct hostapd_data *hapd = eloop_ctx;
3353 struct sta_info *sta = eloop_data;
Paul Stewart092955c2017-02-06 09:13:09 -08003354
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003355 wpa_printf(MSG_DEBUG,
3356 "FILS: HLP response timeout - continue with association response for "
3357 MACSTR, MAC2STR(sta->addr));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003358 if (sta->fils_drv_assoc_finish)
3359 hostapd_notify_assoc_fils_finish(hapd, sta);
3360 else
3361 fils_hlp_finish_assoc(hapd, sta);
Paul Stewart092955c2017-02-06 09:13:09 -08003362}
3363
3364#endif /* CONFIG_FILS */
3365
3366
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003367static void handle_assoc(struct hostapd_data *hapd,
3368 const struct ieee80211_mgmt *mgmt, size_t len,
Hai Shalom74f70d42019-02-11 14:42:39 -08003369 int reassoc, int rssi)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003370{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003371 u16 capab_info, listen_interval, seq_ctrl, fc;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003372 u16 resp = WLAN_STATUS_SUCCESS, reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003373 const u8 *pos;
3374 int left, i;
3375 struct sta_info *sta;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003376 u8 *tmp = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003377 struct hostapd_sta_wpa_psk_short *psk = NULL;
3378 char *identity = NULL;
3379 char *radius_cui = NULL;
3380#ifdef CONFIG_FILS
3381 int delay_assoc = 0;
3382#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003383
3384 if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
3385 sizeof(mgmt->u.assoc_req))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003386 wpa_printf(MSG_INFO, "handle_assoc(reassoc=%d) - too short payload (len=%lu)",
3387 reassoc, (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003388 return;
3389 }
3390
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003391#ifdef CONFIG_TESTING_OPTIONS
3392 if (reassoc) {
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07003393 if (hapd->iconf->ignore_reassoc_probability > 0.0 &&
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003394 drand48() < hapd->iconf->ignore_reassoc_probability) {
3395 wpa_printf(MSG_INFO,
3396 "TESTING: ignoring reassoc request from "
3397 MACSTR, MAC2STR(mgmt->sa));
3398 return;
3399 }
3400 } else {
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07003401 if (hapd->iconf->ignore_assoc_probability > 0.0 &&
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003402 drand48() < hapd->iconf->ignore_assoc_probability) {
3403 wpa_printf(MSG_INFO,
3404 "TESTING: ignoring assoc request from "
3405 MACSTR, MAC2STR(mgmt->sa));
3406 return;
3407 }
3408 }
3409#endif /* CONFIG_TESTING_OPTIONS */
3410
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003411 fc = le_to_host16(mgmt->frame_control);
3412 seq_ctrl = le_to_host16(mgmt->seq_ctrl);
3413
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003414 if (reassoc) {
3415 capab_info = le_to_host16(mgmt->u.reassoc_req.capab_info);
3416 listen_interval = le_to_host16(
3417 mgmt->u.reassoc_req.listen_interval);
3418 wpa_printf(MSG_DEBUG, "reassociation request: STA=" MACSTR
3419 " capab_info=0x%02x listen_interval=%d current_ap="
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003420 MACSTR " seq_ctrl=0x%x%s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003421 MAC2STR(mgmt->sa), capab_info, listen_interval,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003422 MAC2STR(mgmt->u.reassoc_req.current_ap),
3423 seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003424 left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.reassoc_req));
3425 pos = mgmt->u.reassoc_req.variable;
3426 } else {
3427 capab_info = le_to_host16(mgmt->u.assoc_req.capab_info);
3428 listen_interval = le_to_host16(
3429 mgmt->u.assoc_req.listen_interval);
3430 wpa_printf(MSG_DEBUG, "association request: STA=" MACSTR
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003431 " capab_info=0x%02x listen_interval=%d "
3432 "seq_ctrl=0x%x%s",
3433 MAC2STR(mgmt->sa), capab_info, listen_interval,
3434 seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003435 left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req));
3436 pos = mgmt->u.assoc_req.variable;
3437 }
3438
3439 sta = ap_get_sta(hapd, mgmt->sa);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003440#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003441 if (sta && sta->auth_alg == WLAN_AUTH_FT &&
3442 (sta->flags & WLAN_STA_AUTH) == 0) {
3443 wpa_printf(MSG_DEBUG, "FT: Allow STA " MACSTR " to associate "
3444 "prior to authentication since it is using "
3445 "over-the-DS FT", MAC2STR(mgmt->sa));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003446
3447 /*
3448 * Mark station as authenticated, to avoid adding station
3449 * entry in the driver as associated and not authenticated
3450 */
3451 sta->flags |= WLAN_STA_AUTH;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003452 } else
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003453#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003454 if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) {
Dmitry Shmidt29333592017-01-09 12:27:11 -08003455 if (hapd->iface->current_mode &&
3456 hapd->iface->current_mode->mode ==
3457 HOSTAPD_MODE_IEEE80211AD) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003458 int acl_res;
3459 u32 session_timeout, acct_interim_interval;
3460 struct vlan_description vlan_id;
3461
3462 acl_res = ieee802_11_allowed_address(
3463 hapd, mgmt->sa, (const u8 *) mgmt, len,
3464 &session_timeout, &acct_interim_interval,
Roshan Pius3a1667e2018-07-03 15:17:14 -07003465 &vlan_id, &psk, &identity, &radius_cui, 0);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003466 if (acl_res == HOSTAPD_ACL_REJECT) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003467 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
3468 "Ignore Association Request frame from "
3469 MACSTR " due to ACL reject",
3470 MAC2STR(mgmt->sa));
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003471 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
3472 goto fail;
3473 }
3474 if (acl_res == HOSTAPD_ACL_PENDING)
3475 return;
3476
Dmitry Shmidt29333592017-01-09 12:27:11 -08003477 /* DMG/IEEE 802.11ad does not use authentication.
3478 * Allocate sta entry upon association. */
3479 sta = ap_sta_add(hapd, mgmt->sa);
3480 if (!sta) {
3481 hostapd_logger(hapd, mgmt->sa,
3482 HOSTAPD_MODULE_IEEE80211,
3483 HOSTAPD_LEVEL_INFO,
3484 "Failed to add STA");
3485 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
3486 goto fail;
3487 }
3488
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003489 acl_res = ieee802_11_set_radius_info(
3490 hapd, sta, acl_res, session_timeout,
3491 acct_interim_interval, &vlan_id, &psk,
3492 &identity, &radius_cui);
3493 if (acl_res) {
3494 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
3495 goto fail;
3496 }
3497
Dmitry Shmidt29333592017-01-09 12:27:11 -08003498 hostapd_logger(hapd, sta->addr,
3499 HOSTAPD_MODULE_IEEE80211,
3500 HOSTAPD_LEVEL_DEBUG,
3501 "Skip authentication for DMG/IEEE 802.11ad");
3502 sta->flags |= WLAN_STA_AUTH;
3503 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
3504 sta->auth_alg = WLAN_AUTH_OPEN;
3505 } else {
3506 hostapd_logger(hapd, mgmt->sa,
3507 HOSTAPD_MODULE_IEEE80211,
3508 HOSTAPD_LEVEL_INFO,
3509 "Station tried to associate before authentication (aid=%d flags=0x%x)",
3510 sta ? sta->aid : -1,
3511 sta ? sta->flags : 0);
3512 send_deauth(hapd, mgmt->sa,
3513 WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
3514 return;
3515 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003516 }
3517
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003518 if ((fc & WLAN_FC_RETRY) &&
3519 sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ &&
3520 sta->last_seq_ctrl == seq_ctrl &&
Paul Stewart092955c2017-02-06 09:13:09 -08003521 sta->last_subtype == (reassoc ? WLAN_FC_STYPE_REASSOC_REQ :
3522 WLAN_FC_STYPE_ASSOC_REQ)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003523 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3524 HOSTAPD_LEVEL_DEBUG,
3525 "Drop repeated association frame seq_ctrl=0x%x",
3526 seq_ctrl);
3527 return;
3528 }
3529 sta->last_seq_ctrl = seq_ctrl;
3530 sta->last_subtype = reassoc ? WLAN_FC_STYPE_REASSOC_REQ :
3531 WLAN_FC_STYPE_ASSOC_REQ;
3532
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003533 if (hapd->tkip_countermeasures) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003534 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003535 goto fail;
3536 }
3537
3538 if (listen_interval > hapd->conf->max_listen_interval) {
3539 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
3540 HOSTAPD_LEVEL_DEBUG,
3541 "Too large Listen Interval (%d)",
3542 listen_interval);
3543 resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE;
3544 goto fail;
3545 }
3546
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003547#ifdef CONFIG_MBO
3548 if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) {
3549 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
3550 goto fail;
3551 }
Hai Shalom74f70d42019-02-11 14:42:39 -08003552
3553 if (hapd->iconf->rssi_reject_assoc_rssi && rssi &&
3554 rssi < hapd->iconf->rssi_reject_assoc_rssi &&
3555 (sta->auth_rssi == 0 ||
3556 sta->auth_rssi < hapd->iconf->rssi_reject_assoc_rssi)) {
3557 resp = WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS;
3558 goto fail;
3559 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003560#endif /* CONFIG_MBO */
3561
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003562 /*
3563 * sta->capability is used in check_assoc_ies() for RRM enabled
3564 * capability element.
3565 */
3566 sta->capability = capab_info;
3567
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003568#ifdef CONFIG_FILS
3569 if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
3570 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
3571 sta->auth_alg == WLAN_AUTH_FILS_PK) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003572 int res;
3573
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003574 /* The end of the payload is encrypted. Need to decrypt it
3575 * before parsing. */
3576
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003577 tmp = os_memdup(pos, left);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003578 if (!tmp) {
3579 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
3580 goto fail;
3581 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003582
Roshan Pius3a1667e2018-07-03 15:17:14 -07003583 res = fils_decrypt_assoc(sta->wpa_sm, sta->fils_session, mgmt,
3584 len, tmp, left);
3585 if (res < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003586 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
3587 goto fail;
3588 }
3589 pos = tmp;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003590 left = res;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003591 }
3592#endif /* CONFIG_FILS */
3593
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003594 /* followed by SSID and Supported rates; and HT capabilities if 802.11n
3595 * is used */
3596 resp = check_assoc_ies(hapd, sta, pos, left, reassoc);
3597 if (resp != WLAN_STATUS_SUCCESS)
3598 goto fail;
3599
3600 if (hostapd_get_aid(hapd, sta) < 0) {
3601 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
3602 HOSTAPD_LEVEL_INFO, "No room for more AIDs");
3603 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
3604 goto fail;
3605 }
3606
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003607 sta->listen_interval = listen_interval;
3608
Roshan Pius3a1667e2018-07-03 15:17:14 -07003609 if (hapd->iface->current_mode &&
3610 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003611 sta->flags |= WLAN_STA_NONERP;
3612 for (i = 0; i < sta->supported_rates_len; i++) {
3613 if ((sta->supported_rates[i] & 0x7f) > 22) {
3614 sta->flags &= ~WLAN_STA_NONERP;
3615 break;
3616 }
3617 }
3618 if (sta->flags & WLAN_STA_NONERP && !sta->nonerp_set) {
3619 sta->nonerp_set = 1;
3620 hapd->iface->num_sta_non_erp++;
3621 if (hapd->iface->num_sta_non_erp == 1)
3622 ieee802_11_set_beacons(hapd->iface);
3623 }
3624
3625 if (!(sta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) &&
3626 !sta->no_short_slot_time_set) {
3627 sta->no_short_slot_time_set = 1;
3628 hapd->iface->num_sta_no_short_slot_time++;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003629 if (hapd->iface->current_mode &&
3630 hapd->iface->current_mode->mode ==
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003631 HOSTAPD_MODE_IEEE80211G &&
3632 hapd->iface->num_sta_no_short_slot_time == 1)
3633 ieee802_11_set_beacons(hapd->iface);
3634 }
3635
3636 if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
3637 sta->flags |= WLAN_STA_SHORT_PREAMBLE;
3638 else
3639 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
3640
3641 if (!(sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
3642 !sta->no_short_preamble_set) {
3643 sta->no_short_preamble_set = 1;
3644 hapd->iface->num_sta_no_short_preamble++;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003645 if (hapd->iface->current_mode &&
3646 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003647 && hapd->iface->num_sta_no_short_preamble == 1)
3648 ieee802_11_set_beacons(hapd->iface);
3649 }
3650
3651#ifdef CONFIG_IEEE80211N
3652 update_ht_state(hapd, sta);
3653#endif /* CONFIG_IEEE80211N */
3654
3655 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3656 HOSTAPD_LEVEL_DEBUG,
3657 "association OK (aid %d)", sta->aid);
3658 /* Station will be marked associated, after it acknowledges AssocResp
3659 */
3660 sta->flags |= WLAN_STA_ASSOC_REQ_OK;
3661
3662#ifdef CONFIG_IEEE80211W
3663 if ((sta->flags & WLAN_STA_MFP) && sta->sa_query_timed_out) {
3664 wpa_printf(MSG_DEBUG, "Allowing %sassociation after timed out "
3665 "SA Query procedure", reassoc ? "re" : "");
3666 /* TODO: Send a protected Disassociate frame to the STA using
3667 * the old key and Reason Code "Previous Authentication no
3668 * longer valid". Make sure this is only sent protected since
3669 * unprotected frame would be received by the STA that is now
3670 * trying to associate.
3671 */
3672 }
3673#endif /* CONFIG_IEEE80211W */
3674
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003675 /* Make sure that the previously registered inactivity timer will not
3676 * remove the STA immediately. */
3677 sta->timeout_next = STA_NULLFUNC;
3678
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003679#ifdef CONFIG_TAXONOMY
3680 taxonomy_sta_info_assoc_req(hapd, sta, pos, left);
3681#endif /* CONFIG_TAXONOMY */
3682
Dmitry Shmidt29333592017-01-09 12:27:11 -08003683 sta->pending_wds_enable = 0;
3684
Paul Stewart092955c2017-02-06 09:13:09 -08003685#ifdef CONFIG_FILS
3686 if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
3687 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003688 sta->auth_alg == WLAN_AUTH_FILS_PK) {
3689 if (fils_process_hlp(hapd, sta, pos, left) > 0)
3690 delay_assoc = 1;
3691 }
Paul Stewart092955c2017-02-06 09:13:09 -08003692#endif /* CONFIG_FILS */
3693
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003694 fail:
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003695 os_free(identity);
3696 os_free(radius_cui);
3697 hostapd_free_psk_list(psk);
3698
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003699 /*
3700 * In case of a successful response, add the station to the driver.
3701 * Otherwise, the kernel may ignore Data frames before we process the
3702 * ACK frame (TX status). In case of a failure, this station will be
3703 * removed.
3704 *
3705 * Note that this is not compliant with the IEEE 802.11 standard that
3706 * states that a non-AP station should transition into the
3707 * authenticated/associated state only after the station acknowledges
3708 * the (Re)Association Response frame. However, still do this as:
3709 *
3710 * 1. In case the station does not acknowledge the (Re)Association
3711 * Response frame, it will be removed.
3712 * 2. Data frames will be dropped in the kernel until the station is
3713 * set into authorized state, and there are no significant known
3714 * issues with processing other non-Data Class 3 frames during this
3715 * window.
3716 */
Hai Shalom74f70d42019-02-11 14:42:39 -08003717 if (resp == WLAN_STATUS_SUCCESS && sta &&
3718 add_associated_sta(hapd, sta, reassoc))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003719 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
3720
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003721#ifdef CONFIG_FILS
Hai Shalom74f70d42019-02-11 14:42:39 -08003722 if (sta && delay_assoc && resp == WLAN_STATUS_SUCCESS &&
3723 eloop_is_timeout_registered(fils_hlp_timeout, hapd, sta) &&
3724 sta->fils_pending_assoc_req) {
3725 /* Do not reschedule fils_hlp_timeout in case the station
3726 * retransmits (Re)Association Request frame while waiting for
3727 * the previously started FILS HLP wait, so that the timeout can
3728 * be determined from the first pending attempt. */
3729 wpa_printf(MSG_DEBUG,
3730 "FILS: Continue waiting for HLP processing before sending (Re)Association Response frame to "
3731 MACSTR, MAC2STR(sta->addr));
3732 os_free(tmp);
3733 return;
3734 }
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003735 if (sta) {
3736 eloop_cancel_timeout(fils_hlp_timeout, hapd, sta);
3737 os_free(sta->fils_pending_assoc_req);
3738 sta->fils_pending_assoc_req = NULL;
3739 sta->fils_pending_assoc_req_len = 0;
3740 wpabuf_free(sta->fils_hlp_resp);
3741 sta->fils_hlp_resp = NULL;
3742 }
3743 if (sta && delay_assoc && resp == WLAN_STATUS_SUCCESS) {
3744 sta->fils_pending_assoc_req = tmp;
3745 sta->fils_pending_assoc_req_len = left;
3746 sta->fils_pending_assoc_is_reassoc = reassoc;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003747 sta->fils_drv_assoc_finish = 0;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003748 wpa_printf(MSG_DEBUG,
3749 "FILS: Waiting for HLP processing before sending (Re)Association Response frame to "
3750 MACSTR, MAC2STR(sta->addr));
3751 eloop_cancel_timeout(fils_hlp_timeout, hapd, sta);
3752 eloop_register_timeout(0, hapd->conf->fils_hlp_wait_time * 1024,
3753 fils_hlp_timeout, hapd, sta);
3754 return;
3755 }
3756#endif /* CONFIG_FILS */
3757
Dmitry Shmidt29333592017-01-09 12:27:11 -08003758 reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc, pos,
Hai Shalom74f70d42019-02-11 14:42:39 -08003759 left, rssi);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003760 os_free(tmp);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003761
3762 /*
3763 * Remove the station in case tranmission of a success response fails
3764 * (the STA was added associated to the driver) or if the station was
3765 * previously added unassociated.
3766 */
Dmitry Shmidt29333592017-01-09 12:27:11 -08003767 if (sta && ((reply_res != WLAN_STATUS_SUCCESS &&
3768 resp == WLAN_STATUS_SUCCESS) || sta->added_unassoc)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003769 hostapd_drv_sta_remove(hapd, sta->addr);
3770 sta->added_unassoc = 0;
3771 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003772}
3773
3774
3775static void handle_disassoc(struct hostapd_data *hapd,
3776 const struct ieee80211_mgmt *mgmt, size_t len)
3777{
3778 struct sta_info *sta;
3779
3780 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003781 wpa_printf(MSG_INFO, "handle_disassoc - too short payload (len=%lu)",
3782 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003783 return;
3784 }
3785
3786 wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d",
3787 MAC2STR(mgmt->sa),
3788 le_to_host16(mgmt->u.disassoc.reason_code));
3789
3790 sta = ap_get_sta(hapd, mgmt->sa);
3791 if (sta == NULL) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003792 wpa_printf(MSG_INFO, "Station " MACSTR " trying to disassociate, but it is not associated",
3793 MAC2STR(mgmt->sa));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003794 return;
3795 }
3796
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003797 ap_sta_set_authorized(hapd, sta, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003798 sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003799 sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003800 wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
3801 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3802 HOSTAPD_LEVEL_INFO, "disassociated");
3803 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
3804 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
3805 /* Stop Accounting and IEEE 802.1X sessions, but leave the STA
3806 * authenticated. */
3807 accounting_sta_stop(hapd, sta);
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003808 ieee802_1x_free_station(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003809 if (sta->ipaddr)
3810 hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
3811 ap_sta_ip6addr_del(hapd, sta);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003812 hostapd_drv_sta_remove(hapd, sta->addr);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003813 sta->added_unassoc = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003814
3815 if (sta->timeout_next == STA_NULLFUNC ||
3816 sta->timeout_next == STA_DISASSOC) {
3817 sta->timeout_next = STA_DEAUTH;
3818 eloop_cancel_timeout(ap_handle_timer, hapd, sta);
3819 eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
3820 hapd, sta);
3821 }
3822
3823 mlme_disassociate_indication(
3824 hapd, sta, le_to_host16(mgmt->u.disassoc.reason_code));
Dmitry Shmidt29333592017-01-09 12:27:11 -08003825
3826 /* DMG/IEEE 802.11ad does not use deauthication. Deallocate sta upon
3827 * disassociation. */
3828 if (hapd->iface->current_mode &&
3829 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD) {
3830 sta->flags &= ~WLAN_STA_AUTH;
3831 wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
3832 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3833 HOSTAPD_LEVEL_DEBUG, "deauthenticated");
3834 ap_free_sta(hapd, sta);
3835 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003836}
3837
3838
3839static void handle_deauth(struct hostapd_data *hapd,
3840 const struct ieee80211_mgmt *mgmt, size_t len)
3841{
3842 struct sta_info *sta;
3843
3844 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003845 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "handle_deauth - too short "
3846 "payload (len=%lu)", (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003847 return;
3848 }
3849
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003850 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "deauthentication: STA=" MACSTR
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003851 " reason_code=%d",
3852 MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code));
3853
3854 sta = ap_get_sta(hapd, mgmt->sa);
3855 if (sta == NULL) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003856 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying "
3857 "to deauthenticate, but it is not authenticated",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003858 MAC2STR(mgmt->sa));
3859 return;
3860 }
3861
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003862 ap_sta_set_authorized(hapd, sta, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003863 sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003864 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
3865 WLAN_STA_ASSOC_REQ_OK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003866 wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
3867 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3868 HOSTAPD_LEVEL_DEBUG, "deauthenticated");
3869 mlme_deauthenticate_indication(
3870 hapd, sta, le_to_host16(mgmt->u.deauth.reason_code));
3871 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
3872 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
3873 ap_free_sta(hapd, sta);
3874}
3875
3876
3877static void handle_beacon(struct hostapd_data *hapd,
3878 const struct ieee80211_mgmt *mgmt, size_t len,
3879 struct hostapd_frame_info *fi)
3880{
3881 struct ieee802_11_elems elems;
3882
3883 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.beacon)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003884 wpa_printf(MSG_INFO, "handle_beacon - too short payload (len=%lu)",
3885 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003886 return;
3887 }
3888
3889 (void) ieee802_11_parse_elems(mgmt->u.beacon.variable,
3890 len - (IEEE80211_HDRLEN +
3891 sizeof(mgmt->u.beacon)), &elems,
3892 0);
3893
3894 ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);
3895}
3896
3897
3898#ifdef CONFIG_IEEE80211W
3899
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003900static int hostapd_sa_query_action(struct hostapd_data *hapd,
3901 const struct ieee80211_mgmt *mgmt,
3902 size_t len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003903{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003904 const u8 *end;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003905
3906 end = mgmt->u.action.u.sa_query_resp.trans_id +
3907 WLAN_SA_QUERY_TR_ID_LEN;
3908 if (((u8 *) mgmt) + len < end) {
3909 wpa_printf(MSG_DEBUG, "IEEE 802.11: Too short SA Query Action "
3910 "frame (len=%lu)", (unsigned long) len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003911 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003912 }
3913
Hai Shalom74f70d42019-02-11 14:42:39 -08003914 ieee802_11_sa_query_action(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003915 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003916}
3917
3918
3919static int robust_action_frame(u8 category)
3920{
3921 return category != WLAN_ACTION_PUBLIC &&
3922 category != WLAN_ACTION_HT;
3923}
3924#endif /* CONFIG_IEEE80211W */
3925
3926
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003927static int handle_action(struct hostapd_data *hapd,
Roshan Pius3a1667e2018-07-03 15:17:14 -07003928 const struct ieee80211_mgmt *mgmt, size_t len,
3929 unsigned int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003930{
3931 struct sta_info *sta;
Hai Shalom74f70d42019-02-11 14:42:39 -08003932 u8 *action __maybe_unused;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003933
Hai Shalom74f70d42019-02-11 14:42:39 -08003934 if (len < IEEE80211_HDRLEN + 2 + 1) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003935 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
3936 HOSTAPD_LEVEL_DEBUG,
3937 "handle_action - too short payload (len=%lu)",
3938 (unsigned long) len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003939 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003940 }
3941
Hai Shalom74f70d42019-02-11 14:42:39 -08003942 action = (u8 *) &mgmt->u.action.u;
3943 wpa_printf(MSG_DEBUG, "RX_ACTION category %u action %u sa " MACSTR
3944 " da " MACSTR " len %d freq %u",
3945 mgmt->u.action.category, *action,
3946 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), (int) len, freq);
3947
3948 sta = ap_get_sta(hapd, mgmt->sa);
3949
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003950 if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
3951 (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))) {
3952 wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored Action "
3953 "frame (category=%u) from unassociated STA " MACSTR,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003954 mgmt->u.action.category, MAC2STR(mgmt->sa));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003955 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003956 }
3957
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003958#ifdef CONFIG_IEEE80211W
3959 if (sta && (sta->flags & WLAN_STA_MFP) &&
Dmitry Shmidt18463232014-01-24 12:29:41 -08003960 !(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP)) &&
3961 robust_action_frame(mgmt->u.action.category)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003962 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
3963 HOSTAPD_LEVEL_DEBUG,
3964 "Dropped unprotected Robust Action frame from "
3965 "an MFP STA");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003966 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003967 }
3968#endif /* CONFIG_IEEE80211W */
3969
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003970 if (sta) {
3971 u16 fc = le_to_host16(mgmt->frame_control);
3972 u16 seq_ctrl = le_to_host16(mgmt->seq_ctrl);
3973
3974 if ((fc & WLAN_FC_RETRY) &&
3975 sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ &&
3976 sta->last_seq_ctrl == seq_ctrl &&
3977 sta->last_subtype == WLAN_FC_STYPE_ACTION) {
3978 hostapd_logger(hapd, sta->addr,
3979 HOSTAPD_MODULE_IEEE80211,
3980 HOSTAPD_LEVEL_DEBUG,
3981 "Drop repeated action frame seq_ctrl=0x%x",
3982 seq_ctrl);
3983 return 1;
3984 }
3985
3986 sta->last_seq_ctrl = seq_ctrl;
3987 sta->last_subtype = WLAN_FC_STYPE_ACTION;
3988 }
3989
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003990 switch (mgmt->u.action.category) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003991#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003992 case WLAN_ACTION_FT:
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07003993 if (!sta ||
3994 wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003995 len - IEEE80211_HDRLEN))
3996 break;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003997 return 1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003998#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003999 case WLAN_ACTION_WMM:
4000 hostapd_wmm_action(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004001 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004002#ifdef CONFIG_IEEE80211W
4003 case WLAN_ACTION_SA_QUERY:
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004004 return hostapd_sa_query_action(hapd, mgmt, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004005#endif /* CONFIG_IEEE80211W */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004006#ifdef CONFIG_WNM_AP
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004007 case WLAN_ACTION_WNM:
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004008 ieee802_11_rx_wnm_action_ap(hapd, mgmt, len);
4009 return 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004010#endif /* CONFIG_WNM_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004011#ifdef CONFIG_FST
4012 case WLAN_ACTION_FST:
4013 if (hapd->iface->fst)
4014 fst_rx_action(hapd->iface->fst, mgmt, len);
4015 else
4016 wpa_printf(MSG_DEBUG,
4017 "FST: Ignore FST Action frame - no FST attached");
4018 return 1;
4019#endif /* CONFIG_FST */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004020 case WLAN_ACTION_PUBLIC:
Dmitry Shmidt18463232014-01-24 12:29:41 -08004021 case WLAN_ACTION_PROTECTED_DUAL:
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004022#ifdef CONFIG_IEEE80211N
Dmitry Shmidtcc00d5d2015-05-04 10:34:12 -07004023 if (len >= IEEE80211_HDRLEN + 2 &&
4024 mgmt->u.action.u.public_action.action ==
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004025 WLAN_PA_20_40_BSS_COEX) {
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004026 hostapd_2040_coex_action(hapd, mgmt, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004027 return 1;
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004028 }
4029#endif /* CONFIG_IEEE80211N */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004030#ifdef CONFIG_DPP
4031 if (len >= IEEE80211_HDRLEN + 6 &&
4032 mgmt->u.action.u.vs_public_action.action ==
4033 WLAN_PA_VENDOR_SPECIFIC &&
4034 WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) ==
4035 OUI_WFA &&
4036 mgmt->u.action.u.vs_public_action.variable[0] ==
4037 DPP_OUI_TYPE) {
4038 const u8 *pos, *end;
4039
4040 pos = mgmt->u.action.u.vs_public_action.oui;
4041 end = ((const u8 *) mgmt) + len;
4042 hostapd_dpp_rx_action(hapd, mgmt->sa, pos, end - pos,
Roshan Pius3a1667e2018-07-03 15:17:14 -07004043 freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004044 return 1;
4045 }
4046 if (len >= IEEE80211_HDRLEN + 2 &&
4047 (mgmt->u.action.u.public_action.action ==
4048 WLAN_PA_GAS_INITIAL_RESP ||
4049 mgmt->u.action.u.public_action.action ==
4050 WLAN_PA_GAS_COMEBACK_RESP)) {
4051 const u8 *pos, *end;
4052
4053 pos = &mgmt->u.action.u.public_action.action;
4054 end = ((const u8 *) mgmt) + len;
4055 gas_query_ap_rx(hapd->gas, mgmt->sa,
4056 mgmt->u.action.category,
4057 pos, end - pos, hapd->iface->freq);
4058 return 1;
4059 }
4060#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004061 if (hapd->public_action_cb) {
4062 hapd->public_action_cb(hapd->public_action_cb_ctx,
4063 (u8 *) mgmt, len,
4064 hapd->iface->freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004065 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004066 if (hapd->public_action_cb2) {
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004067 hapd->public_action_cb2(hapd->public_action_cb2_ctx,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004068 (u8 *) mgmt, len,
4069 hapd->iface->freq);
4070 }
4071 if (hapd->public_action_cb || hapd->public_action_cb2)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004072 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004073 break;
4074 case WLAN_ACTION_VENDOR_SPECIFIC:
4075 if (hapd->vendor_action_cb) {
4076 if (hapd->vendor_action_cb(hapd->vendor_action_cb_ctx,
4077 (u8 *) mgmt, len,
4078 hapd->iface->freq) == 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004079 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004080 }
4081 break;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004082 case WLAN_ACTION_RADIO_MEASUREMENT:
4083 hostapd_handle_radio_measurement(hapd, (const u8 *) mgmt, len);
4084 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004085 }
4086
4087 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
4088 HOSTAPD_LEVEL_DEBUG,
4089 "handle_action - unknown action category %d or invalid "
4090 "frame",
4091 mgmt->u.action.category);
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07004092 if (!is_multicast_ether_addr(mgmt->da) &&
4093 !(mgmt->u.action.category & 0x80) &&
4094 !is_multicast_ether_addr(mgmt->sa)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004095 struct ieee80211_mgmt *resp;
4096
4097 /*
4098 * IEEE 802.11-REVma/D9.0 - 7.3.1.11
4099 * Return the Action frame to the source without change
4100 * except that MSB of the Category set to 1.
4101 */
4102 wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action "
4103 "frame back to sender");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004104 resp = os_memdup(mgmt, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004105 if (resp == NULL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004106 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004107 os_memcpy(resp->da, resp->sa, ETH_ALEN);
4108 os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
4109 os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
4110 resp->u.action.category |= 0x80;
4111
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004112 if (hostapd_drv_send_mlme(hapd, resp, len, 0) < 0) {
4113 wpa_printf(MSG_ERROR, "IEEE 802.11: Failed to send "
4114 "Action frame");
4115 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004116 os_free(resp);
4117 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004118
4119 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004120}
4121
4122
4123/**
4124 * ieee802_11_mgmt - process incoming IEEE 802.11 management frames
4125 * @hapd: hostapd BSS data structure (the BSS to which the management frame was
4126 * sent to)
4127 * @buf: management frame data (starting from IEEE 802.11 header)
4128 * @len: length of frame data in octets
4129 * @fi: meta data about received frame (signal level, etc.)
4130 *
4131 * Process all incoming IEEE 802.11 management frames. This will be called for
4132 * each frame received from the kernel driver through wlan#ap interface. In
4133 * addition, it can be called to re-inserted pending frames (e.g., when using
4134 * external RADIUS server as an MAC ACL).
4135 */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004136int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
4137 struct hostapd_frame_info *fi)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004138{
4139 struct ieee80211_mgmt *mgmt;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004140 u16 fc, stype;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004141 int ret = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004142 unsigned int freq;
4143 int ssi_signal = fi ? fi->ssi_signal : 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004144
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004145 if (len < 24)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004146 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004147
Roshan Pius3a1667e2018-07-03 15:17:14 -07004148 if (fi && fi->freq)
4149 freq = fi->freq;
4150 else
4151 freq = hapd->iface->freq;
4152
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004153 mgmt = (struct ieee80211_mgmt *) buf;
4154 fc = le_to_host16(mgmt->frame_control);
4155 stype = WLAN_FC_GET_STYPE(fc);
4156
4157 if (stype == WLAN_FC_STYPE_BEACON) {
4158 handle_beacon(hapd, mgmt, len, fi);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004159 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004160 }
4161
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07004162 if (!is_broadcast_ether_addr(mgmt->bssid) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004163#ifdef CONFIG_P2P
4164 /* Invitation responses can be sent with the peer MAC as BSSID */
4165 !((hapd->conf->p2p & P2P_GROUP_OWNER) &&
4166 stype == WLAN_FC_STYPE_ACTION) &&
4167#endif /* CONFIG_P2P */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004168#ifdef CONFIG_MESH
4169 !(hapd->conf->mesh & MESH_ENABLED) &&
4170#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004171 os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004172 wpa_printf(MSG_INFO, "MGMT: BSSID=" MACSTR " not our address",
4173 MAC2STR(mgmt->bssid));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004174 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004175 }
4176
4177
4178 if (stype == WLAN_FC_STYPE_PROBE_REQ) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07004179 handle_probe_req(hapd, mgmt, len, ssi_signal);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004180 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004181 }
4182
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004183 if ((!is_broadcast_ether_addr(mgmt->da) ||
4184 stype != WLAN_FC_STYPE_ACTION) &&
4185 os_memcmp(mgmt->da, hapd->own_addr, ETH_ALEN) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004186 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
4187 HOSTAPD_LEVEL_DEBUG,
4188 "MGMT: DA=" MACSTR " not our address",
4189 MAC2STR(mgmt->da));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004190 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004191 }
4192
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004193 if (hapd->iconf->track_sta_max_num)
Roshan Pius3a1667e2018-07-03 15:17:14 -07004194 sta_track_add(hapd->iface, mgmt->sa, ssi_signal);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004195
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004196 switch (stype) {
4197 case WLAN_FC_STYPE_AUTH:
4198 wpa_printf(MSG_DEBUG, "mgmt::auth");
Hai Shalom74f70d42019-02-11 14:42:39 -08004199 handle_auth(hapd, mgmt, len, ssi_signal);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004200 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004201 break;
4202 case WLAN_FC_STYPE_ASSOC_REQ:
4203 wpa_printf(MSG_DEBUG, "mgmt::assoc_req");
Hai Shalom74f70d42019-02-11 14:42:39 -08004204 handle_assoc(hapd, mgmt, len, 0, ssi_signal);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004205 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004206 break;
4207 case WLAN_FC_STYPE_REASSOC_REQ:
4208 wpa_printf(MSG_DEBUG, "mgmt::reassoc_req");
Hai Shalom74f70d42019-02-11 14:42:39 -08004209 handle_assoc(hapd, mgmt, len, 1, ssi_signal);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004210 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004211 break;
4212 case WLAN_FC_STYPE_DISASSOC:
4213 wpa_printf(MSG_DEBUG, "mgmt::disassoc");
4214 handle_disassoc(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004215 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004216 break;
4217 case WLAN_FC_STYPE_DEAUTH:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004218 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "mgmt::deauth");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004219 handle_deauth(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004220 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004221 break;
4222 case WLAN_FC_STYPE_ACTION:
4223 wpa_printf(MSG_DEBUG, "mgmt::action");
Roshan Pius3a1667e2018-07-03 15:17:14 -07004224 ret = handle_action(hapd, mgmt, len, freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004225 break;
4226 default:
4227 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
4228 HOSTAPD_LEVEL_DEBUG,
4229 "unknown mgmt frame subtype %d", stype);
4230 break;
4231 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004232
4233 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004234}
4235
4236
4237static void handle_auth_cb(struct hostapd_data *hapd,
4238 const struct ieee80211_mgmt *mgmt,
4239 size_t len, int ok)
4240{
4241 u16 auth_alg, auth_transaction, status_code;
4242 struct sta_info *sta;
4243
Hai Shalome5e28bb2019-01-28 14:51:04 -08004244 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
4245 wpa_printf(MSG_INFO, "handle_auth_cb - too short payload (len=%lu)",
4246 (unsigned long) len);
4247
4248 /*
4249 * Initialize status_code here because we are not able to read
4250 * it from the short payload.
4251 */
4252 status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
4253 goto fail;
4254 }
4255
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004256 sta = ap_get_sta(hapd, mgmt->da);
4257 if (!sta) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004258 wpa_printf(MSG_DEBUG, "handle_auth_cb: STA " MACSTR
4259 " not found",
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004260 MAC2STR(mgmt->da));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004261 return;
4262 }
4263
4264 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
4265 auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
4266 status_code = le_to_host16(mgmt->u.auth.status_code);
4267
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004268 if (!ok) {
4269 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
4270 HOSTAPD_LEVEL_NOTICE,
4271 "did not acknowledge authentication response");
4272 goto fail;
4273 }
4274
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004275 if (status_code == WLAN_STATUS_SUCCESS &&
4276 ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) ||
4277 (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) {
4278 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4279 HOSTAPD_LEVEL_INFO, "authenticated");
4280 sta->flags |= WLAN_STA_AUTH;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004281 if (sta->added_unassoc)
4282 hostapd_set_sta_flags(hapd, sta);
4283 return;
4284 }
4285
4286fail:
4287 if (status_code != WLAN_STATUS_SUCCESS && sta->added_unassoc) {
4288 hostapd_drv_sta_remove(hapd, sta->addr);
4289 sta->added_unassoc = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004290 }
4291}
4292
4293
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004294static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
4295 struct sta_info *sta,
4296 char *ifname_wds)
4297{
4298 int i;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004299 struct hostapd_ssid *ssid = &hapd->conf->ssid;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004300
4301 if (hapd->conf->ieee802_1x || hapd->conf->wpa)
4302 return;
4303
4304 for (i = 0; i < 4; i++) {
4305 if (ssid->wep.key[i] &&
4306 hostapd_drv_set_key(ifname_wds, hapd, WPA_ALG_WEP, NULL, i,
4307 i == ssid->wep.idx, NULL, 0,
4308 ssid->wep.key[i], ssid->wep.len[i])) {
4309 wpa_printf(MSG_WARNING,
4310 "Could not set WEP keys for WDS interface; %s",
4311 ifname_wds);
4312 break;
4313 }
4314 }
4315}
4316
4317
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004318static void handle_assoc_cb(struct hostapd_data *hapd,
4319 const struct ieee80211_mgmt *mgmt,
4320 size_t len, int reassoc, int ok)
4321{
4322 u16 status;
4323 struct sta_info *sta;
4324 int new_assoc = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004325
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004326 sta = ap_get_sta(hapd, mgmt->da);
4327 if (!sta) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004328 wpa_printf(MSG_INFO, "handle_assoc_cb: STA " MACSTR " not found",
4329 MAC2STR(mgmt->da));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004330 return;
4331 }
4332
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004333 if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) :
4334 sizeof(mgmt->u.assoc_resp))) {
4335 wpa_printf(MSG_INFO,
4336 "handle_assoc_cb(reassoc=%d) - too short payload (len=%lu)",
4337 reassoc, (unsigned long) len);
4338 hostapd_drv_sta_remove(hapd, sta->addr);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07004339 return;
4340 }
4341
4342 if (reassoc)
4343 status = le_to_host16(mgmt->u.reassoc_resp.status_code);
4344 else
4345 status = le_to_host16(mgmt->u.assoc_resp.status_code);
4346
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004347 if (!ok) {
4348 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
4349 HOSTAPD_LEVEL_DEBUG,
4350 "did not acknowledge association response");
4351 sta->flags &= ~WLAN_STA_ASSOC_REQ_OK;
4352 /* The STA is added only in case of SUCCESS */
4353 if (status == WLAN_STATUS_SUCCESS)
4354 hostapd_drv_sta_remove(hapd, sta->addr);
4355
4356 return;
4357 }
4358
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004359 if (status != WLAN_STATUS_SUCCESS)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004360 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004361
4362 /* Stop previous accounting session, if one is started, and allocate
4363 * new session id for the new session. */
4364 accounting_sta_stop(hapd, sta);
4365
4366 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4367 HOSTAPD_LEVEL_INFO,
4368 "associated (aid %d)",
4369 sta->aid);
4370
4371 if (sta->flags & WLAN_STA_ASSOC)
4372 new_assoc = 0;
4373 sta->flags |= WLAN_STA_ASSOC;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004374 sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004375 if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
4376 !hapd->conf->osen) ||
4377 sta->auth_alg == WLAN_AUTH_FILS_SK ||
4378 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
4379 sta->auth_alg == WLAN_AUTH_FILS_PK ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004380 sta->auth_alg == WLAN_AUTH_FT) {
4381 /*
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004382 * Open, static WEP, FT protocol, or FILS; no separate
4383 * authorization step.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004384 */
4385 ap_sta_set_authorized(hapd, sta, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004386 }
4387
4388 if (reassoc)
4389 mlme_reassociate_indication(hapd, sta);
4390 else
4391 mlme_associate_indication(hapd, sta);
4392
4393#ifdef CONFIG_IEEE80211W
4394 sta->sa_query_timed_out = 0;
4395#endif /* CONFIG_IEEE80211W */
4396
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004397 if (sta->eapol_sm == NULL) {
4398 /*
4399 * This STA does not use RADIUS server for EAP authentication,
4400 * so bind it to the selected VLAN interface now, since the
4401 * interface selection is not going to change anymore.
4402 */
Dmitry Shmidt83474442015-04-15 13:47:09 -07004403 if (ap_sta_bind_vlan(hapd, sta) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004404 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004405 } else if (sta->vlan_id) {
4406 /* VLAN ID already set (e.g., by PMKSA caching), so bind STA */
Dmitry Shmidt83474442015-04-15 13:47:09 -07004407 if (ap_sta_bind_vlan(hapd, sta) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004408 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004409 }
4410
4411 hostapd_set_sta_flags(hapd, sta);
4412
Dmitry Shmidt29333592017-01-09 12:27:11 -08004413 if (!(sta->flags & WLAN_STA_WDS) && sta->pending_wds_enable) {
4414 wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for STA "
4415 MACSTR " based on pending request",
4416 MAC2STR(sta->addr));
4417 sta->pending_wds_enable = 0;
4418 sta->flags |= WLAN_STA_WDS;
4419 }
4420
Hai Shalom74f70d42019-02-11 14:42:39 -08004421 if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP)) {
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08004422 int ret;
4423 char ifname_wds[IFNAMSIZ + 1];
4424
4425 wpa_printf(MSG_DEBUG, "Reenable 4-address WDS mode for STA "
4426 MACSTR " (aid %u)",
4427 MAC2STR(sta->addr), sta->aid);
4428 ret = hostapd_set_wds_sta(hapd, ifname_wds, sta->addr,
4429 sta->aid, 1);
4430 if (!ret)
4431 hostapd_set_wds_encryption(hapd, sta, ifname_wds);
4432 }
4433
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004434 if (sta->auth_alg == WLAN_AUTH_FT)
4435 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
4436 else
4437 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
4438 hapd->new_assoc_sta_cb(hapd, sta, !new_assoc);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004439 ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08004440
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004441#ifdef CONFIG_FILS
4442 if ((sta->auth_alg == WLAN_AUTH_FILS_SK ||
4443 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
4444 sta->auth_alg == WLAN_AUTH_FILS_PK) &&
4445 fils_set_tk(sta->wpa_sm) < 0) {
4446 wpa_printf(MSG_DEBUG, "FILS: TK configuration failed");
4447 ap_sta_disconnect(hapd, sta, sta->addr,
4448 WLAN_REASON_UNSPECIFIED);
4449 return;
4450 }
4451#endif /* CONFIG_FILS */
4452
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08004453 if (sta->pending_eapol_rx) {
4454 struct os_reltime now, age;
4455
4456 os_get_reltime(&now);
4457 os_reltime_sub(&now, &sta->pending_eapol_rx->rx_time, &age);
4458 if (age.sec == 0 && age.usec < 200000) {
4459 wpa_printf(MSG_DEBUG,
4460 "Process pending EAPOL frame that was received from " MACSTR " just before association notification",
4461 MAC2STR(sta->addr));
4462 ieee802_1x_receive(
4463 hapd, mgmt->da,
4464 wpabuf_head(sta->pending_eapol_rx->buf),
4465 wpabuf_len(sta->pending_eapol_rx->buf));
4466 }
4467 wpabuf_free(sta->pending_eapol_rx->buf);
4468 os_free(sta->pending_eapol_rx);
4469 sta->pending_eapol_rx = NULL;
4470 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004471}
4472
4473
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004474static void handle_deauth_cb(struct hostapd_data *hapd,
4475 const struct ieee80211_mgmt *mgmt,
4476 size_t len, int ok)
4477{
4478 struct sta_info *sta;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07004479 if (is_multicast_ether_addr(mgmt->da))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004480 return;
4481 sta = ap_get_sta(hapd, mgmt->da);
4482 if (!sta) {
4483 wpa_printf(MSG_DEBUG, "handle_deauth_cb: STA " MACSTR
4484 " not found", MAC2STR(mgmt->da));
4485 return;
4486 }
4487 if (ok)
4488 wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged deauth",
4489 MAC2STR(sta->addr));
4490 else
4491 wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
4492 "deauth", MAC2STR(sta->addr));
4493
4494 ap_sta_deauth_cb(hapd, sta);
4495}
4496
4497
4498static void handle_disassoc_cb(struct hostapd_data *hapd,
4499 const struct ieee80211_mgmt *mgmt,
4500 size_t len, int ok)
4501{
4502 struct sta_info *sta;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07004503 if (is_multicast_ether_addr(mgmt->da))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004504 return;
4505 sta = ap_get_sta(hapd, mgmt->da);
4506 if (!sta) {
4507 wpa_printf(MSG_DEBUG, "handle_disassoc_cb: STA " MACSTR
4508 " not found", MAC2STR(mgmt->da));
4509 return;
4510 }
4511 if (ok)
4512 wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged disassoc",
4513 MAC2STR(sta->addr));
4514 else
4515 wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
4516 "disassoc", MAC2STR(sta->addr));
4517
4518 ap_sta_disassoc_cb(hapd, sta);
4519}
4520
4521
Dmitry Shmidt29333592017-01-09 12:27:11 -08004522static void handle_action_cb(struct hostapd_data *hapd,
4523 const struct ieee80211_mgmt *mgmt,
4524 size_t len, int ok)
4525{
4526 struct sta_info *sta;
Paul Stewart092955c2017-02-06 09:13:09 -08004527 const struct rrm_measurement_report_element *report;
Dmitry Shmidt29333592017-01-09 12:27:11 -08004528
4529 if (is_multicast_ether_addr(mgmt->da))
4530 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004531#ifdef CONFIG_DPP
4532 if (len >= IEEE80211_HDRLEN + 6 &&
4533 mgmt->u.action.category == WLAN_ACTION_PUBLIC &&
4534 mgmt->u.action.u.vs_public_action.action ==
4535 WLAN_PA_VENDOR_SPECIFIC &&
4536 WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) ==
4537 OUI_WFA &&
4538 mgmt->u.action.u.vs_public_action.variable[0] ==
4539 DPP_OUI_TYPE) {
4540 const u8 *pos, *end;
4541
4542 pos = &mgmt->u.action.u.vs_public_action.variable[1];
4543 end = ((const u8 *) mgmt) + len;
4544 hostapd_dpp_tx_status(hapd, mgmt->da, pos, end - pos, ok);
4545 return;
4546 }
4547 if (len >= IEEE80211_HDRLEN + 2 &&
4548 mgmt->u.action.category == WLAN_ACTION_PUBLIC &&
4549 (mgmt->u.action.u.public_action.action ==
4550 WLAN_PA_GAS_INITIAL_REQ ||
4551 mgmt->u.action.u.public_action.action ==
4552 WLAN_PA_GAS_COMEBACK_REQ)) {
4553 const u8 *pos, *end;
4554
4555 pos = mgmt->u.action.u.public_action.variable;
4556 end = ((const u8 *) mgmt) + len;
4557 gas_query_ap_tx_status(hapd->gas, mgmt->da, pos, end - pos, ok);
4558 return;
4559 }
4560#endif /* CONFIG_DPP */
Dmitry Shmidt29333592017-01-09 12:27:11 -08004561 sta = ap_get_sta(hapd, mgmt->da);
4562 if (!sta) {
4563 wpa_printf(MSG_DEBUG, "handle_action_cb: STA " MACSTR
4564 " not found", MAC2STR(mgmt->da));
4565 return;
4566 }
4567
Paul Stewart092955c2017-02-06 09:13:09 -08004568 if (len < 24 + 5 + sizeof(*report))
Dmitry Shmidt29333592017-01-09 12:27:11 -08004569 return;
Paul Stewart092955c2017-02-06 09:13:09 -08004570 report = (const struct rrm_measurement_report_element *)
4571 &mgmt->u.action.u.rrm.variable[2];
Dmitry Shmidt29333592017-01-09 12:27:11 -08004572 if (mgmt->u.action.category == WLAN_ACTION_RADIO_MEASUREMENT &&
Paul Stewart092955c2017-02-06 09:13:09 -08004573 mgmt->u.action.u.rrm.action == WLAN_RRM_RADIO_MEASUREMENT_REQUEST &&
4574 report->eid == WLAN_EID_MEASURE_REQUEST &&
4575 report->len >= 3 &&
4576 report->type == MEASURE_TYPE_BEACON)
Dmitry Shmidt29333592017-01-09 12:27:11 -08004577 hostapd_rrm_beacon_req_tx_status(hapd, mgmt, len, ok);
4578}
4579
4580
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004581/**
4582 * ieee802_11_mgmt_cb - Process management frame TX status callback
4583 * @hapd: hostapd BSS data structure (the BSS from which the management frame
4584 * was sent from)
4585 * @buf: management frame data (starting from IEEE 802.11 header)
4586 * @len: length of frame data in octets
4587 * @stype: management frame subtype from frame control field
4588 * @ok: Whether the frame was ACK'ed
4589 */
4590void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len,
4591 u16 stype, int ok)
4592{
4593 const struct ieee80211_mgmt *mgmt;
4594 mgmt = (const struct ieee80211_mgmt *) buf;
4595
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004596#ifdef CONFIG_TESTING_OPTIONS
4597 if (hapd->ext_mgmt_frame_handling) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004598 size_t hex_len = 2 * len + 1;
4599 char *hex = os_malloc(hex_len);
4600
4601 if (hex) {
4602 wpa_snprintf_hex(hex, hex_len, buf, len);
4603 wpa_msg(hapd->msg_ctx, MSG_INFO,
4604 "MGMT-TX-STATUS stype=%u ok=%d buf=%s",
4605 stype, ok, hex);
4606 os_free(hex);
4607 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004608 return;
4609 }
4610#endif /* CONFIG_TESTING_OPTIONS */
4611
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004612 switch (stype) {
4613 case WLAN_FC_STYPE_AUTH:
4614 wpa_printf(MSG_DEBUG, "mgmt::auth cb");
4615 handle_auth_cb(hapd, mgmt, len, ok);
4616 break;
4617 case WLAN_FC_STYPE_ASSOC_RESP:
4618 wpa_printf(MSG_DEBUG, "mgmt::assoc_resp cb");
4619 handle_assoc_cb(hapd, mgmt, len, 0, ok);
4620 break;
4621 case WLAN_FC_STYPE_REASSOC_RESP:
4622 wpa_printf(MSG_DEBUG, "mgmt::reassoc_resp cb");
4623 handle_assoc_cb(hapd, mgmt, len, 1, ok);
4624 break;
4625 case WLAN_FC_STYPE_PROBE_RESP:
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004626 wpa_printf(MSG_EXCESSIVE, "mgmt::proberesp cb ok=%d", ok);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004627 break;
4628 case WLAN_FC_STYPE_DEAUTH:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004629 wpa_printf(MSG_DEBUG, "mgmt::deauth cb");
4630 handle_deauth_cb(hapd, mgmt, len, ok);
4631 break;
4632 case WLAN_FC_STYPE_DISASSOC:
4633 wpa_printf(MSG_DEBUG, "mgmt::disassoc cb");
4634 handle_disassoc_cb(hapd, mgmt, len, ok);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004635 break;
4636 case WLAN_FC_STYPE_ACTION:
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004637 wpa_printf(MSG_DEBUG, "mgmt::action cb ok=%d", ok);
Dmitry Shmidt29333592017-01-09 12:27:11 -08004638 handle_action_cb(hapd, mgmt, len, ok);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004639 break;
4640 default:
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004641 wpa_printf(MSG_INFO, "unknown mgmt cb frame subtype %d", stype);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004642 break;
4643 }
4644}
4645
4646
4647int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
4648{
4649 /* TODO */
4650 return 0;
4651}
4652
4653
4654int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
4655 char *buf, size_t buflen)
4656{
4657 /* TODO */
4658 return 0;
4659}
4660
4661
4662void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
4663 const u8 *buf, size_t len, int ack)
4664{
4665 struct sta_info *sta;
4666 struct hostapd_iface *iface = hapd->iface;
4667
4668 sta = ap_get_sta(hapd, addr);
4669 if (sta == NULL && iface->num_bss > 1) {
4670 size_t j;
4671 for (j = 0; j < iface->num_bss; j++) {
4672 hapd = iface->bss[j];
4673 sta = ap_get_sta(hapd, addr);
4674 if (sta)
4675 break;
4676 }
4677 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004678 if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004679 return;
4680 if (sta->flags & WLAN_STA_PENDING_POLL) {
4681 wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending "
4682 "activity poll", MAC2STR(sta->addr),
4683 ack ? "ACKed" : "did not ACK");
4684 if (ack)
4685 sta->flags &= ~WLAN_STA_PENDING_POLL;
4686 }
4687
4688 ieee802_1x_tx_status(hapd, sta, buf, len, ack);
4689}
4690
4691
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004692void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
4693 const u8 *data, size_t len, int ack)
4694{
4695 struct sta_info *sta;
4696 struct hostapd_iface *iface = hapd->iface;
4697
4698 sta = ap_get_sta(hapd, dst);
4699 if (sta == NULL && iface->num_bss > 1) {
4700 size_t j;
4701 for (j = 0; j < iface->num_bss; j++) {
4702 hapd = iface->bss[j];
4703 sta = ap_get_sta(hapd, dst);
4704 if (sta)
4705 break;
4706 }
4707 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004708 if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
4709 wpa_printf(MSG_DEBUG, "Ignore TX status for Data frame to STA "
4710 MACSTR " that is not currently associated",
4711 MAC2STR(dst));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004712 return;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004713 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004714
4715 ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack);
4716}
4717
4718
4719void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr)
4720{
4721 struct sta_info *sta;
4722 struct hostapd_iface *iface = hapd->iface;
4723
4724 sta = ap_get_sta(hapd, addr);
4725 if (sta == NULL && iface->num_bss > 1) {
4726 size_t j;
4727 for (j = 0; j < iface->num_bss; j++) {
4728 hapd = iface->bss[j];
4729 sta = ap_get_sta(hapd, addr);
4730 if (sta)
4731 break;
4732 }
4733 }
4734 if (sta == NULL)
4735 return;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004736 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POLL_OK MACSTR,
4737 MAC2STR(sta->addr));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004738 if (!(sta->flags & WLAN_STA_PENDING_POLL))
4739 return;
4740
4741 wpa_printf(MSG_DEBUG, "STA " MACSTR " ACKed pending "
4742 "activity poll", MAC2STR(sta->addr));
4743 sta->flags &= ~WLAN_STA_PENDING_POLL;
4744}
4745
4746
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004747void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
4748 int wds)
4749{
4750 struct sta_info *sta;
4751
4752 sta = ap_get_sta(hapd, src);
Dmitry Shmidt29333592017-01-09 12:27:11 -08004753 if (sta &&
4754 ((sta->flags & WLAN_STA_ASSOC) ||
4755 ((sta->flags & WLAN_STA_ASSOC_REQ_OK) && wds))) {
Dmitry Shmidtaa532512012-09-24 10:35:31 -07004756 if (!hapd->conf->wds_sta)
4757 return;
4758
Dmitry Shmidt29333592017-01-09 12:27:11 -08004759 if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK)) ==
4760 WLAN_STA_ASSOC_REQ_OK) {
4761 wpa_printf(MSG_DEBUG,
4762 "Postpone 4-address WDS mode enabling for STA "
4763 MACSTR " since TX status for AssocResp is not yet known",
4764 MAC2STR(sta->addr));
4765 sta->pending_wds_enable = 1;
4766 return;
4767 }
4768
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004769 if (wds && !(sta->flags & WLAN_STA_WDS)) {
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004770 int ret;
4771 char ifname_wds[IFNAMSIZ + 1];
4772
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004773 wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for "
4774 "STA " MACSTR " (aid %u)",
4775 MAC2STR(sta->addr), sta->aid);
4776 sta->flags |= WLAN_STA_WDS;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004777 ret = hostapd_set_wds_sta(hapd, ifname_wds,
4778 sta->addr, sta->aid, 1);
4779 if (!ret)
4780 hostapd_set_wds_encryption(hapd, sta,
4781 ifname_wds);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004782 }
4783 return;
4784 }
4785
4786 wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA "
4787 MACSTR, MAC2STR(src));
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07004788 if (is_multicast_ether_addr(src)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004789 /* Broadcast bit set in SA?! Ignore the frame silently. */
4790 return;
4791 }
4792
4793 if (sta && (sta->flags & WLAN_STA_ASSOC_REQ_OK)) {
4794 wpa_printf(MSG_DEBUG, "Association Response to the STA has "
4795 "already been sent, but no TX status yet known - "
4796 "ignore Class 3 frame issue with " MACSTR,
4797 MAC2STR(src));
4798 return;
4799 }
4800
4801 if (sta && (sta->flags & WLAN_STA_AUTH))
4802 hostapd_drv_sta_disassoc(
4803 hapd, src,
4804 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
4805 else
4806 hostapd_drv_sta_deauth(
4807 hapd, src,
4808 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
4809}
4810
4811
4812#endif /* CONFIG_NATIVE_WINDOWS */