/**
 * wpa_parse_wpa_ie - Parse WPA/RSN IE
 * @wpa_ie: Pointer to WPA or RSN IE
 * @wpa_ie_len: Length of the WPA/RSN IE
 * @data: Pointer to data area for parsing results
 * Returns: 0 on success, -1 on failure
 *
 * Parse the contents of WPA or RSN IE and write the parsed data into data.
 */
int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
		     struct wpa_ie_data *data)
{
	if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSN)
		return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
	else
		return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
}
Example #2
0
/**
 * wpa_parse_wpa_ie - Parse WPA/RSN IE
 * @wpa_ie: Pointer to WPA or RSN IE
 * @wpa_ie_len: Length of the WPA/RSN IE
 * @data: Pointer to data area for parsing results
 * Returns: 0 on success, -1 on failure
 *
 * Parse the contents of WPA or RSN IE and write the parsed data into data.
 */
int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
		     struct wpa_ie_data *data)
{
	if (wpa_ie_len >= 1 && wpa_ie[0] == RSN_INFO_ELEM)
		return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
	else
		return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
}
Example #3
0
/**
 * wpa_parse_wpa_ie - Parse WPA/RSN IE
 * @wpa_ie: Pointer to WPA or RSN IE
 * @wpa_ie_len: Length of the WPA/RSN IE
 * @data: Pointer to data area for parsing results
 * Returns: 0 on success, -1 on failure
 *
 * Parse the contents of WPA or RSN IE and write the parsed data into data.
 */
int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len,
		     struct wpa_ie_data *data)
{
	if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSN)
		return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
	if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC &&
	    wpa_ie[1] >= 4 && WPA_GET_BE32(&wpa_ie[2]) == OSEN_IE_VENDOR_TYPE)
		return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
	else
		return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
}
Example #4
0
void sta_update_assoc(struct wlantest_sta *sta, struct ieee802_11_elems *elems)
{
	struct wpa_ie_data data;
	struct wlantest_bss *bss = sta->bss;

	if (elems->wpa_ie && !bss->wpaie[0]) {
		wpa_printf(MSG_INFO, "WPA IE included in Association Request "
			   "frame from " MACSTR " even though BSS does not "
			   "use WPA - ignore IE",
			   MAC2STR(sta->addr));
		elems->wpa_ie = NULL;
	}

	if (elems->rsn_ie && !bss->rsnie[0]) {
		wpa_printf(MSG_INFO, "RSN IE included in Association Request "
			   "frame from " MACSTR " even though BSS does not "
			   "use RSN - ignore IE",
			   MAC2STR(sta->addr));
		elems->rsn_ie = NULL;
	}

	if (elems->wpa_ie && elems->rsn_ie) {
		wpa_printf(MSG_INFO, "Both WPA IE and RSN IE included in "
			   "Association Request frame from " MACSTR,
			   MAC2STR(sta->addr));
	}

	if (elems->rsn_ie) {
		wpa_hexdump(MSG_DEBUG, "RSN IE", elems->rsn_ie - 2,
			    elems->rsn_ie_len + 2);
		os_memcpy(sta->rsnie, elems->rsn_ie - 2,
			  elems->rsn_ie_len + 2);
		if (wpa_parse_wpa_ie_rsn(sta->rsnie, 2 + sta->rsnie[1], &data)
		    < 0) {
			wpa_printf(MSG_INFO, "Failed to parse RSN IE from "
				   MACSTR, MAC2STR(sta->addr));
		}
	} else if (elems->wpa_ie) {
		wpa_hexdump(MSG_DEBUG, "WPA IE", elems->wpa_ie - 2,
			    elems->wpa_ie_len + 2);
		os_memcpy(sta->rsnie, elems->wpa_ie - 2,
			  elems->wpa_ie_len + 2);
		if (wpa_parse_wpa_ie_wpa(sta->rsnie, 2 + sta->rsnie[1], &data)
		    < 0) {
			wpa_printf(MSG_INFO, "Failed to parse WPA IE from "
				   MACSTR, MAC2STR(sta->addr));
		}
	} else {
		sta->rsnie[0] = 0;
		sta->proto = 0;
		sta->pairwise_cipher = 0;
		sta->key_mgmt = 0;
		sta->rsn_capab = 0;
		if (sta->assocreq_capab_info & WLAN_CAPABILITY_PRIVACY)
			sta->pairwise_cipher = WPA_CIPHER_WEP40;
		goto skip_rsn_wpa;
	}

	sta->proto = data.proto;
	sta->pairwise_cipher = data.pairwise_cipher;
	sta->key_mgmt = data.key_mgmt;
	sta->rsn_capab = data.capabilities;
	if (bss->proto && (sta->proto & bss->proto) == 0) {
		wpa_printf(MSG_INFO, "Mismatch in WPA/WPA2 proto: STA "
			   MACSTR " 0x%x  BSS " MACSTR " 0x%x",
			   MAC2STR(sta->addr), sta->proto,
			   MAC2STR(bss->bssid), bss->proto);
	}
	if (bss->pairwise_cipher &&
	    (sta->pairwise_cipher & bss->pairwise_cipher) == 0) {
		wpa_printf(MSG_INFO, "Mismatch in pairwise cipher: STA "
			   MACSTR " 0x%x  BSS " MACSTR " 0x%x",
			   MAC2STR(sta->addr), sta->pairwise_cipher,
			   MAC2STR(bss->bssid), bss->pairwise_cipher);
	}
	if (sta->proto && data.group_cipher != bss->group_cipher) {
		wpa_printf(MSG_INFO, "Mismatch in group cipher: STA "
			   MACSTR " 0x%x != BSS " MACSTR " 0x%x",
			   MAC2STR(sta->addr), data.group_cipher,
			   MAC2STR(bss->bssid), bss->group_cipher);
	}
	if ((bss->rsn_capab & WPA_CAPABILITY_MFPR) &&
	    !(sta->rsn_capab & WPA_CAPABILITY_MFPC)) {
		wpa_printf(MSG_INFO, "STA " MACSTR " tries to associate "
			   "without MFP to BSS " MACSTR " that advertises "
			   "MFPR", MAC2STR(sta->addr), MAC2STR(bss->bssid));
	}

skip_rsn_wpa:
	wpa_printf(MSG_INFO, "STA " MACSTR
		   " proto=%s%s%s"
		   "pairwise=%s%s%s%s"
		   "key_mgmt=%s%s%s%s%s%s%s%s"
		   "rsn_capab=%s%s%s%s%s",
		   MAC2STR(sta->addr),
		   sta->proto == 0 ? "OPEN " : "",
		   sta->proto & WPA_PROTO_WPA ? "WPA " : "",
		   sta->proto & WPA_PROTO_RSN ? "WPA2 " : "",
		   sta->pairwise_cipher == 0 ? "N/A " : "",
		   sta->pairwise_cipher & WPA_CIPHER_NONE ? "NONE " : "",
		   sta->pairwise_cipher & WPA_CIPHER_TKIP ? "TKIP " : "",
		   sta->pairwise_cipher & WPA_CIPHER_CCMP ? "CCMP " : "",
		   sta->key_mgmt == 0 ? "N/A " : "",
		   sta->key_mgmt & WPA_KEY_MGMT_IEEE8021X ? "EAP " : "",
		   sta->key_mgmt & WPA_KEY_MGMT_PSK ? "PSK " : "",
		   sta->key_mgmt & WPA_KEY_MGMT_WPA_NONE ? "WPA-NONE " : "",
		   sta->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X ? "FT-EAP " : "",
		   sta->key_mgmt & WPA_KEY_MGMT_FT_PSK ? "FT-PSK " : "",
		   sta->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256 ?
		   "EAP-SHA256 " : "",
		   sta->key_mgmt & WPA_KEY_MGMT_PSK_SHA256 ?
		   "PSK-SHA256 " : "",
		   sta->rsn_capab & WPA_CAPABILITY_PREAUTH ? "PREAUTH " : "",
		   sta->rsn_capab & WPA_CAPABILITY_NO_PAIRWISE ?
		   "NO_PAIRWISE " : "",
		   sta->rsn_capab & WPA_CAPABILITY_MFPR ? "MFPR " : "",
		   sta->rsn_capab & WPA_CAPABILITY_MFPC ? "MFPC " : "",
		   sta->rsn_capab & WPA_CAPABILITY_PEERKEY_ENABLED ?
		   "PEERKEY " : "");
}
Example #5
0
int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
			struct wpa_state_machine *sm,
			const u8 *wpa_ie, size_t wpa_ie_len,
			const u8 *mdie, size_t mdie_len)
{
	struct wpa_ie_data data;
	int ciphers, key_mgmt, res, version;
	u32 selector;
	size_t i;
	const u8 *pmkid = NULL;

	if (wpa_auth == NULL || sm == NULL)
		return WPA_NOT_ENABLED;

	if (wpa_ie == NULL || wpa_ie_len < 1)
		return WPA_INVALID_IE;

	if (wpa_ie[0] == WLAN_EID_RSN)
		version = WPA_PROTO_RSN;
	else
		version = WPA_PROTO_WPA;

	if (!(wpa_auth->conf.wpa & version)) {
		wpa_printf(MSG_DEBUG, "Invalid WPA proto (%d) from " MACSTR,
			   version, MAC2STR(sm->addr));
		return WPA_INVALID_PROTO;
	}

	if (version == WPA_PROTO_RSN) {
		res = wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, &data);

		selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
		if (0) {
		}
#ifdef CONFIG_IEEE80211R
		else if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
			selector = RSN_AUTH_KEY_MGMT_FT_802_1X;
		else if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK)
			selector = RSN_AUTH_KEY_MGMT_FT_PSK;
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211W
		else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
			selector = RSN_AUTH_KEY_MGMT_802_1X_SHA256;
		else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
			selector = RSN_AUTH_KEY_MGMT_PSK_SHA256;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_SAE
		else if (data.key_mgmt & WPA_KEY_MGMT_SAE)
			selector = RSN_AUTH_KEY_MGMT_SAE;
		else if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE)
			selector = RSN_AUTH_KEY_MGMT_FT_SAE;
#endif /* CONFIG_SAE */
		else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
			selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X;
		else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
			selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X;
		wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector;

		selector = wpa_cipher_to_suite(WPA_PROTO_RSN,
					       data.pairwise_cipher);
		if (!selector)
			selector = RSN_CIPHER_SUITE_CCMP;
		wpa_auth->dot11RSNAPairwiseCipherSelected = selector;

		selector = wpa_cipher_to_suite(WPA_PROTO_RSN,
					       data.group_cipher);
		if (!selector)
			selector = RSN_CIPHER_SUITE_CCMP;
		wpa_auth->dot11RSNAGroupCipherSelected = selector;
	} else {
		res = wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, &data);

		selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;
		if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X)
			selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X;
		else if (data.key_mgmt & WPA_KEY_MGMT_PSK)
			selector = WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X;
		wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector;

		selector = wpa_cipher_to_suite(WPA_PROTO_WPA,
					       data.pairwise_cipher);
		if (!selector)
			selector = RSN_CIPHER_SUITE_TKIP;
		wpa_auth->dot11RSNAPairwiseCipherSelected = selector;

		selector = wpa_cipher_to_suite(WPA_PROTO_WPA,
					       data.group_cipher);
		if (!selector)
			selector = WPA_CIPHER_SUITE_TKIP;
		wpa_auth->dot11RSNAGroupCipherSelected = selector;
	}
	if (res) {
		wpa_printf(MSG_DEBUG, "Failed to parse WPA/RSN IE from "
			   MACSTR " (res=%d)", MAC2STR(sm->addr), res);
		wpa_hexdump(MSG_DEBUG, "WPA/RSN IE", wpa_ie, wpa_ie_len);
		return WPA_INVALID_IE;
	}

	if (data.group_cipher != wpa_auth->conf.wpa_group) {
		wpa_printf(MSG_DEBUG, "Invalid WPA group cipher (0x%x) from "
			   MACSTR, data.group_cipher, MAC2STR(sm->addr));
		return WPA_INVALID_GROUP;
	}

	key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt;
	if (!key_mgmt) {
		wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from "
			   MACSTR, data.key_mgmt, MAC2STR(sm->addr));
		return WPA_INVALID_AKMP;
	}
	if (0) {
	}
#ifdef CONFIG_IEEE80211R
	else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
		sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
	else if (key_mgmt & WPA_KEY_MGMT_FT_PSK)
		sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK;
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_IEEE80211W
	else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256)
		sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256;
	else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256)
		sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_SAE
	else if (key_mgmt & WPA_KEY_MGMT_SAE)
		sm->wpa_key_mgmt = WPA_KEY_MGMT_SAE;
	else if (key_mgmt & WPA_KEY_MGMT_FT_SAE)
		sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_SAE;
#endif /* CONFIG_SAE */
	else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X)
		sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X;
	else
		sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK;

	if (version == WPA_PROTO_RSN)
		ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise;
	else
		ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise;
	if (!ciphers) {
		wpa_printf(MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) "
			   "from " MACSTR,
			   version == WPA_PROTO_RSN ? "RSN" : "WPA",
			   data.pairwise_cipher, MAC2STR(sm->addr));
		return WPA_INVALID_PAIRWISE;
	}

#ifdef CONFIG_IEEE80211W
	if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) {
		if (!(data.capabilities & WPA_CAPABILITY_MFPC)) {
			wpa_printf(MSG_DEBUG, "Management frame protection "
				   "required, but client did not enable it");
			return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
		}

		if (ciphers & WPA_CIPHER_TKIP) {
			wpa_printf(MSG_DEBUG, "Management frame protection "
				   "cannot use TKIP");
			return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
		}

		if (data.mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) {
			wpa_printf(MSG_DEBUG, "Unsupported management group "
				   "cipher %d", data.mgmt_group_cipher);
			return WPA_INVALID_MGMT_GROUP_CIPHER;
		}
	}

	if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION ||
	    !(data.capabilities & WPA_CAPABILITY_MFPC))
		sm->mgmt_frame_prot = 0;
	else
		sm->mgmt_frame_prot = 1;
#endif /* CONFIG_IEEE80211W */

#ifdef CONFIG_IEEE80211R
	if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) {
		if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) {
			wpa_printf(MSG_DEBUG, "RSN: Trying to use FT, but "
				   "MDIE not included");
			return WPA_INVALID_MDIE;
		}
		if (os_memcmp(mdie, wpa_auth->conf.mobility_domain,
			      MOBILITY_DOMAIN_ID_LEN) != 0) {
			wpa_hexdump(MSG_DEBUG, "RSN: Attempted to use unknown "
				    "MDIE", mdie, MOBILITY_DOMAIN_ID_LEN);
			return WPA_INVALID_MDIE;
		}
	}
#endif /* CONFIG_IEEE80211R */

	if (ciphers & WPA_CIPHER_CCMP)
		sm->pairwise = WPA_CIPHER_CCMP;
	else if (ciphers & WPA_CIPHER_GCMP)
		sm->pairwise = WPA_CIPHER_GCMP;
	else
		sm->pairwise = WPA_CIPHER_TKIP;

	/* TODO: clear WPA/WPA2 state if STA changes from one to another */
	if (wpa_ie[0] == WLAN_EID_RSN)
		sm->wpa = WPA_VERSION_WPA2;
	else
		sm->wpa = WPA_VERSION_WPA;

	sm->pmksa = NULL;
	for (i = 0; i < data.num_pmkid; i++) {
		wpa_hexdump(MSG_DEBUG, "RSN IE: STA PMKID",
			    &data.pmkid[i * PMKID_LEN], PMKID_LEN);
		sm->pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sm->addr,
						 &data.pmkid[i * PMKID_LEN]);
		if (sm->pmksa) {
			pmkid = sm->pmksa->pmkid;
			break;
		}
	}
	for (i = 0; sm->pmksa == NULL && wpa_auth->conf.okc &&
		     i < data.num_pmkid; i++) {
		struct wpa_auth_okc_iter_data idata;
		idata.pmksa = NULL;
		idata.aa = wpa_auth->addr;
		idata.spa = sm->addr;
		idata.pmkid = &data.pmkid[i * PMKID_LEN];
		wpa_auth_for_each_auth(wpa_auth, wpa_auth_okc_iter, &idata);
		if (idata.pmksa) {
			wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
					 "OKC match for PMKID");
			sm->pmksa = pmksa_cache_add_okc(wpa_auth->pmksa,
							idata.pmksa,
							wpa_auth->addr,
							idata.pmkid);
			pmkid = idata.pmkid;
			break;
		}
	}
	if (sm->pmksa) {
		wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG,
				 "PMKID found from PMKSA cache "
				 "eap_type=%d vlan_id=%d",
				 sm->pmksa->eap_type_authsrv,
				 sm->pmksa->vlan_id);
		os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmkid, PMKID_LEN);
	}

	if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) {
		os_free(sm->wpa_ie);
		sm->wpa_ie = os_malloc(wpa_ie_len);
		if (sm->wpa_ie == NULL)
			return WPA_ALLOC_FAIL;
	}
	os_memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len);
	sm->wpa_ie_len = wpa_ie_len;

	return WPA_IE_OK;
}
Example #6
0
void bss_update(struct wlantest *wt, struct wlantest_bss *bss,
		struct ieee802_11_elems *elems)
{
	struct wpa_ie_data data;
	int update = 0;

	if (bss->capab_info != bss->prev_capab_info)
		update = 1;

	if (elems->ssid == NULL || elems->ssid_len > 32) {
		wpa_printf(MSG_INFO, "Invalid or missing SSID in a Beacon "
			   "frame for " MACSTR, MAC2STR(bss->bssid));
		bss->parse_error_reported = 1;
		return;
	}

	if (bss->ssid_len != elems->ssid_len ||
	    os_memcmp(bss->ssid, elems->ssid, bss->ssid_len) != 0) {
		wpa_printf(MSG_DEBUG, "Store SSID '%s' for BSSID " MACSTR,
			   wpa_ssid_txt(elems->ssid, elems->ssid_len),
			   MAC2STR(bss->bssid));
		os_memcpy(bss->ssid, elems->ssid, elems->ssid_len);
		bss->ssid_len = elems->ssid_len;
		bss_add_pmk(wt, bss);
	}

	if (elems->osen == NULL) {
		if (bss->osenie[0]) {
			add_note(wt, MSG_INFO, "BSS " MACSTR
				 " - OSEN IE removed", MAC2STR(bss->bssid));
			bss->rsnie[0] = 0;
			update = 1;
		}
	} else {
		if (bss->osenie[0] == 0 ||
		    os_memcmp(bss->osenie, elems->osen - 2,
			      elems->osen_len + 2) != 0) {
			wpa_printf(MSG_INFO, "BSS " MACSTR " - OSEN IE "
				   "stored", MAC2STR(bss->bssid));
			wpa_hexdump(MSG_DEBUG, "OSEN IE", elems->osen - 2,
				    elems->osen_len + 2);
			update = 1;
		}
		os_memcpy(bss->osenie, elems->osen - 2,
			  elems->osen_len + 2);
	}

	if (elems->rsn_ie == NULL) {
		if (bss->rsnie[0]) {
			add_note(wt, MSG_INFO, "BSS " MACSTR
				 " - RSN IE removed", MAC2STR(bss->bssid));
			bss->rsnie[0] = 0;
			update = 1;
		}
	} else {
		if (bss->rsnie[0] == 0 ||
		    os_memcmp(bss->rsnie, elems->rsn_ie - 2,
			      elems->rsn_ie_len + 2) != 0) {
			wpa_printf(MSG_INFO, "BSS " MACSTR " - RSN IE "
				   "stored", MAC2STR(bss->bssid));
			wpa_hexdump(MSG_DEBUG, "RSN IE", elems->rsn_ie - 2,
				    elems->rsn_ie_len + 2);
			update = 1;
		}
		os_memcpy(bss->rsnie, elems->rsn_ie - 2,
			  elems->rsn_ie_len + 2);
	}

	if (elems->wpa_ie == NULL) {
		if (bss->wpaie[0]) {
			add_note(wt, MSG_INFO, "BSS " MACSTR
				 " - WPA IE removed", MAC2STR(bss->bssid));
			bss->wpaie[0] = 0;
			update = 1;
		}
	} else {
		if (bss->wpaie[0] == 0 ||
		    os_memcmp(bss->wpaie, elems->wpa_ie - 2,
			      elems->wpa_ie_len + 2) != 0) {
			wpa_printf(MSG_INFO, "BSS " MACSTR " - WPA IE "
				   "stored", MAC2STR(bss->bssid));
			wpa_hexdump(MSG_DEBUG, "WPA IE", elems->wpa_ie - 2,
				    elems->wpa_ie_len + 2);
			update = 1;
		}
		os_memcpy(bss->wpaie, elems->wpa_ie - 2,
			  elems->wpa_ie_len + 2);
	}

	if (!update)
		return;

	bss->prev_capab_info = bss->capab_info;
	bss->proto = 0;
	bss->pairwise_cipher = 0;
	bss->group_cipher = 0;
	bss->key_mgmt = 0;
	bss->rsn_capab = 0;
	bss->mgmt_group_cipher = 0;

	if (bss->wpaie[0]) {
		if (wpa_parse_wpa_ie_wpa(bss->wpaie, 2 + bss->wpaie[1], &data)
		    < 0) {
			add_note(wt, MSG_INFO, "Failed to parse WPA IE from "
				 MACSTR, MAC2STR(bss->bssid));
		} else {
			bss->proto |= data.proto;
			bss->pairwise_cipher |= data.pairwise_cipher;
			bss->group_cipher |= data.group_cipher;
			bss->key_mgmt |= data.key_mgmt;
			bss->rsn_capab = data.capabilities;
			bss->mgmt_group_cipher |= data.mgmt_group_cipher;
		}
	}

	if (bss->rsnie[0]) {
		if (wpa_parse_wpa_ie_rsn(bss->rsnie, 2 + bss->rsnie[1], &data)
		    < 0) {
			add_note(wt, MSG_INFO, "Failed to parse RSN IE from "
				 MACSTR, MAC2STR(bss->bssid));
		} else {
			bss->proto |= data.proto;
			bss->pairwise_cipher |= data.pairwise_cipher;
			bss->group_cipher |= data.group_cipher;
			bss->key_mgmt |= data.key_mgmt;
			bss->rsn_capab = data.capabilities;
			bss->mgmt_group_cipher |= data.mgmt_group_cipher;
		}
	}

	if (bss->osenie[0]) {
		bss->proto |= WPA_PROTO_OSEN;
		bss->pairwise_cipher |= WPA_CIPHER_CCMP;
		bss->group_cipher |= WPA_CIPHER_CCMP;
		bss->key_mgmt |= WPA_KEY_MGMT_OSEN;
	}

	if (!(bss->proto & WPA_PROTO_RSN) ||
	    !(bss->rsn_capab & WPA_CAPABILITY_MFPC))
		bss->mgmt_group_cipher = 0;

	if (!bss->wpaie[0] && !bss->rsnie[0] && !bss->osenie[0] &&
	    (bss->capab_info & WLAN_CAPABILITY_PRIVACY))
		bss->group_cipher = WPA_CIPHER_WEP40;

	wpa_printf(MSG_INFO, "BSS " MACSTR
		   " proto=%s%s%s%s"
		   "pairwise=%s%s%s%s%s%s%s"
		   "group=%s%s%s%s%s%s%s%s%s"
		   "mgmt_group_cipher=%s%s%s%s%s"
		   "key_mgmt=%s%s%s%s%s%s%s%s%s"
		   "rsn_capab=%s%s%s%s%s",
		   MAC2STR(bss->bssid),
		   bss->proto == 0 ? "OPEN " : "",
		   bss->proto & WPA_PROTO_WPA ? "WPA " : "",
		   bss->proto & WPA_PROTO_RSN ? "WPA2 " : "",
		   bss->proto & WPA_PROTO_OSEN ? "OSEN " : "",
		   bss->pairwise_cipher == 0 ? "N/A " : "",
		   bss->pairwise_cipher & WPA_CIPHER_NONE ? "NONE " : "",
		   bss->pairwise_cipher & WPA_CIPHER_TKIP ? "TKIP " : "",
		   bss->pairwise_cipher & WPA_CIPHER_CCMP ? "CCMP " : "",
		   bss->pairwise_cipher & WPA_CIPHER_CCMP_256 ? "CCMP-256 " :
		   "",
		   bss->pairwise_cipher & WPA_CIPHER_GCMP ? "GCMP " : "",
		   bss->pairwise_cipher & WPA_CIPHER_GCMP_256 ? "GCMP-256 " :
		   "",
		   bss->group_cipher == 0 ? "N/A " : "",
		   bss->group_cipher & WPA_CIPHER_NONE ? "NONE " : "",
		   bss->group_cipher & WPA_CIPHER_WEP40 ? "WEP40 " : "",
		   bss->group_cipher & WPA_CIPHER_WEP104 ? "WEP104 " : "",
		   bss->group_cipher & WPA_CIPHER_TKIP ? "TKIP " : "",
		   bss->group_cipher & WPA_CIPHER_CCMP ? "CCMP " : "",
		   bss->group_cipher & WPA_CIPHER_CCMP_256 ? "CCMP-256 " : "",
		   bss->group_cipher & WPA_CIPHER_GCMP ? "GCMP " : "",
		   bss->group_cipher & WPA_CIPHER_GCMP_256 ? "GCMP-256 " : "",
		   bss->mgmt_group_cipher == 0 ? "N/A " : "",
		   bss->mgmt_group_cipher & WPA_CIPHER_AES_128_CMAC ?
		   "BIP " : "",
		   bss->mgmt_group_cipher & WPA_CIPHER_BIP_GMAC_128 ?
		   "BIP-GMAC-128 " : "",
		   bss->mgmt_group_cipher & WPA_CIPHER_BIP_GMAC_256 ?
		   "BIP-GMAC-256 " : "",
		   bss->mgmt_group_cipher & WPA_CIPHER_BIP_CMAC_256 ?
		   "BIP-CMAC-256 " : "",
		   bss->key_mgmt == 0 ? "N/A " : "",
		   bss->key_mgmt & WPA_KEY_MGMT_IEEE8021X ? "EAP " : "",
		   bss->key_mgmt & WPA_KEY_MGMT_PSK ? "PSK " : "",
		   bss->key_mgmt & WPA_KEY_MGMT_WPA_NONE ? "WPA-NONE " : "",
		   bss->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X ? "FT-EAP " : "",
		   bss->key_mgmt & WPA_KEY_MGMT_FT_PSK ? "FT-PSK " : "",
		   bss->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256 ?
		   "EAP-SHA256 " : "",
		   bss->key_mgmt & WPA_KEY_MGMT_PSK_SHA256 ?
		   "PSK-SHA256 " : "",
		   bss->key_mgmt & WPA_KEY_MGMT_OSEN ? "OSEN " : "",
		   bss->rsn_capab & WPA_CAPABILITY_PREAUTH ? "PREAUTH " : "",
		   bss->rsn_capab & WPA_CAPABILITY_NO_PAIRWISE ?
		   "NO_PAIRWISE " : "",
		   bss->rsn_capab & WPA_CAPABILITY_MFPR ? "MFPR " : "",
		   bss->rsn_capab & WPA_CAPABILITY_MFPC ? "MFPC " : "",
		   bss->rsn_capab & WPA_CAPABILITY_PEERKEY_ENABLED ?
		   "PEERKEY " : "");
}