blob: d8b34fa52b21acbf649e9dc5149015bf5f772234 [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"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070024#include "radius/radius.h"
25#include "radius/radius_client.h"
26#include "p2p/p2p.h"
27#include "wps/wps.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080028#include "fst/fst.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070029#include "hostapd.h"
30#include "beacon.h"
31#include "ieee802_11_auth.h"
32#include "sta_info.h"
33#include "ieee802_1x.h"
34#include "wpa_auth.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080035#include "pmksa_cache_auth.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070036#include "wmm.h"
37#include "ap_list.h"
38#include "accounting.h"
39#include "ap_config.h"
40#include "ap_mlme.h"
41#include "p2p_hostapd.h"
42#include "ap_drv_ops.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080043#include "wnm_ap.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080044#include "hw_features.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070045#include "ieee802_11.h"
Dmitry Shmidtf21452a2014-02-26 10:55:25 -080046#include "dfs.h"
Dmitry Shmidt57c2d392016-02-23 13:40:19 -080047#include "mbo_ap.h"
Dmitry Shmidt849734c2016-05-27 09:59:01 -070048#include "rrm.h"
Dmitry Shmidtaca489e2016-09-28 15:44:14 -070049#include "taxonomy.h"
Dmitry Shmidtebd93af2017-02-21 13:40:44 -080050#include "fils_hlp.h"
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070051#include "dpp_hostapd.h"
52#include "gas_query_ap.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070053
54
Dmitry Shmidtd2986c22017-10-23 14:22:09 -070055#ifdef CONFIG_FILS
56static struct wpabuf *
57prepare_auth_resp_fils(struct hostapd_data *hapd,
58 struct sta_info *sta, u16 *resp,
59 struct rsn_pmksa_cache_entry *pmksa,
60 struct wpabuf *erp_resp,
61 const u8 *msk, size_t msk_len,
62 int *is_pub);
63#endif /* CONFIG_FILS */
64
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070065u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
66{
67 u8 *pos = eid;
68 int i, num, count;
69
70 if (hapd->iface->current_rates == NULL)
71 return eid;
72
73 *pos++ = WLAN_EID_SUPP_RATES;
74 num = hapd->iface->num_rates;
75 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
76 num++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080077 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
78 num++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070079 if (num > 8) {
80 /* rest of the rates are encoded in Extended supported
81 * rates element */
82 num = 8;
83 }
84
85 *pos++ = num;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070086 for (i = 0, count = 0; i < hapd->iface->num_rates && count < num;
87 i++) {
88 count++;
89 *pos = hapd->iface->current_rates[i].rate / 5;
90 if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
91 *pos |= 0x80;
92 pos++;
93 }
94
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080095 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht && count < 8) {
96 count++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070097 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080098 }
99
100 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht && count < 8) {
101 count++;
102 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
103 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700104
105 return pos;
106}
107
108
109u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
110{
111 u8 *pos = eid;
112 int i, num, count;
113
114 if (hapd->iface->current_rates == NULL)
115 return eid;
116
117 num = hapd->iface->num_rates;
118 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
119 num++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800120 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
121 num++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700122 if (num <= 8)
123 return eid;
124 num -= 8;
125
126 *pos++ = WLAN_EID_EXT_SUPP_RATES;
127 *pos++ = num;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700128 for (i = 0, count = 0; i < hapd->iface->num_rates && count < num + 8;
129 i++) {
130 count++;
131 if (count <= 8)
132 continue; /* already in SuppRates IE */
133 *pos = hapd->iface->current_rates[i].rate / 5;
134 if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
135 *pos |= 0x80;
136 pos++;
137 }
138
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800139 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) {
140 count++;
141 if (count > 8)
142 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
143 }
144
145 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) {
146 count++;
147 if (count > 8)
148 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
149 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700150
151 return pos;
152}
153
154
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -0700155u16 hostapd_own_capab_info(struct hostapd_data *hapd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700156{
157 int capab = WLAN_CAPABILITY_ESS;
158 int privacy;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800159 int dfs;
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700160 int i;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800161
162 /* Check if any of configured channels require DFS */
163 dfs = hostapd_is_dfs_required(hapd->iface);
164 if (dfs < 0) {
165 wpa_printf(MSG_WARNING, "Failed to check if DFS is required; ret=%d",
166 dfs);
167 dfs = 0;
168 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700169
170 if (hapd->iface->num_sta_no_short_preamble == 0 &&
171 hapd->iconf->preamble == SHORT_PREAMBLE)
172 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
173
174 privacy = hapd->conf->ssid.wep.keys_set;
175
176 if (hapd->conf->ieee802_1x &&
177 (hapd->conf->default_wep_key_len ||
178 hapd->conf->individual_wep_key_len))
179 privacy = 1;
180
181 if (hapd->conf->wpa)
182 privacy = 1;
183
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800184#ifdef CONFIG_HS20
185 if (hapd->conf->osen)
186 privacy = 1;
187#endif /* CONFIG_HS20 */
188
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700189 if (privacy)
190 capab |= WLAN_CAPABILITY_PRIVACY;
191
192 if (hapd->iface->current_mode &&
193 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
194 hapd->iface->num_sta_no_short_slot_time == 0)
195 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
196
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800197 /*
198 * Currently, Spectrum Management capability bit is set when directly
199 * requested in configuration by spectrum_mgmt_required or when AP is
200 * running on DFS channel.
201 * TODO: Also consider driver support for TPC to set Spectrum Mgmt bit
202 */
203 if (hapd->iface->current_mode &&
204 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
205 (hapd->iconf->spectrum_mgmt_required || dfs))
206 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
207
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700208 for (i = 0; i < RRM_CAPABILITIES_IE_LEN; i++) {
209 if (hapd->conf->radio_measurements[i]) {
210 capab |= IEEE80211_CAP_RRM;
211 break;
212 }
213 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800214
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700215 return capab;
216}
217
218
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800219#ifndef CONFIG_NO_RC4
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700220static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
221 u16 auth_transaction, const u8 *challenge,
222 int iswep)
223{
224 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
225 HOSTAPD_LEVEL_DEBUG,
226 "authentication (shared key, transaction %d)",
227 auth_transaction);
228
229 if (auth_transaction == 1) {
230 if (!sta->challenge) {
231 /* Generate a pseudo-random challenge */
232 u8 key[8];
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800233
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700234 sta->challenge = os_zalloc(WLAN_AUTH_CHALLENGE_LEN);
235 if (sta->challenge == NULL)
236 return WLAN_STATUS_UNSPECIFIED_FAILURE;
237
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800238 if (os_get_random(key, sizeof(key)) < 0) {
239 os_free(sta->challenge);
240 sta->challenge = NULL;
241 return WLAN_STATUS_UNSPECIFIED_FAILURE;
242 }
243
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700244 rc4_skip(key, sizeof(key), 0,
245 sta->challenge, WLAN_AUTH_CHALLENGE_LEN);
246 }
247 return 0;
248 }
249
250 if (auth_transaction != 3)
251 return WLAN_STATUS_UNSPECIFIED_FAILURE;
252
253 /* Transaction 3 */
254 if (!iswep || !sta->challenge || !challenge ||
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700255 os_memcmp_const(sta->challenge, challenge,
256 WLAN_AUTH_CHALLENGE_LEN)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700257 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
258 HOSTAPD_LEVEL_INFO,
259 "shared key authentication - invalid "
260 "challenge-response");
261 return WLAN_STATUS_CHALLENGE_FAIL;
262 }
263
264 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
265 HOSTAPD_LEVEL_DEBUG,
266 "authentication OK (shared key)");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700267 sta->flags |= WLAN_STA_AUTH;
268 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700269 os_free(sta->challenge);
270 sta->challenge = NULL;
271
272 return 0;
273}
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800274#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700275
276
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800277static int send_auth_reply(struct hostapd_data *hapd,
278 const u8 *dst, const u8 *bssid,
279 u16 auth_alg, u16 auth_transaction, u16 resp,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700280 const u8 *ies, size_t ies_len, const char *dbg)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700281{
282 struct ieee80211_mgmt *reply;
283 u8 *buf;
284 size_t rlen;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800285 int reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700286
287 rlen = IEEE80211_HDRLEN + sizeof(reply->u.auth) + ies_len;
288 buf = os_zalloc(rlen);
289 if (buf == NULL)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800290 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700291
292 reply = (struct ieee80211_mgmt *) buf;
293 reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
294 WLAN_FC_STYPE_AUTH);
295 os_memcpy(reply->da, dst, ETH_ALEN);
296 os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
297 os_memcpy(reply->bssid, bssid, ETH_ALEN);
298
299 reply->u.auth.auth_alg = host_to_le16(auth_alg);
300 reply->u.auth.auth_transaction = host_to_le16(auth_transaction);
301 reply->u.auth.status_code = host_to_le16(resp);
302
303 if (ies && ies_len)
304 os_memcpy(reply->u.auth.variable, ies, ies_len);
305
306 wpa_printf(MSG_DEBUG, "authentication reply: STA=" MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700307 " auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu) (dbg=%s)",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700308 MAC2STR(dst), auth_alg, auth_transaction,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700309 resp, (unsigned long) ies_len, dbg);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800310 if (hostapd_drv_send_mlme(hapd, reply, rlen, 0) < 0)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800311 wpa_printf(MSG_INFO, "send_auth_reply: send failed");
312 else
313 reply_res = WLAN_STATUS_SUCCESS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700314
315 os_free(buf);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800316
317 return reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700318}
319
320
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800321#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700322static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
323 u16 auth_transaction, u16 status,
324 const u8 *ies, size_t ies_len)
325{
326 struct hostapd_data *hapd = ctx;
327 struct sta_info *sta;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800328 int reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700329
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800330 reply_res = send_auth_reply(hapd, dst, bssid, WLAN_AUTH_FT,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700331 auth_transaction, status, ies, ies_len,
332 "auth-ft-finish");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700333
334 sta = ap_get_sta(hapd, dst);
335 if (sta == NULL)
336 return;
337
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800338 if (sta->added_unassoc && (reply_res != WLAN_STATUS_SUCCESS ||
339 status != WLAN_STATUS_SUCCESS)) {
340 hostapd_drv_sta_remove(hapd, sta->addr);
341 sta->added_unassoc = 0;
342 return;
343 }
344
345 if (status != WLAN_STATUS_SUCCESS)
346 return;
347
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700348 hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211,
349 HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)");
350 sta->flags |= WLAN_STA_AUTH;
351 mlme_authenticate_indication(hapd, sta);
352}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800353#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700354
355
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800356#ifdef CONFIG_SAE
357
Roshan Pius3a1667e2018-07-03 15:17:14 -0700358static void sae_set_state(struct sta_info *sta, enum sae_state state,
359 const char *reason)
360{
361 wpa_printf(MSG_DEBUG, "SAE: State %s -> %s for peer " MACSTR " (%s)",
362 sae_state_txt(sta->sae->state), sae_state_txt(state),
363 MAC2STR(sta->addr), reason);
364 sta->sae->state = state;
365}
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800366
367
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800368static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
369 struct sta_info *sta, int update)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800370{
371 struct wpabuf *buf;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700372 const char *password = NULL;
373 struct sae_password_entry *pw;
374 const char *rx_id = NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800375
Roshan Pius3a1667e2018-07-03 15:17:14 -0700376 if (sta->sae->tmp)
377 rx_id = sta->sae->tmp->pw_id;
378
379 for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
380 if (!is_broadcast_ether_addr(pw->peer_addr) &&
381 os_memcmp(pw->peer_addr, sta->addr, ETH_ALEN) != 0)
382 continue;
383 if ((rx_id && !pw->identifier) || (!rx_id && pw->identifier))
384 continue;
385 if (rx_id && pw->identifier &&
386 os_strcmp(rx_id, pw->identifier) != 0)
387 continue;
388 password = pw->password;
389 break;
390 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700391 if (!password)
392 password = hapd->conf->ssid.wpa_passphrase;
393 if (!password) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800394 wpa_printf(MSG_DEBUG, "SAE: No password available");
395 return NULL;
396 }
397
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800398 if (update &&
399 sae_prepare_commit(hapd->own_addr, sta->addr,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700400 (u8 *) password, os_strlen(password), rx_id,
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800401 sta->sae) < 0) {
402 wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
403 return NULL;
404 }
405
Roshan Pius3a1667e2018-07-03 15:17:14 -0700406 buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN +
407 (rx_id ? 3 + os_strlen(rx_id) : 0));
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800408 if (buf == NULL)
409 return NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800410 sae_write_commit(sta->sae, buf, sta->sae->tmp ?
Roshan Pius3a1667e2018-07-03 15:17:14 -0700411 sta->sae->tmp->anti_clogging_token : NULL, rx_id);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800412
413 return buf;
414}
415
416
417static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
418 struct sta_info *sta)
419{
420 struct wpabuf *buf;
421
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800422 buf = wpabuf_alloc(SAE_CONFIRM_MAX_LEN);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800423 if (buf == NULL)
424 return NULL;
425
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800426 sae_write_confirm(sta->sae, buf);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800427
428 return buf;
429}
430
431
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800432static int auth_sae_send_commit(struct hostapd_data *hapd,
433 struct sta_info *sta,
434 const u8 *bssid, int update)
435{
436 struct wpabuf *data;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800437 int reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800438
439 data = auth_build_sae_commit(hapd, sta, update);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700440 if (!data && sta->sae->tmp && sta->sae->tmp->pw_id)
441 return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800442 if (data == NULL)
443 return WLAN_STATUS_UNSPECIFIED_FAILURE;
444
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800445 reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 1,
446 WLAN_STATUS_SUCCESS, wpabuf_head(data),
Roshan Pius3a1667e2018-07-03 15:17:14 -0700447 wpabuf_len(data), "sae-send-commit");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800448
449 wpabuf_free(data);
450
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800451 return reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800452}
453
454
455static int auth_sae_send_confirm(struct hostapd_data *hapd,
456 struct sta_info *sta,
457 const u8 *bssid)
458{
459 struct wpabuf *data;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800460 int reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800461
462 data = auth_build_sae_confirm(hapd, sta);
463 if (data == NULL)
464 return WLAN_STATUS_UNSPECIFIED_FAILURE;
465
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800466 reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 2,
467 WLAN_STATUS_SUCCESS, wpabuf_head(data),
Roshan Pius3a1667e2018-07-03 15:17:14 -0700468 wpabuf_len(data), "sae-send-confirm");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800469
470 wpabuf_free(data);
471
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800472 return reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800473}
474
475
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800476static int use_sae_anti_clogging(struct hostapd_data *hapd)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800477{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800478 struct sta_info *sta;
479 unsigned int open = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800480
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800481 if (hapd->conf->sae_anti_clogging_threshold == 0)
482 return 1;
483
484 for (sta = hapd->sta_list; sta; sta = sta->next) {
485 if (!sta->sae)
486 continue;
487 if (sta->sae->state != SAE_COMMITTED &&
488 sta->sae->state != SAE_CONFIRMED)
489 continue;
490 open++;
491 if (open >= hapd->conf->sae_anti_clogging_threshold)
492 return 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800493 }
494
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800495 return 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800496}
497
498
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800499static int check_sae_token(struct hostapd_data *hapd, const u8 *addr,
500 const u8 *token, size_t token_len)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800501{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800502 u8 mac[SHA256_MAC_LEN];
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800503
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800504 if (token_len != SHA256_MAC_LEN)
505 return -1;
506 if (hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
507 addr, ETH_ALEN, mac) < 0 ||
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700508 os_memcmp_const(token, mac, SHA256_MAC_LEN) != 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800509 return -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800510
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800511 return 0;
512}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800513
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800514
515static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800516 int group, const u8 *addr)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800517{
518 struct wpabuf *buf;
519 u8 *token;
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800520 struct os_reltime now;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800521
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800522 os_get_reltime(&now);
523 if (!os_reltime_initialized(&hapd->last_sae_token_key_update) ||
524 os_reltime_expired(&now, &hapd->last_sae_token_key_update, 60)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800525 if (random_get_bytes(hapd->sae_token_key,
526 sizeof(hapd->sae_token_key)) < 0)
527 return NULL;
528 wpa_hexdump(MSG_DEBUG, "SAE: Updated token key",
529 hapd->sae_token_key, sizeof(hapd->sae_token_key));
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800530 hapd->last_sae_token_key_update = now;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800531 }
532
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800533 buf = wpabuf_alloc(sizeof(le16) + SHA256_MAC_LEN);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800534 if (buf == NULL)
535 return NULL;
536
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800537 wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
538
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800539 token = wpabuf_put(buf, SHA256_MAC_LEN);
540 hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
541 addr, ETH_ALEN, token);
542
543 return buf;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800544}
545
546
Roshan Pius3a1667e2018-07-03 15:17:14 -0700547static int sae_check_big_sync(struct hostapd_data *hapd, struct sta_info *sta)
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800548{
Roshan Pius3a1667e2018-07-03 15:17:14 -0700549 if (sta->sae->sync > hapd->conf->sae_sync) {
550 sae_set_state(sta, SAE_NOTHING, "Sync > dot11RSNASAESync");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800551 sta->sae->sync = 0;
552 return -1;
553 }
554 return 0;
555}
556
557
558static void auth_sae_retransmit_timer(void *eloop_ctx, void *eloop_data)
559{
560 struct hostapd_data *hapd = eloop_ctx;
561 struct sta_info *sta = eloop_data;
562 int ret;
563
Roshan Pius3a1667e2018-07-03 15:17:14 -0700564 if (sae_check_big_sync(hapd, sta))
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800565 return;
566 sta->sae->sync++;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700567 wpa_printf(MSG_DEBUG, "SAE: Auth SAE retransmit timer for " MACSTR
Roshan Pius3a1667e2018-07-03 15:17:14 -0700568 " (sync=%d state=%s)",
569 MAC2STR(sta->addr), sta->sae->sync,
570 sae_state_txt(sta->sae->state));
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800571
572 switch (sta->sae->state) {
573 case SAE_COMMITTED:
574 ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800575 eloop_register_timeout(0,
576 hapd->dot11RSNASAERetransPeriod * 1000,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800577 auth_sae_retransmit_timer, hapd, sta);
578 break;
579 case SAE_CONFIRMED:
580 ret = auth_sae_send_confirm(hapd, sta, hapd->own_addr);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800581 eloop_register_timeout(0,
582 hapd->dot11RSNASAERetransPeriod * 1000,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800583 auth_sae_retransmit_timer, hapd, sta);
584 break;
585 default:
586 ret = -1;
587 break;
588 }
589
590 if (ret != WLAN_STATUS_SUCCESS)
591 wpa_printf(MSG_INFO, "SAE: Failed to retransmit: ret=%d", ret);
592}
593
594
595void sae_clear_retransmit_timer(struct hostapd_data *hapd, struct sta_info *sta)
596{
597 eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta);
598}
599
600
601static void sae_set_retransmit_timer(struct hostapd_data *hapd,
602 struct sta_info *sta)
603{
604 if (!(hapd->conf->mesh & MESH_ENABLED))
605 return;
606
607 eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800608 eloop_register_timeout(0, hapd->dot11RSNASAERetransPeriod * 1000,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800609 auth_sae_retransmit_timer, hapd, sta);
610}
611
612
Dmitry Shmidte4663042016-04-04 10:07:49 -0700613void sae_accept_sta(struct hostapd_data *hapd, struct sta_info *sta)
614{
615 sta->flags |= WLAN_STA_AUTH;
616 sta->auth_alg = WLAN_AUTH_SAE;
617 mlme_authenticate_indication(hapd, sta);
618 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700619 sae_set_state(sta, SAE_ACCEPTED, "Accept Confirm");
Dmitry Shmidte4663042016-04-04 10:07:49 -0700620 wpa_auth_pmksa_add_sae(hapd->wpa_auth, sta->addr,
621 sta->sae->pmk, sta->sae->pmkid);
622}
623
624
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800625static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
626 const u8 *bssid, u8 auth_transaction)
627{
628 int ret;
629
630 if (auth_transaction != 1 && auth_transaction != 2)
631 return WLAN_STATUS_UNSPECIFIED_FAILURE;
632
Roshan Pius3a1667e2018-07-03 15:17:14 -0700633 wpa_printf(MSG_DEBUG, "SAE: Peer " MACSTR " state=%s auth_trans=%u",
634 MAC2STR(sta->addr), sae_state_txt(sta->sae->state),
635 auth_transaction);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800636 switch (sta->sae->state) {
637 case SAE_NOTHING:
638 if (auth_transaction == 1) {
639 ret = auth_sae_send_commit(hapd, sta, bssid, 1);
640 if (ret)
641 return ret;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700642 sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800643
644 if (sae_process_commit(sta->sae) < 0)
645 return WLAN_STATUS_UNSPECIFIED_FAILURE;
646
647 /*
648 * In mesh case, both Commit and Confirm can be sent
649 * immediately. In infrastructure BSS, only a single
650 * Authentication frame (Commit) is expected from the AP
651 * here and the second one (Confirm) will be sent once
652 * the STA has sent its second Authentication frame
653 * (Confirm).
654 */
655 if (hapd->conf->mesh & MESH_ENABLED) {
656 /*
657 * Send both Commit and Confirm immediately
658 * based on SAE finite state machine
659 * Nothing -> Confirm transition.
660 */
661 ret = auth_sae_send_confirm(hapd, sta, bssid);
662 if (ret)
663 return ret;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700664 sae_set_state(sta, SAE_CONFIRMED,
665 "Sent Confirm (mesh)");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800666 } else {
667 /*
668 * For infrastructure BSS, send only the Commit
669 * message now to get alternating sequence of
670 * Authentication frames between the AP and STA.
671 * Confirm will be sent in
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800672 * Committed -> Confirmed/Accepted transition
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800673 * when receiving Confirm from STA.
674 */
675 }
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800676 sta->sae->sync = 0;
677 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800678 } else {
679 hostapd_logger(hapd, sta->addr,
680 HOSTAPD_MODULE_IEEE80211,
681 HOSTAPD_LEVEL_DEBUG,
682 "SAE confirm before commit");
683 }
684 break;
685 case SAE_COMMITTED:
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800686 sae_clear_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800687 if (auth_transaction == 1) {
688 if (sae_process_commit(sta->sae) < 0)
689 return WLAN_STATUS_UNSPECIFIED_FAILURE;
690
691 ret = auth_sae_send_confirm(hapd, sta, bssid);
692 if (ret)
693 return ret;
Roshan Pius3a1667e2018-07-03 15:17:14 -0700694 sae_set_state(sta, SAE_CONFIRMED, "Sent Confirm");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800695 sta->sae->sync = 0;
696 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800697 } else if (hapd->conf->mesh & MESH_ENABLED) {
698 /*
699 * In mesh case, follow SAE finite state machine and
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800700 * send Commit now, if sync count allows.
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800701 */
Roshan Pius3a1667e2018-07-03 15:17:14 -0700702 if (sae_check_big_sync(hapd, sta))
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800703 return WLAN_STATUS_SUCCESS;
704 sta->sae->sync++;
705
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700706 ret = auth_sae_send_commit(hapd, sta, bssid, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800707 if (ret)
708 return ret;
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800709
710 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800711 } else {
712 /*
713 * For instructure BSS, send the postponed Confirm from
714 * Nothing -> Confirmed transition that was reduced to
715 * Nothing -> Committed above.
716 */
717 ret = auth_sae_send_confirm(hapd, sta, bssid);
718 if (ret)
719 return ret;
720
Roshan Pius3a1667e2018-07-03 15:17:14 -0700721 sae_set_state(sta, SAE_CONFIRMED, "Sent Confirm");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800722
723 /*
724 * Since this was triggered on Confirm RX, run another
725 * step to get to Accepted without waiting for
726 * additional events.
727 */
728 return sae_sm_step(hapd, sta, bssid, auth_transaction);
729 }
730 break;
731 case SAE_CONFIRMED:
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800732 sae_clear_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800733 if (auth_transaction == 1) {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700734 if (sae_check_big_sync(hapd, sta))
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800735 return WLAN_STATUS_SUCCESS;
736 sta->sae->sync++;
737
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800738 ret = auth_sae_send_commit(hapd, sta, bssid, 1);
739 if (ret)
740 return ret;
741
742 if (sae_process_commit(sta->sae) < 0)
743 return WLAN_STATUS_UNSPECIFIED_FAILURE;
744
745 ret = auth_sae_send_confirm(hapd, sta, bssid);
746 if (ret)
747 return ret;
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800748
749 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800750 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700751 sta->sae->send_confirm = 0xffff;
Dmitry Shmidte4663042016-04-04 10:07:49 -0700752 sae_accept_sta(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800753 }
754 break;
755 case SAE_ACCEPTED:
Roshan Pius3a1667e2018-07-03 15:17:14 -0700756 if (auth_transaction == 1 &&
757 (hapd->conf->mesh & MESH_ENABLED)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800758 wpa_printf(MSG_DEBUG, "SAE: remove the STA (" MACSTR
759 ") doing reauthentication",
760 MAC2STR(sta->addr));
761 ap_free_sta(hapd, sta);
Dmitry Shmidte4663042016-04-04 10:07:49 -0700762 wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
Roshan Pius3a1667e2018-07-03 15:17:14 -0700763 } else if (auth_transaction == 1) {
764 wpa_printf(MSG_DEBUG, "SAE: Start reauthentication");
765 ret = auth_sae_send_commit(hapd, sta, bssid, 1);
766 if (ret)
767 return ret;
768 sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
769
770 if (sae_process_commit(sta->sae) < 0)
771 return WLAN_STATUS_UNSPECIFIED_FAILURE;
772 sta->sae->sync = 0;
773 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800774 } else {
Roshan Pius3a1667e2018-07-03 15:17:14 -0700775 if (sae_check_big_sync(hapd, sta))
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800776 return WLAN_STATUS_SUCCESS;
777 sta->sae->sync++;
778
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800779 ret = auth_sae_send_confirm(hapd, sta, bssid);
780 sae_clear_temp_data(sta->sae);
781 if (ret)
782 return ret;
783 }
784 break;
785 default:
786 wpa_printf(MSG_ERROR, "SAE: invalid state %d",
787 sta->sae->state);
788 return WLAN_STATUS_UNSPECIFIED_FAILURE;
789 }
790 return WLAN_STATUS_SUCCESS;
791}
792
793
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700794static void sae_pick_next_group(struct hostapd_data *hapd, struct sta_info *sta)
795{
796 struct sae_data *sae = sta->sae;
797 int i, *groups = hapd->conf->sae_groups;
798
799 if (sae->state != SAE_COMMITTED)
800 return;
801
802 wpa_printf(MSG_DEBUG, "SAE: Previously selected group: %d", sae->group);
803
804 for (i = 0; groups && groups[i] > 0; i++) {
805 if (sae->group == groups[i])
806 break;
807 }
808
809 if (!groups || groups[i] <= 0) {
810 wpa_printf(MSG_DEBUG,
811 "SAE: Previously selected group not found from the current configuration");
812 return;
813 }
814
815 for (;;) {
816 i++;
817 if (groups[i] <= 0) {
818 wpa_printf(MSG_DEBUG,
819 "SAE: No alternative group enabled");
820 return;
821 }
822
823 if (sae_set_group(sae, groups[i]) < 0)
824 continue;
825
826 break;
827 }
828 wpa_printf(MSG_DEBUG, "SAE: Selected new group: %d", groups[i]);
829}
830
831
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800832static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
833 const struct ieee80211_mgmt *mgmt, size_t len,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800834 u16 auth_transaction, u16 status_code)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800835{
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800836 int resp = WLAN_STATUS_SUCCESS;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800837 struct wpabuf *data = NULL;
838
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700839#ifdef CONFIG_TESTING_OPTIONS
840 if (hapd->conf->sae_reflection_attack && auth_transaction == 1) {
841 const u8 *pos, *end;
842
843 wpa_printf(MSG_DEBUG, "SAE: TESTING - reflection attack");
844 pos = mgmt->u.auth.variable;
845 end = ((const u8 *) mgmt) + len;
846 send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
Roshan Pius3a1667e2018-07-03 15:17:14 -0700847 auth_transaction, resp, pos, end - pos,
848 "auth-sae-reflection-attack");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700849 goto remove_sta;
850 }
851
852 if (hapd->conf->sae_commit_override && auth_transaction == 1) {
853 wpa_printf(MSG_DEBUG, "SAE: TESTING - commit override");
854 send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
855 auth_transaction, resp,
856 wpabuf_head(hapd->conf->sae_commit_override),
Roshan Pius3a1667e2018-07-03 15:17:14 -0700857 wpabuf_len(hapd->conf->sae_commit_override),
858 "sae-commit-override");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700859 goto remove_sta;
860 }
861#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800862 if (!sta->sae) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800863 if (auth_transaction != 1 ||
864 status_code != WLAN_STATUS_SUCCESS) {
865 resp = -1;
866 goto remove_sta;
867 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800868 sta->sae = os_zalloc(sizeof(*sta->sae));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800869 if (!sta->sae) {
870 resp = -1;
871 goto remove_sta;
872 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700873 sae_set_state(sta, SAE_NOTHING, "Init");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800874 sta->sae->sync = 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800875 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800876
Dmitry Shmidte4663042016-04-04 10:07:49 -0700877 if (sta->mesh_sae_pmksa_caching) {
878 wpa_printf(MSG_DEBUG,
879 "SAE: Cancel use of mesh PMKSA caching because peer starts SAE authentication");
880 wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
881 sta->mesh_sae_pmksa_caching = 0;
882 }
883
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800884 if (auth_transaction == 1) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800885 const u8 *token = NULL, *pos, *end;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800886 size_t token_len = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800887 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
888 HOSTAPD_LEVEL_DEBUG,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800889 "start SAE authentication (RX commit, status=%u)",
890 status_code);
891
892 if ((hapd->conf->mesh & MESH_ENABLED) &&
893 status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
894 sta->sae->tmp) {
895 pos = mgmt->u.auth.variable;
896 end = ((const u8 *) mgmt) + len;
897 if (pos + sizeof(le16) > end) {
898 wpa_printf(MSG_ERROR,
899 "SAE: Too short anti-clogging token request");
900 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
901 goto reply;
902 }
903 resp = sae_group_allowed(sta->sae,
904 hapd->conf->sae_groups,
905 WPA_GET_LE16(pos));
906 if (resp != WLAN_STATUS_SUCCESS) {
907 wpa_printf(MSG_ERROR,
908 "SAE: Invalid group in anti-clogging token request");
909 goto reply;
910 }
911 pos += sizeof(le16);
912
913 wpabuf_free(sta->sae->tmp->anti_clogging_token);
914 sta->sae->tmp->anti_clogging_token =
915 wpabuf_alloc_copy(pos, end - pos);
916 if (sta->sae->tmp->anti_clogging_token == NULL) {
917 wpa_printf(MSG_ERROR,
918 "SAE: Failed to alloc for anti-clogging token");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800919 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
920 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800921 }
922
923 /*
924 * IEEE Std 802.11-2012, 11.3.8.6.4: If the Status code
925 * is 76, a new Commit Message shall be constructed
926 * with the Anti-Clogging Token from the received
927 * Authentication frame, and the commit-scalar and
928 * COMMIT-ELEMENT previously sent.
929 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800930 resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 0);
931 if (resp != WLAN_STATUS_SUCCESS) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800932 wpa_printf(MSG_ERROR,
933 "SAE: Failed to send commit message");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800934 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800935 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700936 sae_set_state(sta, SAE_COMMITTED,
937 "Sent Commit (anti-clogging token case in mesh)");
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800938 sta->sae->sync = 0;
939 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800940 return;
941 }
942
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700943 if ((hapd->conf->mesh & MESH_ENABLED) &&
944 status_code ==
945 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
946 sta->sae->tmp) {
947 wpa_printf(MSG_DEBUG,
948 "SAE: Peer did not accept our SAE group");
949 sae_pick_next_group(hapd, sta);
950 goto remove_sta;
951 }
952
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800953 if (status_code != WLAN_STATUS_SUCCESS)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800954 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800955
Roshan Pius3a1667e2018-07-03 15:17:14 -0700956 if (!(hapd->conf->mesh & MESH_ENABLED) &&
957 sta->sae->state == SAE_COMMITTED) {
958 /* This is needed in the infrastructure BSS case to
959 * address a sequence where a STA entry may remain in
960 * hostapd across two attempts to do SAE authentication
961 * by the same STA. The second attempt may end up trying
962 * to use a different group and that would not be
963 * allowed if we remain in Committed state with the
964 * previously set parameters. */
965 sae_set_state(sta, SAE_NOTHING,
966 "Clear existing state to allow restart");
967 sae_clear_data(sta->sae);
968 }
969
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800970 resp = sae_parse_commit(sta->sae, mgmt->u.auth.variable,
971 ((const u8 *) mgmt) + len -
972 mgmt->u.auth.variable, &token,
973 &token_len, hapd->conf->sae_groups);
Dmitry Shmidt41712582015-06-29 11:02:15 -0700974 if (resp == SAE_SILENTLY_DISCARD) {
975 wpa_printf(MSG_DEBUG,
976 "SAE: Drop commit message from " MACSTR " due to reflection attack",
977 MAC2STR(sta->addr));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800978 goto remove_sta;
Dmitry Shmidt41712582015-06-29 11:02:15 -0700979 }
Roshan Pius3a1667e2018-07-03 15:17:14 -0700980
981 if (resp == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER) {
982 wpa_msg(hapd->msg_ctx, MSG_INFO,
983 WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER
984 MACSTR, MAC2STR(sta->addr));
985 sae_clear_retransmit_timer(hapd, sta);
986 sae_set_state(sta, SAE_NOTHING,
987 "Unknown Password Identifier");
988 goto remove_sta;
989 }
990
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800991 if (token && check_sae_token(hapd, sta->addr, token, token_len)
992 < 0) {
993 wpa_printf(MSG_DEBUG, "SAE: Drop commit message with "
994 "incorrect token from " MACSTR,
995 MAC2STR(sta->addr));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800996 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
997 goto remove_sta;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800998 }
999
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001000 if (resp != WLAN_STATUS_SUCCESS)
1001 goto reply;
1002
1003 if (!token && use_sae_anti_clogging(hapd)) {
1004 wpa_printf(MSG_DEBUG,
1005 "SAE: Request anti-clogging token from "
1006 MACSTR, MAC2STR(sta->addr));
1007 data = auth_build_token_req(hapd, sta->sae->group,
1008 sta->addr);
1009 resp = WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ;
1010 if (hapd->conf->mesh & MESH_ENABLED)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001011 sae_set_state(sta, SAE_NOTHING,
1012 "Request anti-clogging token case in mesh");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001013 goto reply;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001014 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001015
1016 resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001017 } else if (auth_transaction == 2) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001018 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1019 HOSTAPD_LEVEL_DEBUG,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001020 "SAE authentication (RX confirm, status=%u)",
1021 status_code);
1022 if (status_code != WLAN_STATUS_SUCCESS)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001023 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001024 if (sta->sae->state >= SAE_CONFIRMED ||
1025 !(hapd->conf->mesh & MESH_ENABLED)) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001026 const u8 *var;
1027 size_t var_len;
1028 u16 peer_send_confirm;
1029
1030 var = mgmt->u.auth.variable;
1031 var_len = ((u8 *) mgmt) + len - mgmt->u.auth.variable;
1032 if (var_len < 2) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001033 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001034 goto reply;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001035 }
Roshan Pius3a1667e2018-07-03 15:17:14 -07001036
1037 peer_send_confirm = WPA_GET_LE16(var);
1038
1039 if (sta->sae->state == SAE_ACCEPTED &&
1040 (peer_send_confirm <= sta->sae->rc ||
1041 peer_send_confirm == 0xffff)) {
1042 wpa_printf(MSG_DEBUG,
1043 "SAE: Silently ignore unexpected Confirm from peer "
1044 MACSTR
1045 " (peer-send-confirm=%u Rc=%u)",
1046 MAC2STR(sta->addr),
1047 peer_send_confirm, sta->sae->rc);
1048 return;
1049 }
1050
1051 if (sae_check_confirm(sta->sae, var, var_len) < 0) {
1052 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1053 goto reply;
1054 }
1055 sta->sae->rc = peer_send_confirm;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001056 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001057 resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001058 } else {
1059 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1060 HOSTAPD_LEVEL_DEBUG,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001061 "unexpected SAE authentication transaction %u (status=%u)",
1062 auth_transaction, status_code);
1063 if (status_code != WLAN_STATUS_SUCCESS)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001064 goto remove_sta;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001065 resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1066 }
1067
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001068reply:
1069 if (resp != WLAN_STATUS_SUCCESS) {
1070 send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
1071 auth_transaction, resp,
1072 data ? wpabuf_head(data) : (u8 *) "",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001073 data ? wpabuf_len(data) : 0, "auth-sae");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001074 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001075
1076remove_sta:
1077 if (sta->added_unassoc && (resp != WLAN_STATUS_SUCCESS ||
1078 status_code != WLAN_STATUS_SUCCESS)) {
1079 hostapd_drv_sta_remove(hapd, sta->addr);
1080 sta->added_unassoc = 0;
1081 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001082 wpabuf_free(data);
1083}
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001084
1085
1086/**
1087 * auth_sae_init_committed - Send COMMIT and start SAE in committed state
1088 * @hapd: BSS data for the device initiating the authentication
1089 * @sta: the peer to which commit authentication frame is sent
1090 *
1091 * This function implements Init event handling (IEEE Std 802.11-2012,
1092 * 11.3.8.6.3) in which initial COMMIT message is sent. Prior to calling, the
1093 * sta->sae structure should be initialized appropriately via a call to
1094 * sae_prepare_commit().
1095 */
1096int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta)
1097{
1098 int ret;
1099
1100 if (!sta->sae || !sta->sae->tmp)
1101 return -1;
1102
1103 if (sta->sae->state != SAE_NOTHING)
1104 return -1;
1105
1106 ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
1107 if (ret)
1108 return -1;
1109
Roshan Pius3a1667e2018-07-03 15:17:14 -07001110 sae_set_state(sta, SAE_COMMITTED, "Init and sent commit");
Dmitry Shmidtff787d52015-01-12 13:01:47 -08001111 sta->sae->sync = 0;
1112 sae_set_retransmit_timer(hapd, sta);
1113
1114 return 0;
1115}
1116
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001117#endif /* CONFIG_SAE */
1118
1119
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001120static u16 wpa_res_to_status_code(int res)
1121{
1122 if (res == WPA_INVALID_GROUP)
1123 return WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
1124 if (res == WPA_INVALID_PAIRWISE)
1125 return WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1126 if (res == WPA_INVALID_AKMP)
1127 return WLAN_STATUS_AKMP_NOT_VALID;
1128 if (res == WPA_ALLOC_FAIL)
1129 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1130#ifdef CONFIG_IEEE80211W
1131 if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
1132 return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
1133 if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
Roshan Pius3a1667e2018-07-03 15:17:14 -07001134 return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001135#endif /* CONFIG_IEEE80211W */
1136 if (res == WPA_INVALID_MDIE)
1137 return WLAN_STATUS_INVALID_MDIE;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001138 if (res == WPA_INVALID_PMKID)
1139 return WLAN_STATUS_INVALID_PMKID;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001140 if (res != WPA_IE_OK)
1141 return WLAN_STATUS_INVALID_IE;
1142 return WLAN_STATUS_SUCCESS;
1143}
1144
1145
1146#ifdef CONFIG_FILS
1147
1148static void handle_auth_fils_finish(struct hostapd_data *hapd,
1149 struct sta_info *sta, u16 resp,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001150 struct wpabuf *data, int pub);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001151
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001152void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
1153 const u8 *pos, size_t len, u16 auth_alg,
1154 u16 auth_transaction, u16 status_code,
1155 void (*cb)(struct hostapd_data *hapd,
1156 struct sta_info *sta, u16 resp,
1157 struct wpabuf *data, int pub))
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001158{
1159 u16 resp = WLAN_STATUS_SUCCESS;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001160 const u8 *end;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001161 struct ieee802_11_elems elems;
1162 int res;
1163 struct wpa_ie_data rsn;
1164 struct rsn_pmksa_cache_entry *pmksa = NULL;
1165
1166 if (auth_transaction != 1 || status_code != WLAN_STATUS_SUCCESS)
1167 return;
1168
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001169 end = pos + len;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001170
1171 wpa_hexdump(MSG_DEBUG, "FILS: Authentication frame fields",
1172 pos, end - pos);
1173
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001174 /* TODO: FILS PK */
1175#ifdef CONFIG_FILS_SK_PFS
1176 if (auth_alg == WLAN_AUTH_FILS_SK_PFS) {
1177 u16 group;
1178 struct wpabuf *pub;
1179 size_t elem_len;
1180
1181 /* Using FILS PFS */
1182
1183 /* Finite Cyclic Group */
1184 if (end - pos < 2) {
1185 wpa_printf(MSG_DEBUG,
1186 "FILS: No room for Finite Cyclic Group");
1187 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1188 goto fail;
1189 }
1190 group = WPA_GET_LE16(pos);
1191 pos += 2;
1192 if (group != hapd->conf->fils_dh_group) {
1193 wpa_printf(MSG_DEBUG,
1194 "FILS: Unsupported Finite Cyclic Group: %u (expected %u)",
1195 group, hapd->conf->fils_dh_group);
1196 resp = WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1197 goto fail;
1198 }
1199
1200 crypto_ecdh_deinit(sta->fils_ecdh);
1201 sta->fils_ecdh = crypto_ecdh_init(group);
1202 if (!sta->fils_ecdh) {
1203 wpa_printf(MSG_INFO,
1204 "FILS: Could not initialize ECDH with group %d",
1205 group);
1206 resp = WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
1207 goto fail;
1208 }
1209
1210 pub = crypto_ecdh_get_pubkey(sta->fils_ecdh, 1);
1211 if (!pub) {
1212 wpa_printf(MSG_DEBUG,
1213 "FILS: Failed to derive ECDH public key");
1214 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1215 goto fail;
1216 }
1217 elem_len = wpabuf_len(pub);
1218 wpabuf_free(pub);
1219
1220 /* Element */
1221 if ((size_t) (end - pos) < elem_len) {
1222 wpa_printf(MSG_DEBUG, "FILS: No room for Element");
1223 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1224 goto fail;
1225 }
1226
1227 wpabuf_free(sta->fils_g_sta);
1228 sta->fils_g_sta = wpabuf_alloc_copy(pos, elem_len);
1229 wpabuf_clear_free(sta->fils_dh_ss);
1230 sta->fils_dh_ss = crypto_ecdh_set_peerkey(sta->fils_ecdh, 1,
1231 pos, elem_len);
1232 if (!sta->fils_dh_ss) {
1233 wpa_printf(MSG_DEBUG, "FILS: ECDH operation failed");
1234 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1235 goto fail;
1236 }
1237 wpa_hexdump_buf_key(MSG_DEBUG, "FILS: DH_SS", sta->fils_dh_ss);
1238 pos += elem_len;
1239 } else {
1240 crypto_ecdh_deinit(sta->fils_ecdh);
1241 sta->fils_ecdh = NULL;
1242 wpabuf_clear_free(sta->fils_dh_ss);
1243 sta->fils_dh_ss = NULL;
1244 }
1245#endif /* CONFIG_FILS_SK_PFS */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001246
1247 wpa_hexdump(MSG_DEBUG, "FILS: Remaining IEs", pos, end - pos);
1248 if (ieee802_11_parse_elems(pos, end - pos, &elems, 1) == ParseFailed) {
1249 wpa_printf(MSG_DEBUG, "FILS: Could not parse elements");
1250 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1251 goto fail;
1252 }
1253
1254 /* RSNE */
1255 wpa_hexdump(MSG_DEBUG, "FILS: RSN element",
1256 elems.rsn_ie, elems.rsn_ie_len);
1257 if (!elems.rsn_ie ||
1258 wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
1259 &rsn) < 0) {
1260 wpa_printf(MSG_DEBUG, "FILS: No valid RSN element");
1261 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1262 goto fail;
1263 }
1264
1265 if (!sta->wpa_sm)
1266 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr,
1267 NULL);
1268 if (!sta->wpa_sm) {
1269 wpa_printf(MSG_DEBUG,
1270 "FILS: Failed to initialize RSN state machine");
1271 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1272 goto fail;
1273 }
1274
1275 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
1276 elems.rsn_ie - 2, elems.rsn_ie_len + 2,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001277 elems.mdie, elems.mdie_len, NULL, 0);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001278 resp = wpa_res_to_status_code(res);
1279 if (resp != WLAN_STATUS_SUCCESS)
1280 goto fail;
1281
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001282 if (!elems.fils_nonce) {
1283 wpa_printf(MSG_DEBUG, "FILS: No FILS Nonce field");
1284 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1285 goto fail;
1286 }
1287 wpa_hexdump(MSG_DEBUG, "FILS: SNonce", elems.fils_nonce,
1288 FILS_NONCE_LEN);
1289 os_memcpy(sta->fils_snonce, elems.fils_nonce, FILS_NONCE_LEN);
1290
1291 /* PMKID List */
1292 if (rsn.pmkid && rsn.num_pmkid > 0) {
1293 u8 num;
1294 const u8 *pmkid;
1295
1296 wpa_hexdump(MSG_DEBUG, "FILS: PMKID List",
1297 rsn.pmkid, rsn.num_pmkid * PMKID_LEN);
1298
1299 pmkid = rsn.pmkid;
1300 num = rsn.num_pmkid;
1301 while (num) {
1302 wpa_hexdump(MSG_DEBUG, "FILS: PMKID", pmkid, PMKID_LEN);
1303 pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr,
1304 pmkid);
1305 if (pmksa)
1306 break;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001307 pmksa = wpa_auth_pmksa_get_fils_cache_id(hapd->wpa_auth,
1308 sta->addr,
1309 pmkid);
1310 if (pmksa)
1311 break;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001312 pmkid += PMKID_LEN;
1313 num--;
1314 }
1315 }
1316 if (pmksa && wpa_auth_sta_key_mgmt(sta->wpa_sm) != pmksa->akmp) {
1317 wpa_printf(MSG_DEBUG,
1318 "FILS: Matching PMKSA cache entry has different AKMP (0x%x != 0x%x) - ignore",
1319 wpa_auth_sta_key_mgmt(sta->wpa_sm), pmksa->akmp);
1320 pmksa = NULL;
1321 }
1322 if (pmksa)
1323 wpa_printf(MSG_DEBUG, "FILS: Found matching PMKSA cache entry");
1324
1325 /* FILS Session */
1326 if (!elems.fils_session) {
1327 wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
1328 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1329 goto fail;
1330 }
1331 wpa_hexdump(MSG_DEBUG, "FILS: FILS Session", elems.fils_session,
1332 FILS_SESSION_LEN);
1333 os_memcpy(sta->fils_session, elems.fils_session, FILS_SESSION_LEN);
1334
1335 /* FILS Wrapped Data */
1336 if (elems.fils_wrapped_data) {
1337 wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data",
1338 elems.fils_wrapped_data,
1339 elems.fils_wrapped_data_len);
1340 if (!pmksa) {
1341#ifndef CONFIG_NO_RADIUS
1342 if (!sta->eapol_sm) {
1343 sta->eapol_sm =
1344 ieee802_1x_alloc_eapol_sm(hapd, sta);
1345 }
1346 wpa_printf(MSG_DEBUG,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001347 "FILS: Forward EAP-Initiate/Re-auth to authentication server");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001348 ieee802_1x_encapsulate_radius(
1349 hapd, sta, elems.fils_wrapped_data,
1350 elems.fils_wrapped_data_len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001351 sta->fils_pending_cb = cb;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001352 wpa_printf(MSG_DEBUG,
1353 "FILS: Will send Authentication frame once the response from authentication server is available");
1354 sta->flags |= WLAN_STA_PENDING_FILS_ERP;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001355 /* Calculate pending PMKID here so that we do not need
1356 * to maintain a copy of the EAP-Initiate/Reauth
1357 * message. */
1358 if (fils_pmkid_erp(wpa_auth_sta_key_mgmt(sta->wpa_sm),
1359 elems.fils_wrapped_data,
1360 elems.fils_wrapped_data_len,
1361 sta->fils_erp_pmkid) == 0)
1362 sta->fils_erp_pmkid_set = 1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001363 return;
1364#else /* CONFIG_NO_RADIUS */
1365 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1366 goto fail;
1367#endif /* CONFIG_NO_RADIUS */
1368 }
1369 }
1370
1371fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001372 if (cb) {
1373 struct wpabuf *data;
1374 int pub = 0;
1375
1376 data = prepare_auth_resp_fils(hapd, sta, &resp, pmksa, NULL,
1377 NULL, 0, &pub);
1378 if (!data) {
1379 wpa_printf(MSG_DEBUG,
1380 "%s: prepare_auth_resp_fils() returned failure",
1381 __func__);
1382 }
1383
1384 cb(hapd, sta, resp, data, pub);
1385 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001386}
1387
1388
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001389static struct wpabuf *
1390prepare_auth_resp_fils(struct hostapd_data *hapd,
1391 struct sta_info *sta, u16 *resp,
1392 struct rsn_pmksa_cache_entry *pmksa,
1393 struct wpabuf *erp_resp,
1394 const u8 *msk, size_t msk_len,
1395 int *is_pub)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001396{
1397 u8 fils_nonce[FILS_NONCE_LEN];
1398 size_t ielen;
1399 struct wpabuf *data = NULL;
1400 const u8 *ie;
1401 u8 *ie_buf = NULL;
1402 const u8 *pmk = NULL;
1403 size_t pmk_len = 0;
Paul Stewart092955c2017-02-06 09:13:09 -08001404 u8 pmk_buf[PMK_LEN_MAX];
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001405 struct wpabuf *pub = NULL;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001406
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001407 if (*resp != WLAN_STATUS_SUCCESS)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001408 goto fail;
1409
1410 ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen);
1411 if (!ie) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001412 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001413 goto fail;
1414 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001415
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001416 if (pmksa) {
1417 /* Add PMKID of the selected PMKSA into RSNE */
1418 ie_buf = os_malloc(ielen + 2 + 2 + PMKID_LEN);
1419 if (!ie_buf) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001420 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001421 goto fail;
1422 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001423
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001424 os_memcpy(ie_buf, ie, ielen);
1425 if (wpa_insert_pmkid(ie_buf, &ielen, pmksa->pmkid) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001426 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001427 goto fail;
1428 }
1429 ie = ie_buf;
1430 }
1431
1432 if (random_get_bytes(fils_nonce, FILS_NONCE_LEN) < 0) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001433 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001434 goto fail;
1435 }
1436 wpa_hexdump(MSG_DEBUG, "RSN: Generated FILS Nonce",
1437 fils_nonce, FILS_NONCE_LEN);
1438
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001439#ifdef CONFIG_FILS_SK_PFS
1440 if (sta->fils_dh_ss && sta->fils_ecdh) {
1441 pub = crypto_ecdh_get_pubkey(sta->fils_ecdh, 1);
1442 if (!pub) {
1443 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1444 goto fail;
1445 }
1446 }
1447#endif /* CONFIG_FILS_SK_PFS */
1448
1449 data = wpabuf_alloc(1000 + ielen + (pub ? wpabuf_len(pub) : 0));
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001450 if (!data) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001451 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001452 goto fail;
1453 }
1454
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001455 /* TODO: FILS PK */
1456#ifdef CONFIG_FILS_SK_PFS
1457 if (pub) {
1458 /* Finite Cyclic Group */
1459 wpabuf_put_le16(data, hapd->conf->fils_dh_group);
1460
1461 /* Element */
1462 wpabuf_put_buf(data, pub);
1463 }
1464#endif /* CONFIG_FILS_SK_PFS */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001465
1466 /* RSNE */
1467 wpabuf_put_data(data, ie, ielen);
1468
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001469 /* MDE when using FILS+FT (already included in ie,ielen with RSNE) */
1470
1471#ifdef CONFIG_IEEE80211R_AP
1472 if (wpa_key_mgmt_ft(wpa_auth_sta_key_mgmt(sta->wpa_sm))) {
1473 /* FTE[R1KH-ID,R0KH-ID] when using FILS+FT */
1474 int res;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001475 int use_sha384 = wpa_key_mgmt_sha384(
1476 wpa_auth_sta_key_mgmt(sta->wpa_sm));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001477
Roshan Pius3a1667e2018-07-03 15:17:14 -07001478 res = wpa_auth_write_fte(hapd->wpa_auth, use_sha384,
1479 wpabuf_put(data, 0),
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001480 wpabuf_tailroom(data));
1481 if (res < 0) {
1482 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1483 goto fail;
1484 }
1485 wpabuf_put(data, res);
1486 }
1487#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001488
1489 /* FILS Nonce */
1490 wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
1491 wpabuf_put_u8(data, 1 + FILS_NONCE_LEN); /* Length */
1492 /* Element ID Extension */
1493 wpabuf_put_u8(data, WLAN_EID_EXT_FILS_NONCE);
1494 wpabuf_put_data(data, fils_nonce, FILS_NONCE_LEN);
1495
1496 /* FILS Session */
1497 wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
1498 wpabuf_put_u8(data, 1 + FILS_SESSION_LEN); /* Length */
1499 /* Element ID Extension */
1500 wpabuf_put_u8(data, WLAN_EID_EXT_FILS_SESSION);
1501 wpabuf_put_data(data, sta->fils_session, FILS_SESSION_LEN);
1502
1503 /* FILS Wrapped Data */
1504 if (!pmksa && erp_resp) {
1505 wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
1506 wpabuf_put_u8(data, 1 + wpabuf_len(erp_resp)); /* Length */
1507 /* Element ID Extension */
1508 wpabuf_put_u8(data, WLAN_EID_EXT_FILS_WRAPPED_DATA);
1509 wpabuf_put_buf(data, erp_resp);
1510
Paul Stewart092955c2017-02-06 09:13:09 -08001511 if (fils_rmsk_to_pmk(wpa_auth_sta_key_mgmt(sta->wpa_sm),
1512 msk, msk_len, sta->fils_snonce, fils_nonce,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001513 sta->fils_dh_ss ?
1514 wpabuf_head(sta->fils_dh_ss) : NULL,
1515 sta->fils_dh_ss ?
1516 wpabuf_len(sta->fils_dh_ss) : 0,
1517 pmk_buf, &pmk_len)) {
Paul Stewart092955c2017-02-06 09:13:09 -08001518 wpa_printf(MSG_DEBUG, "FILS: Failed to derive PMK");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001519 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Paul Stewart092955c2017-02-06 09:13:09 -08001520 wpabuf_free(data);
1521 data = NULL;
1522 goto fail;
1523 }
1524 pmk = pmk_buf;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001525
1526 /* Don't use DHss in PTK derivation if PMKSA caching is not
1527 * used. */
1528 wpabuf_clear_free(sta->fils_dh_ss);
1529 sta->fils_dh_ss = NULL;
1530
1531 if (sta->fils_erp_pmkid_set) {
1532 /* TODO: get PMKLifetime from WPA parameters */
1533 unsigned int dot11RSNAConfigPMKLifetime = 43200;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001534 int session_timeout;
1535
1536 session_timeout = dot11RSNAConfigPMKLifetime;
1537 if (sta->session_timeout_set) {
1538 struct os_reltime now, diff;
1539
1540 os_get_reltime(&now);
1541 os_reltime_sub(&sta->session_timeout, &now,
1542 &diff);
1543 session_timeout = diff.sec;
1544 }
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001545
1546 sta->fils_erp_pmkid_set = 0;
1547 if (wpa_auth_pmksa_add2(
1548 hapd->wpa_auth, sta->addr,
1549 pmk, pmk_len,
1550 sta->fils_erp_pmkid,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001551 session_timeout,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001552 wpa_auth_sta_key_mgmt(sta->wpa_sm)) < 0) {
1553 wpa_printf(MSG_ERROR,
1554 "FILS: Failed to add PMKSA cache entry based on ERP");
1555 }
1556 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001557 } else if (pmksa) {
1558 pmk = pmksa->pmk;
1559 pmk_len = pmksa->pmk_len;
1560 }
1561
1562 if (!pmk) {
1563 wpa_printf(MSG_DEBUG, "FILS: No PMK available");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001564 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001565 wpabuf_free(data);
1566 data = NULL;
1567 goto fail;
1568 }
1569
1570 if (fils_auth_pmk_to_ptk(sta->wpa_sm, pmk, pmk_len,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001571 sta->fils_snonce, fils_nonce,
1572 sta->fils_dh_ss ?
1573 wpabuf_head(sta->fils_dh_ss) : NULL,
1574 sta->fils_dh_ss ?
1575 wpabuf_len(sta->fils_dh_ss) : 0,
1576 sta->fils_g_sta, pub) < 0) {
1577 *resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001578 wpabuf_free(data);
1579 data = NULL;
1580 goto fail;
1581 }
1582
1583fail:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001584 if (is_pub)
1585 *is_pub = pub != NULL;
1586 os_free(ie_buf);
1587 wpabuf_free(pub);
1588 wpabuf_clear_free(sta->fils_dh_ss);
1589 sta->fils_dh_ss = NULL;
1590#ifdef CONFIG_FILS_SK_PFS
1591 crypto_ecdh_deinit(sta->fils_ecdh);
1592 sta->fils_ecdh = NULL;
1593#endif /* CONFIG_FILS_SK_PFS */
1594 return data;
1595}
1596
1597
1598static void handle_auth_fils_finish(struct hostapd_data *hapd,
1599 struct sta_info *sta, u16 resp,
1600 struct wpabuf *data, int pub)
1601{
1602 u16 auth_alg;
1603
1604 auth_alg = (pub ||
1605 resp == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) ?
1606 WLAN_AUTH_FILS_SK_PFS : WLAN_AUTH_FILS_SK;
1607 send_auth_reply(hapd, sta->addr, hapd->own_addr, auth_alg, 2, resp,
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001608 data ? wpabuf_head(data) : (u8 *) "",
Roshan Pius3a1667e2018-07-03 15:17:14 -07001609 data ? wpabuf_len(data) : 0, "auth-fils-finish");
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001610 wpabuf_free(data);
1611
1612 if (resp == WLAN_STATUS_SUCCESS) {
1613 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1614 HOSTAPD_LEVEL_DEBUG,
1615 "authentication OK (FILS)");
1616 sta->flags |= WLAN_STA_AUTH;
1617 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001618 sta->auth_alg = pub ? WLAN_AUTH_FILS_SK_PFS : WLAN_AUTH_FILS_SK;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001619 mlme_authenticate_indication(hapd, sta);
1620 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001621}
1622
1623
1624void ieee802_11_finish_fils_auth(struct hostapd_data *hapd,
1625 struct sta_info *sta, int success,
1626 struct wpabuf *erp_resp,
1627 const u8 *msk, size_t msk_len)
1628{
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001629 struct wpabuf *data;
1630 int pub = 0;
1631 u16 resp;
1632
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001633 sta->flags &= ~WLAN_STA_PENDING_FILS_ERP;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001634
1635 if (!sta->fils_pending_cb)
1636 return;
1637 resp = success ? WLAN_STATUS_SUCCESS : WLAN_STATUS_UNSPECIFIED_FAILURE;
1638 data = prepare_auth_resp_fils(hapd, sta, &resp, NULL, erp_resp,
1639 msk, msk_len, &pub);
1640 if (!data) {
1641 wpa_printf(MSG_DEBUG,
1642 "%s: prepare_auth_resp_fils() returned failure",
1643 __func__);
1644 }
1645 sta->fils_pending_cb(hapd, sta, resp, data, pub);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001646}
1647
1648#endif /* CONFIG_FILS */
1649
1650
Roshan Pius3a1667e2018-07-03 15:17:14 -07001651int
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001652ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
1653 const u8 *msg, size_t len, u32 *session_timeout,
1654 u32 *acct_interim_interval,
1655 struct vlan_description *vlan_id,
1656 struct hostapd_sta_wpa_psk_short **psk,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001657 char **identity, char **radius_cui, int is_probe_req)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001658{
1659 int res;
1660
1661 os_memset(vlan_id, 0, sizeof(*vlan_id));
1662 res = hostapd_allowed_address(hapd, addr, msg, len,
1663 session_timeout, acct_interim_interval,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001664 vlan_id, psk, identity, radius_cui,
1665 is_probe_req);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001666
1667 if (res == HOSTAPD_ACL_REJECT) {
1668 wpa_printf(MSG_INFO,
1669 "Station " MACSTR " not allowed to authenticate",
1670 MAC2STR(addr));
1671 return HOSTAPD_ACL_REJECT;
1672 }
1673
1674 if (res == HOSTAPD_ACL_PENDING) {
1675 wpa_printf(MSG_DEBUG, "Authentication frame from " MACSTR
1676 " waiting for an external authentication",
1677 MAC2STR(addr));
1678 /* Authentication code will re-send the authentication frame
1679 * after it has received (and cached) information from the
1680 * external source. */
1681 return HOSTAPD_ACL_PENDING;
1682 }
1683
1684 return res;
1685}
1686
1687
1688static int
1689ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
1690 int res, u32 session_timeout,
1691 u32 acct_interim_interval,
1692 struct vlan_description *vlan_id,
1693 struct hostapd_sta_wpa_psk_short **psk,
1694 char **identity, char **radius_cui)
1695{
1696 if (vlan_id->notempty &&
1697 !hostapd_vlan_valid(hapd->conf->vlan, vlan_id)) {
1698 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
1699 HOSTAPD_LEVEL_INFO,
1700 "Invalid VLAN %d%s received from RADIUS server",
1701 vlan_id->untagged,
1702 vlan_id->tagged[0] ? "+" : "");
1703 return -1;
1704 }
1705 if (ap_sta_set_vlan(hapd, sta, vlan_id) < 0)
1706 return -1;
1707 if (sta->vlan_id)
1708 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
1709 HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
1710
1711 hostapd_free_psk_list(sta->psk);
1712 if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
1713 sta->psk = *psk;
1714 *psk = NULL;
1715 } else {
1716 sta->psk = NULL;
1717 }
1718
Roshan Pius3a1667e2018-07-03 15:17:14 -07001719 os_free(sta->identity);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001720 sta->identity = *identity;
1721 *identity = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001722
1723 os_free(sta->radius_cui);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001724 sta->radius_cui = *radius_cui;
1725 *radius_cui = NULL;
1726
1727 if (hapd->conf->acct_interim_interval == 0 && acct_interim_interval)
1728 sta->acct_interim_interval = acct_interim_interval;
Roshan Pius3a1667e2018-07-03 15:17:14 -07001729 if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT) {
1730 sta->session_timeout_set = 1;
1731 os_get_reltime(&sta->session_timeout);
1732 sta->session_timeout.sec += session_timeout;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001733 ap_sta_session_timeout(hapd, sta, session_timeout);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001734 } else {
1735 sta->session_timeout_set = 0;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001736 ap_sta_no_session_timeout(hapd, sta);
Roshan Pius3a1667e2018-07-03 15:17:14 -07001737 }
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001738
1739 return 0;
1740}
1741
1742
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001743static void handle_auth(struct hostapd_data *hapd,
1744 const struct ieee80211_mgmt *mgmt, size_t len)
1745{
1746 u16 auth_alg, auth_transaction, status_code;
1747 u16 resp = WLAN_STATUS_SUCCESS;
1748 struct sta_info *sta = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001749 int res, reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001750 u16 fc;
1751 const u8 *challenge = NULL;
1752 u32 session_timeout, acct_interim_interval;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001753 struct vlan_description vlan_id;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001754 struct hostapd_sta_wpa_psk_short *psk = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001755 u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
1756 size_t resp_ies_len = 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001757 char *identity = NULL;
1758 char *radius_cui = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001759 u16 seq_ctrl;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001760
1761 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001762 wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
1763 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001764 return;
1765 }
1766
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001767#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07001768 if (hapd->iconf->ignore_auth_probability > 0.0 &&
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001769 drand48() < hapd->iconf->ignore_auth_probability) {
1770 wpa_printf(MSG_INFO,
1771 "TESTING: ignoring auth frame from " MACSTR,
1772 MAC2STR(mgmt->sa));
1773 return;
1774 }
1775#endif /* CONFIG_TESTING_OPTIONS */
1776
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001777 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
1778 auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
1779 status_code = le_to_host16(mgmt->u.auth.status_code);
1780 fc = le_to_host16(mgmt->frame_control);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001781 seq_ctrl = le_to_host16(mgmt->seq_ctrl);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001782
1783 if (len >= IEEE80211_HDRLEN + sizeof(mgmt->u.auth) +
1784 2 + WLAN_AUTH_CHALLENGE_LEN &&
1785 mgmt->u.auth.variable[0] == WLAN_EID_CHALLENGE &&
1786 mgmt->u.auth.variable[1] == WLAN_AUTH_CHALLENGE_LEN)
1787 challenge = &mgmt->u.auth.variable[2];
1788
1789 wpa_printf(MSG_DEBUG, "authentication: STA=" MACSTR " auth_alg=%d "
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001790 "auth_transaction=%d status_code=%d wep=%d%s "
1791 "seq_ctrl=0x%x%s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001792 MAC2STR(mgmt->sa), auth_alg, auth_transaction,
1793 status_code, !!(fc & WLAN_FC_ISWEP),
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001794 challenge ? " challenge" : "",
1795 seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001796
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001797#ifdef CONFIG_NO_RC4
1798 if (auth_alg == WLAN_AUTH_SHARED_KEY) {
1799 wpa_printf(MSG_INFO,
1800 "Unsupported authentication algorithm (%d)",
1801 auth_alg);
1802 resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1803 goto fail;
1804 }
1805#endif /* CONFIG_NO_RC4 */
1806
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001807 if (hapd->tkip_countermeasures) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001808 wpa_printf(MSG_DEBUG,
1809 "Ongoing TKIP countermeasures (Michael MIC failure) - reject authentication");
1810 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001811 goto fail;
1812 }
1813
1814 if (!(((hapd->conf->auth_algs & WPA_AUTH_ALG_OPEN) &&
1815 auth_alg == WLAN_AUTH_OPEN) ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001816#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001817 (hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001818 auth_alg == WLAN_AUTH_FT) ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001819#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001820#ifdef CONFIG_SAE
1821 (hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
1822 auth_alg == WLAN_AUTH_SAE) ||
1823#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001824#ifdef CONFIG_FILS
1825 (hapd->conf->wpa && wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt) &&
1826 auth_alg == WLAN_AUTH_FILS_SK) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07001827 (hapd->conf->wpa && wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt) &&
1828 hapd->conf->fils_dh_group &&
1829 auth_alg == WLAN_AUTH_FILS_SK_PFS) ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001830#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001831 ((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) &&
1832 auth_alg == WLAN_AUTH_SHARED_KEY))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001833 wpa_printf(MSG_INFO, "Unsupported authentication algorithm (%d)",
1834 auth_alg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001835 resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1836 goto fail;
1837 }
1838
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001839 if (!(auth_transaction == 1 || auth_alg == WLAN_AUTH_SAE ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001840 (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001841 wpa_printf(MSG_INFO, "Unknown authentication transaction number (%d)",
1842 auth_transaction);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001843 resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1844 goto fail;
1845 }
1846
1847 if (os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001848 wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to authenticate",
1849 MAC2STR(mgmt->sa));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001850 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1851 goto fail;
1852 }
1853
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001854 if (hapd->conf->no_auth_if_seen_on) {
1855 struct hostapd_data *other;
1856
1857 other = sta_track_seen_on(hapd->iface, mgmt->sa,
1858 hapd->conf->no_auth_if_seen_on);
1859 if (other) {
1860 u8 *pos;
1861 u32 info;
1862 u8 op_class, channel, phytype;
1863
1864 wpa_printf(MSG_DEBUG, "%s: Reject authentication from "
1865 MACSTR " since STA has been seen on %s",
1866 hapd->conf->iface, MAC2STR(mgmt->sa),
1867 hapd->conf->no_auth_if_seen_on);
1868
1869 resp = WLAN_STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION;
1870 pos = &resp_ies[0];
1871 *pos++ = WLAN_EID_NEIGHBOR_REPORT;
1872 *pos++ = 13;
1873 os_memcpy(pos, other->own_addr, ETH_ALEN);
1874 pos += ETH_ALEN;
1875 info = 0; /* TODO: BSSID Information */
1876 WPA_PUT_LE32(pos, info);
1877 pos += 4;
1878 if (other->iconf->hw_mode == HOSTAPD_MODE_IEEE80211AD)
1879 phytype = 8; /* dmg */
1880 else if (other->iconf->ieee80211ac)
1881 phytype = 9; /* vht */
1882 else if (other->iconf->ieee80211n)
1883 phytype = 7; /* ht */
1884 else if (other->iconf->hw_mode ==
1885 HOSTAPD_MODE_IEEE80211A)
1886 phytype = 4; /* ofdm */
1887 else if (other->iconf->hw_mode ==
1888 HOSTAPD_MODE_IEEE80211G)
1889 phytype = 6; /* erp */
1890 else
1891 phytype = 5; /* hrdsss */
1892 if (ieee80211_freq_to_channel_ext(
1893 hostapd_hw_get_freq(other,
1894 other->iconf->channel),
1895 other->iconf->secondary_channel,
1896 other->iconf->ieee80211ac,
1897 &op_class, &channel) == NUM_HOSTAPD_MODES) {
1898 op_class = 0;
1899 channel = other->iconf->channel;
1900 }
1901 *pos++ = op_class;
1902 *pos++ = channel;
1903 *pos++ = phytype;
1904 resp_ies_len = pos - &resp_ies[0];
1905 goto fail;
1906 }
1907 }
1908
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001909 res = ieee802_11_allowed_address(
1910 hapd, mgmt->sa, (const u8 *) mgmt, len, &session_timeout,
Roshan Pius3a1667e2018-07-03 15:17:14 -07001911 &acct_interim_interval, &vlan_id, &psk, &identity, &radius_cui,
1912 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001913 if (res == HOSTAPD_ACL_REJECT) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001914 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
1915 "Ignore Authentication frame from " MACSTR
1916 " due to ACL reject", MAC2STR(mgmt->sa));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001917 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1918 goto fail;
1919 }
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001920 if (res == HOSTAPD_ACL_PENDING)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001921 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001922
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001923 sta = ap_get_sta(hapd, mgmt->sa);
1924 if (sta) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001925 sta->flags &= ~WLAN_STA_PENDING_FILS_ERP;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001926 if ((fc & WLAN_FC_RETRY) &&
1927 sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ &&
1928 sta->last_seq_ctrl == seq_ctrl &&
1929 sta->last_subtype == WLAN_FC_STYPE_AUTH) {
1930 hostapd_logger(hapd, sta->addr,
1931 HOSTAPD_MODULE_IEEE80211,
1932 HOSTAPD_LEVEL_DEBUG,
1933 "Drop repeated authentication frame seq_ctrl=0x%x",
1934 seq_ctrl);
1935 return;
1936 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001937#ifdef CONFIG_MESH
1938 if ((hapd->conf->mesh & MESH_ENABLED) &&
1939 sta->plink_state == PLINK_BLOCKED) {
1940 wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
1941 " is blocked - drop Authentication frame",
1942 MAC2STR(mgmt->sa));
1943 return;
1944 }
1945#endif /* CONFIG_MESH */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001946 } else {
1947#ifdef CONFIG_MESH
1948 if (hapd->conf->mesh & MESH_ENABLED) {
1949 /* if the mesh peer is not available, we don't do auth.
1950 */
1951 wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001952 " not yet known - drop Authentication frame",
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001953 MAC2STR(mgmt->sa));
1954 /*
1955 * Save a copy of the frame so that it can be processed
1956 * if a new peer entry is added shortly after this.
1957 */
1958 wpabuf_free(hapd->mesh_pending_auth);
1959 hapd->mesh_pending_auth = wpabuf_alloc_copy(mgmt, len);
1960 os_get_reltime(&hapd->mesh_pending_auth_time);
1961 return;
1962 }
1963#endif /* CONFIG_MESH */
1964
1965 sta = ap_sta_add(hapd, mgmt->sa);
1966 if (!sta) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001967 wpa_printf(MSG_DEBUG, "ap_sta_add() failed");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001968 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1969 goto fail;
1970 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001971 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001972 sta->last_seq_ctrl = seq_ctrl;
1973 sta->last_subtype = WLAN_FC_STYPE_AUTH;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001974
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08001975 res = ieee802_11_set_radius_info(
1976 hapd, sta, res, session_timeout, acct_interim_interval,
1977 &vlan_id, &psk, &identity, &radius_cui);
1978 if (res) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07001979 wpa_printf(MSG_DEBUG, "ieee802_11_set_radius_info() failed");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001980 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1981 goto fail;
1982 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001983
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001984 sta->flags &= ~WLAN_STA_PREAUTH;
1985 ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
1986
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001987 /*
1988 * If the driver supports full AP client state, add a station to the
1989 * driver before sending authentication reply to make sure the driver
1990 * has resources, and not to go through the entire authentication and
1991 * association handshake, and fail it at the end.
1992 *
1993 * If this is not the first transaction, in a multi-step authentication
1994 * algorithm, the station already exists in the driver
1995 * (sta->added_unassoc = 1) so skip it.
1996 *
1997 * In mesh mode, the station was already added to the driver when the
1998 * NEW_PEER_CANDIDATE event is received.
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08001999 *
2000 * If PMF was negotiated for the existing association, skip this to
2001 * avoid dropping the STA entry and the associated keys. This is needed
2002 * to allow the original connection work until the attempt can complete
2003 * (re)association, so that unprotected Authentication frame cannot be
2004 * used to bypass PMF protection.
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002005 */
2006 if (FULL_AP_CLIENT_STATE_SUPP(hapd->iface->drv_flags) &&
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08002007 (!(sta->flags & WLAN_STA_MFP) || !ap_sta_is_authorized(sta)) &&
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002008 !(hapd->conf->mesh & MESH_ENABLED) &&
2009 !(sta->added_unassoc)) {
2010 /*
2011 * If a station that is already associated to the AP, is trying
2012 * to authenticate again, remove the STA entry, in order to make
2013 * sure the STA PS state gets cleared and configuration gets
2014 * updated. To handle this, station's added_unassoc flag is
2015 * cleared once the station has completed association.
2016 */
Hai Shalomce48b4a2018-09-05 11:41:35 -07002017 ap_sta_set_authorized(hapd, sta, 0);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002018 hostapd_drv_sta_remove(hapd, sta->addr);
2019 sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_AUTH |
2020 WLAN_STA_AUTHORIZED);
2021
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07002022 if (hostapd_sta_add(hapd, sta->addr, 0, 0, NULL, 0, 0,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002023 NULL, NULL, sta->flags, 0, 0, 0, 0)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002024 hostapd_logger(hapd, sta->addr,
2025 HOSTAPD_MODULE_IEEE80211,
2026 HOSTAPD_LEVEL_NOTICE,
2027 "Could not add STA to kernel driver");
2028 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
2029 goto fail;
2030 }
2031
2032 sta->added_unassoc = 1;
2033 }
2034
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002035 switch (auth_alg) {
2036 case WLAN_AUTH_OPEN:
2037 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2038 HOSTAPD_LEVEL_DEBUG,
2039 "authentication OK (open system)");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002040 sta->flags |= WLAN_STA_AUTH;
2041 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
2042 sta->auth_alg = WLAN_AUTH_OPEN;
2043 mlme_authenticate_indication(hapd, sta);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002044 break;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002045#ifndef CONFIG_NO_RC4
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002046 case WLAN_AUTH_SHARED_KEY:
2047 resp = auth_shared_key(hapd, sta, auth_transaction, challenge,
2048 fc & WLAN_FC_ISWEP);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002049 if (resp != 0)
2050 wpa_printf(MSG_DEBUG,
2051 "auth_shared_key() failed: status=%d", resp);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002052 sta->auth_alg = WLAN_AUTH_SHARED_KEY;
2053 mlme_authenticate_indication(hapd, sta);
2054 if (sta->challenge && auth_transaction == 1) {
2055 resp_ies[0] = WLAN_EID_CHALLENGE;
2056 resp_ies[1] = WLAN_AUTH_CHALLENGE_LEN;
2057 os_memcpy(resp_ies + 2, sta->challenge,
2058 WLAN_AUTH_CHALLENGE_LEN);
2059 resp_ies_len = 2 + WLAN_AUTH_CHALLENGE_LEN;
2060 }
2061 break;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002062#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002063#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002064 case WLAN_AUTH_FT:
2065 sta->auth_alg = WLAN_AUTH_FT;
2066 if (sta->wpa_sm == NULL)
2067 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002068 sta->addr, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002069 if (sta->wpa_sm == NULL) {
2070 wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA "
2071 "state machine");
2072 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
2073 goto fail;
2074 }
2075 wpa_ft_process_auth(sta->wpa_sm, mgmt->bssid,
2076 auth_transaction, mgmt->u.auth.variable,
2077 len - IEEE80211_HDRLEN -
2078 sizeof(mgmt->u.auth),
2079 handle_auth_ft_finish, hapd);
2080 /* handle_auth_ft_finish() callback will complete auth. */
2081 return;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002082#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002083#ifdef CONFIG_SAE
2084 case WLAN_AUTH_SAE:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002085#ifdef CONFIG_MESH
2086 if (status_code == WLAN_STATUS_SUCCESS &&
2087 hapd->conf->mesh & MESH_ENABLED) {
2088 if (sta->wpa_sm == NULL)
2089 sta->wpa_sm =
2090 wpa_auth_sta_init(hapd->wpa_auth,
2091 sta->addr, NULL);
2092 if (sta->wpa_sm == NULL) {
2093 wpa_printf(MSG_DEBUG,
2094 "SAE: Failed to initialize WPA state machine");
2095 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
2096 goto fail;
2097 }
2098 }
2099#endif /* CONFIG_MESH */
2100 handle_auth_sae(hapd, sta, mgmt, len, auth_transaction,
2101 status_code);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002102 return;
2103#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002104#ifdef CONFIG_FILS
2105 case WLAN_AUTH_FILS_SK:
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002106 case WLAN_AUTH_FILS_SK_PFS:
2107 handle_auth_fils(hapd, sta, mgmt->u.auth.variable,
2108 len - IEEE80211_HDRLEN - sizeof(mgmt->u.auth),
2109 auth_alg, auth_transaction, status_code,
2110 handle_auth_fils_finish);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002111 return;
2112#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002113 }
2114
2115 fail:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002116 os_free(identity);
2117 os_free(radius_cui);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002118 hostapd_free_psk_list(psk);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002119
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002120 reply_res = send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
2121 auth_transaction + 1, resp, resp_ies,
Roshan Pius3a1667e2018-07-03 15:17:14 -07002122 resp_ies_len, "handle-auth");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002123
2124 if (sta && sta->added_unassoc && (resp != WLAN_STATUS_SUCCESS ||
2125 reply_res != WLAN_STATUS_SUCCESS)) {
2126 hostapd_drv_sta_remove(hapd, sta->addr);
2127 sta->added_unassoc = 0;
2128 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002129}
2130
2131
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002132int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002133{
2134 int i, j = 32, aid;
2135
2136 /* get a unique AID */
2137 if (sta->aid > 0) {
2138 wpa_printf(MSG_DEBUG, " old AID %d", sta->aid);
2139 return 0;
2140 }
2141
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07002142 if (TEST_FAIL())
2143 return -1;
2144
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002145 for (i = 0; i < AID_WORDS; i++) {
2146 if (hapd->sta_aid[i] == (u32) -1)
2147 continue;
2148 for (j = 0; j < 32; j++) {
2149 if (!(hapd->sta_aid[i] & BIT(j)))
2150 break;
2151 }
2152 if (j < 32)
2153 break;
2154 }
2155 if (j == 32)
2156 return -1;
2157 aid = i * 32 + j + 1;
2158 if (aid > 2007)
2159 return -1;
2160
2161 sta->aid = aid;
2162 hapd->sta_aid[i] |= BIT(j);
2163 wpa_printf(MSG_DEBUG, " new AID %d", sta->aid);
2164 return 0;
2165}
2166
2167
2168static u16 check_ssid(struct hostapd_data *hapd, struct sta_info *sta,
2169 const u8 *ssid_ie, size_t ssid_ie_len)
2170{
2171 if (ssid_ie == NULL)
2172 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2173
2174 if (ssid_ie_len != hapd->conf->ssid.ssid_len ||
2175 os_memcmp(ssid_ie, hapd->conf->ssid.ssid, ssid_ie_len) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002176 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2177 HOSTAPD_LEVEL_INFO,
2178 "Station tried to associate with unknown SSID "
Dmitry Shmidt3c479372014-02-04 10:50:36 -08002179 "'%s'", wpa_ssid_txt(ssid_ie, ssid_ie_len));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002180 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2181 }
2182
2183 return WLAN_STATUS_SUCCESS;
2184}
2185
2186
2187static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta,
2188 const u8 *wmm_ie, size_t wmm_ie_len)
2189{
2190 sta->flags &= ~WLAN_STA_WMM;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002191 sta->qosinfo = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002192 if (wmm_ie && hapd->conf->wmm_enabled) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002193 struct wmm_information_element *wmm;
2194
2195 if (!hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002196 hostapd_logger(hapd, sta->addr,
2197 HOSTAPD_MODULE_WPA,
2198 HOSTAPD_LEVEL_DEBUG,
2199 "invalid WMM element in association "
2200 "request");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002201 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2202 }
2203
2204 sta->flags |= WLAN_STA_WMM;
2205 wmm = (struct wmm_information_element *) wmm_ie;
2206 sta->qosinfo = wmm->qos_info;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002207 }
2208 return WLAN_STATUS_SUCCESS;
2209}
2210
2211
2212static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
2213 struct ieee802_11_elems *elems)
2214{
Dmitry Shmidt29333592017-01-09 12:27:11 -08002215 /* Supported rates not used in IEEE 802.11ad/DMG */
2216 if (hapd->iface->current_mode &&
2217 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD)
2218 return WLAN_STATUS_SUCCESS;
2219
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002220 if (!elems->supp_rates) {
2221 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2222 HOSTAPD_LEVEL_DEBUG,
2223 "No supported rates element in AssocReq");
2224 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2225 }
2226
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002227 if (elems->supp_rates_len + elems->ext_supp_rates_len >
2228 sizeof(sta->supported_rates)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002229 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2230 HOSTAPD_LEVEL_DEBUG,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002231 "Invalid supported rates element length %d+%d",
2232 elems->supp_rates_len,
2233 elems->ext_supp_rates_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002234 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2235 }
2236
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002237 sta->supported_rates_len = merge_byte_arrays(
2238 sta->supported_rates, sizeof(sta->supported_rates),
2239 elems->supp_rates, elems->supp_rates_len,
2240 elems->ext_supp_rates, elems->ext_supp_rates_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002241
2242 return WLAN_STATUS_SUCCESS;
2243}
2244
2245
Dmitry Shmidt051af732013-10-22 13:52:46 -07002246static u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
2247 const u8 *ext_capab_ie, size_t ext_capab_ie_len)
2248{
2249#ifdef CONFIG_INTERWORKING
2250 /* check for QoS Map support */
2251 if (ext_capab_ie_len >= 5) {
2252 if (ext_capab_ie[4] & 0x01)
2253 sta->qos_map_enabled = 1;
2254 }
2255#endif /* CONFIG_INTERWORKING */
2256
Roshan Pius3a1667e2018-07-03 15:17:14 -07002257 if (ext_capab_ie_len > 0) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002258 sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2));
Roshan Pius3a1667e2018-07-03 15:17:14 -07002259 os_free(sta->ext_capability);
2260 sta->ext_capability = os_malloc(1 + ext_capab_ie_len);
2261 if (sta->ext_capability) {
2262 sta->ext_capability[0] = ext_capab_ie_len;
2263 os_memcpy(sta->ext_capability + 1, ext_capab_ie,
2264 ext_capab_ie_len);
2265 }
2266 }
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002267
Dmitry Shmidt051af732013-10-22 13:52:46 -07002268 return WLAN_STATUS_SUCCESS;
2269}
2270
2271
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002272#ifdef CONFIG_OWE
2273
2274static int owe_group_supported(struct hostapd_data *hapd, u16 group)
2275{
2276 int i;
2277 int *groups = hapd->conf->owe_groups;
2278
2279 if (group != 19 && group != 20 && group != 21)
2280 return 0;
2281
2282 if (!groups)
2283 return 1;
2284
2285 for (i = 0; groups[i] > 0; i++) {
2286 if (groups[i] == group)
2287 return 1;
2288 }
2289
2290 return 0;
2291}
2292
2293
2294static u16 owe_process_assoc_req(struct hostapd_data *hapd,
2295 struct sta_info *sta, const u8 *owe_dh,
2296 u8 owe_dh_len)
2297{
2298 struct wpabuf *secret, *pub, *hkey;
2299 int res;
2300 u8 prk[SHA512_MAC_LEN], pmkid[SHA512_MAC_LEN];
2301 const char *info = "OWE Key Generation";
2302 const u8 *addr[2];
2303 size_t len[2];
2304 u16 group;
2305 size_t hash_len, prime_len;
2306
2307 if (wpa_auth_sta_get_pmksa(sta->wpa_sm)) {
2308 wpa_printf(MSG_DEBUG, "OWE: Using PMKSA caching");
2309 return WLAN_STATUS_SUCCESS;
2310 }
2311
2312 group = WPA_GET_LE16(owe_dh);
2313 if (!owe_group_supported(hapd, group)) {
2314 wpa_printf(MSG_DEBUG, "OWE: Unsupported DH group %u", group);
2315 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
2316 }
2317 if (group == 19)
2318 prime_len = 32;
2319 else if (group == 20)
2320 prime_len = 48;
2321 else if (group == 21)
2322 prime_len = 66;
2323 else
2324 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
2325
2326 crypto_ecdh_deinit(sta->owe_ecdh);
2327 sta->owe_ecdh = crypto_ecdh_init(group);
2328 if (!sta->owe_ecdh)
2329 return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
2330 sta->owe_group = group;
2331
2332 secret = crypto_ecdh_set_peerkey(sta->owe_ecdh, 0, owe_dh + 2,
2333 owe_dh_len - 2);
2334 secret = wpabuf_zeropad(secret, prime_len);
2335 if (!secret) {
2336 wpa_printf(MSG_DEBUG, "OWE: Invalid peer DH public key");
2337 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2338 }
2339 wpa_hexdump_buf_key(MSG_DEBUG, "OWE: DH shared secret", secret);
2340
2341 /* prk = HKDF-extract(C | A | group, z) */
2342
2343 pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
2344 if (!pub) {
2345 wpabuf_clear_free(secret);
2346 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2347 }
2348
2349 /* PMKID = Truncate-128(Hash(C | A)) */
2350 addr[0] = owe_dh + 2;
2351 len[0] = owe_dh_len - 2;
2352 addr[1] = wpabuf_head(pub);
2353 len[1] = wpabuf_len(pub);
2354 if (group == 19) {
2355 res = sha256_vector(2, addr, len, pmkid);
2356 hash_len = SHA256_MAC_LEN;
2357 } else if (group == 20) {
2358 res = sha384_vector(2, addr, len, pmkid);
2359 hash_len = SHA384_MAC_LEN;
2360 } else if (group == 21) {
2361 res = sha512_vector(2, addr, len, pmkid);
2362 hash_len = SHA512_MAC_LEN;
2363 } else {
2364 wpabuf_free(pub);
2365 wpabuf_clear_free(secret);
2366 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2367 }
2368 pub = wpabuf_zeropad(pub, prime_len);
2369 if (res < 0 || !pub) {
2370 wpabuf_free(pub);
2371 wpabuf_clear_free(secret);
2372 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2373 }
2374
2375 hkey = wpabuf_alloc(owe_dh_len - 2 + wpabuf_len(pub) + 2);
2376 if (!hkey) {
2377 wpabuf_free(pub);
2378 wpabuf_clear_free(secret);
2379 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2380 }
2381
2382 wpabuf_put_data(hkey, owe_dh + 2, owe_dh_len - 2); /* C */
2383 wpabuf_put_buf(hkey, pub); /* A */
2384 wpabuf_free(pub);
2385 wpabuf_put_le16(hkey, group); /* group */
2386 if (group == 19)
2387 res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey),
2388 wpabuf_head(secret), wpabuf_len(secret), prk);
2389 else if (group == 20)
2390 res = hmac_sha384(wpabuf_head(hkey), wpabuf_len(hkey),
2391 wpabuf_head(secret), wpabuf_len(secret), prk);
2392 else if (group == 21)
2393 res = hmac_sha512(wpabuf_head(hkey), wpabuf_len(hkey),
2394 wpabuf_head(secret), wpabuf_len(secret), prk);
2395 wpabuf_clear_free(hkey);
2396 wpabuf_clear_free(secret);
2397 if (res < 0)
2398 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2399
2400 wpa_hexdump_key(MSG_DEBUG, "OWE: prk", prk, hash_len);
2401
2402 /* PMK = HKDF-expand(prk, "OWE Key Generation", n) */
2403
2404 os_free(sta->owe_pmk);
2405 sta->owe_pmk = os_malloc(hash_len);
2406 if (!sta->owe_pmk) {
2407 os_memset(prk, 0, SHA512_MAC_LEN);
2408 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2409 }
2410
2411 if (group == 19)
2412 res = hmac_sha256_kdf(prk, hash_len, NULL, (const u8 *) info,
2413 os_strlen(info), sta->owe_pmk, hash_len);
2414 else if (group == 20)
2415 res = hmac_sha384_kdf(prk, hash_len, NULL, (const u8 *) info,
2416 os_strlen(info), sta->owe_pmk, hash_len);
2417 else if (group == 21)
2418 res = hmac_sha512_kdf(prk, hash_len, NULL, (const u8 *) info,
2419 os_strlen(info), sta->owe_pmk, hash_len);
2420 os_memset(prk, 0, SHA512_MAC_LEN);
2421 if (res < 0) {
2422 os_free(sta->owe_pmk);
2423 sta->owe_pmk = NULL;
2424 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2425 }
2426 sta->owe_pmk_len = hash_len;
2427
2428 wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sta->owe_pmk, sta->owe_pmk_len);
2429 wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, PMKID_LEN);
2430 wpa_auth_pmksa_add2(hapd->wpa_auth, sta->addr, sta->owe_pmk,
2431 sta->owe_pmk_len, pmkid, 0, WPA_KEY_MGMT_OWE);
2432
2433 return WLAN_STATUS_SUCCESS;
2434}
2435
2436#endif /* CONFIG_OWE */
2437
2438
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002439static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
2440 const u8 *ies, size_t ies_len, int reassoc)
2441{
2442 struct ieee802_11_elems elems;
2443 u16 resp;
2444 const u8 *wpa_ie;
2445 size_t wpa_ie_len;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002446 const u8 *p2p_dev_addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002447
2448 if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
2449 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2450 HOSTAPD_LEVEL_INFO, "Station sent an invalid "
2451 "association request");
2452 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2453 }
2454
2455 resp = check_ssid(hapd, sta, elems.ssid, elems.ssid_len);
2456 if (resp != WLAN_STATUS_SUCCESS)
2457 return resp;
2458 resp = check_wmm(hapd, sta, elems.wmm, elems.wmm_len);
2459 if (resp != WLAN_STATUS_SUCCESS)
2460 return resp;
Dmitry Shmidt051af732013-10-22 13:52:46 -07002461 resp = check_ext_capab(hapd, sta, elems.ext_capab, elems.ext_capab_len);
2462 if (resp != WLAN_STATUS_SUCCESS)
2463 return resp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002464 resp = copy_supp_rates(hapd, sta, &elems);
2465 if (resp != WLAN_STATUS_SUCCESS)
2466 return resp;
2467#ifdef CONFIG_IEEE80211N
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07002468 resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002469 if (resp != WLAN_STATUS_SUCCESS)
2470 return resp;
2471 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
2472 !(sta->flags & WLAN_STA_HT)) {
2473 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2474 HOSTAPD_LEVEL_INFO, "Station does not support "
2475 "mandatory HT PHY - reject association");
2476 return WLAN_STATUS_ASSOC_DENIED_NO_HT;
2477 }
2478#endif /* CONFIG_IEEE80211N */
2479
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002480#ifdef CONFIG_IEEE80211AC
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002481 if (hapd->iconf->ieee80211ac) {
2482 resp = copy_sta_vht_capab(hapd, sta, elems.vht_capabilities);
2483 if (resp != WLAN_STATUS_SUCCESS)
2484 return resp;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002485
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002486 resp = set_sta_vht_opmode(hapd, sta, elems.vht_opmode_notif);
2487 if (resp != WLAN_STATUS_SUCCESS)
2488 return resp;
2489 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08002490
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002491 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht &&
2492 !(sta->flags & WLAN_STA_VHT)) {
2493 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2494 HOSTAPD_LEVEL_INFO, "Station does not support "
2495 "mandatory VHT PHY - reject association");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002496 return WLAN_STATUS_ASSOC_DENIED_NO_VHT;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002497 }
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002498
2499 if (hapd->conf->vendor_vht && !elems.vht_capabilities) {
2500 resp = copy_sta_vendor_vht(hapd, sta, elems.vendor_vht,
2501 elems.vendor_vht_len);
2502 if (resp != WLAN_STATUS_SUCCESS)
2503 return resp;
2504 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002505#endif /* CONFIG_IEEE80211AC */
2506
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002507#ifdef CONFIG_P2P
2508 if (elems.p2p) {
2509 wpabuf_free(sta->p2p_ie);
2510 sta->p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
2511 P2P_IE_VENDOR_TYPE);
2512 if (sta->p2p_ie)
2513 p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie);
2514 } else {
2515 wpabuf_free(sta->p2p_ie);
2516 sta->p2p_ie = NULL;
2517 }
2518#endif /* CONFIG_P2P */
2519
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002520 if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) {
2521 wpa_ie = elems.rsn_ie;
2522 wpa_ie_len = elems.rsn_ie_len;
2523 } else if ((hapd->conf->wpa & WPA_PROTO_WPA) &&
2524 elems.wpa_ie) {
2525 wpa_ie = elems.wpa_ie;
2526 wpa_ie_len = elems.wpa_ie_len;
2527 } else {
2528 wpa_ie = NULL;
2529 wpa_ie_len = 0;
2530 }
2531
2532#ifdef CONFIG_WPS
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002533 sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002534 if (hapd->conf->wps_state && elems.wps_ie) {
2535 wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association "
2536 "Request - assume WPS is used");
2537 sta->flags |= WLAN_STA_WPS;
2538 wpabuf_free(sta->wps_ie);
2539 sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
2540 WPS_IE_VENDOR_TYPE);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002541 if (sta->wps_ie && wps_is_20(sta->wps_ie)) {
2542 wpa_printf(MSG_DEBUG, "WPS: STA supports WPS 2.0");
2543 sta->flags |= WLAN_STA_WPS2;
2544 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002545 wpa_ie = NULL;
2546 wpa_ie_len = 0;
2547 if (sta->wps_ie && wps_validate_assoc_req(sta->wps_ie) < 0) {
2548 wpa_printf(MSG_DEBUG, "WPS: Invalid WPS IE in "
2549 "(Re)Association Request - reject");
2550 return WLAN_STATUS_INVALID_IE;
2551 }
2552 } else if (hapd->conf->wps_state && wpa_ie == NULL) {
2553 wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE in "
2554 "(Re)Association Request - possible WPS use");
2555 sta->flags |= WLAN_STA_MAYBE_WPS;
2556 } else
2557#endif /* CONFIG_WPS */
2558 if (hapd->conf->wpa && wpa_ie == NULL) {
2559 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2560 HOSTAPD_LEVEL_INFO,
2561 "No WPA/RSN IE in association request");
2562 return WLAN_STATUS_INVALID_IE;
2563 }
2564
2565 if (hapd->conf->wpa && wpa_ie) {
2566 int res;
2567 wpa_ie -= 2;
2568 wpa_ie_len += 2;
2569 if (sta->wpa_sm == NULL)
2570 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002571 sta->addr,
2572 p2p_dev_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002573 if (sta->wpa_sm == NULL) {
2574 wpa_printf(MSG_WARNING, "Failed to initialize WPA "
2575 "state machine");
2576 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2577 }
2578 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
2579 wpa_ie, wpa_ie_len,
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002580 elems.mdie, elems.mdie_len,
2581 elems.owe_dh, elems.owe_dh_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002582 resp = wpa_res_to_status_code(res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002583 if (resp != WLAN_STATUS_SUCCESS)
2584 return resp;
2585#ifdef CONFIG_IEEE80211W
2586 if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
2587 sta->sa_query_count > 0)
2588 ap_check_sa_query_timeout(hapd, sta);
2589 if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
2590 (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) {
2591 /*
2592 * STA has already been associated with MFP and SA
2593 * Query timeout has not been reached. Reject the
2594 * association attempt temporarily and start SA Query,
2595 * if one is not pending.
2596 */
2597
2598 if (sta->sa_query_count == 0)
2599 ap_sta_start_sa_query(hapd, sta);
2600
2601 return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
2602 }
2603
2604 if (wpa_auth_uses_mfp(sta->wpa_sm))
2605 sta->flags |= WLAN_STA_MFP;
2606 else
2607 sta->flags &= ~WLAN_STA_MFP;
2608#endif /* CONFIG_IEEE80211W */
2609
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002610#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002611 if (sta->auth_alg == WLAN_AUTH_FT) {
2612 if (!reassoc) {
2613 wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried "
2614 "to use association (not "
2615 "re-association) with FT auth_alg",
2616 MAC2STR(sta->addr));
2617 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2618 }
2619
2620 resp = wpa_ft_validate_reassoc(sta->wpa_sm, ies,
2621 ies_len);
2622 if (resp != WLAN_STATUS_SUCCESS)
2623 return resp;
2624 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002625#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002626
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002627#ifdef CONFIG_SAE
Roshan Pius3a1667e2018-07-03 15:17:14 -07002628 if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae &&
2629 sta->sae->state == SAE_ACCEPTED)
2630 wpa_auth_add_sae_pmkid(sta->wpa_sm, sta->sae->pmkid);
2631
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002632 if (wpa_auth_uses_sae(sta->wpa_sm) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002633 sta->auth_alg == WLAN_AUTH_OPEN) {
2634 struct rsn_pmksa_cache_entry *sa;
2635 sa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
2636 if (!sa || sa->akmp != WPA_KEY_MGMT_SAE) {
2637 wpa_printf(MSG_DEBUG,
2638 "SAE: No PMKSA cache entry found for "
2639 MACSTR, MAC2STR(sta->addr));
2640 return WLAN_STATUS_INVALID_PMKID;
2641 }
2642 wpa_printf(MSG_DEBUG, "SAE: " MACSTR
2643 " using PMKSA caching", MAC2STR(sta->addr));
2644 } else if (wpa_auth_uses_sae(sta->wpa_sm) &&
2645 sta->auth_alg != WLAN_AUTH_SAE &&
2646 !(sta->auth_alg == WLAN_AUTH_FT &&
2647 wpa_auth_uses_ft_sae(sta->wpa_sm))) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002648 wpa_printf(MSG_DEBUG, "SAE: " MACSTR " tried to use "
2649 "SAE AKM after non-SAE auth_alg %u",
2650 MAC2STR(sta->addr), sta->auth_alg);
2651 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
2652 }
2653#endif /* CONFIG_SAE */
2654
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002655#ifdef CONFIG_OWE
2656 if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
2657 wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE &&
2658 elems.owe_dh) {
2659 resp = owe_process_assoc_req(hapd, sta, elems.owe_dh,
2660 elems.owe_dh_len);
2661 if (resp != WLAN_STATUS_SUCCESS)
2662 return resp;
2663 }
2664#endif /* CONFIG_OWE */
2665
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002666#ifdef CONFIG_IEEE80211N
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002667 if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002668 wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
2669 hostapd_logger(hapd, sta->addr,
2670 HOSTAPD_MODULE_IEEE80211,
2671 HOSTAPD_LEVEL_INFO,
2672 "Station tried to use TKIP with HT "
2673 "association");
2674 return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
2675 }
2676#endif /* CONFIG_IEEE80211N */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002677#ifdef CONFIG_HS20
2678 } else if (hapd->conf->osen) {
2679 if (elems.osen == NULL) {
2680 hostapd_logger(
2681 hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2682 HOSTAPD_LEVEL_INFO,
2683 "No HS 2.0 OSEN element in association request");
2684 return WLAN_STATUS_INVALID_IE;
2685 }
2686
2687 wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association");
2688 if (sta->wpa_sm == NULL)
2689 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
2690 sta->addr, NULL);
2691 if (sta->wpa_sm == NULL) {
2692 wpa_printf(MSG_WARNING, "Failed to initialize WPA "
2693 "state machine");
2694 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2695 }
2696 if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm,
2697 elems.osen - 2, elems.osen_len + 2) < 0)
2698 return WLAN_STATUS_INVALID_IE;
2699#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002700 } else
2701 wpa_auth_sta_no_wpa(sta->wpa_sm);
2702
2703#ifdef CONFIG_P2P
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002704 p2p_group_notif_assoc(hapd->p2p_group, sta->addr, ies, ies_len);
2705#endif /* CONFIG_P2P */
2706
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002707#ifdef CONFIG_HS20
2708 wpabuf_free(sta->hs20_ie);
2709 if (elems.hs20 && elems.hs20_len > 4) {
2710 sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
2711 elems.hs20_len - 4);
2712 } else
2713 sta->hs20_ie = NULL;
Roshan Pius3a1667e2018-07-03 15:17:14 -07002714
2715 wpabuf_free(sta->roaming_consortium);
2716 if (elems.roaming_cons_sel)
2717 sta->roaming_consortium = wpabuf_alloc_copy(
2718 elems.roaming_cons_sel + 4,
2719 elems.roaming_cons_sel_len - 4);
2720 else
2721 sta->roaming_consortium = NULL;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002722#endif /* CONFIG_HS20 */
2723
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002724#ifdef CONFIG_FST
2725 wpabuf_free(sta->mb_ies);
2726 if (hapd->iface->fst)
2727 sta->mb_ies = mb_ies_by_info(&elems.mb_ies);
2728 else
2729 sta->mb_ies = NULL;
2730#endif /* CONFIG_FST */
2731
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002732#ifdef CONFIG_MBO
2733 mbo_ap_check_sta_assoc(hapd, sta, &elems);
2734
2735 if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) &&
2736 elems.mbo && sta->cell_capa && !(sta->flags & WLAN_STA_MFP) &&
2737 hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
2738 wpa_printf(MSG_INFO,
2739 "MBO: Reject WPA2 association without PMF");
2740 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2741 }
2742#endif /* CONFIG_MBO */
2743
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002744 ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes,
2745 elems.supp_op_classes_len);
2746
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002747 if ((sta->capability & WLAN_CAPABILITY_RADIO_MEASUREMENT) &&
2748 elems.rrm_enabled &&
2749 elems.rrm_enabled_len >= sizeof(sta->rrm_enabled_capa))
2750 os_memcpy(sta->rrm_enabled_capa, elems.rrm_enabled,
2751 sizeof(sta->rrm_enabled_capa));
2752
Roshan Pius3a1667e2018-07-03 15:17:14 -07002753 if (elems.power_capab) {
2754 sta->min_tx_power = elems.power_capab[0];
2755 sta->max_tx_power = elems.power_capab[1];
2756 sta->power_capab = 1;
2757 } else {
2758 sta->power_capab = 0;
2759 }
2760
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002761 return WLAN_STATUS_SUCCESS;
2762}
2763
2764
2765static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
2766 u16 reason_code)
2767{
2768 int send_len;
2769 struct ieee80211_mgmt reply;
2770
2771 os_memset(&reply, 0, sizeof(reply));
2772 reply.frame_control =
2773 IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DEAUTH);
2774 os_memcpy(reply.da, addr, ETH_ALEN);
2775 os_memcpy(reply.sa, hapd->own_addr, ETH_ALEN);
2776 os_memcpy(reply.bssid, hapd->own_addr, ETH_ALEN);
2777
2778 send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth);
2779 reply.u.deauth.reason_code = host_to_le16(reason_code);
2780
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002781 if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002782 wpa_printf(MSG_INFO, "Failed to send deauth: %s",
2783 strerror(errno));
2784}
2785
2786
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002787static int add_associated_sta(struct hostapd_data *hapd,
2788 struct sta_info *sta)
2789{
2790 struct ieee80211_ht_capabilities ht_cap;
2791 struct ieee80211_vht_capabilities vht_cap;
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02002792 int set = 1;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002793
2794 /*
2795 * Remove the STA entry to ensure the STA PS state gets cleared and
2796 * configuration gets updated. This is relevant for cases, such as
2797 * FT-over-the-DS, where a station re-associates back to the same AP but
2798 * skips the authentication flow, or if working with a driver that
2799 * does not support full AP client state.
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02002800 *
2801 * Skip this if the STA has already completed FT reassociation and the
2802 * TK has been configured since the TX/RX PN must not be reset to 0 for
2803 * the same key.
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002804 */
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02002805 if (!sta->added_unassoc &&
2806 (!(sta->flags & WLAN_STA_AUTHORIZED) ||
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002807 (!wpa_auth_sta_ft_tk_already_set(sta->wpa_sm) &&
2808 !wpa_auth_sta_fils_tk_already_set(sta->wpa_sm)))) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002809 hostapd_drv_sta_remove(hapd, sta->addr);
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02002810 wpa_auth_sm_event(sta->wpa_sm, WPA_DRV_STA_REMOVED);
2811 set = 0;
2812 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002813
2814#ifdef CONFIG_IEEE80211N
2815 if (sta->flags & WLAN_STA_HT)
2816 hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
2817#endif /* CONFIG_IEEE80211N */
2818#ifdef CONFIG_IEEE80211AC
2819 if (sta->flags & WLAN_STA_VHT)
2820 hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
2821#endif /* CONFIG_IEEE80211AC */
2822
2823 /*
2824 * Add the station with forced WLAN_STA_ASSOC flag. The sta->flags
2825 * will be set when the ACK frame for the (Re)Association Response frame
2826 * is processed (TX status driver event).
2827 */
2828 if (hostapd_sta_add(hapd, sta->addr, sta->aid, sta->capability,
2829 sta->supported_rates, sta->supported_rates_len,
2830 sta->listen_interval,
2831 sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
2832 sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
2833 sta->flags | WLAN_STA_ASSOC, sta->qosinfo,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002834 sta->vht_opmode, sta->p2p_ie ? 1 : 0,
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02002835 set)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002836 hostapd_logger(hapd, sta->addr,
2837 HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE,
2838 "Could not %s STA to kernel driver",
Mathy Vanhoeff6e1f662017-07-14 15:15:35 +02002839 set ? "set" : "add");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002840
2841 if (sta->added_unassoc) {
2842 hostapd_drv_sta_remove(hapd, sta->addr);
2843 sta->added_unassoc = 0;
2844 }
2845
2846 return -1;
2847 }
2848
2849 sta->added_unassoc = 0;
2850
2851 return 0;
2852}
2853
2854
2855static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
Dmitry Shmidt29333592017-01-09 12:27:11 -08002856 const u8 *addr, u16 status_code, int reassoc,
2857 const u8 *ies, size_t ies_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002858{
2859 int send_len;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002860 u8 *buf;
2861 size_t buflen;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002862 struct ieee80211_mgmt *reply;
2863 u8 *p;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002864 u16 res = WLAN_STATUS_SUCCESS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002865
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002866 buflen = sizeof(struct ieee80211_mgmt) + 1024;
2867#ifdef CONFIG_FILS
2868 if (sta && sta->fils_hlp_resp)
2869 buflen += wpabuf_len(sta->fils_hlp_resp);
2870#endif /* CONFIG_FILS */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002871#ifdef CONFIG_OWE
2872 if (sta && (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE))
2873 buflen += 150;
2874#endif /* CONFIG_OWE */
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002875 buf = os_zalloc(buflen);
2876 if (!buf) {
2877 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
2878 goto done;
2879 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002880 reply = (struct ieee80211_mgmt *) buf;
2881 reply->frame_control =
2882 IEEE80211_FC(WLAN_FC_TYPE_MGMT,
2883 (reassoc ? WLAN_FC_STYPE_REASSOC_RESP :
2884 WLAN_FC_STYPE_ASSOC_RESP));
Dmitry Shmidt29333592017-01-09 12:27:11 -08002885 os_memcpy(reply->da, addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002886 os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
2887 os_memcpy(reply->bssid, hapd->own_addr, ETH_ALEN);
2888
2889 send_len = IEEE80211_HDRLEN;
2890 send_len += sizeof(reply->u.assoc_resp);
2891 reply->u.assoc_resp.capab_info =
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07002892 host_to_le16(hostapd_own_capab_info(hapd));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002893 reply->u.assoc_resp.status_code = host_to_le16(status_code);
Dmitry Shmidt29333592017-01-09 12:27:11 -08002894
2895 reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0) |
2896 BIT(14) | BIT(15));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002897 /* Supported rates */
2898 p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable);
2899 /* Extended supported rates */
2900 p = hostapd_eid_ext_supp_rates(hapd, p);
2901
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002902#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt29333592017-01-09 12:27:11 -08002903 if (sta && status_code == WLAN_STATUS_SUCCESS) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002904 /* IEEE 802.11r: Mobility Domain Information, Fast BSS
2905 * Transition Information, RSN, [RIC Response] */
2906 p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08002907 buf + buflen - p,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002908 sta->auth_alg, ies, ies_len);
Roshan Pius3a1667e2018-07-03 15:17:14 -07002909 if (!p) {
2910 wpa_printf(MSG_DEBUG,
2911 "FT: Failed to write AssocResp IEs");
2912 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
2913 goto done;
2914 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002915 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002916#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002917
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07002918#ifdef CONFIG_OWE
2919 if (sta && (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE))
2920 p = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, p,
2921 buf + buflen - p,
2922 ies, ies_len);
2923#endif /* CONFIG_OWE */
2924
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002925#ifdef CONFIG_IEEE80211W
Dmitry Shmidt29333592017-01-09 12:27:11 -08002926 if (sta && status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002927 p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
2928#endif /* CONFIG_IEEE80211W */
2929
2930#ifdef CONFIG_IEEE80211N
2931 p = hostapd_eid_ht_capabilities(hapd, p);
2932 p = hostapd_eid_ht_operation(hapd, p);
2933#endif /* CONFIG_IEEE80211N */
2934
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002935#ifdef CONFIG_IEEE80211AC
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002936 if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
Dmitry Shmidt7d175302016-09-06 13:11:34 -07002937 u32 nsts = 0, sta_nsts;
2938
Dmitry Shmidt29333592017-01-09 12:27:11 -08002939 if (sta && hapd->conf->use_sta_nsts && sta->vht_capabilities) {
Dmitry Shmidt7d175302016-09-06 13:11:34 -07002940 struct ieee80211_vht_capabilities *capa;
2941
2942 nsts = (hapd->iface->conf->vht_capab >>
2943 VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7;
2944 capa = sta->vht_capabilities;
2945 sta_nsts = (le_to_host32(capa->vht_capabilities_info) >>
2946 VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7;
2947
2948 if (nsts < sta_nsts)
2949 nsts = 0;
2950 else
2951 nsts = sta_nsts;
2952 }
2953 p = hostapd_eid_vht_capabilities(hapd, p, nsts);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002954 p = hostapd_eid_vht_operation(hapd, p);
2955 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002956#endif /* CONFIG_IEEE80211AC */
2957
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002958 p = hostapd_eid_ext_capab(hapd, p);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002959 p = hostapd_eid_bss_max_idle_period(hapd, p);
Dmitry Shmidt29333592017-01-09 12:27:11 -08002960 if (sta && sta->qos_map_enabled)
Dmitry Shmidt051af732013-10-22 13:52:46 -07002961 p = hostapd_eid_qos_map_set(hapd, p);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002962
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002963#ifdef CONFIG_FST
2964 if (hapd->iface->fst_ies) {
2965 os_memcpy(p, wpabuf_head(hapd->iface->fst_ies),
2966 wpabuf_len(hapd->iface->fst_ies));
2967 p += wpabuf_len(hapd->iface->fst_ies);
2968 }
2969#endif /* CONFIG_FST */
2970
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002971#ifdef CONFIG_IEEE80211AC
Dmitry Shmidt29333592017-01-09 12:27:11 -08002972 if (sta && hapd->conf->vendor_vht && (sta->flags & WLAN_STA_VENDOR_VHT))
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002973 p = hostapd_eid_vendor_vht(hapd, p);
2974#endif /* CONFIG_IEEE80211AC */
2975
Dmitry Shmidt29333592017-01-09 12:27:11 -08002976 if (sta && (sta->flags & WLAN_STA_WMM))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002977 p = hostapd_eid_wmm(hapd, p);
2978
2979#ifdef CONFIG_WPS
Dmitry Shmidt29333592017-01-09 12:27:11 -08002980 if (sta &&
2981 ((sta->flags & WLAN_STA_WPS) ||
2982 ((sta->flags & WLAN_STA_MAYBE_WPS) && hapd->conf->wpa))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002983 struct wpabuf *wps = wps_build_assoc_resp_ie();
2984 if (wps) {
2985 os_memcpy(p, wpabuf_head(wps), wpabuf_len(wps));
2986 p += wpabuf_len(wps);
2987 wpabuf_free(wps);
2988 }
2989 }
2990#endif /* CONFIG_WPS */
2991
2992#ifdef CONFIG_P2P
Dmitry Shmidt29333592017-01-09 12:27:11 -08002993 if (sta && sta->p2p_ie && hapd->p2p_group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002994 struct wpabuf *p2p_resp_ie;
2995 enum p2p_status_code status;
2996 switch (status_code) {
2997 case WLAN_STATUS_SUCCESS:
2998 status = P2P_SC_SUCCESS;
2999 break;
3000 case WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA:
3001 status = P2P_SC_FAIL_LIMIT_REACHED;
3002 break;
3003 default:
3004 status = P2P_SC_FAIL_INVALID_PARAMS;
3005 break;
3006 }
3007 p2p_resp_ie = p2p_group_assoc_resp_ie(hapd->p2p_group, status);
3008 if (p2p_resp_ie) {
3009 os_memcpy(p, wpabuf_head(p2p_resp_ie),
3010 wpabuf_len(p2p_resp_ie));
3011 p += wpabuf_len(p2p_resp_ie);
3012 wpabuf_free(p2p_resp_ie);
3013 }
3014 }
3015#endif /* CONFIG_P2P */
3016
3017#ifdef CONFIG_P2P_MANAGER
3018 if (hapd->conf->p2p & P2P_MANAGE)
3019 p = hostapd_eid_p2p_manage(hapd, p);
3020#endif /* CONFIG_P2P_MANAGER */
3021
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003022 p = hostapd_eid_mbo(hapd, p, buf + buflen - p);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003023
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003024 if (hapd->conf->assocresp_elements &&
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003025 (size_t) (buf + buflen - p) >=
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003026 wpabuf_len(hapd->conf->assocresp_elements)) {
3027 os_memcpy(p, wpabuf_head(hapd->conf->assocresp_elements),
3028 wpabuf_len(hapd->conf->assocresp_elements));
3029 p += wpabuf_len(hapd->conf->assocresp_elements);
3030 }
3031
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003032 send_len += p - reply->u.assoc_resp.variable;
3033
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003034#ifdef CONFIG_FILS
Dmitry Shmidt29333592017-01-09 12:27:11 -08003035 if (sta &&
3036 (sta->auth_alg == WLAN_AUTH_FILS_SK ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003037 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
3038 sta->auth_alg == WLAN_AUTH_FILS_PK) &&
3039 status_code == WLAN_STATUS_SUCCESS) {
3040 struct ieee802_11_elems elems;
3041
3042 if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) ==
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003043 ParseFailed || !elems.fils_session) {
3044 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3045 goto done;
3046 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003047
3048 /* FILS Session */
3049 *p++ = WLAN_EID_EXTENSION; /* Element ID */
3050 *p++ = 1 + FILS_SESSION_LEN; /* Length */
3051 *p++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */
3052 os_memcpy(p, elems.fils_session, FILS_SESSION_LEN);
3053 send_len += 2 + 1 + FILS_SESSION_LEN;
3054
3055 send_len = fils_encrypt_assoc(sta->wpa_sm, buf, send_len,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003056 buflen, sta->fils_hlp_resp);
3057 if (send_len < 0) {
3058 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3059 goto done;
3060 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003061 }
3062#endif /* CONFIG_FILS */
3063
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003064#ifdef CONFIG_OWE
3065 if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
3066 sta && sta->owe_ecdh &&
3067 wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE) {
3068 struct wpabuf *pub;
3069
3070 pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
3071 if (!pub) {
3072 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
3073 goto done;
3074 }
3075 /* OWE Diffie-Hellman Parameter element */
3076 *p++ = WLAN_EID_EXTENSION; /* Element ID */
3077 *p++ = 1 + 2 + wpabuf_len(pub); /* Length */
3078 *p++ = WLAN_EID_EXT_OWE_DH_PARAM; /* Element ID Extension */
3079 WPA_PUT_LE16(p, sta->owe_group);
3080 p += 2;
3081 os_memcpy(p, wpabuf_head(pub), wpabuf_len(pub));
3082 p += wpabuf_len(pub);
3083 send_len += 3 + 2 + wpabuf_len(pub);
3084 wpabuf_free(pub);
3085 }
3086#endif /* CONFIG_OWE */
3087
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003088 if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003089 wpa_printf(MSG_INFO, "Failed to send assoc resp: %s",
3090 strerror(errno));
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003091 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003092 }
3093
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003094done:
3095 os_free(buf);
3096 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003097}
3098
3099
Roshan Pius3a1667e2018-07-03 15:17:14 -07003100#ifdef CONFIG_OWE
3101u8 * owe_assoc_req_process(struct hostapd_data *hapd, struct sta_info *sta,
3102 const u8 *owe_dh, u8 owe_dh_len,
3103 u8 *owe_buf, size_t owe_buf_len, u16 *reason)
3104{
3105#ifdef CONFIG_TESTING_OPTIONS
3106 if (hapd->conf->own_ie_override) {
3107 wpa_printf(MSG_DEBUG, "OWE: Using IE override");
3108 *reason = WLAN_STATUS_SUCCESS;
3109 return wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
3110 owe_buf_len, NULL, 0);
3111 }
3112#endif /* CONFIG_TESTING_OPTIONS */
3113
3114 if (wpa_auth_sta_get_pmksa(sta->wpa_sm)) {
3115 wpa_printf(MSG_DEBUG, "OWE: Using PMKSA caching");
3116 owe_buf = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
3117 owe_buf_len, NULL, 0);
3118 *reason = WLAN_STATUS_SUCCESS;
3119 return owe_buf;
3120 }
3121
3122 *reason = owe_process_assoc_req(hapd, sta, owe_dh, owe_dh_len);
3123 if (*reason != WLAN_STATUS_SUCCESS)
3124 return NULL;
3125
3126 owe_buf = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf,
3127 owe_buf_len, NULL, 0);
3128
3129 if (sta->owe_ecdh && owe_buf) {
3130 struct wpabuf *pub;
3131
3132 pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0);
3133 if (!pub) {
3134 *reason = WLAN_STATUS_UNSPECIFIED_FAILURE;
3135 return owe_buf;
3136 }
3137
3138 /* OWE Diffie-Hellman Parameter element */
3139 *owe_buf++ = WLAN_EID_EXTENSION; /* Element ID */
3140 *owe_buf++ = 1 + 2 + wpabuf_len(pub); /* Length */
3141 *owe_buf++ = WLAN_EID_EXT_OWE_DH_PARAM; /* Element ID Extension
3142 */
3143 WPA_PUT_LE16(owe_buf, sta->owe_group);
3144 owe_buf += 2;
3145 os_memcpy(owe_buf, wpabuf_head(pub), wpabuf_len(pub));
3146 owe_buf += wpabuf_len(pub);
3147 wpabuf_free(pub);
3148 }
3149
3150 return owe_buf;
3151}
3152#endif /* CONFIG_OWE */
3153
3154
Paul Stewart092955c2017-02-06 09:13:09 -08003155#ifdef CONFIG_FILS
3156
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003157void fils_hlp_finish_assoc(struct hostapd_data *hapd, struct sta_info *sta)
Paul Stewart092955c2017-02-06 09:13:09 -08003158{
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003159 u16 reply_res;
Paul Stewart092955c2017-02-06 09:13:09 -08003160
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003161 wpa_printf(MSG_DEBUG, "FILS: Finish association with " MACSTR,
3162 MAC2STR(sta->addr));
3163 eloop_cancel_timeout(fils_hlp_timeout, hapd, sta);
3164 if (!sta->fils_pending_assoc_req)
Paul Stewart092955c2017-02-06 09:13:09 -08003165 return;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003166 reply_res = send_assoc_resp(hapd, sta, sta->addr, WLAN_STATUS_SUCCESS,
3167 sta->fils_pending_assoc_is_reassoc,
3168 sta->fils_pending_assoc_req,
3169 sta->fils_pending_assoc_req_len);
3170 os_free(sta->fils_pending_assoc_req);
3171 sta->fils_pending_assoc_req = NULL;
3172 sta->fils_pending_assoc_req_len = 0;
3173 wpabuf_free(sta->fils_hlp_resp);
3174 sta->fils_hlp_resp = NULL;
3175 wpabuf_free(sta->hlp_dhcp_discover);
3176 sta->hlp_dhcp_discover = NULL;
Paul Stewart092955c2017-02-06 09:13:09 -08003177
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003178 /*
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003179 * Remove the station in case transmission of a success response fails.
3180 * At this point the station was already added associated to the driver.
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003181 */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003182 if (reply_res != WLAN_STATUS_SUCCESS)
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003183 hostapd_drv_sta_remove(hapd, sta->addr);
Paul Stewart092955c2017-02-06 09:13:09 -08003184}
3185
3186
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003187void fils_hlp_timeout(void *eloop_ctx, void *eloop_data)
Paul Stewart092955c2017-02-06 09:13:09 -08003188{
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003189 struct hostapd_data *hapd = eloop_ctx;
3190 struct sta_info *sta = eloop_data;
Paul Stewart092955c2017-02-06 09:13:09 -08003191
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003192 wpa_printf(MSG_DEBUG,
3193 "FILS: HLP response timeout - continue with association response for "
3194 MACSTR, MAC2STR(sta->addr));
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003195 if (sta->fils_drv_assoc_finish)
3196 hostapd_notify_assoc_fils_finish(hapd, sta);
3197 else
3198 fils_hlp_finish_assoc(hapd, sta);
Paul Stewart092955c2017-02-06 09:13:09 -08003199}
3200
3201#endif /* CONFIG_FILS */
3202
3203
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003204static void handle_assoc(struct hostapd_data *hapd,
3205 const struct ieee80211_mgmt *mgmt, size_t len,
3206 int reassoc)
3207{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003208 u16 capab_info, listen_interval, seq_ctrl, fc;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003209 u16 resp = WLAN_STATUS_SUCCESS, reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003210 const u8 *pos;
3211 int left, i;
3212 struct sta_info *sta;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003213 u8 *tmp = NULL;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003214 struct hostapd_sta_wpa_psk_short *psk = NULL;
3215 char *identity = NULL;
3216 char *radius_cui = NULL;
3217#ifdef CONFIG_FILS
3218 int delay_assoc = 0;
3219#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003220
3221 if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
3222 sizeof(mgmt->u.assoc_req))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003223 wpa_printf(MSG_INFO, "handle_assoc(reassoc=%d) - too short payload (len=%lu)",
3224 reassoc, (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003225 return;
3226 }
3227
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003228#ifdef CONFIG_TESTING_OPTIONS
3229 if (reassoc) {
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07003230 if (hapd->iconf->ignore_reassoc_probability > 0.0 &&
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003231 drand48() < hapd->iconf->ignore_reassoc_probability) {
3232 wpa_printf(MSG_INFO,
3233 "TESTING: ignoring reassoc request from "
3234 MACSTR, MAC2STR(mgmt->sa));
3235 return;
3236 }
3237 } else {
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07003238 if (hapd->iconf->ignore_assoc_probability > 0.0 &&
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07003239 drand48() < hapd->iconf->ignore_assoc_probability) {
3240 wpa_printf(MSG_INFO,
3241 "TESTING: ignoring assoc request from "
3242 MACSTR, MAC2STR(mgmt->sa));
3243 return;
3244 }
3245 }
3246#endif /* CONFIG_TESTING_OPTIONS */
3247
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003248 fc = le_to_host16(mgmt->frame_control);
3249 seq_ctrl = le_to_host16(mgmt->seq_ctrl);
3250
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003251 if (reassoc) {
3252 capab_info = le_to_host16(mgmt->u.reassoc_req.capab_info);
3253 listen_interval = le_to_host16(
3254 mgmt->u.reassoc_req.listen_interval);
3255 wpa_printf(MSG_DEBUG, "reassociation request: STA=" MACSTR
3256 " capab_info=0x%02x listen_interval=%d current_ap="
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003257 MACSTR " seq_ctrl=0x%x%s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003258 MAC2STR(mgmt->sa), capab_info, listen_interval,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003259 MAC2STR(mgmt->u.reassoc_req.current_ap),
3260 seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003261 left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.reassoc_req));
3262 pos = mgmt->u.reassoc_req.variable;
3263 } else {
3264 capab_info = le_to_host16(mgmt->u.assoc_req.capab_info);
3265 listen_interval = le_to_host16(
3266 mgmt->u.assoc_req.listen_interval);
3267 wpa_printf(MSG_DEBUG, "association request: STA=" MACSTR
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003268 " capab_info=0x%02x listen_interval=%d "
3269 "seq_ctrl=0x%x%s",
3270 MAC2STR(mgmt->sa), capab_info, listen_interval,
3271 seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003272 left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req));
3273 pos = mgmt->u.assoc_req.variable;
3274 }
3275
3276 sta = ap_get_sta(hapd, mgmt->sa);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003277#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003278 if (sta && sta->auth_alg == WLAN_AUTH_FT &&
3279 (sta->flags & WLAN_STA_AUTH) == 0) {
3280 wpa_printf(MSG_DEBUG, "FT: Allow STA " MACSTR " to associate "
3281 "prior to authentication since it is using "
3282 "over-the-DS FT", MAC2STR(mgmt->sa));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003283
3284 /*
3285 * Mark station as authenticated, to avoid adding station
3286 * entry in the driver as associated and not authenticated
3287 */
3288 sta->flags |= WLAN_STA_AUTH;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003289 } else
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003290#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003291 if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) {
Dmitry Shmidt29333592017-01-09 12:27:11 -08003292 if (hapd->iface->current_mode &&
3293 hapd->iface->current_mode->mode ==
3294 HOSTAPD_MODE_IEEE80211AD) {
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003295 int acl_res;
3296 u32 session_timeout, acct_interim_interval;
3297 struct vlan_description vlan_id;
3298
3299 acl_res = ieee802_11_allowed_address(
3300 hapd, mgmt->sa, (const u8 *) mgmt, len,
3301 &session_timeout, &acct_interim_interval,
Roshan Pius3a1667e2018-07-03 15:17:14 -07003302 &vlan_id, &psk, &identity, &radius_cui, 0);
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003303 if (acl_res == HOSTAPD_ACL_REJECT) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003304 wpa_msg(hapd->msg_ctx, MSG_DEBUG,
3305 "Ignore Association Request frame from "
3306 MACSTR " due to ACL reject",
3307 MAC2STR(mgmt->sa));
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003308 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
3309 goto fail;
3310 }
3311 if (acl_res == HOSTAPD_ACL_PENDING)
3312 return;
3313
Dmitry Shmidt29333592017-01-09 12:27:11 -08003314 /* DMG/IEEE 802.11ad does not use authentication.
3315 * Allocate sta entry upon association. */
3316 sta = ap_sta_add(hapd, mgmt->sa);
3317 if (!sta) {
3318 hostapd_logger(hapd, mgmt->sa,
3319 HOSTAPD_MODULE_IEEE80211,
3320 HOSTAPD_LEVEL_INFO,
3321 "Failed to add STA");
3322 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
3323 goto fail;
3324 }
3325
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003326 acl_res = ieee802_11_set_radius_info(
3327 hapd, sta, acl_res, session_timeout,
3328 acct_interim_interval, &vlan_id, &psk,
3329 &identity, &radius_cui);
3330 if (acl_res) {
3331 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
3332 goto fail;
3333 }
3334
Dmitry Shmidt29333592017-01-09 12:27:11 -08003335 hostapd_logger(hapd, sta->addr,
3336 HOSTAPD_MODULE_IEEE80211,
3337 HOSTAPD_LEVEL_DEBUG,
3338 "Skip authentication for DMG/IEEE 802.11ad");
3339 sta->flags |= WLAN_STA_AUTH;
3340 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
3341 sta->auth_alg = WLAN_AUTH_OPEN;
3342 } else {
3343 hostapd_logger(hapd, mgmt->sa,
3344 HOSTAPD_MODULE_IEEE80211,
3345 HOSTAPD_LEVEL_INFO,
3346 "Station tried to associate before authentication (aid=%d flags=0x%x)",
3347 sta ? sta->aid : -1,
3348 sta ? sta->flags : 0);
3349 send_deauth(hapd, mgmt->sa,
3350 WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
3351 return;
3352 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003353 }
3354
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003355 if ((fc & WLAN_FC_RETRY) &&
3356 sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ &&
3357 sta->last_seq_ctrl == seq_ctrl &&
Paul Stewart092955c2017-02-06 09:13:09 -08003358 sta->last_subtype == (reassoc ? WLAN_FC_STYPE_REASSOC_REQ :
3359 WLAN_FC_STYPE_ASSOC_REQ)) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003360 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3361 HOSTAPD_LEVEL_DEBUG,
3362 "Drop repeated association frame seq_ctrl=0x%x",
3363 seq_ctrl);
3364 return;
3365 }
3366 sta->last_seq_ctrl = seq_ctrl;
3367 sta->last_subtype = reassoc ? WLAN_FC_STYPE_REASSOC_REQ :
3368 WLAN_FC_STYPE_ASSOC_REQ;
3369
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003370 if (hapd->tkip_countermeasures) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003371 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003372 goto fail;
3373 }
3374
3375 if (listen_interval > hapd->conf->max_listen_interval) {
3376 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
3377 HOSTAPD_LEVEL_DEBUG,
3378 "Too large Listen Interval (%d)",
3379 listen_interval);
3380 resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE;
3381 goto fail;
3382 }
3383
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003384#ifdef CONFIG_MBO
3385 if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) {
3386 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
3387 goto fail;
3388 }
3389#endif /* CONFIG_MBO */
3390
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003391 /*
3392 * sta->capability is used in check_assoc_ies() for RRM enabled
3393 * capability element.
3394 */
3395 sta->capability = capab_info;
3396
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003397#ifdef CONFIG_FILS
3398 if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
3399 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
3400 sta->auth_alg == WLAN_AUTH_FILS_PK) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003401 int res;
3402
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003403 /* The end of the payload is encrypted. Need to decrypt it
3404 * before parsing. */
3405
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003406 tmp = os_memdup(pos, left);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003407 if (!tmp) {
3408 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
3409 goto fail;
3410 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003411
Roshan Pius3a1667e2018-07-03 15:17:14 -07003412 res = fils_decrypt_assoc(sta->wpa_sm, sta->fils_session, mgmt,
3413 len, tmp, left);
3414 if (res < 0) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003415 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
3416 goto fail;
3417 }
3418 pos = tmp;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003419 left = res;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003420 }
3421#endif /* CONFIG_FILS */
3422
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003423 /* followed by SSID and Supported rates; and HT capabilities if 802.11n
3424 * is used */
3425 resp = check_assoc_ies(hapd, sta, pos, left, reassoc);
3426 if (resp != WLAN_STATUS_SUCCESS)
3427 goto fail;
3428
3429 if (hostapd_get_aid(hapd, sta) < 0) {
3430 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
3431 HOSTAPD_LEVEL_INFO, "No room for more AIDs");
3432 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
3433 goto fail;
3434 }
3435
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003436 sta->listen_interval = listen_interval;
3437
Roshan Pius3a1667e2018-07-03 15:17:14 -07003438 if (hapd->iface->current_mode &&
3439 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003440 sta->flags |= WLAN_STA_NONERP;
3441 for (i = 0; i < sta->supported_rates_len; i++) {
3442 if ((sta->supported_rates[i] & 0x7f) > 22) {
3443 sta->flags &= ~WLAN_STA_NONERP;
3444 break;
3445 }
3446 }
3447 if (sta->flags & WLAN_STA_NONERP && !sta->nonerp_set) {
3448 sta->nonerp_set = 1;
3449 hapd->iface->num_sta_non_erp++;
3450 if (hapd->iface->num_sta_non_erp == 1)
3451 ieee802_11_set_beacons(hapd->iface);
3452 }
3453
3454 if (!(sta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) &&
3455 !sta->no_short_slot_time_set) {
3456 sta->no_short_slot_time_set = 1;
3457 hapd->iface->num_sta_no_short_slot_time++;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003458 if (hapd->iface->current_mode &&
3459 hapd->iface->current_mode->mode ==
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003460 HOSTAPD_MODE_IEEE80211G &&
3461 hapd->iface->num_sta_no_short_slot_time == 1)
3462 ieee802_11_set_beacons(hapd->iface);
3463 }
3464
3465 if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
3466 sta->flags |= WLAN_STA_SHORT_PREAMBLE;
3467 else
3468 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
3469
3470 if (!(sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
3471 !sta->no_short_preamble_set) {
3472 sta->no_short_preamble_set = 1;
3473 hapd->iface->num_sta_no_short_preamble++;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003474 if (hapd->iface->current_mode &&
3475 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003476 && hapd->iface->num_sta_no_short_preamble == 1)
3477 ieee802_11_set_beacons(hapd->iface);
3478 }
3479
3480#ifdef CONFIG_IEEE80211N
3481 update_ht_state(hapd, sta);
3482#endif /* CONFIG_IEEE80211N */
3483
3484 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3485 HOSTAPD_LEVEL_DEBUG,
3486 "association OK (aid %d)", sta->aid);
3487 /* Station will be marked associated, after it acknowledges AssocResp
3488 */
3489 sta->flags |= WLAN_STA_ASSOC_REQ_OK;
3490
3491#ifdef CONFIG_IEEE80211W
3492 if ((sta->flags & WLAN_STA_MFP) && sta->sa_query_timed_out) {
3493 wpa_printf(MSG_DEBUG, "Allowing %sassociation after timed out "
3494 "SA Query procedure", reassoc ? "re" : "");
3495 /* TODO: Send a protected Disassociate frame to the STA using
3496 * the old key and Reason Code "Previous Authentication no
3497 * longer valid". Make sure this is only sent protected since
3498 * unprotected frame would be received by the STA that is now
3499 * trying to associate.
3500 */
3501 }
3502#endif /* CONFIG_IEEE80211W */
3503
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003504 /* Make sure that the previously registered inactivity timer will not
3505 * remove the STA immediately. */
3506 sta->timeout_next = STA_NULLFUNC;
3507
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07003508#ifdef CONFIG_TAXONOMY
3509 taxonomy_sta_info_assoc_req(hapd, sta, pos, left);
3510#endif /* CONFIG_TAXONOMY */
3511
Dmitry Shmidt29333592017-01-09 12:27:11 -08003512 sta->pending_wds_enable = 0;
3513
Paul Stewart092955c2017-02-06 09:13:09 -08003514#ifdef CONFIG_FILS
3515 if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
3516 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003517 sta->auth_alg == WLAN_AUTH_FILS_PK) {
3518 if (fils_process_hlp(hapd, sta, pos, left) > 0)
3519 delay_assoc = 1;
3520 }
Paul Stewart092955c2017-02-06 09:13:09 -08003521#endif /* CONFIG_FILS */
3522
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003523 fail:
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003524 os_free(identity);
3525 os_free(radius_cui);
3526 hostapd_free_psk_list(psk);
3527
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003528 /*
3529 * In case of a successful response, add the station to the driver.
3530 * Otherwise, the kernel may ignore Data frames before we process the
3531 * ACK frame (TX status). In case of a failure, this station will be
3532 * removed.
3533 *
3534 * Note that this is not compliant with the IEEE 802.11 standard that
3535 * states that a non-AP station should transition into the
3536 * authenticated/associated state only after the station acknowledges
3537 * the (Re)Association Response frame. However, still do this as:
3538 *
3539 * 1. In case the station does not acknowledge the (Re)Association
3540 * Response frame, it will be removed.
3541 * 2. Data frames will be dropped in the kernel until the station is
3542 * set into authorized state, and there are no significant known
3543 * issues with processing other non-Data Class 3 frames during this
3544 * window.
3545 */
Dmitry Shmidt29333592017-01-09 12:27:11 -08003546 if (resp == WLAN_STATUS_SUCCESS && sta && add_associated_sta(hapd, sta))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003547 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
3548
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003549#ifdef CONFIG_FILS
3550 if (sta) {
3551 eloop_cancel_timeout(fils_hlp_timeout, hapd, sta);
3552 os_free(sta->fils_pending_assoc_req);
3553 sta->fils_pending_assoc_req = NULL;
3554 sta->fils_pending_assoc_req_len = 0;
3555 wpabuf_free(sta->fils_hlp_resp);
3556 sta->fils_hlp_resp = NULL;
3557 }
3558 if (sta && delay_assoc && resp == WLAN_STATUS_SUCCESS) {
3559 sta->fils_pending_assoc_req = tmp;
3560 sta->fils_pending_assoc_req_len = left;
3561 sta->fils_pending_assoc_is_reassoc = reassoc;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003562 sta->fils_drv_assoc_finish = 0;
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003563 wpa_printf(MSG_DEBUG,
3564 "FILS: Waiting for HLP processing before sending (Re)Association Response frame to "
3565 MACSTR, MAC2STR(sta->addr));
3566 eloop_cancel_timeout(fils_hlp_timeout, hapd, sta);
3567 eloop_register_timeout(0, hapd->conf->fils_hlp_wait_time * 1024,
3568 fils_hlp_timeout, hapd, sta);
3569 return;
3570 }
3571#endif /* CONFIG_FILS */
3572
Dmitry Shmidt29333592017-01-09 12:27:11 -08003573 reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc, pos,
3574 left);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003575 os_free(tmp);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003576
3577 /*
3578 * Remove the station in case tranmission of a success response fails
3579 * (the STA was added associated to the driver) or if the station was
3580 * previously added unassociated.
3581 */
Dmitry Shmidt29333592017-01-09 12:27:11 -08003582 if (sta && ((reply_res != WLAN_STATUS_SUCCESS &&
3583 resp == WLAN_STATUS_SUCCESS) || sta->added_unassoc)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003584 hostapd_drv_sta_remove(hapd, sta->addr);
3585 sta->added_unassoc = 0;
3586 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003587}
3588
3589
3590static void handle_disassoc(struct hostapd_data *hapd,
3591 const struct ieee80211_mgmt *mgmt, size_t len)
3592{
3593 struct sta_info *sta;
3594
3595 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003596 wpa_printf(MSG_INFO, "handle_disassoc - too short payload (len=%lu)",
3597 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003598 return;
3599 }
3600
3601 wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d",
3602 MAC2STR(mgmt->sa),
3603 le_to_host16(mgmt->u.disassoc.reason_code));
3604
3605 sta = ap_get_sta(hapd, mgmt->sa);
3606 if (sta == NULL) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003607 wpa_printf(MSG_INFO, "Station " MACSTR " trying to disassociate, but it is not associated",
3608 MAC2STR(mgmt->sa));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003609 return;
3610 }
3611
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003612 ap_sta_set_authorized(hapd, sta, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003613 sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003614 sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003615 wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
3616 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3617 HOSTAPD_LEVEL_INFO, "disassociated");
3618 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
3619 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
3620 /* Stop Accounting and IEEE 802.1X sessions, but leave the STA
3621 * authenticated. */
3622 accounting_sta_stop(hapd, sta);
Dmitry Shmidtde47be72016-01-07 12:52:55 -08003623 ieee802_1x_free_station(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003624 if (sta->ipaddr)
3625 hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
3626 ap_sta_ip6addr_del(hapd, sta);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003627 hostapd_drv_sta_remove(hapd, sta->addr);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003628 sta->added_unassoc = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003629
3630 if (sta->timeout_next == STA_NULLFUNC ||
3631 sta->timeout_next == STA_DISASSOC) {
3632 sta->timeout_next = STA_DEAUTH;
3633 eloop_cancel_timeout(ap_handle_timer, hapd, sta);
3634 eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
3635 hapd, sta);
3636 }
3637
3638 mlme_disassociate_indication(
3639 hapd, sta, le_to_host16(mgmt->u.disassoc.reason_code));
Dmitry Shmidt29333592017-01-09 12:27:11 -08003640
3641 /* DMG/IEEE 802.11ad does not use deauthication. Deallocate sta upon
3642 * disassociation. */
3643 if (hapd->iface->current_mode &&
3644 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD) {
3645 sta->flags &= ~WLAN_STA_AUTH;
3646 wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
3647 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3648 HOSTAPD_LEVEL_DEBUG, "deauthenticated");
3649 ap_free_sta(hapd, sta);
3650 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003651}
3652
3653
3654static void handle_deauth(struct hostapd_data *hapd,
3655 const struct ieee80211_mgmt *mgmt, size_t len)
3656{
3657 struct sta_info *sta;
3658
3659 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003660 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "handle_deauth - too short "
3661 "payload (len=%lu)", (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003662 return;
3663 }
3664
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003665 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "deauthentication: STA=" MACSTR
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003666 " reason_code=%d",
3667 MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code));
3668
3669 sta = ap_get_sta(hapd, mgmt->sa);
3670 if (sta == NULL) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003671 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying "
3672 "to deauthenticate, but it is not authenticated",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003673 MAC2STR(mgmt->sa));
3674 return;
3675 }
3676
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003677 ap_sta_set_authorized(hapd, sta, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003678 sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003679 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
3680 WLAN_STA_ASSOC_REQ_OK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003681 wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
3682 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3683 HOSTAPD_LEVEL_DEBUG, "deauthenticated");
3684 mlme_deauthenticate_indication(
3685 hapd, sta, le_to_host16(mgmt->u.deauth.reason_code));
3686 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
3687 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
3688 ap_free_sta(hapd, sta);
3689}
3690
3691
3692static void handle_beacon(struct hostapd_data *hapd,
3693 const struct ieee80211_mgmt *mgmt, size_t len,
3694 struct hostapd_frame_info *fi)
3695{
3696 struct ieee802_11_elems elems;
3697
3698 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.beacon)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003699 wpa_printf(MSG_INFO, "handle_beacon - too short payload (len=%lu)",
3700 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003701 return;
3702 }
3703
3704 (void) ieee802_11_parse_elems(mgmt->u.beacon.variable,
3705 len - (IEEE80211_HDRLEN +
3706 sizeof(mgmt->u.beacon)), &elems,
3707 0);
3708
3709 ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);
3710}
3711
3712
3713#ifdef CONFIG_IEEE80211W
3714
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003715static int hostapd_sa_query_action(struct hostapd_data *hapd,
3716 const struct ieee80211_mgmt *mgmt,
3717 size_t len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003718{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003719 const u8 *end;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003720
3721 end = mgmt->u.action.u.sa_query_resp.trans_id +
3722 WLAN_SA_QUERY_TR_ID_LEN;
3723 if (((u8 *) mgmt) + len < end) {
3724 wpa_printf(MSG_DEBUG, "IEEE 802.11: Too short SA Query Action "
3725 "frame (len=%lu)", (unsigned long) len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003726 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003727 }
3728
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003729 ieee802_11_sa_query_action(hapd, mgmt->sa,
3730 mgmt->u.action.u.sa_query_resp.action,
3731 mgmt->u.action.u.sa_query_resp.trans_id);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003732 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003733}
3734
3735
3736static int robust_action_frame(u8 category)
3737{
3738 return category != WLAN_ACTION_PUBLIC &&
3739 category != WLAN_ACTION_HT;
3740}
3741#endif /* CONFIG_IEEE80211W */
3742
3743
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003744static int handle_action(struct hostapd_data *hapd,
Roshan Pius3a1667e2018-07-03 15:17:14 -07003745 const struct ieee80211_mgmt *mgmt, size_t len,
3746 unsigned int freq)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003747{
3748 struct sta_info *sta;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003749 sta = ap_get_sta(hapd, mgmt->sa);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003750
3751 if (len < IEEE80211_HDRLEN + 1) {
3752 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
3753 HOSTAPD_LEVEL_DEBUG,
3754 "handle_action - too short payload (len=%lu)",
3755 (unsigned long) len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003756 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003757 }
3758
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003759 if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
3760 (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))) {
3761 wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored Action "
3762 "frame (category=%u) from unassociated STA " MACSTR,
Dmitry Shmidtebd93af2017-02-21 13:40:44 -08003763 mgmt->u.action.category, MAC2STR(mgmt->sa));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003764 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003765 }
3766
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003767#ifdef CONFIG_IEEE80211W
3768 if (sta && (sta->flags & WLAN_STA_MFP) &&
Dmitry Shmidt18463232014-01-24 12:29:41 -08003769 !(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP)) &&
3770 robust_action_frame(mgmt->u.action.category)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003771 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
3772 HOSTAPD_LEVEL_DEBUG,
3773 "Dropped unprotected Robust Action frame from "
3774 "an MFP STA");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003775 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003776 }
3777#endif /* CONFIG_IEEE80211W */
3778
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003779 if (sta) {
3780 u16 fc = le_to_host16(mgmt->frame_control);
3781 u16 seq_ctrl = le_to_host16(mgmt->seq_ctrl);
3782
3783 if ((fc & WLAN_FC_RETRY) &&
3784 sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ &&
3785 sta->last_seq_ctrl == seq_ctrl &&
3786 sta->last_subtype == WLAN_FC_STYPE_ACTION) {
3787 hostapd_logger(hapd, sta->addr,
3788 HOSTAPD_MODULE_IEEE80211,
3789 HOSTAPD_LEVEL_DEBUG,
3790 "Drop repeated action frame seq_ctrl=0x%x",
3791 seq_ctrl);
3792 return 1;
3793 }
3794
3795 sta->last_seq_ctrl = seq_ctrl;
3796 sta->last_subtype = WLAN_FC_STYPE_ACTION;
3797 }
3798
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003799 switch (mgmt->u.action.category) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003800#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003801 case WLAN_ACTION_FT:
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07003802 if (!sta ||
3803 wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003804 len - IEEE80211_HDRLEN))
3805 break;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003806 return 1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003807#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003808 case WLAN_ACTION_WMM:
3809 hostapd_wmm_action(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003810 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003811#ifdef CONFIG_IEEE80211W
3812 case WLAN_ACTION_SA_QUERY:
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003813 return hostapd_sa_query_action(hapd, mgmt, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003814#endif /* CONFIG_IEEE80211W */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003815#ifdef CONFIG_WNM_AP
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08003816 case WLAN_ACTION_WNM:
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003817 ieee802_11_rx_wnm_action_ap(hapd, mgmt, len);
3818 return 1;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003819#endif /* CONFIG_WNM_AP */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003820#ifdef CONFIG_FST
3821 case WLAN_ACTION_FST:
3822 if (hapd->iface->fst)
3823 fst_rx_action(hapd->iface->fst, mgmt, len);
3824 else
3825 wpa_printf(MSG_DEBUG,
3826 "FST: Ignore FST Action frame - no FST attached");
3827 return 1;
3828#endif /* CONFIG_FST */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003829 case WLAN_ACTION_PUBLIC:
Dmitry Shmidt18463232014-01-24 12:29:41 -08003830 case WLAN_ACTION_PROTECTED_DUAL:
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07003831#ifdef CONFIG_IEEE80211N
Dmitry Shmidtcc00d5d2015-05-04 10:34:12 -07003832 if (len >= IEEE80211_HDRLEN + 2 &&
3833 mgmt->u.action.u.public_action.action ==
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07003834 WLAN_PA_20_40_BSS_COEX) {
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07003835 hostapd_2040_coex_action(hapd, mgmt, len);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003836 return 1;
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07003837 }
3838#endif /* CONFIG_IEEE80211N */
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003839#ifdef CONFIG_DPP
3840 if (len >= IEEE80211_HDRLEN + 6 &&
3841 mgmt->u.action.u.vs_public_action.action ==
3842 WLAN_PA_VENDOR_SPECIFIC &&
3843 WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) ==
3844 OUI_WFA &&
3845 mgmt->u.action.u.vs_public_action.variable[0] ==
3846 DPP_OUI_TYPE) {
3847 const u8 *pos, *end;
3848
3849 pos = mgmt->u.action.u.vs_public_action.oui;
3850 end = ((const u8 *) mgmt) + len;
3851 hostapd_dpp_rx_action(hapd, mgmt->sa, pos, end - pos,
Roshan Pius3a1667e2018-07-03 15:17:14 -07003852 freq);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003853 return 1;
3854 }
3855 if (len >= IEEE80211_HDRLEN + 2 &&
3856 (mgmt->u.action.u.public_action.action ==
3857 WLAN_PA_GAS_INITIAL_RESP ||
3858 mgmt->u.action.u.public_action.action ==
3859 WLAN_PA_GAS_COMEBACK_RESP)) {
3860 const u8 *pos, *end;
3861
3862 pos = &mgmt->u.action.u.public_action.action;
3863 end = ((const u8 *) mgmt) + len;
3864 gas_query_ap_rx(hapd->gas, mgmt->sa,
3865 mgmt->u.action.category,
3866 pos, end - pos, hapd->iface->freq);
3867 return 1;
3868 }
3869#endif /* CONFIG_DPP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003870 if (hapd->public_action_cb) {
3871 hapd->public_action_cb(hapd->public_action_cb_ctx,
3872 (u8 *) mgmt, len,
3873 hapd->iface->freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003874 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003875 if (hapd->public_action_cb2) {
Dmitry Shmidtf8623282013-02-20 14:34:59 -08003876 hapd->public_action_cb2(hapd->public_action_cb2_ctx,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08003877 (u8 *) mgmt, len,
3878 hapd->iface->freq);
3879 }
3880 if (hapd->public_action_cb || hapd->public_action_cb2)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003881 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003882 break;
3883 case WLAN_ACTION_VENDOR_SPECIFIC:
3884 if (hapd->vendor_action_cb) {
3885 if (hapd->vendor_action_cb(hapd->vendor_action_cb_ctx,
3886 (u8 *) mgmt, len,
3887 hapd->iface->freq) == 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003888 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003889 }
3890 break;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003891 case WLAN_ACTION_RADIO_MEASUREMENT:
3892 hostapd_handle_radio_measurement(hapd, (const u8 *) mgmt, len);
3893 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003894 }
3895
3896 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
3897 HOSTAPD_LEVEL_DEBUG,
3898 "handle_action - unknown action category %d or invalid "
3899 "frame",
3900 mgmt->u.action.category);
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003901 if (!is_multicast_ether_addr(mgmt->da) &&
3902 !(mgmt->u.action.category & 0x80) &&
3903 !is_multicast_ether_addr(mgmt->sa)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003904 struct ieee80211_mgmt *resp;
3905
3906 /*
3907 * IEEE 802.11-REVma/D9.0 - 7.3.1.11
3908 * Return the Action frame to the source without change
3909 * except that MSB of the Category set to 1.
3910 */
3911 wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action "
3912 "frame back to sender");
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003913 resp = os_memdup(mgmt, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003914 if (resp == NULL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003915 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003916 os_memcpy(resp->da, resp->sa, ETH_ALEN);
3917 os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
3918 os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
3919 resp->u.action.category |= 0x80;
3920
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003921 if (hostapd_drv_send_mlme(hapd, resp, len, 0) < 0) {
3922 wpa_printf(MSG_ERROR, "IEEE 802.11: Failed to send "
3923 "Action frame");
3924 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003925 os_free(resp);
3926 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003927
3928 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003929}
3930
3931
3932/**
3933 * ieee802_11_mgmt - process incoming IEEE 802.11 management frames
3934 * @hapd: hostapd BSS data structure (the BSS to which the management frame was
3935 * sent to)
3936 * @buf: management frame data (starting from IEEE 802.11 header)
3937 * @len: length of frame data in octets
3938 * @fi: meta data about received frame (signal level, etc.)
3939 *
3940 * Process all incoming IEEE 802.11 management frames. This will be called for
3941 * each frame received from the kernel driver through wlan#ap interface. In
3942 * addition, it can be called to re-inserted pending frames (e.g., when using
3943 * external RADIUS server as an MAC ACL).
3944 */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003945int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
3946 struct hostapd_frame_info *fi)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003947{
3948 struct ieee80211_mgmt *mgmt;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003949 u16 fc, stype;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003950 int ret = 0;
Roshan Pius3a1667e2018-07-03 15:17:14 -07003951 unsigned int freq;
3952 int ssi_signal = fi ? fi->ssi_signal : 0;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003953
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003954 if (len < 24)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003955 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003956
Roshan Pius3a1667e2018-07-03 15:17:14 -07003957 if (fi && fi->freq)
3958 freq = fi->freq;
3959 else
3960 freq = hapd->iface->freq;
3961
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003962 mgmt = (struct ieee80211_mgmt *) buf;
3963 fc = le_to_host16(mgmt->frame_control);
3964 stype = WLAN_FC_GET_STYPE(fc);
3965
3966 if (stype == WLAN_FC_STYPE_BEACON) {
3967 handle_beacon(hapd, mgmt, len, fi);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003968 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003969 }
3970
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07003971 if (!is_broadcast_ether_addr(mgmt->bssid) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003972#ifdef CONFIG_P2P
3973 /* Invitation responses can be sent with the peer MAC as BSSID */
3974 !((hapd->conf->p2p & P2P_GROUP_OWNER) &&
3975 stype == WLAN_FC_STYPE_ACTION) &&
3976#endif /* CONFIG_P2P */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003977#ifdef CONFIG_MESH
3978 !(hapd->conf->mesh & MESH_ENABLED) &&
3979#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003980 os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003981 wpa_printf(MSG_INFO, "MGMT: BSSID=" MACSTR " not our address",
3982 MAC2STR(mgmt->bssid));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003983 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003984 }
3985
3986
3987 if (stype == WLAN_FC_STYPE_PROBE_REQ) {
Roshan Pius3a1667e2018-07-03 15:17:14 -07003988 handle_probe_req(hapd, mgmt, len, ssi_signal);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003989 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003990 }
3991
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07003992 if ((!is_broadcast_ether_addr(mgmt->da) ||
3993 stype != WLAN_FC_STYPE_ACTION) &&
3994 os_memcmp(mgmt->da, hapd->own_addr, ETH_ALEN) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003995 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
3996 HOSTAPD_LEVEL_DEBUG,
3997 "MGMT: DA=" MACSTR " not our address",
3998 MAC2STR(mgmt->da));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003999 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004000 }
4001
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004002 if (hapd->iconf->track_sta_max_num)
Roshan Pius3a1667e2018-07-03 15:17:14 -07004003 sta_track_add(hapd->iface, mgmt->sa, ssi_signal);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08004004
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004005 switch (stype) {
4006 case WLAN_FC_STYPE_AUTH:
4007 wpa_printf(MSG_DEBUG, "mgmt::auth");
4008 handle_auth(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004009 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004010 break;
4011 case WLAN_FC_STYPE_ASSOC_REQ:
4012 wpa_printf(MSG_DEBUG, "mgmt::assoc_req");
4013 handle_assoc(hapd, mgmt, len, 0);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004014 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004015 break;
4016 case WLAN_FC_STYPE_REASSOC_REQ:
4017 wpa_printf(MSG_DEBUG, "mgmt::reassoc_req");
4018 handle_assoc(hapd, mgmt, len, 1);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004019 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004020 break;
4021 case WLAN_FC_STYPE_DISASSOC:
4022 wpa_printf(MSG_DEBUG, "mgmt::disassoc");
4023 handle_disassoc(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004024 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004025 break;
4026 case WLAN_FC_STYPE_DEAUTH:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004027 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "mgmt::deauth");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004028 handle_deauth(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004029 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004030 break;
4031 case WLAN_FC_STYPE_ACTION:
4032 wpa_printf(MSG_DEBUG, "mgmt::action");
Roshan Pius3a1667e2018-07-03 15:17:14 -07004033 ret = handle_action(hapd, mgmt, len, freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004034 break;
4035 default:
4036 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
4037 HOSTAPD_LEVEL_DEBUG,
4038 "unknown mgmt frame subtype %d", stype);
4039 break;
4040 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004041
4042 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004043}
4044
4045
4046static void handle_auth_cb(struct hostapd_data *hapd,
4047 const struct ieee80211_mgmt *mgmt,
4048 size_t len, int ok)
4049{
4050 u16 auth_alg, auth_transaction, status_code;
4051 struct sta_info *sta;
4052
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004053 sta = ap_get_sta(hapd, mgmt->da);
4054 if (!sta) {
4055 wpa_printf(MSG_INFO, "handle_auth_cb: STA " MACSTR " not found",
4056 MAC2STR(mgmt->da));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004057 return;
4058 }
4059
4060 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
4061 auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
4062 status_code = le_to_host16(mgmt->u.auth.status_code);
4063
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004064 if (!ok) {
4065 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
4066 HOSTAPD_LEVEL_NOTICE,
4067 "did not acknowledge authentication response");
4068 goto fail;
4069 }
4070
4071 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
4072 wpa_printf(MSG_INFO, "handle_auth_cb - too short payload (len=%lu)",
4073 (unsigned long) len);
4074 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004075 }
4076
4077 if (status_code == WLAN_STATUS_SUCCESS &&
4078 ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) ||
4079 (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) {
4080 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4081 HOSTAPD_LEVEL_INFO, "authenticated");
4082 sta->flags |= WLAN_STA_AUTH;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004083 if (sta->added_unassoc)
4084 hostapd_set_sta_flags(hapd, sta);
4085 return;
4086 }
4087
4088fail:
4089 if (status_code != WLAN_STATUS_SUCCESS && sta->added_unassoc) {
4090 hostapd_drv_sta_remove(hapd, sta->addr);
4091 sta->added_unassoc = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004092 }
4093}
4094
4095
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004096static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
4097 struct sta_info *sta,
4098 char *ifname_wds)
4099{
4100 int i;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07004101 struct hostapd_ssid *ssid = &hapd->conf->ssid;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004102
4103 if (hapd->conf->ieee802_1x || hapd->conf->wpa)
4104 return;
4105
4106 for (i = 0; i < 4; i++) {
4107 if (ssid->wep.key[i] &&
4108 hostapd_drv_set_key(ifname_wds, hapd, WPA_ALG_WEP, NULL, i,
4109 i == ssid->wep.idx, NULL, 0,
4110 ssid->wep.key[i], ssid->wep.len[i])) {
4111 wpa_printf(MSG_WARNING,
4112 "Could not set WEP keys for WDS interface; %s",
4113 ifname_wds);
4114 break;
4115 }
4116 }
4117}
4118
4119
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004120static void handle_assoc_cb(struct hostapd_data *hapd,
4121 const struct ieee80211_mgmt *mgmt,
4122 size_t len, int reassoc, int ok)
4123{
4124 u16 status;
4125 struct sta_info *sta;
4126 int new_assoc = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004127
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004128 sta = ap_get_sta(hapd, mgmt->da);
4129 if (!sta) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004130 wpa_printf(MSG_INFO, "handle_assoc_cb: STA " MACSTR " not found",
4131 MAC2STR(mgmt->da));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004132 return;
4133 }
4134
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004135 if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) :
4136 sizeof(mgmt->u.assoc_resp))) {
4137 wpa_printf(MSG_INFO,
4138 "handle_assoc_cb(reassoc=%d) - too short payload (len=%lu)",
4139 reassoc, (unsigned long) len);
4140 hostapd_drv_sta_remove(hapd, sta->addr);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07004141 return;
4142 }
4143
4144 if (reassoc)
4145 status = le_to_host16(mgmt->u.reassoc_resp.status_code);
4146 else
4147 status = le_to_host16(mgmt->u.assoc_resp.status_code);
4148
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004149 if (!ok) {
4150 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
4151 HOSTAPD_LEVEL_DEBUG,
4152 "did not acknowledge association response");
4153 sta->flags &= ~WLAN_STA_ASSOC_REQ_OK;
4154 /* The STA is added only in case of SUCCESS */
4155 if (status == WLAN_STATUS_SUCCESS)
4156 hostapd_drv_sta_remove(hapd, sta->addr);
4157
4158 return;
4159 }
4160
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004161 if (status != WLAN_STATUS_SUCCESS)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004162 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004163
4164 /* Stop previous accounting session, if one is started, and allocate
4165 * new session id for the new session. */
4166 accounting_sta_stop(hapd, sta);
4167
4168 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
4169 HOSTAPD_LEVEL_INFO,
4170 "associated (aid %d)",
4171 sta->aid);
4172
4173 if (sta->flags & WLAN_STA_ASSOC)
4174 new_assoc = 0;
4175 sta->flags |= WLAN_STA_ASSOC;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004176 sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004177 if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
4178 !hapd->conf->osen) ||
4179 sta->auth_alg == WLAN_AUTH_FILS_SK ||
4180 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
4181 sta->auth_alg == WLAN_AUTH_FILS_PK ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004182 sta->auth_alg == WLAN_AUTH_FT) {
4183 /*
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004184 * Open, static WEP, FT protocol, or FILS; no separate
4185 * authorization step.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004186 */
4187 ap_sta_set_authorized(hapd, sta, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004188 }
4189
4190 if (reassoc)
4191 mlme_reassociate_indication(hapd, sta);
4192 else
4193 mlme_associate_indication(hapd, sta);
4194
4195#ifdef CONFIG_IEEE80211W
4196 sta->sa_query_timed_out = 0;
4197#endif /* CONFIG_IEEE80211W */
4198
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004199 if (sta->eapol_sm == NULL) {
4200 /*
4201 * This STA does not use RADIUS server for EAP authentication,
4202 * so bind it to the selected VLAN interface now, since the
4203 * interface selection is not going to change anymore.
4204 */
Dmitry Shmidt83474442015-04-15 13:47:09 -07004205 if (ap_sta_bind_vlan(hapd, sta) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004206 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004207 } else if (sta->vlan_id) {
4208 /* VLAN ID already set (e.g., by PMKSA caching), so bind STA */
Dmitry Shmidt83474442015-04-15 13:47:09 -07004209 if (ap_sta_bind_vlan(hapd, sta) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07004210 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004211 }
4212
4213 hostapd_set_sta_flags(hapd, sta);
4214
Dmitry Shmidt29333592017-01-09 12:27:11 -08004215 if (!(sta->flags & WLAN_STA_WDS) && sta->pending_wds_enable) {
4216 wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for STA "
4217 MACSTR " based on pending request",
4218 MAC2STR(sta->addr));
4219 sta->pending_wds_enable = 0;
4220 sta->flags |= WLAN_STA_WDS;
4221 }
4222
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08004223 if (sta->flags & WLAN_STA_WDS) {
4224 int ret;
4225 char ifname_wds[IFNAMSIZ + 1];
4226
4227 wpa_printf(MSG_DEBUG, "Reenable 4-address WDS mode for STA "
4228 MACSTR " (aid %u)",
4229 MAC2STR(sta->addr), sta->aid);
4230 ret = hostapd_set_wds_sta(hapd, ifname_wds, sta->addr,
4231 sta->aid, 1);
4232 if (!ret)
4233 hostapd_set_wds_encryption(hapd, sta, ifname_wds);
4234 }
4235
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004236 if (sta->auth_alg == WLAN_AUTH_FT)
4237 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
4238 else
4239 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
4240 hapd->new_assoc_sta_cb(hapd, sta, !new_assoc);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004241 ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08004242
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08004243#ifdef CONFIG_FILS
4244 if ((sta->auth_alg == WLAN_AUTH_FILS_SK ||
4245 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
4246 sta->auth_alg == WLAN_AUTH_FILS_PK) &&
4247 fils_set_tk(sta->wpa_sm) < 0) {
4248 wpa_printf(MSG_DEBUG, "FILS: TK configuration failed");
4249 ap_sta_disconnect(hapd, sta, sta->addr,
4250 WLAN_REASON_UNSPECIFIED);
4251 return;
4252 }
4253#endif /* CONFIG_FILS */
4254
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08004255 if (sta->pending_eapol_rx) {
4256 struct os_reltime now, age;
4257
4258 os_get_reltime(&now);
4259 os_reltime_sub(&now, &sta->pending_eapol_rx->rx_time, &age);
4260 if (age.sec == 0 && age.usec < 200000) {
4261 wpa_printf(MSG_DEBUG,
4262 "Process pending EAPOL frame that was received from " MACSTR " just before association notification",
4263 MAC2STR(sta->addr));
4264 ieee802_1x_receive(
4265 hapd, mgmt->da,
4266 wpabuf_head(sta->pending_eapol_rx->buf),
4267 wpabuf_len(sta->pending_eapol_rx->buf));
4268 }
4269 wpabuf_free(sta->pending_eapol_rx->buf);
4270 os_free(sta->pending_eapol_rx);
4271 sta->pending_eapol_rx = NULL;
4272 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004273}
4274
4275
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004276static void handle_deauth_cb(struct hostapd_data *hapd,
4277 const struct ieee80211_mgmt *mgmt,
4278 size_t len, int ok)
4279{
4280 struct sta_info *sta;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07004281 if (is_multicast_ether_addr(mgmt->da))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004282 return;
4283 sta = ap_get_sta(hapd, mgmt->da);
4284 if (!sta) {
4285 wpa_printf(MSG_DEBUG, "handle_deauth_cb: STA " MACSTR
4286 " not found", MAC2STR(mgmt->da));
4287 return;
4288 }
4289 if (ok)
4290 wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged deauth",
4291 MAC2STR(sta->addr));
4292 else
4293 wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
4294 "deauth", MAC2STR(sta->addr));
4295
4296 ap_sta_deauth_cb(hapd, sta);
4297}
4298
4299
4300static void handle_disassoc_cb(struct hostapd_data *hapd,
4301 const struct ieee80211_mgmt *mgmt,
4302 size_t len, int ok)
4303{
4304 struct sta_info *sta;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07004305 if (is_multicast_ether_addr(mgmt->da))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004306 return;
4307 sta = ap_get_sta(hapd, mgmt->da);
4308 if (!sta) {
4309 wpa_printf(MSG_DEBUG, "handle_disassoc_cb: STA " MACSTR
4310 " not found", MAC2STR(mgmt->da));
4311 return;
4312 }
4313 if (ok)
4314 wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged disassoc",
4315 MAC2STR(sta->addr));
4316 else
4317 wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
4318 "disassoc", MAC2STR(sta->addr));
4319
4320 ap_sta_disassoc_cb(hapd, sta);
4321}
4322
4323
Dmitry Shmidt29333592017-01-09 12:27:11 -08004324static void handle_action_cb(struct hostapd_data *hapd,
4325 const struct ieee80211_mgmt *mgmt,
4326 size_t len, int ok)
4327{
4328 struct sta_info *sta;
Paul Stewart092955c2017-02-06 09:13:09 -08004329 const struct rrm_measurement_report_element *report;
Dmitry Shmidt29333592017-01-09 12:27:11 -08004330
4331 if (is_multicast_ether_addr(mgmt->da))
4332 return;
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004333#ifdef CONFIG_DPP
4334 if (len >= IEEE80211_HDRLEN + 6 &&
4335 mgmt->u.action.category == WLAN_ACTION_PUBLIC &&
4336 mgmt->u.action.u.vs_public_action.action ==
4337 WLAN_PA_VENDOR_SPECIFIC &&
4338 WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) ==
4339 OUI_WFA &&
4340 mgmt->u.action.u.vs_public_action.variable[0] ==
4341 DPP_OUI_TYPE) {
4342 const u8 *pos, *end;
4343
4344 pos = &mgmt->u.action.u.vs_public_action.variable[1];
4345 end = ((const u8 *) mgmt) + len;
4346 hostapd_dpp_tx_status(hapd, mgmt->da, pos, end - pos, ok);
4347 return;
4348 }
4349 if (len >= IEEE80211_HDRLEN + 2 &&
4350 mgmt->u.action.category == WLAN_ACTION_PUBLIC &&
4351 (mgmt->u.action.u.public_action.action ==
4352 WLAN_PA_GAS_INITIAL_REQ ||
4353 mgmt->u.action.u.public_action.action ==
4354 WLAN_PA_GAS_COMEBACK_REQ)) {
4355 const u8 *pos, *end;
4356
4357 pos = mgmt->u.action.u.public_action.variable;
4358 end = ((const u8 *) mgmt) + len;
4359 gas_query_ap_tx_status(hapd->gas, mgmt->da, pos, end - pos, ok);
4360 return;
4361 }
4362#endif /* CONFIG_DPP */
Dmitry Shmidt29333592017-01-09 12:27:11 -08004363 sta = ap_get_sta(hapd, mgmt->da);
4364 if (!sta) {
4365 wpa_printf(MSG_DEBUG, "handle_action_cb: STA " MACSTR
4366 " not found", MAC2STR(mgmt->da));
4367 return;
4368 }
4369
Paul Stewart092955c2017-02-06 09:13:09 -08004370 if (len < 24 + 5 + sizeof(*report))
Dmitry Shmidt29333592017-01-09 12:27:11 -08004371 return;
Paul Stewart092955c2017-02-06 09:13:09 -08004372 report = (const struct rrm_measurement_report_element *)
4373 &mgmt->u.action.u.rrm.variable[2];
Dmitry Shmidt29333592017-01-09 12:27:11 -08004374 if (mgmt->u.action.category == WLAN_ACTION_RADIO_MEASUREMENT &&
Paul Stewart092955c2017-02-06 09:13:09 -08004375 mgmt->u.action.u.rrm.action == WLAN_RRM_RADIO_MEASUREMENT_REQUEST &&
4376 report->eid == WLAN_EID_MEASURE_REQUEST &&
4377 report->len >= 3 &&
4378 report->type == MEASURE_TYPE_BEACON)
Dmitry Shmidt29333592017-01-09 12:27:11 -08004379 hostapd_rrm_beacon_req_tx_status(hapd, mgmt, len, ok);
4380}
4381
4382
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004383/**
4384 * ieee802_11_mgmt_cb - Process management frame TX status callback
4385 * @hapd: hostapd BSS data structure (the BSS from which the management frame
4386 * was sent from)
4387 * @buf: management frame data (starting from IEEE 802.11 header)
4388 * @len: length of frame data in octets
4389 * @stype: management frame subtype from frame control field
4390 * @ok: Whether the frame was ACK'ed
4391 */
4392void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len,
4393 u16 stype, int ok)
4394{
4395 const struct ieee80211_mgmt *mgmt;
4396 mgmt = (const struct ieee80211_mgmt *) buf;
4397
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004398#ifdef CONFIG_TESTING_OPTIONS
4399 if (hapd->ext_mgmt_frame_handling) {
Dmitry Shmidtd2986c22017-10-23 14:22:09 -07004400 size_t hex_len = 2 * len + 1;
4401 char *hex = os_malloc(hex_len);
4402
4403 if (hex) {
4404 wpa_snprintf_hex(hex, hex_len, buf, len);
4405 wpa_msg(hapd->msg_ctx, MSG_INFO,
4406 "MGMT-TX-STATUS stype=%u ok=%d buf=%s",
4407 stype, ok, hex);
4408 os_free(hex);
4409 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08004410 return;
4411 }
4412#endif /* CONFIG_TESTING_OPTIONS */
4413
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004414 switch (stype) {
4415 case WLAN_FC_STYPE_AUTH:
4416 wpa_printf(MSG_DEBUG, "mgmt::auth cb");
4417 handle_auth_cb(hapd, mgmt, len, ok);
4418 break;
4419 case WLAN_FC_STYPE_ASSOC_RESP:
4420 wpa_printf(MSG_DEBUG, "mgmt::assoc_resp cb");
4421 handle_assoc_cb(hapd, mgmt, len, 0, ok);
4422 break;
4423 case WLAN_FC_STYPE_REASSOC_RESP:
4424 wpa_printf(MSG_DEBUG, "mgmt::reassoc_resp cb");
4425 handle_assoc_cb(hapd, mgmt, len, 1, ok);
4426 break;
4427 case WLAN_FC_STYPE_PROBE_RESP:
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004428 wpa_printf(MSG_EXCESSIVE, "mgmt::proberesp cb ok=%d", ok);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004429 break;
4430 case WLAN_FC_STYPE_DEAUTH:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004431 wpa_printf(MSG_DEBUG, "mgmt::deauth cb");
4432 handle_deauth_cb(hapd, mgmt, len, ok);
4433 break;
4434 case WLAN_FC_STYPE_DISASSOC:
4435 wpa_printf(MSG_DEBUG, "mgmt::disassoc cb");
4436 handle_disassoc_cb(hapd, mgmt, len, ok);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004437 break;
4438 case WLAN_FC_STYPE_ACTION:
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08004439 wpa_printf(MSG_DEBUG, "mgmt::action cb ok=%d", ok);
Dmitry Shmidt29333592017-01-09 12:27:11 -08004440 handle_action_cb(hapd, mgmt, len, ok);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004441 break;
4442 default:
Dmitry Shmidtcce06662013-11-04 18:44:24 -08004443 wpa_printf(MSG_INFO, "unknown mgmt cb frame subtype %d", stype);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004444 break;
4445 }
4446}
4447
4448
4449int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
4450{
4451 /* TODO */
4452 return 0;
4453}
4454
4455
4456int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
4457 char *buf, size_t buflen)
4458{
4459 /* TODO */
4460 return 0;
4461}
4462
4463
4464void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
4465 const u8 *buf, size_t len, int ack)
4466{
4467 struct sta_info *sta;
4468 struct hostapd_iface *iface = hapd->iface;
4469
4470 sta = ap_get_sta(hapd, addr);
4471 if (sta == NULL && iface->num_bss > 1) {
4472 size_t j;
4473 for (j = 0; j < iface->num_bss; j++) {
4474 hapd = iface->bss[j];
4475 sta = ap_get_sta(hapd, addr);
4476 if (sta)
4477 break;
4478 }
4479 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004480 if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004481 return;
4482 if (sta->flags & WLAN_STA_PENDING_POLL) {
4483 wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending "
4484 "activity poll", MAC2STR(sta->addr),
4485 ack ? "ACKed" : "did not ACK");
4486 if (ack)
4487 sta->flags &= ~WLAN_STA_PENDING_POLL;
4488 }
4489
4490 ieee802_1x_tx_status(hapd, sta, buf, len, ack);
4491}
4492
4493
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004494void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
4495 const u8 *data, size_t len, int ack)
4496{
4497 struct sta_info *sta;
4498 struct hostapd_iface *iface = hapd->iface;
4499
4500 sta = ap_get_sta(hapd, dst);
4501 if (sta == NULL && iface->num_bss > 1) {
4502 size_t j;
4503 for (j = 0; j < iface->num_bss; j++) {
4504 hapd = iface->bss[j];
4505 sta = ap_get_sta(hapd, dst);
4506 if (sta)
4507 break;
4508 }
4509 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004510 if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
4511 wpa_printf(MSG_DEBUG, "Ignore TX status for Data frame to STA "
4512 MACSTR " that is not currently associated",
4513 MAC2STR(dst));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004514 return;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08004515 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004516
4517 ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack);
4518}
4519
4520
4521void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr)
4522{
4523 struct sta_info *sta;
4524 struct hostapd_iface *iface = hapd->iface;
4525
4526 sta = ap_get_sta(hapd, addr);
4527 if (sta == NULL && iface->num_bss > 1) {
4528 size_t j;
4529 for (j = 0; j < iface->num_bss; j++) {
4530 hapd = iface->bss[j];
4531 sta = ap_get_sta(hapd, addr);
4532 if (sta)
4533 break;
4534 }
4535 }
4536 if (sta == NULL)
4537 return;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07004538 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POLL_OK MACSTR,
4539 MAC2STR(sta->addr));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08004540 if (!(sta->flags & WLAN_STA_PENDING_POLL))
4541 return;
4542
4543 wpa_printf(MSG_DEBUG, "STA " MACSTR " ACKed pending "
4544 "activity poll", MAC2STR(sta->addr));
4545 sta->flags &= ~WLAN_STA_PENDING_POLL;
4546}
4547
4548
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004549void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
4550 int wds)
4551{
4552 struct sta_info *sta;
4553
4554 sta = ap_get_sta(hapd, src);
Dmitry Shmidt29333592017-01-09 12:27:11 -08004555 if (sta &&
4556 ((sta->flags & WLAN_STA_ASSOC) ||
4557 ((sta->flags & WLAN_STA_ASSOC_REQ_OK) && wds))) {
Dmitry Shmidtaa532512012-09-24 10:35:31 -07004558 if (!hapd->conf->wds_sta)
4559 return;
4560
Dmitry Shmidt29333592017-01-09 12:27:11 -08004561 if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK)) ==
4562 WLAN_STA_ASSOC_REQ_OK) {
4563 wpa_printf(MSG_DEBUG,
4564 "Postpone 4-address WDS mode enabling for STA "
4565 MACSTR " since TX status for AssocResp is not yet known",
4566 MAC2STR(sta->addr));
4567 sta->pending_wds_enable = 1;
4568 return;
4569 }
4570
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004571 if (wds && !(sta->flags & WLAN_STA_WDS)) {
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004572 int ret;
4573 char ifname_wds[IFNAMSIZ + 1];
4574
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004575 wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for "
4576 "STA " MACSTR " (aid %u)",
4577 MAC2STR(sta->addr), sta->aid);
4578 sta->flags |= WLAN_STA_WDS;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07004579 ret = hostapd_set_wds_sta(hapd, ifname_wds,
4580 sta->addr, sta->aid, 1);
4581 if (!ret)
4582 hostapd_set_wds_encryption(hapd, sta,
4583 ifname_wds);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004584 }
4585 return;
4586 }
4587
4588 wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA "
4589 MACSTR, MAC2STR(src));
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07004590 if (is_multicast_ether_addr(src)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004591 /* Broadcast bit set in SA?! Ignore the frame silently. */
4592 return;
4593 }
4594
4595 if (sta && (sta->flags & WLAN_STA_ASSOC_REQ_OK)) {
4596 wpa_printf(MSG_DEBUG, "Association Response to the STA has "
4597 "already been sent, but no TX status yet known - "
4598 "ignore Class 3 frame issue with " MACSTR,
4599 MAC2STR(src));
4600 return;
4601 }
4602
4603 if (sta && (sta->flags & WLAN_STA_AUTH))
4604 hostapd_drv_sta_disassoc(
4605 hapd, src,
4606 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
4607 else
4608 hostapd_drv_sta_deauth(
4609 hapd, src,
4610 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
4611}
4612
4613
4614#endif /* CONFIG_NATIVE_WINDOWS */