18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / Callback functions for driver wrappers
3391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * Copyright (c) 2002-2013, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h"
127832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#include "utils/eloop.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "radius/radius.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "drivers/driver.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h"
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_common.h"
17f86232838cf712377867cb42417c1613ab5dc425Dmitry Shmidt#include "common/wpa_ctrl.h"
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h"
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "p2p/p2p.h"
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps/wps.h"
2161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#include "wnm_ap.h"
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "hostapd.h"
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_11.h"
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "sta_info.h"
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "accounting.h"
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "tkip_countermeasures.h"
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ieee802_1x.h"
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_auth.h"
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_hostapd.h"
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_drv_ops.h"
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_config.h"
3204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt#include "hw_features.h"
33051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#include "dfs.h"
347832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#include "beacon.h"
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			const u8 *req_ies, size_t req_ies_len, int reassoc)
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct sta_info *sta;
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int new_assoc, res;
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	struct ieee802_11_elems elems;
431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	const u8 *ie;
441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	size_t ielen;
4561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211R
4661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 buf[sizeof(struct ieee80211_mgmt) + 1024];
4761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u8 *p = buf;
4861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	u16 reason = WLAN_REASON_UNSPECIFIED;
5061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	u16 status = WLAN_STATUS_SUCCESS;
51391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt	const u8 *p2p_dev_addr = NULL;
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (addr == NULL) {
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * This could potentially happen with unexpected event from the
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * driver wrapper. This was seen at least in one case where the
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * driver ended up being set to station mode while hostapd was
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * running, so better make sure we stop processing such an
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * event here.
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "hostapd_notif_assoc: Skip event with "
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "no address");
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	random_add_randomness(addr, ETH_ALEN);
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		       HOSTAPD_LEVEL_INFO, "associated");
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	ieee802_11_parse_elems(req_ies, req_ies_len, &elems, 0);
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.wps_ie) {
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ie = elems.wps_ie - 2;
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ielen = elems.wps_ie_len + 2;
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq");
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (elems.rsn_ie) {
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ie = elems.rsn_ie - 2;
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ielen = elems.rsn_ie_len + 2;
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq");
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (elems.wpa_ie) {
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ie = elems.wpa_ie - 2;
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ielen = elems.wpa_ie_len + 2;
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq");
83f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_HS20
84f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	} else if (elems.osen) {
85f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		ie = elems.osen - 2;
86f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		ielen = elems.osen_len + 2;
87f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		wpa_printf(MSG_DEBUG, "STA included OSEN IE in (Re)AssocReq");
88f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_HS20 */
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ie = NULL;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		ielen = 0;
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "STA did not include WPS/RSN/WPA IE in "
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   "(Re)AssocReq");
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta = ap_get_sta(hapd, addr);
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (sta) {
9834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt		ap_sta_no_session_timeout(hapd, sta);
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		accounting_sta_stop(hapd, sta);
10004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
10104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		/*
10204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * Make sure that the previously registered inactivity timer
10304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 * will not remove the STA immediately.
10404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		 */
10504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		sta->timeout_next = STA_NULLFUNC;
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else {
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		sta = ap_sta_add(hapd, addr);
10804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		if (sta == NULL) {
10904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			hostapd_drv_sta_disassoc(hapd, addr,
11004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt						 WLAN_REASON_DISASSOC_AP_BUSY);
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
11204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		}
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt	sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2);
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_P2P
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (elems.p2p) {
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_free(sta->p2p_ie);
1191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		sta->p2p_ie = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							  P2P_IE_VENDOR_TYPE);
121391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt		if (sta->p2p_ie)
122391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt			p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie);
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_P2P */
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1267832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#ifdef CONFIG_IEEE80211N
1277832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#ifdef NEED_AP_MLME
1287832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt	if (elems.ht_capabilities &&
1297832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt	    elems.ht_capabilities_len >=
1307832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt	    sizeof(struct ieee80211_ht_capabilities) &&
1317832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt	    (hapd->iface->conf->ht_capab &
1327832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt	     HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) {
1337832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt		struct ieee80211_ht_capabilities *ht_cap =
1347832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			(struct ieee80211_ht_capabilities *)
1357832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			elems.ht_capabilities;
1367832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt
1377832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt		if (le_to_host16(ht_cap->ht_capabilities_info) &
1387832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt		    HT_CAP_INFO_40MHZ_INTOLERANT)
1397832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt			ht40_intolerant_add(hapd->iface, sta);
1407832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt	}
1417832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#endif /* NEED_AP_MLME */
1427832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#endif /* CONFIG_IEEE80211N */
1437832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt
144051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#ifdef CONFIG_INTERWORKING
145051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	if (elems.ext_capab && elems.ext_capab_len > 4) {
146051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt		if (elems.ext_capab[4] & 0x01)
147051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt			sta->qos_map_enabled = 1;
148051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt	}
149051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#endif /* CONFIG_INTERWORKING */
150051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt
151d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#ifdef CONFIG_HS20
152d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	wpabuf_free(sta->hs20_ie);
153d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	if (elems.hs20 && elems.hs20_len > 4) {
154d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		sta->hs20_ie = wpabuf_alloc_copy(elems.hs20 + 4,
155d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt						 elems.hs20_len - 4);
156d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt	} else
157d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt		sta->hs20_ie = NULL;
158d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt#endif /* CONFIG_HS20 */
159d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (hapd->conf->wpa) {
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (ie == NULL || ielen == 0) {
1621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_WPS
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			if (hapd->conf->wps_state) {
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				wpa_printf(MSG_DEBUG, "STA did not include "
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "WPA/RSN IE in (Re)Association "
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					   "Request - possible WPS use");
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				sta->flags |= WLAN_STA_MAYBE_WPS;
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				goto skip_wpa_check;
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			}
1701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_WPS */
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_WPS
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		    os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
1781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			struct wpabuf *wps;
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sta->flags |= WLAN_STA_WPS;
1801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wps = ieee802_11_vendor_ie_concat(ie, ielen,
1811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt							  WPS_IE_VENDOR_TYPE);
1821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (wps) {
1831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				if (wps_is_20(wps)) {
1841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					wpa_printf(MSG_DEBUG, "WPS: STA "
1851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt						   "supports WPS 2.0");
1861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					sta->flags |= WLAN_STA_WPS2;
1871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				}
1881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				wpabuf_free(wps);
1891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			}
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			goto skip_wpa_check;
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
1921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_WPS */
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sta->wpa_sm == NULL)
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
196391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt							sta->addr,
197391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt							p2p_dev_addr);
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (sta->wpa_sm == NULL) {
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "machine");
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			return -1;
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
20461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					  ie, ielen,
20561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					  elems.mdie, elems.mdie_len);
2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (res != WPA_IE_OK) {
2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_printf(MSG_DEBUG, "WPA/RSN information element "
2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   "rejected? (res %u)", res);
2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
21061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (res == WPA_INVALID_GROUP) {
2111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
21261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
21361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			} else if (res == WPA_INVALID_PAIRWISE) {
2141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID;
21561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
21661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			} else if (res == WPA_INVALID_AKMP) {
2171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				reason = WLAN_REASON_AKMP_NOT_VALID;
21861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				status = WLAN_STATUS_AKMP_NOT_VALID;
21961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			}
2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211W
22161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) {
2221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				reason = WLAN_REASON_INVALID_IE;
22361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				status = WLAN_STATUS_INVALID_IE;
22461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			} else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) {
2251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID;
22661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
22761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			}
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
22961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			else {
2301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				reason = WLAN_REASON_INVALID_IE;
23161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				status = WLAN_STATUS_INVALID_IE;
23261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			}
2331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			goto fail;
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
23561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211W
23661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
23761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    sta->sa_query_count > 0)
23861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			ap_check_sa_query_timeout(hapd, sta);
23961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
24061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		    (sta->auth_alg != WLAN_AUTH_FT)) {
24161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			/*
24261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			 * STA has already been associated with MFP and SA
24361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			 * Query timeout has not been reached. Reject the
24461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			 * association attempt temporarily and start SA Query,
24561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			 * if one is not pending.
24661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			 */
24761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
24861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (sta->sa_query_count == 0)
24961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				ap_sta_start_sa_query(hapd, sta);
25061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
25161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211R
25261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY;
25361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
25461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			p = hostapd_eid_assoc_comeback_time(hapd, sta, p);
25561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
25661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			hostapd_sta_assoc(hapd, addr, reassoc, status, buf,
25761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					  p - buf);
25861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
25961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			return 0;
26061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
26161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
26261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (wpa_auth_uses_mfp(sta->wpa_sm))
26361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			sta->flags |= WLAN_STA_MFP;
26461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		else
26561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			sta->flags &= ~WLAN_STA_MFP;
26661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211W */
26761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
26861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211R
26961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		if (sta->auth_alg == WLAN_AUTH_FT) {
27061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			status = wpa_ft_validate_reassoc(sta->wpa_sm, req_ies,
27161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt							 req_ies_len);
27261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			if (status != WLAN_STATUS_SUCCESS) {
27361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				if (status == WLAN_STATUS_INVALID_PMKID)
27461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					reason = WLAN_REASON_INVALID_IE;
27561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				if (status == WLAN_STATUS_INVALID_MDIE)
27661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					reason = WLAN_REASON_INVALID_IE;
27761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				if (status == WLAN_STATUS_INVALID_FTIE)
27861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					reason = WLAN_REASON_INVALID_IE;
27961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt				goto fail;
28061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			}
28161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt		}
28261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	} else if (hapd->conf->wps_state) {
2841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_WPS
2851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		struct wpabuf *wps;
2861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (req_ies)
2871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wps = ieee802_11_vendor_ie_concat(req_ies, req_ies_len,
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt							  WPS_IE_VENDOR_TYPE);
2891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		else
2901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			wps = NULL;
2911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_WPS_STRICT
2921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (wps && wps_validate_assoc_req(wps) < 0) {
2931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			reason = WLAN_REASON_INVALID_IE;
29461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt			status = WLAN_STATUS_INVALID_IE;
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			wpabuf_free(wps);
2961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			goto fail;
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		}
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_STRICT */
2991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		if (wps) {
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sta->flags |= WLAN_STA_WPS;
3011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			if (wps_is_20(wps)) {
3021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				wpa_printf(MSG_DEBUG, "WPS: STA supports "
3031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt					   "WPS 2.0");
3041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt				sta->flags |= WLAN_STA_WPS2;
3051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt			}
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		} else
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			sta->flags |= WLAN_STA_MAYBE_WPS;
3081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt		wpabuf_free(wps);
3091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_WPS */
310f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#ifdef CONFIG_HS20
311f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt	} else if (hapd->conf->osen) {
312f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		if (elems.osen == NULL) {
313f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			hostapd_logger(
314f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
315f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				HOSTAPD_LEVEL_INFO,
316f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				"No HS 2.0 OSEN element in association request");
317f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			return WLAN_STATUS_INVALID_IE;
318f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		}
319f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt
320f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association");
321f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		if (sta->wpa_sm == NULL)
322f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
323f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt							sta->addr, NULL);
324f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		if (sta->wpa_sm == NULL) {
325f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			wpa_printf(MSG_WARNING, "Failed to initialize WPA "
326f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				   "state machine");
327f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			return WLAN_STATUS_UNSPECIFIED_FAILURE;
328f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		}
329f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt		if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm,
330f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt				      elems.osen - 2, elems.osen_len + 2) < 0)
331f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt			return WLAN_STATUS_INVALID_IE;
332f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt#endif /* CONFIG_HS20 */
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#ifdef CONFIG_WPS
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_wpa_check:
3361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#endif /* CONFIG_WPS */
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
33861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#ifdef CONFIG_IEEE80211R
33961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf),
34061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt					sta->auth_alg, req_ies, req_ies_len);
34161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
34261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf);
343661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt
344661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt	if (sta->auth_alg == WLAN_AUTH_FT)
345661b4f78e48c697429dc46154a4125892c001718Dmitry Shmidt		ap_sta_set_authorized(hapd, sta, 1);
34661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#else /* CONFIG_IEEE80211R */
34761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	/* Keep compiler silent about unused variables */
34861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	if (status) {
34961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt	}
35061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt#endif /* CONFIG_IEEE80211R */
35161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
354