blob: 5b704255497ff4a52c24e14235860cee410f26dc [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * hostapd / IEEE 802.11 Management
Dmitry Shmidt29333592017-01-09 12:27:11 -08003 * Copyright (c) 2002-2017, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "utils/includes.h"
10
11#ifndef CONFIG_NATIVE_WINDOWS
12
13#include "utils/common.h"
14#include "utils/eloop.h"
15#include "crypto/crypto.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080016#include "crypto/sha256.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070017#include "crypto/sha384.h"
18#include "crypto/sha512.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080019#include "crypto/random.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070020#include "common/ieee802_11_defs.h"
21#include "common/ieee802_11_common.h"
22#include "common/wpa_ctrl.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080023#include "common/sae.h"
Hai Shalom021b0b52019-04-10 11:17:58 -070024#include "common/dpp.h"
Hai Shalom74f70d42019-02-11 14:42:39 -080025#include "common/ocv.h"
Hai Shalom81f62d82019-07-22 12:10:00 -070026#include "common/wpa_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070027#include "radius/radius.h"
28#include "radius/radius_client.h"
29#include "p2p/p2p.h"
30#include "wps/wps.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080031#include "fst/fst.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070032#include "hostapd.h"
33#include "beacon.h"
34#include "ieee802_11_auth.h"
35#include "sta_info.h"
36#include "ieee802_1x.h"
37#include "wpa_auth.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080038#include "pmksa_cache_auth.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070039#include "wmm.h"
40#include "ap_list.h"
41#include "accounting.h"
42#include "ap_config.h"
43#include "ap_mlme.h"
44#include "p2p_hostapd.h"
45#include "ap_drv_ops.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080046#include "wnm_ap.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080047#include "hw_features.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070048#include "ieee802_11.h"
Dmitry Shmidtf21452a2014-02-26 10:55:25 -080049#include "dfs.h"
Dmitry Shmidt57c2d392016-02-23 13:40:19 -080050#include "mbo_ap.h"
Dmitry Shmidt849734c2016-05-27 09:59:01 -070051#include "rrm.h"
Dmitry Shmidtaca489e2016-09-28 15:44:14 -070052#include "taxonomy.h"
Dmitry Shmidtebd93af2017-02-21 13:40:44 -080053#include "fils_hlp.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070054#include "dpp_hostapd.h"
55#include "gas_query_ap.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070056
57
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070058#ifdef CONFIG_FILS
59static struct wpabuf *
60prepare_auth_resp_fils(struct hostapd_data *hapd,
61 struct sta_info *sta, u16 *resp,
62 struct rsn_pmksa_cache_entry *pmksa,
63 struct wpabuf *erp_resp,
64 const u8 *msk, size_t msk_len,
65 int *is_pub);
66#endif /* CONFIG_FILS */
Hai Shalom021b0b52019-04-10 11:17:58 -070067static void handle_auth(struct hostapd_data *hapd,
68 const struct ieee80211_mgmt *mgmt, size_t len,
69 int rssi, int from_queue);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070070
Hai Shalom74f70d42019-02-11 14:42:39 -080071
72u8 * hostapd_eid_multi_ap(struct hostapd_data *hapd, u8 *eid)
73{
74 u8 multi_ap_val = 0;
75
76 if (!hapd->conf->multi_ap)
77 return eid;
78 if (hapd->conf->multi_ap & BACKHAUL_BSS)
79 multi_ap_val |= MULTI_AP_BACKHAUL_BSS;
80 if (hapd->conf->multi_ap & FRONTHAUL_BSS)
81 multi_ap_val |= MULTI_AP_FRONTHAUL_BSS;
82
83 return eid + add_multi_ap_ie(eid, 9, multi_ap_val);
84}
85
86
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070087u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
88{
89 u8 *pos = eid;
90 int i, num, count;
91
92 if (hapd->iface->current_rates == NULL)
93 return eid;
94
95 *pos++ = WLAN_EID_SUPP_RATES;
96 num = hapd->iface->num_rates;
97 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
98 num++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080099 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
100 num++;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800101 if (hapd->conf->sae_pwe == 1 &&
102 wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt))
Hai Shalomc3565922019-10-28 11:58:20 -0700103 num++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700104 if (num > 8) {
105 /* rest of the rates are encoded in Extended supported
106 * rates element */
107 num = 8;
108 }
109
110 *pos++ = num;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700111 for (i = 0, count = 0; i < hapd->iface->num_rates && count < num;
112 i++) {
113 count++;
114 *pos = hapd->iface->current_rates[i].rate / 5;
115 if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
116 *pos |= 0x80;
117 pos++;
118 }
119
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800120 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht && count < 8) {
121 count++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700122 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800123 }
124
125 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht && count < 8) {
126 count++;
127 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
128 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700129
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800130 if (hapd->conf->sae_pwe == 1 &&
131 wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
132 count < 8) {
Hai Shalomc3565922019-10-28 11:58:20 -0700133 count++;
134 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
135 }
136
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700137 return pos;
138}
139
140
141u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
142{
143 u8 *pos = eid;
144 int i, num, count;
145
146 if (hapd->iface->current_rates == NULL)
147 return eid;
148
149 num = hapd->iface->num_rates;
150 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
151 num++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800152 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
153 num++;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800154 if (hapd->conf->sae_pwe == 1 &&
155 wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt))
Hai Shalomc3565922019-10-28 11:58:20 -0700156 num++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700157 if (num <= 8)
158 return eid;
159 num -= 8;
160
161 *pos++ = WLAN_EID_EXT_SUPP_RATES;
162 *pos++ = num;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700163 for (i = 0, count = 0; i < hapd->iface->num_rates && count < num + 8;
164 i++) {
165 count++;
166 if (count <= 8)
167 continue; /* already in SuppRates IE */
168 *pos = hapd->iface->current_rates[i].rate / 5;
169 if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
170 *pos |= 0x80;
171 pos++;
172 }
173
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800174 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) {
175 count++;
176 if (count > 8)
177 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
178 }
179
180 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) {
181 count++;
182 if (count > 8)
183 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
184 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700185
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -0800186 if (hapd->conf->sae_pwe == 1 &&
187 wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt)) {
Hai Shalomc3565922019-10-28 11:58:20 -0700188 count++;
189 if (count > 8)
190 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_SAE_H2E_ONLY;
191 }
192
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700193 return pos;
194}
195
196
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -0700197u16 hostapd_own_capab_info(struct hostapd_data *hapd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700198{
199 int capab = WLAN_CAPABILITY_ESS;
200 int privacy;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800201 int dfs;
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700202 int i;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800203
204 /* Check if any of configured channels require DFS */
205 dfs = hostapd_is_dfs_required(hapd->iface);
206 if (dfs < 0) {
207 wpa_printf(MSG_WARNING, "Failed to check if DFS is required; ret=%d",
208 dfs);
209 dfs = 0;
210 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700211
212 if (hapd->iface->num_sta_no_short_preamble == 0 &&
213 hapd->iconf->preamble == SHORT_PREAMBLE)
214 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
215
216 privacy = hapd->conf->ssid.wep.keys_set;
217
218 if (hapd->conf->ieee802_1x &&
219 (hapd->conf->default_wep_key_len ||
220 hapd->conf->individual_wep_key_len))
221 privacy = 1;
222
223 if (hapd->conf->wpa)
224 privacy = 1;
225
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800226#ifdef CONFIG_HS20
227 if (hapd->conf->osen)
228 privacy = 1;
229#endif /* CONFIG_HS20 */
230
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700231 if (privacy)
232 capab |= WLAN_CAPABILITY_PRIVACY;
233
234 if (hapd->iface->current_mode &&
235 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
236 hapd->iface->num_sta_no_short_slot_time == 0)
237 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
238
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800239 /*
240 * Currently, Spectrum Management capability bit is set when directly
241 * requested in configuration by spectrum_mgmt_required or when AP is
242 * running on DFS channel.
243 * TODO: Also consider driver support for TPC to set Spectrum Mgmt bit
244 */
245 if (hapd->iface->current_mode &&
246 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
247 (hapd->iconf->spectrum_mgmt_required || dfs))
248 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
249
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700250 for (i = 0; i < RRM_CAPABILITIES_IE_LEN; i++) {
251 if (hapd->conf->radio_measurements[i]) {
252 capab |= IEEE80211_CAP_RRM;
253 break;
254 }
255 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800256
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700257 return capab;
258}
259
260
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800261#ifndef CONFIG_NO_RC4
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700262static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
263 u16 auth_transaction, const u8 *challenge,
264 int iswep)
265{
266 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
267 HOSTAPD_LEVEL_DEBUG,
268 "authentication (shared key, transaction %d)",
269 auth_transaction);
270
271 if (auth_transaction == 1) {
272 if (!sta->challenge) {
273 /* Generate a pseudo-random challenge */
274 u8 key[8];
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800275
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700276 sta->challenge = os_zalloc(WLAN_AUTH_CHALLENGE_LEN);
277 if (sta->challenge == NULL)
278 return WLAN_STATUS_UNSPECIFIED_FAILURE;
279
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800280 if (os_get_random(key, sizeof(key)) < 0) {
281 os_free(sta->challenge);
282 sta->challenge = NULL;
283 return WLAN_STATUS_UNSPECIFIED_FAILURE;
284 }
285
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700286 rc4_skip(key, sizeof(key), 0,
287 sta->challenge, WLAN_AUTH_CHALLENGE_LEN);
288 }
289 return 0;
290 }
291
292 if (auth_transaction != 3)
293 return WLAN_STATUS_UNSPECIFIED_FAILURE;
294
295 /* Transaction 3 */
296 if (!iswep || !sta->challenge || !challenge ||
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700297 os_memcmp_const(sta->challenge, challenge,
298 WLAN_AUTH_CHALLENGE_LEN)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700299 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
300 HOSTAPD_LEVEL_INFO,
301 "shared key authentication - invalid "
302 "challenge-response");
303 return WLAN_STATUS_CHALLENGE_FAIL;
304 }
305
306 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
307 HOSTAPD_LEVEL_DEBUG,
308 "authentication OK (shared key)");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700309 sta->flags |= WLAN_STA_AUTH;
310 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700311 os_free(sta->challenge);
312 sta->challenge = NULL;
313
314 return 0;
315}
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800316#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700317
318
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800319static int send_auth_reply(struct hostapd_data *hapd,
320 const u8 *dst, const u8 *bssid,
321 u16 auth_alg, u16 auth_transaction, u16 resp,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700322 const u8 *ies, size_t ies_len, const char *dbg)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700323{
324 struct ieee80211_mgmt *reply;
325 u8 *buf;
326 size_t rlen;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800327 int reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700328
329 rlen = IEEE80211_HDRLEN + sizeof(reply->u.auth) + ies_len;
330 buf = os_zalloc(rlen);
331 if (buf == NULL)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800332 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700333
334 reply = (struct ieee80211_mgmt *) buf;
335 reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
336 WLAN_FC_STYPE_AUTH);
337 os_memcpy(reply->da, dst, ETH_ALEN);
338 os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
339 os_memcpy(reply->bssid, bssid, ETH_ALEN);
340
341 reply->u.auth.auth_alg = host_to_le16(auth_alg);
342 reply->u.auth.auth_transaction = host_to_le16(auth_transaction);
343 reply->u.auth.status_code = host_to_le16(resp);
344
345 if (ies && ies_len)
346 os_memcpy(reply->u.auth.variable, ies, ies_len);
347
348 wpa_printf(MSG_DEBUG, "authentication reply: STA=" MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700349 " auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu) (dbg=%s)",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700350 MAC2STR(dst), auth_alg, auth_transaction,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700351 resp, (unsigned long) ies_len, dbg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800352 if (hostapd_drv_send_mlme(hapd, reply, rlen, 0) < 0)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800353 wpa_printf(MSG_INFO, "send_auth_reply: send failed");
354 else
355 reply_res = WLAN_STATUS_SUCCESS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700356
357 os_free(buf);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800358
359 return reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700360}
361
362
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800363#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700364static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
365 u16 auth_transaction, u16 status,
366 const u8 *ies, size_t ies_len)
367{
368 struct hostapd_data *hapd = ctx;
369 struct sta_info *sta;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800370 int reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700371
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800372 reply_res = send_auth_reply(hapd, dst, bssid, WLAN_AUTH_FT,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700373 auth_transaction, status, ies, ies_len,
374 "auth-ft-finish");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700375
376 sta = ap_get_sta(hapd, dst);
377 if (sta == NULL)
378 return;
379
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800380 if (sta->added_unassoc && (reply_res != WLAN_STATUS_SUCCESS ||
381 status != WLAN_STATUS_SUCCESS)) {
382 hostapd_drv_sta_remove(hapd, sta->addr);
383 sta->added_unassoc = 0;
384 return;
385 }
386
387 if (status != WLAN_STATUS_SUCCESS)
388 return;
389
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700390 hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211,
391 HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)");
392 sta->flags |= WLAN_STA_AUTH;
393 mlme_authenticate_indication(hapd, sta);
394}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800395#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700396
397
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800398#ifdef CONFIG_SAE
399
Roshan Pius3a1667e2018-07-03 15:17:14 -0700400static void sae_set_state(struct sta_info *sta, enum sae_state state,
401 const char *reason)
402{
403 wpa_printf(MSG_DEBUG, "SAE: State %s -> %s for peer " MACSTR " (%s)",
404 sae_state_txt(sta->sae->state), sae_state_txt(state),
405 MAC2STR(sta->addr), reason);
406 sta->sae->state = state;
407}
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800408
409
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800410static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
Hai Shalomc3565922019-10-28 11:58:20 -0700411 struct sta_info *sta, int update,
412 int status_code)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800413{
414 struct wpabuf *buf;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700415 const char *password = NULL;
416 struct sae_password_entry *pw;
417 const char *rx_id = NULL;
Hai Shalomc3565922019-10-28 11:58:20 -0700418 int use_pt = 0;
419 struct sae_pt *pt = NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800420
Hai Shalomc3565922019-10-28 11:58:20 -0700421 if (sta->sae->tmp) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700422 rx_id = sta->sae->tmp->pw_id;
Hai Shalomc3565922019-10-28 11:58:20 -0700423 use_pt = sta->sae->tmp->h2e;
424 }
425
426 if (status_code == WLAN_STATUS_SUCCESS)
427 use_pt = 0;
428 else if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT)
429 use_pt = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700430
431 for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
432 if (!is_broadcast_ether_addr(pw->peer_addr) &&
433 os_memcmp(pw->peer_addr, sta->addr, ETH_ALEN) != 0)
434 continue;
435 if ((rx_id && !pw->identifier) || (!rx_id && pw->identifier))
436 continue;
437 if (rx_id && pw->identifier &&
438 os_strcmp(rx_id, pw->identifier) != 0)
439 continue;
440 password = pw->password;
Hai Shalomc3565922019-10-28 11:58:20 -0700441 pt = pw->pt;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700442 break;
443 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700444 if (!password) {
Hai Shalomc3565922019-10-28 11:58:20 -0700445 password = hapd->conf->ssid.wpa_passphrase;
446 pt = hapd->conf->ssid.pt;
447 }
448 if (!password || (use_pt && !pt)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800449 wpa_printf(MSG_DEBUG, "SAE: No password available");
450 return NULL;
451 }
452
Hai Shalomc3565922019-10-28 11:58:20 -0700453 if (update && use_pt &&
454 sae_prepare_commit_pt(sta->sae, pt, hapd->own_addr, sta->addr,
455 NULL) < 0)
456 return NULL;
457
458 if (update && !use_pt &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800459 sae_prepare_commit(hapd->own_addr, sta->addr,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700460 (u8 *) password, os_strlen(password), rx_id,
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800461 sta->sae) < 0) {
462 wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
463 return NULL;
464 }
465
Hai Shalom021b0b52019-04-10 11:17:58 -0700466 if (pw && pw->vlan_id) {
467 if (!sta->sae->tmp) {
468 wpa_printf(MSG_INFO,
469 "SAE: No temporary data allocated - cannot store VLAN ID");
470 return NULL;
471 }
472 sta->sae->tmp->vlan_id = pw->vlan_id;
473 }
474
Roshan Pius3a1667e2018-07-03 15:17:14 -0700475 buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN +
476 (rx_id ? 3 + os_strlen(rx_id) : 0));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800477 if (buf == NULL)
478 return NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800479 sae_write_commit(sta->sae, buf, sta->sae->tmp ?
Roshan Pius3a1667e2018-07-03 15:17:14 -0700480 sta->sae->tmp->anti_clogging_token : NULL, rx_id);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800481
482 return buf;
483}
484
485
486static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
487 struct sta_info *sta)
488{
489 struct wpabuf *buf;
490
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800491 buf = wpabuf_alloc(SAE_CONFIRM_MAX_LEN);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800492 if (buf == NULL)
493 return NULL;
494
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800495 sae_write_confirm(sta->sae, buf);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800496
497 return buf;
498}
499
500
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800501static int auth_sae_send_commit(struct hostapd_data *hapd,
502 struct sta_info *sta,
Hai Shalomc3565922019-10-28 11:58:20 -0700503 const u8 *bssid, int update, int status_code)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800504{
505 struct wpabuf *data;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800506 int reply_res;
Hai Shalomc3565922019-10-28 11:58:20 -0700507 u16 status;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800508
Hai Shalomc3565922019-10-28 11:58:20 -0700509 data = auth_build_sae_commit(hapd, sta, update, status_code);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700510 if (!data && sta->sae->tmp && sta->sae->tmp->pw_id)
511 return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800512 if (data == NULL)
513 return WLAN_STATUS_UNSPECIFIED_FAILURE;
514
Hai Shalomc3565922019-10-28 11:58:20 -0700515 status = (sta->sae->tmp && sta->sae->tmp->h2e) ?
516 WLAN_STATUS_SAE_HASH_TO_ELEMENT : WLAN_STATUS_SUCCESS;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800517 reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 1,
Hai Shalomc3565922019-10-28 11:58:20 -0700518 status, wpabuf_head(data),
Roshan Pius3a1667e2018-07-03 15:17:14 -0700519 wpabuf_len(data), "sae-send-commit");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800520
521 wpabuf_free(data);
522
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800523 return reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800524}
525
526
527static int auth_sae_send_confirm(struct hostapd_data *hapd,
528 struct sta_info *sta,
529 const u8 *bssid)
530{
531 struct wpabuf *data;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800532 int reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800533
534 data = auth_build_sae_confirm(hapd, sta);
535 if (data == NULL)
536 return WLAN_STATUS_UNSPECIFIED_FAILURE;
537
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800538 reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 2,
539 WLAN_STATUS_SUCCESS, wpabuf_head(data),
Roshan Pius3a1667e2018-07-03 15:17:14 -0700540 wpabuf_len(data), "sae-send-confirm");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800541
542 wpabuf_free(data);
543
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800544 return reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800545}
546
547
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800548static int use_sae_anti_clogging(struct hostapd_data *hapd)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800549{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800550 struct sta_info *sta;
551 unsigned int open = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800552
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800553 if (hapd->conf->sae_anti_clogging_threshold == 0)
554 return 1;
555
556 for (sta = hapd->sta_list; sta; sta = sta->next) {
557 if (!sta->sae)
558 continue;
559 if (sta->sae->state != SAE_COMMITTED &&
560 sta->sae->state != SAE_CONFIRMED)
561 continue;
562 open++;
563 if (open >= hapd->conf->sae_anti_clogging_threshold)
564 return 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800565 }
566
Hai Shalom021b0b52019-04-10 11:17:58 -0700567 /* In addition to already existing open SAE sessions, check whether
568 * there are enough pending commit messages in the processing queue to
569 * potentially result in too many open sessions. */
570 if (open + dl_list_len(&hapd->sae_commit_queue) >=
571 hapd->conf->sae_anti_clogging_threshold)
572 return 1;
573
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800574 return 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800575}
576
577
Hai Shalom021b0b52019-04-10 11:17:58 -0700578static u8 sae_token_hash(struct hostapd_data *hapd, const u8 *addr)
579{
580 u8 hash[SHA256_MAC_LEN];
581
582 hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
583 addr, ETH_ALEN, hash);
584 return hash[0];
585}
586
587
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800588static int check_sae_token(struct hostapd_data *hapd, const u8 *addr,
589 const u8 *token, size_t token_len)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800590{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800591 u8 mac[SHA256_MAC_LEN];
Hai Shalom021b0b52019-04-10 11:17:58 -0700592 const u8 *addrs[2];
593 size_t len[2];
594 u16 token_idx;
595 u8 idx;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800596
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800597 if (token_len != SHA256_MAC_LEN)
598 return -1;
Hai Shalom021b0b52019-04-10 11:17:58 -0700599 idx = sae_token_hash(hapd, addr);
600 token_idx = hapd->sae_pending_token_idx[idx];
601 if (token_idx == 0 || token_idx != WPA_GET_BE16(token)) {
602 wpa_printf(MSG_DEBUG, "SAE: Invalid anti-clogging token from "
603 MACSTR " - token_idx 0x%04x, expected 0x%04x",
604 MAC2STR(addr), WPA_GET_BE16(token), token_idx);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800605 return -1;
Hai Shalom021b0b52019-04-10 11:17:58 -0700606 }
607
608 addrs[0] = addr;
609 len[0] = ETH_ALEN;
610 addrs[1] = token;
611 len[1] = 2;
612 if (hmac_sha256_vector(hapd->sae_token_key, sizeof(hapd->sae_token_key),
613 2, addrs, len, mac) < 0 ||
614 os_memcmp_const(token + 2, &mac[2], SHA256_MAC_LEN - 2) != 0)
615 return -1;
616
617 hapd->sae_pending_token_idx[idx] = 0; /* invalidate used token */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800618
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800619 return 0;
620}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800621
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800622
623static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800624 int group, const u8 *addr)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800625{
626 struct wpabuf *buf;
627 u8 *token;
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800628 struct os_reltime now;
Hai Shalom021b0b52019-04-10 11:17:58 -0700629 u8 idx[2];
630 const u8 *addrs[2];
631 size_t len[2];
632 u8 p_idx;
633 u16 token_idx;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800634
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800635 os_get_reltime(&now);
636 if (!os_reltime_initialized(&hapd->last_sae_token_key_update) ||
Hai Shalom021b0b52019-04-10 11:17:58 -0700637 os_reltime_expired(&now, &hapd->last_sae_token_key_update, 60) ||
638 hapd->sae_token_idx == 0xffff) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800639 if (random_get_bytes(hapd->sae_token_key,
640 sizeof(hapd->sae_token_key)) < 0)
641 return NULL;
642 wpa_hexdump(MSG_DEBUG, "SAE: Updated token key",
643 hapd->sae_token_key, sizeof(hapd->sae_token_key));
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800644 hapd->last_sae_token_key_update = now;
Hai Shalom021b0b52019-04-10 11:17:58 -0700645 hapd->sae_token_idx = 0;
646 os_memset(hapd->sae_pending_token_idx, 0,
647 sizeof(hapd->sae_pending_token_idx));
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800648 }
649
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800650 buf = wpabuf_alloc(sizeof(le16) + SHA256_MAC_LEN);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800651 if (buf == NULL)
652 return NULL;
653
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800654 wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
655
Hai Shalom021b0b52019-04-10 11:17:58 -0700656 p_idx = sae_token_hash(hapd, addr);
657 token_idx = hapd->sae_pending_token_idx[p_idx];
658 if (!token_idx) {
659 hapd->sae_token_idx++;
660 token_idx = hapd->sae_token_idx;
661 hapd->sae_pending_token_idx[p_idx] = token_idx;
662 }
663 WPA_PUT_BE16(idx, token_idx);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800664 token = wpabuf_put(buf, SHA256_MAC_LEN);
Hai Shalom021b0b52019-04-10 11:17:58 -0700665 addrs[0] = addr;
666 len[0] = ETH_ALEN;
667 addrs[1] = idx;
668 len[1] = sizeof(idx);
669 if (hmac_sha256_vector(hapd->sae_token_key, sizeof(hapd->sae_token_key),
670 2, addrs, len, token) < 0) {
671 wpabuf_free(buf);
672 return NULL;
673 }
674 WPA_PUT_BE16(token, token_idx);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800675
676 return buf;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800677}
678
679
Roshan Pius3a1667e2018-07-03 15:17:14 -0700680static int sae_check_big_sync(struct hostapd_data *hapd, struct sta_info *sta)
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800681{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700682 if (sta->sae->sync > hapd->conf->sae_sync) {
683 sae_set_state(sta, SAE_NOTHING, "Sync > dot11RSNASAESync");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800684 sta->sae->sync = 0;
685 return -1;
686 }
687 return 0;
688}
689
690
691static void auth_sae_retransmit_timer(void *eloop_ctx, void *eloop_data)
692{
693 struct hostapd_data *hapd = eloop_ctx;
694 struct sta_info *sta = eloop_data;
695 int ret;
696
Roshan Pius3a1667e2018-07-03 15:17:14 -0700697 if (sae_check_big_sync(hapd, sta))
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800698 return;
699 sta->sae->sync++;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700700 wpa_printf(MSG_DEBUG, "SAE: Auth SAE retransmit timer for " MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700701 " (sync=%d state=%s)",
702 MAC2STR(sta->addr), sta->sae->sync,
703 sae_state_txt(sta->sae->state));
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800704
705 switch (sta->sae->state) {
706 case SAE_COMMITTED:
Hai Shalomc3565922019-10-28 11:58:20 -0700707 ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0, -1);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800708 eloop_register_timeout(0,
709 hapd->dot11RSNASAERetransPeriod * 1000,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800710 auth_sae_retransmit_timer, hapd, sta);
711 break;
712 case SAE_CONFIRMED:
713 ret = auth_sae_send_confirm(hapd, sta, hapd->own_addr);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800714 eloop_register_timeout(0,
715 hapd->dot11RSNASAERetransPeriod * 1000,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800716 auth_sae_retransmit_timer, hapd, sta);
717 break;
718 default:
719 ret = -1;
720 break;
721 }
722
723 if (ret != WLAN_STATUS_SUCCESS)
724 wpa_printf(MSG_INFO, "SAE: Failed to retransmit: ret=%d", ret);
725}
726
727
728void sae_clear_retransmit_timer(struct hostapd_data *hapd, struct sta_info *sta)
729{
730 eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta);
731}
732
733
734static void sae_set_retransmit_timer(struct hostapd_data *hapd,
735 struct sta_info *sta)
736{
737 if (!(hapd->conf->mesh & MESH_ENABLED))
738 return;
739
740 eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800741 eloop_register_timeout(0, hapd->dot11RSNASAERetransPeriod * 1000,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800742 auth_sae_retransmit_timer, hapd, sta);
743}
744
745
Hai Shalom5f92bc92019-04-18 11:54:11 -0700746static void sae_sme_send_external_auth_status(struct hostapd_data *hapd,
747 struct sta_info *sta, u16 status)
748{
749 struct external_auth params;
750
751 os_memset(&params, 0, sizeof(params));
752 params.status = status;
753 params.bssid = sta->addr;
Hai Shalom81f62d82019-07-22 12:10:00 -0700754 if (status == WLAN_STATUS_SUCCESS && sta->sae &&
755 !hapd->conf->disable_pmksa_caching)
Hai Shalom5f92bc92019-04-18 11:54:11 -0700756 params.pmkid = sta->sae->pmkid;
757
758 hostapd_drv_send_external_auth_status(hapd, &params);
759}
760
761
Dmitry Shmidte4663042016-04-04 10:07:49 -0700762void sae_accept_sta(struct hostapd_data *hapd, struct sta_info *sta)
763{
Hai Shalom021b0b52019-04-10 11:17:58 -0700764#ifndef CONFIG_NO_VLAN
765 struct vlan_description vlan_desc;
766
767 if (sta->sae->tmp && sta->sae->tmp->vlan_id > 0) {
768 wpa_printf(MSG_DEBUG, "SAE: Assign STA " MACSTR
769 " to VLAN ID %d",
770 MAC2STR(sta->addr), sta->sae->tmp->vlan_id);
771
772 os_memset(&vlan_desc, 0, sizeof(vlan_desc));
773 vlan_desc.notempty = 1;
774 vlan_desc.untagged = sta->sae->tmp->vlan_id;
775 if (!hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) {
776 wpa_printf(MSG_INFO,
777 "Invalid VLAN ID %d in sae_password",
778 sta->sae->tmp->vlan_id);
779 return;
780 }
781
782 if (ap_sta_set_vlan(hapd, sta, &vlan_desc) < 0 ||
783 ap_sta_bind_vlan(hapd, sta) < 0) {
784 wpa_printf(MSG_INFO,
785 "Failed to assign VLAN ID %d from sae_password to "
786 MACSTR, sta->sae->tmp->vlan_id,
787 MAC2STR(sta->addr));
788 return;
789 }
790 }
791#endif /* CONFIG_NO_VLAN */
792
Dmitry Shmidte4663042016-04-04 10:07:49 -0700793 sta->flags |= WLAN_STA_AUTH;
794 sta->auth_alg = WLAN_AUTH_SAE;
795 mlme_authenticate_indication(hapd, sta);
796 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700797 sae_set_state(sta, SAE_ACCEPTED, "Accept Confirm");
Dmitry Shmidte4663042016-04-04 10:07:49 -0700798 wpa_auth_pmksa_add_sae(hapd->wpa_auth, sta->addr,
799 sta->sae->pmk, sta->sae->pmkid);
Hai Shalom5f92bc92019-04-18 11:54:11 -0700800 sae_sme_send_external_auth_status(hapd, sta, WLAN_STATUS_SUCCESS);
Dmitry Shmidte4663042016-04-04 10:07:49 -0700801}
802
803
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800804static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
Hai Shalomc3565922019-10-28 11:58:20 -0700805 const u8 *bssid, u16 auth_transaction, u16 status_code,
806 int allow_reuse, int *sta_removed)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800807{
808 int ret;
809
Hai Shalom5f92bc92019-04-18 11:54:11 -0700810 *sta_removed = 0;
811
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800812 if (auth_transaction != 1 && auth_transaction != 2)
813 return WLAN_STATUS_UNSPECIFIED_FAILURE;
814
Roshan Pius3a1667e2018-07-03 15:17:14 -0700815 wpa_printf(MSG_DEBUG, "SAE: Peer " MACSTR " state=%s auth_trans=%u",
816 MAC2STR(sta->addr), sae_state_txt(sta->sae->state),
817 auth_transaction);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800818 switch (sta->sae->state) {
819 case SAE_NOTHING:
820 if (auth_transaction == 1) {
Hai Shalomc3565922019-10-28 11:58:20 -0700821 if (sta->sae->tmp)
822 sta->sae->tmp->h2e = status_code ==
823 WLAN_STATUS_SAE_HASH_TO_ELEMENT;
Hai Shalom021b0b52019-04-10 11:17:58 -0700824 ret = auth_sae_send_commit(hapd, sta, bssid,
Hai Shalomc3565922019-10-28 11:58:20 -0700825 !allow_reuse, status_code);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800826 if (ret)
827 return ret;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700828 sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800829
830 if (sae_process_commit(sta->sae) < 0)
831 return WLAN_STATUS_UNSPECIFIED_FAILURE;
832
833 /*
Hai Shalomc3565922019-10-28 11:58:20 -0700834 * In mesh case, both Commit and Confirm are sent
835 * immediately. In infrastructure BSS, by default, only
836 * a single Authentication frame (Commit) is expected
837 * from the AP here and the second one (Confirm) will
838 * be sent once the STA has sent its second
839 * Authentication frame (Confirm). This behavior can be
840 * overridden with explicit configuration so that the
841 * infrastructure BSS case sends both frames together.
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800842 */
Hai Shalomc3565922019-10-28 11:58:20 -0700843 if ((hapd->conf->mesh & MESH_ENABLED) ||
844 hapd->conf->sae_confirm_immediate) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800845 /*
846 * Send both Commit and Confirm immediately
847 * based on SAE finite state machine
848 * Nothing -> Confirm transition.
849 */
850 ret = auth_sae_send_confirm(hapd, sta, bssid);
851 if (ret)
852 return ret;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700853 sae_set_state(sta, SAE_CONFIRMED,
854 "Sent Confirm (mesh)");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800855 } else {
856 /*
857 * For infrastructure BSS, send only the Commit
858 * message now to get alternating sequence of
859 * Authentication frames between the AP and STA.
860 * Confirm will be sent in
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800861 * Committed -> Confirmed/Accepted transition
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800862 * when receiving Confirm from STA.
863 */
864 }
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800865 sta->sae->sync = 0;
866 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800867 } else {
868 hostapd_logger(hapd, sta->addr,
869 HOSTAPD_MODULE_IEEE80211,
870 HOSTAPD_LEVEL_DEBUG,
871 "SAE confirm before commit");
872 }
873 break;
874 case SAE_COMMITTED:
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800875 sae_clear_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800876 if (auth_transaction == 1) {
877 if (sae_process_commit(sta->sae) < 0)
878 return WLAN_STATUS_UNSPECIFIED_FAILURE;
879
880 ret = auth_sae_send_confirm(hapd, sta, bssid);
881 if (ret)
882 return ret;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700883 sae_set_state(sta, SAE_CONFIRMED, "Sent Confirm");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800884 sta->sae->sync = 0;
885 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800886 } else if (hapd->conf->mesh & MESH_ENABLED) {
887 /*
888 * In mesh case, follow SAE finite state machine and
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800889 * send Commit now, if sync count allows.
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800890 */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700891 if (sae_check_big_sync(hapd, sta))
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800892 return WLAN_STATUS_SUCCESS;
893 sta->sae->sync++;
894
Hai Shalomc3565922019-10-28 11:58:20 -0700895 ret = auth_sae_send_commit(hapd, sta, bssid, 0,
896 status_code);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800897 if (ret)
898 return ret;
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800899
900 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800901 } else {
902 /*
903 * For instructure BSS, send the postponed Confirm from
904 * Nothing -> Confirmed transition that was reduced to
905 * Nothing -> Committed above.
906 */
907 ret = auth_sae_send_confirm(hapd, sta, bssid);
908 if (ret)
909 return ret;
910
Roshan Pius3a1667e2018-07-03 15:17:14 -0700911 sae_set_state(sta, SAE_CONFIRMED, "Sent Confirm");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800912
913 /*
914 * Since this was triggered on Confirm RX, run another
915 * step to get to Accepted without waiting for
916 * additional events.
917 */
Hai Shalom021b0b52019-04-10 11:17:58 -0700918 return sae_sm_step(hapd, sta, bssid, auth_transaction,
Hai Shalomc3565922019-10-28 11:58:20 -0700919 WLAN_STATUS_SUCCESS, 0, sta_removed);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800920 }
921 break;
922 case SAE_CONFIRMED:
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800923 sae_clear_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800924 if (auth_transaction == 1) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700925 if (sae_check_big_sync(hapd, sta))
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800926 return WLAN_STATUS_SUCCESS;
927 sta->sae->sync++;
928
Hai Shalomc3565922019-10-28 11:58:20 -0700929 ret = auth_sae_send_commit(hapd, sta, bssid, 1,
930 status_code);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800931 if (ret)
932 return ret;
933
934 if (sae_process_commit(sta->sae) < 0)
935 return WLAN_STATUS_UNSPECIFIED_FAILURE;
936
937 ret = auth_sae_send_confirm(hapd, sta, bssid);
938 if (ret)
939 return ret;
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800940
941 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800942 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700943 sta->sae->send_confirm = 0xffff;
Dmitry Shmidte4663042016-04-04 10:07:49 -0700944 sae_accept_sta(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800945 }
946 break;
947 case SAE_ACCEPTED:
Roshan Pius3a1667e2018-07-03 15:17:14 -0700948 if (auth_transaction == 1 &&
949 (hapd->conf->mesh & MESH_ENABLED)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800950 wpa_printf(MSG_DEBUG, "SAE: remove the STA (" MACSTR
951 ") doing reauthentication",
952 MAC2STR(sta->addr));
Dmitry Shmidte4663042016-04-04 10:07:49 -0700953 wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
Hai Shalom5f92bc92019-04-18 11:54:11 -0700954 ap_free_sta(hapd, sta);
955 *sta_removed = 1;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700956 } else if (auth_transaction == 1) {
957 wpa_printf(MSG_DEBUG, "SAE: Start reauthentication");
Hai Shalomc3565922019-10-28 11:58:20 -0700958 ret = auth_sae_send_commit(hapd, sta, bssid, 1,
959 status_code);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700960 if (ret)
961 return ret;
962 sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
963
964 if (sae_process_commit(sta->sae) < 0)
965 return WLAN_STATUS_UNSPECIFIED_FAILURE;
966 sta->sae->sync = 0;
967 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800968 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700969 if (sae_check_big_sync(hapd, sta))
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800970 return WLAN_STATUS_SUCCESS;
971 sta->sae->sync++;
972
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800973 ret = auth_sae_send_confirm(hapd, sta, bssid);
974 sae_clear_temp_data(sta->sae);
975 if (ret)
976 return ret;
977 }
978 break;
979 default:
980 wpa_printf(MSG_ERROR, "SAE: invalid state %d",
981 sta->sae->state);
982 return WLAN_STATUS_UNSPECIFIED_FAILURE;
983 }
984 return WLAN_STATUS_SUCCESS;
985}
986
987
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700988static void sae_pick_next_group(struct hostapd_data *hapd, struct sta_info *sta)
989{
990 struct sae_data *sae = sta->sae;
991 int i, *groups = hapd->conf->sae_groups;
Hai Shalom021b0b52019-04-10 11:17:58 -0700992 int default_groups[] = { 19, 0 };
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700993
994 if (sae->state != SAE_COMMITTED)
995 return;
996
997 wpa_printf(MSG_DEBUG, "SAE: Previously selected group: %d", sae->group);
998
Hai Shalom021b0b52019-04-10 11:17:58 -0700999 if (!groups)
1000 groups = default_groups;
1001 for (i = 0; groups[i] > 0; i++) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07001002 if (sae->group == groups[i])
1003 break;
1004 }
1005
Hai Shalom021b0b52019-04-10 11:17:58 -07001006 if (groups[i] <= 0) {
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07001007 wpa_printf(MSG_DEBUG,
1008 "SAE: Previously selected group not found from the current configuration");
1009 return;
1010 }
1011
1012 for (;;) {
1013 i++;
1014 if (groups[i] <= 0) {
1015 wpa_printf(MSG_DEBUG,
1016 "SAE: No alternative group enabled");
1017 return;
1018 }
1019
1020 if (sae_set_group(sae, groups[i]) < 0)
1021 continue;
1022
1023 break;
1024 }
1025 wpa_printf(MSG_DEBUG, "SAE: Selected new group: %d", groups[i]);
1026}
1027
1028
Hai Shalomc3565922019-10-28 11:58:20 -07001029static int sae_status_success(struct hostapd_data *hapd, u16 status_code)
1030{
1031 return (hapd->conf->sae_pwe == 0 &&
1032 status_code == WLAN_STATUS_SUCCESS) ||
1033 (hapd->conf->sae_pwe == 1 &&
1034 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) ||
1035 (hapd->conf->sae_pwe == 2 &&
1036 (status_code == WLAN_STATUS_SUCCESS ||
1037 status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT));
1038}
1039
1040
1041static int sae_is_group_enabled(struct hostapd_data *hapd, int group)
1042{
1043 int *groups = hapd->conf->sae_groups;
1044 int default_groups[] = { 19, 0 };
1045 int i;
1046
1047 if (!groups)
1048 groups = default_groups;
1049
1050 for (i = 0; groups[i] > 0; i++) {
1051 if (groups[i] == group)
1052 return 1;
1053 }
1054
1055 return 0;
1056}
1057
1058
1059static int check_sae_rejected_groups(struct hostapd_data *hapd,
1060 const struct wpabuf *groups)
1061{
1062 size_t i, count;
1063 const u8 *pos;
1064
1065 if (!groups)
1066 return 0;
1067
1068 pos = wpabuf_head(groups);
1069 count = wpabuf_len(groups) / 2;
1070 for (i = 0; i < count; i++) {
1071 int enabled;
1072 u16 group;
1073
1074 group = WPA_GET_LE16(pos);
1075 pos += 2;
1076 enabled = sae_is_group_enabled(hapd, group);
1077 wpa_printf(MSG_DEBUG, "SAE: Rejected group %u is %s",
1078 group, enabled ? "enabled" : "disabled");
1079 if (enabled)
1080 return 1;
1081 }
1082
1083 return 0;
1084}
1085
1086
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001087static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
1088 const struct ieee80211_mgmt *mgmt, size_t len,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001089 u16 auth_transaction, u16 status_code)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001090{
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001091 int resp = WLAN_STATUS_SUCCESS;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001092 struct wpabuf *data = NULL;
Hai Shalom021b0b52019-04-10 11:17:58 -07001093 int *groups = hapd->conf->sae_groups;
1094 int default_groups[] = { 19, 0 };
1095 const u8 *pos, *end;
Hai Shalom5f92bc92019-04-18 11:54:11 -07001096 int sta_removed = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001097
1098 if (!groups)
1099 groups = default_groups;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001100
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001101#ifdef CONFIG_TESTING_OPTIONS
1102 if (hapd->conf->sae_reflection_attack && auth_transaction == 1) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001103 wpa_printf(MSG_DEBUG, "SAE: TESTING - reflection attack");
1104 pos = mgmt->u.auth.variable;
1105 end = ((const u8 *) mgmt) + len;
1106 send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001107 auth_transaction, resp, pos, end - pos,
1108 "auth-sae-reflection-attack");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001109 goto remove_sta;
1110 }
1111
1112 if (hapd->conf->sae_commit_override && auth_transaction == 1) {
1113 wpa_printf(MSG_DEBUG, "SAE: TESTING - commit override");
1114 send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
1115 auth_transaction, resp,
1116 wpabuf_head(hapd->conf->sae_commit_override),
Roshan Pius3a1667e2018-07-03 15:17:14 -07001117 wpabuf_len(hapd->conf->sae_commit_override),
1118 "sae-commit-override");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001119 goto remove_sta;
1120 }
1121#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001122 if (!sta->sae) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001123 if (auth_transaction != 1 ||
Hai Shalomc3565922019-10-28 11:58:20 -07001124 !sae_status_success(hapd, status_code)) {
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001125 wpa_printf(MSG_DEBUG, "SAE: Unexpected Status Code %u",
1126 status_code);
1127 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1128 goto reply;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001129 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001130 sta->sae = os_zalloc(sizeof(*sta->sae));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001131 if (!sta->sae) {
1132 resp = -1;
1133 goto remove_sta;
1134 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001135 sae_set_state(sta, SAE_NOTHING, "Init");
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001136 sta->sae->sync = 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001137 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001138
Dmitry Shmidte4663042016-04-04 10:07:49 -07001139 if (sta->mesh_sae_pmksa_caching) {
1140 wpa_printf(MSG_DEBUG,
1141 "SAE: Cancel use of mesh PMKSA caching because peer starts SAE authentication");
1142 wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
1143 sta->mesh_sae_pmksa_caching = 0;
1144 }
1145
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001146 if (auth_transaction == 1) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001147 const u8 *token = NULL;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001148 size_t token_len = 0;
Hai Shalom021b0b52019-04-10 11:17:58 -07001149 int allow_reuse = 0;
1150
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001151 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1152 HOSTAPD_LEVEL_DEBUG,
Hai Shalom81f62d82019-07-22 12:10:00 -07001153 "start SAE authentication (RX commit, status=%u (%s))",
1154 status_code, status2str(status_code));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001155
1156 if ((hapd->conf->mesh & MESH_ENABLED) &&
1157 status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
1158 sta->sae->tmp) {
1159 pos = mgmt->u.auth.variable;
1160 end = ((const u8 *) mgmt) + len;
1161 if (pos + sizeof(le16) > end) {
1162 wpa_printf(MSG_ERROR,
1163 "SAE: Too short anti-clogging token request");
1164 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1165 goto reply;
1166 }
Hai Shalom021b0b52019-04-10 11:17:58 -07001167 resp = sae_group_allowed(sta->sae, groups,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001168 WPA_GET_LE16(pos));
1169 if (resp != WLAN_STATUS_SUCCESS) {
1170 wpa_printf(MSG_ERROR,
1171 "SAE: Invalid group in anti-clogging token request");
1172 goto reply;
1173 }
1174 pos += sizeof(le16);
1175
1176 wpabuf_free(sta->sae->tmp->anti_clogging_token);
1177 sta->sae->tmp->anti_clogging_token =
1178 wpabuf_alloc_copy(pos, end - pos);
1179 if (sta->sae->tmp->anti_clogging_token == NULL) {
1180 wpa_printf(MSG_ERROR,
1181 "SAE: Failed to alloc for anti-clogging token");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001182 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1183 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001184 }
1185
1186 /*
1187 * IEEE Std 802.11-2012, 11.3.8.6.4: If the Status code
1188 * is 76, a new Commit Message shall be constructed
1189 * with the Anti-Clogging Token from the received
1190 * Authentication frame, and the commit-scalar and
1191 * COMMIT-ELEMENT previously sent.
1192 */
Hai Shalomc3565922019-10-28 11:58:20 -07001193 resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 0,
1194 status_code);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001195 if (resp != WLAN_STATUS_SUCCESS) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001196 wpa_printf(MSG_ERROR,
1197 "SAE: Failed to send commit message");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001198 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001199 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001200 sae_set_state(sta, SAE_COMMITTED,
1201 "Sent Commit (anti-clogging token case in mesh)");
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001202 sta->sae->sync = 0;
1203 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001204 return;
1205 }
1206
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -07001207 if ((hapd->conf->mesh & MESH_ENABLED) &&
1208 status_code ==
1209 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
1210 sta->sae->tmp) {
1211 wpa_printf(MSG_DEBUG,
1212 "SAE: Peer did not accept our SAE group");
1213 sae_pick_next_group(hapd, sta);
1214 goto remove_sta;
1215 }
1216
Hai Shalomc3565922019-10-28 11:58:20 -07001217 if (!sae_status_success(hapd, status_code))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001218 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001219
Roshan Pius3a1667e2018-07-03 15:17:14 -07001220 if (!(hapd->conf->mesh & MESH_ENABLED) &&
1221 sta->sae->state == SAE_COMMITTED) {
1222 /* This is needed in the infrastructure BSS case to
1223 * address a sequence where a STA entry may remain in
1224 * hostapd across two attempts to do SAE authentication
1225 * by the same STA. The second attempt may end up trying
1226 * to use a different group and that would not be
1227 * allowed if we remain in Committed state with the
1228 * previously set parameters. */
Hai Shalom021b0b52019-04-10 11:17:58 -07001229 pos = mgmt->u.auth.variable;
1230 end = ((const u8 *) mgmt) + len;
1231 if (end - pos >= (int) sizeof(le16) &&
1232 sae_group_allowed(sta->sae, groups,
1233 WPA_GET_LE16(pos)) ==
1234 WLAN_STATUS_SUCCESS) {
1235 /* Do not waste resources deriving the same PWE
1236 * again since the same group is reused. */
1237 sae_set_state(sta, SAE_NOTHING,
1238 "Allow previous PWE to be reused");
1239 allow_reuse = 1;
1240 } else {
1241 sae_set_state(sta, SAE_NOTHING,
1242 "Clear existing state to allow restart");
1243 sae_clear_data(sta->sae);
1244 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001245 }
1246
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001247 resp = sae_parse_commit(sta->sae, mgmt->u.auth.variable,
1248 ((const u8 *) mgmt) + len -
1249 mgmt->u.auth.variable, &token,
Hai Shalomc3565922019-10-28 11:58:20 -07001250 &token_len, groups, status_code ==
1251 WLAN_STATUS_SAE_HASH_TO_ELEMENT);
Dmitry Shmidt41712582015-06-29 11:02:15 -07001252 if (resp == SAE_SILENTLY_DISCARD) {
1253 wpa_printf(MSG_DEBUG,
1254 "SAE: Drop commit message from " MACSTR " due to reflection attack",
1255 MAC2STR(sta->addr));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001256 goto remove_sta;
Dmitry Shmidt41712582015-06-29 11:02:15 -07001257 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001258
1259 if (resp == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER) {
1260 wpa_msg(hapd->msg_ctx, MSG_INFO,
1261 WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER
1262 MACSTR, MAC2STR(sta->addr));
1263 sae_clear_retransmit_timer(hapd, sta);
1264 sae_set_state(sta, SAE_NOTHING,
1265 "Unknown Password Identifier");
1266 goto remove_sta;
1267 }
1268
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001269 if (token && check_sae_token(hapd, sta->addr, token, token_len)
1270 < 0) {
1271 wpa_printf(MSG_DEBUG, "SAE: Drop commit message with "
1272 "incorrect token from " MACSTR,
1273 MAC2STR(sta->addr));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001274 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1275 goto remove_sta;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001276 }
1277
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001278 if (resp != WLAN_STATUS_SUCCESS)
1279 goto reply;
1280
Hai Shalomc3565922019-10-28 11:58:20 -07001281 if (sta->sae->tmp &&
1282 check_sae_rejected_groups(
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001283 hapd, sta->sae->tmp->peer_rejected_groups)) {
Hai Shalomc3565922019-10-28 11:58:20 -07001284 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Ahmed ElArabawy0ff61c52019-12-26 12:38:39 -08001285 goto reply;
Hai Shalomc3565922019-10-28 11:58:20 -07001286 }
1287
Hai Shalom021b0b52019-04-10 11:17:58 -07001288 if (!token && use_sae_anti_clogging(hapd) && !allow_reuse) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001289 wpa_printf(MSG_DEBUG,
1290 "SAE: Request anti-clogging token from "
1291 MACSTR, MAC2STR(sta->addr));
1292 data = auth_build_token_req(hapd, sta->sae->group,
1293 sta->addr);
1294 resp = WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ;
1295 if (hapd->conf->mesh & MESH_ENABLED)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001296 sae_set_state(sta, SAE_NOTHING,
1297 "Request anti-clogging token case in mesh");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001298 goto reply;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001299 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001300
Hai Shalom021b0b52019-04-10 11:17:58 -07001301 resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction,
Hai Shalomc3565922019-10-28 11:58:20 -07001302 status_code, allow_reuse, &sta_removed);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001303 } else if (auth_transaction == 2) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001304 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1305 HOSTAPD_LEVEL_DEBUG,
Hai Shalom81f62d82019-07-22 12:10:00 -07001306 "SAE authentication (RX confirm, status=%u (%s))",
1307 status_code, status2str(status_code));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001308 if (status_code != WLAN_STATUS_SUCCESS)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001309 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001310 if (sta->sae->state >= SAE_CONFIRMED ||
1311 !(hapd->conf->mesh & MESH_ENABLED)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001312 const u8 *var;
1313 size_t var_len;
1314 u16 peer_send_confirm;
1315
1316 var = mgmt->u.auth.variable;
1317 var_len = ((u8 *) mgmt) + len - mgmt->u.auth.variable;
1318 if (var_len < 2) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001319 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001320 goto reply;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001321 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001322
1323 peer_send_confirm = WPA_GET_LE16(var);
1324
1325 if (sta->sae->state == SAE_ACCEPTED &&
1326 (peer_send_confirm <= sta->sae->rc ||
1327 peer_send_confirm == 0xffff)) {
1328 wpa_printf(MSG_DEBUG,
1329 "SAE: Silently ignore unexpected Confirm from peer "
1330 MACSTR
1331 " (peer-send-confirm=%u Rc=%u)",
1332 MAC2STR(sta->addr),
1333 peer_send_confirm, sta->sae->rc);
1334 return;
1335 }
1336
1337 if (sae_check_confirm(sta->sae, var, var_len) < 0) {
1338 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1339 goto reply;
1340 }
1341 sta->sae->rc = peer_send_confirm;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001342 }
Hai Shalomc3565922019-10-28 11:58:20 -07001343 resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction,
1344 status_code, 0, &sta_removed);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001345 } else {
1346 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1347 HOSTAPD_LEVEL_DEBUG,
Hai Shalom81f62d82019-07-22 12:10:00 -07001348 "unexpected SAE authentication transaction %u (status=%u (%s))",
1349 auth_transaction, status_code,
1350 status2str(status_code));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001351 if (status_code != WLAN_STATUS_SUCCESS)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001352 goto remove_sta;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001353 resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1354 }
1355
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001356reply:
Hai Shalom5f92bc92019-04-18 11:54:11 -07001357 if (!sta_removed && resp != WLAN_STATUS_SUCCESS) {
Hai Shalom021b0b52019-04-10 11:17:58 -07001358 pos = mgmt->u.auth.variable;
1359 end = ((const u8 *) mgmt) + len;
1360
1361 /* Copy the Finite Cyclic Group field from the request if we
1362 * rejected it as unsupported group. */
1363 if (resp == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
1364 !data && end - pos >= 2)
1365 data = wpabuf_alloc_copy(pos, 2);
1366
Hai Shalom5f92bc92019-04-18 11:54:11 -07001367 sae_sme_send_external_auth_status(hapd, sta, resp);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001368 send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
1369 auth_transaction, resp,
1370 data ? wpabuf_head(data) : (u8 *) "",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001371 data ? wpabuf_len(data) : 0, "auth-sae");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001372 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001373
1374remove_sta:
Hai Shalom5f92bc92019-04-18 11:54:11 -07001375 if (!sta_removed && sta->added_unassoc &&
1376 (resp != WLAN_STATUS_SUCCESS ||
1377 status_code != WLAN_STATUS_SUCCESS)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001378 hostapd_drv_sta_remove(hapd, sta->addr);
1379 sta->added_unassoc = 0;
1380 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001381 wpabuf_free(data);
1382}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001383
1384
1385/**
1386 * auth_sae_init_committed - Send COMMIT and start SAE in committed state
1387 * @hapd: BSS data for the device initiating the authentication
1388 * @sta: the peer to which commit authentication frame is sent
1389 *
1390 * This function implements Init event handling (IEEE Std 802.11-2012,
1391 * 11.3.8.6.3) in which initial COMMIT message is sent. Prior to calling, the
1392 * sta->sae structure should be initialized appropriately via a call to
1393 * sae_prepare_commit().
1394 */
1395int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta)
1396{
1397 int ret;
1398
1399 if (!sta->sae || !sta->sae->tmp)
1400 return -1;
1401
1402 if (sta->sae->state != SAE_NOTHING)
1403 return -1;
1404
Hai Shalomc3565922019-10-28 11:58:20 -07001405 ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0, -1);
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001406 if (ret)
1407 return -1;
1408
Roshan Pius3a1667e2018-07-03 15:17:14 -07001409 sae_set_state(sta, SAE_COMMITTED, "Init and sent commit");
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001410 sta->sae->sync = 0;
1411 sae_set_retransmit_timer(hapd, sta);
1412
1413 return 0;
1414}
1415
Hai Shalom021b0b52019-04-10 11:17:58 -07001416
1417void auth_sae_process_commit(void *eloop_ctx, void *user_ctx)
1418{
1419 struct hostapd_data *hapd = eloop_ctx;
1420 struct hostapd_sae_commit_queue *q;
1421 unsigned int queue_len;
1422
1423 q = dl_list_first(&hapd->sae_commit_queue,
1424 struct hostapd_sae_commit_queue, list);
1425 if (!q)
1426 return;
1427 wpa_printf(MSG_DEBUG,
1428 "SAE: Process next available message from queue");
1429 dl_list_del(&q->list);
1430 handle_auth(hapd, (const struct ieee80211_mgmt *) q->msg, q->len,
1431 q->rssi, 1);
1432 os_free(q);
1433
1434 if (eloop_is_timeout_registered(auth_sae_process_commit, hapd, NULL))
1435 return;
1436 queue_len = dl_list_len(&hapd->sae_commit_queue);
1437 eloop_register_timeout(0, queue_len * 10000, auth_sae_process_commit,
1438 hapd, NULL);
1439}
1440
1441
1442static void auth_sae_queue(struct hostapd_data *hapd,
1443 const struct ieee80211_mgmt *mgmt, size_t len,
1444 int rssi)
1445{
1446 struct hostapd_sae_commit_queue *q, *q2;
1447 unsigned int queue_len;
1448 const struct ieee80211_mgmt *mgmt2;
1449
1450 queue_len = dl_list_len(&hapd->sae_commit_queue);
1451 if (queue_len >= 15) {
1452 wpa_printf(MSG_DEBUG,
1453 "SAE: No more room in message queue - drop the new frame from "
1454 MACSTR, MAC2STR(mgmt->sa));
1455 return;
1456 }
1457
1458 wpa_printf(MSG_DEBUG, "SAE: Queue Authentication message from "
1459 MACSTR " for processing (queue_len %u)", MAC2STR(mgmt->sa),
1460 queue_len);
1461 q = os_zalloc(sizeof(*q) + len);
1462 if (!q)
1463 return;
1464 q->rssi = rssi;
1465 q->len = len;
1466 os_memcpy(q->msg, mgmt, len);
1467
1468 /* Check whether there is already a queued Authentication frame from the
1469 * same station with the same transaction number and if so, replace that
1470 * queue entry with the new one. This avoids issues with a peer that
1471 * sends multiple times (e.g., due to frequent SAE retries). There is no
1472 * point in us trying to process the old attempts after a new one has
1473 * obsoleted them. */
1474 dl_list_for_each(q2, &hapd->sae_commit_queue,
1475 struct hostapd_sae_commit_queue, list) {
1476 mgmt2 = (const struct ieee80211_mgmt *) q2->msg;
1477 if (os_memcmp(mgmt->sa, mgmt2->sa, ETH_ALEN) == 0 &&
1478 mgmt->u.auth.auth_transaction ==
1479 mgmt2->u.auth.auth_transaction) {
1480 wpa_printf(MSG_DEBUG,
1481 "SAE: Replace queued message from same STA with same transaction number");
1482 dl_list_add(&q2->list, &q->list);
1483 dl_list_del(&q2->list);
1484 os_free(q2);
1485 goto queued;
1486 }
1487 }
1488
1489 /* No pending identical entry, so add to the end of the queue */
1490 dl_list_add_tail(&hapd->sae_commit_queue, &q->list);
1491
1492queued:
1493 if (eloop_is_timeout_registered(auth_sae_process_commit, hapd, NULL))
1494 return;
1495 eloop_register_timeout(0, queue_len * 10000, auth_sae_process_commit,
1496 hapd, NULL);
1497}
1498
1499
1500static int auth_sae_queued_addr(struct hostapd_data *hapd, const u8 *addr)
1501{
1502 struct hostapd_sae_commit_queue *q;
1503 const struct ieee80211_mgmt *mgmt;
1504
1505 dl_list_for_each(q, &hapd->sae_commit_queue,
1506 struct hostapd_sae_commit_queue, list) {
1507 mgmt = (const struct ieee80211_mgmt *) q->msg;
1508 if (os_memcmp(addr, mgmt->sa, ETH_ALEN) == 0)
1509 return 1;
1510 }
1511
1512 return 0;
1513}
1514
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001515#endif /* CONFIG_SAE */
1516
1517
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001518static u16 wpa_res_to_status_code(int res)
1519{
1520 if (res == WPA_INVALID_GROUP)
1521 return WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1522 if (res == WPA_INVALID_PAIRWISE)
1523 return WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1524 if (res == WPA_INVALID_AKMP)
1525 return WLAN_STATUS_AKMP_NOT_VALID;
1526 if (res == WPA_ALLOC_FAIL)
1527 return WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001528 if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
1529 return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
1530 if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001531 return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001532 if (res == WPA_INVALID_MDIE)
1533 return WLAN_STATUS_INVALID_MDIE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001534 if (res == WPA_INVALID_PMKID)
1535 return WLAN_STATUS_INVALID_PMKID;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001536 if (res != WPA_IE_OK)
1537 return WLAN_STATUS_INVALID_IE;
1538 return WLAN_STATUS_SUCCESS;
1539}
1540
1541
1542#ifdef CONFIG_FILS
1543
1544static void handle_auth_fils_finish(struct hostapd_data *hapd,
1545 struct sta_info *sta, u16 resp,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001546 struct wpabuf *data, int pub);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001547
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001548void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
1549 const u8 *pos, size_t len, u16 auth_alg,
1550 u16 auth_transaction, u16 status_code,
1551 void (*cb)(struct hostapd_data *hapd,
1552 struct sta_info *sta, u16 resp,
1553 struct wpabuf *data, int pub))
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001554{
1555 u16 resp = WLAN_STATUS_SUCCESS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001556 const u8 *end;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001557 struct ieee802_11_elems elems;
1558 int res;
1559 struct wpa_ie_data rsn;
1560 struct rsn_pmksa_cache_entry *pmksa = NULL;
1561
1562 if (auth_transaction != 1 || status_code != WLAN_STATUS_SUCCESS)
1563 return;
1564
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001565 end = pos + len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001566
1567 wpa_hexdump(MSG_DEBUG, "FILS: Authentication frame fields",
1568 pos, end - pos);
1569
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001570 /* TODO: FILS PK */
1571#ifdef CONFIG_FILS_SK_PFS
1572 if (auth_alg == WLAN_AUTH_FILS_SK_PFS) {
1573 u16 group;
1574 struct wpabuf *pub;
1575 size_t elem_len;
1576
1577 /* Using FILS PFS */
1578
1579 /* Finite Cyclic Group */
1580 if (end - pos < 2) {
1581 wpa_printf(MSG_DEBUG,
1582 "FILS: No room for Finite Cyclic Group");
1583 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1584 goto fail;
1585 }
1586 group = WPA_GET_LE16(pos);
1587 pos += 2;
1588 if (group != hapd->conf->fils_dh_group) {
1589 wpa_printf(MSG_DEBUG,
1590 "FILS: Unsupported Finite Cyclic Group: %u (expected %u)",
1591 group, hapd->conf->fils_dh_group);
1592 resp = WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1593 goto fail;
1594 }
1595
1596 crypto_ecdh_deinit(sta->fils_ecdh);
1597 sta->fils_ecdh = crypto_ecdh_init(group);
1598 if (!sta->fils_ecdh) {
1599 wpa_printf(MSG_INFO,
1600 "FILS: Could not initialize ECDH with group %d",
1601 group);
1602 resp = WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1603 goto fail;
1604 }
1605
1606 pub = crypto_ecdh_get_pubkey(sta->fils_ecdh, 1);
1607 if (!pub) {
1608 wpa_printf(MSG_DEBUG,
1609 "FILS: Failed to derive ECDH public key");
1610 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1611 goto fail;
1612 }
1613 elem_len = wpabuf_len(pub);
1614 wpabuf_free(pub);
1615
1616 /* Element */
1617 if ((size_t) (end - pos) < elem_len) {
1618 wpa_printf(MSG_DEBUG, "FILS: No room for Element");
1619 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1620 goto fail;
1621 }
1622
1623 wpabuf_free(sta->fils_g_sta);
1624 sta->fils_g_sta = wpabuf_alloc_copy(pos, elem_len);
1625 wpabuf_clear_free(sta->fils_dh_ss);
1626 sta->fils_dh_ss = crypto_ecdh_set_peerkey(sta->fils_ecdh, 1,
1627 pos, elem_len);
1628 if (!sta->fils_dh_ss) {
1629 wpa_printf(MSG_DEBUG, "FILS: ECDH operation failed");
1630 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1631 goto fail;
1632 }
1633 wpa_hexdump_buf_key(MSG_DEBUG, "FILS: DH_SS", sta->fils_dh_ss);
1634 pos += elem_len;
1635 } else {
1636 crypto_ecdh_deinit(sta->fils_ecdh);
1637 sta->fils_ecdh = NULL;
1638 wpabuf_clear_free(sta->fils_dh_ss);
1639 sta->fils_dh_ss = NULL;
1640 }
1641#endif /* CONFIG_FILS_SK_PFS */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001642
1643 wpa_hexdump(MSG_DEBUG, "FILS: Remaining IEs", pos, end - pos);
1644 if (ieee802_11_parse_elems(pos, end - pos, &elems, 1) == ParseFailed) {
1645 wpa_printf(MSG_DEBUG, "FILS: Could not parse elements");
1646 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1647 goto fail;
1648 }
1649
1650 /* RSNE */
1651 wpa_hexdump(MSG_DEBUG, "FILS: RSN element",
1652 elems.rsn_ie, elems.rsn_ie_len);
1653 if (!elems.rsn_ie ||
1654 wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
1655 &rsn) < 0) {
1656 wpa_printf(MSG_DEBUG, "FILS: No valid RSN element");
1657 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1658 goto fail;
1659 }
1660
1661 if (!sta->wpa_sm)
1662 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr,
1663 NULL);
1664 if (!sta->wpa_sm) {
1665 wpa_printf(MSG_DEBUG,
1666 "FILS: Failed to initialize RSN state machine");
1667 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1668 goto fail;
1669 }
1670
1671 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
Hai Shalom021b0b52019-04-10 11:17:58 -07001672 hapd->iface->freq,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001673 elems.rsn_ie - 2, elems.rsn_ie_len + 2,
Hai Shalomc3565922019-10-28 11:58:20 -07001674 elems.rsnxe ? elems.rsnxe - 2 : NULL,
1675 elems.rsnxe ? elems.rsnxe_len + 2 : 0,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001676 elems.mdie, elems.mdie_len, NULL, 0);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001677 resp = wpa_res_to_status_code(res);
1678 if (resp != WLAN_STATUS_SUCCESS)
1679 goto fail;
1680
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001681 if (!elems.fils_nonce) {
1682 wpa_printf(MSG_DEBUG, "FILS: No FILS Nonce field");
1683 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1684 goto fail;
1685 }
1686 wpa_hexdump(MSG_DEBUG, "FILS: SNonce", elems.fils_nonce,
1687 FILS_NONCE_LEN);
1688 os_memcpy(sta->fils_snonce, elems.fils_nonce, FILS_NONCE_LEN);
1689
1690 /* PMKID List */
1691 if (rsn.pmkid && rsn.num_pmkid > 0) {
1692 u8 num;
1693 const u8 *pmkid;
1694
1695 wpa_hexdump(MSG_DEBUG, "FILS: PMKID List",
1696 rsn.pmkid, rsn.num_pmkid * PMKID_LEN);
1697
1698 pmkid = rsn.pmkid;
1699 num = rsn.num_pmkid;
1700 while (num) {
1701 wpa_hexdump(MSG_DEBUG, "FILS: PMKID", pmkid, PMKID_LEN);
1702 pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr,
1703 pmkid);
1704 if (pmksa)
1705 break;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001706 pmksa = wpa_auth_pmksa_get_fils_cache_id(hapd->wpa_auth,
1707 sta->addr,
1708 pmkid);
1709 if (pmksa)
1710 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001711 pmkid += PMKID_LEN;
1712 num--;
1713 }
1714 }
1715 if (pmksa && wpa_auth_sta_key_mgmt(sta->wpa_sm) != pmksa->akmp) {
1716 wpa_printf(MSG_DEBUG,
1717 "FILS: Matching PMKSA cache entry has different AKMP (0x%x != 0x%x) - ignore",
1718 wpa_auth_sta_key_mgmt(sta->wpa_sm), pmksa->akmp);
1719 pmksa = NULL;
1720 }
1721 if (pmksa)
1722 wpa_printf(MSG_DEBUG, "FILS: Found matching PMKSA cache entry");
1723
1724 /* FILS Session */
1725 if (!elems.fils_session) {
1726 wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
1727 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1728 goto fail;
1729 }
1730 wpa_hexdump(MSG_DEBUG, "FILS: FILS Session", elems.fils_session,
1731 FILS_SESSION_LEN);
1732 os_memcpy(sta->fils_session, elems.fils_session, FILS_SESSION_LEN);
1733
1734 /* FILS Wrapped Data */
1735 if (elems.fils_wrapped_data) {
1736 wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data",
1737 elems.fils_wrapped_data,
1738 elems.fils_wrapped_data_len);
1739 if (!pmksa) {
1740#ifndef CONFIG_NO_RADIUS
1741 if (!sta->eapol_sm) {
1742 sta->eapol_sm =
1743 ieee802_1x_alloc_eapol_sm(hapd, sta);
1744 }
1745 wpa_printf(MSG_DEBUG,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001746 "FILS: Forward EAP-Initiate/Re-auth to authentication server");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001747 ieee802_1x_encapsulate_radius(
1748 hapd, sta, elems.fils_wrapped_data,
1749 elems.fils_wrapped_data_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001750 sta->fils_pending_cb = cb;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001751 wpa_printf(MSG_DEBUG,
1752 "FILS: Will send Authentication frame once the response from authentication server is available");
1753 sta->flags |= WLAN_STA_PENDING_FILS_ERP;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001754 /* Calculate pending PMKID here so that we do not need
1755 * to maintain a copy of the EAP-Initiate/Reauth
1756 * message. */
1757 if (fils_pmkid_erp(wpa_auth_sta_key_mgmt(sta->wpa_sm),
1758 elems.fils_wrapped_data,
1759 elems.fils_wrapped_data_len,
1760 sta->fils_erp_pmkid) == 0)
1761 sta->fils_erp_pmkid_set = 1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001762 return;
1763#else /* CONFIG_NO_RADIUS */
1764 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1765 goto fail;
1766#endif /* CONFIG_NO_RADIUS */
1767 }
1768 }
1769
1770fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001771 if (cb) {
1772 struct wpabuf *data;
1773 int pub = 0;
1774
1775 data = prepare_auth_resp_fils(hapd, sta, &resp, pmksa, NULL,
1776 NULL, 0, &pub);
1777 if (!data) {
1778 wpa_printf(MSG_DEBUG,
1779 "%s: prepare_auth_resp_fils() returned failure",
1780 __func__);
1781 }
1782
1783 cb(hapd, sta, resp, data, pub);
1784 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001785}
1786
1787
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001788static struct wpabuf *
1789prepare_auth_resp_fils(struct hostapd_data *hapd,
1790 struct sta_info *sta, u16 *resp,
1791 struct rsn_pmksa_cache_entry *pmksa,
1792 struct wpabuf *erp_resp,
1793 const u8 *msk, size_t msk_len,
1794 int *is_pub)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001795{
1796 u8 fils_nonce[FILS_NONCE_LEN];
1797 size_t ielen;
1798 struct wpabuf *data = NULL;
1799 const u8 *ie;
1800 u8 *ie_buf = NULL;
1801 const u8 *pmk = NULL;
1802 size_t pmk_len = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08001803 u8 pmk_buf[PMK_LEN_MAX];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001804 struct wpabuf *pub = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001805
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001806 if (*resp != WLAN_STATUS_SUCCESS)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001807 goto fail;
1808
1809 ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen);
1810 if (!ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001811 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001812 goto fail;
1813 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001814
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001815 if (pmksa) {
1816 /* Add PMKID of the selected PMKSA into RSNE */
1817 ie_buf = os_malloc(ielen + 2 + 2 + PMKID_LEN);
1818 if (!ie_buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001819 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001820 goto fail;
1821 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001822
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001823 os_memcpy(ie_buf, ie, ielen);
1824 if (wpa_insert_pmkid(ie_buf, &ielen, pmksa->pmkid) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001825 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001826 goto fail;
1827 }
1828 ie = ie_buf;
1829 }
1830
1831 if (random_get_bytes(fils_nonce, FILS_NONCE_LEN) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001832 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001833 goto fail;
1834 }
1835 wpa_hexdump(MSG_DEBUG, "RSN: Generated FILS Nonce",
1836 fils_nonce, FILS_NONCE_LEN);
1837
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001838#ifdef CONFIG_FILS_SK_PFS
1839 if (sta->fils_dh_ss && sta->fils_ecdh) {
1840 pub = crypto_ecdh_get_pubkey(sta->fils_ecdh, 1);
1841 if (!pub) {
1842 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1843 goto fail;
1844 }
1845 }
1846#endif /* CONFIG_FILS_SK_PFS */
1847
1848 data = wpabuf_alloc(1000 + ielen + (pub ? wpabuf_len(pub) : 0));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001849 if (!data) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001850 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001851 goto fail;
1852 }
1853
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001854 /* TODO: FILS PK */
1855#ifdef CONFIG_FILS_SK_PFS
1856 if (pub) {
1857 /* Finite Cyclic Group */
1858 wpabuf_put_le16(data, hapd->conf->fils_dh_group);
1859
1860 /* Element */
1861 wpabuf_put_buf(data, pub);
1862 }
1863#endif /* CONFIG_FILS_SK_PFS */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001864
1865 /* RSNE */
1866 wpabuf_put_data(data, ie, ielen);
1867
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001868 /* MDE when using FILS+FT (already included in ie,ielen with RSNE) */
1869
1870#ifdef CONFIG_IEEE80211R_AP
1871 if (wpa_key_mgmt_ft(wpa_auth_sta_key_mgmt(sta->wpa_sm))) {
1872 /* FTE[R1KH-ID,R0KH-ID] when using FILS+FT */
1873 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001874 int use_sha384 = wpa_key_mgmt_sha384(
1875 wpa_auth_sta_key_mgmt(sta->wpa_sm));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001876
Roshan Pius3a1667e2018-07-03 15:17:14 -07001877 res = wpa_auth_write_fte(hapd->wpa_auth, use_sha384,
1878 wpabuf_put(data, 0),
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001879 wpabuf_tailroom(data));
1880 if (res < 0) {
1881 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1882 goto fail;
1883 }
1884 wpabuf_put(data, res);
1885 }
1886#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001887
1888 /* FILS Nonce */
1889 wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
1890 wpabuf_put_u8(data, 1 + FILS_NONCE_LEN); /* Length */
1891 /* Element ID Extension */
1892 wpabuf_put_u8(data, WLAN_EID_EXT_FILS_NONCE);
1893 wpabuf_put_data(data, fils_nonce, FILS_NONCE_LEN);
1894
1895 /* FILS Session */
1896 wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
1897 wpabuf_put_u8(data, 1 + FILS_SESSION_LEN); /* Length */
1898 /* Element ID Extension */
1899 wpabuf_put_u8(data, WLAN_EID_EXT_FILS_SESSION);
1900 wpabuf_put_data(data, sta->fils_session, FILS_SESSION_LEN);
1901
1902 /* FILS Wrapped Data */
1903 if (!pmksa && erp_resp) {
1904 wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
1905 wpabuf_put_u8(data, 1 + wpabuf_len(erp_resp)); /* Length */
1906 /* Element ID Extension */
1907 wpabuf_put_u8(data, WLAN_EID_EXT_FILS_WRAPPED_DATA);
1908 wpabuf_put_buf(data, erp_resp);
1909
Paul Stewart092955c2017-02-06 09:13:09 -08001910 if (fils_rmsk_to_pmk(wpa_auth_sta_key_mgmt(sta->wpa_sm),
1911 msk, msk_len, sta->fils_snonce, fils_nonce,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001912 sta->fils_dh_ss ?
1913 wpabuf_head(sta->fils_dh_ss) : NULL,
1914 sta->fils_dh_ss ?
1915 wpabuf_len(sta->fils_dh_ss) : 0,
1916 pmk_buf, &pmk_len)) {
Paul Stewart092955c2017-02-06 09:13:09 -08001917 wpa_printf(MSG_DEBUG, "FILS: Failed to derive PMK");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001918 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Paul Stewart092955c2017-02-06 09:13:09 -08001919 wpabuf_free(data);
1920 data = NULL;
1921 goto fail;
1922 }
1923 pmk = pmk_buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001924
1925 /* Don't use DHss in PTK derivation if PMKSA caching is not
1926 * used. */
1927 wpabuf_clear_free(sta->fils_dh_ss);
1928 sta->fils_dh_ss = NULL;
1929
1930 if (sta->fils_erp_pmkid_set) {
1931 /* TODO: get PMKLifetime from WPA parameters */
1932 unsigned int dot11RSNAConfigPMKLifetime = 43200;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001933 int session_timeout;
1934
1935 session_timeout = dot11RSNAConfigPMKLifetime;
1936 if (sta->session_timeout_set) {
1937 struct os_reltime now, diff;
1938
1939 os_get_reltime(&now);
1940 os_reltime_sub(&sta->session_timeout, &now,
1941 &diff);
1942 session_timeout = diff.sec;
1943 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001944
1945 sta->fils_erp_pmkid_set = 0;
Hai Shalom81f62d82019-07-22 12:10:00 -07001946 wpa_auth_add_fils_pmk_pmkid(sta->wpa_sm, pmk, pmk_len,
1947 sta->fils_erp_pmkid);
Hai Shalom021b0b52019-04-10 11:17:58 -07001948 if (!hapd->conf->disable_pmksa_caching &&
1949 wpa_auth_pmksa_add2(
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001950 hapd->wpa_auth, sta->addr,
1951 pmk, pmk_len,
1952 sta->fils_erp_pmkid,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001953 session_timeout,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001954 wpa_auth_sta_key_mgmt(sta->wpa_sm)) < 0) {
1955 wpa_printf(MSG_ERROR,
1956 "FILS: Failed to add PMKSA cache entry based on ERP");
1957 }
1958 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001959 } else if (pmksa) {
1960 pmk = pmksa->pmk;
1961 pmk_len = pmksa->pmk_len;
1962 }
1963
1964 if (!pmk) {
1965 wpa_printf(MSG_DEBUG, "FILS: No PMK available");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001966 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001967 wpabuf_free(data);
1968 data = NULL;
1969 goto fail;
1970 }
1971
1972 if (fils_auth_pmk_to_ptk(sta->wpa_sm, pmk, pmk_len,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001973 sta->fils_snonce, fils_nonce,
1974 sta->fils_dh_ss ?
1975 wpabuf_head(sta->fils_dh_ss) : NULL,
1976 sta->fils_dh_ss ?
1977 wpabuf_len(sta->fils_dh_ss) : 0,
1978 sta->fils_g_sta, pub) < 0) {
1979 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001980 wpabuf_free(data);
1981 data = NULL;
1982 goto fail;
1983 }
1984
1985fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001986 if (is_pub)
1987 *is_pub = pub != NULL;
1988 os_free(ie_buf);
1989 wpabuf_free(pub);
1990 wpabuf_clear_free(sta->fils_dh_ss);
1991 sta->fils_dh_ss = NULL;
1992#ifdef CONFIG_FILS_SK_PFS
1993 crypto_ecdh_deinit(sta->fils_ecdh);
1994 sta->fils_ecdh = NULL;
1995#endif /* CONFIG_FILS_SK_PFS */
1996 return data;
1997}
1998
1999
2000static void handle_auth_fils_finish(struct hostapd_data *hapd,
2001 struct sta_info *sta, u16 resp,
2002 struct wpabuf *data, int pub)
2003{
2004 u16 auth_alg;
2005
2006 auth_alg = (pub ||
2007 resp == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) ?
2008 WLAN_AUTH_FILS_SK_PFS : WLAN_AUTH_FILS_SK;
2009 send_auth_reply(hapd, sta->addr, hapd->own_addr, auth_alg, 2, resp,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002010 data ? wpabuf_head(data) : (u8 *) "",
Roshan Pius3a1667e2018-07-03 15:17:14 -07002011 data ? wpabuf_len(data) : 0, "auth-fils-finish");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002012 wpabuf_free(data);
2013
2014 if (resp == WLAN_STATUS_SUCCESS) {
2015 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2016 HOSTAPD_LEVEL_DEBUG,
2017 "authentication OK (FILS)");
2018 sta->flags |= WLAN_STA_AUTH;
2019 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002020 sta->auth_alg = pub ? WLAN_AUTH_FILS_SK_PFS : WLAN_AUTH_FILS_SK;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002021 mlme_authenticate_indication(hapd, sta);
2022 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002023}
2024
2025
2026void ieee802_11_finish_fils_auth(struct hostapd_data *hapd,
2027 struct sta_info *sta, int success,
2028 struct wpabuf *erp_resp,
2029 const u8 *msk, size_t msk_len)
2030{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002031 struct wpabuf *data;
2032 int pub = 0;
2033 u16 resp;
2034
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002035 sta->flags &= ~WLAN_STA_PENDING_FILS_ERP;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002036
2037 if (!sta->fils_pending_cb)
2038 return;
2039 resp = success ? WLAN_STATUS_SUCCESS : WLAN_STATUS_UNSPECIFIED_FAILURE;
2040 data = prepare_auth_resp_fils(hapd, sta, &resp, NULL, erp_resp,
2041 msk, msk_len, &pub);
2042 if (!data) {
2043 wpa_printf(MSG_DEBUG,
2044 "%s: prepare_auth_resp_fils() returned failure",
2045 __func__);
2046 }
2047 sta->fils_pending_cb(hapd, sta, resp, data, pub);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002048}
2049
2050#endif /* CONFIG_FILS */
2051
2052
Roshan Pius3a1667e2018-07-03 15:17:14 -07002053int
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002054ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
2055 const u8 *msg, size_t len, u32 *session_timeout,
2056 u32 *acct_interim_interval,
2057 struct vlan_description *vlan_id,
2058 struct hostapd_sta_wpa_psk_short **psk,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002059 char **identity, char **radius_cui, int is_probe_req)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002060{
2061 int res;
2062
2063 os_memset(vlan_id, 0, sizeof(*vlan_id));
2064 res = hostapd_allowed_address(hapd, addr, msg, len,
2065 session_timeout, acct_interim_interval,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002066 vlan_id, psk, identity, radius_cui,
2067 is_probe_req);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002068
2069 if (res == HOSTAPD_ACL_REJECT) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08002070 if (!is_probe_req)
2071 wpa_printf(MSG_DEBUG,
2072 "Station " MACSTR
2073 " not allowed to authenticate",
2074 MAC2STR(addr));
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002075 return HOSTAPD_ACL_REJECT;
2076 }
2077
2078 if (res == HOSTAPD_ACL_PENDING) {
2079 wpa_printf(MSG_DEBUG, "Authentication frame from " MACSTR
2080 " waiting for an external authentication",
2081 MAC2STR(addr));
2082 /* Authentication code will re-send the authentication frame
2083 * after it has received (and cached) information from the
2084 * external source. */
2085 return HOSTAPD_ACL_PENDING;
2086 }
2087
2088 return res;
2089}
2090
2091
2092static int
2093ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
2094 int res, u32 session_timeout,
2095 u32 acct_interim_interval,
2096 struct vlan_description *vlan_id,
2097 struct hostapd_sta_wpa_psk_short **psk,
2098 char **identity, char **radius_cui)
2099{
2100 if (vlan_id->notempty &&
2101 !hostapd_vlan_valid(hapd->conf->vlan, vlan_id)) {
2102 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
2103 HOSTAPD_LEVEL_INFO,
2104 "Invalid VLAN %d%s received from RADIUS server",
2105 vlan_id->untagged,
2106 vlan_id->tagged[0] ? "+" : "");
2107 return -1;
2108 }
2109 if (ap_sta_set_vlan(hapd, sta, vlan_id) < 0)
2110 return -1;
2111 if (sta->vlan_id)
2112 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
2113 HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
2114
2115 hostapd_free_psk_list(sta->psk);
2116 if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
2117 sta->psk = *psk;
2118 *psk = NULL;
2119 } else {
2120 sta->psk = NULL;
2121 }
2122
Roshan Pius3a1667e2018-07-03 15:17:14 -07002123 os_free(sta->identity);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002124 sta->identity = *identity;
2125 *identity = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002126
2127 os_free(sta->radius_cui);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002128 sta->radius_cui = *radius_cui;
2129 *radius_cui = NULL;
2130
2131 if (hapd->conf->acct_interim_interval == 0 && acct_interim_interval)
2132 sta->acct_interim_interval = acct_interim_interval;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002133 if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT) {
2134 sta->session_timeout_set = 1;
2135 os_get_reltime(&sta->session_timeout);
2136 sta->session_timeout.sec += session_timeout;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002137 ap_sta_session_timeout(hapd, sta, session_timeout);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002138 } else {
2139 sta->session_timeout_set = 0;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002140 ap_sta_no_session_timeout(hapd, sta);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002141 }
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002142
2143 return 0;
2144}
2145
2146
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002147static void handle_auth(struct hostapd_data *hapd,
Hai Shalom74f70d42019-02-11 14:42:39 -08002148 const struct ieee80211_mgmt *mgmt, size_t len,
Hai Shalom021b0b52019-04-10 11:17:58 -07002149 int rssi, int from_queue)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002150{
2151 u16 auth_alg, auth_transaction, status_code;
2152 u16 resp = WLAN_STATUS_SUCCESS;
2153 struct sta_info *sta = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002154 int res, reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002155 u16 fc;
2156 const u8 *challenge = NULL;
2157 u32 session_timeout, acct_interim_interval;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002158 struct vlan_description vlan_id;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002159 struct hostapd_sta_wpa_psk_short *psk = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002160 u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
2161 size_t resp_ies_len = 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002162 char *identity = NULL;
2163 char *radius_cui = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002164 u16 seq_ctrl;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002165
2166 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002167 wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
2168 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002169 return;
2170 }
2171
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002172#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07002173 if (hapd->iconf->ignore_auth_probability > 0.0 &&
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002174 drand48() < hapd->iconf->ignore_auth_probability) {
2175 wpa_printf(MSG_INFO,
2176 "TESTING: ignoring auth frame from " MACSTR,
2177 MAC2STR(mgmt->sa));
2178 return;
2179 }
2180#endif /* CONFIG_TESTING_OPTIONS */
2181
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002182 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
2183 auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
2184 status_code = le_to_host16(mgmt->u.auth.status_code);
2185 fc = le_to_host16(mgmt->frame_control);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002186 seq_ctrl = le_to_host16(mgmt->seq_ctrl);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002187
2188 if (len >= IEEE80211_HDRLEN + sizeof(mgmt->u.auth) +
2189 2 + WLAN_AUTH_CHALLENGE_LEN &&
2190 mgmt->u.auth.variable[0] == WLAN_EID_CHALLENGE &&
2191 mgmt->u.auth.variable[1] == WLAN_AUTH_CHALLENGE_LEN)
2192 challenge = &mgmt->u.auth.variable[2];
2193
2194 wpa_printf(MSG_DEBUG, "authentication: STA=" MACSTR " auth_alg=%d "
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002195 "auth_transaction=%d status_code=%d wep=%d%s "
Hai Shalom021b0b52019-04-10 11:17:58 -07002196 "seq_ctrl=0x%x%s%s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002197 MAC2STR(mgmt->sa), auth_alg, auth_transaction,
2198 status_code, !!(fc & WLAN_FC_ISWEP),
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002199 challenge ? " challenge" : "",
Hai Shalom021b0b52019-04-10 11:17:58 -07002200 seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "",
2201 from_queue ? " (from queue)" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002202
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002203#ifdef CONFIG_NO_RC4
2204 if (auth_alg == WLAN_AUTH_SHARED_KEY) {
2205 wpa_printf(MSG_INFO,
2206 "Unsupported authentication algorithm (%d)",
2207 auth_alg);
2208 resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
2209 goto fail;
2210 }
2211#endif /* CONFIG_NO_RC4 */
2212
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002213 if (hapd->tkip_countermeasures) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002214 wpa_printf(MSG_DEBUG,
2215 "Ongoing TKIP countermeasures (Michael MIC failure) - reject authentication");
2216 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002217 goto fail;
2218 }
2219
2220 if (!(((hapd->conf->auth_algs & WPA_AUTH_ALG_OPEN) &&
2221 auth_alg == WLAN_AUTH_OPEN) ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002222#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002223 (hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002224 auth_alg == WLAN_AUTH_FT) ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002225#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002226#ifdef CONFIG_SAE
2227 (hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
2228 auth_alg == WLAN_AUTH_SAE) ||
2229#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002230#ifdef CONFIG_FILS
2231 (hapd->conf->wpa && wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt) &&
2232 auth_alg == WLAN_AUTH_FILS_SK) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002233 (hapd->conf->wpa && wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt) &&
2234 hapd->conf->fils_dh_group &&
2235 auth_alg == WLAN_AUTH_FILS_SK_PFS) ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002236#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002237 ((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) &&
2238 auth_alg == WLAN_AUTH_SHARED_KEY))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002239 wpa_printf(MSG_INFO, "Unsupported authentication algorithm (%d)",
2240 auth_alg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002241 resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
2242 goto fail;
2243 }
2244
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002245 if (!(auth_transaction == 1 || auth_alg == WLAN_AUTH_SAE ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002246 (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002247 wpa_printf(MSG_INFO, "Unknown authentication transaction number (%d)",
2248 auth_transaction);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002249 resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
2250 goto fail;
2251 }
2252
2253 if (os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002254 wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to authenticate",
2255 MAC2STR(mgmt->sa));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002256 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
2257 goto fail;
2258 }
2259
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002260 if (hapd->conf->no_auth_if_seen_on) {
2261 struct hostapd_data *other;
2262
2263 other = sta_track_seen_on(hapd->iface, mgmt->sa,
2264 hapd->conf->no_auth_if_seen_on);
2265 if (other) {
2266 u8 *pos;
2267 u32 info;
2268 u8 op_class, channel, phytype;
2269
2270 wpa_printf(MSG_DEBUG, "%s: Reject authentication from "
2271 MACSTR " since STA has been seen on %s",
2272 hapd->conf->iface, MAC2STR(mgmt->sa),
2273 hapd->conf->no_auth_if_seen_on);
2274
2275 resp = WLAN_STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION;
2276 pos = &resp_ies[0];
2277 *pos++ = WLAN_EID_NEIGHBOR_REPORT;
2278 *pos++ = 13;
2279 os_memcpy(pos, other->own_addr, ETH_ALEN);
2280 pos += ETH_ALEN;
2281 info = 0; /* TODO: BSSID Information */
2282 WPA_PUT_LE32(pos, info);
2283 pos += 4;
2284 if (other->iconf->hw_mode == HOSTAPD_MODE_IEEE80211AD)
2285 phytype = 8; /* dmg */
2286 else if (other->iconf->ieee80211ac)
2287 phytype = 9; /* vht */
2288 else if (other->iconf->ieee80211n)
2289 phytype = 7; /* ht */
2290 else if (other->iconf->hw_mode ==
2291 HOSTAPD_MODE_IEEE80211A)
2292 phytype = 4; /* ofdm */
2293 else if (other->iconf->hw_mode ==
2294 HOSTAPD_MODE_IEEE80211G)
2295 phytype = 6; /* erp */
2296 else
2297 phytype = 5; /* hrdsss */
2298 if (ieee80211_freq_to_channel_ext(
2299 hostapd_hw_get_freq(other,
2300 other->iconf->channel),
2301 other->iconf->secondary_channel,
2302 other->iconf->ieee80211ac,
2303 &op_class, &channel) == NUM_HOSTAPD_MODES) {
2304 op_class = 0;
2305 channel = other->iconf->channel;
2306 }
2307 *pos++ = op_class;
2308 *pos++ = channel;
2309 *pos++ = phytype;
2310 resp_ies_len = pos - &resp_ies[0];
2311 goto fail;
2312 }
2313 }
2314
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002315 res = ieee802_11_allowed_address(
2316 hapd, mgmt->sa, (const u8 *) mgmt, len, &session_timeout,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002317 &acct_interim_interval, &vlan_id, &psk, &identity, &radius_cui,
2318 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002319 if (res == HOSTAPD_ACL_REJECT) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002320 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
2321 "Ignore Authentication frame from " MACSTR
2322 " due to ACL reject", MAC2STR(mgmt->sa));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002323 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
2324 goto fail;
2325 }
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002326 if (res == HOSTAPD_ACL_PENDING)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002327 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002328
Hai Shalom021b0b52019-04-10 11:17:58 -07002329#ifdef CONFIG_SAE
2330 if (auth_alg == WLAN_AUTH_SAE && !from_queue &&
2331 (auth_transaction == 1 ||
2332 (auth_transaction == 2 && auth_sae_queued_addr(hapd, mgmt->sa)))) {
2333 /* Handle SAE Authentication commit message through a queue to
2334 * provide more control for postponing the needed heavy
2335 * processing under a possible DoS attack scenario. In addition,
2336 * queue SAE Authentication confirm message if there happens to
2337 * be a queued commit message from the same peer. This is needed
2338 * to avoid reordering Authentication frames within the same
2339 * SAE exchange. */
2340 auth_sae_queue(hapd, mgmt, len, rssi);
2341 return;
2342 }
2343#endif /* CONFIG_SAE */
2344
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002345 sta = ap_get_sta(hapd, mgmt->sa);
2346 if (sta) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002347 sta->flags &= ~WLAN_STA_PENDING_FILS_ERP;
Hai Shalom74f70d42019-02-11 14:42:39 -08002348 sta->ft_over_ds = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002349 if ((fc & WLAN_FC_RETRY) &&
2350 sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ &&
2351 sta->last_seq_ctrl == seq_ctrl &&
2352 sta->last_subtype == WLAN_FC_STYPE_AUTH) {
2353 hostapd_logger(hapd, sta->addr,
2354 HOSTAPD_MODULE_IEEE80211,
2355 HOSTAPD_LEVEL_DEBUG,
2356 "Drop repeated authentication frame seq_ctrl=0x%x",
2357 seq_ctrl);
2358 return;
2359 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002360#ifdef CONFIG_MESH
2361 if ((hapd->conf->mesh & MESH_ENABLED) &&
2362 sta->plink_state == PLINK_BLOCKED) {
2363 wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
2364 " is blocked - drop Authentication frame",
2365 MAC2STR(mgmt->sa));
2366 return;
2367 }
2368#endif /* CONFIG_MESH */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002369 } else {
2370#ifdef CONFIG_MESH
2371 if (hapd->conf->mesh & MESH_ENABLED) {
2372 /* if the mesh peer is not available, we don't do auth.
2373 */
2374 wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002375 " not yet known - drop Authentication frame",
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002376 MAC2STR(mgmt->sa));
2377 /*
2378 * Save a copy of the frame so that it can be processed
2379 * if a new peer entry is added shortly after this.
2380 */
2381 wpabuf_free(hapd->mesh_pending_auth);
2382 hapd->mesh_pending_auth = wpabuf_alloc_copy(mgmt, len);
2383 os_get_reltime(&hapd->mesh_pending_auth_time);
2384 return;
2385 }
2386#endif /* CONFIG_MESH */
2387
2388 sta = ap_sta_add(hapd, mgmt->sa);
2389 if (!sta) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002390 wpa_printf(MSG_DEBUG, "ap_sta_add() failed");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002391 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
2392 goto fail;
2393 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002394 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002395 sta->last_seq_ctrl = seq_ctrl;
2396 sta->last_subtype = WLAN_FC_STYPE_AUTH;
Hai Shalom74f70d42019-02-11 14:42:39 -08002397#ifdef CONFIG_MBO
2398 sta->auth_rssi = rssi;
2399#endif /* CONFIG_MBO */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002400
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002401 res = ieee802_11_set_radius_info(
2402 hapd, sta, res, session_timeout, acct_interim_interval,
2403 &vlan_id, &psk, &identity, &radius_cui);
2404 if (res) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07002405 wpa_printf(MSG_DEBUG, "ieee802_11_set_radius_info() failed");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002406 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
2407 goto fail;
2408 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002409
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002410 sta->flags &= ~WLAN_STA_PREAUTH;
2411 ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
2412
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002413 /*
2414 * If the driver supports full AP client state, add a station to the
2415 * driver before sending authentication reply to make sure the driver
2416 * has resources, and not to go through the entire authentication and
2417 * association handshake, and fail it at the end.
2418 *
2419 * If this is not the first transaction, in a multi-step authentication
2420 * algorithm, the station already exists in the driver
2421 * (sta->added_unassoc = 1) so skip it.
2422 *
2423 * In mesh mode, the station was already added to the driver when the
2424 * NEW_PEER_CANDIDATE event is received.
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08002425 *
2426 * If PMF was negotiated for the existing association, skip this to
2427 * avoid dropping the STA entry and the associated keys. This is needed
2428 * to allow the original connection work until the attempt can complete
2429 * (re)association, so that unprotected Authentication frame cannot be
2430 * used to bypass PMF protection.
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002431 */
2432 if (FULL_AP_CLIENT_STATE_SUPP(hapd->iface->drv_flags) &&
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08002433 (!(sta->flags & WLAN_STA_MFP) || !ap_sta_is_authorized(sta)) &&
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002434 !(hapd->conf->mesh & MESH_ENABLED) &&
2435 !(sta->added_unassoc)) {
2436 /*
2437 * If a station that is already associated to the AP, is trying
2438 * to authenticate again, remove the STA entry, in order to make
2439 * sure the STA PS state gets cleared and configuration gets
2440 * updated. To handle this, station's added_unassoc flag is
2441 * cleared once the station has completed association.
2442 */
Hai Shalomce48b4a2018-09-05 11:41:35 -07002443 ap_sta_set_authorized(hapd, sta, 0);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002444 hostapd_drv_sta_remove(hapd, sta->addr);
2445 sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_AUTH |
2446 WLAN_STA_AUTHORIZED);
2447
Hai Shalom81f62d82019-07-22 12:10:00 -07002448 if (hostapd_sta_add(hapd, sta->addr, 0, 0,
2449 sta->supported_rates,
2450 sta->supported_rates_len,
2451 0, NULL, NULL, NULL, 0,
2452 sta->flags, 0, 0, 0, 0)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002453 hostapd_logger(hapd, sta->addr,
2454 HOSTAPD_MODULE_IEEE80211,
2455 HOSTAPD_LEVEL_NOTICE,
2456 "Could not add STA to kernel driver");
2457 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
2458 goto fail;
2459 }
2460
2461 sta->added_unassoc = 1;
2462 }
2463
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002464 switch (auth_alg) {
2465 case WLAN_AUTH_OPEN:
2466 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2467 HOSTAPD_LEVEL_DEBUG,
2468 "authentication OK (open system)");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002469 sta->flags |= WLAN_STA_AUTH;
2470 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
2471 sta->auth_alg = WLAN_AUTH_OPEN;
2472 mlme_authenticate_indication(hapd, sta);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002473 break;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002474#ifndef CONFIG_NO_RC4
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002475 case WLAN_AUTH_SHARED_KEY:
2476 resp = auth_shared_key(hapd, sta, auth_transaction, challenge,
2477 fc & WLAN_FC_ISWEP);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002478 if (resp != 0)
2479 wpa_printf(MSG_DEBUG,
2480 "auth_shared_key() failed: status=%d", resp);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002481 sta->auth_alg = WLAN_AUTH_SHARED_KEY;
2482 mlme_authenticate_indication(hapd, sta);
2483 if (sta->challenge && auth_transaction == 1) {
2484 resp_ies[0] = WLAN_EID_CHALLENGE;
2485 resp_ies[1] = WLAN_AUTH_CHALLENGE_LEN;
2486 os_memcpy(resp_ies + 2, sta->challenge,
2487 WLAN_AUTH_CHALLENGE_LEN);
2488 resp_ies_len = 2 + WLAN_AUTH_CHALLENGE_LEN;
2489 }
2490 break;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002491#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002492#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002493 case WLAN_AUTH_FT:
2494 sta->auth_alg = WLAN_AUTH_FT;
2495 if (sta->wpa_sm == NULL)
2496 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002497 sta->addr, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002498 if (sta->wpa_sm == NULL) {
2499 wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA "
2500 "state machine");
2501 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
2502 goto fail;
2503 }
2504 wpa_ft_process_auth(sta->wpa_sm, mgmt->bssid,
2505 auth_transaction, mgmt->u.auth.variable,
2506 len - IEEE80211_HDRLEN -
2507 sizeof(mgmt->u.auth),
2508 handle_auth_ft_finish, hapd);
2509 /* handle_auth_ft_finish() callback will complete auth. */
2510 return;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002511#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002512#ifdef CONFIG_SAE
2513 case WLAN_AUTH_SAE:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002514#ifdef CONFIG_MESH
2515 if (status_code == WLAN_STATUS_SUCCESS &&
2516 hapd->conf->mesh & MESH_ENABLED) {
2517 if (sta->wpa_sm == NULL)
2518 sta->wpa_sm =
2519 wpa_auth_sta_init(hapd->wpa_auth,
2520 sta->addr, NULL);
2521 if (sta->wpa_sm == NULL) {
2522 wpa_printf(MSG_DEBUG,
2523 "SAE: Failed to initialize WPA state machine");
2524 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
2525 goto fail;
2526 }
2527 }
2528#endif /* CONFIG_MESH */
2529 handle_auth_sae(hapd, sta, mgmt, len, auth_transaction,
2530 status_code);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002531 return;
2532#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002533#ifdef CONFIG_FILS
2534 case WLAN_AUTH_FILS_SK:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002535 case WLAN_AUTH_FILS_SK_PFS:
2536 handle_auth_fils(hapd, sta, mgmt->u.auth.variable,
2537 len - IEEE80211_HDRLEN - sizeof(mgmt->u.auth),
2538 auth_alg, auth_transaction, status_code,
2539 handle_auth_fils_finish);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002540 return;
2541#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002542 }
2543
2544 fail:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002545 os_free(identity);
2546 os_free(radius_cui);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002547 hostapd_free_psk_list(psk);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002548
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002549 reply_res = send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
2550 auth_transaction + 1, resp, resp_ies,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002551 resp_ies_len, "handle-auth");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002552
2553 if (sta && sta->added_unassoc && (resp != WLAN_STATUS_SUCCESS ||
2554 reply_res != WLAN_STATUS_SUCCESS)) {
2555 hostapd_drv_sta_remove(hapd, sta->addr);
2556 sta->added_unassoc = 0;
2557 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002558}
2559
2560
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002561int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002562{
2563 int i, j = 32, aid;
2564
2565 /* get a unique AID */
2566 if (sta->aid > 0) {
2567 wpa_printf(MSG_DEBUG, " old AID %d", sta->aid);
2568 return 0;
2569 }
2570
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002571 if (TEST_FAIL())
2572 return -1;
2573
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002574 for (i = 0; i < AID_WORDS; i++) {
2575 if (hapd->sta_aid[i] == (u32) -1)
2576 continue;
2577 for (j = 0; j < 32; j++) {
2578 if (!(hapd->sta_aid[i] & BIT(j)))
2579 break;
2580 }
2581 if (j < 32)
2582 break;
2583 }
2584 if (j == 32)
2585 return -1;
2586 aid = i * 32 + j + 1;
2587 if (aid > 2007)
2588 return -1;
2589
2590 sta->aid = aid;
2591 hapd->sta_aid[i] |= BIT(j);
2592 wpa_printf(MSG_DEBUG, " new AID %d", sta->aid);
2593 return 0;
2594}
2595
2596
2597static u16 check_ssid(struct hostapd_data *hapd, struct sta_info *sta,
2598 const u8 *ssid_ie, size_t ssid_ie_len)
2599{
2600 if (ssid_ie == NULL)
2601 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2602
2603 if (ssid_ie_len != hapd->conf->ssid.ssid_len ||
2604 os_memcmp(ssid_ie, hapd->conf->ssid.ssid, ssid_ie_len) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002605 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2606 HOSTAPD_LEVEL_INFO,
2607 "Station tried to associate with unknown SSID "
Dmitry Shmidt3c479372014-02-04 10:50:36 -08002608 "'%s'", wpa_ssid_txt(ssid_ie, ssid_ie_len));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002609 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2610 }
2611
2612 return WLAN_STATUS_SUCCESS;
2613}
2614
2615
2616static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta,
2617 const u8 *wmm_ie, size_t wmm_ie_len)
2618{
2619 sta->flags &= ~WLAN_STA_WMM;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002620 sta->qosinfo = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002621 if (wmm_ie && hapd->conf->wmm_enabled) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002622 struct wmm_information_element *wmm;
2623
2624 if (!hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002625 hostapd_logger(hapd, sta->addr,
2626 HOSTAPD_MODULE_WPA,
2627 HOSTAPD_LEVEL_DEBUG,
2628 "invalid WMM element in association "
2629 "request");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002630 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2631 }
2632
2633 sta->flags |= WLAN_STA_WMM;
2634 wmm = (struct wmm_information_element *) wmm_ie;
2635 sta->qosinfo = wmm->qos_info;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002636 }
2637 return WLAN_STATUS_SUCCESS;
2638}
2639
Hai Shalom74f70d42019-02-11 14:42:39 -08002640static u16 check_multi_ap(struct hostapd_data *hapd, struct sta_info *sta,
2641 const u8 *multi_ap_ie, size_t multi_ap_len)
2642{
2643 u8 multi_ap_value = 0;
2644
2645 sta->flags &= ~WLAN_STA_MULTI_AP;
2646
2647 if (!hapd->conf->multi_ap)
2648 return WLAN_STATUS_SUCCESS;
2649
2650 if (multi_ap_ie) {
2651 const u8 *multi_ap_subelem;
2652
2653 multi_ap_subelem = get_ie(multi_ap_ie + 4,
2654 multi_ap_len - 4,
2655 MULTI_AP_SUB_ELEM_TYPE);
2656 if (multi_ap_subelem && multi_ap_subelem[1] == 1) {
2657 multi_ap_value = multi_ap_subelem[2];
2658 } else {
2659 hostapd_logger(hapd, sta->addr,
2660 HOSTAPD_MODULE_IEEE80211,
2661 HOSTAPD_LEVEL_INFO,
2662 "Multi-AP IE has missing or invalid Multi-AP subelement");
2663 return WLAN_STATUS_INVALID_IE;
2664 }
2665 }
2666
Hai Shalom021b0b52019-04-10 11:17:58 -07002667 if (multi_ap_value && multi_ap_value != MULTI_AP_BACKHAUL_STA)
2668 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2669 HOSTAPD_LEVEL_INFO,
2670 "Multi-AP IE with unexpected value 0x%02x",
2671 multi_ap_value);
Hai Shalom74f70d42019-02-11 14:42:39 -08002672
Hai Shalom021b0b52019-04-10 11:17:58 -07002673 if (!(multi_ap_value & MULTI_AP_BACKHAUL_STA)) {
2674 if (hapd->conf->multi_ap & FRONTHAUL_BSS)
2675 return WLAN_STATUS_SUCCESS;
Hai Shalom74f70d42019-02-11 14:42:39 -08002676
Hai Shalom021b0b52019-04-10 11:17:58 -07002677 hostapd_logger(hapd, sta->addr,
2678 HOSTAPD_MODULE_IEEE80211,
2679 HOSTAPD_LEVEL_INFO,
2680 "Non-Multi-AP STA tries to associate with backhaul-only BSS");
2681 return WLAN_STATUS_ASSOC_DENIED_UNSPEC;
Hai Shalom74f70d42019-02-11 14:42:39 -08002682 }
2683
Hai Shalom021b0b52019-04-10 11:17:58 -07002684 if (!(hapd->conf->multi_ap & BACKHAUL_BSS))
2685 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2686 HOSTAPD_LEVEL_DEBUG,
2687 "Backhaul STA tries to associate with fronthaul-only BSS");
2688
2689 sta->flags |= WLAN_STA_MULTI_AP;
2690 return WLAN_STATUS_SUCCESS;
Hai Shalom74f70d42019-02-11 14:42:39 -08002691}
2692
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002693
2694static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
2695 struct ieee802_11_elems *elems)
2696{
Dmitry Shmidt29333592017-01-09 12:27:11 -08002697 /* Supported rates not used in IEEE 802.11ad/DMG */
2698 if (hapd->iface->current_mode &&
2699 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD)
2700 return WLAN_STATUS_SUCCESS;
2701
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002702 if (!elems->supp_rates) {
2703 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2704 HOSTAPD_LEVEL_DEBUG,
2705 "No supported rates element in AssocReq");
2706 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2707 }
2708
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002709 if (elems->supp_rates_len + elems->ext_supp_rates_len >
2710 sizeof(sta->supported_rates)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002711 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2712 HOSTAPD_LEVEL_DEBUG,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002713 "Invalid supported rates element length %d+%d",
2714 elems->supp_rates_len,
2715 elems->ext_supp_rates_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002716 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2717 }
2718
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002719 sta->supported_rates_len = merge_byte_arrays(
2720 sta->supported_rates, sizeof(sta->supported_rates),
2721 elems->supp_rates, elems->supp_rates_len,
2722 elems->ext_supp_rates, elems->ext_supp_rates_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002723
2724 return WLAN_STATUS_SUCCESS;
2725}
2726
2727
Dmitry Shmidt051af732013-10-22 13:52:46 -07002728static u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
2729 const u8 *ext_capab_ie, size_t ext_capab_ie_len)
2730{
2731#ifdef CONFIG_INTERWORKING
2732 /* check for QoS Map support */
2733 if (ext_capab_ie_len >= 5) {
2734 if (ext_capab_ie[4] & 0x01)
2735 sta->qos_map_enabled = 1;
2736 }
2737#endif /* CONFIG_INTERWORKING */
2738
Roshan Pius3a1667e2018-07-03 15:17:14 -07002739 if (ext_capab_ie_len > 0) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002740 sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2));
Roshan Pius3a1667e2018-07-03 15:17:14 -07002741 os_free(sta->ext_capability);
2742 sta->ext_capability = os_malloc(1 + ext_capab_ie_len);
2743 if (sta->ext_capability) {
2744 sta->ext_capability[0] = ext_capab_ie_len;
2745 os_memcpy(sta->ext_capability + 1, ext_capab_ie,
2746 ext_capab_ie_len);
2747 }
2748 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002749
Dmitry Shmidt051af732013-10-22 13:52:46 -07002750 return WLAN_STATUS_SUCCESS;
2751}
2752
2753
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002754#ifdef CONFIG_OWE
2755
2756static int owe_group_supported(struct hostapd_data *hapd, u16 group)
2757{
2758 int i;
2759 int *groups = hapd->conf->owe_groups;
2760
2761 if (group != 19 && group != 20 && group != 21)
2762 return 0;
2763
2764 if (!groups)
2765 return 1;
2766
2767 for (i = 0; groups[i] > 0; i++) {
2768 if (groups[i] == group)
2769 return 1;
2770 }
2771
2772 return 0;
2773}
2774
2775
2776static u16 owe_process_assoc_req(struct hostapd_data *hapd,
2777 struct sta_info *sta, const u8 *owe_dh,
2778 u8 owe_dh_len)
2779{
2780 struct wpabuf *secret, *pub, *hkey;
2781 int res;
2782 u8 prk[SHA512_MAC_LEN], pmkid[SHA512_MAC_LEN];
2783 const char *info = "OWE Key Generation";
2784 const u8 *addr[2];
2785 size_t len[2];
2786 u16 group;
2787 size_t hash_len, prime_len;
2788
2789 if (wpa_auth_sta_get_pmksa(sta->wpa_sm)) {
2790 wpa_printf(MSG_DEBUG, "OWE: Using PMKSA caching");
2791 return WLAN_STATUS_SUCCESS;
2792 }
2793
2794 group = WPA_GET_LE16(owe_dh);
2795 if (!owe_group_supported(hapd, group)) {
2796 wpa_printf(MSG_DEBUG, "OWE: Unsupported DH group %u", group);
2797 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
2798 }
2799 if (group == 19)
2800 prime_len = 32;
2801 else if (group == 20)
2802 prime_len = 48;
2803 else if (group == 21)
2804 prime_len = 66;
2805 else
2806 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
2807
2808 crypto_ecdh_deinit(sta->owe_ecdh);
2809 sta->owe_ecdh = crypto_ecdh_init(group);
2810 if (!sta->owe_ecdh)
2811 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
2812 sta->owe_group = group;
2813
2814 secret = crypto_ecdh_set_peerkey(sta->owe_ecdh, 0, owe_dh + 2,
2815 owe_dh_len - 2);
2816 secret = wpabuf_zeropad(secret, prime_len);
2817 if (!secret) {
2818 wpa_printf(MSG_DEBUG, "OWE: Invalid peer DH public key");
2819 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2820 }
2821 wpa_hexdump_buf_key(MSG_DEBUG, "OWE: DH shared secret", secret);
2822
2823 /* prk = HKDF-extract(C | A | group, z) */
2824
2825 pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
2826 if (!pub) {
2827 wpabuf_clear_free(secret);
2828 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2829 }
2830
2831 /* PMKID = Truncate-128(Hash(C | A)) */
2832 addr[0] = owe_dh + 2;
2833 len[0] = owe_dh_len - 2;
2834 addr[1] = wpabuf_head(pub);
2835 len[1] = wpabuf_len(pub);
2836 if (group == 19) {
2837 res = sha256_vector(2, addr, len, pmkid);
2838 hash_len = SHA256_MAC_LEN;
2839 } else if (group == 20) {
2840 res = sha384_vector(2, addr, len, pmkid);
2841 hash_len = SHA384_MAC_LEN;
2842 } else if (group == 21) {
2843 res = sha512_vector(2, addr, len, pmkid);
2844 hash_len = SHA512_MAC_LEN;
2845 } else {
2846 wpabuf_free(pub);
2847 wpabuf_clear_free(secret);
2848 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2849 }
2850 pub = wpabuf_zeropad(pub, prime_len);
2851 if (res < 0 || !pub) {
2852 wpabuf_free(pub);
2853 wpabuf_clear_free(secret);
2854 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2855 }
2856
2857 hkey = wpabuf_alloc(owe_dh_len - 2 + wpabuf_len(pub) + 2);
2858 if (!hkey) {
2859 wpabuf_free(pub);
2860 wpabuf_clear_free(secret);
2861 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2862 }
2863
2864 wpabuf_put_data(hkey, owe_dh + 2, owe_dh_len - 2); /* C */
2865 wpabuf_put_buf(hkey, pub); /* A */
2866 wpabuf_free(pub);
2867 wpabuf_put_le16(hkey, group); /* group */
2868 if (group == 19)
2869 res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey),
2870 wpabuf_head(secret), wpabuf_len(secret), prk);
2871 else if (group == 20)
2872 res = hmac_sha384(wpabuf_head(hkey), wpabuf_len(hkey),
2873 wpabuf_head(secret), wpabuf_len(secret), prk);
2874 else if (group == 21)
2875 res = hmac_sha512(wpabuf_head(hkey), wpabuf_len(hkey),
2876 wpabuf_head(secret), wpabuf_len(secret), prk);
2877 wpabuf_clear_free(hkey);
2878 wpabuf_clear_free(secret);
2879 if (res < 0)
2880 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2881
2882 wpa_hexdump_key(MSG_DEBUG, "OWE: prk", prk, hash_len);
2883
2884 /* PMK = HKDF-expand(prk, "OWE Key Generation", n) */
2885
2886 os_free(sta->owe_pmk);
2887 sta->owe_pmk = os_malloc(hash_len);
2888 if (!sta->owe_pmk) {
2889 os_memset(prk, 0, SHA512_MAC_LEN);
2890 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2891 }
2892
2893 if (group == 19)
2894 res = hmac_sha256_kdf(prk, hash_len, NULL, (const u8 *) info,
2895 os_strlen(info), sta->owe_pmk, hash_len);
2896 else if (group == 20)
2897 res = hmac_sha384_kdf(prk, hash_len, NULL, (const u8 *) info,
2898 os_strlen(info), sta->owe_pmk, hash_len);
2899 else if (group == 21)
2900 res = hmac_sha512_kdf(prk, hash_len, NULL, (const u8 *) info,
2901 os_strlen(info), sta->owe_pmk, hash_len);
2902 os_memset(prk, 0, SHA512_MAC_LEN);
2903 if (res < 0) {
2904 os_free(sta->owe_pmk);
2905 sta->owe_pmk = NULL;
2906 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2907 }
2908 sta->owe_pmk_len = hash_len;
2909
2910 wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sta->owe_pmk, sta->owe_pmk_len);
2911 wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, PMKID_LEN);
2912 wpa_auth_pmksa_add2(hapd->wpa_auth, sta->addr, sta->owe_pmk,
2913 sta->owe_pmk_len, pmkid, 0, WPA_KEY_MGMT_OWE);
2914
2915 return WLAN_STATUS_SUCCESS;
2916}
2917
Hai Shalom81f62d82019-07-22 12:10:00 -07002918
2919u16 owe_validate_request(struct hostapd_data *hapd, const u8 *peer,
2920 const u8 *rsn_ie, size_t rsn_ie_len,
2921 const u8 *owe_dh, size_t owe_dh_len)
2922{
2923 struct wpa_ie_data data;
2924 int res;
2925
2926 if (!rsn_ie || rsn_ie_len < 2) {
2927 wpa_printf(MSG_DEBUG, "OWE: Invalid RSNE from " MACSTR,
2928 MAC2STR(peer));
2929 return WLAN_STATUS_INVALID_IE;
2930 }
2931 rsn_ie -= 2;
2932 rsn_ie_len += 2;
2933
2934 res = wpa_parse_wpa_ie_rsn(rsn_ie, rsn_ie_len, &data);
2935 if (res) {
2936 wpa_printf(MSG_DEBUG, "Failed to parse RSNE from " MACSTR
2937 " (res=%d)", MAC2STR(peer), res);
2938 wpa_hexdump(MSG_DEBUG, "RSNE", rsn_ie, rsn_ie_len);
2939 return wpa_res_to_status_code(res);
2940 }
2941 if (!(data.key_mgmt & WPA_KEY_MGMT_OWE)) {
2942 wpa_printf(MSG_DEBUG,
2943 "OWE: Unexpected key mgmt 0x%x from " MACSTR,
2944 (unsigned int) data.key_mgmt, MAC2STR(peer));
2945 return WLAN_STATUS_AKMP_NOT_VALID;
2946 }
2947 if (!owe_dh) {
2948 wpa_printf(MSG_DEBUG,
2949 "OWE: No Diffie-Hellman Parameter element from "
2950 MACSTR, MAC2STR(peer));
2951 return WLAN_STATUS_AKMP_NOT_VALID;
2952 }
2953
2954 return WLAN_STATUS_SUCCESS;
2955}
2956
2957
2958u16 owe_process_rsn_ie(struct hostapd_data *hapd,
2959 struct sta_info *sta,
2960 const u8 *rsn_ie, size_t rsn_ie_len,
2961 const u8 *owe_dh, size_t owe_dh_len)
2962{
2963 u16 status;
2964 u8 *owe_buf, ie[256 * 2];
2965 size_t ie_len = 0;
2966 int res;
2967
2968 if (!rsn_ie || rsn_ie_len < 2) {
2969 wpa_printf(MSG_DEBUG, "OWE: No RSNE in (Re)AssocReq");
2970 status = WLAN_STATUS_INVALID_IE;
2971 goto end;
2972 }
2973
2974 if (!sta->wpa_sm)
2975 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr,
2976 NULL);
2977 if (!sta->wpa_sm) {
2978 wpa_printf(MSG_WARNING,
2979 "OWE: Failed to initialize WPA state machine");
2980 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
2981 goto end;
2982 }
2983 rsn_ie -= 2;
2984 rsn_ie_len += 2;
2985 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
2986 hapd->iface->freq, rsn_ie, rsn_ie_len,
Hai Shalomc3565922019-10-28 11:58:20 -07002987 NULL, 0, NULL, 0, owe_dh, owe_dh_len);
Hai Shalom81f62d82019-07-22 12:10:00 -07002988 status = wpa_res_to_status_code(res);
2989 if (status != WLAN_STATUS_SUCCESS)
2990 goto end;
2991 status = owe_process_assoc_req(hapd, sta, owe_dh, owe_dh_len);
2992 if (status != WLAN_STATUS_SUCCESS)
2993 goto end;
2994 owe_buf = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, ie, sizeof(ie),
2995 NULL, 0);
2996 if (!owe_buf) {
2997 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
2998 goto end;
2999 }
3000
3001 if (sta->owe_ecdh) {
3002 struct wpabuf *pub;
3003
3004 pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
3005 if (!pub) {
3006 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
3007 goto end;
3008 }
3009
3010 /* OWE Diffie-Hellman Parameter element */
3011 *owe_buf++ = WLAN_EID_EXTENSION; /* Element ID */
3012 *owe_buf++ = 1 + 2 + wpabuf_len(pub); /* Length */
3013 *owe_buf++ = WLAN_EID_EXT_OWE_DH_PARAM; /* Element ID Extension
3014 */
3015 WPA_PUT_LE16(owe_buf, sta->owe_group);
3016 owe_buf += 2;
3017 os_memcpy(owe_buf, wpabuf_head(pub), wpabuf_len(pub));
3018 owe_buf += wpabuf_len(pub);
3019 wpabuf_free(pub);
3020 sta->external_dh_updated = 1;
3021 }
3022 ie_len = owe_buf - ie;
3023
3024end:
3025 wpa_printf(MSG_DEBUG, "OWE: Update status %d, ie len %d for peer "
3026 MACSTR, status, (unsigned int) ie_len,
3027 MAC2STR(sta->addr));
3028 hostapd_drv_update_dh_ie(hapd, sta->addr, status,
3029 status == WLAN_STATUS_SUCCESS ? ie : NULL,
3030 ie_len);
3031
3032 return status;
3033}
3034
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003035#endif /* CONFIG_OWE */
3036
3037
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003038static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
3039 const u8 *ies, size_t ies_len, int reassoc)
3040{
3041 struct ieee802_11_elems elems;
3042 u16 resp;
3043 const u8 *wpa_ie;
3044 size_t wpa_ie_len;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003045 const u8 *p2p_dev_addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003046
3047 if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
3048 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3049 HOSTAPD_LEVEL_INFO, "Station sent an invalid "
3050 "association request");
3051 return WLAN_STATUS_UNSPECIFIED_FAILURE;
3052 }
3053
3054 resp = check_ssid(hapd, sta, elems.ssid, elems.ssid_len);
3055 if (resp != WLAN_STATUS_SUCCESS)
3056 return resp;
3057 resp = check_wmm(hapd, sta, elems.wmm, elems.wmm_len);
3058 if (resp != WLAN_STATUS_SUCCESS)
3059 return resp;
Dmitry Shmidt051af732013-10-22 13:52:46 -07003060 resp = check_ext_capab(hapd, sta, elems.ext_capab, elems.ext_capab_len);
3061 if (resp != WLAN_STATUS_SUCCESS)
3062 return resp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003063 resp = copy_supp_rates(hapd, sta, &elems);
3064 if (resp != WLAN_STATUS_SUCCESS)
3065 return resp;
Hai Shalom74f70d42019-02-11 14:42:39 -08003066
3067 resp = check_multi_ap(hapd, sta, elems.multi_ap, elems.multi_ap_len);
3068 if (resp != WLAN_STATUS_SUCCESS)
3069 return resp;
3070
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003071#ifdef CONFIG_IEEE80211N
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003072 resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003073 if (resp != WLAN_STATUS_SUCCESS)
3074 return resp;
3075 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
3076 !(sta->flags & WLAN_STA_HT)) {
3077 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3078 HOSTAPD_LEVEL_INFO, "Station does not support "
3079 "mandatory HT PHY - reject association");
3080 return WLAN_STATUS_ASSOC_DENIED_NO_HT;
3081 }
3082#endif /* CONFIG_IEEE80211N */
3083
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003084#ifdef CONFIG_IEEE80211AC
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003085 if (hapd->iconf->ieee80211ac) {
3086 resp = copy_sta_vht_capab(hapd, sta, elems.vht_capabilities);
3087 if (resp != WLAN_STATUS_SUCCESS)
3088 return resp;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003089
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003090 resp = set_sta_vht_opmode(hapd, sta, elems.vht_opmode_notif);
3091 if (resp != WLAN_STATUS_SUCCESS)
3092 return resp;
3093 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08003094
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003095 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht &&
3096 !(sta->flags & WLAN_STA_VHT)) {
3097 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3098 HOSTAPD_LEVEL_INFO, "Station does not support "
3099 "mandatory VHT PHY - reject association");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003100 return WLAN_STATUS_ASSOC_DENIED_NO_VHT;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003101 }
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003102
3103 if (hapd->conf->vendor_vht && !elems.vht_capabilities) {
3104 resp = copy_sta_vendor_vht(hapd, sta, elems.vendor_vht,
3105 elems.vendor_vht_len);
3106 if (resp != WLAN_STATUS_SUCCESS)
3107 return resp;
3108 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003109#endif /* CONFIG_IEEE80211AC */
Hai Shalom81f62d82019-07-22 12:10:00 -07003110#ifdef CONFIG_IEEE80211AX
3111 if (hapd->iconf->ieee80211ax) {
3112 resp = copy_sta_he_capab(hapd, sta, IEEE80211_MODE_AP,
3113 elems.he_capabilities,
3114 elems.he_capabilities_len);
3115 if (resp != WLAN_STATUS_SUCCESS)
3116 return resp;
3117 }
3118#endif /* CONFIG_IEEE80211AX */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003119
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003120#ifdef CONFIG_P2P
3121 if (elems.p2p) {
3122 wpabuf_free(sta->p2p_ie);
3123 sta->p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
3124 P2P_IE_VENDOR_TYPE);
3125 if (sta->p2p_ie)
3126 p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie);
3127 } else {
3128 wpabuf_free(sta->p2p_ie);
3129 sta->p2p_ie = NULL;
3130 }
3131#endif /* CONFIG_P2P */
3132
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003133 if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) {
3134 wpa_ie = elems.rsn_ie;
3135 wpa_ie_len = elems.rsn_ie_len;
3136 } else if ((hapd->conf->wpa & WPA_PROTO_WPA) &&
3137 elems.wpa_ie) {
3138 wpa_ie = elems.wpa_ie;
3139 wpa_ie_len = elems.wpa_ie_len;
3140 } else {
3141 wpa_ie = NULL;
3142 wpa_ie_len = 0;
3143 }
3144
3145#ifdef CONFIG_WPS
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003146 sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003147 if (hapd->conf->wps_state && elems.wps_ie) {
3148 wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association "
3149 "Request - assume WPS is used");
3150 sta->flags |= WLAN_STA_WPS;
3151 wpabuf_free(sta->wps_ie);
3152 sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
3153 WPS_IE_VENDOR_TYPE);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003154 if (sta->wps_ie && wps_is_20(sta->wps_ie)) {
3155 wpa_printf(MSG_DEBUG, "WPS: STA supports WPS 2.0");
3156 sta->flags |= WLAN_STA_WPS2;
3157 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003158 wpa_ie = NULL;
3159 wpa_ie_len = 0;
3160 if (sta->wps_ie && wps_validate_assoc_req(sta->wps_ie) < 0) {
3161 wpa_printf(MSG_DEBUG, "WPS: Invalid WPS IE in "
3162 "(Re)Association Request - reject");
3163 return WLAN_STATUS_INVALID_IE;
3164 }
3165 } else if (hapd->conf->wps_state && wpa_ie == NULL) {
3166 wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE in "
3167 "(Re)Association Request - possible WPS use");
3168 sta->flags |= WLAN_STA_MAYBE_WPS;
3169 } else
3170#endif /* CONFIG_WPS */
3171 if (hapd->conf->wpa && wpa_ie == NULL) {
3172 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3173 HOSTAPD_LEVEL_INFO,
3174 "No WPA/RSN IE in association request");
3175 return WLAN_STATUS_INVALID_IE;
3176 }
3177
3178 if (hapd->conf->wpa && wpa_ie) {
3179 int res;
3180 wpa_ie -= 2;
3181 wpa_ie_len += 2;
3182 if (sta->wpa_sm == NULL)
3183 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003184 sta->addr,
3185 p2p_dev_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003186 if (sta->wpa_sm == NULL) {
3187 wpa_printf(MSG_WARNING, "Failed to initialize WPA "
3188 "state machine");
3189 return WLAN_STATUS_UNSPECIFIED_FAILURE;
3190 }
Hai Shalom021b0b52019-04-10 11:17:58 -07003191 wpa_auth_set_auth_alg(sta->wpa_sm, sta->auth_alg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003192 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
Hai Shalom021b0b52019-04-10 11:17:58 -07003193 hapd->iface->freq,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003194 wpa_ie, wpa_ie_len,
Hai Shalomc3565922019-10-28 11:58:20 -07003195 elems.rsnxe ? elems.rsnxe - 2 : NULL,
3196 elems.rsnxe ? elems.rsnxe_len + 2 : 0,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003197 elems.mdie, elems.mdie_len,
3198 elems.owe_dh, elems.owe_dh_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003199 resp = wpa_res_to_status_code(res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003200 if (resp != WLAN_STATUS_SUCCESS)
3201 return resp;
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003202 if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
3203 (WLAN_STA_ASSOC | WLAN_STA_MFP) &&
3204 !sta->sa_query_timed_out &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003205 sta->sa_query_count > 0)
3206 ap_check_sa_query_timeout(hapd, sta);
Hai Shalom39ba6fc2019-01-22 12:40:38 -08003207 if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
3208 (WLAN_STA_ASSOC | WLAN_STA_MFP) &&
3209 !sta->sa_query_timed_out &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003210 (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) {
3211 /*
3212 * STA has already been associated with MFP and SA
3213 * Query timeout has not been reached. Reject the
3214 * association attempt temporarily and start SA Query,
3215 * if one is not pending.
3216 */
3217
3218 if (sta->sa_query_count == 0)
3219 ap_sta_start_sa_query(hapd, sta);
3220
3221 return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
3222 }
3223
3224 if (wpa_auth_uses_mfp(sta->wpa_sm))
3225 sta->flags |= WLAN_STA_MFP;
3226 else
3227 sta->flags &= ~WLAN_STA_MFP;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003228
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003229#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003230 if (sta->auth_alg == WLAN_AUTH_FT) {
3231 if (!reassoc) {
3232 wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried "
3233 "to use association (not "
3234 "re-association) with FT auth_alg",
3235 MAC2STR(sta->addr));
3236 return WLAN_STATUS_UNSPECIFIED_FAILURE;
3237 }
3238
3239 resp = wpa_ft_validate_reassoc(sta->wpa_sm, ies,
3240 ies_len);
3241 if (resp != WLAN_STATUS_SUCCESS)
3242 return resp;
3243 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003244#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003245
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003246#ifdef CONFIG_SAE
Roshan Pius3a1667e2018-07-03 15:17:14 -07003247 if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae &&
3248 sta->sae->state == SAE_ACCEPTED)
3249 wpa_auth_add_sae_pmkid(sta->wpa_sm, sta->sae->pmkid);
3250
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003251 if (wpa_auth_uses_sae(sta->wpa_sm) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003252 sta->auth_alg == WLAN_AUTH_OPEN) {
3253 struct rsn_pmksa_cache_entry *sa;
3254 sa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
3255 if (!sa || sa->akmp != WPA_KEY_MGMT_SAE) {
3256 wpa_printf(MSG_DEBUG,
3257 "SAE: No PMKSA cache entry found for "
3258 MACSTR, MAC2STR(sta->addr));
3259 return WLAN_STATUS_INVALID_PMKID;
3260 }
3261 wpa_printf(MSG_DEBUG, "SAE: " MACSTR
3262 " using PMKSA caching", MAC2STR(sta->addr));
3263 } else if (wpa_auth_uses_sae(sta->wpa_sm) &&
3264 sta->auth_alg != WLAN_AUTH_SAE &&
3265 !(sta->auth_alg == WLAN_AUTH_FT &&
3266 wpa_auth_uses_ft_sae(sta->wpa_sm))) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003267 wpa_printf(MSG_DEBUG, "SAE: " MACSTR " tried to use "
3268 "SAE AKM after non-SAE auth_alg %u",
3269 MAC2STR(sta->addr), sta->auth_alg);
3270 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
3271 }
Hai Shalomc3565922019-10-28 11:58:20 -07003272
3273 if (hapd->conf->sae_pwe == 2 &&
3274 sta->auth_alg == WLAN_AUTH_SAE &&
3275 sta->sae && sta->sae->tmp && !sta->sae->tmp->h2e &&
3276 elems.rsnxe && elems.rsnxe_len >= 1 &&
3277 (elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) {
3278 wpa_printf(MSG_INFO, "SAE: " MACSTR
3279 " indicates support for SAE H2E, but did not use it",
3280 MAC2STR(sta->addr));
3281 return WLAN_STATUS_UNSPECIFIED_FAILURE;
3282 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003283#endif /* CONFIG_SAE */
3284
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003285#ifdef CONFIG_OWE
3286 if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
3287 wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE &&
3288 elems.owe_dh) {
3289 resp = owe_process_assoc_req(hapd, sta, elems.owe_dh,
3290 elems.owe_dh_len);
3291 if (resp != WLAN_STATUS_SUCCESS)
3292 return resp;
3293 }
3294#endif /* CONFIG_OWE */
3295
Hai Shalom021b0b52019-04-10 11:17:58 -07003296#ifdef CONFIG_DPP2
3297 dpp_pfs_free(sta->dpp_pfs);
3298 sta->dpp_pfs = NULL;
3299
3300 if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) &&
3301 hapd->conf->dpp_netaccesskey && sta->wpa_sm &&
3302 wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP &&
3303 elems.owe_dh) {
3304 sta->dpp_pfs = dpp_pfs_init(
3305 wpabuf_head(hapd->conf->dpp_netaccesskey),
3306 wpabuf_len(hapd->conf->dpp_netaccesskey));
3307 if (!sta->dpp_pfs) {
3308 wpa_printf(MSG_DEBUG,
3309 "DPP: Could not initialize PFS");
3310 /* Try to continue without PFS */
3311 goto pfs_fail;
3312 }
3313
3314 if (dpp_pfs_process(sta->dpp_pfs, elems.owe_dh,
3315 elems.owe_dh_len) < 0) {
3316 dpp_pfs_free(sta->dpp_pfs);
3317 sta->dpp_pfs = NULL;
3318 return WLAN_STATUS_UNSPECIFIED_FAILURE;
3319 }
3320 }
3321
3322 wpa_auth_set_dpp_z(sta->wpa_sm, sta->dpp_pfs ?
3323 sta->dpp_pfs->secret : NULL);
3324 pfs_fail:
3325#endif /* CONFIG_DPP2 */
3326
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003327#ifdef CONFIG_IEEE80211N
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003328 if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003329 wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
3330 hostapd_logger(hapd, sta->addr,
3331 HOSTAPD_MODULE_IEEE80211,
3332 HOSTAPD_LEVEL_INFO,
3333 "Station tried to use TKIP with HT "
3334 "association");
3335 return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
3336 }
3337#endif /* CONFIG_IEEE80211N */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003338#ifdef CONFIG_HS20
3339 } else if (hapd->conf->osen) {
3340 if (elems.osen == NULL) {
3341 hostapd_logger(
3342 hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3343 HOSTAPD_LEVEL_INFO,
3344 "No HS 2.0 OSEN element in association request");
3345 return WLAN_STATUS_INVALID_IE;
3346 }
3347
3348 wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association");
3349 if (sta->wpa_sm == NULL)
3350 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
3351 sta->addr, NULL);
3352 if (sta->wpa_sm == NULL) {
3353 wpa_printf(MSG_WARNING, "Failed to initialize WPA "
3354 "state machine");
3355 return WLAN_STATUS_UNSPECIFIED_FAILURE;
3356 }
3357 if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm,
3358 elems.osen - 2, elems.osen_len + 2) < 0)
3359 return WLAN_STATUS_INVALID_IE;
3360#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003361 } else
3362 wpa_auth_sta_no_wpa(sta->wpa_sm);
3363
3364#ifdef CONFIG_P2P
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003365 p2p_group_notif_assoc(hapd->p2p_group, sta->addr, ies, ies_len);
3366#endif /* CONFIG_P2P */
3367
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003368#ifdef CONFIG_HS20
3369 wpabuf_free(sta->hs20_ie);
3370 if (elems.hs20 && elems.hs20_len > 4) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003371 int release;
3372
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003373 sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
3374 elems.hs20_len - 4);
Hai Shalom74f70d42019-02-11 14:42:39 -08003375 release = ((elems.hs20[4] >> 4) & 0x0f) + 1;
Hai Shalomc3565922019-10-28 11:58:20 -07003376 if (release >= 2 && !wpa_auth_uses_mfp(sta->wpa_sm) &&
3377 hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
Hai Shalom74f70d42019-02-11 14:42:39 -08003378 wpa_printf(MSG_DEBUG,
3379 "HS 2.0: PMF not negotiated by release %d station "
3380 MACSTR, release, MAC2STR(sta->addr));
3381 return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
3382 }
3383 } else {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003384 sta->hs20_ie = NULL;
Hai Shalom74f70d42019-02-11 14:42:39 -08003385 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07003386
3387 wpabuf_free(sta->roaming_consortium);
3388 if (elems.roaming_cons_sel)
3389 sta->roaming_consortium = wpabuf_alloc_copy(
3390 elems.roaming_cons_sel + 4,
3391 elems.roaming_cons_sel_len - 4);
3392 else
3393 sta->roaming_consortium = NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08003394#endif /* CONFIG_HS20 */
3395
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003396#ifdef CONFIG_FST
3397 wpabuf_free(sta->mb_ies);
3398 if (hapd->iface->fst)
3399 sta->mb_ies = mb_ies_by_info(&elems.mb_ies);
3400 else
3401 sta->mb_ies = NULL;
3402#endif /* CONFIG_FST */
3403
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003404#ifdef CONFIG_MBO
3405 mbo_ap_check_sta_assoc(hapd, sta, &elems);
3406
3407 if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) &&
3408 elems.mbo && sta->cell_capa && !(sta->flags & WLAN_STA_MFP) &&
3409 hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
3410 wpa_printf(MSG_INFO,
3411 "MBO: Reject WPA2 association without PMF");
3412 return WLAN_STATUS_UNSPECIFIED_FAILURE;
3413 }
3414#endif /* CONFIG_MBO */
3415
Hai Shalom74f70d42019-02-11 14:42:39 -08003416#if defined(CONFIG_FILS) && defined(CONFIG_OCV)
3417 if (wpa_auth_uses_ocv(sta->wpa_sm) &&
3418 (sta->auth_alg == WLAN_AUTH_FILS_SK ||
3419 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
3420 sta->auth_alg == WLAN_AUTH_FILS_PK)) {
3421 struct wpa_channel_info ci;
3422 int tx_chanwidth;
3423 int tx_seg1_idx;
3424
3425 if (hostapd_drv_channel_info(hapd, &ci) != 0) {
3426 wpa_printf(MSG_WARNING,
3427 "Failed to get channel info to validate received OCI in FILS (Re)Association Request frame");
3428 return WLAN_STATUS_UNSPECIFIED_FAILURE;
3429 }
3430
3431 if (get_sta_tx_parameters(sta->wpa_sm,
3432 channel_width_to_int(ci.chanwidth),
3433 ci.seg1_idx, &tx_chanwidth,
3434 &tx_seg1_idx) < 0)
3435 return WLAN_STATUS_UNSPECIFIED_FAILURE;
3436
3437 if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci,
3438 tx_chanwidth, tx_seg1_idx) != 0) {
3439 wpa_printf(MSG_WARNING, "FILS: %s", ocv_errorstr);
3440 return WLAN_STATUS_UNSPECIFIED_FAILURE;
3441 }
3442 }
3443#endif /* CONFIG_FILS && CONFIG_OCV */
3444
Dmitry Shmidt9c175262016-03-03 10:20:07 -08003445 ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes,
3446 elems.supp_op_classes_len);
3447
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003448 if ((sta->capability & WLAN_CAPABILITY_RADIO_MEASUREMENT) &&
3449 elems.rrm_enabled &&
3450 elems.rrm_enabled_len >= sizeof(sta->rrm_enabled_capa))
3451 os_memcpy(sta->rrm_enabled_capa, elems.rrm_enabled,
3452 sizeof(sta->rrm_enabled_capa));
3453
Roshan Pius3a1667e2018-07-03 15:17:14 -07003454 if (elems.power_capab) {
3455 sta->min_tx_power = elems.power_capab[0];
3456 sta->max_tx_power = elems.power_capab[1];
3457 sta->power_capab = 1;
3458 } else {
3459 sta->power_capab = 0;
3460 }
3461
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003462 return WLAN_STATUS_SUCCESS;
3463}
3464
3465
3466static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
3467 u16 reason_code)
3468{
3469 int send_len;
3470 struct ieee80211_mgmt reply;
3471
3472 os_memset(&reply, 0, sizeof(reply));
3473 reply.frame_control =
3474 IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DEAUTH);
3475 os_memcpy(reply.da, addr, ETH_ALEN);
3476 os_memcpy(reply.sa, hapd->own_addr, ETH_ALEN);
3477 os_memcpy(reply.bssid, hapd->own_addr, ETH_ALEN);
3478
3479 send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth);
3480 reply.u.deauth.reason_code = host_to_le16(reason_code);
3481
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003482 if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003483 wpa_printf(MSG_INFO, "Failed to send deauth: %s",
3484 strerror(errno));
3485}
3486
3487
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003488static int add_associated_sta(struct hostapd_data *hapd,
Hai Shalom74f70d42019-02-11 14:42:39 -08003489 struct sta_info *sta, int reassoc)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003490{
3491 struct ieee80211_ht_capabilities ht_cap;
3492 struct ieee80211_vht_capabilities vht_cap;
Hai Shalom81f62d82019-07-22 12:10:00 -07003493 struct ieee80211_he_capabilities he_cap;
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02003494 int set = 1;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003495
3496 /*
3497 * Remove the STA entry to ensure the STA PS state gets cleared and
3498 * configuration gets updated. This is relevant for cases, such as
3499 * FT-over-the-DS, where a station re-associates back to the same AP but
3500 * skips the authentication flow, or if working with a driver that
3501 * does not support full AP client state.
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02003502 *
3503 * Skip this if the STA has already completed FT reassociation and the
3504 * TK has been configured since the TX/RX PN must not be reset to 0 for
3505 * the same key.
Hai Shalom74f70d42019-02-11 14:42:39 -08003506 *
3507 * FT-over-the-DS has a special case where the STA entry (and as such,
3508 * the TK) has not yet been configured to the driver depending on which
3509 * driver interface is used. For that case, allow add-STA operation to
3510 * be used (instead of set-STA). This is needed to allow mac80211-based
3511 * drivers to accept the STA parameter configuration. Since this is
3512 * after a new FT-over-DS exchange, a new TK has been derived, so key
3513 * reinstallation is not a concern for this case.
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003514 */
Hai Shalom74f70d42019-02-11 14:42:39 -08003515 wpa_printf(MSG_DEBUG, "Add associated STA " MACSTR
3516 " (added_unassoc=%d auth_alg=%u ft_over_ds=%u reassoc=%d authorized=%d ft_tk=%d fils_tk=%d)",
3517 MAC2STR(sta->addr), sta->added_unassoc, sta->auth_alg,
3518 sta->ft_over_ds, reassoc,
3519 !!(sta->flags & WLAN_STA_AUTHORIZED),
3520 wpa_auth_sta_ft_tk_already_set(sta->wpa_sm),
3521 wpa_auth_sta_fils_tk_already_set(sta->wpa_sm));
3522
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02003523 if (!sta->added_unassoc &&
3524 (!(sta->flags & WLAN_STA_AUTHORIZED) ||
Hai Shalom74f70d42019-02-11 14:42:39 -08003525 (reassoc && sta->ft_over_ds && sta->auth_alg == WLAN_AUTH_FT) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003526 (!wpa_auth_sta_ft_tk_already_set(sta->wpa_sm) &&
3527 !wpa_auth_sta_fils_tk_already_set(sta->wpa_sm)))) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003528 hostapd_drv_sta_remove(hapd, sta->addr);
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02003529 wpa_auth_sm_event(sta->wpa_sm, WPA_DRV_STA_REMOVED);
3530 set = 0;
Hai Shalom74f70d42019-02-11 14:42:39 -08003531
3532 /* Do not allow the FT-over-DS exception to be used more than
3533 * once per authentication exchange to guarantee a new TK is
3534 * used here */
3535 sta->ft_over_ds = 0;
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02003536 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003537
3538#ifdef CONFIG_IEEE80211N
3539 if (sta->flags & WLAN_STA_HT)
3540 hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
3541#endif /* CONFIG_IEEE80211N */
3542#ifdef CONFIG_IEEE80211AC
3543 if (sta->flags & WLAN_STA_VHT)
3544 hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
3545#endif /* CONFIG_IEEE80211AC */
Hai Shalom81f62d82019-07-22 12:10:00 -07003546#ifdef CONFIG_IEEE80211AX
3547 if (sta->flags & WLAN_STA_HE) {
3548 hostapd_get_he_capab(hapd, sta->he_capab, &he_cap,
3549 sta->he_capab_len);
3550 }
3551#endif /* CONFIG_IEEE80211AX */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003552
3553 /*
3554 * Add the station with forced WLAN_STA_ASSOC flag. The sta->flags
3555 * will be set when the ACK frame for the (Re)Association Response frame
3556 * is processed (TX status driver event).
3557 */
3558 if (hostapd_sta_add(hapd, sta->addr, sta->aid, sta->capability,
3559 sta->supported_rates, sta->supported_rates_len,
3560 sta->listen_interval,
3561 sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
3562 sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
Hai Shalom81f62d82019-07-22 12:10:00 -07003563 sta->flags & WLAN_STA_HE ? &he_cap : NULL,
3564 sta->flags & WLAN_STA_HE ? sta->he_capab_len : 0,
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003565 sta->flags | WLAN_STA_ASSOC, sta->qosinfo,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003566 sta->vht_opmode, sta->p2p_ie ? 1 : 0,
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02003567 set)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003568 hostapd_logger(hapd, sta->addr,
3569 HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE,
3570 "Could not %s STA to kernel driver",
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02003571 set ? "set" : "add");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003572
3573 if (sta->added_unassoc) {
3574 hostapd_drv_sta_remove(hapd, sta->addr);
3575 sta->added_unassoc = 0;
3576 }
3577
3578 return -1;
3579 }
3580
3581 sta->added_unassoc = 0;
3582
3583 return 0;
3584}
3585
3586
3587static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
Dmitry Shmidt29333592017-01-09 12:27:11 -08003588 const u8 *addr, u16 status_code, int reassoc,
Hai Shalom74f70d42019-02-11 14:42:39 -08003589 const u8 *ies, size_t ies_len, int rssi)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003590{
3591 int send_len;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003592 u8 *buf;
3593 size_t buflen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003594 struct ieee80211_mgmt *reply;
3595 u8 *p;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003596 u16 res = WLAN_STATUS_SUCCESS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003597
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003598 buflen = sizeof(struct ieee80211_mgmt) + 1024;
3599#ifdef CONFIG_FILS
3600 if (sta && sta->fils_hlp_resp)
3601 buflen += wpabuf_len(sta->fils_hlp_resp);
Hai Shalom81f62d82019-07-22 12:10:00 -07003602 if (sta)
3603 buflen += 150;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003604#endif /* CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003605#ifdef CONFIG_OWE
3606 if (sta && (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE))
3607 buflen += 150;
3608#endif /* CONFIG_OWE */
Hai Shalom021b0b52019-04-10 11:17:58 -07003609#ifdef CONFIG_DPP2
3610 if (sta && sta->dpp_pfs)
3611 buflen += 5 + sta->dpp_pfs->curve->prime_len;
3612#endif /* CONFIG_DPP2 */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003613 buf = os_zalloc(buflen);
3614 if (!buf) {
3615 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3616 goto done;
3617 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003618 reply = (struct ieee80211_mgmt *) buf;
3619 reply->frame_control =
3620 IEEE80211_FC(WLAN_FC_TYPE_MGMT,
3621 (reassoc ? WLAN_FC_STYPE_REASSOC_RESP :
3622 WLAN_FC_STYPE_ASSOC_RESP));
Dmitry Shmidt29333592017-01-09 12:27:11 -08003623 os_memcpy(reply->da, addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003624 os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
3625 os_memcpy(reply->bssid, hapd->own_addr, ETH_ALEN);
3626
3627 send_len = IEEE80211_HDRLEN;
3628 send_len += sizeof(reply->u.assoc_resp);
3629 reply->u.assoc_resp.capab_info =
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003630 host_to_le16(hostapd_own_capab_info(hapd));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003631 reply->u.assoc_resp.status_code = host_to_le16(status_code);
Dmitry Shmidt29333592017-01-09 12:27:11 -08003632
3633 reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0) |
3634 BIT(14) | BIT(15));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003635 /* Supported rates */
3636 p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable);
3637 /* Extended supported rates */
3638 p = hostapd_eid_ext_supp_rates(hapd, p);
3639
Hai Shalom74f70d42019-02-11 14:42:39 -08003640#ifdef CONFIG_MBO
3641 if (status_code == WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS &&
3642 rssi != 0) {
3643 int delta = hapd->iconf->rssi_reject_assoc_rssi - rssi;
3644
3645 p = hostapd_eid_mbo_rssi_assoc_rej(hapd, p, buf + buflen - p,
3646 delta);
3647 }
3648#endif /* CONFIG_MBO */
3649
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003650#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt29333592017-01-09 12:27:11 -08003651 if (sta && status_code == WLAN_STATUS_SUCCESS) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003652 /* IEEE 802.11r: Mobility Domain Information, Fast BSS
3653 * Transition Information, RSN, [RIC Response] */
3654 p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003655 buf + buflen - p,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003656 sta->auth_alg, ies, ies_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07003657 if (!p) {
3658 wpa_printf(MSG_DEBUG,
3659 "FT: Failed to write AssocResp IEs");
3660 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3661 goto done;
3662 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003663 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003664#endif /* CONFIG_IEEE80211R_AP */
Hai Shalom81f62d82019-07-22 12:10:00 -07003665#ifdef CONFIG_FILS
3666 if (sta && status_code == WLAN_STATUS_SUCCESS &&
3667 (sta->auth_alg == WLAN_AUTH_FILS_SK ||
3668 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
3669 sta->auth_alg == WLAN_AUTH_FILS_PK))
3670 p = wpa_auth_write_assoc_resp_fils(sta->wpa_sm, p,
3671 buf + buflen - p,
3672 ies, ies_len);
3673#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003674
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003675#ifdef CONFIG_OWE
Hai Shalom74f70d42019-02-11 14:42:39 -08003676 if (sta && status_code == WLAN_STATUS_SUCCESS &&
3677 (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE))
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003678 p = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, p,
3679 buf + buflen - p,
3680 ies, ies_len);
3681#endif /* CONFIG_OWE */
3682
Dmitry Shmidt29333592017-01-09 12:27:11 -08003683 if (sta && status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003684 p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003685
3686#ifdef CONFIG_IEEE80211N
3687 p = hostapd_eid_ht_capabilities(hapd, p);
3688 p = hostapd_eid_ht_operation(hapd, p);
3689#endif /* CONFIG_IEEE80211N */
3690
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003691#ifdef CONFIG_IEEE80211AC
Hai Shalomc3565922019-10-28 11:58:20 -07003692 if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac &&
3693 !is_6ghz_op_class(hapd->iconf->op_class)) {
Dmitry Shmidt7d175302016-09-06 13:11:34 -07003694 u32 nsts = 0, sta_nsts;
3695
Dmitry Shmidt29333592017-01-09 12:27:11 -08003696 if (sta && hapd->conf->use_sta_nsts && sta->vht_capabilities) {
Dmitry Shmidt7d175302016-09-06 13:11:34 -07003697 struct ieee80211_vht_capabilities *capa;
3698
3699 nsts = (hapd->iface->conf->vht_capab >>
3700 VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7;
3701 capa = sta->vht_capabilities;
3702 sta_nsts = (le_to_host32(capa->vht_capabilities_info) >>
3703 VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7;
3704
3705 if (nsts < sta_nsts)
3706 nsts = 0;
3707 else
3708 nsts = sta_nsts;
3709 }
3710 p = hostapd_eid_vht_capabilities(hapd, p, nsts);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003711 p = hostapd_eid_vht_operation(hapd, p);
3712 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003713#endif /* CONFIG_IEEE80211AC */
3714
Hai Shalom81f62d82019-07-22 12:10:00 -07003715#ifdef CONFIG_IEEE80211AX
3716 if (hapd->iconf->ieee80211ax) {
3717 p = hostapd_eid_he_capab(hapd, p, IEEE80211_MODE_AP);
3718 p = hostapd_eid_he_operation(hapd, p);
3719 p = hostapd_eid_spatial_reuse(hapd, p);
3720 p = hostapd_eid_he_mu_edca_parameter_set(hapd, p);
3721 }
3722#endif /* CONFIG_IEEE80211AX */
3723
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003724 p = hostapd_eid_ext_capab(hapd, p);
Dmitry Shmidt04949592012-07-19 12:16:46 -07003725 p = hostapd_eid_bss_max_idle_period(hapd, p);
Dmitry Shmidt29333592017-01-09 12:27:11 -08003726 if (sta && sta->qos_map_enabled)
Dmitry Shmidt051af732013-10-22 13:52:46 -07003727 p = hostapd_eid_qos_map_set(hapd, p);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003728
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003729#ifdef CONFIG_FST
3730 if (hapd->iface->fst_ies) {
3731 os_memcpy(p, wpabuf_head(hapd->iface->fst_ies),
3732 wpabuf_len(hapd->iface->fst_ies));
3733 p += wpabuf_len(hapd->iface->fst_ies);
3734 }
3735#endif /* CONFIG_FST */
3736
Hai Shalomc3565922019-10-28 11:58:20 -07003737 p = hostapd_eid_rsnxe(hapd, p, buf + buflen - p);
3738
Hai Shalom021b0b52019-04-10 11:17:58 -07003739#ifdef CONFIG_OWE
3740 if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
3741 sta && sta->owe_ecdh && status_code == WLAN_STATUS_SUCCESS &&
3742 wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE) {
3743 struct wpabuf *pub;
3744
3745 pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
3746 if (!pub) {
3747 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3748 goto done;
3749 }
3750 /* OWE Diffie-Hellman Parameter element */
3751 *p++ = WLAN_EID_EXTENSION; /* Element ID */
3752 *p++ = 1 + 2 + wpabuf_len(pub); /* Length */
3753 *p++ = WLAN_EID_EXT_OWE_DH_PARAM; /* Element ID Extension */
3754 WPA_PUT_LE16(p, sta->owe_group);
3755 p += 2;
3756 os_memcpy(p, wpabuf_head(pub), wpabuf_len(pub));
3757 p += wpabuf_len(pub);
3758 wpabuf_free(pub);
3759 }
3760#endif /* CONFIG_OWE */
3761
3762#ifdef CONFIG_DPP2
3763 if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) &&
3764 sta && sta->dpp_pfs && status_code == WLAN_STATUS_SUCCESS &&
3765 wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP) {
3766 os_memcpy(p, wpabuf_head(sta->dpp_pfs->ie),
3767 wpabuf_len(sta->dpp_pfs->ie));
3768 p += wpabuf_len(sta->dpp_pfs->ie);
3769 }
3770#endif /* CONFIG_DPP2 */
3771
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003772#ifdef CONFIG_IEEE80211AC
Dmitry Shmidt29333592017-01-09 12:27:11 -08003773 if (sta && hapd->conf->vendor_vht && (sta->flags & WLAN_STA_VENDOR_VHT))
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08003774 p = hostapd_eid_vendor_vht(hapd, p);
3775#endif /* CONFIG_IEEE80211AC */
3776
Dmitry Shmidt29333592017-01-09 12:27:11 -08003777 if (sta && (sta->flags & WLAN_STA_WMM))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003778 p = hostapd_eid_wmm(hapd, p);
3779
3780#ifdef CONFIG_WPS
Dmitry Shmidt29333592017-01-09 12:27:11 -08003781 if (sta &&
3782 ((sta->flags & WLAN_STA_WPS) ||
3783 ((sta->flags & WLAN_STA_MAYBE_WPS) && hapd->conf->wpa))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003784 struct wpabuf *wps = wps_build_assoc_resp_ie();
3785 if (wps) {
3786 os_memcpy(p, wpabuf_head(wps), wpabuf_len(wps));
3787 p += wpabuf_len(wps);
3788 wpabuf_free(wps);
3789 }
3790 }
3791#endif /* CONFIG_WPS */
3792
Hai Shalom74f70d42019-02-11 14:42:39 -08003793 if (sta && (sta->flags & WLAN_STA_MULTI_AP))
3794 p = hostapd_eid_multi_ap(hapd, p);
3795
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003796#ifdef CONFIG_P2P
Dmitry Shmidt29333592017-01-09 12:27:11 -08003797 if (sta && sta->p2p_ie && hapd->p2p_group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003798 struct wpabuf *p2p_resp_ie;
3799 enum p2p_status_code status;
3800 switch (status_code) {
3801 case WLAN_STATUS_SUCCESS:
3802 status = P2P_SC_SUCCESS;
3803 break;
3804 case WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA:
3805 status = P2P_SC_FAIL_LIMIT_REACHED;
3806 break;
3807 default:
3808 status = P2P_SC_FAIL_INVALID_PARAMS;
3809 break;
3810 }
3811 p2p_resp_ie = p2p_group_assoc_resp_ie(hapd->p2p_group, status);
3812 if (p2p_resp_ie) {
3813 os_memcpy(p, wpabuf_head(p2p_resp_ie),
3814 wpabuf_len(p2p_resp_ie));
3815 p += wpabuf_len(p2p_resp_ie);
3816 wpabuf_free(p2p_resp_ie);
3817 }
3818 }
3819#endif /* CONFIG_P2P */
3820
3821#ifdef CONFIG_P2P_MANAGER
3822 if (hapd->conf->p2p & P2P_MANAGE)
3823 p = hostapd_eid_p2p_manage(hapd, p);
3824#endif /* CONFIG_P2P_MANAGER */
3825
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003826 p = hostapd_eid_mbo(hapd, p, buf + buflen - p);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003827
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003828 if (hapd->conf->assocresp_elements &&
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003829 (size_t) (buf + buflen - p) >=
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003830 wpabuf_len(hapd->conf->assocresp_elements)) {
3831 os_memcpy(p, wpabuf_head(hapd->conf->assocresp_elements),
3832 wpabuf_len(hapd->conf->assocresp_elements));
3833 p += wpabuf_len(hapd->conf->assocresp_elements);
3834 }
3835
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003836 send_len += p - reply->u.assoc_resp.variable;
3837
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003838#ifdef CONFIG_FILS
Dmitry Shmidt29333592017-01-09 12:27:11 -08003839 if (sta &&
3840 (sta->auth_alg == WLAN_AUTH_FILS_SK ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003841 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
3842 sta->auth_alg == WLAN_AUTH_FILS_PK) &&
3843 status_code == WLAN_STATUS_SUCCESS) {
3844 struct ieee802_11_elems elems;
3845
3846 if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) ==
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003847 ParseFailed || !elems.fils_session) {
3848 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3849 goto done;
3850 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003851
3852 /* FILS Session */
3853 *p++ = WLAN_EID_EXTENSION; /* Element ID */
3854 *p++ = 1 + FILS_SESSION_LEN; /* Length */
3855 *p++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */
3856 os_memcpy(p, elems.fils_session, FILS_SESSION_LEN);
3857 send_len += 2 + 1 + FILS_SESSION_LEN;
3858
3859 send_len = fils_encrypt_assoc(sta->wpa_sm, buf, send_len,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003860 buflen, sta->fils_hlp_resp);
3861 if (send_len < 0) {
3862 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3863 goto done;
3864 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003865 }
3866#endif /* CONFIG_FILS */
3867
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003868 if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003869 wpa_printf(MSG_INFO, "Failed to send assoc resp: %s",
3870 strerror(errno));
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003871 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003872 }
3873
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003874done:
3875 os_free(buf);
3876 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003877}
3878
3879
Roshan Pius3a1667e2018-07-03 15:17:14 -07003880#ifdef CONFIG_OWE
3881u8 * owe_assoc_req_process(struct hostapd_data *hapd, struct sta_info *sta,
3882 const u8 *owe_dh, u8 owe_dh_len,
3883 u8 *owe_buf, size_t owe_buf_len, u16 *reason)
3884{
3885#ifdef CONFIG_TESTING_OPTIONS
3886 if (hapd->conf->own_ie_override) {
3887 wpa_printf(MSG_DEBUG, "OWE: Using IE override");
3888 *reason = WLAN_STATUS_SUCCESS;
3889 return wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
3890 owe_buf_len, NULL, 0);
3891 }
3892#endif /* CONFIG_TESTING_OPTIONS */
3893
3894 if (wpa_auth_sta_get_pmksa(sta->wpa_sm)) {
3895 wpa_printf(MSG_DEBUG, "OWE: Using PMKSA caching");
3896 owe_buf = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
3897 owe_buf_len, NULL, 0);
3898 *reason = WLAN_STATUS_SUCCESS;
3899 return owe_buf;
3900 }
3901
Hai Shalom81f62d82019-07-22 12:10:00 -07003902 if (sta->owe_pmk && sta->external_dh_updated) {
3903 wpa_printf(MSG_DEBUG, "OWE: Using previously derived PMK");
3904 *reason = WLAN_STATUS_SUCCESS;
3905 return owe_buf;
3906 }
3907
Roshan Pius3a1667e2018-07-03 15:17:14 -07003908 *reason = owe_process_assoc_req(hapd, sta, owe_dh, owe_dh_len);
3909 if (*reason != WLAN_STATUS_SUCCESS)
3910 return NULL;
3911
3912 owe_buf = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
3913 owe_buf_len, NULL, 0);
3914
3915 if (sta->owe_ecdh && owe_buf) {
3916 struct wpabuf *pub;
3917
3918 pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
3919 if (!pub) {
3920 *reason = WLAN_STATUS_UNSPECIFIED_FAILURE;
3921 return owe_buf;
3922 }
3923
3924 /* OWE Diffie-Hellman Parameter element */
3925 *owe_buf++ = WLAN_EID_EXTENSION; /* Element ID */
3926 *owe_buf++ = 1 + 2 + wpabuf_len(pub); /* Length */
3927 *owe_buf++ = WLAN_EID_EXT_OWE_DH_PARAM; /* Element ID Extension
3928 */
3929 WPA_PUT_LE16(owe_buf, sta->owe_group);
3930 owe_buf += 2;
3931 os_memcpy(owe_buf, wpabuf_head(pub), wpabuf_len(pub));
3932 owe_buf += wpabuf_len(pub);
3933 wpabuf_free(pub);
3934 }
3935
3936 return owe_buf;
3937}
3938#endif /* CONFIG_OWE */
3939
3940
Paul Stewart092955c2017-02-06 09:13:09 -08003941#ifdef CONFIG_FILS
3942
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003943void fils_hlp_finish_assoc(struct hostapd_data *hapd, struct sta_info *sta)
Paul Stewart092955c2017-02-06 09:13:09 -08003944{
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003945 u16 reply_res;
Paul Stewart092955c2017-02-06 09:13:09 -08003946
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003947 wpa_printf(MSG_DEBUG, "FILS: Finish association with " MACSTR,
3948 MAC2STR(sta->addr));
3949 eloop_cancel_timeout(fils_hlp_timeout, hapd, sta);
3950 if (!sta->fils_pending_assoc_req)
Paul Stewart092955c2017-02-06 09:13:09 -08003951 return;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003952 reply_res = send_assoc_resp(hapd, sta, sta->addr, WLAN_STATUS_SUCCESS,
3953 sta->fils_pending_assoc_is_reassoc,
3954 sta->fils_pending_assoc_req,
Hai Shalom74f70d42019-02-11 14:42:39 -08003955 sta->fils_pending_assoc_req_len, 0);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003956 os_free(sta->fils_pending_assoc_req);
3957 sta->fils_pending_assoc_req = NULL;
3958 sta->fils_pending_assoc_req_len = 0;
3959 wpabuf_free(sta->fils_hlp_resp);
3960 sta->fils_hlp_resp = NULL;
3961 wpabuf_free(sta->hlp_dhcp_discover);
3962 sta->hlp_dhcp_discover = NULL;
Paul Stewart092955c2017-02-06 09:13:09 -08003963
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003964 /*
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003965 * Remove the station in case transmission of a success response fails.
3966 * At this point the station was already added associated to the driver.
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003967 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003968 if (reply_res != WLAN_STATUS_SUCCESS)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003969 hostapd_drv_sta_remove(hapd, sta->addr);
Paul Stewart092955c2017-02-06 09:13:09 -08003970}
3971
3972
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003973void fils_hlp_timeout(void *eloop_ctx, void *eloop_data)
Paul Stewart092955c2017-02-06 09:13:09 -08003974{
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003975 struct hostapd_data *hapd = eloop_ctx;
3976 struct sta_info *sta = eloop_data;
Paul Stewart092955c2017-02-06 09:13:09 -08003977
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003978 wpa_printf(MSG_DEBUG,
3979 "FILS: HLP response timeout - continue with association response for "
3980 MACSTR, MAC2STR(sta->addr));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003981 if (sta->fils_drv_assoc_finish)
3982 hostapd_notify_assoc_fils_finish(hapd, sta);
3983 else
3984 fils_hlp_finish_assoc(hapd, sta);
Paul Stewart092955c2017-02-06 09:13:09 -08003985}
3986
3987#endif /* CONFIG_FILS */
3988
3989
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003990static void handle_assoc(struct hostapd_data *hapd,
3991 const struct ieee80211_mgmt *mgmt, size_t len,
Hai Shalom74f70d42019-02-11 14:42:39 -08003992 int reassoc, int rssi)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003993{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003994 u16 capab_info, listen_interval, seq_ctrl, fc;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003995 u16 resp = WLAN_STATUS_SUCCESS, reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003996 const u8 *pos;
3997 int left, i;
3998 struct sta_info *sta;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003999 u8 *tmp = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004000 struct hostapd_sta_wpa_psk_short *psk = NULL;
4001 char *identity = NULL;
4002 char *radius_cui = NULL;
4003#ifdef CONFIG_FILS
4004 int delay_assoc = 0;
4005#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004006
4007 if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
4008 sizeof(mgmt->u.assoc_req))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004009 wpa_printf(MSG_INFO, "handle_assoc(reassoc=%d) - too short payload (len=%lu)",
4010 reassoc, (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004011 return;
4012 }
4013
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004014#ifdef CONFIG_TESTING_OPTIONS
4015 if (reassoc) {
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004016 if (hapd->iconf->ignore_reassoc_probability > 0.0 &&
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004017 drand48() < hapd->iconf->ignore_reassoc_probability) {
4018 wpa_printf(MSG_INFO,
4019 "TESTING: ignoring reassoc request from "
4020 MACSTR, MAC2STR(mgmt->sa));
4021 return;
4022 }
4023 } else {
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004024 if (hapd->iconf->ignore_assoc_probability > 0.0 &&
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07004025 drand48() < hapd->iconf->ignore_assoc_probability) {
4026 wpa_printf(MSG_INFO,
4027 "TESTING: ignoring assoc request from "
4028 MACSTR, MAC2STR(mgmt->sa));
4029 return;
4030 }
4031 }
4032#endif /* CONFIG_TESTING_OPTIONS */
4033
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004034 fc = le_to_host16(mgmt->frame_control);
4035 seq_ctrl = le_to_host16(mgmt->seq_ctrl);
4036
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004037 if (reassoc) {
4038 capab_info = le_to_host16(mgmt->u.reassoc_req.capab_info);
4039 listen_interval = le_to_host16(
4040 mgmt->u.reassoc_req.listen_interval);
4041 wpa_printf(MSG_DEBUG, "reassociation request: STA=" MACSTR
4042 " capab_info=0x%02x listen_interval=%d current_ap="
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004043 MACSTR " seq_ctrl=0x%x%s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004044 MAC2STR(mgmt->sa), capab_info, listen_interval,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004045 MAC2STR(mgmt->u.reassoc_req.current_ap),
4046 seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004047 left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.reassoc_req));
4048 pos = mgmt->u.reassoc_req.variable;
4049 } else {
4050 capab_info = le_to_host16(mgmt->u.assoc_req.capab_info);
4051 listen_interval = le_to_host16(
4052 mgmt->u.assoc_req.listen_interval);
4053 wpa_printf(MSG_DEBUG, "association request: STA=" MACSTR
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004054 " capab_info=0x%02x listen_interval=%d "
4055 "seq_ctrl=0x%x%s",
4056 MAC2STR(mgmt->sa), capab_info, listen_interval,
4057 seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004058 left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req));
4059 pos = mgmt->u.assoc_req.variable;
4060 }
4061
4062 sta = ap_get_sta(hapd, mgmt->sa);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004063#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004064 if (sta && sta->auth_alg == WLAN_AUTH_FT &&
4065 (sta->flags & WLAN_STA_AUTH) == 0) {
4066 wpa_printf(MSG_DEBUG, "FT: Allow STA " MACSTR " to associate "
4067 "prior to authentication since it is using "
4068 "over-the-DS FT", MAC2STR(mgmt->sa));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004069
4070 /*
4071 * Mark station as authenticated, to avoid adding station
4072 * entry in the driver as associated and not authenticated
4073 */
4074 sta->flags |= WLAN_STA_AUTH;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004075 } else
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004076#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004077 if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) {
Dmitry Shmidt29333592017-01-09 12:27:11 -08004078 if (hapd->iface->current_mode &&
4079 hapd->iface->current_mode->mode ==
4080 HOSTAPD_MODE_IEEE80211AD) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004081 int acl_res;
4082 u32 session_timeout, acct_interim_interval;
4083 struct vlan_description vlan_id;
4084
4085 acl_res = ieee802_11_allowed_address(
4086 hapd, mgmt->sa, (const u8 *) mgmt, len,
4087 &session_timeout, &acct_interim_interval,
Roshan Pius3a1667e2018-07-03 15:17:14 -07004088 &vlan_id, &psk, &identity, &radius_cui, 0);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004089 if (acl_res == HOSTAPD_ACL_REJECT) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07004090 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
4091 "Ignore Association Request frame from "
4092 MACSTR " due to ACL reject",
4093 MAC2STR(mgmt->sa));
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004094 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
4095 goto fail;
4096 }
4097 if (acl_res == HOSTAPD_ACL_PENDING)
4098 return;
4099
Dmitry Shmidt29333592017-01-09 12:27:11 -08004100 /* DMG/IEEE 802.11ad does not use authentication.
4101 * Allocate sta entry upon association. */
4102 sta = ap_sta_add(hapd, mgmt->sa);
4103 if (!sta) {
4104 hostapd_logger(hapd, mgmt->sa,
4105 HOSTAPD_MODULE_IEEE80211,
4106 HOSTAPD_LEVEL_INFO,
4107 "Failed to add STA");
4108 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
4109 goto fail;
4110 }
4111
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004112 acl_res = ieee802_11_set_radius_info(
4113 hapd, sta, acl_res, session_timeout,
4114 acct_interim_interval, &vlan_id, &psk,
4115 &identity, &radius_cui);
4116 if (acl_res) {
4117 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
4118 goto fail;
4119 }
4120
Dmitry Shmidt29333592017-01-09 12:27:11 -08004121 hostapd_logger(hapd, sta->addr,
4122 HOSTAPD_MODULE_IEEE80211,
4123 HOSTAPD_LEVEL_DEBUG,
4124 "Skip authentication for DMG/IEEE 802.11ad");
4125 sta->flags |= WLAN_STA_AUTH;
4126 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
4127 sta->auth_alg = WLAN_AUTH_OPEN;
4128 } else {
4129 hostapd_logger(hapd, mgmt->sa,
4130 HOSTAPD_MODULE_IEEE80211,
4131 HOSTAPD_LEVEL_INFO,
4132 "Station tried to associate before authentication (aid=%d flags=0x%x)",
4133 sta ? sta->aid : -1,
4134 sta ? sta->flags : 0);
4135 send_deauth(hapd, mgmt->sa,
4136 WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
4137 return;
4138 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004139 }
4140
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004141 if ((fc & WLAN_FC_RETRY) &&
4142 sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ &&
4143 sta->last_seq_ctrl == seq_ctrl &&
Paul Stewart092955c2017-02-06 09:13:09 -08004144 sta->last_subtype == (reassoc ? WLAN_FC_STYPE_REASSOC_REQ :
4145 WLAN_FC_STYPE_ASSOC_REQ)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004146 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4147 HOSTAPD_LEVEL_DEBUG,
4148 "Drop repeated association frame seq_ctrl=0x%x",
4149 seq_ctrl);
4150 return;
4151 }
4152 sta->last_seq_ctrl = seq_ctrl;
4153 sta->last_subtype = reassoc ? WLAN_FC_STYPE_REASSOC_REQ :
4154 WLAN_FC_STYPE_ASSOC_REQ;
4155
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004156 if (hapd->tkip_countermeasures) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07004157 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004158 goto fail;
4159 }
4160
4161 if (listen_interval > hapd->conf->max_listen_interval) {
4162 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
4163 HOSTAPD_LEVEL_DEBUG,
4164 "Too large Listen Interval (%d)",
4165 listen_interval);
4166 resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE;
4167 goto fail;
4168 }
4169
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004170#ifdef CONFIG_MBO
4171 if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) {
4172 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
4173 goto fail;
4174 }
Hai Shalom74f70d42019-02-11 14:42:39 -08004175
4176 if (hapd->iconf->rssi_reject_assoc_rssi && rssi &&
4177 rssi < hapd->iconf->rssi_reject_assoc_rssi &&
4178 (sta->auth_rssi == 0 ||
4179 sta->auth_rssi < hapd->iconf->rssi_reject_assoc_rssi)) {
4180 resp = WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS;
4181 goto fail;
4182 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004183#endif /* CONFIG_MBO */
4184
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004185 /*
4186 * sta->capability is used in check_assoc_ies() for RRM enabled
4187 * capability element.
4188 */
4189 sta->capability = capab_info;
4190
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004191#ifdef CONFIG_FILS
4192 if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
4193 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
4194 sta->auth_alg == WLAN_AUTH_FILS_PK) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07004195 int res;
4196
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004197 /* The end of the payload is encrypted. Need to decrypt it
4198 * before parsing. */
4199
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004200 tmp = os_memdup(pos, left);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004201 if (!tmp) {
4202 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
4203 goto fail;
4204 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004205
Roshan Pius3a1667e2018-07-03 15:17:14 -07004206 res = fils_decrypt_assoc(sta->wpa_sm, sta->fils_session, mgmt,
4207 len, tmp, left);
4208 if (res < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004209 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
4210 goto fail;
4211 }
4212 pos = tmp;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004213 left = res;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004214 }
4215#endif /* CONFIG_FILS */
4216
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004217 /* followed by SSID and Supported rates; and HT capabilities if 802.11n
4218 * is used */
4219 resp = check_assoc_ies(hapd, sta, pos, left, reassoc);
4220 if (resp != WLAN_STATUS_SUCCESS)
4221 goto fail;
4222
4223 if (hostapd_get_aid(hapd, sta) < 0) {
4224 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
4225 HOSTAPD_LEVEL_INFO, "No room for more AIDs");
4226 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
4227 goto fail;
4228 }
4229
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004230 sta->listen_interval = listen_interval;
4231
Roshan Pius3a1667e2018-07-03 15:17:14 -07004232 if (hapd->iface->current_mode &&
4233 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004234 sta->flags |= WLAN_STA_NONERP;
4235 for (i = 0; i < sta->supported_rates_len; i++) {
4236 if ((sta->supported_rates[i] & 0x7f) > 22) {
4237 sta->flags &= ~WLAN_STA_NONERP;
4238 break;
4239 }
4240 }
4241 if (sta->flags & WLAN_STA_NONERP && !sta->nonerp_set) {
4242 sta->nonerp_set = 1;
4243 hapd->iface->num_sta_non_erp++;
4244 if (hapd->iface->num_sta_non_erp == 1)
4245 ieee802_11_set_beacons(hapd->iface);
4246 }
4247
4248 if (!(sta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) &&
4249 !sta->no_short_slot_time_set) {
4250 sta->no_short_slot_time_set = 1;
4251 hapd->iface->num_sta_no_short_slot_time++;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004252 if (hapd->iface->current_mode &&
4253 hapd->iface->current_mode->mode ==
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004254 HOSTAPD_MODE_IEEE80211G &&
4255 hapd->iface->num_sta_no_short_slot_time == 1)
4256 ieee802_11_set_beacons(hapd->iface);
4257 }
4258
4259 if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
4260 sta->flags |= WLAN_STA_SHORT_PREAMBLE;
4261 else
4262 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
4263
4264 if (!(sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
4265 !sta->no_short_preamble_set) {
4266 sta->no_short_preamble_set = 1;
4267 hapd->iface->num_sta_no_short_preamble++;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004268 if (hapd->iface->current_mode &&
4269 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004270 && hapd->iface->num_sta_no_short_preamble == 1)
4271 ieee802_11_set_beacons(hapd->iface);
4272 }
4273
4274#ifdef CONFIG_IEEE80211N
4275 update_ht_state(hapd, sta);
4276#endif /* CONFIG_IEEE80211N */
4277
4278 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4279 HOSTAPD_LEVEL_DEBUG,
4280 "association OK (aid %d)", sta->aid);
4281 /* Station will be marked associated, after it acknowledges AssocResp
4282 */
4283 sta->flags |= WLAN_STA_ASSOC_REQ_OK;
4284
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004285 if ((sta->flags & WLAN_STA_MFP) && sta->sa_query_timed_out) {
4286 wpa_printf(MSG_DEBUG, "Allowing %sassociation after timed out "
4287 "SA Query procedure", reassoc ? "re" : "");
4288 /* TODO: Send a protected Disassociate frame to the STA using
4289 * the old key and Reason Code "Previous Authentication no
4290 * longer valid". Make sure this is only sent protected since
4291 * unprotected frame would be received by the STA that is now
4292 * trying to associate.
4293 */
4294 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004295
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004296 /* Make sure that the previously registered inactivity timer will not
4297 * remove the STA immediately. */
4298 sta->timeout_next = STA_NULLFUNC;
4299
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07004300#ifdef CONFIG_TAXONOMY
4301 taxonomy_sta_info_assoc_req(hapd, sta, pos, left);
4302#endif /* CONFIG_TAXONOMY */
4303
Dmitry Shmidt29333592017-01-09 12:27:11 -08004304 sta->pending_wds_enable = 0;
4305
Paul Stewart092955c2017-02-06 09:13:09 -08004306#ifdef CONFIG_FILS
4307 if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
4308 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004309 sta->auth_alg == WLAN_AUTH_FILS_PK) {
4310 if (fils_process_hlp(hapd, sta, pos, left) > 0)
4311 delay_assoc = 1;
4312 }
Paul Stewart092955c2017-02-06 09:13:09 -08004313#endif /* CONFIG_FILS */
4314
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004315 fail:
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004316 os_free(identity);
4317 os_free(radius_cui);
4318 hostapd_free_psk_list(psk);
4319
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004320 /*
4321 * In case of a successful response, add the station to the driver.
4322 * Otherwise, the kernel may ignore Data frames before we process the
4323 * ACK frame (TX status). In case of a failure, this station will be
4324 * removed.
4325 *
4326 * Note that this is not compliant with the IEEE 802.11 standard that
4327 * states that a non-AP station should transition into the
4328 * authenticated/associated state only after the station acknowledges
4329 * the (Re)Association Response frame. However, still do this as:
4330 *
4331 * 1. In case the station does not acknowledge the (Re)Association
4332 * Response frame, it will be removed.
4333 * 2. Data frames will be dropped in the kernel until the station is
4334 * set into authorized state, and there are no significant known
4335 * issues with processing other non-Data Class 3 frames during this
4336 * window.
4337 */
Hai Shalom74f70d42019-02-11 14:42:39 -08004338 if (resp == WLAN_STATUS_SUCCESS && sta &&
4339 add_associated_sta(hapd, sta, reassoc))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004340 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
4341
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004342#ifdef CONFIG_FILS
Hai Shalom74f70d42019-02-11 14:42:39 -08004343 if (sta && delay_assoc && resp == WLAN_STATUS_SUCCESS &&
4344 eloop_is_timeout_registered(fils_hlp_timeout, hapd, sta) &&
4345 sta->fils_pending_assoc_req) {
4346 /* Do not reschedule fils_hlp_timeout in case the station
4347 * retransmits (Re)Association Request frame while waiting for
4348 * the previously started FILS HLP wait, so that the timeout can
4349 * be determined from the first pending attempt. */
4350 wpa_printf(MSG_DEBUG,
4351 "FILS: Continue waiting for HLP processing before sending (Re)Association Response frame to "
4352 MACSTR, MAC2STR(sta->addr));
4353 os_free(tmp);
4354 return;
4355 }
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004356 if (sta) {
4357 eloop_cancel_timeout(fils_hlp_timeout, hapd, sta);
4358 os_free(sta->fils_pending_assoc_req);
4359 sta->fils_pending_assoc_req = NULL;
4360 sta->fils_pending_assoc_req_len = 0;
4361 wpabuf_free(sta->fils_hlp_resp);
4362 sta->fils_hlp_resp = NULL;
4363 }
4364 if (sta && delay_assoc && resp == WLAN_STATUS_SUCCESS) {
4365 sta->fils_pending_assoc_req = tmp;
4366 sta->fils_pending_assoc_req_len = left;
4367 sta->fils_pending_assoc_is_reassoc = reassoc;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004368 sta->fils_drv_assoc_finish = 0;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004369 wpa_printf(MSG_DEBUG,
4370 "FILS: Waiting for HLP processing before sending (Re)Association Response frame to "
4371 MACSTR, MAC2STR(sta->addr));
4372 eloop_cancel_timeout(fils_hlp_timeout, hapd, sta);
4373 eloop_register_timeout(0, hapd->conf->fils_hlp_wait_time * 1024,
4374 fils_hlp_timeout, hapd, sta);
4375 return;
4376 }
4377#endif /* CONFIG_FILS */
4378
Dmitry Shmidt29333592017-01-09 12:27:11 -08004379 reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc, pos,
Hai Shalom74f70d42019-02-11 14:42:39 -08004380 left, rssi);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004381 os_free(tmp);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004382
4383 /*
4384 * Remove the station in case tranmission of a success response fails
4385 * (the STA was added associated to the driver) or if the station was
4386 * previously added unassociated.
4387 */
Dmitry Shmidt29333592017-01-09 12:27:11 -08004388 if (sta && ((reply_res != WLAN_STATUS_SUCCESS &&
4389 resp == WLAN_STATUS_SUCCESS) || sta->added_unassoc)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004390 hostapd_drv_sta_remove(hapd, sta->addr);
4391 sta->added_unassoc = 0;
4392 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004393}
4394
4395
4396static void handle_disassoc(struct hostapd_data *hapd,
4397 const struct ieee80211_mgmt *mgmt, size_t len)
4398{
4399 struct sta_info *sta;
4400
4401 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004402 wpa_printf(MSG_INFO, "handle_disassoc - too short payload (len=%lu)",
4403 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004404 return;
4405 }
4406
4407 wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d",
4408 MAC2STR(mgmt->sa),
4409 le_to_host16(mgmt->u.disassoc.reason_code));
4410
4411 sta = ap_get_sta(hapd, mgmt->sa);
4412 if (sta == NULL) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004413 wpa_printf(MSG_INFO, "Station " MACSTR " trying to disassociate, but it is not associated",
4414 MAC2STR(mgmt->sa));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004415 return;
4416 }
4417
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004418 ap_sta_set_authorized(hapd, sta, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004419 sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004420 sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004421 wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
4422 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4423 HOSTAPD_LEVEL_INFO, "disassociated");
4424 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
4425 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
4426 /* Stop Accounting and IEEE 802.1X sessions, but leave the STA
4427 * authenticated. */
4428 accounting_sta_stop(hapd, sta);
Dmitry Shmidtde47be72016-01-07 12:52:55 -08004429 ieee802_1x_free_station(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004430 if (sta->ipaddr)
4431 hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
4432 ap_sta_ip6addr_del(hapd, sta);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004433 hostapd_drv_sta_remove(hapd, sta->addr);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004434 sta->added_unassoc = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004435
4436 if (sta->timeout_next == STA_NULLFUNC ||
4437 sta->timeout_next == STA_DISASSOC) {
4438 sta->timeout_next = STA_DEAUTH;
4439 eloop_cancel_timeout(ap_handle_timer, hapd, sta);
4440 eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
4441 hapd, sta);
4442 }
4443
4444 mlme_disassociate_indication(
4445 hapd, sta, le_to_host16(mgmt->u.disassoc.reason_code));
Dmitry Shmidt29333592017-01-09 12:27:11 -08004446
4447 /* DMG/IEEE 802.11ad does not use deauthication. Deallocate sta upon
4448 * disassociation. */
4449 if (hapd->iface->current_mode &&
4450 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD) {
4451 sta->flags &= ~WLAN_STA_AUTH;
4452 wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
4453 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4454 HOSTAPD_LEVEL_DEBUG, "deauthenticated");
4455 ap_free_sta(hapd, sta);
4456 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004457}
4458
4459
4460static void handle_deauth(struct hostapd_data *hapd,
4461 const struct ieee80211_mgmt *mgmt, size_t len)
4462{
4463 struct sta_info *sta;
4464
4465 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004466 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "handle_deauth - too short "
4467 "payload (len=%lu)", (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004468 return;
4469 }
4470
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004471 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "deauthentication: STA=" MACSTR
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004472 " reason_code=%d",
4473 MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code));
4474
4475 sta = ap_get_sta(hapd, mgmt->sa);
4476 if (sta == NULL) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004477 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying "
4478 "to deauthenticate, but it is not authenticated",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004479 MAC2STR(mgmt->sa));
4480 return;
4481 }
4482
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004483 ap_sta_set_authorized(hapd, sta, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004484 sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004485 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
4486 WLAN_STA_ASSOC_REQ_OK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004487 wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
4488 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4489 HOSTAPD_LEVEL_DEBUG, "deauthenticated");
4490 mlme_deauthenticate_indication(
4491 hapd, sta, le_to_host16(mgmt->u.deauth.reason_code));
4492 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
4493 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
4494 ap_free_sta(hapd, sta);
4495}
4496
4497
4498static void handle_beacon(struct hostapd_data *hapd,
4499 const struct ieee80211_mgmt *mgmt, size_t len,
4500 struct hostapd_frame_info *fi)
4501{
4502 struct ieee802_11_elems elems;
4503
4504 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.beacon)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004505 wpa_printf(MSG_INFO, "handle_beacon - too short payload (len=%lu)",
4506 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004507 return;
4508 }
4509
4510 (void) ieee802_11_parse_elems(mgmt->u.beacon.variable,
4511 len - (IEEE80211_HDRLEN +
4512 sizeof(mgmt->u.beacon)), &elems,
4513 0);
4514
4515 ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);
4516}
4517
4518
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004519static int robust_action_frame(u8 category)
4520{
4521 return category != WLAN_ACTION_PUBLIC &&
4522 category != WLAN_ACTION_HT;
4523}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004524
4525
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004526static int handle_action(struct hostapd_data *hapd,
Roshan Pius3a1667e2018-07-03 15:17:14 -07004527 const struct ieee80211_mgmt *mgmt, size_t len,
4528 unsigned int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004529{
4530 struct sta_info *sta;
Hai Shalom74f70d42019-02-11 14:42:39 -08004531 u8 *action __maybe_unused;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004532
Hai Shalom74f70d42019-02-11 14:42:39 -08004533 if (len < IEEE80211_HDRLEN + 2 + 1) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004534 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
4535 HOSTAPD_LEVEL_DEBUG,
4536 "handle_action - too short payload (len=%lu)",
4537 (unsigned long) len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004538 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004539 }
4540
Hai Shalom74f70d42019-02-11 14:42:39 -08004541 action = (u8 *) &mgmt->u.action.u;
4542 wpa_printf(MSG_DEBUG, "RX_ACTION category %u action %u sa " MACSTR
4543 " da " MACSTR " len %d freq %u",
4544 mgmt->u.action.category, *action,
4545 MAC2STR(mgmt->sa), MAC2STR(mgmt->da), (int) len, freq);
4546
4547 sta = ap_get_sta(hapd, mgmt->sa);
4548
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004549 if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
4550 (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))) {
4551 wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored Action "
4552 "frame (category=%u) from unassociated STA " MACSTR,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08004553 mgmt->u.action.category, MAC2STR(mgmt->sa));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004554 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004555 }
4556
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004557 if (sta && (sta->flags & WLAN_STA_MFP) &&
Dmitry Shmidt18463232014-01-24 12:29:41 -08004558 !(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP)) &&
4559 robust_action_frame(mgmt->u.action.category)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004560 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
4561 HOSTAPD_LEVEL_DEBUG,
4562 "Dropped unprotected Robust Action frame from "
4563 "an MFP STA");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004564 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004565 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004566
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004567 if (sta) {
4568 u16 fc = le_to_host16(mgmt->frame_control);
4569 u16 seq_ctrl = le_to_host16(mgmt->seq_ctrl);
4570
4571 if ((fc & WLAN_FC_RETRY) &&
4572 sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ &&
4573 sta->last_seq_ctrl == seq_ctrl &&
4574 sta->last_subtype == WLAN_FC_STYPE_ACTION) {
4575 hostapd_logger(hapd, sta->addr,
4576 HOSTAPD_MODULE_IEEE80211,
4577 HOSTAPD_LEVEL_DEBUG,
4578 "Drop repeated action frame seq_ctrl=0x%x",
4579 seq_ctrl);
4580 return 1;
4581 }
4582
4583 sta->last_seq_ctrl = seq_ctrl;
4584 sta->last_subtype = WLAN_FC_STYPE_ACTION;
4585 }
4586
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004587 switch (mgmt->u.action.category) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004588#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004589 case WLAN_ACTION_FT:
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004590 if (!sta ||
4591 wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004592 len - IEEE80211_HDRLEN))
4593 break;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004594 return 1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004595#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004596 case WLAN_ACTION_WMM:
4597 hostapd_wmm_action(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004598 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004599 case WLAN_ACTION_SA_QUERY:
Hai Shalom021b0b52019-04-10 11:17:58 -07004600 ieee802_11_sa_query_action(hapd, mgmt, len);
4601 return 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004602#ifdef CONFIG_WNM_AP
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08004603 case WLAN_ACTION_WNM:
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004604 ieee802_11_rx_wnm_action_ap(hapd, mgmt, len);
4605 return 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004606#endif /* CONFIG_WNM_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004607#ifdef CONFIG_FST
4608 case WLAN_ACTION_FST:
4609 if (hapd->iface->fst)
4610 fst_rx_action(hapd->iface->fst, mgmt, len);
4611 else
4612 wpa_printf(MSG_DEBUG,
4613 "FST: Ignore FST Action frame - no FST attached");
4614 return 1;
4615#endif /* CONFIG_FST */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004616 case WLAN_ACTION_PUBLIC:
Dmitry Shmidt18463232014-01-24 12:29:41 -08004617 case WLAN_ACTION_PROTECTED_DUAL:
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004618#ifdef CONFIG_IEEE80211N
Dmitry Shmidtcc00d5d2015-05-04 10:34:12 -07004619 if (len >= IEEE80211_HDRLEN + 2 &&
4620 mgmt->u.action.u.public_action.action ==
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004621 WLAN_PA_20_40_BSS_COEX) {
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004622 hostapd_2040_coex_action(hapd, mgmt, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004623 return 1;
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07004624 }
4625#endif /* CONFIG_IEEE80211N */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004626#ifdef CONFIG_DPP
4627 if (len >= IEEE80211_HDRLEN + 6 &&
4628 mgmt->u.action.u.vs_public_action.action ==
4629 WLAN_PA_VENDOR_SPECIFIC &&
4630 WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) ==
4631 OUI_WFA &&
4632 mgmt->u.action.u.vs_public_action.variable[0] ==
4633 DPP_OUI_TYPE) {
4634 const u8 *pos, *end;
4635
4636 pos = mgmt->u.action.u.vs_public_action.oui;
4637 end = ((const u8 *) mgmt) + len;
4638 hostapd_dpp_rx_action(hapd, mgmt->sa, pos, end - pos,
Roshan Pius3a1667e2018-07-03 15:17:14 -07004639 freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004640 return 1;
4641 }
4642 if (len >= IEEE80211_HDRLEN + 2 &&
4643 (mgmt->u.action.u.public_action.action ==
4644 WLAN_PA_GAS_INITIAL_RESP ||
4645 mgmt->u.action.u.public_action.action ==
4646 WLAN_PA_GAS_COMEBACK_RESP)) {
4647 const u8 *pos, *end;
4648
4649 pos = &mgmt->u.action.u.public_action.action;
4650 end = ((const u8 *) mgmt) + len;
4651 gas_query_ap_rx(hapd->gas, mgmt->sa,
4652 mgmt->u.action.category,
4653 pos, end - pos, hapd->iface->freq);
4654 return 1;
4655 }
4656#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004657 if (hapd->public_action_cb) {
4658 hapd->public_action_cb(hapd->public_action_cb_ctx,
4659 (u8 *) mgmt, len,
4660 hapd->iface->freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004661 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004662 if (hapd->public_action_cb2) {
Dmitry Shmidtf8623282013-02-20 14:34:59 -08004663 hapd->public_action_cb2(hapd->public_action_cb2_ctx,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08004664 (u8 *) mgmt, len,
4665 hapd->iface->freq);
4666 }
4667 if (hapd->public_action_cb || hapd->public_action_cb2)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004668 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004669 break;
4670 case WLAN_ACTION_VENDOR_SPECIFIC:
4671 if (hapd->vendor_action_cb) {
4672 if (hapd->vendor_action_cb(hapd->vendor_action_cb_ctx,
4673 (u8 *) mgmt, len,
4674 hapd->iface->freq) == 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004675 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004676 }
4677 break;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004678 case WLAN_ACTION_RADIO_MEASUREMENT:
4679 hostapd_handle_radio_measurement(hapd, (const u8 *) mgmt, len);
4680 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004681 }
4682
4683 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
4684 HOSTAPD_LEVEL_DEBUG,
4685 "handle_action - unknown action category %d or invalid "
4686 "frame",
4687 mgmt->u.action.category);
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07004688 if (!is_multicast_ether_addr(mgmt->da) &&
4689 !(mgmt->u.action.category & 0x80) &&
4690 !is_multicast_ether_addr(mgmt->sa)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004691 struct ieee80211_mgmt *resp;
4692
4693 /*
4694 * IEEE 802.11-REVma/D9.0 - 7.3.1.11
4695 * Return the Action frame to the source without change
4696 * except that MSB of the Category set to 1.
4697 */
4698 wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action "
4699 "frame back to sender");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004700 resp = os_memdup(mgmt, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004701 if (resp == NULL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004702 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004703 os_memcpy(resp->da, resp->sa, ETH_ALEN);
4704 os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
4705 os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
4706 resp->u.action.category |= 0x80;
4707
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07004708 if (hostapd_drv_send_mlme(hapd, resp, len, 0) < 0) {
4709 wpa_printf(MSG_ERROR, "IEEE 802.11: Failed to send "
4710 "Action frame");
4711 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004712 os_free(resp);
4713 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004714
4715 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004716}
4717
4718
4719/**
4720 * ieee802_11_mgmt - process incoming IEEE 802.11 management frames
4721 * @hapd: hostapd BSS data structure (the BSS to which the management frame was
4722 * sent to)
4723 * @buf: management frame data (starting from IEEE 802.11 header)
4724 * @len: length of frame data in octets
4725 * @fi: meta data about received frame (signal level, etc.)
4726 *
4727 * Process all incoming IEEE 802.11 management frames. This will be called for
4728 * each frame received from the kernel driver through wlan#ap interface. In
4729 * addition, it can be called to re-inserted pending frames (e.g., when using
4730 * external RADIUS server as an MAC ACL).
4731 */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004732int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
4733 struct hostapd_frame_info *fi)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004734{
4735 struct ieee80211_mgmt *mgmt;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004736 u16 fc, stype;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004737 int ret = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07004738 unsigned int freq;
4739 int ssi_signal = fi ? fi->ssi_signal : 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004740
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004741 if (len < 24)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004742 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004743
Roshan Pius3a1667e2018-07-03 15:17:14 -07004744 if (fi && fi->freq)
4745 freq = fi->freq;
4746 else
4747 freq = hapd->iface->freq;
4748
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004749 mgmt = (struct ieee80211_mgmt *) buf;
4750 fc = le_to_host16(mgmt->frame_control);
4751 stype = WLAN_FC_GET_STYPE(fc);
4752
Hai Shalomc3565922019-10-28 11:58:20 -07004753 if (is_multicast_ether_addr(mgmt->sa) ||
4754 is_zero_ether_addr(mgmt->sa) ||
4755 os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) {
4756 /* Do not process any frames with unexpected/invalid SA so that
4757 * we do not add any state for unexpected STA addresses or end
4758 * up sending out frames to unexpected destination. */
4759 wpa_printf(MSG_DEBUG, "MGMT: Invalid SA=" MACSTR
4760 " in received frame - ignore this frame silently",
4761 MAC2STR(mgmt->sa));
4762 return 0;
4763 }
4764
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004765 if (stype == WLAN_FC_STYPE_BEACON) {
4766 handle_beacon(hapd, mgmt, len, fi);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004767 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004768 }
4769
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07004770 if (!is_broadcast_ether_addr(mgmt->bssid) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004771#ifdef CONFIG_P2P
4772 /* Invitation responses can be sent with the peer MAC as BSSID */
4773 !((hapd->conf->p2p & P2P_GROUP_OWNER) &&
4774 stype == WLAN_FC_STYPE_ACTION) &&
4775#endif /* CONFIG_P2P */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08004776#ifdef CONFIG_MESH
4777 !(hapd->conf->mesh & MESH_ENABLED) &&
4778#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004779 os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004780 wpa_printf(MSG_INFO, "MGMT: BSSID=" MACSTR " not our address",
4781 MAC2STR(mgmt->bssid));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004782 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004783 }
4784
4785
4786 if (stype == WLAN_FC_STYPE_PROBE_REQ) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07004787 handle_probe_req(hapd, mgmt, len, ssi_signal);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004788 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004789 }
4790
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004791 if ((!is_broadcast_ether_addr(mgmt->da) ||
4792 stype != WLAN_FC_STYPE_ACTION) &&
4793 os_memcmp(mgmt->da, hapd->own_addr, ETH_ALEN) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004794 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
4795 HOSTAPD_LEVEL_DEBUG,
4796 "MGMT: DA=" MACSTR " not our address",
4797 MAC2STR(mgmt->da));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004798 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004799 }
4800
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004801 if (hapd->iconf->track_sta_max_num)
Roshan Pius3a1667e2018-07-03 15:17:14 -07004802 sta_track_add(hapd->iface, mgmt->sa, ssi_signal);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004803
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004804 switch (stype) {
4805 case WLAN_FC_STYPE_AUTH:
4806 wpa_printf(MSG_DEBUG, "mgmt::auth");
Hai Shalom021b0b52019-04-10 11:17:58 -07004807 handle_auth(hapd, mgmt, len, ssi_signal, 0);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004808 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004809 break;
4810 case WLAN_FC_STYPE_ASSOC_REQ:
4811 wpa_printf(MSG_DEBUG, "mgmt::assoc_req");
Hai Shalom74f70d42019-02-11 14:42:39 -08004812 handle_assoc(hapd, mgmt, len, 0, ssi_signal);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004813 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004814 break;
4815 case WLAN_FC_STYPE_REASSOC_REQ:
4816 wpa_printf(MSG_DEBUG, "mgmt::reassoc_req");
Hai Shalom74f70d42019-02-11 14:42:39 -08004817 handle_assoc(hapd, mgmt, len, 1, ssi_signal);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004818 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004819 break;
4820 case WLAN_FC_STYPE_DISASSOC:
4821 wpa_printf(MSG_DEBUG, "mgmt::disassoc");
4822 handle_disassoc(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004823 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004824 break;
4825 case WLAN_FC_STYPE_DEAUTH:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004826 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "mgmt::deauth");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004827 handle_deauth(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004828 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004829 break;
4830 case WLAN_FC_STYPE_ACTION:
4831 wpa_printf(MSG_DEBUG, "mgmt::action");
Roshan Pius3a1667e2018-07-03 15:17:14 -07004832 ret = handle_action(hapd, mgmt, len, freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004833 break;
4834 default:
4835 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
4836 HOSTAPD_LEVEL_DEBUG,
4837 "unknown mgmt frame subtype %d", stype);
4838 break;
4839 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004840
4841 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004842}
4843
4844
4845static void handle_auth_cb(struct hostapd_data *hapd,
4846 const struct ieee80211_mgmt *mgmt,
4847 size_t len, int ok)
4848{
4849 u16 auth_alg, auth_transaction, status_code;
4850 struct sta_info *sta;
4851
Hai Shalome5e28bb2019-01-28 14:51:04 -08004852 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
4853 wpa_printf(MSG_INFO, "handle_auth_cb - too short payload (len=%lu)",
4854 (unsigned long) len);
4855
4856 /*
4857 * Initialize status_code here because we are not able to read
4858 * it from the short payload.
4859 */
4860 status_code = WLAN_STATUS_UNSPECIFIED_FAILURE;
4861 goto fail;
4862 }
4863
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004864 sta = ap_get_sta(hapd, mgmt->da);
4865 if (!sta) {
Hai Shalom39ba6fc2019-01-22 12:40:38 -08004866 wpa_printf(MSG_DEBUG, "handle_auth_cb: STA " MACSTR
4867 " not found",
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004868 MAC2STR(mgmt->da));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004869 return;
4870 }
4871
4872 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
4873 auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
4874 status_code = le_to_host16(mgmt->u.auth.status_code);
4875
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004876 if (!ok) {
4877 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
4878 HOSTAPD_LEVEL_NOTICE,
4879 "did not acknowledge authentication response");
4880 goto fail;
4881 }
4882
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004883 if (status_code == WLAN_STATUS_SUCCESS &&
4884 ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) ||
4885 (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) {
4886 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4887 HOSTAPD_LEVEL_INFO, "authenticated");
4888 sta->flags |= WLAN_STA_AUTH;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004889 if (sta->added_unassoc)
4890 hostapd_set_sta_flags(hapd, sta);
4891 return;
4892 }
4893
4894fail:
4895 if (status_code != WLAN_STATUS_SUCCESS && sta->added_unassoc) {
4896 hostapd_drv_sta_remove(hapd, sta->addr);
4897 sta->added_unassoc = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004898 }
4899}
4900
4901
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004902static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
4903 struct sta_info *sta,
4904 char *ifname_wds)
4905{
4906 int i;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004907 struct hostapd_ssid *ssid = &hapd->conf->ssid;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004908
4909 if (hapd->conf->ieee802_1x || hapd->conf->wpa)
4910 return;
4911
4912 for (i = 0; i < 4; i++) {
4913 if (ssid->wep.key[i] &&
4914 hostapd_drv_set_key(ifname_wds, hapd, WPA_ALG_WEP, NULL, i,
4915 i == ssid->wep.idx, NULL, 0,
4916 ssid->wep.key[i], ssid->wep.len[i])) {
4917 wpa_printf(MSG_WARNING,
4918 "Could not set WEP keys for WDS interface; %s",
4919 ifname_wds);
4920 break;
4921 }
4922 }
4923}
4924
4925
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004926static void handle_assoc_cb(struct hostapd_data *hapd,
4927 const struct ieee80211_mgmt *mgmt,
4928 size_t len, int reassoc, int ok)
4929{
4930 u16 status;
4931 struct sta_info *sta;
4932 int new_assoc = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004933
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004934 sta = ap_get_sta(hapd, mgmt->da);
4935 if (!sta) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004936 wpa_printf(MSG_INFO, "handle_assoc_cb: STA " MACSTR " not found",
4937 MAC2STR(mgmt->da));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004938 return;
4939 }
4940
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004941 if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) :
4942 sizeof(mgmt->u.assoc_resp))) {
4943 wpa_printf(MSG_INFO,
4944 "handle_assoc_cb(reassoc=%d) - too short payload (len=%lu)",
4945 reassoc, (unsigned long) len);
4946 hostapd_drv_sta_remove(hapd, sta->addr);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07004947 return;
4948 }
4949
4950 if (reassoc)
4951 status = le_to_host16(mgmt->u.reassoc_resp.status_code);
4952 else
4953 status = le_to_host16(mgmt->u.assoc_resp.status_code);
4954
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004955 if (!ok) {
4956 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
4957 HOSTAPD_LEVEL_DEBUG,
4958 "did not acknowledge association response");
4959 sta->flags &= ~WLAN_STA_ASSOC_REQ_OK;
4960 /* The STA is added only in case of SUCCESS */
4961 if (status == WLAN_STATUS_SUCCESS)
4962 hostapd_drv_sta_remove(hapd, sta->addr);
4963
4964 return;
4965 }
4966
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004967 if (status != WLAN_STATUS_SUCCESS)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004968 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004969
4970 /* Stop previous accounting session, if one is started, and allocate
4971 * new session id for the new session. */
4972 accounting_sta_stop(hapd, sta);
4973
4974 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4975 HOSTAPD_LEVEL_INFO,
4976 "associated (aid %d)",
4977 sta->aid);
4978
4979 if (sta->flags & WLAN_STA_ASSOC)
4980 new_assoc = 0;
4981 sta->flags |= WLAN_STA_ASSOC;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004982 sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004983 if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
4984 !hapd->conf->osen) ||
4985 sta->auth_alg == WLAN_AUTH_FILS_SK ||
4986 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
4987 sta->auth_alg == WLAN_AUTH_FILS_PK ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004988 sta->auth_alg == WLAN_AUTH_FT) {
4989 /*
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004990 * Open, static WEP, FT protocol, or FILS; no separate
4991 * authorization step.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004992 */
4993 ap_sta_set_authorized(hapd, sta, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004994 }
4995
4996 if (reassoc)
4997 mlme_reassociate_indication(hapd, sta);
4998 else
4999 mlme_associate_indication(hapd, sta);
5000
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005001 sta->sa_query_timed_out = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005002
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005003 if (sta->eapol_sm == NULL) {
5004 /*
5005 * This STA does not use RADIUS server for EAP authentication,
5006 * so bind it to the selected VLAN interface now, since the
5007 * interface selection is not going to change anymore.
5008 */
Dmitry Shmidt83474442015-04-15 13:47:09 -07005009 if (ap_sta_bind_vlan(hapd, sta) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005010 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005011 } else if (sta->vlan_id) {
5012 /* VLAN ID already set (e.g., by PMKSA caching), so bind STA */
Dmitry Shmidt83474442015-04-15 13:47:09 -07005013 if (ap_sta_bind_vlan(hapd, sta) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07005014 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005015 }
5016
5017 hostapd_set_sta_flags(hapd, sta);
5018
Dmitry Shmidt29333592017-01-09 12:27:11 -08005019 if (!(sta->flags & WLAN_STA_WDS) && sta->pending_wds_enable) {
5020 wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for STA "
5021 MACSTR " based on pending request",
5022 MAC2STR(sta->addr));
5023 sta->pending_wds_enable = 0;
5024 sta->flags |= WLAN_STA_WDS;
5025 }
5026
Hai Shalom74f70d42019-02-11 14:42:39 -08005027 if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP)) {
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08005028 int ret;
5029 char ifname_wds[IFNAMSIZ + 1];
5030
5031 wpa_printf(MSG_DEBUG, "Reenable 4-address WDS mode for STA "
5032 MACSTR " (aid %u)",
5033 MAC2STR(sta->addr), sta->aid);
5034 ret = hostapd_set_wds_sta(hapd, ifname_wds, sta->addr,
5035 sta->aid, 1);
5036 if (!ret)
5037 hostapd_set_wds_encryption(hapd, sta, ifname_wds);
5038 }
5039
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005040 if (sta->auth_alg == WLAN_AUTH_FT)
5041 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
5042 else
5043 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
5044 hapd->new_assoc_sta_cb(hapd, sta, !new_assoc);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005045 ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08005046
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08005047#ifdef CONFIG_FILS
5048 if ((sta->auth_alg == WLAN_AUTH_FILS_SK ||
5049 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
5050 sta->auth_alg == WLAN_AUTH_FILS_PK) &&
5051 fils_set_tk(sta->wpa_sm) < 0) {
5052 wpa_printf(MSG_DEBUG, "FILS: TK configuration failed");
5053 ap_sta_disconnect(hapd, sta, sta->addr,
5054 WLAN_REASON_UNSPECIFIED);
5055 return;
5056 }
5057#endif /* CONFIG_FILS */
5058
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08005059 if (sta->pending_eapol_rx) {
5060 struct os_reltime now, age;
5061
5062 os_get_reltime(&now);
5063 os_reltime_sub(&now, &sta->pending_eapol_rx->rx_time, &age);
5064 if (age.sec == 0 && age.usec < 200000) {
5065 wpa_printf(MSG_DEBUG,
5066 "Process pending EAPOL frame that was received from " MACSTR " just before association notification",
5067 MAC2STR(sta->addr));
5068 ieee802_1x_receive(
5069 hapd, mgmt->da,
5070 wpabuf_head(sta->pending_eapol_rx->buf),
5071 wpabuf_len(sta->pending_eapol_rx->buf));
5072 }
5073 wpabuf_free(sta->pending_eapol_rx->buf);
5074 os_free(sta->pending_eapol_rx);
5075 sta->pending_eapol_rx = NULL;
5076 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005077}
5078
5079
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005080static void handle_deauth_cb(struct hostapd_data *hapd,
5081 const struct ieee80211_mgmt *mgmt,
5082 size_t len, int ok)
5083{
5084 struct sta_info *sta;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07005085 if (is_multicast_ether_addr(mgmt->da))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005086 return;
5087 sta = ap_get_sta(hapd, mgmt->da);
5088 if (!sta) {
5089 wpa_printf(MSG_DEBUG, "handle_deauth_cb: STA " MACSTR
5090 " not found", MAC2STR(mgmt->da));
5091 return;
5092 }
5093 if (ok)
5094 wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged deauth",
5095 MAC2STR(sta->addr));
5096 else
5097 wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
5098 "deauth", MAC2STR(sta->addr));
5099
5100 ap_sta_deauth_cb(hapd, sta);
5101}
5102
5103
5104static void handle_disassoc_cb(struct hostapd_data *hapd,
5105 const struct ieee80211_mgmt *mgmt,
5106 size_t len, int ok)
5107{
5108 struct sta_info *sta;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07005109 if (is_multicast_ether_addr(mgmt->da))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005110 return;
5111 sta = ap_get_sta(hapd, mgmt->da);
5112 if (!sta) {
5113 wpa_printf(MSG_DEBUG, "handle_disassoc_cb: STA " MACSTR
5114 " not found", MAC2STR(mgmt->da));
5115 return;
5116 }
5117 if (ok)
5118 wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged disassoc",
5119 MAC2STR(sta->addr));
5120 else
5121 wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
5122 "disassoc", MAC2STR(sta->addr));
5123
5124 ap_sta_disassoc_cb(hapd, sta);
5125}
5126
5127
Dmitry Shmidt29333592017-01-09 12:27:11 -08005128static void handle_action_cb(struct hostapd_data *hapd,
5129 const struct ieee80211_mgmt *mgmt,
5130 size_t len, int ok)
5131{
5132 struct sta_info *sta;
Paul Stewart092955c2017-02-06 09:13:09 -08005133 const struct rrm_measurement_report_element *report;
Dmitry Shmidt29333592017-01-09 12:27:11 -08005134
5135 if (is_multicast_ether_addr(mgmt->da))
5136 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005137#ifdef CONFIG_DPP
5138 if (len >= IEEE80211_HDRLEN + 6 &&
5139 mgmt->u.action.category == WLAN_ACTION_PUBLIC &&
5140 mgmt->u.action.u.vs_public_action.action ==
5141 WLAN_PA_VENDOR_SPECIFIC &&
5142 WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) ==
5143 OUI_WFA &&
5144 mgmt->u.action.u.vs_public_action.variable[0] ==
5145 DPP_OUI_TYPE) {
5146 const u8 *pos, *end;
5147
5148 pos = &mgmt->u.action.u.vs_public_action.variable[1];
5149 end = ((const u8 *) mgmt) + len;
5150 hostapd_dpp_tx_status(hapd, mgmt->da, pos, end - pos, ok);
5151 return;
5152 }
5153 if (len >= IEEE80211_HDRLEN + 2 &&
5154 mgmt->u.action.category == WLAN_ACTION_PUBLIC &&
5155 (mgmt->u.action.u.public_action.action ==
5156 WLAN_PA_GAS_INITIAL_REQ ||
5157 mgmt->u.action.u.public_action.action ==
5158 WLAN_PA_GAS_COMEBACK_REQ)) {
5159 const u8 *pos, *end;
5160
5161 pos = mgmt->u.action.u.public_action.variable;
5162 end = ((const u8 *) mgmt) + len;
5163 gas_query_ap_tx_status(hapd->gas, mgmt->da, pos, end - pos, ok);
5164 return;
5165 }
5166#endif /* CONFIG_DPP */
Dmitry Shmidt29333592017-01-09 12:27:11 -08005167 sta = ap_get_sta(hapd, mgmt->da);
5168 if (!sta) {
5169 wpa_printf(MSG_DEBUG, "handle_action_cb: STA " MACSTR
5170 " not found", MAC2STR(mgmt->da));
5171 return;
5172 }
5173
Paul Stewart092955c2017-02-06 09:13:09 -08005174 if (len < 24 + 5 + sizeof(*report))
Dmitry Shmidt29333592017-01-09 12:27:11 -08005175 return;
Paul Stewart092955c2017-02-06 09:13:09 -08005176 report = (const struct rrm_measurement_report_element *)
5177 &mgmt->u.action.u.rrm.variable[2];
Dmitry Shmidt29333592017-01-09 12:27:11 -08005178 if (mgmt->u.action.category == WLAN_ACTION_RADIO_MEASUREMENT &&
Paul Stewart092955c2017-02-06 09:13:09 -08005179 mgmt->u.action.u.rrm.action == WLAN_RRM_RADIO_MEASUREMENT_REQUEST &&
5180 report->eid == WLAN_EID_MEASURE_REQUEST &&
5181 report->len >= 3 &&
5182 report->type == MEASURE_TYPE_BEACON)
Dmitry Shmidt29333592017-01-09 12:27:11 -08005183 hostapd_rrm_beacon_req_tx_status(hapd, mgmt, len, ok);
5184}
5185
5186
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005187/**
5188 * ieee802_11_mgmt_cb - Process management frame TX status callback
5189 * @hapd: hostapd BSS data structure (the BSS from which the management frame
5190 * was sent from)
5191 * @buf: management frame data (starting from IEEE 802.11 header)
5192 * @len: length of frame data in octets
5193 * @stype: management frame subtype from frame control field
5194 * @ok: Whether the frame was ACK'ed
5195 */
5196void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len,
5197 u16 stype, int ok)
5198{
5199 const struct ieee80211_mgmt *mgmt;
5200 mgmt = (const struct ieee80211_mgmt *) buf;
5201
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005202#ifdef CONFIG_TESTING_OPTIONS
5203 if (hapd->ext_mgmt_frame_handling) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07005204 size_t hex_len = 2 * len + 1;
5205 char *hex = os_malloc(hex_len);
5206
5207 if (hex) {
5208 wpa_snprintf_hex(hex, hex_len, buf, len);
5209 wpa_msg(hapd->msg_ctx, MSG_INFO,
5210 "MGMT-TX-STATUS stype=%u ok=%d buf=%s",
5211 stype, ok, hex);
5212 os_free(hex);
5213 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08005214 return;
5215 }
5216#endif /* CONFIG_TESTING_OPTIONS */
5217
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005218 switch (stype) {
5219 case WLAN_FC_STYPE_AUTH:
5220 wpa_printf(MSG_DEBUG, "mgmt::auth cb");
5221 handle_auth_cb(hapd, mgmt, len, ok);
5222 break;
5223 case WLAN_FC_STYPE_ASSOC_RESP:
5224 wpa_printf(MSG_DEBUG, "mgmt::assoc_resp cb");
5225 handle_assoc_cb(hapd, mgmt, len, 0, ok);
5226 break;
5227 case WLAN_FC_STYPE_REASSOC_RESP:
5228 wpa_printf(MSG_DEBUG, "mgmt::reassoc_resp cb");
5229 handle_assoc_cb(hapd, mgmt, len, 1, ok);
5230 break;
5231 case WLAN_FC_STYPE_PROBE_RESP:
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005232 wpa_printf(MSG_EXCESSIVE, "mgmt::proberesp cb ok=%d", ok);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005233 break;
5234 case WLAN_FC_STYPE_DEAUTH:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005235 wpa_printf(MSG_DEBUG, "mgmt::deauth cb");
5236 handle_deauth_cb(hapd, mgmt, len, ok);
5237 break;
5238 case WLAN_FC_STYPE_DISASSOC:
5239 wpa_printf(MSG_DEBUG, "mgmt::disassoc cb");
5240 handle_disassoc_cb(hapd, mgmt, len, ok);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005241 break;
5242 case WLAN_FC_STYPE_ACTION:
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08005243 wpa_printf(MSG_DEBUG, "mgmt::action cb ok=%d", ok);
Dmitry Shmidt29333592017-01-09 12:27:11 -08005244 handle_action_cb(hapd, mgmt, len, ok);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005245 break;
5246 default:
Dmitry Shmidtcce06662013-11-04 18:44:24 -08005247 wpa_printf(MSG_INFO, "unknown mgmt cb frame subtype %d", stype);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005248 break;
5249 }
5250}
5251
5252
5253int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
5254{
5255 /* TODO */
5256 return 0;
5257}
5258
5259
5260int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
5261 char *buf, size_t buflen)
5262{
5263 /* TODO */
5264 return 0;
5265}
5266
5267
5268void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
5269 const u8 *buf, size_t len, int ack)
5270{
5271 struct sta_info *sta;
5272 struct hostapd_iface *iface = hapd->iface;
5273
5274 sta = ap_get_sta(hapd, addr);
5275 if (sta == NULL && iface->num_bss > 1) {
5276 size_t j;
5277 for (j = 0; j < iface->num_bss; j++) {
5278 hapd = iface->bss[j];
5279 sta = ap_get_sta(hapd, addr);
5280 if (sta)
5281 break;
5282 }
5283 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005284 if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005285 return;
5286 if (sta->flags & WLAN_STA_PENDING_POLL) {
5287 wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending "
5288 "activity poll", MAC2STR(sta->addr),
5289 ack ? "ACKed" : "did not ACK");
5290 if (ack)
5291 sta->flags &= ~WLAN_STA_PENDING_POLL;
5292 }
5293
5294 ieee802_1x_tx_status(hapd, sta, buf, len, ack);
5295}
5296
5297
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005298void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
5299 const u8 *data, size_t len, int ack)
5300{
5301 struct sta_info *sta;
5302 struct hostapd_iface *iface = hapd->iface;
5303
5304 sta = ap_get_sta(hapd, dst);
5305 if (sta == NULL && iface->num_bss > 1) {
5306 size_t j;
5307 for (j = 0; j < iface->num_bss; j++) {
5308 hapd = iface->bss[j];
5309 sta = ap_get_sta(hapd, dst);
5310 if (sta)
5311 break;
5312 }
5313 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005314 if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
5315 wpa_printf(MSG_DEBUG, "Ignore TX status for Data frame to STA "
5316 MACSTR " that is not currently associated",
5317 MAC2STR(dst));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005318 return;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005319 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005320
5321 ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack);
5322}
5323
5324
5325void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr)
5326{
5327 struct sta_info *sta;
5328 struct hostapd_iface *iface = hapd->iface;
5329
5330 sta = ap_get_sta(hapd, addr);
5331 if (sta == NULL && iface->num_bss > 1) {
5332 size_t j;
5333 for (j = 0; j < iface->num_bss; j++) {
5334 hapd = iface->bss[j];
5335 sta = ap_get_sta(hapd, addr);
5336 if (sta)
5337 break;
5338 }
5339 }
5340 if (sta == NULL)
5341 return;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07005342 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POLL_OK MACSTR,
5343 MAC2STR(sta->addr));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08005344 if (!(sta->flags & WLAN_STA_PENDING_POLL))
5345 return;
5346
5347 wpa_printf(MSG_DEBUG, "STA " MACSTR " ACKed pending "
5348 "activity poll", MAC2STR(sta->addr));
5349 sta->flags &= ~WLAN_STA_PENDING_POLL;
5350}
5351
5352
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005353void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
5354 int wds)
5355{
5356 struct sta_info *sta;
5357
5358 sta = ap_get_sta(hapd, src);
Dmitry Shmidt29333592017-01-09 12:27:11 -08005359 if (sta &&
5360 ((sta->flags & WLAN_STA_ASSOC) ||
5361 ((sta->flags & WLAN_STA_ASSOC_REQ_OK) && wds))) {
Dmitry Shmidtaa532512012-09-24 10:35:31 -07005362 if (!hapd->conf->wds_sta)
5363 return;
5364
Dmitry Shmidt29333592017-01-09 12:27:11 -08005365 if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK)) ==
5366 WLAN_STA_ASSOC_REQ_OK) {
5367 wpa_printf(MSG_DEBUG,
5368 "Postpone 4-address WDS mode enabling for STA "
5369 MACSTR " since TX status for AssocResp is not yet known",
5370 MAC2STR(sta->addr));
5371 sta->pending_wds_enable = 1;
5372 return;
5373 }
5374
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005375 if (wds && !(sta->flags & WLAN_STA_WDS)) {
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005376 int ret;
5377 char ifname_wds[IFNAMSIZ + 1];
5378
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005379 wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for "
5380 "STA " MACSTR " (aid %u)",
5381 MAC2STR(sta->addr), sta->aid);
5382 sta->flags |= WLAN_STA_WDS;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07005383 ret = hostapd_set_wds_sta(hapd, ifname_wds,
5384 sta->addr, sta->aid, 1);
5385 if (!ret)
5386 hostapd_set_wds_encryption(hapd, sta,
5387 ifname_wds);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005388 }
5389 return;
5390 }
5391
5392 wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA "
5393 MACSTR, MAC2STR(src));
Hai Shalomc3565922019-10-28 11:58:20 -07005394 if (is_multicast_ether_addr(src) || is_zero_ether_addr(src) ||
5395 os_memcmp(src, hapd->own_addr, ETH_ALEN) == 0) {
5396 /* Broadcast bit set in SA or unexpected SA?! Ignore the frame
5397 * silently. */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07005398 return;
5399 }
5400
5401 if (sta && (sta->flags & WLAN_STA_ASSOC_REQ_OK)) {
5402 wpa_printf(MSG_DEBUG, "Association Response to the STA has "
5403 "already been sent, but no TX status yet known - "
5404 "ignore Class 3 frame issue with " MACSTR,
5405 MAC2STR(src));
5406 return;
5407 }
5408
5409 if (sta && (sta->flags & WLAN_STA_AUTH))
5410 hostapd_drv_sta_disassoc(
5411 hapd, src,
5412 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
5413 else
5414 hostapd_drv_sta_deauth(
5415 hapd, src,
5416 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
5417}
5418
5419
5420#endif /* CONFIG_NATIVE_WINDOWS */