blob: 09850ef089d283f2a8c0437e0e86752e1ce9ba3d [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"
17#include "crypto/random.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070018#include "common/ieee802_11_defs.h"
19#include "common/ieee802_11_common.h"
20#include "common/wpa_ctrl.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080021#include "common/sae.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "radius/radius.h"
23#include "radius/radius_client.h"
24#include "p2p/p2p.h"
25#include "wps/wps.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080026#include "fst/fst.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070027#include "hostapd.h"
28#include "beacon.h"
29#include "ieee802_11_auth.h"
30#include "sta_info.h"
31#include "ieee802_1x.h"
32#include "wpa_auth.h"
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -080033#include "pmksa_cache_auth.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070034#include "wmm.h"
35#include "ap_list.h"
36#include "accounting.h"
37#include "ap_config.h"
38#include "ap_mlme.h"
39#include "p2p_hostapd.h"
40#include "ap_drv_ops.h"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080041#include "wnm_ap.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080042#include "hw_features.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070043#include "ieee802_11.h"
Dmitry Shmidtf21452a2014-02-26 10:55:25 -080044#include "dfs.h"
Dmitry Shmidt57c2d392016-02-23 13:40:19 -080045#include "mbo_ap.h"
Dmitry Shmidt849734c2016-05-27 09:59:01 -070046#include "rrm.h"
Dmitry Shmidtaca489e2016-09-28 15:44:14 -070047#include "taxonomy.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070048
49
50u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid)
51{
52 u8 *pos = eid;
53 int i, num, count;
54
55 if (hapd->iface->current_rates == NULL)
56 return eid;
57
58 *pos++ = WLAN_EID_SUPP_RATES;
59 num = hapd->iface->num_rates;
60 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
61 num++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080062 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
63 num++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070064 if (num > 8) {
65 /* rest of the rates are encoded in Extended supported
66 * rates element */
67 num = 8;
68 }
69
70 *pos++ = num;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070071 for (i = 0, count = 0; i < hapd->iface->num_rates && count < num;
72 i++) {
73 count++;
74 *pos = hapd->iface->current_rates[i].rate / 5;
75 if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
76 *pos |= 0x80;
77 pos++;
78 }
79
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080080 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht && count < 8) {
81 count++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070082 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -080083 }
84
85 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht && count < 8) {
86 count++;
87 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
88 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070089
90 return pos;
91}
92
93
94u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid)
95{
96 u8 *pos = eid;
97 int i, num, count;
98
99 if (hapd->iface->current_rates == NULL)
100 return eid;
101
102 num = hapd->iface->num_rates;
103 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht)
104 num++;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800105 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht)
106 num++;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700107 if (num <= 8)
108 return eid;
109 num -= 8;
110
111 *pos++ = WLAN_EID_EXT_SUPP_RATES;
112 *pos++ = num;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700113 for (i = 0, count = 0; i < hapd->iface->num_rates && count < num + 8;
114 i++) {
115 count++;
116 if (count <= 8)
117 continue; /* already in SuppRates IE */
118 *pos = hapd->iface->current_rates[i].rate / 5;
119 if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC)
120 *pos |= 0x80;
121 pos++;
122 }
123
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800124 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) {
125 count++;
126 if (count > 8)
127 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY;
128 }
129
130 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) {
131 count++;
132 if (count > 8)
133 *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY;
134 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700135
136 return pos;
137}
138
139
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -0700140u16 hostapd_own_capab_info(struct hostapd_data *hapd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700141{
142 int capab = WLAN_CAPABILITY_ESS;
143 int privacy;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800144 int dfs;
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700145 int i;
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800146
147 /* Check if any of configured channels require DFS */
148 dfs = hostapd_is_dfs_required(hapd->iface);
149 if (dfs < 0) {
150 wpa_printf(MSG_WARNING, "Failed to check if DFS is required; ret=%d",
151 dfs);
152 dfs = 0;
153 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700154
155 if (hapd->iface->num_sta_no_short_preamble == 0 &&
156 hapd->iconf->preamble == SHORT_PREAMBLE)
157 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
158
159 privacy = hapd->conf->ssid.wep.keys_set;
160
161 if (hapd->conf->ieee802_1x &&
162 (hapd->conf->default_wep_key_len ||
163 hapd->conf->individual_wep_key_len))
164 privacy = 1;
165
166 if (hapd->conf->wpa)
167 privacy = 1;
168
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800169#ifdef CONFIG_HS20
170 if (hapd->conf->osen)
171 privacy = 1;
172#endif /* CONFIG_HS20 */
173
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700174 if (privacy)
175 capab |= WLAN_CAPABILITY_PRIVACY;
176
177 if (hapd->iface->current_mode &&
178 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G &&
179 hapd->iface->num_sta_no_short_slot_time == 0)
180 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
181
Dmitry Shmidtf21452a2014-02-26 10:55:25 -0800182 /*
183 * Currently, Spectrum Management capability bit is set when directly
184 * requested in configuration by spectrum_mgmt_required or when AP is
185 * running on DFS channel.
186 * TODO: Also consider driver support for TPC to set Spectrum Mgmt bit
187 */
188 if (hapd->iface->current_mode &&
189 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A &&
190 (hapd->iconf->spectrum_mgmt_required || dfs))
191 capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
192
Dmitry Shmidt849734c2016-05-27 09:59:01 -0700193 for (i = 0; i < RRM_CAPABILITIES_IE_LEN; i++) {
194 if (hapd->conf->radio_measurements[i]) {
195 capab |= IEEE80211_CAP_RRM;
196 break;
197 }
198 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800199
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700200 return capab;
201}
202
203
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800204#ifndef CONFIG_NO_RC4
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700205static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta,
206 u16 auth_transaction, const u8 *challenge,
207 int iswep)
208{
209 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
210 HOSTAPD_LEVEL_DEBUG,
211 "authentication (shared key, transaction %d)",
212 auth_transaction);
213
214 if (auth_transaction == 1) {
215 if (!sta->challenge) {
216 /* Generate a pseudo-random challenge */
217 u8 key[8];
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800218
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700219 sta->challenge = os_zalloc(WLAN_AUTH_CHALLENGE_LEN);
220 if (sta->challenge == NULL)
221 return WLAN_STATUS_UNSPECIFIED_FAILURE;
222
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800223 if (os_get_random(key, sizeof(key)) < 0) {
224 os_free(sta->challenge);
225 sta->challenge = NULL;
226 return WLAN_STATUS_UNSPECIFIED_FAILURE;
227 }
228
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700229 rc4_skip(key, sizeof(key), 0,
230 sta->challenge, WLAN_AUTH_CHALLENGE_LEN);
231 }
232 return 0;
233 }
234
235 if (auth_transaction != 3)
236 return WLAN_STATUS_UNSPECIFIED_FAILURE;
237
238 /* Transaction 3 */
239 if (!iswep || !sta->challenge || !challenge ||
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700240 os_memcmp_const(sta->challenge, challenge,
241 WLAN_AUTH_CHALLENGE_LEN)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700242 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
243 HOSTAPD_LEVEL_INFO,
244 "shared key authentication - invalid "
245 "challenge-response");
246 return WLAN_STATUS_CHALLENGE_FAIL;
247 }
248
249 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
250 HOSTAPD_LEVEL_DEBUG,
251 "authentication OK (shared key)");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700252 sta->flags |= WLAN_STA_AUTH;
253 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700254 os_free(sta->challenge);
255 sta->challenge = NULL;
256
257 return 0;
258}
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800259#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700260
261
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800262static int send_auth_reply(struct hostapd_data *hapd,
263 const u8 *dst, const u8 *bssid,
264 u16 auth_alg, u16 auth_transaction, u16 resp,
265 const u8 *ies, size_t ies_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700266{
267 struct ieee80211_mgmt *reply;
268 u8 *buf;
269 size_t rlen;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800270 int reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700271
272 rlen = IEEE80211_HDRLEN + sizeof(reply->u.auth) + ies_len;
273 buf = os_zalloc(rlen);
274 if (buf == NULL)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800275 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700276
277 reply = (struct ieee80211_mgmt *) buf;
278 reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
279 WLAN_FC_STYPE_AUTH);
280 os_memcpy(reply->da, dst, ETH_ALEN);
281 os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
282 os_memcpy(reply->bssid, bssid, ETH_ALEN);
283
284 reply->u.auth.auth_alg = host_to_le16(auth_alg);
285 reply->u.auth.auth_transaction = host_to_le16(auth_transaction);
286 reply->u.auth.status_code = host_to_le16(resp);
287
288 if (ies && ies_len)
289 os_memcpy(reply->u.auth.variable, ies, ies_len);
290
291 wpa_printf(MSG_DEBUG, "authentication reply: STA=" MACSTR
292 " auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu)",
293 MAC2STR(dst), auth_alg, auth_transaction,
294 resp, (unsigned long) ies_len);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800295 if (hostapd_drv_send_mlme(hapd, reply, rlen, 0) < 0)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800296 wpa_printf(MSG_INFO, "send_auth_reply: send failed");
297 else
298 reply_res = WLAN_STATUS_SUCCESS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700299
300 os_free(buf);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800301
302 return reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700303}
304
305
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800306#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700307static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid,
308 u16 auth_transaction, u16 status,
309 const u8 *ies, size_t ies_len)
310{
311 struct hostapd_data *hapd = ctx;
312 struct sta_info *sta;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800313 int reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700314
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800315 reply_res = send_auth_reply(hapd, dst, bssid, WLAN_AUTH_FT,
316 auth_transaction, status, ies, ies_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700317
318 sta = ap_get_sta(hapd, dst);
319 if (sta == NULL)
320 return;
321
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800322 if (sta->added_unassoc && (reply_res != WLAN_STATUS_SUCCESS ||
323 status != WLAN_STATUS_SUCCESS)) {
324 hostapd_drv_sta_remove(hapd, sta->addr);
325 sta->added_unassoc = 0;
326 return;
327 }
328
329 if (status != WLAN_STATUS_SUCCESS)
330 return;
331
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700332 hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211,
333 HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)");
334 sta->flags |= WLAN_STA_AUTH;
335 mlme_authenticate_indication(hapd, sta);
336}
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800337#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700338
339
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800340#ifdef CONFIG_SAE
341
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800342#define dot11RSNASAESync 5 /* attempts */
343
344
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800345static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd,
346 struct sta_info *sta, int update)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800347{
348 struct wpabuf *buf;
349
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800350 if (hapd->conf->ssid.wpa_passphrase == NULL) {
351 wpa_printf(MSG_DEBUG, "SAE: No password available");
352 return NULL;
353 }
354
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800355 if (update &&
356 sae_prepare_commit(hapd->own_addr, sta->addr,
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800357 (u8 *) hapd->conf->ssid.wpa_passphrase,
358 os_strlen(hapd->conf->ssid.wpa_passphrase),
359 sta->sae) < 0) {
360 wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE");
361 return NULL;
362 }
363
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800364 buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800365 if (buf == NULL)
366 return NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800367 sae_write_commit(sta->sae, buf, sta->sae->tmp ?
368 sta->sae->tmp->anti_clogging_token : NULL);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800369
370 return buf;
371}
372
373
374static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd,
375 struct sta_info *sta)
376{
377 struct wpabuf *buf;
378
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800379 buf = wpabuf_alloc(SAE_CONFIRM_MAX_LEN);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800380 if (buf == NULL)
381 return NULL;
382
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800383 sae_write_confirm(sta->sae, buf);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800384
385 return buf;
386}
387
388
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800389static int auth_sae_send_commit(struct hostapd_data *hapd,
390 struct sta_info *sta,
391 const u8 *bssid, int update)
392{
393 struct wpabuf *data;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800394 int reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800395
396 data = auth_build_sae_commit(hapd, sta, update);
397 if (data == NULL)
398 return WLAN_STATUS_UNSPECIFIED_FAILURE;
399
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800400 reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 1,
401 WLAN_STATUS_SUCCESS, wpabuf_head(data),
402 wpabuf_len(data));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800403
404 wpabuf_free(data);
405
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800406 return reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800407}
408
409
410static int auth_sae_send_confirm(struct hostapd_data *hapd,
411 struct sta_info *sta,
412 const u8 *bssid)
413{
414 struct wpabuf *data;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800415 int reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800416
417 data = auth_build_sae_confirm(hapd, sta);
418 if (data == NULL)
419 return WLAN_STATUS_UNSPECIFIED_FAILURE;
420
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800421 reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 2,
422 WLAN_STATUS_SUCCESS, wpabuf_head(data),
423 wpabuf_len(data));
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800424
425 wpabuf_free(data);
426
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800427 return reply_res;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800428}
429
430
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800431static int use_sae_anti_clogging(struct hostapd_data *hapd)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800432{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800433 struct sta_info *sta;
434 unsigned int open = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800435
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800436 if (hapd->conf->sae_anti_clogging_threshold == 0)
437 return 1;
438
439 for (sta = hapd->sta_list; sta; sta = sta->next) {
440 if (!sta->sae)
441 continue;
442 if (sta->sae->state != SAE_COMMITTED &&
443 sta->sae->state != SAE_CONFIRMED)
444 continue;
445 open++;
446 if (open >= hapd->conf->sae_anti_clogging_threshold)
447 return 1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800448 }
449
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800450 return 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800451}
452
453
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800454static int check_sae_token(struct hostapd_data *hapd, const u8 *addr,
455 const u8 *token, size_t token_len)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800456{
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800457 u8 mac[SHA256_MAC_LEN];
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800458
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800459 if (token_len != SHA256_MAC_LEN)
460 return -1;
461 if (hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
462 addr, ETH_ALEN, mac) < 0 ||
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700463 os_memcmp_const(token, mac, SHA256_MAC_LEN) != 0)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800464 return -1;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800465
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800466 return 0;
467}
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800468
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800469
470static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800471 int group, const u8 *addr)
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800472{
473 struct wpabuf *buf;
474 u8 *token;
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800475 struct os_reltime now;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800476
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800477 os_get_reltime(&now);
478 if (!os_reltime_initialized(&hapd->last_sae_token_key_update) ||
479 os_reltime_expired(&now, &hapd->last_sae_token_key_update, 60)) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800480 if (random_get_bytes(hapd->sae_token_key,
481 sizeof(hapd->sae_token_key)) < 0)
482 return NULL;
483 wpa_hexdump(MSG_DEBUG, "SAE: Updated token key",
484 hapd->sae_token_key, sizeof(hapd->sae_token_key));
Dmitry Shmidt04f534e2013-12-09 15:50:16 -0800485 hapd->last_sae_token_key_update = now;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800486 }
487
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800488 buf = wpabuf_alloc(sizeof(le16) + SHA256_MAC_LEN);
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800489 if (buf == NULL)
490 return NULL;
491
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800492 wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
493
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800494 token = wpabuf_put(buf, SHA256_MAC_LEN);
495 hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
496 addr, ETH_ALEN, token);
497
498 return buf;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800499}
500
501
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800502static int sae_check_big_sync(struct sta_info *sta)
503{
504 if (sta->sae->sync > dot11RSNASAESync) {
505 sta->sae->state = SAE_NOTHING;
506 sta->sae->sync = 0;
507 return -1;
508 }
509 return 0;
510}
511
512
513static void auth_sae_retransmit_timer(void *eloop_ctx, void *eloop_data)
514{
515 struct hostapd_data *hapd = eloop_ctx;
516 struct sta_info *sta = eloop_data;
517 int ret;
518
519 if (sae_check_big_sync(sta))
520 return;
521 sta->sae->sync++;
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700522 wpa_printf(MSG_DEBUG, "SAE: Auth SAE retransmit timer for " MACSTR
523 " (sync=%d state=%d)",
524 MAC2STR(sta->addr), sta->sae->sync, sta->sae->state);
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800525
526 switch (sta->sae->state) {
527 case SAE_COMMITTED:
528 ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800529 eloop_register_timeout(0,
530 hapd->dot11RSNASAERetransPeriod * 1000,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800531 auth_sae_retransmit_timer, hapd, sta);
532 break;
533 case SAE_CONFIRMED:
534 ret = auth_sae_send_confirm(hapd, sta, hapd->own_addr);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800535 eloop_register_timeout(0,
536 hapd->dot11RSNASAERetransPeriod * 1000,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800537 auth_sae_retransmit_timer, hapd, sta);
538 break;
539 default:
540 ret = -1;
541 break;
542 }
543
544 if (ret != WLAN_STATUS_SUCCESS)
545 wpa_printf(MSG_INFO, "SAE: Failed to retransmit: ret=%d", ret);
546}
547
548
549void sae_clear_retransmit_timer(struct hostapd_data *hapd, struct sta_info *sta)
550{
551 eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta);
552}
553
554
555static void sae_set_retransmit_timer(struct hostapd_data *hapd,
556 struct sta_info *sta)
557{
558 if (!(hapd->conf->mesh & MESH_ENABLED))
559 return;
560
561 eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800562 eloop_register_timeout(0, hapd->dot11RSNASAERetransPeriod * 1000,
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800563 auth_sae_retransmit_timer, hapd, sta);
564}
565
566
Dmitry Shmidte4663042016-04-04 10:07:49 -0700567void sae_accept_sta(struct hostapd_data *hapd, struct sta_info *sta)
568{
569 sta->flags |= WLAN_STA_AUTH;
570 sta->auth_alg = WLAN_AUTH_SAE;
571 mlme_authenticate_indication(hapd, sta);
572 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
573 sta->sae->state = SAE_ACCEPTED;
574 wpa_auth_pmksa_add_sae(hapd->wpa_auth, sta->addr,
575 sta->sae->pmk, sta->sae->pmkid);
576}
577
578
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800579static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
580 const u8 *bssid, u8 auth_transaction)
581{
582 int ret;
583
584 if (auth_transaction != 1 && auth_transaction != 2)
585 return WLAN_STATUS_UNSPECIFIED_FAILURE;
586
587 switch (sta->sae->state) {
588 case SAE_NOTHING:
589 if (auth_transaction == 1) {
590 ret = auth_sae_send_commit(hapd, sta, bssid, 1);
591 if (ret)
592 return ret;
593 sta->sae->state = SAE_COMMITTED;
594
595 if (sae_process_commit(sta->sae) < 0)
596 return WLAN_STATUS_UNSPECIFIED_FAILURE;
597
598 /*
599 * In mesh case, both Commit and Confirm can be sent
600 * immediately. In infrastructure BSS, only a single
601 * Authentication frame (Commit) is expected from the AP
602 * here and the second one (Confirm) will be sent once
603 * the STA has sent its second Authentication frame
604 * (Confirm).
605 */
606 if (hapd->conf->mesh & MESH_ENABLED) {
607 /*
608 * Send both Commit and Confirm immediately
609 * based on SAE finite state machine
610 * Nothing -> Confirm transition.
611 */
612 ret = auth_sae_send_confirm(hapd, sta, bssid);
613 if (ret)
614 return ret;
615 sta->sae->state = SAE_CONFIRMED;
616 } else {
617 /*
618 * For infrastructure BSS, send only the Commit
619 * message now to get alternating sequence of
620 * Authentication frames between the AP and STA.
621 * Confirm will be sent in
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800622 * Committed -> Confirmed/Accepted transition
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800623 * when receiving Confirm from STA.
624 */
625 }
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800626 sta->sae->sync = 0;
627 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800628 } else {
629 hostapd_logger(hapd, sta->addr,
630 HOSTAPD_MODULE_IEEE80211,
631 HOSTAPD_LEVEL_DEBUG,
632 "SAE confirm before commit");
633 }
634 break;
635 case SAE_COMMITTED:
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800636 sae_clear_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800637 if (auth_transaction == 1) {
638 if (sae_process_commit(sta->sae) < 0)
639 return WLAN_STATUS_UNSPECIFIED_FAILURE;
640
641 ret = auth_sae_send_confirm(hapd, sta, bssid);
642 if (ret)
643 return ret;
644 sta->sae->state = SAE_CONFIRMED;
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800645 sta->sae->sync = 0;
646 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800647 } else if (hapd->conf->mesh & MESH_ENABLED) {
648 /*
649 * In mesh case, follow SAE finite state machine and
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800650 * send Commit now, if sync count allows.
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800651 */
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800652 if (sae_check_big_sync(sta))
653 return WLAN_STATUS_SUCCESS;
654 sta->sae->sync++;
655
Dmitry Shmidt1d755d02015-04-28 10:34:29 -0700656 ret = auth_sae_send_commit(hapd, sta, bssid, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800657 if (ret)
658 return ret;
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800659
660 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800661 } else {
662 /*
663 * For instructure BSS, send the postponed Confirm from
664 * Nothing -> Confirmed transition that was reduced to
665 * Nothing -> Committed above.
666 */
667 ret = auth_sae_send_confirm(hapd, sta, bssid);
668 if (ret)
669 return ret;
670
671 sta->sae->state = SAE_CONFIRMED;
672
673 /*
674 * Since this was triggered on Confirm RX, run another
675 * step to get to Accepted without waiting for
676 * additional events.
677 */
678 return sae_sm_step(hapd, sta, bssid, auth_transaction);
679 }
680 break;
681 case SAE_CONFIRMED:
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800682 sae_clear_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800683 if (auth_transaction == 1) {
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800684 if (sae_check_big_sync(sta))
685 return WLAN_STATUS_SUCCESS;
686 sta->sae->sync++;
687
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800688 ret = auth_sae_send_commit(hapd, sta, bssid, 1);
689 if (ret)
690 return ret;
691
692 if (sae_process_commit(sta->sae) < 0)
693 return WLAN_STATUS_UNSPECIFIED_FAILURE;
694
695 ret = auth_sae_send_confirm(hapd, sta, bssid);
696 if (ret)
697 return ret;
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800698
699 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800700 } else {
Dmitry Shmidte4663042016-04-04 10:07:49 -0700701 sae_accept_sta(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800702 }
703 break;
704 case SAE_ACCEPTED:
705 if (auth_transaction == 1) {
706 wpa_printf(MSG_DEBUG, "SAE: remove the STA (" MACSTR
707 ") doing reauthentication",
708 MAC2STR(sta->addr));
709 ap_free_sta(hapd, sta);
Dmitry Shmidte4663042016-04-04 10:07:49 -0700710 wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800711 } else {
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800712 if (sae_check_big_sync(sta))
713 return WLAN_STATUS_SUCCESS;
714 sta->sae->sync++;
715
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800716 ret = auth_sae_send_confirm(hapd, sta, bssid);
717 sae_clear_temp_data(sta->sae);
718 if (ret)
719 return ret;
720 }
721 break;
722 default:
723 wpa_printf(MSG_ERROR, "SAE: invalid state %d",
724 sta->sae->state);
725 return WLAN_STATUS_UNSPECIFIED_FAILURE;
726 }
727 return WLAN_STATUS_SUCCESS;
728}
729
730
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700731static void sae_pick_next_group(struct hostapd_data *hapd, struct sta_info *sta)
732{
733 struct sae_data *sae = sta->sae;
734 int i, *groups = hapd->conf->sae_groups;
735
736 if (sae->state != SAE_COMMITTED)
737 return;
738
739 wpa_printf(MSG_DEBUG, "SAE: Previously selected group: %d", sae->group);
740
741 for (i = 0; groups && groups[i] > 0; i++) {
742 if (sae->group == groups[i])
743 break;
744 }
745
746 if (!groups || groups[i] <= 0) {
747 wpa_printf(MSG_DEBUG,
748 "SAE: Previously selected group not found from the current configuration");
749 return;
750 }
751
752 for (;;) {
753 i++;
754 if (groups[i] <= 0) {
755 wpa_printf(MSG_DEBUG,
756 "SAE: No alternative group enabled");
757 return;
758 }
759
760 if (sae_set_group(sae, groups[i]) < 0)
761 continue;
762
763 break;
764 }
765 wpa_printf(MSG_DEBUG, "SAE: Selected new group: %d", groups[i]);
766}
767
768
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800769static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
770 const struct ieee80211_mgmt *mgmt, size_t len,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800771 u16 auth_transaction, u16 status_code)
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800772{
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800773 int resp = WLAN_STATUS_SUCCESS;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800774 struct wpabuf *data = NULL;
775
776 if (!sta->sae) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800777 if (auth_transaction != 1 ||
778 status_code != WLAN_STATUS_SUCCESS) {
779 resp = -1;
780 goto remove_sta;
781 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800782 sta->sae = os_zalloc(sizeof(*sta->sae));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800783 if (!sta->sae) {
784 resp = -1;
785 goto remove_sta;
786 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800787 sta->sae->state = SAE_NOTHING;
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800788 sta->sae->sync = 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800789 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800790
Dmitry Shmidte4663042016-04-04 10:07:49 -0700791 if (sta->mesh_sae_pmksa_caching) {
792 wpa_printf(MSG_DEBUG,
793 "SAE: Cancel use of mesh PMKSA caching because peer starts SAE authentication");
794 wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr);
795 sta->mesh_sae_pmksa_caching = 0;
796 }
797
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800798 if (auth_transaction == 1) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800799 const u8 *token = NULL, *pos, *end;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800800 size_t token_len = 0;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800801 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
802 HOSTAPD_LEVEL_DEBUG,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800803 "start SAE authentication (RX commit, status=%u)",
804 status_code);
805
806 if ((hapd->conf->mesh & MESH_ENABLED) &&
807 status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
808 sta->sae->tmp) {
809 pos = mgmt->u.auth.variable;
810 end = ((const u8 *) mgmt) + len;
811 if (pos + sizeof(le16) > end) {
812 wpa_printf(MSG_ERROR,
813 "SAE: Too short anti-clogging token request");
814 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
815 goto reply;
816 }
817 resp = sae_group_allowed(sta->sae,
818 hapd->conf->sae_groups,
819 WPA_GET_LE16(pos));
820 if (resp != WLAN_STATUS_SUCCESS) {
821 wpa_printf(MSG_ERROR,
822 "SAE: Invalid group in anti-clogging token request");
823 goto reply;
824 }
825 pos += sizeof(le16);
826
827 wpabuf_free(sta->sae->tmp->anti_clogging_token);
828 sta->sae->tmp->anti_clogging_token =
829 wpabuf_alloc_copy(pos, end - pos);
830 if (sta->sae->tmp->anti_clogging_token == NULL) {
831 wpa_printf(MSG_ERROR,
832 "SAE: Failed to alloc for anti-clogging token");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800833 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
834 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800835 }
836
837 /*
838 * IEEE Std 802.11-2012, 11.3.8.6.4: If the Status code
839 * is 76, a new Commit Message shall be constructed
840 * with the Anti-Clogging Token from the received
841 * Authentication frame, and the commit-scalar and
842 * COMMIT-ELEMENT previously sent.
843 */
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800844 resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 0);
845 if (resp != WLAN_STATUS_SUCCESS) {
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800846 wpa_printf(MSG_ERROR,
847 "SAE: Failed to send commit message");
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800848 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800849 }
850 sta->sae->state = SAE_COMMITTED;
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800851 sta->sae->sync = 0;
852 sae_set_retransmit_timer(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800853 return;
854 }
855
Dmitry Shmidtd5ab1b52016-06-21 12:38:41 -0700856 if ((hapd->conf->mesh & MESH_ENABLED) &&
857 status_code ==
858 WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED &&
859 sta->sae->tmp) {
860 wpa_printf(MSG_DEBUG,
861 "SAE: Peer did not accept our SAE group");
862 sae_pick_next_group(hapd, sta);
863 goto remove_sta;
864 }
865
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800866 if (status_code != WLAN_STATUS_SUCCESS)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800867 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800868
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800869 resp = sae_parse_commit(sta->sae, mgmt->u.auth.variable,
870 ((const u8 *) mgmt) + len -
871 mgmt->u.auth.variable, &token,
872 &token_len, hapd->conf->sae_groups);
Dmitry Shmidt41712582015-06-29 11:02:15 -0700873 if (resp == SAE_SILENTLY_DISCARD) {
874 wpa_printf(MSG_DEBUG,
875 "SAE: Drop commit message from " MACSTR " due to reflection attack",
876 MAC2STR(sta->addr));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800877 goto remove_sta;
Dmitry Shmidt41712582015-06-29 11:02:15 -0700878 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800879 if (token && check_sae_token(hapd, sta->addr, token, token_len)
880 < 0) {
881 wpa_printf(MSG_DEBUG, "SAE: Drop commit message with "
882 "incorrect token from " MACSTR,
883 MAC2STR(sta->addr));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800884 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
885 goto remove_sta;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800886 }
887
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800888 if (resp != WLAN_STATUS_SUCCESS)
889 goto reply;
890
891 if (!token && use_sae_anti_clogging(hapd)) {
892 wpa_printf(MSG_DEBUG,
893 "SAE: Request anti-clogging token from "
894 MACSTR, MAC2STR(sta->addr));
895 data = auth_build_token_req(hapd, sta->sae->group,
896 sta->addr);
897 resp = WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ;
898 if (hapd->conf->mesh & MESH_ENABLED)
899 sta->sae->state = SAE_NOTHING;
900 goto reply;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800901 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800902
903 resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800904 } else if (auth_transaction == 2) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800905 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
906 HOSTAPD_LEVEL_DEBUG,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800907 "SAE authentication (RX confirm, status=%u)",
908 status_code);
909 if (status_code != WLAN_STATUS_SUCCESS)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800910 goto remove_sta;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800911 if (sta->sae->state >= SAE_CONFIRMED ||
912 !(hapd->conf->mesh & MESH_ENABLED)) {
913 if (sae_check_confirm(sta->sae, mgmt->u.auth.variable,
914 ((u8 *) mgmt) + len -
915 mgmt->u.auth.variable) < 0) {
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800916 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800917 goto reply;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -0800918 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800919 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800920 resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800921 } else {
922 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
923 HOSTAPD_LEVEL_DEBUG,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800924 "unexpected SAE authentication transaction %u (status=%u)",
925 auth_transaction, status_code);
926 if (status_code != WLAN_STATUS_SUCCESS)
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800927 goto remove_sta;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800928 resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
929 }
930
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800931reply:
932 if (resp != WLAN_STATUS_SUCCESS) {
933 send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE,
934 auth_transaction, resp,
935 data ? wpabuf_head(data) : (u8 *) "",
936 data ? wpabuf_len(data) : 0);
937 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -0800938
939remove_sta:
940 if (sta->added_unassoc && (resp != WLAN_STATUS_SUCCESS ||
941 status_code != WLAN_STATUS_SUCCESS)) {
942 hostapd_drv_sta_remove(hapd, sta->addr);
943 sta->added_unassoc = 0;
944 }
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800945 wpabuf_free(data);
946}
Dmitry Shmidtff787d52015-01-12 13:01:47 -0800947
948
949/**
950 * auth_sae_init_committed - Send COMMIT and start SAE in committed state
951 * @hapd: BSS data for the device initiating the authentication
952 * @sta: the peer to which commit authentication frame is sent
953 *
954 * This function implements Init event handling (IEEE Std 802.11-2012,
955 * 11.3.8.6.3) in which initial COMMIT message is sent. Prior to calling, the
956 * sta->sae structure should be initialized appropriately via a call to
957 * sae_prepare_commit().
958 */
959int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta)
960{
961 int ret;
962
963 if (!sta->sae || !sta->sae->tmp)
964 return -1;
965
966 if (sta->sae->state != SAE_NOTHING)
967 return -1;
968
969 ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0);
970 if (ret)
971 return -1;
972
973 sta->sae->state = SAE_COMMITTED;
974 sta->sae->sync = 0;
975 sae_set_retransmit_timer(hapd, sta);
976
977 return 0;
978}
979
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800980#endif /* CONFIG_SAE */
981
982
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -0800983static u16 wpa_res_to_status_code(int res)
984{
985 if (res == WPA_INVALID_GROUP)
986 return WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
987 if (res == WPA_INVALID_PAIRWISE)
988 return WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
989 if (res == WPA_INVALID_AKMP)
990 return WLAN_STATUS_AKMP_NOT_VALID;
991 if (res == WPA_ALLOC_FAIL)
992 return WLAN_STATUS_UNSPECIFIED_FAILURE;
993#ifdef CONFIG_IEEE80211W
994 if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION)
995 return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
996 if (res == WPA_INVALID_MGMT_GROUP_CIPHER)
997 return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION;
998#endif /* CONFIG_IEEE80211W */
999 if (res == WPA_INVALID_MDIE)
1000 return WLAN_STATUS_INVALID_MDIE;
1001 if (res != WPA_IE_OK)
1002 return WLAN_STATUS_INVALID_IE;
1003 return WLAN_STATUS_SUCCESS;
1004}
1005
1006
1007#ifdef CONFIG_FILS
1008
1009static void handle_auth_fils_finish(struct hostapd_data *hapd,
1010 struct sta_info *sta, u16 resp,
1011 struct rsn_pmksa_cache_entry *pmksa,
1012 struct wpabuf *erp_resp,
1013 const u8 *msk, size_t msk_len);
1014
1015static void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta,
1016 const struct ieee80211_mgmt *mgmt, size_t len,
1017 u16 auth_transaction, u16 status_code)
1018{
1019 u16 resp = WLAN_STATUS_SUCCESS;
1020 const u8 *pos, *end;
1021 struct ieee802_11_elems elems;
1022 int res;
1023 struct wpa_ie_data rsn;
1024 struct rsn_pmksa_cache_entry *pmksa = NULL;
1025
1026 if (auth_transaction != 1 || status_code != WLAN_STATUS_SUCCESS)
1027 return;
1028
1029 pos = mgmt->u.auth.variable;
1030 end = ((const u8 *) mgmt) + len;
1031
1032 wpa_hexdump(MSG_DEBUG, "FILS: Authentication frame fields",
1033 pos, end - pos);
1034
1035 /* TODO: Finite Cyclic Group when using PK or PFS */
1036 /* TODO: Element when using PK or PFS */
1037
1038 wpa_hexdump(MSG_DEBUG, "FILS: Remaining IEs", pos, end - pos);
1039 if (ieee802_11_parse_elems(pos, end - pos, &elems, 1) == ParseFailed) {
1040 wpa_printf(MSG_DEBUG, "FILS: Could not parse elements");
1041 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1042 goto fail;
1043 }
1044
1045 /* RSNE */
1046 wpa_hexdump(MSG_DEBUG, "FILS: RSN element",
1047 elems.rsn_ie, elems.rsn_ie_len);
1048 if (!elems.rsn_ie ||
1049 wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
1050 &rsn) < 0) {
1051 wpa_printf(MSG_DEBUG, "FILS: No valid RSN element");
1052 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1053 goto fail;
1054 }
1055
1056 if (!sta->wpa_sm)
1057 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr,
1058 NULL);
1059 if (!sta->wpa_sm) {
1060 wpa_printf(MSG_DEBUG,
1061 "FILS: Failed to initialize RSN state machine");
1062 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1063 goto fail;
1064 }
1065
1066 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
1067 elems.rsn_ie - 2, elems.rsn_ie_len + 2,
1068 elems.mdie, elems.mdie_len);
1069 resp = wpa_res_to_status_code(res);
1070 if (resp != WLAN_STATUS_SUCCESS)
1071 goto fail;
1072
1073 /* TODO: MDE when using FILS+FT */
1074 /* TODO: FTE when using FILS+FT */
1075
1076 if (!elems.fils_nonce) {
1077 wpa_printf(MSG_DEBUG, "FILS: No FILS Nonce field");
1078 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1079 goto fail;
1080 }
1081 wpa_hexdump(MSG_DEBUG, "FILS: SNonce", elems.fils_nonce,
1082 FILS_NONCE_LEN);
1083 os_memcpy(sta->fils_snonce, elems.fils_nonce, FILS_NONCE_LEN);
1084
1085 /* PMKID List */
1086 if (rsn.pmkid && rsn.num_pmkid > 0) {
1087 u8 num;
1088 const u8 *pmkid;
1089
1090 wpa_hexdump(MSG_DEBUG, "FILS: PMKID List",
1091 rsn.pmkid, rsn.num_pmkid * PMKID_LEN);
1092
1093 pmkid = rsn.pmkid;
1094 num = rsn.num_pmkid;
1095 while (num) {
1096 wpa_hexdump(MSG_DEBUG, "FILS: PMKID", pmkid, PMKID_LEN);
1097 pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr,
1098 pmkid);
1099 if (pmksa)
1100 break;
1101 pmkid += PMKID_LEN;
1102 num--;
1103 }
1104 }
1105 if (pmksa && wpa_auth_sta_key_mgmt(sta->wpa_sm) != pmksa->akmp) {
1106 wpa_printf(MSG_DEBUG,
1107 "FILS: Matching PMKSA cache entry has different AKMP (0x%x != 0x%x) - ignore",
1108 wpa_auth_sta_key_mgmt(sta->wpa_sm), pmksa->akmp);
1109 pmksa = NULL;
1110 }
1111 if (pmksa)
1112 wpa_printf(MSG_DEBUG, "FILS: Found matching PMKSA cache entry");
1113
1114 /* FILS Session */
1115 if (!elems.fils_session) {
1116 wpa_printf(MSG_DEBUG, "FILS: No FILS Session element");
1117 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1118 goto fail;
1119 }
1120 wpa_hexdump(MSG_DEBUG, "FILS: FILS Session", elems.fils_session,
1121 FILS_SESSION_LEN);
1122 os_memcpy(sta->fils_session, elems.fils_session, FILS_SESSION_LEN);
1123
1124 /* FILS Wrapped Data */
1125 if (elems.fils_wrapped_data) {
1126 wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data",
1127 elems.fils_wrapped_data,
1128 elems.fils_wrapped_data_len);
1129 if (!pmksa) {
1130#ifndef CONFIG_NO_RADIUS
1131 if (!sta->eapol_sm) {
1132 sta->eapol_sm =
1133 ieee802_1x_alloc_eapol_sm(hapd, sta);
1134 }
1135 wpa_printf(MSG_DEBUG,
1136 "FILS: Forward EAP-Identity/Re-auth Start to authentication server");
1137 ieee802_1x_encapsulate_radius(
1138 hapd, sta, elems.fils_wrapped_data,
1139 elems.fils_wrapped_data_len);
1140 wpa_printf(MSG_DEBUG,
1141 "FILS: Will send Authentication frame once the response from authentication server is available");
1142 sta->flags |= WLAN_STA_PENDING_FILS_ERP;
1143 return;
1144#else /* CONFIG_NO_RADIUS */
1145 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1146 goto fail;
1147#endif /* CONFIG_NO_RADIUS */
1148 }
1149 }
1150
1151fail:
1152 handle_auth_fils_finish(hapd, sta, resp, pmksa, NULL, NULL, 0);
1153}
1154
1155
1156static void handle_auth_fils_finish(struct hostapd_data *hapd,
1157 struct sta_info *sta, u16 resp,
1158 struct rsn_pmksa_cache_entry *pmksa,
1159 struct wpabuf *erp_resp,
1160 const u8 *msk, size_t msk_len)
1161{
1162 u8 fils_nonce[FILS_NONCE_LEN];
1163 size_t ielen;
1164 struct wpabuf *data = NULL;
1165 const u8 *ie;
1166 u8 *ie_buf = NULL;
1167 const u8 *pmk = NULL;
1168 size_t pmk_len = 0;
1169
1170 if (resp != WLAN_STATUS_SUCCESS)
1171 goto fail;
1172
1173 ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen);
1174 if (!ie) {
1175 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1176 goto fail;
1177 }
1178 if (pmksa) {
1179 /* Add PMKID of the selected PMKSA into RSNE */
1180 ie_buf = os_malloc(ielen + 2 + 2 + PMKID_LEN);
1181 if (!ie_buf) {
1182 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1183 goto fail;
1184 }
1185 os_memcpy(ie_buf, ie, ielen);
1186 if (wpa_insert_pmkid(ie_buf, &ielen, pmksa->pmkid) < 0) {
1187 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1188 goto fail;
1189 }
1190 ie = ie_buf;
1191 }
1192
1193 if (random_get_bytes(fils_nonce, FILS_NONCE_LEN) < 0) {
1194 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1195 goto fail;
1196 }
1197 wpa_hexdump(MSG_DEBUG, "RSN: Generated FILS Nonce",
1198 fils_nonce, FILS_NONCE_LEN);
1199
1200 data = wpabuf_alloc(1000 + ielen);
1201 if (!data) {
1202 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1203 goto fail;
1204 }
1205
1206 /* TODO: Finite Cyclic Group when using PK or PFS */
1207 /* TODO: Element when using PK or PFS */
1208
1209 /* RSNE */
1210 wpabuf_put_data(data, ie, ielen);
1211
1212 /* TODO: MDE when using FILS+FT */
1213 /* TODO: FTE when using FILS+FT */
1214
1215 /* FILS Nonce */
1216 wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
1217 wpabuf_put_u8(data, 1 + FILS_NONCE_LEN); /* Length */
1218 /* Element ID Extension */
1219 wpabuf_put_u8(data, WLAN_EID_EXT_FILS_NONCE);
1220 wpabuf_put_data(data, fils_nonce, FILS_NONCE_LEN);
1221
1222 /* FILS Session */
1223 wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
1224 wpabuf_put_u8(data, 1 + FILS_SESSION_LEN); /* Length */
1225 /* Element ID Extension */
1226 wpabuf_put_u8(data, WLAN_EID_EXT_FILS_SESSION);
1227 wpabuf_put_data(data, sta->fils_session, FILS_SESSION_LEN);
1228
1229 /* FILS Wrapped Data */
1230 if (!pmksa && erp_resp) {
1231 wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */
1232 wpabuf_put_u8(data, 1 + wpabuf_len(erp_resp)); /* Length */
1233 /* Element ID Extension */
1234 wpabuf_put_u8(data, WLAN_EID_EXT_FILS_WRAPPED_DATA);
1235 wpabuf_put_buf(data, erp_resp);
1236
1237 pmk = msk;
1238 pmk_len = msk_len > PMK_LEN ? PMK_LEN : msk_len;
1239 } else if (pmksa) {
1240 pmk = pmksa->pmk;
1241 pmk_len = pmksa->pmk_len;
1242 }
1243
1244 if (!pmk) {
1245 wpa_printf(MSG_DEBUG, "FILS: No PMK available");
1246 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1247 wpabuf_free(data);
1248 data = NULL;
1249 goto fail;
1250 }
1251
1252 if (fils_auth_pmk_to_ptk(sta->wpa_sm, pmk, pmk_len,
1253 sta->fils_snonce, fils_nonce) < 0) {
1254 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1255 wpabuf_free(data);
1256 data = NULL;
1257 goto fail;
1258 }
1259
1260fail:
1261 send_auth_reply(hapd, sta->addr, hapd->own_addr, WLAN_AUTH_FILS_SK, 2,
1262 resp,
1263 data ? wpabuf_head(data) : (u8 *) "",
1264 data ? wpabuf_len(data) : 0);
1265 wpabuf_free(data);
1266
1267 if (resp == WLAN_STATUS_SUCCESS) {
1268 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1269 HOSTAPD_LEVEL_DEBUG,
1270 "authentication OK (FILS)");
1271 sta->flags |= WLAN_STA_AUTH;
1272 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
1273 sta->auth_alg = WLAN_AUTH_FILS_SK;
1274 mlme_authenticate_indication(hapd, sta);
1275 }
1276
1277 os_free(ie_buf);
1278}
1279
1280
1281void ieee802_11_finish_fils_auth(struct hostapd_data *hapd,
1282 struct sta_info *sta, int success,
1283 struct wpabuf *erp_resp,
1284 const u8 *msk, size_t msk_len)
1285{
1286 sta->flags &= ~WLAN_STA_PENDING_FILS_ERP;
1287 handle_auth_fils_finish(hapd, sta, success ? WLAN_STATUS_SUCCESS :
1288 WLAN_STATUS_UNSPECIFIED_FAILURE, NULL,
1289 erp_resp, msk, msk_len);
1290}
1291
1292#endif /* CONFIG_FILS */
1293
1294
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001295static void handle_auth(struct hostapd_data *hapd,
1296 const struct ieee80211_mgmt *mgmt, size_t len)
1297{
1298 u16 auth_alg, auth_transaction, status_code;
1299 u16 resp = WLAN_STATUS_SUCCESS;
1300 struct sta_info *sta = NULL;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001301 int res, reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001302 u16 fc;
1303 const u8 *challenge = NULL;
1304 u32 session_timeout, acct_interim_interval;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001305 struct vlan_description vlan_id;
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001306 struct hostapd_sta_wpa_psk_short *psk = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001307 u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
1308 size_t resp_ies_len = 0;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001309 char *identity = NULL;
1310 char *radius_cui = NULL;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001311 u16 seq_ctrl;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001312
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001313 os_memset(&vlan_id, 0, sizeof(vlan_id));
1314
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001315 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001316 wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
1317 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001318 return;
1319 }
1320
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001321#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07001322 if (hapd->iconf->ignore_auth_probability > 0.0 &&
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07001323 drand48() < hapd->iconf->ignore_auth_probability) {
1324 wpa_printf(MSG_INFO,
1325 "TESTING: ignoring auth frame from " MACSTR,
1326 MAC2STR(mgmt->sa));
1327 return;
1328 }
1329#endif /* CONFIG_TESTING_OPTIONS */
1330
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001331 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
1332 auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
1333 status_code = le_to_host16(mgmt->u.auth.status_code);
1334 fc = le_to_host16(mgmt->frame_control);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001335 seq_ctrl = le_to_host16(mgmt->seq_ctrl);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001336
1337 if (len >= IEEE80211_HDRLEN + sizeof(mgmt->u.auth) +
1338 2 + WLAN_AUTH_CHALLENGE_LEN &&
1339 mgmt->u.auth.variable[0] == WLAN_EID_CHALLENGE &&
1340 mgmt->u.auth.variable[1] == WLAN_AUTH_CHALLENGE_LEN)
1341 challenge = &mgmt->u.auth.variable[2];
1342
1343 wpa_printf(MSG_DEBUG, "authentication: STA=" MACSTR " auth_alg=%d "
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001344 "auth_transaction=%d status_code=%d wep=%d%s "
1345 "seq_ctrl=0x%x%s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001346 MAC2STR(mgmt->sa), auth_alg, auth_transaction,
1347 status_code, !!(fc & WLAN_FC_ISWEP),
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001348 challenge ? " challenge" : "",
1349 seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001350
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001351#ifdef CONFIG_NO_RC4
1352 if (auth_alg == WLAN_AUTH_SHARED_KEY) {
1353 wpa_printf(MSG_INFO,
1354 "Unsupported authentication algorithm (%d)",
1355 auth_alg);
1356 resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1357 goto fail;
1358 }
1359#endif /* CONFIG_NO_RC4 */
1360
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001361 if (hapd->tkip_countermeasures) {
1362 resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
1363 goto fail;
1364 }
1365
1366 if (!(((hapd->conf->auth_algs & WPA_AUTH_ALG_OPEN) &&
1367 auth_alg == WLAN_AUTH_OPEN) ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001368#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001369 (hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001370 auth_alg == WLAN_AUTH_FT) ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001371#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001372#ifdef CONFIG_SAE
1373 (hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) &&
1374 auth_alg == WLAN_AUTH_SAE) ||
1375#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001376#ifdef CONFIG_FILS
1377 (hapd->conf->wpa && wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt) &&
1378 auth_alg == WLAN_AUTH_FILS_SK) ||
1379#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001380 ((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) &&
1381 auth_alg == WLAN_AUTH_SHARED_KEY))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001382 wpa_printf(MSG_INFO, "Unsupported authentication algorithm (%d)",
1383 auth_alg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001384 resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1385 goto fail;
1386 }
1387
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001388 if (!(auth_transaction == 1 || auth_alg == WLAN_AUTH_SAE ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001389 (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001390 wpa_printf(MSG_INFO, "Unknown authentication transaction number (%d)",
1391 auth_transaction);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001392 resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION;
1393 goto fail;
1394 }
1395
1396 if (os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001397 wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to authenticate",
1398 MAC2STR(mgmt->sa));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001399 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1400 goto fail;
1401 }
1402
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001403 if (hapd->conf->no_auth_if_seen_on) {
1404 struct hostapd_data *other;
1405
1406 other = sta_track_seen_on(hapd->iface, mgmt->sa,
1407 hapd->conf->no_auth_if_seen_on);
1408 if (other) {
1409 u8 *pos;
1410 u32 info;
1411 u8 op_class, channel, phytype;
1412
1413 wpa_printf(MSG_DEBUG, "%s: Reject authentication from "
1414 MACSTR " since STA has been seen on %s",
1415 hapd->conf->iface, MAC2STR(mgmt->sa),
1416 hapd->conf->no_auth_if_seen_on);
1417
1418 resp = WLAN_STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION;
1419 pos = &resp_ies[0];
1420 *pos++ = WLAN_EID_NEIGHBOR_REPORT;
1421 *pos++ = 13;
1422 os_memcpy(pos, other->own_addr, ETH_ALEN);
1423 pos += ETH_ALEN;
1424 info = 0; /* TODO: BSSID Information */
1425 WPA_PUT_LE32(pos, info);
1426 pos += 4;
1427 if (other->iconf->hw_mode == HOSTAPD_MODE_IEEE80211AD)
1428 phytype = 8; /* dmg */
1429 else if (other->iconf->ieee80211ac)
1430 phytype = 9; /* vht */
1431 else if (other->iconf->ieee80211n)
1432 phytype = 7; /* ht */
1433 else if (other->iconf->hw_mode ==
1434 HOSTAPD_MODE_IEEE80211A)
1435 phytype = 4; /* ofdm */
1436 else if (other->iconf->hw_mode ==
1437 HOSTAPD_MODE_IEEE80211G)
1438 phytype = 6; /* erp */
1439 else
1440 phytype = 5; /* hrdsss */
1441 if (ieee80211_freq_to_channel_ext(
1442 hostapd_hw_get_freq(other,
1443 other->iconf->channel),
1444 other->iconf->secondary_channel,
1445 other->iconf->ieee80211ac,
1446 &op_class, &channel) == NUM_HOSTAPD_MODES) {
1447 op_class = 0;
1448 channel = other->iconf->channel;
1449 }
1450 *pos++ = op_class;
1451 *pos++ = channel;
1452 *pos++ = phytype;
1453 resp_ies_len = pos - &resp_ies[0];
1454 goto fail;
1455 }
1456 }
1457
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001458 res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len,
1459 &session_timeout,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001460 &acct_interim_interval, &vlan_id,
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001461 &psk, &identity, &radius_cui);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001462
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001463 if (res == HOSTAPD_ACL_REJECT) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08001464 wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to authenticate",
1465 MAC2STR(mgmt->sa));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001466 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1467 goto fail;
1468 }
1469 if (res == HOSTAPD_ACL_PENDING) {
1470 wpa_printf(MSG_DEBUG, "Authentication frame from " MACSTR
1471 " waiting for an external authentication",
1472 MAC2STR(mgmt->sa));
1473 /* Authentication code will re-send the authentication frame
1474 * after it has received (and cached) information from the
1475 * external source. */
1476 return;
1477 }
1478
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001479 sta = ap_get_sta(hapd, mgmt->sa);
1480 if (sta) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001481 sta->flags &= ~WLAN_STA_PENDING_FILS_ERP;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001482 if ((fc & WLAN_FC_RETRY) &&
1483 sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ &&
1484 sta->last_seq_ctrl == seq_ctrl &&
1485 sta->last_subtype == WLAN_FC_STYPE_AUTH) {
1486 hostapd_logger(hapd, sta->addr,
1487 HOSTAPD_MODULE_IEEE80211,
1488 HOSTAPD_LEVEL_DEBUG,
1489 "Drop repeated authentication frame seq_ctrl=0x%x",
1490 seq_ctrl);
1491 return;
1492 }
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001493#ifdef CONFIG_MESH
1494 if ((hapd->conf->mesh & MESH_ENABLED) &&
1495 sta->plink_state == PLINK_BLOCKED) {
1496 wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
1497 " is blocked - drop Authentication frame",
1498 MAC2STR(mgmt->sa));
1499 return;
1500 }
1501#endif /* CONFIG_MESH */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001502 } else {
1503#ifdef CONFIG_MESH
1504 if (hapd->conf->mesh & MESH_ENABLED) {
1505 /* if the mesh peer is not available, we don't do auth.
1506 */
1507 wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001508 " not yet known - drop Authentication frame",
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001509 MAC2STR(mgmt->sa));
1510 /*
1511 * Save a copy of the frame so that it can be processed
1512 * if a new peer entry is added shortly after this.
1513 */
1514 wpabuf_free(hapd->mesh_pending_auth);
1515 hapd->mesh_pending_auth = wpabuf_alloc_copy(mgmt, len);
1516 os_get_reltime(&hapd->mesh_pending_auth_time);
1517 return;
1518 }
1519#endif /* CONFIG_MESH */
1520
1521 sta = ap_sta_add(hapd, mgmt->sa);
1522 if (!sta) {
1523 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1524 goto fail;
1525 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001526 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001527 sta->last_seq_ctrl = seq_ctrl;
1528 sta->last_subtype = WLAN_FC_STYPE_AUTH;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001529
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001530 if (vlan_id.notempty &&
1531 !hostapd_vlan_valid(hapd->conf->vlan, &vlan_id)) {
1532 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
1533 HOSTAPD_LEVEL_INFO,
1534 "Invalid VLAN %d%s received from RADIUS server",
1535 vlan_id.untagged,
1536 vlan_id.tagged[0] ? "+" : "");
1537 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1538 goto fail;
1539 }
1540 if (ap_sta_set_vlan(hapd, sta, &vlan_id) < 0) {
1541 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1542 goto fail;
1543 }
1544 if (sta->vlan_id)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001545 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS,
1546 HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001547
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001548 hostapd_free_psk_list(sta->psk);
1549 if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) {
1550 sta->psk = psk;
1551 psk = NULL;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001552 } else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001553 sta->psk = NULL;
1554 }
1555
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001556 sta->identity = identity;
1557 identity = NULL;
1558 sta->radius_cui = radius_cui;
1559 radius_cui = NULL;
1560
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001561 sta->flags &= ~WLAN_STA_PREAUTH;
1562 ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
1563
1564 if (hapd->conf->acct_interim_interval == 0 && acct_interim_interval)
1565 sta->acct_interim_interval = acct_interim_interval;
1566 if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT)
1567 ap_sta_session_timeout(hapd, sta, session_timeout);
1568 else
1569 ap_sta_no_session_timeout(hapd, sta);
1570
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001571 /*
1572 * If the driver supports full AP client state, add a station to the
1573 * driver before sending authentication reply to make sure the driver
1574 * has resources, and not to go through the entire authentication and
1575 * association handshake, and fail it at the end.
1576 *
1577 * If this is not the first transaction, in a multi-step authentication
1578 * algorithm, the station already exists in the driver
1579 * (sta->added_unassoc = 1) so skip it.
1580 *
1581 * In mesh mode, the station was already added to the driver when the
1582 * NEW_PEER_CANDIDATE event is received.
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08001583 *
1584 * If PMF was negotiated for the existing association, skip this to
1585 * avoid dropping the STA entry and the associated keys. This is needed
1586 * to allow the original connection work until the attempt can complete
1587 * (re)association, so that unprotected Authentication frame cannot be
1588 * used to bypass PMF protection.
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001589 */
1590 if (FULL_AP_CLIENT_STATE_SUPP(hapd->iface->drv_flags) &&
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08001591 (!(sta->flags & WLAN_STA_MFP) || !ap_sta_is_authorized(sta)) &&
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001592 !(hapd->conf->mesh & MESH_ENABLED) &&
1593 !(sta->added_unassoc)) {
1594 /*
1595 * If a station that is already associated to the AP, is trying
1596 * to authenticate again, remove the STA entry, in order to make
1597 * sure the STA PS state gets cleared and configuration gets
1598 * updated. To handle this, station's added_unassoc flag is
1599 * cleared once the station has completed association.
1600 */
1601 hostapd_drv_sta_remove(hapd, sta->addr);
1602 sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_AUTH |
1603 WLAN_STA_AUTHORIZED);
1604
Dmitry Shmidt4ae50e62016-06-27 13:48:39 -07001605 if (hostapd_sta_add(hapd, sta->addr, 0, 0, NULL, 0, 0,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07001606 NULL, NULL, sta->flags, 0, 0, 0, 0)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001607 hostapd_logger(hapd, sta->addr,
1608 HOSTAPD_MODULE_IEEE80211,
1609 HOSTAPD_LEVEL_NOTICE,
1610 "Could not add STA to kernel driver");
1611 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
1612 goto fail;
1613 }
1614
1615 sta->added_unassoc = 1;
1616 }
1617
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001618 switch (auth_alg) {
1619 case WLAN_AUTH_OPEN:
1620 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1621 HOSTAPD_LEVEL_DEBUG,
1622 "authentication OK (open system)");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001623 sta->flags |= WLAN_STA_AUTH;
1624 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
1625 sta->auth_alg = WLAN_AUTH_OPEN;
1626 mlme_authenticate_indication(hapd, sta);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001627 break;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001628#ifndef CONFIG_NO_RC4
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001629 case WLAN_AUTH_SHARED_KEY:
1630 resp = auth_shared_key(hapd, sta, auth_transaction, challenge,
1631 fc & WLAN_FC_ISWEP);
1632 sta->auth_alg = WLAN_AUTH_SHARED_KEY;
1633 mlme_authenticate_indication(hapd, sta);
1634 if (sta->challenge && auth_transaction == 1) {
1635 resp_ies[0] = WLAN_EID_CHALLENGE;
1636 resp_ies[1] = WLAN_AUTH_CHALLENGE_LEN;
1637 os_memcpy(resp_ies + 2, sta->challenge,
1638 WLAN_AUTH_CHALLENGE_LEN);
1639 resp_ies_len = 2 + WLAN_AUTH_CHALLENGE_LEN;
1640 }
1641 break;
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001642#endif /* CONFIG_NO_RC4 */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001643#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001644 case WLAN_AUTH_FT:
1645 sta->auth_alg = WLAN_AUTH_FT;
1646 if (sta->wpa_sm == NULL)
1647 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001648 sta->addr, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001649 if (sta->wpa_sm == NULL) {
1650 wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA "
1651 "state machine");
1652 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1653 goto fail;
1654 }
1655 wpa_ft_process_auth(sta->wpa_sm, mgmt->bssid,
1656 auth_transaction, mgmt->u.auth.variable,
1657 len - IEEE80211_HDRLEN -
1658 sizeof(mgmt->u.auth),
1659 handle_auth_ft_finish, hapd);
1660 /* handle_auth_ft_finish() callback will complete auth. */
1661 return;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001662#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001663#ifdef CONFIG_SAE
1664 case WLAN_AUTH_SAE:
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08001665#ifdef CONFIG_MESH
1666 if (status_code == WLAN_STATUS_SUCCESS &&
1667 hapd->conf->mesh & MESH_ENABLED) {
1668 if (sta->wpa_sm == NULL)
1669 sta->wpa_sm =
1670 wpa_auth_sta_init(hapd->wpa_auth,
1671 sta->addr, NULL);
1672 if (sta->wpa_sm == NULL) {
1673 wpa_printf(MSG_DEBUG,
1674 "SAE: Failed to initialize WPA state machine");
1675 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
1676 goto fail;
1677 }
1678 }
1679#endif /* CONFIG_MESH */
1680 handle_auth_sae(hapd, sta, mgmt, len, auth_transaction,
1681 status_code);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001682 return;
1683#endif /* CONFIG_SAE */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001684#ifdef CONFIG_FILS
1685 case WLAN_AUTH_FILS_SK:
1686 handle_auth_fils(hapd, sta, mgmt, len, auth_transaction,
1687 status_code);
1688 return;
1689#endif /* CONFIG_FILS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001690 }
1691
1692 fail:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001693 os_free(identity);
1694 os_free(radius_cui);
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001695 hostapd_free_psk_list(psk);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001696
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08001697 reply_res = send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg,
1698 auth_transaction + 1, resp, resp_ies,
1699 resp_ies_len);
1700
1701 if (sta && sta->added_unassoc && (resp != WLAN_STATUS_SUCCESS ||
1702 reply_res != WLAN_STATUS_SUCCESS)) {
1703 hostapd_drv_sta_remove(hapd, sta->addr);
1704 sta->added_unassoc = 0;
1705 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001706}
1707
1708
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001709int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001710{
1711 int i, j = 32, aid;
1712
1713 /* get a unique AID */
1714 if (sta->aid > 0) {
1715 wpa_printf(MSG_DEBUG, " old AID %d", sta->aid);
1716 return 0;
1717 }
1718
Dmitry Shmidt58d12ad2016-07-28 10:07:03 -07001719 if (TEST_FAIL())
1720 return -1;
1721
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001722 for (i = 0; i < AID_WORDS; i++) {
1723 if (hapd->sta_aid[i] == (u32) -1)
1724 continue;
1725 for (j = 0; j < 32; j++) {
1726 if (!(hapd->sta_aid[i] & BIT(j)))
1727 break;
1728 }
1729 if (j < 32)
1730 break;
1731 }
1732 if (j == 32)
1733 return -1;
1734 aid = i * 32 + j + 1;
1735 if (aid > 2007)
1736 return -1;
1737
1738 sta->aid = aid;
1739 hapd->sta_aid[i] |= BIT(j);
1740 wpa_printf(MSG_DEBUG, " new AID %d", sta->aid);
1741 return 0;
1742}
1743
1744
1745static u16 check_ssid(struct hostapd_data *hapd, struct sta_info *sta,
1746 const u8 *ssid_ie, size_t ssid_ie_len)
1747{
1748 if (ssid_ie == NULL)
1749 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1750
1751 if (ssid_ie_len != hapd->conf->ssid.ssid_len ||
1752 os_memcmp(ssid_ie, hapd->conf->ssid.ssid, ssid_ie_len) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001753 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1754 HOSTAPD_LEVEL_INFO,
1755 "Station tried to associate with unknown SSID "
Dmitry Shmidt3c479372014-02-04 10:50:36 -08001756 "'%s'", wpa_ssid_txt(ssid_ie, ssid_ie_len));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001757 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1758 }
1759
1760 return WLAN_STATUS_SUCCESS;
1761}
1762
1763
1764static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta,
1765 const u8 *wmm_ie, size_t wmm_ie_len)
1766{
1767 sta->flags &= ~WLAN_STA_WMM;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001768 sta->qosinfo = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001769 if (wmm_ie && hapd->conf->wmm_enabled) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001770 struct wmm_information_element *wmm;
1771
1772 if (!hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001773 hostapd_logger(hapd, sta->addr,
1774 HOSTAPD_MODULE_WPA,
1775 HOSTAPD_LEVEL_DEBUG,
1776 "invalid WMM element in association "
1777 "request");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001778 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1779 }
1780
1781 sta->flags |= WLAN_STA_WMM;
1782 wmm = (struct wmm_information_element *) wmm_ie;
1783 sta->qosinfo = wmm->qos_info;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001784 }
1785 return WLAN_STATUS_SUCCESS;
1786}
1787
1788
1789static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta,
1790 struct ieee802_11_elems *elems)
1791{
Dmitry Shmidt29333592017-01-09 12:27:11 -08001792 /* Supported rates not used in IEEE 802.11ad/DMG */
1793 if (hapd->iface->current_mode &&
1794 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD)
1795 return WLAN_STATUS_SUCCESS;
1796
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001797 if (!elems->supp_rates) {
1798 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1799 HOSTAPD_LEVEL_DEBUG,
1800 "No supported rates element in AssocReq");
1801 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1802 }
1803
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001804 if (elems->supp_rates_len + elems->ext_supp_rates_len >
1805 sizeof(sta->supported_rates)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001806 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1807 HOSTAPD_LEVEL_DEBUG,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001808 "Invalid supported rates element length %d+%d",
1809 elems->supp_rates_len,
1810 elems->ext_supp_rates_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001811 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1812 }
1813
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001814 sta->supported_rates_len = merge_byte_arrays(
1815 sta->supported_rates, sizeof(sta->supported_rates),
1816 elems->supp_rates, elems->supp_rates_len,
1817 elems->ext_supp_rates, elems->ext_supp_rates_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001818
1819 return WLAN_STATUS_SUCCESS;
1820}
1821
1822
Dmitry Shmidt051af732013-10-22 13:52:46 -07001823static u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
1824 const u8 *ext_capab_ie, size_t ext_capab_ie_len)
1825{
1826#ifdef CONFIG_INTERWORKING
1827 /* check for QoS Map support */
1828 if (ext_capab_ie_len >= 5) {
1829 if (ext_capab_ie[4] & 0x01)
1830 sta->qos_map_enabled = 1;
1831 }
1832#endif /* CONFIG_INTERWORKING */
1833
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001834 if (ext_capab_ie_len > 0)
1835 sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2));
1836
Dmitry Shmidt051af732013-10-22 13:52:46 -07001837 return WLAN_STATUS_SUCCESS;
1838}
1839
1840
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001841static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
1842 const u8 *ies, size_t ies_len, int reassoc)
1843{
1844 struct ieee802_11_elems elems;
1845 u16 resp;
1846 const u8 *wpa_ie;
1847 size_t wpa_ie_len;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001848 const u8 *p2p_dev_addr = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001849
1850 if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) {
1851 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1852 HOSTAPD_LEVEL_INFO, "Station sent an invalid "
1853 "association request");
1854 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1855 }
1856
1857 resp = check_ssid(hapd, sta, elems.ssid, elems.ssid_len);
1858 if (resp != WLAN_STATUS_SUCCESS)
1859 return resp;
1860 resp = check_wmm(hapd, sta, elems.wmm, elems.wmm_len);
1861 if (resp != WLAN_STATUS_SUCCESS)
1862 return resp;
Dmitry Shmidt051af732013-10-22 13:52:46 -07001863 resp = check_ext_capab(hapd, sta, elems.ext_capab, elems.ext_capab_len);
1864 if (resp != WLAN_STATUS_SUCCESS)
1865 return resp;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001866 resp = copy_supp_rates(hapd, sta, &elems);
1867 if (resp != WLAN_STATUS_SUCCESS)
1868 return resp;
1869#ifdef CONFIG_IEEE80211N
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07001870 resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001871 if (resp != WLAN_STATUS_SUCCESS)
1872 return resp;
1873 if (hapd->iconf->ieee80211n && hapd->iconf->require_ht &&
1874 !(sta->flags & WLAN_STA_HT)) {
1875 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1876 HOSTAPD_LEVEL_INFO, "Station does not support "
1877 "mandatory HT PHY - reject association");
1878 return WLAN_STATUS_ASSOC_DENIED_NO_HT;
1879 }
1880#endif /* CONFIG_IEEE80211N */
1881
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001882#ifdef CONFIG_IEEE80211AC
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001883 if (hapd->iconf->ieee80211ac) {
1884 resp = copy_sta_vht_capab(hapd, sta, elems.vht_capabilities);
1885 if (resp != WLAN_STATUS_SUCCESS)
1886 return resp;
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001887
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08001888 resp = set_sta_vht_opmode(hapd, sta, elems.vht_opmode_notif);
1889 if (resp != WLAN_STATUS_SUCCESS)
1890 return resp;
1891 }
Dmitry Shmidtbd14a572014-02-18 10:33:49 -08001892
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001893 if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht &&
1894 !(sta->flags & WLAN_STA_VHT)) {
1895 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1896 HOSTAPD_LEVEL_INFO, "Station does not support "
1897 "mandatory VHT PHY - reject association");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08001898 return WLAN_STATUS_ASSOC_DENIED_NO_VHT;
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001899 }
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08001900
1901 if (hapd->conf->vendor_vht && !elems.vht_capabilities) {
1902 resp = copy_sta_vendor_vht(hapd, sta, elems.vendor_vht,
1903 elems.vendor_vht_len);
1904 if (resp != WLAN_STATUS_SUCCESS)
1905 return resp;
1906 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001907#endif /* CONFIG_IEEE80211AC */
1908
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001909#ifdef CONFIG_P2P
1910 if (elems.p2p) {
1911 wpabuf_free(sta->p2p_ie);
1912 sta->p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
1913 P2P_IE_VENDOR_TYPE);
1914 if (sta->p2p_ie)
1915 p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie);
1916 } else {
1917 wpabuf_free(sta->p2p_ie);
1918 sta->p2p_ie = NULL;
1919 }
1920#endif /* CONFIG_P2P */
1921
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001922 if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) {
1923 wpa_ie = elems.rsn_ie;
1924 wpa_ie_len = elems.rsn_ie_len;
1925 } else if ((hapd->conf->wpa & WPA_PROTO_WPA) &&
1926 elems.wpa_ie) {
1927 wpa_ie = elems.wpa_ie;
1928 wpa_ie_len = elems.wpa_ie_len;
1929 } else {
1930 wpa_ie = NULL;
1931 wpa_ie_len = 0;
1932 }
1933
1934#ifdef CONFIG_WPS
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001935 sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001936 if (hapd->conf->wps_state && elems.wps_ie) {
1937 wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association "
1938 "Request - assume WPS is used");
1939 sta->flags |= WLAN_STA_WPS;
1940 wpabuf_free(sta->wps_ie);
1941 sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
1942 WPS_IE_VENDOR_TYPE);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001943 if (sta->wps_ie && wps_is_20(sta->wps_ie)) {
1944 wpa_printf(MSG_DEBUG, "WPS: STA supports WPS 2.0");
1945 sta->flags |= WLAN_STA_WPS2;
1946 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001947 wpa_ie = NULL;
1948 wpa_ie_len = 0;
1949 if (sta->wps_ie && wps_validate_assoc_req(sta->wps_ie) < 0) {
1950 wpa_printf(MSG_DEBUG, "WPS: Invalid WPS IE in "
1951 "(Re)Association Request - reject");
1952 return WLAN_STATUS_INVALID_IE;
1953 }
1954 } else if (hapd->conf->wps_state && wpa_ie == NULL) {
1955 wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE in "
1956 "(Re)Association Request - possible WPS use");
1957 sta->flags |= WLAN_STA_MAYBE_WPS;
1958 } else
1959#endif /* CONFIG_WPS */
1960 if (hapd->conf->wpa && wpa_ie == NULL) {
1961 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
1962 HOSTAPD_LEVEL_INFO,
1963 "No WPA/RSN IE in association request");
1964 return WLAN_STATUS_INVALID_IE;
1965 }
1966
1967 if (hapd->conf->wpa && wpa_ie) {
1968 int res;
1969 wpa_ie -= 2;
1970 wpa_ie_len += 2;
1971 if (sta->wpa_sm == NULL)
1972 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07001973 sta->addr,
1974 p2p_dev_addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001975 if (sta->wpa_sm == NULL) {
1976 wpa_printf(MSG_WARNING, "Failed to initialize WPA "
1977 "state machine");
1978 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1979 }
1980 res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
1981 wpa_ie, wpa_ie_len,
1982 elems.mdie, elems.mdie_len);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08001983 resp = wpa_res_to_status_code(res);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001984 if (resp != WLAN_STATUS_SUCCESS)
1985 return resp;
1986#ifdef CONFIG_IEEE80211W
1987 if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
1988 sta->sa_query_count > 0)
1989 ap_check_sa_query_timeout(hapd, sta);
1990 if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
1991 (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) {
1992 /*
1993 * STA has already been associated with MFP and SA
1994 * Query timeout has not been reached. Reject the
1995 * association attempt temporarily and start SA Query,
1996 * if one is not pending.
1997 */
1998
1999 if (sta->sa_query_count == 0)
2000 ap_sta_start_sa_query(hapd, sta);
2001
2002 return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
2003 }
2004
2005 if (wpa_auth_uses_mfp(sta->wpa_sm))
2006 sta->flags |= WLAN_STA_MFP;
2007 else
2008 sta->flags &= ~WLAN_STA_MFP;
2009#endif /* CONFIG_IEEE80211W */
2010
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002011#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002012 if (sta->auth_alg == WLAN_AUTH_FT) {
2013 if (!reassoc) {
2014 wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried "
2015 "to use association (not "
2016 "re-association) with FT auth_alg",
2017 MAC2STR(sta->addr));
2018 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2019 }
2020
2021 resp = wpa_ft_validate_reassoc(sta->wpa_sm, ies,
2022 ies_len);
2023 if (resp != WLAN_STATUS_SUCCESS)
2024 return resp;
2025 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002026#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002027
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002028#ifdef CONFIG_SAE
2029 if (wpa_auth_uses_sae(sta->wpa_sm) &&
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002030 sta->auth_alg == WLAN_AUTH_OPEN) {
2031 struct rsn_pmksa_cache_entry *sa;
2032 sa = wpa_auth_sta_get_pmksa(sta->wpa_sm);
2033 if (!sa || sa->akmp != WPA_KEY_MGMT_SAE) {
2034 wpa_printf(MSG_DEBUG,
2035 "SAE: No PMKSA cache entry found for "
2036 MACSTR, MAC2STR(sta->addr));
2037 return WLAN_STATUS_INVALID_PMKID;
2038 }
2039 wpa_printf(MSG_DEBUG, "SAE: " MACSTR
2040 " using PMKSA caching", MAC2STR(sta->addr));
2041 } else if (wpa_auth_uses_sae(sta->wpa_sm) &&
2042 sta->auth_alg != WLAN_AUTH_SAE &&
2043 !(sta->auth_alg == WLAN_AUTH_FT &&
2044 wpa_auth_uses_ft_sae(sta->wpa_sm))) {
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002045 wpa_printf(MSG_DEBUG, "SAE: " MACSTR " tried to use "
2046 "SAE AKM after non-SAE auth_alg %u",
2047 MAC2STR(sta->addr), sta->auth_alg);
2048 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
2049 }
2050#endif /* CONFIG_SAE */
2051
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002052#ifdef CONFIG_IEEE80211N
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002053 if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) &&
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002054 wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) {
2055 hostapd_logger(hapd, sta->addr,
2056 HOSTAPD_MODULE_IEEE80211,
2057 HOSTAPD_LEVEL_INFO,
2058 "Station tried to use TKIP with HT "
2059 "association");
2060 return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
2061 }
2062#endif /* CONFIG_IEEE80211N */
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002063#ifdef CONFIG_HS20
2064 } else if (hapd->conf->osen) {
2065 if (elems.osen == NULL) {
2066 hostapd_logger(
2067 hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2068 HOSTAPD_LEVEL_INFO,
2069 "No HS 2.0 OSEN element in association request");
2070 return WLAN_STATUS_INVALID_IE;
2071 }
2072
2073 wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association");
2074 if (sta->wpa_sm == NULL)
2075 sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
2076 sta->addr, NULL);
2077 if (sta->wpa_sm == NULL) {
2078 wpa_printf(MSG_WARNING, "Failed to initialize WPA "
2079 "state machine");
2080 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2081 }
2082 if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm,
2083 elems.osen - 2, elems.osen_len + 2) < 0)
2084 return WLAN_STATUS_INVALID_IE;
2085#endif /* CONFIG_HS20 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002086 } else
2087 wpa_auth_sta_no_wpa(sta->wpa_sm);
2088
2089#ifdef CONFIG_P2P
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002090 p2p_group_notif_assoc(hapd->p2p_group, sta->addr, ies, ies_len);
2091#endif /* CONFIG_P2P */
2092
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002093#ifdef CONFIG_HS20
2094 wpabuf_free(sta->hs20_ie);
2095 if (elems.hs20 && elems.hs20_len > 4) {
2096 sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
2097 elems.hs20_len - 4);
2098 } else
2099 sta->hs20_ie = NULL;
2100#endif /* CONFIG_HS20 */
2101
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002102#ifdef CONFIG_FST
2103 wpabuf_free(sta->mb_ies);
2104 if (hapd->iface->fst)
2105 sta->mb_ies = mb_ies_by_info(&elems.mb_ies);
2106 else
2107 sta->mb_ies = NULL;
2108#endif /* CONFIG_FST */
2109
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002110#ifdef CONFIG_MBO
2111 mbo_ap_check_sta_assoc(hapd, sta, &elems);
2112
2113 if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) &&
2114 elems.mbo && sta->cell_capa && !(sta->flags & WLAN_STA_MFP) &&
2115 hapd->conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) {
2116 wpa_printf(MSG_INFO,
2117 "MBO: Reject WPA2 association without PMF");
2118 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2119 }
2120#endif /* CONFIG_MBO */
2121
Dmitry Shmidt9c175262016-03-03 10:20:07 -08002122 ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes,
2123 elems.supp_op_classes_len);
2124
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002125 if ((sta->capability & WLAN_CAPABILITY_RADIO_MEASUREMENT) &&
2126 elems.rrm_enabled &&
2127 elems.rrm_enabled_len >= sizeof(sta->rrm_enabled_capa))
2128 os_memcpy(sta->rrm_enabled_capa, elems.rrm_enabled,
2129 sizeof(sta->rrm_enabled_capa));
2130
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002131 return WLAN_STATUS_SUCCESS;
2132}
2133
2134
2135static void send_deauth(struct hostapd_data *hapd, const u8 *addr,
2136 u16 reason_code)
2137{
2138 int send_len;
2139 struct ieee80211_mgmt reply;
2140
2141 os_memset(&reply, 0, sizeof(reply));
2142 reply.frame_control =
2143 IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DEAUTH);
2144 os_memcpy(reply.da, addr, ETH_ALEN);
2145 os_memcpy(reply.sa, hapd->own_addr, ETH_ALEN);
2146 os_memcpy(reply.bssid, hapd->own_addr, ETH_ALEN);
2147
2148 send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth);
2149 reply.u.deauth.reason_code = host_to_le16(reason_code);
2150
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002151 if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002152 wpa_printf(MSG_INFO, "Failed to send deauth: %s",
2153 strerror(errno));
2154}
2155
2156
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002157static int add_associated_sta(struct hostapd_data *hapd,
2158 struct sta_info *sta)
2159{
2160 struct ieee80211_ht_capabilities ht_cap;
2161 struct ieee80211_vht_capabilities vht_cap;
2162
2163 /*
2164 * Remove the STA entry to ensure the STA PS state gets cleared and
2165 * configuration gets updated. This is relevant for cases, such as
2166 * FT-over-the-DS, where a station re-associates back to the same AP but
2167 * skips the authentication flow, or if working with a driver that
2168 * does not support full AP client state.
2169 */
2170 if (!sta->added_unassoc)
2171 hostapd_drv_sta_remove(hapd, sta->addr);
2172
2173#ifdef CONFIG_IEEE80211N
2174 if (sta->flags & WLAN_STA_HT)
2175 hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap);
2176#endif /* CONFIG_IEEE80211N */
2177#ifdef CONFIG_IEEE80211AC
2178 if (sta->flags & WLAN_STA_VHT)
2179 hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap);
2180#endif /* CONFIG_IEEE80211AC */
2181
2182 /*
2183 * Add the station with forced WLAN_STA_ASSOC flag. The sta->flags
2184 * will be set when the ACK frame for the (Re)Association Response frame
2185 * is processed (TX status driver event).
2186 */
2187 if (hostapd_sta_add(hapd, sta->addr, sta->aid, sta->capability,
2188 sta->supported_rates, sta->supported_rates_len,
2189 sta->listen_interval,
2190 sta->flags & WLAN_STA_HT ? &ht_cap : NULL,
2191 sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
2192 sta->flags | WLAN_STA_ASSOC, sta->qosinfo,
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002193 sta->vht_opmode, sta->p2p_ie ? 1 : 0,
2194 sta->added_unassoc)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002195 hostapd_logger(hapd, sta->addr,
2196 HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE,
2197 "Could not %s STA to kernel driver",
2198 sta->added_unassoc ? "set" : "add");
2199
2200 if (sta->added_unassoc) {
2201 hostapd_drv_sta_remove(hapd, sta->addr);
2202 sta->added_unassoc = 0;
2203 }
2204
2205 return -1;
2206 }
2207
2208 sta->added_unassoc = 0;
2209
2210 return 0;
2211}
2212
2213
2214static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
Dmitry Shmidt29333592017-01-09 12:27:11 -08002215 const u8 *addr, u16 status_code, int reassoc,
2216 const u8 *ies, size_t ies_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002217{
2218 int send_len;
2219 u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
2220 struct ieee80211_mgmt *reply;
2221 u8 *p;
2222
2223 os_memset(buf, 0, sizeof(buf));
2224 reply = (struct ieee80211_mgmt *) buf;
2225 reply->frame_control =
2226 IEEE80211_FC(WLAN_FC_TYPE_MGMT,
2227 (reassoc ? WLAN_FC_STYPE_REASSOC_RESP :
2228 WLAN_FC_STYPE_ASSOC_RESP));
Dmitry Shmidt29333592017-01-09 12:27:11 -08002229 os_memcpy(reply->da, addr, ETH_ALEN);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002230 os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN);
2231 os_memcpy(reply->bssid, hapd->own_addr, ETH_ALEN);
2232
2233 send_len = IEEE80211_HDRLEN;
2234 send_len += sizeof(reply->u.assoc_resp);
2235 reply->u.assoc_resp.capab_info =
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07002236 host_to_le16(hostapd_own_capab_info(hapd));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002237 reply->u.assoc_resp.status_code = host_to_le16(status_code);
Dmitry Shmidt29333592017-01-09 12:27:11 -08002238
2239 reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0) |
2240 BIT(14) | BIT(15));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002241 /* Supported rates */
2242 p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable);
2243 /* Extended supported rates */
2244 p = hostapd_eid_ext_supp_rates(hapd, p);
2245
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002246#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt29333592017-01-09 12:27:11 -08002247 if (sta && status_code == WLAN_STATUS_SUCCESS) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002248 /* IEEE 802.11r: Mobility Domain Information, Fast BSS
2249 * Transition Information, RSN, [RIC Response] */
2250 p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p,
2251 buf + sizeof(buf) - p,
2252 sta->auth_alg, ies, ies_len);
2253 }
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002254#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002255
2256#ifdef CONFIG_IEEE80211W
Dmitry Shmidt29333592017-01-09 12:27:11 -08002257 if (sta && status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002258 p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
2259#endif /* CONFIG_IEEE80211W */
2260
2261#ifdef CONFIG_IEEE80211N
2262 p = hostapd_eid_ht_capabilities(hapd, p);
2263 p = hostapd_eid_ht_operation(hapd, p);
2264#endif /* CONFIG_IEEE80211N */
2265
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002266#ifdef CONFIG_IEEE80211AC
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002267 if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) {
Dmitry Shmidt7d175302016-09-06 13:11:34 -07002268 u32 nsts = 0, sta_nsts;
2269
Dmitry Shmidt29333592017-01-09 12:27:11 -08002270 if (sta && hapd->conf->use_sta_nsts && sta->vht_capabilities) {
Dmitry Shmidt7d175302016-09-06 13:11:34 -07002271 struct ieee80211_vht_capabilities *capa;
2272
2273 nsts = (hapd->iface->conf->vht_capab >>
2274 VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7;
2275 capa = sta->vht_capabilities;
2276 sta_nsts = (le_to_host32(capa->vht_capabilities_info) >>
2277 VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7;
2278
2279 if (nsts < sta_nsts)
2280 nsts = 0;
2281 else
2282 nsts = sta_nsts;
2283 }
2284 p = hostapd_eid_vht_capabilities(hapd, p, nsts);
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002285 p = hostapd_eid_vht_operation(hapd, p);
2286 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002287#endif /* CONFIG_IEEE80211AC */
2288
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002289 p = hostapd_eid_ext_capab(hapd, p);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002290 p = hostapd_eid_bss_max_idle_period(hapd, p);
Dmitry Shmidt29333592017-01-09 12:27:11 -08002291 if (sta && sta->qos_map_enabled)
Dmitry Shmidt051af732013-10-22 13:52:46 -07002292 p = hostapd_eid_qos_map_set(hapd, p);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002293
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002294#ifdef CONFIG_FST
2295 if (hapd->iface->fst_ies) {
2296 os_memcpy(p, wpabuf_head(hapd->iface->fst_ies),
2297 wpabuf_len(hapd->iface->fst_ies));
2298 p += wpabuf_len(hapd->iface->fst_ies);
2299 }
2300#endif /* CONFIG_FST */
2301
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002302#ifdef CONFIG_IEEE80211AC
Dmitry Shmidt29333592017-01-09 12:27:11 -08002303 if (sta && hapd->conf->vendor_vht && (sta->flags & WLAN_STA_VENDOR_VHT))
Dmitry Shmidt2f74e362015-01-21 13:19:05 -08002304 p = hostapd_eid_vendor_vht(hapd, p);
2305#endif /* CONFIG_IEEE80211AC */
2306
Dmitry Shmidt29333592017-01-09 12:27:11 -08002307 if (sta && (sta->flags & WLAN_STA_WMM))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002308 p = hostapd_eid_wmm(hapd, p);
2309
2310#ifdef CONFIG_WPS
Dmitry Shmidt29333592017-01-09 12:27:11 -08002311 if (sta &&
2312 ((sta->flags & WLAN_STA_WPS) ||
2313 ((sta->flags & WLAN_STA_MAYBE_WPS) && hapd->conf->wpa))) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002314 struct wpabuf *wps = wps_build_assoc_resp_ie();
2315 if (wps) {
2316 os_memcpy(p, wpabuf_head(wps), wpabuf_len(wps));
2317 p += wpabuf_len(wps);
2318 wpabuf_free(wps);
2319 }
2320 }
2321#endif /* CONFIG_WPS */
2322
2323#ifdef CONFIG_P2P
Dmitry Shmidt29333592017-01-09 12:27:11 -08002324 if (sta && sta->p2p_ie && hapd->p2p_group) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002325 struct wpabuf *p2p_resp_ie;
2326 enum p2p_status_code status;
2327 switch (status_code) {
2328 case WLAN_STATUS_SUCCESS:
2329 status = P2P_SC_SUCCESS;
2330 break;
2331 case WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA:
2332 status = P2P_SC_FAIL_LIMIT_REACHED;
2333 break;
2334 default:
2335 status = P2P_SC_FAIL_INVALID_PARAMS;
2336 break;
2337 }
2338 p2p_resp_ie = p2p_group_assoc_resp_ie(hapd->p2p_group, status);
2339 if (p2p_resp_ie) {
2340 os_memcpy(p, wpabuf_head(p2p_resp_ie),
2341 wpabuf_len(p2p_resp_ie));
2342 p += wpabuf_len(p2p_resp_ie);
2343 wpabuf_free(p2p_resp_ie);
2344 }
2345 }
2346#endif /* CONFIG_P2P */
2347
2348#ifdef CONFIG_P2P_MANAGER
2349 if (hapd->conf->p2p & P2P_MANAGE)
2350 p = hostapd_eid_p2p_manage(hapd, p);
2351#endif /* CONFIG_P2P_MANAGER */
2352
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002353 p = hostapd_eid_mbo(hapd, p, buf + sizeof(buf) - p);
2354
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002355 if (hapd->conf->assocresp_elements &&
2356 (size_t) (buf + sizeof(buf) - p) >=
2357 wpabuf_len(hapd->conf->assocresp_elements)) {
2358 os_memcpy(p, wpabuf_head(hapd->conf->assocresp_elements),
2359 wpabuf_len(hapd->conf->assocresp_elements));
2360 p += wpabuf_len(hapd->conf->assocresp_elements);
2361 }
2362
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002363 send_len += p - reply->u.assoc_resp.variable;
2364
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002365#ifdef CONFIG_FILS
Dmitry Shmidt29333592017-01-09 12:27:11 -08002366 if (sta &&
2367 (sta->auth_alg == WLAN_AUTH_FILS_SK ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002368 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
2369 sta->auth_alg == WLAN_AUTH_FILS_PK) &&
2370 status_code == WLAN_STATUS_SUCCESS) {
2371 struct ieee802_11_elems elems;
2372
2373 if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) ==
2374 ParseFailed || !elems.fils_session)
2375 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2376
2377 /* FILS Session */
2378 *p++ = WLAN_EID_EXTENSION; /* Element ID */
2379 *p++ = 1 + FILS_SESSION_LEN; /* Length */
2380 *p++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */
2381 os_memcpy(p, elems.fils_session, FILS_SESSION_LEN);
2382 send_len += 2 + 1 + FILS_SESSION_LEN;
2383
2384 send_len = fils_encrypt_assoc(sta->wpa_sm, buf, send_len,
2385 sizeof(buf));
2386 if (send_len < 0)
2387 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2388 }
2389#endif /* CONFIG_FILS */
2390
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002391 if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002392 wpa_printf(MSG_INFO, "Failed to send assoc resp: %s",
2393 strerror(errno));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002394 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2395 }
2396
2397 return WLAN_STATUS_SUCCESS;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002398}
2399
2400
2401static void handle_assoc(struct hostapd_data *hapd,
2402 const struct ieee80211_mgmt *mgmt, size_t len,
2403 int reassoc)
2404{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002405 u16 capab_info, listen_interval, seq_ctrl, fc;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002406 u16 resp = WLAN_STATUS_SUCCESS, reply_res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002407 const u8 *pos;
2408 int left, i;
2409 struct sta_info *sta;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002410 u8 *tmp = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002411
2412 if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) :
2413 sizeof(mgmt->u.assoc_req))) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002414 wpa_printf(MSG_INFO, "handle_assoc(reassoc=%d) - too short payload (len=%lu)",
2415 reassoc, (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002416 return;
2417 }
2418
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002419#ifdef CONFIG_TESTING_OPTIONS
2420 if (reassoc) {
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07002421 if (hapd->iconf->ignore_reassoc_probability > 0.0 &&
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002422 drand48() < hapd->iconf->ignore_reassoc_probability) {
2423 wpa_printf(MSG_INFO,
2424 "TESTING: ignoring reassoc request from "
2425 MACSTR, MAC2STR(mgmt->sa));
2426 return;
2427 }
2428 } else {
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07002429 if (hapd->iconf->ignore_assoc_probability > 0.0 &&
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002430 drand48() < hapd->iconf->ignore_assoc_probability) {
2431 wpa_printf(MSG_INFO,
2432 "TESTING: ignoring assoc request from "
2433 MACSTR, MAC2STR(mgmt->sa));
2434 return;
2435 }
2436 }
2437#endif /* CONFIG_TESTING_OPTIONS */
2438
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002439 fc = le_to_host16(mgmt->frame_control);
2440 seq_ctrl = le_to_host16(mgmt->seq_ctrl);
2441
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002442 if (reassoc) {
2443 capab_info = le_to_host16(mgmt->u.reassoc_req.capab_info);
2444 listen_interval = le_to_host16(
2445 mgmt->u.reassoc_req.listen_interval);
2446 wpa_printf(MSG_DEBUG, "reassociation request: STA=" MACSTR
2447 " capab_info=0x%02x listen_interval=%d current_ap="
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002448 MACSTR " seq_ctrl=0x%x%s",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002449 MAC2STR(mgmt->sa), capab_info, listen_interval,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002450 MAC2STR(mgmt->u.reassoc_req.current_ap),
2451 seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002452 left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.reassoc_req));
2453 pos = mgmt->u.reassoc_req.variable;
2454 } else {
2455 capab_info = le_to_host16(mgmt->u.assoc_req.capab_info);
2456 listen_interval = le_to_host16(
2457 mgmt->u.assoc_req.listen_interval);
2458 wpa_printf(MSG_DEBUG, "association request: STA=" MACSTR
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002459 " capab_info=0x%02x listen_interval=%d "
2460 "seq_ctrl=0x%x%s",
2461 MAC2STR(mgmt->sa), capab_info, listen_interval,
2462 seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002463 left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req));
2464 pos = mgmt->u.assoc_req.variable;
2465 }
2466
2467 sta = ap_get_sta(hapd, mgmt->sa);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002468#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002469 if (sta && sta->auth_alg == WLAN_AUTH_FT &&
2470 (sta->flags & WLAN_STA_AUTH) == 0) {
2471 wpa_printf(MSG_DEBUG, "FT: Allow STA " MACSTR " to associate "
2472 "prior to authentication since it is using "
2473 "over-the-DS FT", MAC2STR(mgmt->sa));
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002474
2475 /*
2476 * Mark station as authenticated, to avoid adding station
2477 * entry in the driver as associated and not authenticated
2478 */
2479 sta->flags |= WLAN_STA_AUTH;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002480 } else
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002481#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002482 if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) {
Dmitry Shmidt29333592017-01-09 12:27:11 -08002483 if (hapd->iface->current_mode &&
2484 hapd->iface->current_mode->mode ==
2485 HOSTAPD_MODE_IEEE80211AD) {
2486 /* DMG/IEEE 802.11ad does not use authentication.
2487 * Allocate sta entry upon association. */
2488 sta = ap_sta_add(hapd, mgmt->sa);
2489 if (!sta) {
2490 hostapd_logger(hapd, mgmt->sa,
2491 HOSTAPD_MODULE_IEEE80211,
2492 HOSTAPD_LEVEL_INFO,
2493 "Failed to add STA");
2494 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
2495 goto fail;
2496 }
2497
2498 hostapd_logger(hapd, sta->addr,
2499 HOSTAPD_MODULE_IEEE80211,
2500 HOSTAPD_LEVEL_DEBUG,
2501 "Skip authentication for DMG/IEEE 802.11ad");
2502 sta->flags |= WLAN_STA_AUTH;
2503 wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH);
2504 sta->auth_alg = WLAN_AUTH_OPEN;
2505 } else {
2506 hostapd_logger(hapd, mgmt->sa,
2507 HOSTAPD_MODULE_IEEE80211,
2508 HOSTAPD_LEVEL_INFO,
2509 "Station tried to associate before authentication (aid=%d flags=0x%x)",
2510 sta ? sta->aid : -1,
2511 sta ? sta->flags : 0);
2512 send_deauth(hapd, mgmt->sa,
2513 WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA);
2514 return;
2515 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002516 }
2517
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002518 if ((fc & WLAN_FC_RETRY) &&
2519 sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ &&
2520 sta->last_seq_ctrl == seq_ctrl &&
2521 sta->last_subtype == reassoc ? WLAN_FC_STYPE_REASSOC_REQ :
2522 WLAN_FC_STYPE_ASSOC_REQ) {
2523 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2524 HOSTAPD_LEVEL_DEBUG,
2525 "Drop repeated association frame seq_ctrl=0x%x",
2526 seq_ctrl);
2527 return;
2528 }
2529 sta->last_seq_ctrl = seq_ctrl;
2530 sta->last_subtype = reassoc ? WLAN_FC_STYPE_REASSOC_REQ :
2531 WLAN_FC_STYPE_ASSOC_REQ;
2532
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002533 if (hapd->tkip_countermeasures) {
2534 resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
2535 goto fail;
2536 }
2537
2538 if (listen_interval > hapd->conf->max_listen_interval) {
2539 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
2540 HOSTAPD_LEVEL_DEBUG,
2541 "Too large Listen Interval (%d)",
2542 listen_interval);
2543 resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE;
2544 goto fail;
2545 }
2546
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002547#ifdef CONFIG_MBO
2548 if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) {
2549 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
2550 goto fail;
2551 }
2552#endif /* CONFIG_MBO */
2553
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002554 /*
2555 * sta->capability is used in check_assoc_ies() for RRM enabled
2556 * capability element.
2557 */
2558 sta->capability = capab_info;
2559
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002560#ifdef CONFIG_FILS
2561 if (sta->auth_alg == WLAN_AUTH_FILS_SK ||
2562 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
2563 sta->auth_alg == WLAN_AUTH_FILS_PK) {
2564 /* The end of the payload is encrypted. Need to decrypt it
2565 * before parsing. */
2566
2567 tmp = os_malloc(left);
2568 if (!tmp) {
2569 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
2570 goto fail;
2571 }
2572 os_memcpy(tmp, pos, left);
2573
2574 left = fils_decrypt_assoc(sta->wpa_sm, sta->fils_session, mgmt,
2575 len, tmp, left);
2576 if (left < 0) {
2577 resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
2578 goto fail;
2579 }
2580 pos = tmp;
2581 }
2582#endif /* CONFIG_FILS */
2583
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002584 /* followed by SSID and Supported rates; and HT capabilities if 802.11n
2585 * is used */
2586 resp = check_assoc_ies(hapd, sta, pos, left, reassoc);
2587 if (resp != WLAN_STATUS_SUCCESS)
2588 goto fail;
2589
2590 if (hostapd_get_aid(hapd, sta) < 0) {
2591 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
2592 HOSTAPD_LEVEL_INFO, "No room for more AIDs");
2593 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
2594 goto fail;
2595 }
2596
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002597 sta->listen_interval = listen_interval;
2598
2599 if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
2600 sta->flags |= WLAN_STA_NONERP;
2601 for (i = 0; i < sta->supported_rates_len; i++) {
2602 if ((sta->supported_rates[i] & 0x7f) > 22) {
2603 sta->flags &= ~WLAN_STA_NONERP;
2604 break;
2605 }
2606 }
2607 if (sta->flags & WLAN_STA_NONERP && !sta->nonerp_set) {
2608 sta->nonerp_set = 1;
2609 hapd->iface->num_sta_non_erp++;
2610 if (hapd->iface->num_sta_non_erp == 1)
2611 ieee802_11_set_beacons(hapd->iface);
2612 }
2613
2614 if (!(sta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) &&
2615 !sta->no_short_slot_time_set) {
2616 sta->no_short_slot_time_set = 1;
2617 hapd->iface->num_sta_no_short_slot_time++;
2618 if (hapd->iface->current_mode->mode ==
2619 HOSTAPD_MODE_IEEE80211G &&
2620 hapd->iface->num_sta_no_short_slot_time == 1)
2621 ieee802_11_set_beacons(hapd->iface);
2622 }
2623
2624 if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
2625 sta->flags |= WLAN_STA_SHORT_PREAMBLE;
2626 else
2627 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
2628
2629 if (!(sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
2630 !sta->no_short_preamble_set) {
2631 sta->no_short_preamble_set = 1;
2632 hapd->iface->num_sta_no_short_preamble++;
2633 if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
2634 && hapd->iface->num_sta_no_short_preamble == 1)
2635 ieee802_11_set_beacons(hapd->iface);
2636 }
2637
2638#ifdef CONFIG_IEEE80211N
2639 update_ht_state(hapd, sta);
2640#endif /* CONFIG_IEEE80211N */
2641
2642 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2643 HOSTAPD_LEVEL_DEBUG,
2644 "association OK (aid %d)", sta->aid);
2645 /* Station will be marked associated, after it acknowledges AssocResp
2646 */
2647 sta->flags |= WLAN_STA_ASSOC_REQ_OK;
2648
2649#ifdef CONFIG_IEEE80211W
2650 if ((sta->flags & WLAN_STA_MFP) && sta->sa_query_timed_out) {
2651 wpa_printf(MSG_DEBUG, "Allowing %sassociation after timed out "
2652 "SA Query procedure", reassoc ? "re" : "");
2653 /* TODO: Send a protected Disassociate frame to the STA using
2654 * the old key and Reason Code "Previous Authentication no
2655 * longer valid". Make sure this is only sent protected since
2656 * unprotected frame would be received by the STA that is now
2657 * trying to associate.
2658 */
2659 }
2660#endif /* CONFIG_IEEE80211W */
2661
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002662 /* Make sure that the previously registered inactivity timer will not
2663 * remove the STA immediately. */
2664 sta->timeout_next = STA_NULLFUNC;
2665
Dmitry Shmidtaca489e2016-09-28 15:44:14 -07002666#ifdef CONFIG_TAXONOMY
2667 taxonomy_sta_info_assoc_req(hapd, sta, pos, left);
2668#endif /* CONFIG_TAXONOMY */
2669
Dmitry Shmidt29333592017-01-09 12:27:11 -08002670 sta->pending_wds_enable = 0;
2671
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002672 fail:
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002673 /*
2674 * In case of a successful response, add the station to the driver.
2675 * Otherwise, the kernel may ignore Data frames before we process the
2676 * ACK frame (TX status). In case of a failure, this station will be
2677 * removed.
2678 *
2679 * Note that this is not compliant with the IEEE 802.11 standard that
2680 * states that a non-AP station should transition into the
2681 * authenticated/associated state only after the station acknowledges
2682 * the (Re)Association Response frame. However, still do this as:
2683 *
2684 * 1. In case the station does not acknowledge the (Re)Association
2685 * Response frame, it will be removed.
2686 * 2. Data frames will be dropped in the kernel until the station is
2687 * set into authorized state, and there are no significant known
2688 * issues with processing other non-Data Class 3 frames during this
2689 * window.
2690 */
Dmitry Shmidt29333592017-01-09 12:27:11 -08002691 if (resp == WLAN_STATUS_SUCCESS && sta && add_associated_sta(hapd, sta))
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002692 resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
2693
Dmitry Shmidt29333592017-01-09 12:27:11 -08002694 reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc, pos,
2695 left);
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002696 os_free(tmp);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002697
2698 /*
2699 * Remove the station in case tranmission of a success response fails
2700 * (the STA was added associated to the driver) or if the station was
2701 * previously added unassociated.
2702 */
Dmitry Shmidt29333592017-01-09 12:27:11 -08002703 if (sta && ((reply_res != WLAN_STATUS_SUCCESS &&
2704 resp == WLAN_STATUS_SUCCESS) || sta->added_unassoc)) {
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002705 hostapd_drv_sta_remove(hapd, sta->addr);
2706 sta->added_unassoc = 0;
2707 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002708}
2709
2710
2711static void handle_disassoc(struct hostapd_data *hapd,
2712 const struct ieee80211_mgmt *mgmt, size_t len)
2713{
2714 struct sta_info *sta;
2715
2716 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002717 wpa_printf(MSG_INFO, "handle_disassoc - too short payload (len=%lu)",
2718 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002719 return;
2720 }
2721
2722 wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d",
2723 MAC2STR(mgmt->sa),
2724 le_to_host16(mgmt->u.disassoc.reason_code));
2725
2726 sta = ap_get_sta(hapd, mgmt->sa);
2727 if (sta == NULL) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002728 wpa_printf(MSG_INFO, "Station " MACSTR " trying to disassociate, but it is not associated",
2729 MAC2STR(mgmt->sa));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002730 return;
2731 }
2732
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002733 ap_sta_set_authorized(hapd, sta, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002734 sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002735 sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002736 wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
2737 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2738 HOSTAPD_LEVEL_INFO, "disassociated");
2739 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
2740 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
2741 /* Stop Accounting and IEEE 802.1X sessions, but leave the STA
2742 * authenticated. */
2743 accounting_sta_stop(hapd, sta);
Dmitry Shmidtde47be72016-01-07 12:52:55 -08002744 ieee802_1x_free_station(hapd, sta);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002745 if (sta->ipaddr)
2746 hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr);
2747 ap_sta_ip6addr_del(hapd, sta);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002748 hostapd_drv_sta_remove(hapd, sta->addr);
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002749 sta->added_unassoc = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002750
2751 if (sta->timeout_next == STA_NULLFUNC ||
2752 sta->timeout_next == STA_DISASSOC) {
2753 sta->timeout_next = STA_DEAUTH;
2754 eloop_cancel_timeout(ap_handle_timer, hapd, sta);
2755 eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer,
2756 hapd, sta);
2757 }
2758
2759 mlme_disassociate_indication(
2760 hapd, sta, le_to_host16(mgmt->u.disassoc.reason_code));
Dmitry Shmidt29333592017-01-09 12:27:11 -08002761
2762 /* DMG/IEEE 802.11ad does not use deauthication. Deallocate sta upon
2763 * disassociation. */
2764 if (hapd->iface->current_mode &&
2765 hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD) {
2766 sta->flags &= ~WLAN_STA_AUTH;
2767 wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
2768 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2769 HOSTAPD_LEVEL_DEBUG, "deauthenticated");
2770 ap_free_sta(hapd, sta);
2771 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002772}
2773
2774
2775static void handle_deauth(struct hostapd_data *hapd,
2776 const struct ieee80211_mgmt *mgmt, size_t len)
2777{
2778 struct sta_info *sta;
2779
2780 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002781 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "handle_deauth - too short "
2782 "payload (len=%lu)", (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002783 return;
2784 }
2785
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002786 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "deauthentication: STA=" MACSTR
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002787 " reason_code=%d",
2788 MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code));
2789
2790 sta = ap_get_sta(hapd, mgmt->sa);
2791 if (sta == NULL) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002792 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying "
2793 "to deauthenticate, but it is not authenticated",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002794 MAC2STR(mgmt->sa));
2795 return;
2796 }
2797
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002798 ap_sta_set_authorized(hapd, sta, 0);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002799 sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002800 sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC |
2801 WLAN_STA_ASSOC_REQ_OK);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002802 wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH);
2803 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
2804 HOSTAPD_LEVEL_DEBUG, "deauthenticated");
2805 mlme_deauthenticate_indication(
2806 hapd, sta, le_to_host16(mgmt->u.deauth.reason_code));
2807 sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
2808 ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
2809 ap_free_sta(hapd, sta);
2810}
2811
2812
2813static void handle_beacon(struct hostapd_data *hapd,
2814 const struct ieee80211_mgmt *mgmt, size_t len,
2815 struct hostapd_frame_info *fi)
2816{
2817 struct ieee802_11_elems elems;
2818
2819 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.beacon)) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08002820 wpa_printf(MSG_INFO, "handle_beacon - too short payload (len=%lu)",
2821 (unsigned long) len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002822 return;
2823 }
2824
2825 (void) ieee802_11_parse_elems(mgmt->u.beacon.variable,
2826 len - (IEEE80211_HDRLEN +
2827 sizeof(mgmt->u.beacon)), &elems,
2828 0);
2829
2830 ap_list_process_beacon(hapd->iface, mgmt, &elems, fi);
2831}
2832
2833
2834#ifdef CONFIG_IEEE80211W
2835
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002836static int hostapd_sa_query_action(struct hostapd_data *hapd,
2837 const struct ieee80211_mgmt *mgmt,
2838 size_t len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002839{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002840 const u8 *end;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002841
2842 end = mgmt->u.action.u.sa_query_resp.trans_id +
2843 WLAN_SA_QUERY_TR_ID_LEN;
2844 if (((u8 *) mgmt) + len < end) {
2845 wpa_printf(MSG_DEBUG, "IEEE 802.11: Too short SA Query Action "
2846 "frame (len=%lu)", (unsigned long) len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002847 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002848 }
2849
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002850 ieee802_11_sa_query_action(hapd, mgmt->sa,
2851 mgmt->u.action.u.sa_query_resp.action,
2852 mgmt->u.action.u.sa_query_resp.trans_id);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002853 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002854}
2855
2856
2857static int robust_action_frame(u8 category)
2858{
2859 return category != WLAN_ACTION_PUBLIC &&
2860 category != WLAN_ACTION_HT;
2861}
2862#endif /* CONFIG_IEEE80211W */
2863
2864
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002865static int handle_action(struct hostapd_data *hapd,
2866 const struct ieee80211_mgmt *mgmt, size_t len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002867{
2868 struct sta_info *sta;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002869 sta = ap_get_sta(hapd, mgmt->sa);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002870
2871 if (len < IEEE80211_HDRLEN + 1) {
2872 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
2873 HOSTAPD_LEVEL_DEBUG,
2874 "handle_action - too short payload (len=%lu)",
2875 (unsigned long) len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002876 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002877 }
2878
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002879 if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
2880 (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))) {
2881 wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored Action "
2882 "frame (category=%u) from unassociated STA " MACSTR,
2883 MAC2STR(mgmt->sa), mgmt->u.action.category);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002884 return 0;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002885 }
2886
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002887#ifdef CONFIG_IEEE80211W
2888 if (sta && (sta->flags & WLAN_STA_MFP) &&
Dmitry Shmidt18463232014-01-24 12:29:41 -08002889 !(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP)) &&
2890 robust_action_frame(mgmt->u.action.category)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002891 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
2892 HOSTAPD_LEVEL_DEBUG,
2893 "Dropped unprotected Robust Action frame from "
2894 "an MFP STA");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002895 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002896 }
2897#endif /* CONFIG_IEEE80211W */
2898
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002899 if (sta) {
2900 u16 fc = le_to_host16(mgmt->frame_control);
2901 u16 seq_ctrl = le_to_host16(mgmt->seq_ctrl);
2902
2903 if ((fc & WLAN_FC_RETRY) &&
2904 sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ &&
2905 sta->last_seq_ctrl == seq_ctrl &&
2906 sta->last_subtype == WLAN_FC_STYPE_ACTION) {
2907 hostapd_logger(hapd, sta->addr,
2908 HOSTAPD_MODULE_IEEE80211,
2909 HOSTAPD_LEVEL_DEBUG,
2910 "Drop repeated action frame seq_ctrl=0x%x",
2911 seq_ctrl);
2912 return 1;
2913 }
2914
2915 sta->last_seq_ctrl = seq_ctrl;
2916 sta->last_subtype = WLAN_FC_STYPE_ACTION;
2917 }
2918
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002919 switch (mgmt->u.action.category) {
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002920#ifdef CONFIG_IEEE80211R_AP
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002921 case WLAN_ACTION_FT:
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07002922 if (!sta ||
2923 wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002924 len - IEEE80211_HDRLEN))
2925 break;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002926 return 1;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08002927#endif /* CONFIG_IEEE80211R_AP */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002928 case WLAN_ACTION_WMM:
2929 hostapd_wmm_action(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002930 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002931#ifdef CONFIG_IEEE80211W
2932 case WLAN_ACTION_SA_QUERY:
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002933 return hostapd_sa_query_action(hapd, mgmt, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002934#endif /* CONFIG_IEEE80211W */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002935#ifdef CONFIG_WNM
2936 case WLAN_ACTION_WNM:
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002937 ieee802_11_rx_wnm_action_ap(hapd, mgmt, len);
2938 return 1;
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002939#endif /* CONFIG_WNM */
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002940#ifdef CONFIG_FST
2941 case WLAN_ACTION_FST:
2942 if (hapd->iface->fst)
2943 fst_rx_action(hapd->iface->fst, mgmt, len);
2944 else
2945 wpa_printf(MSG_DEBUG,
2946 "FST: Ignore FST Action frame - no FST attached");
2947 return 1;
2948#endif /* CONFIG_FST */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002949 case WLAN_ACTION_PUBLIC:
Dmitry Shmidt18463232014-01-24 12:29:41 -08002950 case WLAN_ACTION_PROTECTED_DUAL:
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07002951#ifdef CONFIG_IEEE80211N
Dmitry Shmidtcc00d5d2015-05-04 10:34:12 -07002952 if (len >= IEEE80211_HDRLEN + 2 &&
2953 mgmt->u.action.u.public_action.action ==
Dmitry Shmidt7832adb2014-04-29 10:53:02 -07002954 WLAN_PA_20_40_BSS_COEX) {
2955 wpa_printf(MSG_DEBUG,
2956 "HT20/40 coex mgmt frame received from STA "
2957 MACSTR, MAC2STR(mgmt->sa));
2958 hostapd_2040_coex_action(hapd, mgmt, len);
2959 }
2960#endif /* CONFIG_IEEE80211N */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002961 if (hapd->public_action_cb) {
2962 hapd->public_action_cb(hapd->public_action_cb_ctx,
2963 (u8 *) mgmt, len,
2964 hapd->iface->freq);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002965 }
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002966 if (hapd->public_action_cb2) {
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002967 hapd->public_action_cb2(hapd->public_action_cb2_ctx,
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002968 (u8 *) mgmt, len,
2969 hapd->iface->freq);
2970 }
2971 if (hapd->public_action_cb || hapd->public_action_cb2)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002972 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002973 break;
2974 case WLAN_ACTION_VENDOR_SPECIFIC:
2975 if (hapd->vendor_action_cb) {
2976 if (hapd->vendor_action_cb(hapd->vendor_action_cb_ctx,
2977 (u8 *) mgmt, len,
2978 hapd->iface->freq) == 0)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002979 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002980 }
2981 break;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07002982 case WLAN_ACTION_RADIO_MEASUREMENT:
2983 hostapd_handle_radio_measurement(hapd, (const u8 *) mgmt, len);
2984 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002985 }
2986
2987 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
2988 HOSTAPD_LEVEL_DEBUG,
2989 "handle_action - unknown action category %d or invalid "
2990 "frame",
2991 mgmt->u.action.category);
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07002992 if (!is_multicast_ether_addr(mgmt->da) &&
2993 !(mgmt->u.action.category & 0x80) &&
2994 !is_multicast_ether_addr(mgmt->sa)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002995 struct ieee80211_mgmt *resp;
2996
2997 /*
2998 * IEEE 802.11-REVma/D9.0 - 7.3.1.11
2999 * Return the Action frame to the source without change
3000 * except that MSB of the Category set to 1.
3001 */
3002 wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action "
3003 "frame back to sender");
3004 resp = os_malloc(len);
3005 if (resp == NULL)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003006 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003007 os_memcpy(resp, mgmt, len);
3008 os_memcpy(resp->da, resp->sa, ETH_ALEN);
3009 os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
3010 os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
3011 resp->u.action.category |= 0x80;
3012
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003013 if (hostapd_drv_send_mlme(hapd, resp, len, 0) < 0) {
3014 wpa_printf(MSG_ERROR, "IEEE 802.11: Failed to send "
3015 "Action frame");
3016 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003017 os_free(resp);
3018 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003019
3020 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003021}
3022
3023
3024/**
3025 * ieee802_11_mgmt - process incoming IEEE 802.11 management frames
3026 * @hapd: hostapd BSS data structure (the BSS to which the management frame was
3027 * sent to)
3028 * @buf: management frame data (starting from IEEE 802.11 header)
3029 * @len: length of frame data in octets
3030 * @fi: meta data about received frame (signal level, etc.)
3031 *
3032 * Process all incoming IEEE 802.11 management frames. This will be called for
3033 * each frame received from the kernel driver through wlan#ap interface. In
3034 * addition, it can be called to re-inserted pending frames (e.g., when using
3035 * external RADIUS server as an MAC ACL).
3036 */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003037int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len,
3038 struct hostapd_frame_info *fi)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003039{
3040 struct ieee80211_mgmt *mgmt;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003041 u16 fc, stype;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003042 int ret = 0;
3043
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003044 if (len < 24)
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003045 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003046
3047 mgmt = (struct ieee80211_mgmt *) buf;
3048 fc = le_to_host16(mgmt->frame_control);
3049 stype = WLAN_FC_GET_STYPE(fc);
3050
3051 if (stype == WLAN_FC_STYPE_BEACON) {
3052 handle_beacon(hapd, mgmt, len, fi);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003053 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003054 }
3055
Dmitry Shmidt7f2c7532016-08-15 09:48:12 -07003056 if (!is_broadcast_ether_addr(mgmt->bssid) &&
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003057#ifdef CONFIG_P2P
3058 /* Invitation responses can be sent with the peer MAC as BSSID */
3059 !((hapd->conf->p2p & P2P_GROUP_OWNER) &&
3060 stype == WLAN_FC_STYPE_ACTION) &&
3061#endif /* CONFIG_P2P */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003062#ifdef CONFIG_MESH
3063 !(hapd->conf->mesh & MESH_ENABLED) &&
3064#endif /* CONFIG_MESH */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003065 os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003066 wpa_printf(MSG_INFO, "MGMT: BSSID=" MACSTR " not our address",
3067 MAC2STR(mgmt->bssid));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003068 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003069 }
3070
3071
3072 if (stype == WLAN_FC_STYPE_PROBE_REQ) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003073 handle_probe_req(hapd, mgmt, len, fi->ssi_signal);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003074 return 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003075 }
3076
3077 if (os_memcmp(mgmt->da, hapd->own_addr, ETH_ALEN) != 0) {
3078 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
3079 HOSTAPD_LEVEL_DEBUG,
3080 "MGMT: DA=" MACSTR " not our address",
3081 MAC2STR(mgmt->da));
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003082 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003083 }
3084
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003085 if (hapd->iconf->track_sta_max_num)
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003086 sta_track_add(hapd->iface, mgmt->sa, fi->ssi_signal);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003087
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003088 switch (stype) {
3089 case WLAN_FC_STYPE_AUTH:
3090 wpa_printf(MSG_DEBUG, "mgmt::auth");
3091 handle_auth(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003092 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003093 break;
3094 case WLAN_FC_STYPE_ASSOC_REQ:
3095 wpa_printf(MSG_DEBUG, "mgmt::assoc_req");
3096 handle_assoc(hapd, mgmt, len, 0);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003097 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003098 break;
3099 case WLAN_FC_STYPE_REASSOC_REQ:
3100 wpa_printf(MSG_DEBUG, "mgmt::reassoc_req");
3101 handle_assoc(hapd, mgmt, len, 1);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003102 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003103 break;
3104 case WLAN_FC_STYPE_DISASSOC:
3105 wpa_printf(MSG_DEBUG, "mgmt::disassoc");
3106 handle_disassoc(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003107 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003108 break;
3109 case WLAN_FC_STYPE_DEAUTH:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003110 wpa_msg(hapd->msg_ctx, MSG_DEBUG, "mgmt::deauth");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003111 handle_deauth(hapd, mgmt, len);
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003112 ret = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003113 break;
3114 case WLAN_FC_STYPE_ACTION:
3115 wpa_printf(MSG_DEBUG, "mgmt::action");
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003116 ret = handle_action(hapd, mgmt, len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003117 break;
3118 default:
3119 hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
3120 HOSTAPD_LEVEL_DEBUG,
3121 "unknown mgmt frame subtype %d", stype);
3122 break;
3123 }
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003124
3125 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003126}
3127
3128
3129static void handle_auth_cb(struct hostapd_data *hapd,
3130 const struct ieee80211_mgmt *mgmt,
3131 size_t len, int ok)
3132{
3133 u16 auth_alg, auth_transaction, status_code;
3134 struct sta_info *sta;
3135
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003136 sta = ap_get_sta(hapd, mgmt->da);
3137 if (!sta) {
3138 wpa_printf(MSG_INFO, "handle_auth_cb: STA " MACSTR " not found",
3139 MAC2STR(mgmt->da));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003140 return;
3141 }
3142
3143 auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
3144 auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
3145 status_code = le_to_host16(mgmt->u.auth.status_code);
3146
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003147 if (!ok) {
3148 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
3149 HOSTAPD_LEVEL_NOTICE,
3150 "did not acknowledge authentication response");
3151 goto fail;
3152 }
3153
3154 if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
3155 wpa_printf(MSG_INFO, "handle_auth_cb - too short payload (len=%lu)",
3156 (unsigned long) len);
3157 goto fail;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003158 }
3159
3160 if (status_code == WLAN_STATUS_SUCCESS &&
3161 ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) ||
3162 (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) {
3163 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3164 HOSTAPD_LEVEL_INFO, "authenticated");
3165 sta->flags |= WLAN_STA_AUTH;
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003166 if (sta->added_unassoc)
3167 hostapd_set_sta_flags(hapd, sta);
3168 return;
3169 }
3170
3171fail:
3172 if (status_code != WLAN_STATUS_SUCCESS && sta->added_unassoc) {
3173 hostapd_drv_sta_remove(hapd, sta->addr);
3174 sta->added_unassoc = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003175 }
3176}
3177
3178
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003179static void hostapd_set_wds_encryption(struct hostapd_data *hapd,
3180 struct sta_info *sta,
3181 char *ifname_wds)
3182{
3183 int i;
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07003184 struct hostapd_ssid *ssid = &hapd->conf->ssid;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003185
3186 if (hapd->conf->ieee802_1x || hapd->conf->wpa)
3187 return;
3188
3189 for (i = 0; i < 4; i++) {
3190 if (ssid->wep.key[i] &&
3191 hostapd_drv_set_key(ifname_wds, hapd, WPA_ALG_WEP, NULL, i,
3192 i == ssid->wep.idx, NULL, 0,
3193 ssid->wep.key[i], ssid->wep.len[i])) {
3194 wpa_printf(MSG_WARNING,
3195 "Could not set WEP keys for WDS interface; %s",
3196 ifname_wds);
3197 break;
3198 }
3199 }
3200}
3201
3202
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003203static void handle_assoc_cb(struct hostapd_data *hapd,
3204 const struct ieee80211_mgmt *mgmt,
3205 size_t len, int reassoc, int ok)
3206{
3207 u16 status;
3208 struct sta_info *sta;
3209 int new_assoc = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003210
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003211 sta = ap_get_sta(hapd, mgmt->da);
3212 if (!sta) {
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003213 wpa_printf(MSG_INFO, "handle_assoc_cb: STA " MACSTR " not found",
3214 MAC2STR(mgmt->da));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003215 return;
3216 }
3217
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003218 if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) :
3219 sizeof(mgmt->u.assoc_resp))) {
3220 wpa_printf(MSG_INFO,
3221 "handle_assoc_cb(reassoc=%d) - too short payload (len=%lu)",
3222 reassoc, (unsigned long) len);
3223 hostapd_drv_sta_remove(hapd, sta->addr);
Dmitry Shmidtaa532512012-09-24 10:35:31 -07003224 return;
3225 }
3226
3227 if (reassoc)
3228 status = le_to_host16(mgmt->u.reassoc_resp.status_code);
3229 else
3230 status = le_to_host16(mgmt->u.assoc_resp.status_code);
3231
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003232 if (!ok) {
3233 hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211,
3234 HOSTAPD_LEVEL_DEBUG,
3235 "did not acknowledge association response");
3236 sta->flags &= ~WLAN_STA_ASSOC_REQ_OK;
3237 /* The STA is added only in case of SUCCESS */
3238 if (status == WLAN_STATUS_SUCCESS)
3239 hostapd_drv_sta_remove(hapd, sta->addr);
3240
3241 return;
3242 }
3243
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003244 if (status != WLAN_STATUS_SUCCESS)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003245 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003246
3247 /* Stop previous accounting session, if one is started, and allocate
3248 * new session id for the new session. */
3249 accounting_sta_stop(hapd, sta);
3250
3251 hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
3252 HOSTAPD_LEVEL_INFO,
3253 "associated (aid %d)",
3254 sta->aid);
3255
3256 if (sta->flags & WLAN_STA_ASSOC)
3257 new_assoc = 0;
3258 sta->flags |= WLAN_STA_ASSOC;
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003259 sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE;
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003260 if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa &&
3261 !hapd->conf->osen) ||
3262 sta->auth_alg == WLAN_AUTH_FILS_SK ||
3263 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
3264 sta->auth_alg == WLAN_AUTH_FILS_PK ||
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003265 sta->auth_alg == WLAN_AUTH_FT) {
3266 /*
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003267 * Open, static WEP, FT protocol, or FILS; no separate
3268 * authorization step.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003269 */
3270 ap_sta_set_authorized(hapd, sta, 1);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003271 }
3272
3273 if (reassoc)
3274 mlme_reassociate_indication(hapd, sta);
3275 else
3276 mlme_associate_indication(hapd, sta);
3277
3278#ifdef CONFIG_IEEE80211W
3279 sta->sa_query_timed_out = 0;
3280#endif /* CONFIG_IEEE80211W */
3281
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003282 if (sta->eapol_sm == NULL) {
3283 /*
3284 * This STA does not use RADIUS server for EAP authentication,
3285 * so bind it to the selected VLAN interface now, since the
3286 * interface selection is not going to change anymore.
3287 */
Dmitry Shmidt83474442015-04-15 13:47:09 -07003288 if (ap_sta_bind_vlan(hapd, sta) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003289 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003290 } else if (sta->vlan_id) {
3291 /* VLAN ID already set (e.g., by PMKSA caching), so bind STA */
Dmitry Shmidt83474442015-04-15 13:47:09 -07003292 if (ap_sta_bind_vlan(hapd, sta) < 0)
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07003293 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003294 }
3295
3296 hostapd_set_sta_flags(hapd, sta);
3297
Dmitry Shmidt29333592017-01-09 12:27:11 -08003298 if (!(sta->flags & WLAN_STA_WDS) && sta->pending_wds_enable) {
3299 wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for STA "
3300 MACSTR " based on pending request",
3301 MAC2STR(sta->addr));
3302 sta->pending_wds_enable = 0;
3303 sta->flags |= WLAN_STA_WDS;
3304 }
3305
Dmitry Shmidtabb90a32016-12-05 15:34:39 -08003306 if (sta->flags & WLAN_STA_WDS) {
3307 int ret;
3308 char ifname_wds[IFNAMSIZ + 1];
3309
3310 wpa_printf(MSG_DEBUG, "Reenable 4-address WDS mode for STA "
3311 MACSTR " (aid %u)",
3312 MAC2STR(sta->addr), sta->aid);
3313 ret = hostapd_set_wds_sta(hapd, ifname_wds, sta->addr,
3314 sta->aid, 1);
3315 if (!ret)
3316 hostapd_set_wds_encryption(hapd, sta, ifname_wds);
3317 }
3318
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003319 if (sta->auth_alg == WLAN_AUTH_FT)
3320 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT);
3321 else
3322 wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
3323 hapd->new_assoc_sta_cb(hapd, sta, !new_assoc);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003324 ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08003325
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003326#ifdef CONFIG_FILS
3327 if ((sta->auth_alg == WLAN_AUTH_FILS_SK ||
3328 sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
3329 sta->auth_alg == WLAN_AUTH_FILS_PK) &&
3330 fils_set_tk(sta->wpa_sm) < 0) {
3331 wpa_printf(MSG_DEBUG, "FILS: TK configuration failed");
3332 ap_sta_disconnect(hapd, sta, sta->addr,
3333 WLAN_REASON_UNSPECIFIED);
3334 return;
3335 }
3336#endif /* CONFIG_FILS */
3337
Dmitry Shmidt31a29cc2016-03-09 15:58:17 -08003338 if (sta->pending_eapol_rx) {
3339 struct os_reltime now, age;
3340
3341 os_get_reltime(&now);
3342 os_reltime_sub(&now, &sta->pending_eapol_rx->rx_time, &age);
3343 if (age.sec == 0 && age.usec < 200000) {
3344 wpa_printf(MSG_DEBUG,
3345 "Process pending EAPOL frame that was received from " MACSTR " just before association notification",
3346 MAC2STR(sta->addr));
3347 ieee802_1x_receive(
3348 hapd, mgmt->da,
3349 wpabuf_head(sta->pending_eapol_rx->buf),
3350 wpabuf_len(sta->pending_eapol_rx->buf));
3351 }
3352 wpabuf_free(sta->pending_eapol_rx->buf);
3353 os_free(sta->pending_eapol_rx);
3354 sta->pending_eapol_rx = NULL;
3355 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003356}
3357
3358
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003359static void handle_deauth_cb(struct hostapd_data *hapd,
3360 const struct ieee80211_mgmt *mgmt,
3361 size_t len, int ok)
3362{
3363 struct sta_info *sta;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003364 if (is_multicast_ether_addr(mgmt->da))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003365 return;
3366 sta = ap_get_sta(hapd, mgmt->da);
3367 if (!sta) {
3368 wpa_printf(MSG_DEBUG, "handle_deauth_cb: STA " MACSTR
3369 " not found", MAC2STR(mgmt->da));
3370 return;
3371 }
3372 if (ok)
3373 wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged deauth",
3374 MAC2STR(sta->addr));
3375 else
3376 wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
3377 "deauth", MAC2STR(sta->addr));
3378
3379 ap_sta_deauth_cb(hapd, sta);
3380}
3381
3382
3383static void handle_disassoc_cb(struct hostapd_data *hapd,
3384 const struct ieee80211_mgmt *mgmt,
3385 size_t len, int ok)
3386{
3387 struct sta_info *sta;
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003388 if (is_multicast_ether_addr(mgmt->da))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003389 return;
3390 sta = ap_get_sta(hapd, mgmt->da);
3391 if (!sta) {
3392 wpa_printf(MSG_DEBUG, "handle_disassoc_cb: STA " MACSTR
3393 " not found", MAC2STR(mgmt->da));
3394 return;
3395 }
3396 if (ok)
3397 wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged disassoc",
3398 MAC2STR(sta->addr));
3399 else
3400 wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge "
3401 "disassoc", MAC2STR(sta->addr));
3402
3403 ap_sta_disassoc_cb(hapd, sta);
3404}
3405
3406
Dmitry Shmidt29333592017-01-09 12:27:11 -08003407static void handle_action_cb(struct hostapd_data *hapd,
3408 const struct ieee80211_mgmt *mgmt,
3409 size_t len, int ok)
3410{
3411 struct sta_info *sta;
3412
3413 if (is_multicast_ether_addr(mgmt->da))
3414 return;
3415 sta = ap_get_sta(hapd, mgmt->da);
3416 if (!sta) {
3417 wpa_printf(MSG_DEBUG, "handle_action_cb: STA " MACSTR
3418 " not found", MAC2STR(mgmt->da));
3419 return;
3420 }
3421
3422 if (len < 24 + 2)
3423 return;
3424 if (mgmt->u.action.category == WLAN_ACTION_RADIO_MEASUREMENT &&
3425 mgmt->u.action.u.rrm.action == WLAN_RRM_RADIO_MEASUREMENT_REQUEST)
3426 hostapd_rrm_beacon_req_tx_status(hapd, mgmt, len, ok);
3427}
3428
3429
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003430/**
3431 * ieee802_11_mgmt_cb - Process management frame TX status callback
3432 * @hapd: hostapd BSS data structure (the BSS from which the management frame
3433 * was sent from)
3434 * @buf: management frame data (starting from IEEE 802.11 header)
3435 * @len: length of frame data in octets
3436 * @stype: management frame subtype from frame control field
3437 * @ok: Whether the frame was ACK'ed
3438 */
3439void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len,
3440 u16 stype, int ok)
3441{
3442 const struct ieee80211_mgmt *mgmt;
3443 mgmt = (const struct ieee80211_mgmt *) buf;
3444
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08003445#ifdef CONFIG_TESTING_OPTIONS
3446 if (hapd->ext_mgmt_frame_handling) {
3447 wpa_msg(hapd->msg_ctx, MSG_INFO, "MGMT-TX-STATUS stype=%u ok=%d",
3448 stype, ok);
3449 return;
3450 }
3451#endif /* CONFIG_TESTING_OPTIONS */
3452
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003453 switch (stype) {
3454 case WLAN_FC_STYPE_AUTH:
3455 wpa_printf(MSG_DEBUG, "mgmt::auth cb");
3456 handle_auth_cb(hapd, mgmt, len, ok);
3457 break;
3458 case WLAN_FC_STYPE_ASSOC_RESP:
3459 wpa_printf(MSG_DEBUG, "mgmt::assoc_resp cb");
3460 handle_assoc_cb(hapd, mgmt, len, 0, ok);
3461 break;
3462 case WLAN_FC_STYPE_REASSOC_RESP:
3463 wpa_printf(MSG_DEBUG, "mgmt::reassoc_resp cb");
3464 handle_assoc_cb(hapd, mgmt, len, 1, ok);
3465 break;
3466 case WLAN_FC_STYPE_PROBE_RESP:
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003467 wpa_printf(MSG_EXCESSIVE, "mgmt::proberesp cb ok=%d", ok);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003468 break;
3469 case WLAN_FC_STYPE_DEAUTH:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003470 wpa_printf(MSG_DEBUG, "mgmt::deauth cb");
3471 handle_deauth_cb(hapd, mgmt, len, ok);
3472 break;
3473 case WLAN_FC_STYPE_DISASSOC:
3474 wpa_printf(MSG_DEBUG, "mgmt::disassoc cb");
3475 handle_disassoc_cb(hapd, mgmt, len, ok);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003476 break;
3477 case WLAN_FC_STYPE_ACTION:
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08003478 wpa_printf(MSG_DEBUG, "mgmt::action cb ok=%d", ok);
Dmitry Shmidt29333592017-01-09 12:27:11 -08003479 handle_action_cb(hapd, mgmt, len, ok);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003480 break;
3481 default:
Dmitry Shmidtcce06662013-11-04 18:44:24 -08003482 wpa_printf(MSG_INFO, "unknown mgmt cb frame subtype %d", stype);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003483 break;
3484 }
3485}
3486
3487
3488int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
3489{
3490 /* TODO */
3491 return 0;
3492}
3493
3494
3495int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta,
3496 char *buf, size_t buflen)
3497{
3498 /* TODO */
3499 return 0;
3500}
3501
3502
3503void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr,
3504 const u8 *buf, size_t len, int ack)
3505{
3506 struct sta_info *sta;
3507 struct hostapd_iface *iface = hapd->iface;
3508
3509 sta = ap_get_sta(hapd, addr);
3510 if (sta == NULL && iface->num_bss > 1) {
3511 size_t j;
3512 for (j = 0; j < iface->num_bss; j++) {
3513 hapd = iface->bss[j];
3514 sta = ap_get_sta(hapd, addr);
3515 if (sta)
3516 break;
3517 }
3518 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003519 if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003520 return;
3521 if (sta->flags & WLAN_STA_PENDING_POLL) {
3522 wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending "
3523 "activity poll", MAC2STR(sta->addr),
3524 ack ? "ACKed" : "did not ACK");
3525 if (ack)
3526 sta->flags &= ~WLAN_STA_PENDING_POLL;
3527 }
3528
3529 ieee802_1x_tx_status(hapd, sta, buf, len, ack);
3530}
3531
3532
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003533void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst,
3534 const u8 *data, size_t len, int ack)
3535{
3536 struct sta_info *sta;
3537 struct hostapd_iface *iface = hapd->iface;
3538
3539 sta = ap_get_sta(hapd, dst);
3540 if (sta == NULL && iface->num_bss > 1) {
3541 size_t j;
3542 for (j = 0; j < iface->num_bss; j++) {
3543 hapd = iface->bss[j];
3544 sta = ap_get_sta(hapd, dst);
3545 if (sta)
3546 break;
3547 }
3548 }
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003549 if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) {
3550 wpa_printf(MSG_DEBUG, "Ignore TX status for Data frame to STA "
3551 MACSTR " that is not currently associated",
3552 MAC2STR(dst));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003553 return;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003554 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003555
3556 ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack);
3557}
3558
3559
3560void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr)
3561{
3562 struct sta_info *sta;
3563 struct hostapd_iface *iface = hapd->iface;
3564
3565 sta = ap_get_sta(hapd, addr);
3566 if (sta == NULL && iface->num_bss > 1) {
3567 size_t j;
3568 for (j = 0; j < iface->num_bss; j++) {
3569 hapd = iface->bss[j];
3570 sta = ap_get_sta(hapd, addr);
3571 if (sta)
3572 break;
3573 }
3574 }
3575 if (sta == NULL)
3576 return;
Dmitry Shmidt849734c2016-05-27 09:59:01 -07003577 wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POLL_OK MACSTR,
3578 MAC2STR(sta->addr));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003579 if (!(sta->flags & WLAN_STA_PENDING_POLL))
3580 return;
3581
3582 wpa_printf(MSG_DEBUG, "STA " MACSTR " ACKed pending "
3583 "activity poll", MAC2STR(sta->addr));
3584 sta->flags &= ~WLAN_STA_PENDING_POLL;
3585}
3586
3587
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003588void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src,
3589 int wds)
3590{
3591 struct sta_info *sta;
3592
3593 sta = ap_get_sta(hapd, src);
Dmitry Shmidt29333592017-01-09 12:27:11 -08003594 if (sta &&
3595 ((sta->flags & WLAN_STA_ASSOC) ||
3596 ((sta->flags & WLAN_STA_ASSOC_REQ_OK) && wds))) {
Dmitry Shmidtaa532512012-09-24 10:35:31 -07003597 if (!hapd->conf->wds_sta)
3598 return;
3599
Dmitry Shmidt29333592017-01-09 12:27:11 -08003600 if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK)) ==
3601 WLAN_STA_ASSOC_REQ_OK) {
3602 wpa_printf(MSG_DEBUG,
3603 "Postpone 4-address WDS mode enabling for STA "
3604 MACSTR " since TX status for AssocResp is not yet known",
3605 MAC2STR(sta->addr));
3606 sta->pending_wds_enable = 1;
3607 return;
3608 }
3609
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003610 if (wds && !(sta->flags & WLAN_STA_WDS)) {
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003611 int ret;
3612 char ifname_wds[IFNAMSIZ + 1];
3613
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003614 wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for "
3615 "STA " MACSTR " (aid %u)",
3616 MAC2STR(sta->addr), sta->aid);
3617 sta->flags |= WLAN_STA_WDS;
Dmitry Shmidtc2ebb4b2013-07-24 12:57:51 -07003618 ret = hostapd_set_wds_sta(hapd, ifname_wds,
3619 sta->addr, sta->aid, 1);
3620 if (!ret)
3621 hostapd_set_wds_encryption(hapd, sta,
3622 ifname_wds);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003623 }
3624 return;
3625 }
3626
3627 wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA "
3628 MACSTR, MAC2STR(src));
Dmitry Shmidtd13095b2016-08-22 14:02:19 -07003629 if (is_multicast_ether_addr(src)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003630 /* Broadcast bit set in SA?! Ignore the frame silently. */
3631 return;
3632 }
3633
3634 if (sta && (sta->flags & WLAN_STA_ASSOC_REQ_OK)) {
3635 wpa_printf(MSG_DEBUG, "Association Response to the STA has "
3636 "already been sent, but no TX status yet known - "
3637 "ignore Class 3 frame issue with " MACSTR,
3638 MAC2STR(src));
3639 return;
3640 }
3641
3642 if (sta && (sta->flags & WLAN_STA_AUTH))
3643 hostapd_drv_sta_disassoc(
3644 hapd, src,
3645 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
3646 else
3647 hostapd_drv_sta_deauth(
3648 hapd, src,
3649 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
3650}
3651
3652
3653#endif /* CONFIG_NATIVE_WINDOWS */