wpa_supplicant: Resolve secondary VAP association issue

Association will fail on a secondary open unprotected VAP when the
primary VAP is configured for WPA. Examples of secondary VAPs are,
hotels, universities, and commodity routers' guest networks.

A broadly similar bug was discussed on Red Hat's bugzilla affecting
association to a D-Link DIR-842.

This suggests that as IEs were added to the 802.11 protocol the old code
was increasingly inadaquate to handle the additional IEs, not only a
secondary VAP.

PR:		264238
Reported by:	Jaskie <jiangjun12321@gmail.com>
		"J.R. Oldroyd" <fbsd@opal.com>
Submitted by:	"J.R. Oldroyd" <fbsd@opal.com>
MFC after:	3 days
This commit is contained in:
J.R. Oldroyd 2022-07-02 11:15:31 -07:00 committed by Cy Schubert
parent 7999a7f2a8
commit 775611ea11

View file

@ -14,6 +14,7 @@
#include "driver.h"
#include "eloop.h"
#include "common/ieee802_11_defs.h"
#include "common/ieee802_11_common.h"
#include "common/wpa_common.h"
#include <ifaddrs.h>
@ -1200,14 +1201,42 @@ handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
drv_event_eapol_rx(drv->ctx, src_addr, buf, len);
}
static int
wpa_driver_bsd_set_rsn_wpa_ie(struct bsd_driver_data * drv,
struct wpa_driver_associate_params *params, const u8 *ie)
{
int privacy;
size_t ie_len = ie[1] ? ie[1] + 2 : 0;
/* XXX error handling is wrong but unclear what to do... */
if (wpa_driver_bsd_set_wpa_ie(drv, ie, ie_len) < 0)
return -1;
privacy = !(params->pairwise_suite == WPA_CIPHER_NONE &&
params->group_suite == WPA_CIPHER_NONE &&
params->key_mgmt_suite == WPA_KEY_MGMT_NONE);
wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__,
privacy);
if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
return -1;
if (ie_len &&
set80211param(drv, IEEE80211_IOC_WPA,
ie[0] == WLAN_EID_RSN ? 2 : 1) < 0)
return -1;
return 0;
}
static int
wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
{
struct bsd_driver_data *drv = priv;
struct ieee80211req_mlme mlme;
u32 mode;
int privacy;
int ret = 0;
const u8 *wpa_ie, *rsn_ie;
wpa_printf(MSG_DEBUG,
"%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u"
@ -1256,23 +1285,25 @@ wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params)
ret = -1;
if (wpa_driver_bsd_set_auth_alg(drv, params->auth_alg) < 0)
ret = -1;
/* XXX error handling is wrong but unclear what to do... */
if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0)
return -1;
privacy = !(params->pairwise_suite == WPA_CIPHER_NONE &&
params->group_suite == WPA_CIPHER_NONE &&
params->key_mgmt_suite == WPA_KEY_MGMT_NONE &&
params->wpa_ie_len == 0);
wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy);
if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0)
return -1;
if (params->wpa_ie_len &&
set80211param(drv, IEEE80211_IOC_WPA,
params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0)
return -1;
if (params->wpa_ie_len) {
rsn_ie = get_ie(params->wpa_ie, params->wpa_ie_len,
WLAN_EID_RSN);
if (rsn_ie) {
if (wpa_driver_bsd_set_rsn_wpa_ie(drv, params,
rsn_ie) < 0)
return -1;
}
else {
wpa_ie = get_vendor_ie(params->wpa_ie,
params->wpa_ie_len, WPA_IE_VENDOR_TYPE);
if (wpa_ie) {
if (wpa_driver_bsd_set_rsn_wpa_ie(drv, params,
wpa_ie) < 0)
return -1;
}
}
}
/*
* NB: interface must be marked UP for association