aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant
diff options
context:
space:
mode:
Diffstat (limited to 'wpa_supplicant')
-rw-r--r--wpa_supplicant/Android.mk24
-rw-r--r--wpa_supplicant/Makefile20
-rw-r--r--wpa_supplicant/ap.c12
-rw-r--r--wpa_supplicant/blacklist.h33
-rw-r--r--wpa_supplicant/bss.c18
-rw-r--r--wpa_supplicant/bss.h16
-rw-r--r--wpa_supplicant/bssid_ignore.c (renamed from wpa_supplicant/blacklist.c)112
-rw-r--r--wpa_supplicant/bssid_ignore.h33
-rw-r--r--wpa_supplicant/config.c116
-rw-r--r--wpa_supplicant/config.h68
-rw-r--r--wpa_supplicant/config_file.c121
-rw-r--r--wpa_supplicant/config_ssid.h12
-rw-r--r--wpa_supplicant/ctrl_iface.c191
-rw-r--r--wpa_supplicant/dbus/dbus_new_handlers.c22
-rw-r--r--wpa_supplicant/defconfig8
-rw-r--r--wpa_supplicant/doc/docbook/eapol_test.sgml4
-rw-r--r--wpa_supplicant/doc/docbook/wpa_background.sgml4
-rw-r--r--wpa_supplicant/doc/docbook/wpa_cli.sgml4
-rw-r--r--wpa_supplicant/doc/docbook/wpa_gui.sgml4
-rw-r--r--wpa_supplicant/doc/docbook/wpa_passphrase.sgml4
-rw-r--r--wpa_supplicant/doc/docbook/wpa_priv.sgml4
-rw-r--r--wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml4
-rw-r--r--wpa_supplicant/doc/docbook/wpa_supplicant.sgml4
-rw-r--r--wpa_supplicant/dpp_supplicant.c103
-rw-r--r--wpa_supplicant/driver_i.h4
-rw-r--r--wpa_supplicant/events.c117
-rw-r--r--wpa_supplicant/hs20_supplicant.c6
-rw-r--r--wpa_supplicant/interworking.c16
-rw-r--r--wpa_supplicant/mesh.c65
-rw-r--r--wpa_supplicant/nmake.mak2
-rw-r--r--wpa_supplicant/notify.c5
-rw-r--r--wpa_supplicant/op_classes.c25
-rw-r--r--wpa_supplicant/p2p_supplicant.c100
-rw-r--r--wpa_supplicant/pasn_supplicant.c1509
-rw-r--r--wpa_supplicant/robust_av.c7
-rw-r--r--wpa_supplicant/rrm.c6
-rw-r--r--wpa_supplicant/scan.c75
-rw-r--r--wpa_supplicant/scan.h4
-rw-r--r--wpa_supplicant/sme.c8
-rwxr-xr-xwpa_supplicant/vs2005/eapol_test/eapol_test.vcproj6
-rwxr-xr-xwpa_supplicant/vs2005/wpa_supplicant/wpa_supplicant.vcproj6
-rwxr-xr-xwpa_supplicant/vs2005/wpasvc/wpasvc.vcproj6
-rw-r--r--wpa_supplicant/wnm_sta.c2
-rw-r--r--wpa_supplicant/wpa_cli.c84
-rw-r--r--wpa_supplicant/wpa_supplicant.c133
-rw-r--r--wpa_supplicant/wpa_supplicant.conf26
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h92
-rw-r--r--wpa_supplicant/wpas_glue.c43
-rw-r--r--wpa_supplicant/wpas_module_tests.c90
-rw-r--r--wpa_supplicant/wps_supplicant.c17
50 files changed, 2825 insertions, 570 deletions
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index ed7e358..fd74c16 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -32,6 +32,10 @@ ifeq ($(BOARD_WPA_SUPPLICANT_PRIVATE_LIB),)
L_CFLAGS += -DANDROID_LIB_STUB
endif
+ifneq ($(BOARD_WPA_SUPPLICANT_PRIVATE_LIB_EVENT),)
+L_CFLAGS += -DANDROID_LIB_EVENT
+endif
+
# Disable roaming in wpa_supplicant
ifdef CONFIG_NO_ROAMING
L_CFLAGS += -DCONFIG_NO_ROAMING
@@ -90,6 +94,7 @@ OBJS += notify.c
OBJS += bss.c
OBJS += eap_register.c
OBJS += src/utils/common.c
+OBJS += src/utils/config.c
OBJS += src/utils/wpa_debug.c
OBJS += src/utils/wpabuf.c
OBJS += src/utils/bitfield.c
@@ -367,6 +372,17 @@ L_CFLAGS += -DCONFIG_WIFI_DISPLAY
OBJS += wifi_display.c
endif
+ifdef CONFIG_PASN
+L_CFLAGS += -DCONFIG_PASN
+L_CFLAGS += -DCONFIG_PTKSA_CACHE
+NEED_HMAC_SHA256_KDF=y
+NEED_HMAC_SHA384_KDF=y
+NEED_SHA256=y
+NEED_SHA384=y
+OBJS += src/common/ptksa_cache.c
+OBJS += pasn_supplicant.c
+endif
+
ifdef CONFIG_HS20
OBJS += hs20_supplicant.c
L_CFLAGS += -DCONFIG_HS20
@@ -1601,6 +1617,12 @@ L_CFLAGS += -DCONFIG_EXT_PASSWORD_TEST
NEED_EXT_PASSWORD=y
endif
+ifdef CONFIG_EXT_PASSWORD_FILE
+OBJS += src/utils/ext_password_file.c
+L_CFLAGS += -DCONFIG_EXT_PASSWORD_FILE
+NEED_EXT_PASSWORD=y
+endif
+
ifdef NEED_EXT_PASSWORD
OBJS += src/utils/ext_password.c
L_CFLAGS += -DCONFIG_EXT_PASSWORD
@@ -1631,7 +1653,7 @@ endif
OBJS += src/drivers/driver_common.c
-OBJS += wpa_supplicant.c events.c blacklist.c wpas_glue.c scan.c
+OBJS += wpa_supplicant.c events.c bssid_ignore.c wpas_glue.c scan.c
OBJS_t := $(OBJS) $(OBJS_l2) eapol_test.c
OBJS_t += src/radius/radius_client.c
OBJS_t += src/radius/radius.c
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index 9adadf1..bc3aa1d 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -83,6 +83,7 @@ OBJS += notify.o
OBJS += bss.o
OBJS += eap_register.o
OBJS += ../src/utils/common.o
+OBJS += ../src/utils/config.o
OBJS += ../src/utils/wpa_debug.o
OBJS += ../src/utils/wpabuf.o
OBJS += ../src/utils/bitfield.o
@@ -390,6 +391,17 @@ CFLAGS += -DCONFIG_WIFI_DISPLAY
OBJS += wifi_display.o
endif
+ifdef CONFIG_PASN
+CFLAGS += -DCONFIG_PASN
+CFLAGS += -DCONFIG_PTKSA_CACHE
+NEED_HMAC_SHA256_KDF=y
+NEED_HMAC_SHA384_KDF=y
+NEED_SHA256=y
+NEED_SHA384=y
+OBJS += ../src/common/ptksa_cache.o
+OBJS += pasn_supplicant.o
+endif
+
ifdef CONFIG_HS20
OBJS += hs20_supplicant.o
CFLAGS += -DCONFIG_HS20
@@ -1739,6 +1751,12 @@ CFLAGS += -DCONFIG_EXT_PASSWORD_TEST
NEED_EXT_PASSWORD=y
endif
+ifdef CONFIG_EXT_PASSWORD_FILE
+OBJS += ../src/utils/ext_password_file.o
+CFLAGS += -DCONFIG_EXT_PASSWORD_FILE
+NEED_EXT_PASSWORD=y
+endif
+
ifdef NEED_EXT_PASSWORD
OBJS += ../src/utils/ext_password.o
CFLAGS += -DCONFIG_EXT_PASSWORD
@@ -1781,7 +1799,7 @@ endif
OBJS += ../src/drivers/driver_common.o
OBJS_priv += ../src/drivers/driver_common.o
-OBJS += wpa_supplicant.o events.o blacklist.o wpas_glue.o scan.o
+OBJS += wpa_supplicant.o events.o bssid_ignore.o wpas_glue.o scan.o
OBJS_t := $(OBJS) $(OBJS_l2) eapol_test.o
OBJS_t += ../src/radius/radius_client.o
OBJS_t += ../src/radius/radius.o
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index ac88a7d..cfefa48 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -44,6 +44,7 @@ static void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
#endif /* CONFIG_WPS */
+#ifdef CONFIG_P2P
static bool is_chanwidth160_supported(struct hostapd_hw_modes *mode,
struct hostapd_config *conf)
{
@@ -63,6 +64,7 @@ static bool is_chanwidth160_supported(struct hostapd_hw_modes *mode,
return true;
return false;
}
+#endif /* CONFIG_P2P */
static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s,
@@ -264,6 +266,16 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s,
wpa_printf(MSG_DEBUG,
"HT secondary channel offset %d for P2P group",
conf->secondary_channel);
+ } else if (ssid->p2p_group && conf->secondary_channel &&
+ conf->hw_mode != HOSTAPD_MODE_IEEE80211A) {
+ /* This ended up trying to configure invalid
+ * 2.4 GHz channels (e.g., HT40+ on channel 11)
+ * in some cases, so clear the secondary channel
+ * configuration now to avoid such cases that
+ * would lead to group formation failures. */
+ wpa_printf(MSG_DEBUG,
+ "Disable HT secondary channel for P2P group on 2.4 GHz");
+ conf->secondary_channel = 0;
}
#endif /* CONFIG_P2P */
diff --git a/wpa_supplicant/blacklist.h b/wpa_supplicant/blacklist.h
deleted file mode 100644
index a1c60d5..0000000
--- a/wpa_supplicant/blacklist.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * wpa_supplicant - Temporary BSSID blacklist
- * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
- *
- * This software may be distributed under the terms of the BSD license.
- * See README for more details.
- */
-
-#ifndef BLACKLIST_H
-#define BLACKLIST_H
-
-struct wpa_blacklist {
- struct wpa_blacklist *next;
- u8 bssid[ETH_ALEN];
- int count;
- /* Time of most recent blacklist event. */
- struct os_reltime blacklist_start;
- /*
- * Number of seconds after blacklist_start that the entry will be
- * considered blacklisted.
- */
- int timeout_secs;
-};
-
-struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s,
- const u8 *bssid);
-int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid);
-int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid);
-int wpa_blacklist_is_blacklisted(struct wpa_supplicant *wpa_s, const u8 *bssid);
-void wpa_blacklist_clear(struct wpa_supplicant *wpa_s);
-void wpa_blacklist_update(struct wpa_supplicant *wpa_s);
-
-#endif /* BLACKLIST_H */
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index e9c2f82..e13783c 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -19,18 +19,6 @@
#include "scan.h"
#include "bss.h"
-
-#define WPA_BSS_FREQ_CHANGED_FLAG BIT(0)
-#define WPA_BSS_SIGNAL_CHANGED_FLAG BIT(1)
-#define WPA_BSS_PRIVACY_CHANGED_FLAG BIT(2)
-#define WPA_BSS_MODE_CHANGED_FLAG BIT(3)
-#define WPA_BSS_WPAIE_CHANGED_FLAG BIT(4)
-#define WPA_BSS_RSNIE_CHANGED_FLAG BIT(5)
-#define WPA_BSS_WPS_CHANGED_FLAG BIT(6)
-#define WPA_BSS_RATES_CHANGED_FLAG BIT(7)
-#define WPA_BSS_IES_CHANGED_FLAG BIT(8)
-
-
static void wpa_bss_set_hessid(struct wpa_bss *bss)
{
#ifdef CONFIG_INTERWORKING
@@ -588,8 +576,8 @@ static u32 wpa_bss_compare_res(const struct wpa_bss *old,
}
-static void notify_bss_changes(struct wpa_supplicant *wpa_s, u32 changes,
- const struct wpa_bss *bss)
+void notify_bss_changes(struct wpa_supplicant *wpa_s, u32 changes,
+ const struct wpa_bss *bss)
{
if (changes & WPA_BSS_FREQ_CHANGED_FLAG)
wpas_notify_bss_freq_changed(wpa_s, bss->id);
@@ -1390,6 +1378,8 @@ const u8 * wpa_bss_get_fils_cache_id(const struct wpa_bss *bss)
int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab)
{
+ if (!bss)
+ return 0;
return ieee802_11_ext_capab(wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB),
capab);
}
diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h
index 7cb1745..4078b9b 100644
--- a/wpa_supplicant/bss.h
+++ b/wpa_supplicant/bss.h
@@ -20,10 +20,20 @@ struct wpa_scan_res;
#define WPA_BSS_ANQP_FETCH_TRIED BIT(6)
#define WPA_BSS_OWE_TRANSITION BIT(7)
+#define WPA_BSS_FREQ_CHANGED_FLAG BIT(0)
+#define WPA_BSS_SIGNAL_CHANGED_FLAG BIT(1)
+#define WPA_BSS_PRIVACY_CHANGED_FLAG BIT(2)
+#define WPA_BSS_MODE_CHANGED_FLAG BIT(3)
+#define WPA_BSS_WPAIE_CHANGED_FLAG BIT(4)
+#define WPA_BSS_RSNIE_CHANGED_FLAG BIT(5)
+#define WPA_BSS_WPS_CHANGED_FLAG BIT(6)
+#define WPA_BSS_RATES_CHANGED_FLAG BIT(7)
+#define WPA_BSS_IES_CHANGED_FLAG BIT(8)
+
struct wpa_bss_anqp_elem {
struct dl_list list;
u16 infoid;
- bool protected; /* received in a protected GAS response */
+ bool protected_response; /* received in a protected GAS response */
struct wpabuf *payload;
};
@@ -120,6 +130,8 @@ static inline const u8 * wpa_bss_ie_ptr(const struct wpa_bss *bss)
return bss->ies;
}
+void notify_bss_changes(struct wpa_supplicant *wpa_s, u32 changes,
+ const struct wpa_bss *bss);
void wpa_bss_update_start(struct wpa_supplicant *wpa_s);
void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
struct wpa_scan_res *res,
@@ -177,7 +189,7 @@ static inline int bss_is_pbss(struct wpa_bss *bss)
static inline void wpa_bss_update_level(struct wpa_bss *bss, int new_level)
{
- if (bss != NULL && new_level < 0)
+ if (bss != NULL && new_level > -WPA_INVALID_NOISE && new_level < 0)
bss->level = new_level;
}
diff --git a/wpa_supplicant/blacklist.c b/wpa_supplicant/bssid_ignore.c
index 2f32644..e378577 100644
--- a/wpa_supplicant/blacklist.c
+++ b/wpa_supplicant/bssid_ignore.c
@@ -1,6 +1,6 @@
/*
- * wpa_supplicant - Temporary BSSID blacklist
- * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ * wpa_supplicant - List of temporarily ignored BSSIDs
+ * Copyright (c) 2003-2021, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -10,32 +10,32 @@
#include "common.h"
#include "wpa_supplicant_i.h"
-#include "blacklist.h"
+#include "bssid_ignore.h"
/**
- * wpa_blacklist_get - Get the blacklist entry for a BSSID
+ * wpa_bssid_ignore_get - Get the ignore list entry for a BSSID
* @wpa_s: Pointer to wpa_supplicant data
* @bssid: BSSID
- * Returns: Matching blacklist entry for the BSSID or %NULL if not found
+ * Returns: Matching entry for the BSSID or %NULL if not found
*/
-struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s,
- const u8 *bssid)
+struct wpa_bssid_ignore * wpa_bssid_ignore_get(struct wpa_supplicant *wpa_s,
+ const u8 *bssid)
{
- struct wpa_blacklist *e;
+ struct wpa_bssid_ignore *e;
if (wpa_s == NULL || bssid == NULL)
return NULL;
if (wpa_s->current_ssid &&
wpa_s->current_ssid->was_recently_reconfigured) {
- wpa_blacklist_clear(wpa_s);
+ wpa_bssid_ignore_clear(wpa_s);
wpa_s->current_ssid->was_recently_reconfigured = false;
return NULL;
}
- wpa_blacklist_update(wpa_s);
+ wpa_bssid_ignore_update(wpa_s);
- e = wpa_s->blacklist;
+ e = wpa_s->bssid_ignore;
while (e) {
if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0)
return e;
@@ -47,33 +47,33 @@ struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s,
/**
- * wpa_blacklist_add - Add an BSSID to the blacklist
+ * wpa_bssid_ignore_add - Add an BSSID to the ignore list
* @wpa_s: Pointer to wpa_supplicant data
- * @bssid: BSSID to be added to the blacklist
- * Returns: Current blacklist count on success, -1 on failure
+ * @bssid: BSSID to be added to the ignore list
+ * Returns: Current ignore list count on success, -1 on failure
*
- * This function adds the specified BSSID to the blacklist or increases the
- * blacklist count if the BSSID was already listed. It should be called when
+ * This function adds the specified BSSID to the ignore list or increases the
+ * ignore count if the BSSID was already listed. It should be called when
* an association attempt fails either due to the selected BSS rejecting
* association or due to timeout.
*
- * This blacklist is used to force %wpa_supplicant to go through all available
+ * This ignore list is used to force %wpa_supplicant to go through all available
* BSSes before retrying to associate with an BSS that rejected or timed out
* association. It does not prevent the listed BSS from being used; it only
* changes the order in which they are tried.
*/
-int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
+int wpa_bssid_ignore_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
{
- struct wpa_blacklist *e;
+ struct wpa_bssid_ignore *e;
struct os_reltime now;
if (wpa_s == NULL || bssid == NULL)
return -1;
- e = wpa_blacklist_get(wpa_s, bssid);
+ e = wpa_bssid_ignore_get(wpa_s, bssid);
os_get_reltime(&now);
if (e) {
- e->blacklist_start = now;
+ e->start = now;
e->count++;
if (e->count > 5)
e->timeout_secs = 1800;
@@ -86,7 +86,7 @@ int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
else
e->timeout_secs = 10;
wpa_printf(MSG_INFO, "BSSID " MACSTR
- " blacklist count incremented to %d, blacklisting for %d seconds",
+ " ignore list count incremented to %d, ignoring for %d seconds",
MAC2STR(bssid), e->count, e->timeout_secs);
return e->count;
}
@@ -97,11 +97,11 @@ int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
os_memcpy(e->bssid, bssid, ETH_ALEN);
e->count = 1;
e->timeout_secs = 10;
- e->blacklist_start = now;
- e->next = wpa_s->blacklist;
- wpa_s->blacklist = e;
+ e->start = now;
+ e->next = wpa_s->bssid_ignore;
+ wpa_s->bssid_ignore = e;
wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR
- " into blacklist, blacklisting for %d seconds",
+ " into ignore list, ignoring for %d seconds",
MAC2STR(bssid), e->timeout_secs);
return e->count;
@@ -109,28 +109,28 @@ int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid)
/**
- * wpa_blacklist_del - Remove an BSSID from the blacklist
+ * wpa_bssid_ignore_del - Remove an BSSID from the ignore list
* @wpa_s: Pointer to wpa_supplicant data
- * @bssid: BSSID to be removed from the blacklist
+ * @bssid: BSSID to be removed from the ignore list
* Returns: 0 on success, -1 on failure
*/
-int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid)
+int wpa_bssid_ignore_del(struct wpa_supplicant *wpa_s, const u8 *bssid)
{
- struct wpa_blacklist *e, *prev = NULL;
+ struct wpa_bssid_ignore *e, *prev = NULL;
if (wpa_s == NULL || bssid == NULL)
return -1;
- e = wpa_s->blacklist;
+ e = wpa_s->bssid_ignore;
while (e) {
if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) {
if (prev == NULL) {
- wpa_s->blacklist = e->next;
+ wpa_s->bssid_ignore = e->next;
} else {
prev->next = e->next;
}
- wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from "
- "blacklist", MAC2STR(bssid));
+ wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR
+ " from ignore list", MAC2STR(bssid));
os_free(e);
return 0;
}
@@ -142,75 +142,75 @@ int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid)
/**
- * wpa_blacklist_is_blacklisted - Check the blacklist status of a BSS
+ * wpa_bssid_ignore_is_listed - Check whether a BSSID is ignored temporarily
* @wpa_s: Pointer to wpa_supplicant data
* @bssid: BSSID to be checked
- * Returns: count if BSS is currently considered to be blacklisted, 0 otherwise
+ * Returns: count if BSS is currently considered to be ignored, 0 otherwise
*/
-int wpa_blacklist_is_blacklisted(struct wpa_supplicant *wpa_s, const u8 *bssid)
+int wpa_bssid_ignore_is_listed(struct wpa_supplicant *wpa_s, const u8 *bssid)
{
- struct wpa_blacklist *e;
+ struct wpa_bssid_ignore *e;
struct os_reltime now;
- e = wpa_blacklist_get(wpa_s, bssid);
+ e = wpa_bssid_ignore_get(wpa_s, bssid);
if (!e)
return 0;
os_get_reltime(&now);
- if (os_reltime_expired(&now, &e->blacklist_start, e->timeout_secs))
+ if (os_reltime_expired(&now, &e->start, e->timeout_secs))
return 0;
return e->count;
}
/**
- * wpa_blacklist_clear - Clear the blacklist of all entries
+ * wpa_bssid_ignore_clear - Clear the ignore list of all entries
* @wpa_s: Pointer to wpa_supplicant data
*/
-void wpa_blacklist_clear(struct wpa_supplicant *wpa_s)
+void wpa_bssid_ignore_clear(struct wpa_supplicant *wpa_s)
{
- struct wpa_blacklist *e, *prev;
+ struct wpa_bssid_ignore *e, *prev;
- e = wpa_s->blacklist;
- wpa_s->blacklist = NULL;
+ e = wpa_s->bssid_ignore;
+ wpa_s->bssid_ignore = NULL;
while (e) {
prev = e;
e = e->next;
- wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from "
- "blacklist (clear)", MAC2STR(prev->bssid));
+ wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR
+ " from ignore list (clear)", MAC2STR(prev->bssid));
os_free(prev);
}
}
/**
- * wpa_blacklist_update - Update the entries in the blacklist,
+ * wpa_bssid_ignore_update - Update the entries in the ignore list,
* deleting entries that have been expired for over an hour.
* @wpa_s: Pointer to wpa_supplicant data
*/
-void wpa_blacklist_update(struct wpa_supplicant *wpa_s)
+void wpa_bssid_ignore_update(struct wpa_supplicant *wpa_s)
{
- struct wpa_blacklist *e, *prev = NULL;
+ struct wpa_bssid_ignore *e, *prev = NULL;
struct os_reltime now;
if (!wpa_s)
return;
- e = wpa_s->blacklist;
+ e = wpa_s->bssid_ignore;
os_get_reltime(&now);
while (e) {
- if (os_reltime_expired(&now, &e->blacklist_start,
+ if (os_reltime_expired(&now, &e->start,
e->timeout_secs + 3600)) {
- struct wpa_blacklist *to_delete = e;
+ struct wpa_bssid_ignore *to_delete = e;
if (prev) {
prev->next = e->next;
e = prev->next;
} else {
- wpa_s->blacklist = e->next;
- e = wpa_s->blacklist;
+ wpa_s->bssid_ignore = e->next;
+ e = wpa_s->bssid_ignore;
}
wpa_printf(MSG_INFO, "Removed BSSID " MACSTR
- " from blacklist (expired)",
+ " from ignore list (expired)",
MAC2STR(to_delete->bssid));
os_free(to_delete);
} else {
diff --git a/wpa_supplicant/bssid_ignore.h b/wpa_supplicant/bssid_ignore.h
new file mode 100644
index 0000000..721b0e1
--- /dev/null
+++ b/wpa_supplicant/bssid_ignore.h
@@ -0,0 +1,33 @@
+/*
+ * wpa_supplicant - List of temporarily ignored BSSIDs
+ * Copyright (c) 2003-2021, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef BSSID_IGNORE_H
+#define BSSID_IGNORE_H
+
+struct wpa_bssid_ignore {
+ struct wpa_bssid_ignore *next;
+ u8 bssid[ETH_ALEN];
+ int count;
+ /* Time of the most recent trigger to ignore this BSSID. */
+ struct os_reltime start;
+ /*
+ * Number of seconds after start that the entey will be considered
+ * valid.
+ */
+ int timeout_secs;
+};
+
+struct wpa_bssid_ignore * wpa_bssid_ignore_get(struct wpa_supplicant *wpa_s,
+ const u8 *bssid);
+int wpa_bssid_ignore_add(struct wpa_supplicant *wpa_s, const u8 *bssid);
+int wpa_bssid_ignore_del(struct wpa_supplicant *wpa_s, const u8 *bssid);
+int wpa_bssid_ignore_is_listed(struct wpa_supplicant *wpa_s, const u8 *bssid);
+void wpa_bssid_ignore_clear(struct wpa_supplicant *wpa_s);
+void wpa_bssid_ignore_update(struct wpa_supplicant *wpa_s);
+
+#endif /* BSSID_IGNORE_H */
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index c516154..ce5c80d 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -442,47 +442,99 @@ static char * wpa_config_write_bssid_hint(const struct parse_data *data,
#endif /* NO_CONFIG_WRITE */
+static int wpa_config_parse_bssid_ignore(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ return wpa_config_parse_addr_list(data, line, value,
+ &ssid->bssid_ignore,
+ &ssid->num_bssid_ignore,
+ "bssid_ignore", 1, 1);
+}
+
+
+/* deprecated alias for bssid_ignore for backwards compatibility */
static int wpa_config_parse_bssid_blacklist(const struct parse_data *data,
struct wpa_ssid *ssid, int line,
const char *value)
{
return wpa_config_parse_addr_list(data, line, value,
- &ssid->bssid_blacklist,
- &ssid->num_bssid_blacklist,
- "bssid_blacklist", 1, 1);
+ &ssid->bssid_ignore,
+ &ssid->num_bssid_ignore,
+ "bssid_ignore", 1, 1);
}
#ifndef NO_CONFIG_WRITE
+
+static char * wpa_config_write_bssid_ignore(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ return wpa_config_write_addr_list(data, ssid->bssid_ignore,
+ ssid->num_bssid_ignore,
+ "bssid_ignore");
+}
+
+
+/* deprecated alias for bssid_ignore for backwards compatibility */
static char * wpa_config_write_bssid_blacklist(const struct parse_data *data,
struct wpa_ssid *ssid)
{
- return wpa_config_write_addr_list(data, ssid->bssid_blacklist,
- ssid->num_bssid_blacklist,
- "bssid_blacklist");
+ return wpa_config_write_addr_list(data, ssid->bssid_ignore,
+ ssid->num_bssid_ignore,
+ "bssid_ignore");
}
+
#endif /* NO_CONFIG_WRITE */
+static int wpa_config_parse_bssid_accept(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ return wpa_config_parse_addr_list(data, line, value,
+ &ssid->bssid_accept,
+ &ssid->num_bssid_accept,
+ "bssid_accept", 1, 1);
+}
+
+
+/* deprecated alias for bssid_accept for backwards compatibility */
static int wpa_config_parse_bssid_whitelist(const struct parse_data *data,
struct wpa_ssid *ssid, int line,
const char *value)
{
return wpa_config_parse_addr_list(data, line, value,
- &ssid->bssid_whitelist,
- &ssid->num_bssid_whitelist,
- "bssid_whitelist", 1, 1);
+ &ssid->bssid_accept,
+ &ssid->num_bssid_accept,
+ "bssid_accept", 1, 1);
}
#ifndef NO_CONFIG_WRITE
+
+static char * wpa_config_write_bssid_accept(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ return wpa_config_write_addr_list(data, ssid->bssid_accept,
+ ssid->num_bssid_accept,
+ "bssid_accept");
+}
+
+
+/* deprecated alias for bssid_accept for backwards compatibility */
static char * wpa_config_write_bssid_whitelist(const struct parse_data *data,
struct wpa_ssid *ssid)
{
- return wpa_config_write_addr_list(data, ssid->bssid_whitelist,
- ssid->num_bssid_whitelist,
- "bssid_whitelist");
+ return wpa_config_write_addr_list(data, ssid->bssid_accept,
+ ssid->num_bssid_accept,
+ "bssid_accept");
}
+
+#endif /* NO_CONFIG_WRITE */
+
+
+#ifndef NO_CONFIG_WRITE
#endif /* NO_CONFIG_WRITE */
@@ -2362,8 +2414,10 @@ static const struct parse_data ssid_fields[] = {
{ INT_RANGE(scan_ssid, 0, 1) },
{ FUNC(bssid) },
{ FUNC(bssid_hint) },
- { FUNC(bssid_blacklist) },
- { FUNC(bssid_whitelist) },
+ { FUNC(bssid_ignore) },
+ { FUNC(bssid_accept) },
+ { FUNC(bssid_blacklist) }, /* deprecated alias for bssid_ignore */
+ { FUNC(bssid_whitelist) }, /* deprecated alias for bssid_accept */
{ FUNC_KEY(psk) },
{ INT(mem_only_psk) },
{ STR_KEY(sae_password) },
@@ -2763,8 +2817,8 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid)
os_free(ssid->freq_list);
os_free(ssid->bgscan);
os_free(ssid->p2p_client_list);
- os_free(ssid->bssid_blacklist);
- os_free(ssid->bssid_whitelist);
+ os_free(ssid->bssid_ignore);
+ os_free(ssid->bssid_accept);
#ifdef CONFIG_HT_OVERRIDES
os_free(ssid->ht_mcs);
#endif /* CONFIG_HT_OVERRIDES */
@@ -2890,6 +2944,7 @@ void wpa_config_free(struct wpa_config *config)
os_free(config->p2p_no_go_freq.range);
os_free(config->autoscan);
os_free(config->freq_list);
+ os_free(config->initial_freq_list);
wpabuf_free(config->wps_nfc_dh_pubkey);
wpabuf_free(config->wps_nfc_dh_privkey);
wpabuf_free(config->wps_nfc_dev_pw);
@@ -4308,6 +4363,7 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface,
config->ap_isolate = DEFAULT_AP_ISOLATE;
config->access_network_type = DEFAULT_ACCESS_NETWORK_TYPE;
config->scan_cur_freq = DEFAULT_SCAN_CUR_FREQ;
+ config->scan_res_valid_for_connect = DEFAULT_SCAN_RES_VALID_FOR_CONNECT;
config->wmm_ac_params[0] = ac_be;
config->wmm_ac_params[1] = ac_bk;
config->wmm_ac_params[2] = ac_vi;
@@ -4547,6 +4603,26 @@ static int wpa_config_process_freq_list(const struct global_parse_data *data,
}
+static int
+wpa_config_process_initial_freq_list(const struct global_parse_data *data,
+ struct wpa_config *config, int line,
+ const char *value)
+{
+ int *freqs;
+
+ freqs = wpa_config_parse_int_array(value);
+ if (!freqs)
+ return -1;
+ if (freqs[0] == 0) {
+ os_free(freqs);
+ freqs = NULL;
+ }
+ os_free(config->initial_freq_list);
+ config->initial_freq_list = freqs;
+ return 0;
+}
+
+
#ifdef CONFIG_P2P
static int wpa_global_config_parse_ipv4(const struct global_parse_data *data,
struct wpa_config *config, int line,
@@ -5082,7 +5158,9 @@ static const struct global_parse_data global_fields[] = {
{ FUNC(ap_vendor_elements), 0 },
{ INT_RANGE(ignore_old_scan_res, 0, 1), 0 },
{ FUNC(freq_list), 0 },
+ { FUNC(initial_freq_list), 0},
{ INT(scan_cur_freq), 0 },
+ { INT(scan_res_valid_for_connect), 0},
{ INT(sched_scan_interval), 0 },
{ INT(sched_scan_start_delay), 0 },
{ INT(tdls_external_control), 0},
@@ -5126,6 +5204,12 @@ static const struct global_parse_data global_fields[] = {
{ INT_RANGE(disable_btm, 0, 1), CFG_CHANGED_DISABLE_BTM },
{ INT_RANGE(extended_key_id, 0, 1), 0 },
#endif /* CONFIG_WNM */
+ { INT_RANGE(wowlan_disconnect_on_deinit, 0, 1), 0},
+#ifdef CONFIG_PASN
+#ifdef CONFIG_TESTING_OPTIONS
+ { INT_RANGE(force_kdk_derivation, 0, 1), 0 },
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_PASN */
};
#undef FUNC
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index 648573d..aac4a9d 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -45,6 +45,7 @@
#define DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD -75
#define DEFAULT_OCE_SUPPORT OCE_STA
#define DEFAULT_EXTENDED_KEY_ID 0
+#define DEFAULT_SCAN_RES_VALID_FOR_CONNECT 5
#include "config_ssid.h"
#include "wps/wps.h"
@@ -917,6 +918,19 @@ struct wpa_config {
int *freq_list;
/**
+ * initial_freq_list - like freq_list but for initial scan
+ *
+ * This is an optional zero-terminated array of frequencies in
+ * megahertz (MHz) to allow for narrowing scanning range when
+ * the application is started.
+ *
+ * This can be used to speed up initial connection time if the
+ * channel is known ahead of time, without limiting the scanned
+ * frequencies during normal use.
+ */
+ int *initial_freq_list;
+
+ /**
* scan_cur_freq - Whether to scan only the current channel
*
* If true, attempt to scan only the current channel if any other
@@ -925,6 +939,15 @@ struct wpa_config {
int scan_cur_freq;
/**
+ * scan_res_valid_for_connect - Seconds scans are valid for association
+ *
+ * This configures the number of seconds old scan results are considered
+ * valid for association. When scan results are older than this value
+ * a new scan is triggered prior to the association.
+ */
+ int scan_res_valid_for_connect;
+
+ /**
* changed_parameters - Bitmap of changed parameters since last update
*/
unsigned int changed_parameters;
@@ -1541,9 +1564,31 @@ struct wpa_config {
/**
* p2p_device_random_mac_addr - P2P Device MAC address policy default
*
- * 0 = use permanent MAC address
+ * 0 = use permanent MAC address (the one set by default by the device
+ * driver). Notice that, if the device driver is configured to
+ * always use random MAC addresses, this flag breaks reinvoking a
+ * persistent group, so flags 1 or 2 should be used instead with
+ * such drivers if persistent groups are used.
* 1 = use random MAC address on creating the interface if there is no
- * persistent groups.
+ * persistent group. Besides, if a persistent group is created,
+ * p2p_device_persistent_mac_addr is set to the MAC address of the
+ * P2P Device interface, so that this address will be subsequently
+ * used to change the MAC address of the P2P Device interface. With
+ * no persistent group, the random MAC address is created by
+ * wpa_supplicant, changing the one set by the device driver.
+ * The device driver shall support SIOCGIFFLAGS/SIOCSIFFLAGS ioctl
+ * interface control operations.
+ * 2 = this flag should be used when the device driver uses random MAC
+ * addresses by default when a P2P Device interface is created.
+ * If p2p_device_persistent_mac_addr is set, use this MAC address
+ * on creating the P2P Device interface. If not set, use the
+ * default method adopted by the device driver (e.g., random MAC
+ * address). Besides, if a persistent group is created,
+ * p2p_device_persistent_mac_addr is set to the MAC address of the
+ * P2P Device interface, so that this address will be subsequently
+ * used in place of the default address set by the device driver.
+ * (This option does not need support of SIOCGIFFLAGS/SIOCSIFFLAGS
+ * ioctl interface control operations and uses NL80211_ATTR_MAC).
*
* By default, permanent MAC address is used.
*/
@@ -1586,6 +1631,25 @@ struct wpa_config {
* 1 = use Extended Key ID when possible
*/
int extended_key_id;
+
+ /**
+ * wowlan_disconnect_on_deinit - Trigger disconnect on wpa_supplicant
+ * interface deinit even if the driver has enabled WoWLAN.
+ *
+ * 0 = Do not disconnect
+ * 1 = Trigger disconnection
+ */
+ int wowlan_disconnect_on_deinit;
+
+#ifdef CONFIG_PASN
+#ifdef CONFIG_TESTING_OPTIONS
+ /*
+ * Normally, KDK should be derived if and only if both sides support
+ * secure LTF. Allow forcing KDK derivation for testing purposes.
+ */
+ int force_kdk_derivation;
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_PASN*/
};
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 246644a..a535e3f 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -23,105 +23,7 @@
#include "p2p/p2p.h"
#include "eap_peer/eap_methods.h"
#include "eap_peer/eap.h"
-
-
-static int newline_terminated(const char *buf, size_t buflen)
-{
- size_t len = os_strlen(buf);
- if (len == 0)
- return 0;
- if (len == buflen - 1 && buf[buflen - 1] != '\r' &&
- buf[len - 1] != '\n')
- return 0;
- return 1;
-}
-
-
-static void skip_line_end(FILE *stream)
-{
- char buf[100];
- while (fgets(buf, sizeof(buf), stream)) {
- buf[sizeof(buf) - 1] = '\0';
- if (newline_terminated(buf, sizeof(buf)))
- return;
- }
-}
-
-
-/**
- * wpa_config_get_line - Read the next configuration file line
- * @s: Buffer for the line
- * @size: The buffer length
- * @stream: File stream to read from
- * @line: Pointer to a variable storing the file line number
- * @_pos: Buffer for the pointer to the beginning of data on the text line or
- * %NULL if not needed (returned value used instead)
- * Returns: Pointer to the beginning of data on the text line or %NULL if no
- * more text lines are available.
- *
- * This function reads the next non-empty line from the configuration file and
- * removes comments. The returned string is guaranteed to be null-terminated.
- */
-static char * wpa_config_get_line(char *s, int size, FILE *stream, int *line,
- char **_pos)
-{
- char *pos, *end, *sstart;
-
- while (fgets(s, size, stream)) {
- (*line)++;
- s[size - 1] = '\0';
- if (!newline_terminated(s, size)) {
- /*
- * The line was truncated - skip rest of it to avoid
- * confusing error messages.
- */
- wpa_printf(MSG_INFO, "Long line in configuration file "
- "truncated");
- skip_line_end(stream);
- }
- pos = s;
-
- /* Skip white space from the beginning of line. */
- while (*pos == ' ' || *pos == '\t' || *pos == '\r')
- pos++;
-
- /* Skip comment lines and empty lines */
- if (*pos == '#' || *pos == '\n' || *pos == '\0')
- continue;
-
- /*
- * Remove # comments unless they are within a double quoted
- * string.
- */
- sstart = os_strchr(pos, '"');
- if (sstart)
- sstart = os_strrchr(sstart + 1, '"');
- if (!sstart)
- sstart = pos;
- end = os_strchr(sstart, '#');
- if (end)
- *end-- = '\0';
- else
- end = pos + os_strlen(pos) - 1;
-
- /* Remove trailing white space. */
- while (end > pos &&
- (*end == '\n' || *end == ' ' || *end == '\t' ||
- *end == '\r'))
- *end-- = '\0';
-
- if (*pos == '\0')
- continue;
-
- if (_pos)
- *_pos = pos;
- return pos;
- }
-
- if (_pos)
- *_pos = NULL;
- return NULL;
-}
+#include "utils/config.h"
static int wpa_config_validate_network(struct wpa_ssid *ssid, int line)
@@ -767,8 +669,8 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
INT(scan_ssid);
write_bssid(f, ssid);
write_bssid_hint(f, ssid);
- write_str(f, "bssid_blacklist", ssid);
- write_str(f, "bssid_whitelist", ssid);
+ write_str(f, "bssid_ignore", ssid);
+ write_str(f, "bssid_accept", ssid);
write_psk(f, ssid);
INT(mem_only_psk);
STR(sae_password);
@@ -1475,9 +1377,23 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
}
fprintf(f, "\n");
}
+ if (config->initial_freq_list && config->initial_freq_list[0]) {
+ int i;
+ fprintf(f, "initial_freq_list=");
+ for (i = 0; config->initial_freq_list[i]; i++) {
+ fprintf(f, "%s%d", i > 0 ? " " : "",
+ config->initial_freq_list[i]);
+ }
+ fprintf(f, "\n");
+ }
if (config->scan_cur_freq != DEFAULT_SCAN_CUR_FREQ)
fprintf(f, "scan_cur_freq=%d\n", config->scan_cur_freq);
+ if (config->scan_res_valid_for_connect !=
+ DEFAULT_SCAN_RES_VALID_FOR_CONNECT)
+ fprintf(f, "scan_res_valid_for_connect=%d\n",
+ config->scan_res_valid_for_connect);
+
if (config->sched_scan_interval)
fprintf(f, "sched_scan_interval=%u\n",
config->sched_scan_interval);
@@ -1611,6 +1527,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
if (config->extended_key_id != DEFAULT_EXTENDED_KEY_ID)
fprintf(f, "extended_key_id=%d\n",
config->extended_key_id);
+ if (config->wowlan_disconnect_on_deinit)
+ fprintf(f, "wowlan_disconnect_on_deinit=%d\n",
+ config->wowlan_disconnect_on_deinit);
}
#endif /* CONFIG_NO_CONFIG_WRITE */
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index b4fdc8a..3f7b314 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -153,16 +153,16 @@ struct wpa_ssid {
u8 bssid[ETH_ALEN];
/**
- * bssid_blacklist - List of inacceptable BSSIDs
+ * bssid_ignore - List of inacceptable BSSIDs
*/
- u8 *bssid_blacklist;
- size_t num_bssid_blacklist;
+ u8 *bssid_ignore;
+ size_t num_bssid_ignore;
/**
- * bssid_blacklist - List of acceptable BSSIDs
+ * bssid_accept - List of acceptable BSSIDs
*/
- u8 *bssid_whitelist;
- size_t num_bssid_whitelist;
+ u8 *bssid_accept;
+ size_t num_bssid_accept;
/**
* bssid_set - Whether BSSID is configured for this network
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 8306950..0d4c2bc 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -22,6 +22,7 @@
#ifdef CONFIG_DPP
#include "common/dpp.h"
#endif /* CONFIG_DPP */
+#include "common/ptksa_cache.h"
#include "crypto/tls.h"
#include "ap/hostapd.h"
#include "eap_peer/eap.h"
@@ -48,7 +49,7 @@
#include "scan.h"
#include "ctrl_iface.h"
#include "interworking.h"
-#include "blacklist.h"
+#include "bssid_ignore.h"
#include "autoscan.h"
#include "wnm_sta.h"
#include "offchannel.h"
@@ -299,20 +300,30 @@ static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd)
}
-static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *band)
+static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *bands)
{
union wpa_event_data event;
+ u32 setband_mask = WPA_SETBAND_AUTO;
- if (os_strcmp(band, "AUTO") == 0)
- wpa_s->setband = WPA_SETBAND_AUTO;
- else if (os_strcmp(band, "5G") == 0)
- wpa_s->setband = WPA_SETBAND_5G;
- else if (os_strcmp(band, "2G") == 0)
- wpa_s->setband = WPA_SETBAND_2G;
- else
- return -1;
+ /*
+ * For example:
+ * SET setband 2G,6G
+ * SET setband 5G
+ * SET setband AUTO
+ */
+ if (!os_strstr(bands, "AUTO")) {
+ if (os_strstr(bands, "5G"))
+ setband_mask |= WPA_SETBAND_5G;
+ if (os_strstr(bands, "6G"))
+ setband_mask |= WPA_SETBAND_6G;
+ if (os_strstr(bands, "2G"))
+ setband_mask |= WPA_SETBAND_2G;
+ if (setband_mask == WPA_SETBAND_AUTO)
+ return -1;
+ }
- if (wpa_drv_setband(wpa_s, wpa_s->setband) == 0) {
+ wpa_s->setband_mask = setband_mask;
+ if (wpa_drv_setband(wpa_s, wpa_s->setband_mask) == 0) {
os_memset(&event, 0, sizeof(event));
event.channel_list_changed.initiator = REGDOM_SET_BY_USER;
event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN;
@@ -2543,20 +2554,20 @@ static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
}
-static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
- char *cmd, char *buf,
- size_t buflen)
+static int wpa_supplicant_ctrl_iface_bssid_ignore(struct wpa_supplicant *wpa_s,
+ char *cmd, char *buf,
+ size_t buflen)
{
u8 bssid[ETH_ALEN];
- struct wpa_blacklist *e;
+ struct wpa_bssid_ignore *e;
char *pos, *end;
int ret;
- /* cmd: "BLACKLIST [<BSSID>]" */
+ /* cmd: "BSSID_IGNORE [<BSSID>]" */
if (*cmd == '\0') {
pos = buf;
end = buf + buflen;
- e = wpa_s->blacklist;
+ e = wpa_s->bssid_ignore;
while (e) {
ret = os_snprintf(pos, end - pos, MACSTR "\n",
MAC2STR(e->bssid));
@@ -2570,12 +2581,12 @@ static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
cmd++;
if (os_strncmp(cmd, "clear", 5) == 0) {
- wpa_blacklist_clear(wpa_s);
+ wpa_bssid_ignore_clear(wpa_s);
os_memcpy(buf, "OK\n", 3);
return 3;
}
- wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: BSSID_IGNORE bssid='%s'", cmd);
if (hwaddr_aton(cmd, bssid)) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
return -1;
@@ -2585,10 +2596,10 @@ static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
* Add the BSSID twice, so its count will be 2, causing it to be
* skipped when processing scan results.
*/
- ret = wpa_blacklist_add(wpa_s, bssid);
+ ret = wpa_bssid_ignore_add(wpa_s, bssid);
if (ret < 0)
return -1;
- ret = wpa_blacklist_add(wpa_s, bssid);
+ ret = wpa_bssid_ignore_add(wpa_s, bssid);
if (ret < 0)
return -1;
os_memcpy(buf, "OK\n", 3);
@@ -4488,6 +4499,15 @@ static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_FILS_SK_PFS */
#endif /* CONFIG_FILS */
+#ifdef CONFIG_PASN
+ ret = os_snprintf(pos, end - pos, "%sPASN",
+ pos == buf ? "" : " ");
+ if (os_snprintf_error(end - pos, ret))
+ return pos - buf;
+ pos += ret;
+
+#endif /* CONFIG_PASN */
+
return pos - buf;
}
@@ -4813,6 +4833,31 @@ static int wpa_supplicant_ctrl_iface_get_capability(
}
#endif /* CONFIG_SAE */
+#ifdef CONFIG_OCV
+ if (os_strcmp(field, "ocv") == 0) {
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
+ (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
+ res = os_snprintf(buf, buflen, "supported");
+ else
+ res = os_snprintf(buf, buflen, "not supported");
+ if (os_snprintf_error(buflen, res))
+ return -1;
+ return res;
+ }
+#endif /* CONFIG_OCV */
+
+ if (os_strcmp(field, "beacon_prot") == 0) {
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION) ||
+ (wpa_s->drv_flags2 &
+ WPA_DRIVER_FLAGS2_BEACON_PROTECTION_CLIENT))
+ res = os_snprintf(buf, buflen, "supported");
+ else
+ res = os_snprintf(buf, buflen, "not supported");
+ if (os_snprintf_error(buflen, res))
+ return -1;
+ return res;
+ }
+
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
field);
@@ -5285,7 +5330,7 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
os_snprintf(title, sizeof(title), "anqp[%u]",
elem->infoid);
pos = anqp_add_hex(pos, end, title, elem->payload);
- if (elem->protected) {
+ if (elem->protected_response) {
ret = os_snprintf(pos, end - pos,
"protected-anqp-info[%u]=1\n",
elem->infoid);
@@ -8414,13 +8459,14 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
wpa_s->consecutive_conn_failures = 0;
wpa_drv_radio_disable(wpa_s, 0);
- wpa_blacklist_clear(wpa_s);
+ wpa_bssid_ignore_clear(wpa_s);
wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all");
wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all");
wpa_config_flush_blobs(wpa_s->conf);
wpa_s->conf->auto_interworking = 0;
wpa_s->conf->okc = 0;
+ ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
rsn_preauth_deinit(wpa_s->wpa);
@@ -8521,6 +8567,13 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
free_bss_tmp_disallowed(wpa_s);
os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data));
+
+#ifdef CONFIG_PASN
+ wpas_pasn_auth_stop(wpa_s);
+#endif /* CONFIG_PASN */
+
+ if (wpa_s->mac_addr_changed && wpa_s->conf->mac_addr == 0)
+ wpas_restore_permanent_mac_addr(wpa_s);
}
@@ -9774,8 +9827,7 @@ static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
if (wpa_s->vendor_elem[frame] == NULL) {
wpa_s->vendor_elem[frame] = buf;
- wpas_vendor_elem_update(wpa_s);
- return 0;
+ goto update_ies;
}
if (wpabuf_resize(&wpa_s->vendor_elem[frame], len) < 0) {
@@ -9785,8 +9837,14 @@ static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
wpabuf_free(buf);
+
+update_ies:
wpas_vendor_elem_update(wpa_s);
+ if (frame == VENDOR_ELEM_PROBE_REQ ||
+ frame == VENDOR_ELEM_PROBE_REQ_P2P)
+ wpa_supplicant_set_default_scan_ies(wpa_s);
+
return 0;
}
@@ -10093,6 +10151,7 @@ static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s,
static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s)
{
+ ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
#ifdef CONFIG_AP
wpas_ap_pmksa_cache_flush(wpa_s);
@@ -10425,6 +10484,73 @@ static int wpas_ctrl_iface_configure_mscs(struct wpa_supplicant *wpa_s,
}
+#ifdef CONFIG_PASN
+static int wpas_ctrl_iface_pasn_start(struct wpa_supplicant *wpa_s, char *cmd)
+{
+ char *token, *context = NULL;
+ u8 bssid[ETH_ALEN];
+ int akmp = -1, cipher = -1, got_bssid = 0;
+ u16 group = 0xFFFF;
+ int id = 0;
+
+ /*
+ * Entry format: bssid=<BSSID> akmp=<AKMP> cipher=<CIPHER> group=<group>
+ */
+ while ((token = str_token(cmd, " ", &context))) {
+ if (os_strncmp(token, "bssid=", 6) == 0) {
+ if (hwaddr_aton(token + 6, bssid))
+ return -1;
+ got_bssid = 1;
+ } else if (os_strcmp(token, "akmp=PASN") == 0) {
+ akmp = WPA_KEY_MGMT_PASN;
+#ifdef CONFIG_IEEE80211R
+ } else if (os_strcmp(token, "akmp=FT-PSK") == 0) {
+ akmp = WPA_KEY_MGMT_FT_PSK;
+ } else if (os_strcmp(token, "akmp=FT-EAP-SHA384") == 0) {
+ akmp = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
+ } else if (os_strcmp(token, "akmp=FT-EAP") == 0) {
+ akmp = WPA_KEY_MGMT_FT_IEEE8021X;
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_SAE
+ } else if (os_strcmp(token, "akmp=SAE") == 0) {
+ akmp = WPA_KEY_MGMT_SAE;
+#endif /* CONFIG_SAE */
+#ifdef CONFIG_FILS
+ } else if (os_strcmp(token, "akmp=FILS-SHA256") == 0) {
+ akmp = WPA_KEY_MGMT_FILS_SHA256;
+ } else if (os_strcmp(token, "akmp=FILS-SHA384") == 0) {
+ akmp = WPA_KEY_MGMT_FILS_SHA384;
+#endif /* CONFIG_FILS */
+ } else if (os_strcmp(token, "cipher=CCMP-256") == 0) {
+ cipher = WPA_CIPHER_CCMP_256;
+ } else if (os_strcmp(token, "cipher=GCMP-256") == 0) {
+ cipher = WPA_CIPHER_GCMP_256;
+ } else if (os_strcmp(token, "cipher=CCMP") == 0) {
+ cipher = WPA_CIPHER_CCMP;
+ } else if (os_strcmp(token, "cipher=GCMP") == 0) {
+ cipher = WPA_CIPHER_GCMP;
+ } else if (os_strncmp(token, "group=", 6) == 0) {
+ group = atoi(token + 6);
+ } else if (os_strncmp(token, "nid=", 4) == 0) {
+ id = atoi(token + 4);
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "CTRL: PASN Invalid parameter: '%s'",
+ token);
+ return -1;
+ }
+ }
+
+ if (!got_bssid || akmp == -1 || cipher == -1 || group == 0xFFFF) {
+ wpa_printf(MSG_DEBUG,"CTRL: PASN missing parameter");
+ return -1;
+ }
+
+ return wpas_pasn_auth_start(wpa_s, bssid, akmp, cipher, group, id);
+}
+#endif /* CONFIG_PASN */
+
+
char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
char *buf, size_t *resp_len)
{
@@ -10883,8 +11009,12 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "BSSID ", 6) == 0) {
if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
reply_len = -1;
+ } else if (os_strncmp(buf, "BSSID_IGNORE", 12) == 0) {
+ reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
+ wpa_s, buf + 12, reply, reply_size);
} else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
- reply_len = wpa_supplicant_ctrl_iface_blacklist(
+ /* deprecated backwards compatibility alias for BSSID_IGNORE */
+ reply_len = wpa_supplicant_ctrl_iface_bssid_ignore(
wpa_s, buf + 9, reply, reply_size);
} else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
reply_len = wpa_supplicant_ctrl_iface_log_level(
@@ -11319,6 +11449,15 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "MSCS ", 5) == 0) {
if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5))
reply_len = -1;
+#ifdef CONFIG_PASN
+ } else if (os_strncmp(buf, "PASN_START ", 11) == 0) {
+ if (wpas_ctrl_iface_pasn_start(wpa_s, buf + 11) < 0)
+ reply_len = -1;
+ } else if (os_strcmp(buf, "PASN_STOP") == 0) {
+ wpas_pasn_auth_stop(wpa_s);
+ } else if (os_strcmp(buf, "PTKSA_CACHE_LIST") == 0) {
+ reply_len = ptksa_cache_list(wpa_s->ptksa, reply, reply_size);
+#endif /* CONFIG_PASN */
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index fa9a1a3..7d20f21 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -138,7 +138,9 @@ DBusMessage * wpas_dbus_error_no_memory(DBusMessage *message)
static const char * const dont_quote[] = {
"key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap",
"bssid", "scan_freq", "freq_list", "scan_ssid", "bssid_hint",
- "bssid_blacklist", "bssid_whitelist", "group_mgmt",
+ "bssid_ignore", "bssid_accept", /* deprecated aliases */
+ "bssid_blacklist", "bssid_whitelist",
+ "group_mgmt",
"ignore_broadcast_ssid",
#ifdef CONFIG_MESH
"mesh_basic_rates",
@@ -1011,7 +1013,7 @@ dbus_bool_t wpas_dbus_getter_global_capabilities(
const struct wpa_dbus_property_desc *property_desc,
DBusMessageIter *iter, DBusError *error, void *user_data)
{
- const char *capabilities[12];
+ const char *capabilities[13];
size_t num_items = 0;
struct wpa_global *global = user_data;
struct wpa_supplicant *wpa_s;
@@ -1062,6 +1064,9 @@ dbus_bool_t wpas_dbus_getter_global_capabilities(
#ifdef CONFIG_OWE
capabilities[num_items++] = "owe";
#endif /* CONFIG_OWE */
+#ifdef CONFIG_SUITEB192
+ capabilities[num_items++] = "suiteb192";
+#endif /* CONFIG_SUITEB192 */
if (ext_key_id_supported)
capabilities[num_items++] = "extended_key_id";
@@ -1697,7 +1702,8 @@ DBusMessage * wpas_dbus_handler_reassociate(DBusMessage *message,
* Returns: NULL
*
* Handler function for notifying system there will be a expected disconnect.
- * This will prevent wpa_supplicant from adding blacklists upon next disconnect..
+ * This will prevent wpa_supplicant from adding the BSSID to the ignore list
+ * upon next disconnect.
*/
DBusMessage * wpas_dbus_handler_expect_disconnect(DBusMessage *message,
struct wpa_global *global)
@@ -2869,6 +2875,12 @@ dbus_bool_t wpas_dbus_getter_capabilities(
goto nomem;
#endif /* CONFIG_SAE */
+#ifdef CONFIG_OWE
+ if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) &&
+ !wpa_dbus_dict_string_array_add_element(&iter_array, "owe"))
+ goto nomem;
+#endif /* CONFIG_OWE */
+
if (!wpa_dbus_dict_end_string_array(&iter_dict,
&iter_dict_entry,
&iter_dict_val,
@@ -5073,8 +5085,8 @@ dbus_bool_t wpas_dbus_getter_bss_ies(
return FALSE;
return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_BYTE,
- res + 1, res->ie_len,
- error);
+ wpa_bss_ie_ptr(res),
+ res->ie_len, error);
}
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index a0fe94e..708a823 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -530,6 +530,8 @@ CONFIG_WIFI_DISPLAY=y
#
# External password backend for testing purposes (developer use)
#CONFIG_EXT_PASSWORD_TEST=y
+# File-based backend to read passwords from an external file.
+#CONFIG_EXT_PASSWORD_FILE=y
# Enable Fast Session Transfer (FST)
#CONFIG_FST=y
@@ -620,3 +622,9 @@ CONFIG_DPP=y
# support for this by default, but that functionality is subject to be removed
# in the future.
#CONFIG_NO_TKIP=y
+
+# Pre-Association Security Negotiation (PASN)
+# Experimental implementation based on IEEE P802.11z/D2.6 and the protocol
+# design is still subject to change. As such, this should not yet be enabled in
+# production use.
+#CONFIG_PASN=y
diff --git a/wpa_supplicant/doc/docbook/eapol_test.sgml b/wpa_supplicant/doc/docbook/eapol_test.sgml
index e7705ab..4cfa3c1 100644
--- a/wpa_supplicant/doc/docbook/eapol_test.sgml
+++ b/wpa_supplicant/doc/docbook/eapol_test.sgml
@@ -1,6 +1,10 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<refentry>
+ <refentryinfo>
+ <date>07 August 2019</date>
+ </refentryinfo>
+
<refmeta>
<refentrytitle>eapol_test</refentrytitle>
<manvolnum>8</manvolnum>
diff --git a/wpa_supplicant/doc/docbook/wpa_background.sgml b/wpa_supplicant/doc/docbook/wpa_background.sgml
index f6a0ca8..22241cc 100644
--- a/wpa_supplicant/doc/docbook/wpa_background.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_background.sgml
@@ -1,6 +1,10 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<refentry>
+ <refentryinfo>
+ <date>07 August 2019</date>
+ </refentryinfo>
+
<refmeta>
<refentrytitle>wpa_background</refentrytitle>
<manvolnum>8</manvolnum>
diff --git a/wpa_supplicant/doc/docbook/wpa_cli.sgml b/wpa_supplicant/doc/docbook/wpa_cli.sgml
index dc7fee4..2ba1fe4 100644
--- a/wpa_supplicant/doc/docbook/wpa_cli.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_cli.sgml
@@ -1,6 +1,10 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<refentry>
+ <refentryinfo>
+ <date>07 August 2019</date>
+ </refentryinfo>
+
<refmeta>
<refentrytitle>wpa_cli</refentrytitle>
<manvolnum>8</manvolnum>
diff --git a/wpa_supplicant/doc/docbook/wpa_gui.sgml b/wpa_supplicant/doc/docbook/wpa_gui.sgml
index 31214e3..cb0c735 100644
--- a/wpa_supplicant/doc/docbook/wpa_gui.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_gui.sgml
@@ -1,6 +1,10 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<refentry>
+ <refentryinfo>
+ <date>07 August 2019</date>
+ </refentryinfo>
+
<refmeta>
<refentrytitle>wpa_gui</refentrytitle>
<manvolnum>8</manvolnum>
diff --git a/wpa_supplicant/doc/docbook/wpa_passphrase.sgml b/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
index ed9baf1..0772969 100644
--- a/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
@@ -1,6 +1,10 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<refentry>
+ <refentryinfo>
+ <date>07 August 2019</date>
+ </refentryinfo>
+
<refmeta>
<refentrytitle>wpa_passphrase</refentrytitle>
<manvolnum>8</manvolnum>
diff --git a/wpa_supplicant/doc/docbook/wpa_priv.sgml b/wpa_supplicant/doc/docbook/wpa_priv.sgml
index dd44565..0d5c94a 100644
--- a/wpa_supplicant/doc/docbook/wpa_priv.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_priv.sgml
@@ -1,6 +1,10 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<refentry>
+ <refentryinfo>
+ <date>07 August 2019</date>
+ </refentryinfo>
+
<refmeta>
<refentrytitle>wpa_priv</refentrytitle>
<manvolnum>8</manvolnum>
diff --git a/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml b/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml
index 462039d..8a0314e 100644
--- a/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_supplicant.conf.sgml
@@ -1,5 +1,9 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<refentry>
+ <refentryinfo>
+ <date>07 August 2019</date>
+ </refentryinfo>
+
<refmeta>
<refentrytitle>wpa_supplicant.conf</refentrytitle>
<manvolnum>5</manvolnum>
diff --git a/wpa_supplicant/doc/docbook/wpa_supplicant.sgml b/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
index aaff150..144654a 100644
--- a/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
@@ -1,6 +1,10 @@
<!doctype refentry PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
<refentry>
+ <refentryinfo>
+ <date>07 August 2019</date>
+ </refentryinfo>
+
<refmeta>
<refentrytitle>wpa_supplicant</refentrytitle>
<manvolnum>8</manvolnum>
diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
index 7451488..2bcf10b 100644
--- a/wpa_supplicant/dpp_supplicant.c
+++ b/wpa_supplicant/dpp_supplicant.c
@@ -32,6 +32,7 @@
static int wpas_dpp_listen_start(struct wpa_supplicant *wpa_s,
unsigned int freq);
static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx);
+static void wpas_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx);
static void wpas_dpp_auth_success(struct wpa_supplicant *wpa_s, int initiator);
static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
unsigned int freq, const u8 *dst,
@@ -473,6 +474,8 @@ static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
"DPP: Terminate authentication exchange due to a request to do so on TX status");
eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
+ eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
+ NULL);
eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
NULL);
#ifdef CONFIG_DPP2
@@ -505,6 +508,17 @@ static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s,
}
}
+ if (auth->waiting_auth_conf &&
+ auth->auth_resp_status == DPP_STATUS_OK) {
+ /* Make sure we do not get stuck waiting for Auth Confirm
+ * indefinitely after successfully transmitted Auth Response to
+ * allow new authentication exchanges to be started. */
+ eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
+ NULL);
+ eloop_register_timeout(1, 0, wpas_dpp_auth_conf_wait_timeout,
+ wpa_s, NULL);
+ }
+
if (!is_broadcast_ether_addr(dst) && auth->waiting_auth_resp &&
result == OFFCHANNEL_SEND_ACTION_SUCCESS) {
/* Allow timeout handling to stop iteration if no response is
@@ -593,6 +607,23 @@ static void wpas_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx)
}
+static void wpas_dpp_auth_conf_wait_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+ struct dpp_authentication *auth = wpa_s->dpp_auth;
+
+ if (!auth || !auth->waiting_auth_conf)
+ return;
+
+ wpa_printf(MSG_DEBUG,
+ "DPP: Terminate authentication exchange due to Auth Confirm timeout");
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL "No Auth Confirm received");
+ offchannel_send_action_done(wpa_s);
+ dpp_auth_deinit(auth);
+ wpa_s->dpp_auth = NULL;
+}
+
+
static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s,
struct dpp_authentication *auth)
{
@@ -678,7 +709,9 @@ static int wpas_dpp_auth_init_next(struct wpa_supplicant *wpa_s)
freq = auth->freq[auth->freq_idx++];
auth->curr_freq = freq;
- if (is_zero_ether_addr(auth->peer_bi->mac_addr))
+ if (!is_zero_ether_addr(auth->peer_mac_addr))
+ dst = auth->peer_mac_addr;
+ else if (is_zero_ether_addr(auth->peer_bi->mac_addr))
dst = broadcast;
else
dst = auth->peer_bi->mac_addr;
@@ -809,6 +842,8 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
if (!tcp && wpa_s->dpp_auth) {
eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
+ eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s,
+ NULL);
eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s,
NULL);
#ifdef CONFIG_DPP2
@@ -1408,6 +1443,8 @@ static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
struct dpp_config_obj *conf)
{
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED);
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_AKM "%s",
+ dpp_akm_str(conf->akm));
if (conf->ssid_len)
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_SSID "%s",
wpa_ssid_txt(conf->ssid, conf->ssid_len));
@@ -1423,6 +1460,21 @@ static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s,
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONNECTOR "%s",
conf->connector);
}
+ if (conf->passphrase[0]) {
+ char hex[64 * 2 + 1];
+
+ wpa_snprintf_hex(hex, sizeof(hex),
+ (const u8 *) conf->passphrase,
+ os_strlen(conf->passphrase));
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PASS "%s",
+ hex);
+ } else if (conf->psk_set) {
+ char hex[PMK_LEN * 2 + 1];
+
+ wpa_snprintf_hex(hex, sizeof(hex), conf->psk, PMK_LEN);
+ wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONFOBJ_PSK "%s",
+ hex);
+ }
if (conf->c_sign_key) {
char *hex;
size_t hexlen;
@@ -1808,6 +1860,8 @@ static void wpas_dpp_rx_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src,
return;
}
+ eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
+
if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
return;
@@ -1864,9 +1918,22 @@ static void wpas_dpp_rx_conf_result(struct wpa_supplicant *wpa_s, const u8 *src,
MAC2STR(src));
if (!auth || !auth->waiting_conf_result) {
- wpa_printf(MSG_DEBUG,
- "DPP: No DPP Configuration waiting for result - drop");
- return;
+ if (auth &&
+ os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) == 0 &&
+ gas_server_response_sent(wpa_s->gas_server,
+ auth->gas_server_ctx)) {
+ /* This could happen if the TX status event gets delayed
+ * long enough for the Enrollee to have time to send
+ * the next frame before the TX status gets processed
+ * locally. */
+ wpa_printf(MSG_DEBUG,
+ "DPP: GAS response was sent but TX status not yet received - assume it was ACKed since the Enrollee sent the next frame in the sequence");
+ auth->waiting_conf_result = 1;
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "DPP: No DPP Configuration waiting for result - drop");
+ return;
+ }
}
if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) {
@@ -2021,8 +2088,9 @@ wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src,
auth->neg_freq = freq;
- if (!is_zero_ether_addr(peer_bi->mac_addr))
- os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN);
+ /* The source address of the Presence Announcement frame overrides any
+ * MAC address information from the bootstrapping information. */
+ os_memcpy(auth->peer_mac_addr, src, ETH_ALEN);
wpa_s->dpp_auth = auth;
if (wpas_dpp_auth_init_next(wpa_s) < 0) {
@@ -2914,6 +2982,7 @@ wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa,
if (!resp)
wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED);
auth->conf_resp = resp;
+ auth->gas_server_ctx = resp_ctx;
return resp;
}
@@ -2947,10 +3016,12 @@ wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok)
wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)",
ok);
eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
+ eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
#ifdef CONFIG_DPP2
if (ok && auth->peer_version >= 2 &&
- auth->conf_resp_status == DPP_STATUS_OK) {
+ auth->conf_resp_status == DPP_STATUS_OK &&
+ !auth->waiting_conf_result) {
wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
auth->waiting_conf_result = 1;
auth->conf_resp = NULL;
@@ -3324,6 +3395,7 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s)
return;
eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL);
eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL);
+ eloop_cancel_timeout(wpas_dpp_auth_conf_wait_timeout, wpa_s, NULL);
eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL);
eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL);
#ifdef CONFIG_DPP2
@@ -3493,7 +3565,7 @@ static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
/* Preferred chirping channels */
mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
- HOSTAPD_MODE_IEEE80211G, 0);
+ HOSTAPD_MODE_IEEE80211G, false);
chan6 = mode == NULL;
if (mode) {
for (c = 0; c < mode->num_channels; c++) {
@@ -3510,7 +3582,7 @@ static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
int_array_add_unique(&wpa_s->dpp_chirp_freqs, 2437);
mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
- HOSTAPD_MODE_IEEE80211A, 0);
+ HOSTAPD_MODE_IEEE80211A, false);
if (mode) {
int chan44 = 0, chan149 = 0;
@@ -3532,7 +3604,7 @@ static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s,
}
mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
- HOSTAPD_MODE_IEEE80211AD, 0);
+ HOSTAPD_MODE_IEEE80211AD, false);
if (mode) {
for (c = 0; c < mode->num_channels; c++) {
struct hostapd_channel_data *chan = &mode->channels[c];
@@ -3571,6 +3643,17 @@ static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx)
if (wpa_s->dpp_chirp_freq == 0) {
if (wpa_s->dpp_chirp_round % 4 == 0 &&
!wpa_s->dpp_chirp_scan_done) {
+ if (wpas_scan_scheduled(wpa_s)) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: Deferring chirp scan because another scan is planned already");
+ if (eloop_register_timeout(1, 0,
+ wpas_dpp_chirp_next,
+ wpa_s, NULL) < 0) {
+ wpas_dpp_chirp_stop(wpa_s);
+ return;
+ }
+ return;
+ }
wpa_printf(MSG_DEBUG,
"DPP: Update channel list for chirping");
wpa_s->scan_req = MANUAL_SCAN_REQ;
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 3a28289..237f4e0 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -954,11 +954,11 @@ static inline int wpa_drv_disable_transmit_sa(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_MACSEC */
static inline int wpa_drv_setband(struct wpa_supplicant *wpa_s,
- enum set_band band)
+ u32 band_mask)
{
if (!wpa_s->driver->set_band)
return -1;
- return wpa_s->driver->set_band(wpa_s->drv_priv, band);
+ return wpa_s->driver->set_band(wpa_s->drv_priv, band_mask);
}
static inline int wpa_drv_get_pref_freq_list(struct wpa_supplicant *wpa_s,
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 89e6e73..9abb197 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -30,8 +30,9 @@
#include "common/ieee802_11_common.h"
#include "common/gas_server.h"
#include "common/dpp.h"
+#include "common/ptksa_cache.h"
#include "crypto/random.h"
-#include "blacklist.h"
+#include "bssid_ignore.h"
#include "wpas_glue.h"
#include "wps_supplicant.h"
#include "ibss_rsn.h"
@@ -1085,7 +1086,7 @@ static int disabled_freq(struct wpa_supplicant *wpa_s, int freq)
static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
const u8 *match_ssid, size_t match_ssid_len,
- struct wpa_bss *bss, int blacklist_count,
+ struct wpa_bss *bss, int bssid_ignore_count,
bool debug_print);
@@ -1117,7 +1118,7 @@ static bool sae_pk_acceptable_bss_with_pk(struct wpa_supplicant *wpa_s,
if (bss->est_throughput < 2000)
return false;
- count = wpa_blacklist_is_blacklisted(wpa_s, bss->bssid);
+ count = wpa_bssid_ignore_is_listed(wpa_s, bss->bssid);
if (wpa_scan_res_ok(wpa_s, ssid, match_ssid, match_ssid_len,
bss, count, 0))
return true;
@@ -1130,7 +1131,7 @@ static bool sae_pk_acceptable_bss_with_pk(struct wpa_supplicant *wpa_s,
static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
const u8 *match_ssid, size_t match_ssid_len,
- struct wpa_bss *bss, int blacklist_count,
+ struct wpa_bss *bss, int bssid_ignore_count,
bool debug_print)
{
int res;
@@ -1178,10 +1179,10 @@ static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
}
#ifdef CONFIG_WPS
- if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && blacklist_count) {
+ if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && bssid_ignore_count) {
if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - blacklisted (WPS)");
+ " skip - BSSID ignored (WPS)");
return false;
}
@@ -1216,23 +1217,23 @@ static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid,
return false;
}
- /* check blacklist */
- if (ssid->num_bssid_blacklist &&
- addr_in_list(bss->bssid, ssid->bssid_blacklist,
- ssid->num_bssid_blacklist)) {
+ /* check the list of BSSIDs to ignore */
+ if (ssid->num_bssid_ignore &&
+ addr_in_list(bss->bssid, ssid->bssid_ignore,
+ ssid->num_bssid_ignore)) {
if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - BSSID blacklisted");
+ " skip - BSSID configured to be ignored");
return false;
}
- /* if there is a whitelist, only accept those APs */
- if (ssid->num_bssid_whitelist &&
- !addr_in_list(bss->bssid, ssid->bssid_whitelist,
- ssid->num_bssid_whitelist)) {
+ /* if there is a list of accepted BSSIDs, only accept those APs */
+ if (ssid->num_bssid_accept &&
+ !addr_in_list(bss->bssid, ssid->bssid_accept,
+ ssid->num_bssid_accept)) {
if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - BSSID not in whitelist");
+ " skip - BSSID not in list of accepted values");
return false;
}
@@ -1477,7 +1478,7 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
int osen;
const u8 *match_ssid;
size_t match_ssid_len;
- int blacklist_count;
+ int bssid_ignore_count;
ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
wpa_ie_len = ie ? ie[1] : 0;
@@ -1503,13 +1504,13 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
osen ? " osen=1" : "");
}
- blacklist_count = wpa_blacklist_is_blacklisted(wpa_s, bss->bssid);
- if (blacklist_count) {
+ bssid_ignore_count = wpa_bssid_ignore_is_listed(wpa_s, bss->bssid);
+ if (bssid_ignore_count) {
int limit = 1;
if (wpa_supplicant_enabled_networks(wpa_s) == 1) {
/*
* When only a single network is enabled, we can
- * trigger blacklisting on the first failure. This
+ * trigger BSSID ignoring on the first failure. This
* should not be done with multiple enabled networks to
* avoid getting forced to move into a worse ESS on
* single error if there are no other BSSes of the
@@ -1517,11 +1518,11 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
*/
limit = 0;
}
- if (blacklist_count > limit) {
+ if (bssid_ignore_count > limit) {
if (debug_print) {
wpa_dbg(wpa_s, MSG_DEBUG,
- " skip - blacklisted (count=%d limit=%d)",
- blacklist_count, limit);
+ " skip - BSSID ignored (count=%d limit=%d)",
+ bssid_ignore_count, limit);
}
return NULL;
}
@@ -1557,7 +1558,7 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s,
for (ssid = group; ssid; ssid = only_first_ssid ? NULL : ssid->pnext) {
if (wpa_scan_res_ok(wpa_s, ssid, match_ssid, match_ssid_len,
- bss, blacklist_count, debug_print))
+ bss, bssid_ignore_count, debug_print))
return ssid;
}
@@ -1659,12 +1660,12 @@ struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s,
break;
}
- if (selected == NULL && wpa_s->blacklist &&
+ if (selected == NULL && wpa_s->bssid_ignore &&
!wpa_s->countermeasures) {
- wpa_dbg(wpa_s, MSG_DEBUG, "No APs found - clear "
- "blacklist and try again");
- wpa_blacklist_clear(wpa_s);
- wpa_s->blacklist_cleared++;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "No APs found - clear BSSID ignore list and try again");
+ wpa_bssid_ignore_clear(wpa_s);
+ wpa_s->bssid_ignore_cleared = true;
} else if (selected == NULL)
break;
}
@@ -2091,9 +2092,18 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
return -1;
if (data && data->scan_info.external_scan)
return -1;
- wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results - try "
- "scanning again");
- wpa_supplicant_req_new_scan(wpa_s, 1, 0);
+ if (wpa_s->scan_res_fail_handler) {
+ void (*handler)(struct wpa_supplicant *wpa_s);
+
+ handler = wpa_s->scan_res_fail_handler;
+ wpa_s->scan_res_fail_handler = NULL;
+ handler(wpa_s);
+ } else {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Failed to get scan results - try scanning again");
+ wpa_supplicant_req_new_scan(wpa_s, 1, 0);
+ }
+
ret = -1;
goto scan_work_done;
}
@@ -2439,7 +2449,7 @@ int wpa_supplicant_fast_associate(struct wpa_supplicant *wpa_s)
os_get_reltime(&now);
if (os_reltime_expired(&now, &wpa_s->last_scan,
- SCAN_RES_VALID_FOR_CONNECT)) {
+ wpa_s->conf->scan_res_valid_for_connect)) {
wpa_printf(MSG_DEBUG, "Fast associate: Old scan results");
return -1;
}
@@ -3473,6 +3483,8 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s,
if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
wpas_connection_failed(wpa_s, bssid);
wpa_sm_notify_disassoc(wpa_s->wpa);
+ ptksa_cache_flush(wpa_s->ptksa, wpa_s->bssid, WPA_CIPHER_NONE);
+
if (locally_generated)
wpa_s->disconnect_reason = -reason_code;
else
@@ -3566,7 +3578,7 @@ wpa_supplicant_event_michael_mic_failure(struct wpa_supplicant *wpa_s,
/* initialize countermeasures */
wpa_s->countermeasures = 1;
- wpa_blacklist_add(wpa_s, wpa_s->bssid);
+ wpa_bssid_ignore_add(wpa_s, wpa_s->bssid);
wpa_msg(wpa_s, MSG_WARNING, "TKIP countermeasures started");
@@ -4715,6 +4727,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
break;
}
#endif /* CONFIG_TESTING_OPTIONS */
+ if (wpa_s->disconnected) {
+ wpa_printf(MSG_INFO,
+ "Ignore unexpected EVENT_ASSOC in disconnected state");
+ break;
+ }
wpa_supplicant_event_assoc(wpa_s, data);
wpa_s->assoc_status_code = WLAN_STATUS_SUCCESS;
if (data &&
@@ -4775,7 +4792,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
}
} else {
wpa_dbg(wpa_s, MSG_DEBUG, "External program started a scan");
- wpa_s->radio->external_scan_running = 1;
+ wpa_s->radio->external_scan_req_interface = wpa_s;
wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED);
}
break;
@@ -4783,7 +4800,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) {
wpa_s->scan_res_handler = NULL;
wpa_s->own_scan_running = 0;
- wpa_s->radio->external_scan_running = 0;
+ wpa_s->radio->external_scan_req_interface = NULL;
wpa_s->last_scan_req = NORMAL_SCAN_REQ;
break;
}
@@ -4803,7 +4820,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
if (!(data && data->scan_info.external_scan))
wpa_s->own_scan_running = 0;
if (data && data->scan_info.nl_scan_event)
- wpa_s->radio->external_scan_running = 0;
+ wpa_s->radio->external_scan_req_interface = NULL;
radio_work_check_next(wpa_s);
break;
#endif /* CONFIG_NO_SCAN_PROCESSING */
@@ -4866,6 +4883,14 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
" type=%d stype=%d",
MAC2STR(data->tx_status.dst),
data->tx_status.type, data->tx_status.stype);
+#ifdef CONFIG_PASN
+ if (data->tx_status.type == WLAN_FC_TYPE_MGMT &&
+ data->tx_status.stype == WLAN_FC_STYPE_AUTH &&
+ wpas_pasn_auth_tx_status(wpa_s, data->tx_status.data,
+ data->tx_status.data_len,
+ data->tx_status.ack) == 0)
+ break;
+#endif /* CONFIG_PASN */
#ifdef CONFIG_AP
if (wpa_s->ap_iface == NULL) {
#ifdef CONFIG_OFFCHANNEL
@@ -4961,6 +4986,12 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpa_s->assoc_freq = data->ch_switch.freq;
wpa_s->current_ssid->frequency = data->ch_switch.freq;
+ if (wpa_s->current_bss &&
+ wpa_s->current_bss->freq != data->ch_switch.freq) {
+ wpa_s->current_bss->freq = data->ch_switch.freq;
+ notify_bss_changes(wpa_s, WPA_BSS_FREQ_CHANGED_FLAG,
+ wpa_s->current_bss);
+ }
#ifdef CONFIG_SME
switch (data->ch_switch.ch_offset) {
@@ -5094,6 +5125,12 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
mesh_mpm_mgmt_rx(wpa_s, &data->rx_mgmt);
break;
}
+#ifdef CONFIG_PASN
+ if (stype == WLAN_FC_STYPE_AUTH &&
+ wpas_pasn_auth_rx(wpa_s, mgmt,
+ data->rx_mgmt.frame_len) != -2)
+ break;
+#endif /* CONFIG_PASN */
#ifdef CONFIG_SAE
if (stype == WLAN_FC_STYPE_AUTH &&
@@ -5276,13 +5313,13 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
}
wpa_supplicant_mark_disassoc(wpa_s);
os_reltime_age(&wpa_s->last_scan, &age);
- if (age.sec >= SCAN_RES_VALID_FOR_CONNECT) {
- clear_at.sec = SCAN_RES_VALID_FOR_CONNECT;
+ if (age.sec >= wpa_s->conf->scan_res_valid_for_connect) {
+ clear_at.sec = wpa_s->conf->scan_res_valid_for_connect;
clear_at.usec = 0;
} else {
struct os_reltime tmp;
- tmp.sec = SCAN_RES_VALID_FOR_CONNECT;
+ tmp.sec = wpa_s->conf->scan_res_valid_for_connect;
tmp.usec = 0;
os_reltime_sub(&tmp, &age, &clear_at);
}
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index de350bb..c1c823f 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -21,7 +21,7 @@
#include "config.h"
#include "scan.h"
#include "bss.h"
-#include "blacklist.h"
+#include "bssid_ignore.h"
#include "gas_query.h"
#include "interworking.h"
#include "hs20_supplicant.h"
@@ -1299,8 +1299,8 @@ void hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s, u8 code,
code, reauth_delay, url);
if (code == HS20_DEAUTH_REASON_CODE_BSS) {
- wpa_printf(MSG_DEBUG, "HS 2.0: Add BSS to blacklist");
- wpa_blacklist_add(wpa_s, wpa_s->bssid);
+ wpa_printf(MSG_DEBUG, "HS 2.0: Add BSS to ignore list");
+ wpa_bssid_ignore_add(wpa_s, wpa_s->bssid);
/* TODO: For now, disable full ESS since some drivers may not
* support disabling per BSS. */
if (wpa_s->current_ssid) {
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index 5f9d1dc..1c82d21 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -2482,7 +2482,7 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s)
bss_load = cred_over_max_bss_load(wpa_s, cred, bss);
conn_capab = cred_conn_capab_missing(wpa_s, cred, bss);
wpa_msg(wpa_s, MSG_INFO, "%s" MACSTR " type=%s%s%s%s id=%d priority=%d sp_priority=%d",
- excluded ? INTERWORKING_BLACKLISTED : INTERWORKING_AP,
+ excluded ? INTERWORKING_EXCLUDED : INTERWORKING_AP,
MAC2STR(bss->bssid), type,
bh ? " below_min_backhaul=1" : "",
bss_load ? " over_max_bss_load=1" : "",
@@ -2793,6 +2793,7 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, int freq,
wpa_printf(MSG_WARNING,
"ANQP: Cannot send MBO query to unknown BSS "
MACSTR, MAC2STR(dst));
+ wpabuf_free(extra_buf);
return -1;
}
@@ -2831,7 +2832,7 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, int freq,
static void anqp_add_extra(struct wpa_supplicant *wpa_s,
struct wpa_bss_anqp *anqp, u16 info_id,
- const u8 *data, size_t slen, bool protected)
+ const u8 *data, size_t slen, bool protected_response)
{
struct wpa_bss_anqp_elem *tmp, *elem = NULL;
@@ -2856,7 +2857,7 @@ static void anqp_add_extra(struct wpa_supplicant *wpa_s,
wpabuf_free(elem->payload);
}
- elem->protected = protected;
+ elem->protected_response = protected_response;
elem->payload = wpabuf_alloc_copy(data, slen);
if (!elem->payload) {
dl_list_del(&elem->list);
@@ -2899,7 +2900,7 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
const u8 *pos = data;
struct wpa_bss_anqp *anqp = NULL;
u8 type;
- bool protected;
+ bool protected_response;
if (bss)
anqp = bss->anqp;
@@ -3000,10 +3001,11 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s,
case ANQP_VENUE_URL:
wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR " Venue URL",
MAC2STR(sa));
- protected = pmf_in_use(wpa_s, sa);
- anqp_add_extra(wpa_s, anqp, info_id, pos, slen, protected);
+ protected_response = pmf_in_use(wpa_s, sa);
+ anqp_add_extra(wpa_s, anqp, info_id, pos, slen,
+ protected_response);
- if (!protected) {
+ if (!protected_response) {
wpa_printf(MSG_DEBUG,
"ANQP: Ignore Venue URL since PMF was not enabled");
break;
diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c
index 336ae69..901b49b 100644
--- a/wpa_supplicant/mesh.c
+++ b/wpa_supplicant/mesh.c
@@ -44,7 +44,8 @@ static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s,
os_free(wpa_s->mesh_rsn);
wpa_s->mesh_rsn = NULL;
- wpa_supplicant_leave_mesh(wpa_s, false);
+ if (!also_clear_hostapd)
+ wpa_supplicant_leave_mesh(wpa_s, false);
}
@@ -204,6 +205,40 @@ static int wpas_mesh_init_rsn(struct wpa_supplicant *wpa_s)
}
+static int wpas_mesh_update_freq_params(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_driver_mesh_join_params *params = wpa_s->mesh_params;
+ struct hostapd_iface *ifmsh = wpa_s->ifmsh;
+ struct he_capabilities *he_capab = NULL;
+
+ if (ifmsh->current_mode)
+ he_capab = &ifmsh->current_mode->he_capab[IEEE80211_MODE_MESH];
+
+ if (hostapd_set_freq_params(
+ &params->freq,
+ ifmsh->conf->hw_mode,
+ ifmsh->freq,
+ ifmsh->conf->channel,
+ ifmsh->conf->enable_edmg,
+ ifmsh->conf->edmg_channel,
+ ifmsh->conf->ieee80211n,
+ ifmsh->conf->ieee80211ac,
+ ifmsh->conf->ieee80211ax,
+ ifmsh->conf->secondary_channel,
+ hostapd_get_oper_chwidth(ifmsh->conf),
+ hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf),
+ hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf),
+ ifmsh->conf->vht_capab,
+ he_capab)) {
+ wpa_printf(MSG_ERROR, "Error updating mesh frequency params");
+ wpa_supplicant_mesh_deinit(wpa_s, true);
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int wpas_mesh_complete(struct wpa_supplicant *wpa_s)
{
struct hostapd_iface *ifmsh = wpa_s->ifmsh;
@@ -222,36 +257,10 @@ static int wpas_mesh_complete(struct wpa_supplicant *wpa_s)
* initial setting, i.e., due to DFS radar detection during CAC.
*/
if (ifmsh->freq > 0 && ifmsh->freq != params->freq.freq) {
- struct he_capabilities *he_capab = NULL;
-
wpa_s->assoc_freq = ifmsh->freq;
ssid->frequency = ifmsh->freq;
-
- if (ifmsh->current_mode)
- he_capab = &ifmsh->current_mode->he_capab[
- IEEE80211_MODE_MESH];
-
- if (hostapd_set_freq_params(
- &params->freq,
- ifmsh->conf->hw_mode,
- ifmsh->freq,
- ifmsh->conf->channel,
- ifmsh->conf->enable_edmg,
- ifmsh->conf->edmg_channel,
- ifmsh->conf->ieee80211n,
- ifmsh->conf->ieee80211ac,
- ifmsh->conf->ieee80211ax,
- ifmsh->conf->secondary_channel,
- hostapd_get_oper_chwidth(ifmsh->conf),
- hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf),
- hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf),
- ifmsh->conf->vht_capab,
- he_capab)) {
- wpa_printf(MSG_ERROR,
- "Error updating mesh frequency params");
- wpa_supplicant_mesh_deinit(wpa_s, true);
+ if (wpas_mesh_update_freq_params(wpa_s) < 0)
return -1;
- }
}
if (ifmsh->mconf->security != MESH_CONF_SEC_NONE &&
diff --git a/wpa_supplicant/nmake.mak b/wpa_supplicant/nmake.mak
index 80e0ac8..617df03 100644
--- a/wpa_supplicant/nmake.mak
+++ b/wpa_supplicant/nmake.mak
@@ -114,7 +114,7 @@ OBJS = \
$(OBJDIR)\driver_ndis_.obj \
$(OBJDIR)\scan_helpers.obj \
$(OBJDIR)\events.obj \
- $(OBJDIR)\blacklist.obj \
+ $(OBJDIR)\bssid_ignore.obj \
$(OBJDIR)\scan.obj \
$(OBJDIR)\wpas_glue.obj \
$(OBJDIR)\eap_register.obj \
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 0ba1e14..e0e7e54 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -387,6 +387,11 @@ void wpas_notify_network_removed(struct wpa_supplicant *wpa_s,
wpas_notify_persistent_group_removed(wpa_s, ssid);
wpas_p2p_network_removed(wpa_s, ssid);
+
+#ifdef CONFIG_PASN
+ if (wpa_s->pasn.ssid == ssid)
+ wpa_s->pasn.ssid = NULL;
+#endif /* CONFIG_PASN */
}
diff --git a/wpa_supplicant/op_classes.c b/wpa_supplicant/op_classes.c
index b4c0c8a..a0ad0c2 100644
--- a/wpa_supplicant/op_classes.c
+++ b/wpa_supplicant/op_classes.c
@@ -22,10 +22,10 @@ static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode,
unsigned int *flags)
{
int i;
- int is_6ghz = op_class >= 131 && op_class <= 136;
+ bool is_6ghz = op_class >= 131 && op_class <= 136;
for (i = 0; i < mode->num_channels; i++) {
- int chan_is_6ghz;
+ bool chan_is_6ghz;
chan_is_6ghz = mode->channels[i].freq >= 5935 &&
mode->channels[i].freq <= 7115;
@@ -77,7 +77,7 @@ static enum chan_allowed verify_80mhz(struct hostapd_hw_modes *mode,
unsigned int no_ir = 0;
const u8 *center_channels;
size_t num_chan;
- const u8 center_channels_5ghz[] = { 42, 58, 106, 122, 138, 155 };
+ const u8 center_channels_5ghz[] = { 42, 58, 106, 122, 138, 155, 171 };
const u8 center_channels_6ghz[] = { 7, 23, 39, 55, 71, 87, 103, 119,
135, 151, 167, 183, 199, 215 };
@@ -150,7 +150,7 @@ static enum chan_allowed verify_160mhz(struct hostapd_hw_modes *mode,
unsigned int no_ir = 0;
const u8 *center_channels;
size_t num_chan;
- const u8 center_channels_5ghz[] = { 50, 114 };
+ const u8 center_channels_5ghz[] = { 50, 114, 163 };
const u8 center_channels_6ghz[] = { 15, 47, 79, 111, 143, 175, 207 };
if (is_6ghz_op_class(op_class)) {
@@ -320,7 +320,7 @@ static int wpas_op_class_supported(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_VHT_OVERRIDES */
if (op_class->op_class == 128) {
- u8 channels[] = { 42, 58, 106, 122, 138, 155 };
+ u8 channels[] = { 42, 58, 106, 122, 138, 155, 171 };
for (i = 0; i < ARRAY_SIZE(channels); i++) {
if (verify_channel(mode, op_class->op_class,
@@ -337,6 +337,8 @@ static int wpas_op_class_supported(struct wpa_supplicant *wpa_s,
return verify_channel(mode, op_class->op_class, 50,
op_class->bw) != NOT_ALLOWED ||
verify_channel(mode, op_class->op_class, 114,
+ op_class->bw) != NOT_ALLOWED ||
+ verify_channel(mode, op_class->op_class, 163,
op_class->bw) != NOT_ALLOWED;
}
@@ -354,6 +356,10 @@ static int wpas_op_class_supported(struct wpa_supplicant *wpa_s,
verify_channel(mode, op_class->op_class, 122,
op_class->bw) != NOT_ALLOWED ||
verify_channel(mode, op_class->op_class, 138,
+ op_class->bw) != NOT_ALLOWED ||
+ verify_channel(mode, op_class->op_class, 155,
+ op_class->bw) != NOT_ALLOWED ||
+ verify_channel(mode, op_class->op_class, 171,
op_class->bw) != NOT_ALLOWED)
found++;
if (verify_channel(mode, op_class->op_class, 106,
@@ -361,7 +367,14 @@ static int wpas_op_class_supported(struct wpa_supplicant *wpa_s,
verify_channel(mode, op_class->op_class, 138,
op_class->bw) != NOT_ALLOWED)
found++;
- if (verify_channel(mode, op_class->op_class, 155,
+ if (verify_channel(mode, op_class->op_class, 122,
+ op_class->bw) != NOT_ALLOWED &&
+ verify_channel(mode, op_class->op_class, 155,
+ op_class->bw) != NOT_ALLOWED)
+ found++;
+ if (verify_channel(mode, op_class->op_class, 138,
+ op_class->bw) != NOT_ALLOWED &&
+ verify_channel(mode, op_class->op_class, 171,
op_class->bw) != NOT_ALLOWED)
found++;
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 9bcce8c..c04e8ec 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -242,6 +242,22 @@ static void wpas_p2p_set_own_freq_preference(struct wpa_supplicant *wpa_s,
}
+static void wpas_p2p_scan_res_handled(struct wpa_supplicant *wpa_s)
+{
+ unsigned int delay = wpas_p2p_search_delay(wpa_s);
+
+ /* In case of concurrent P2P and external scans, delay P2P search. */
+ if (external_scan_running(wpa_s->radio)) {
+ delay = wpa_s->conf->p2p_search_delay;
+ wpa_printf(MSG_DEBUG,
+ "P2P: Delay next P2P search by %d ms to let externally triggered scan complete",
+ delay);
+ }
+
+ p2p_scan_res_handled(wpa_s->global->p2p, delay);
+}
+
+
static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res)
{
@@ -287,42 +303,25 @@ static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
break;
}
- p2p_scan_res_handled(wpa_s->global->p2p);
+ wpas_p2p_scan_res_handled(wpa_s);
}
-static int wpas_p2p_add_scan_freq_list(struct wpa_supplicant *wpa_s,
- enum hostapd_hw_mode band,
- struct wpa_driver_scan_params *params)
+static void wpas_p2p_scan_res_fail_handler(struct wpa_supplicant *wpa_s)
{
- struct hostapd_hw_modes *mode;
- int num_chans = 0;
- int *freqs, i;
-
- mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band, 0);
- if (!mode)
- return -1;
+ if (wpa_s->p2p_scan_work) {
+ struct wpa_radio_work *work = wpa_s->p2p_scan_work;
- if (params->freqs) {
- while (params->freqs[num_chans])
- num_chans++;
+ wpa_s->p2p_scan_work = NULL;
+ radio_work_done(work);
}
- freqs = os_realloc(params->freqs,
- (num_chans + mode->num_channels + 1) * sizeof(int));
- if (!freqs)
- return -1;
-
- params->freqs = freqs;
-
- for (i = 0; i < mode->num_channels; i++) {
- if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
- continue;
- params->freqs[num_chans++] = mode->channels[i].freq;
- }
- params->freqs[num_chans] = 0;
+ if (wpa_s->global->p2p_disabled || !wpa_s->global->p2p)
+ return;
- return 0;
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "P2P: Failed to get scan results - try to continue");
+ wpas_p2p_scan_res_handled(wpa_s);
}
@@ -351,10 +350,10 @@ static void wpas_p2p_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
if (wpa_s->conf->p2p_6ghz_disable && !params->freqs) {
wpa_printf(MSG_DEBUG,
"P2P: 6 GHz disabled - update the scan frequency list");
- wpas_p2p_add_scan_freq_list(wpa_s, HOSTAPD_MODE_IEEE80211G,
- params);
- wpas_p2p_add_scan_freq_list(wpa_s, HOSTAPD_MODE_IEEE80211A,
- params);
+ wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, params,
+ 0);
+ wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params,
+ 0);
}
ret = wpa_drv_scan(wpa_s, params);
if (ret == 0)
@@ -370,6 +369,7 @@ static void wpas_p2p_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
p2p_notify_scan_trigger_status(wpa_s->global->p2p, ret);
os_get_reltime(&wpa_s->scan_trigger_time);
wpa_s->scan_res_handler = wpas_p2p_scan_res_handler;
+ wpa_s->scan_res_fail_handler = wpas_p2p_scan_res_fail_handler;
wpa_s->own_scan_requested = 1;
wpa_s->clear_driver_scan_cache = 0;
wpa_s->p2p_scan_work = work;
@@ -1956,7 +1956,7 @@ static int wpas_p2p_freq_to_edmg_channel(struct wpa_supplicant *wpa_s,
return -1;
hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
- HOSTAPD_MODE_IEEE80211AD, 0);
+ HOSTAPD_MODE_IEEE80211AD, false);
if (!hwmode) {
wpa_printf(MSG_ERROR,
"Unsupported AP mode: HOSTAPD_MODE_IEEE80211AD");
@@ -3578,7 +3578,7 @@ static int wpas_p2p_get_center_80mhz(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode,
u8 channel)
{
- u8 center_channels[] = { 42, 58, 106, 122, 138, 155 };
+ u8 center_channels[] = { 42, 58, 106, 122, 138, 155, 171 };
size_t i;
if (mode->mode != HOSTAPD_MODE_IEEE80211A)
@@ -3639,7 +3639,7 @@ static int wpas_p2p_get_center_160mhz(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode,
u8 channel)
{
- u8 center_channels[] = { 50, 114 };
+ u8 center_channels[] = { 50, 114, 163 };
unsigned int i;
if (mode->mode != HOSTAPD_MODE_IEEE80211A)
@@ -3787,7 +3787,7 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s,
/* Check for non-continuous jump in channel index
* incrementation */
- if ((o->op_class == 128 || o->op_class == 130) &&
+ if ((o->op_class >= 128 && o->op_class <= 130) &&
ch < 149 && ch + o->inc > 149)
ch = 149;
@@ -3980,6 +3980,7 @@ int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s,
char ifname[100];
char force_name[100];
int ret;
+ const u8 *if_addr = NULL;
ret = os_snprintf(ifname, sizeof(ifname), P2P_MGMT_DEVICE_PREFIX "%s",
wpa_s->ifname);
@@ -3991,7 +3992,12 @@ int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s,
ifname[IFNAMSIZ - 1] = '\0';
force_name[0] = '\0';
wpa_s->pending_interface_type = WPA_IF_P2P_DEVICE;
- ret = wpa_drv_if_add(wpa_s, WPA_IF_P2P_DEVICE, ifname, NULL, NULL,
+
+ if (wpa_s->conf->p2p_device_random_mac_addr == 2 &&
+ !is_zero_ether_addr(wpa_s->conf->p2p_device_persistent_mac_addr))
+ if_addr = wpa_s->conf->p2p_device_persistent_mac_addr;
+
+ ret = wpa_drv_if_add(wpa_s, WPA_IF_P2P_DEVICE, ifname, if_addr, NULL,
force_name, wpa_s->pending_interface_addr, NULL);
if (ret < 0) {
wpa_printf(MSG_DEBUG, "P2P: Failed to create P2P Device interface");
@@ -4568,6 +4574,16 @@ int wpas_p2p_mac_setup(struct wpa_supplicant *wpa_s)
if (wpa_s->conf->p2p_device_random_mac_addr == 0)
return 0;
+ if (wpa_s->conf->p2p_device_random_mac_addr == 2) {
+ if (is_zero_ether_addr(
+ wpa_s->conf->p2p_device_persistent_mac_addr) &&
+ !is_zero_ether_addr(wpa_s->own_addr)) {
+ os_memcpy(wpa_s->conf->p2p_device_persistent_mac_addr,
+ wpa_s->own_addr, ETH_ALEN);
+ }
+ return 0;
+ }
+
if (!wpa_s->conf->ssid) {
if (random_mac_addr(addr) < 0) {
wpa_msg(wpa_s, MSG_INFO,
@@ -5342,10 +5358,10 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq,
} else if (wpa_s->conf->p2p_6ghz_disable) {
wpa_printf(MSG_DEBUG,
"P2P: 6 GHz disabled - update the scan frequency list");
- wpas_p2p_add_scan_freq_list(wpa_s, HOSTAPD_MODE_IEEE80211G,
- &params);
- wpas_p2p_add_scan_freq_list(wpa_s, HOSTAPD_MODE_IEEE80211A,
- &params);
+ wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, &params,
+ 0);
+ wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, &params,
+ 0);
}
ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p);
@@ -7105,7 +7121,7 @@ static void wpas_p2p_scan_res_ignore_search(struct wpa_supplicant *wpa_s,
* Indicate that results have been processed so that the P2P module can
* continue pending tasks.
*/
- p2p_scan_res_handled(wpa_s->global->p2p);
+ wpas_p2p_scan_res_handled(wpa_s);
}
diff --git a/wpa_supplicant/pasn_supplicant.c b/wpa_supplicant/pasn_supplicant.c
new file mode 100644
index 0000000..4f5ac58
--- /dev/null
+++ b/wpa_supplicant/pasn_supplicant.c
@@ -0,0 +1,1509 @@
+/*
+ * wpa_supplicant - PASN processing
+ *
+ * Copyright (C) 2019 Intel Corporation
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common/ieee802_11_defs.h"
+#include "common/ieee802_11_common.h"
+#include "common/dragonfly.h"
+#include "common/ptksa_cache.h"
+#include "utils/eloop.h"
+#include "drivers/driver.h"
+#include "crypto/crypto.h"
+#include "crypto/random.h"
+#include "eap_common/eap_defs.h"
+#include "rsn_supp/wpa.h"
+#include "rsn_supp/pmksa_cache.h"
+#include "wpa_supplicant_i.h"
+#include "driver_i.h"
+#include "bss.h"
+#include "config.h"
+
+static const int dot11RSNAConfigPMKLifetime = 43200;
+
+struct wpa_pasn_auth_work {
+ u8 bssid[ETH_ALEN];
+ int akmp;
+ int cipher;
+ u16 group;
+ int network_id;
+};
+
+
+static void wpas_pasn_auth_work_timeout(void *eloop_ctx, void *timeout_ctx)
+{
+ struct wpa_supplicant *wpa_s = eloop_ctx;
+
+ wpa_printf(MSG_DEBUG, "PASN: Auth work timeout - stopping auth");
+
+ wpas_pasn_auth_stop(wpa_s);
+}
+
+
+static void wpas_pasn_cancel_auth_work(struct wpa_supplicant *wpa_s)
+{
+ wpa_printf(MSG_DEBUG, "PASN: Cancel pasn-start-auth work");
+
+ /* Remove pending/started work */
+ radio_remove_works(wpa_s, "pasn-start-auth", 0);
+}
+
+
+static void wpas_pasn_auth_status(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ int akmp, int cipher, u8 status)
+{
+ wpa_msg(wpa_s, MSG_INFO,
+ PASN_AUTH_STATUS MACSTR " akmp=%s, status=%u",
+ MAC2STR(bssid), wpa_key_mgmt_txt(akmp, WPA_PROTO_RSN),
+ status);
+}
+
+
+#ifdef CONFIG_SAE
+
+static struct wpabuf * wpas_pasn_wd_sae_commit(struct wpa_supplicant *wpa_s)
+{
+ struct wpas_pasn *pasn = &wpa_s->pasn;
+ struct wpabuf *buf = NULL;
+ const char *password = NULL;
+ int ret;
+
+ if (pasn->ssid) {
+ password = pasn->ssid->sae_password;
+ if (!password)
+ password = pasn->ssid->passphrase;
+ }
+
+ if (!password) {
+ wpa_printf(MSG_DEBUG, "PASN: SAE without a password");
+ return NULL;
+ }
+
+ ret = sae_set_group(&pasn->sae, pasn->group);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed to set SAE group");
+ return NULL;
+ }
+
+ /* TODO: SAE H2E */
+ ret = sae_prepare_commit(wpa_s->own_addr, pasn->bssid,
+ (const u8 *) password, os_strlen(password), 0,
+ &pasn->sae);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed to prepare SAE commit");
+ return NULL;
+ }
+
+ /* Need to add the entire Authentication frame body */
+ buf = wpabuf_alloc(6 + SAE_COMMIT_MAX_LEN);
+ if (!buf) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed to allocate SAE buffer");
+ return NULL;
+ }
+
+ wpabuf_put_le16(buf, WLAN_AUTH_SAE);
+ wpabuf_put_le16(buf, 1);
+ wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
+
+ sae_write_commit(&pasn->sae, buf, NULL, 0);
+ pasn->sae.state = SAE_COMMITTED;
+
+ return buf;
+}
+
+
+static int wpas_pasn_wd_sae_rx(struct wpa_supplicant *wpa_s, struct wpabuf *wd)
+{
+ struct wpas_pasn *pasn = &wpa_s->pasn;
+ const u8 *data;
+ size_t buf_len;
+ u16 len, res, alg, seq, status;
+ int groups[] = { pasn->group, 0 };
+ int ret;
+
+ if (!wd)
+ return -1;
+
+ data = wpabuf_head_u8(wd);
+ buf_len = wpabuf_len(wd);
+
+ /* first handle the commit message */
+ if (buf_len < 2) {
+ wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short (commit)");
+ return -1;
+ }
+
+ len = WPA_GET_LE16(data);
+ if (len < 6 || buf_len - 2 < len) {
+ wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short for commit");
+ return -1;
+ }
+
+ buf_len -= 2;
+ data += 2;
+
+ alg = WPA_GET_LE16(data);
+ seq = WPA_GET_LE16(data + 2);
+ status = WPA_GET_LE16(data + 4);
+
+ wpa_printf(MSG_DEBUG, "PASN: SAE: commit: alg=%u, seq=%u, status=%u",
+ alg, seq, status);
+
+ /* TODO: SAE H2E */
+ if (alg != WLAN_AUTH_SAE || seq != 1 || status != WLAN_STATUS_SUCCESS) {
+ wpa_printf(MSG_DEBUG, "PASN: SAE: dropping peer commit");
+ return -1;
+ }
+
+ res = sae_parse_commit(&pasn->sae, data + 6, len - 6, NULL, 0, groups,
+ 0);
+ if (res != WLAN_STATUS_SUCCESS) {
+ wpa_printf(MSG_DEBUG, "PASN: SAE failed parsing commit");
+ return -1;
+ }
+
+ /* Process the commit message and derive the PMK */
+ ret = sae_process_commit(&pasn->sae);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "SAE: Failed to process peer commit");
+ return -1;
+ }
+
+ buf_len -= len;
+ data += len;
+
+ /* Handle the confirm message */
+ if (buf_len < 2) {
+ wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short (confirm)");
+ return -1;
+ }
+
+ len = WPA_GET_LE16(data);
+ if (len < 6 || buf_len - 2 < len) {
+ wpa_printf(MSG_DEBUG, "PASN: SAE buffer too short for confirm");
+ return -1;
+ }
+
+ buf_len -= 2;
+ data += 2;
+
+ alg = WPA_GET_LE16(data);
+ seq = WPA_GET_LE16(data + 2);
+ status = WPA_GET_LE16(data + 4);
+
+ wpa_printf(MSG_DEBUG, "PASN: SAE confirm: alg=%u, seq=%u, status=%u",
+ alg, seq, status);
+
+ if (alg != WLAN_AUTH_SAE || seq != 2 || status != WLAN_STATUS_SUCCESS) {
+ wpa_printf(MSG_DEBUG, "PASN: Dropping peer SAE confirm");
+ return -1;
+ }
+
+ res = sae_check_confirm(&pasn->sae, data + 6, len - 6);
+ if (res != WLAN_STATUS_SUCCESS) {
+ wpa_printf(MSG_DEBUG, "PASN: SAE failed checking confirm");
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "PASN: SAE completed successfully");
+ pasn->sae.state = SAE_ACCEPTED;
+
+ return 0;
+}
+
+
+static struct wpabuf * wpas_pasn_wd_sae_confirm(struct wpa_supplicant *wpa_s)
+{
+ struct wpas_pasn *pasn = &wpa_s->pasn;
+ struct wpabuf *buf = NULL;
+
+ /* Need to add the entire authentication frame body */
+ buf = wpabuf_alloc(6 + SAE_CONFIRM_MAX_LEN);
+ if (!buf) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed to allocate SAE buffer");
+ return NULL;
+ }
+
+ wpabuf_put_le16(buf, WLAN_AUTH_SAE);
+ wpabuf_put_le16(buf, 2);
+ wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
+
+ sae_write_confirm(&pasn->sae, buf);
+ pasn->sae.state = SAE_CONFIRMED;
+
+ return buf;
+}
+
+#endif /* CONFIG_SAE */
+
+
+#ifdef CONFIG_FILS
+
+static struct wpabuf * wpas_pasn_fils_build_auth(struct wpa_supplicant *wpa_s)
+{
+ struct wpas_pasn *pasn = &wpa_s->pasn;
+ struct wpabuf *buf = NULL;
+ struct wpabuf *erp_msg;
+ int ret;
+
+ erp_msg = eapol_sm_build_erp_reauth_start(wpa_s->eapol);
+ if (!erp_msg) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: FILS: ERP EAP-Initiate/Re-auth unavailable");
+ return NULL;
+ }
+
+ if (random_get_bytes(pasn->fils.nonce, FILS_NONCE_LEN) < 0 ||
+ random_get_bytes(pasn->fils.session, FILS_SESSION_LEN) < 0)
+ goto fail;
+
+ wpa_hexdump(MSG_DEBUG, "PASN: FILS: Nonce", pasn->fils.nonce,
+ FILS_NONCE_LEN);
+
+ wpa_hexdump(MSG_DEBUG, "PASN: FILS: Session", pasn->fils.session,
+ FILS_SESSION_LEN);
+
+ buf = wpabuf_alloc(1500);
+ if (!buf)
+ goto fail;
+
+ /* Add the authentication algorithm */
+ wpabuf_put_le16(buf, WLAN_AUTH_FILS_SK);
+
+ /* Authentication Transaction seq# */
+ wpabuf_put_le16(buf, 1);
+
+ /* Status Code */
+ wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
+
+ /* Own RSNE */
+ wpa_pasn_add_rsne(buf, NULL, pasn->akmp, pasn->cipher);
+
+ /* FILS Nonce */
+ wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
+ wpabuf_put_u8(buf, 1 + FILS_NONCE_LEN);
+ wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_NONCE);
+ wpabuf_put_data(buf, pasn->fils.nonce, FILS_NONCE_LEN);
+
+ /* FILS Session */
+ wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
+ wpabuf_put_u8(buf, 1 + FILS_SESSION_LEN);
+ wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_SESSION);
+ wpabuf_put_data(buf, pasn->fils.session, FILS_SESSION_LEN);
+
+ /* Wrapped Data (ERP) */
+ wpabuf_put_u8(buf, WLAN_EID_EXTENSION);
+ wpabuf_put_u8(buf, 1 + wpabuf_len(erp_msg));
+ wpabuf_put_u8(buf, WLAN_EID_EXT_WRAPPED_DATA);
+ wpabuf_put_buf(buf, erp_msg);
+
+ /*
+ * Calculate pending PMKID here so that we do not need to maintain a
+ * copy of the EAP-Initiate/Reauth message.
+ */
+ ret = fils_pmkid_erp(pasn->akmp, wpabuf_head(erp_msg),
+ wpabuf_len(erp_msg),
+ pasn->fils.erp_pmkid);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: FILS: Failed to get ERP PMKID");
+ goto fail;
+ }
+
+ wpabuf_free(erp_msg);
+ erp_msg = NULL;
+
+ wpa_hexdump_buf(MSG_DEBUG, "PASN: FILS: Authentication frame", buf);
+ return buf;
+fail:
+ wpabuf_free(erp_msg);
+ wpabuf_free(buf);
+ return NULL;
+}
+
+
+static void wpas_pasn_initiate_eapol(struct wpa_supplicant *wpa_s)
+{
+ struct wpas_pasn *pasn = &wpa_s->pasn;
+ struct eapol_config eapol_conf;
+ struct wpa_ssid *ssid = pasn->ssid;
+
+ wpa_printf(MSG_DEBUG, "PASN: FILS: Initiating EAPOL");
+
+ eapol_sm_notify_eap_success(wpa_s->eapol, false);
+ eapol_sm_notify_eap_fail(wpa_s->eapol, false);
+ eapol_sm_notify_portControl(wpa_s->eapol, Auto);
+
+ os_memset(&eapol_conf, 0, sizeof(eapol_conf));
+ eapol_conf.fast_reauth = wpa_s->conf->fast_reauth;
+ eapol_conf.workaround = ssid->eap_workaround;
+
+ eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf);
+}
+
+
+static struct wpabuf * wpas_pasn_wd_fils_auth(struct wpa_supplicant *wpa_s)
+{
+ struct wpas_pasn *pasn = &wpa_s->pasn;
+ struct wpa_bss *bss;
+ const u8 *indic;
+ u16 fils_info;
+
+ wpa_printf(MSG_DEBUG, "PASN: FILS: wrapped data - completed=%u",
+ pasn->fils.completed);
+
+ /* Nothing to add as we are done */
+ if (pasn->fils.completed)
+ return NULL;
+
+ if (!pasn->ssid) {
+ wpa_printf(MSG_DEBUG, "PASN: FILS: No network block");
+ return NULL;
+ }
+
+ bss = wpa_bss_get_bssid(wpa_s, pasn->bssid);
+ if (!bss) {
+ wpa_printf(MSG_DEBUG, "PASN: FILS: BSS not found");
+ return NULL;
+ }
+
+ indic = wpa_bss_get_ie(bss, WLAN_EID_FILS_INDICATION);
+ if (!indic || indic[1] < 2) {
+ wpa_printf(MSG_DEBUG, "PASN: Missing FILS Indication IE");
+ return NULL;
+ }
+
+ fils_info = WPA_GET_LE16(indic + 2);
+ if (!(fils_info & BIT(9))) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: FILS auth without PFS not supported");
+ return NULL;
+ }
+
+ wpas_pasn_initiate_eapol(wpa_s);
+
+ return wpas_pasn_fils_build_auth(wpa_s);
+}
+
+
+static int wpas_pasn_wd_fils_rx(struct wpa_supplicant *wpa_s, struct wpabuf *wd)
+{
+ struct wpas_pasn *pasn = &wpa_s->pasn;
+ struct ieee802_11_elems elems;
+ struct wpa_ie_data rsne_data;
+ u8 rmsk[ERP_MAX_KEY_LEN];
+ size_t rmsk_len;
+ u8 anonce[FILS_NONCE_LEN];
+ const u8 *data;
+ size_t buf_len;
+ struct wpabuf *fils_wd = NULL;
+ u16 alg, seq, status;
+ int ret;
+
+ if (!wd)
+ return -1;
+
+ data = wpabuf_head(wd);
+ buf_len = wpabuf_len(wd);
+
+ wpa_hexdump(MSG_DEBUG, "PASN: FILS: Authentication frame len=%zu",
+ data, buf_len);
+
+ /* first handle the header */
+ if (buf_len < 6) {
+ wpa_printf(MSG_DEBUG, "PASN: FILS: Buffer too short");
+ return -1;
+ }
+
+ alg = WPA_GET_LE16(data);
+ seq = WPA_GET_LE16(data + 2);
+ status = WPA_GET_LE16(data + 4);
+
+ wpa_printf(MSG_DEBUG, "PASN: FILS: commit: alg=%u, seq=%u, status=%u",
+ alg, seq, status);
+
+ if (alg != WLAN_AUTH_FILS_SK || seq != 2 ||
+ status != WLAN_STATUS_SUCCESS) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: FILS: Dropping peer authentication");
+ return -1;
+ }
+
+ data += 6;
+ buf_len -= 6;
+
+ if (ieee802_11_parse_elems(data, buf_len, &elems, 1) == ParseFailed) {
+ wpa_printf(MSG_DEBUG, "PASN: FILS: Could not parse elements");
+ return -1;
+ }
+
+ if (!elems.rsn_ie || !elems.fils_nonce || !elems.fils_nonce ||
+ !elems.wrapped_data) {
+ wpa_printf(MSG_DEBUG, "PASN: FILS: Missing IEs");
+ return -1;
+ }
+
+ ret = wpa_parse_wpa_ie(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
+ &rsne_data);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: FILS: Failed parsing RNSE");
+ return -1;
+ }
+
+ ret = wpa_pasn_validate_rsne(&rsne_data);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: FILS: Failed validating RSNE");
+ return -1;
+ }
+
+ if (rsne_data.num_pmkid) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: FILS: Not expecting PMKID in RSNE");
+ return -1;
+ }
+
+ wpa_hexdump(MSG_DEBUG, "PASN: FILS: ANonce", elems.fils_nonce,
+ FILS_NONCE_LEN);
+ os_memcpy(anonce, elems.fils_nonce, FILS_NONCE_LEN);
+
+ wpa_hexdump(MSG_DEBUG, "PASN: FILS: FILS Session", elems.fils_session,
+ FILS_SESSION_LEN);
+
+ if (os_memcmp(pasn->fils.session, elems.fils_session,
+ FILS_SESSION_LEN)) {
+ wpa_printf(MSG_DEBUG, "PASN: FILS: Session mismatch");
+ return -1;
+ }
+
+ fils_wd = ieee802_11_defrag(&elems, WLAN_EID_EXTENSION,
+ WLAN_EID_EXT_WRAPPED_DATA);
+
+ if (!fils_wd) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: FILS: Failed getting wrapped data");
+ return -1;
+ }
+
+ eapol_sm_process_erp_finish(wpa_s->eapol, wpabuf_head(fils_wd),
+ wpabuf_len(fils_wd));
+
+ wpabuf_free(fils_wd);
+ fils_wd = NULL;
+
+ if (eapol_sm_failed(wpa_s->eapol)) {
+ wpa_printf(MSG_DEBUG, "PASN: FILS: ERP finish failed");
+ return -1;
+ }
+
+ rmsk_len = ERP_MAX_KEY_LEN;
+ ret = eapol_sm_get_key(wpa_s->eapol, rmsk, rmsk_len);
+
+ if (ret == PMK_LEN) {
+ rmsk_len = PMK_LEN;
+ ret = eapol_sm_get_key(wpa_s->eapol, rmsk, rmsk_len);
+ }
+
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: FILS: Failed getting RMSK");
+ return -1;
+ }
+
+ ret = fils_rmsk_to_pmk(pasn->akmp, rmsk, rmsk_len,
+ pasn->fils.nonce, anonce, NULL, 0,
+ pasn->pmk, &pasn->pmk_len);
+
+ forced_memzero(rmsk, sizeof(rmsk));
+
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: FILS: Failed to derive PMK");
+ return -1;
+ }
+
+ wpa_hexdump(MSG_DEBUG, "PASN: FILS: PMKID", pasn->fils.erp_pmkid,
+ PMKID_LEN);
+
+ wpa_printf(MSG_DEBUG, "PASN: FILS: ERP processing succeeded");
+
+ wpa_pasn_pmksa_cache_add(wpa_s->wpa, pasn->pmk,
+ pasn->pmk_len, pasn->fils.erp_pmkid,
+ pasn->bssid, pasn->akmp);
+
+ pasn->fils.completed = true;
+ return 0;
+}
+
+#endif /* CONFIG_FILS */
+
+
+static struct wpabuf * wpas_pasn_get_wrapped_data(struct wpa_supplicant *wpa_s)
+{
+ struct wpas_pasn *pasn = &wpa_s->pasn;
+
+ if (pasn->using_pmksa)
+ return NULL;
+
+ switch (pasn->akmp) {
+ case WPA_KEY_MGMT_PASN:
+ /* no wrapped data */
+ return NULL;
+ case WPA_KEY_MGMT_SAE:
+#ifdef CONFIG_SAE
+ if (pasn->trans_seq == 0)
+ return wpas_pasn_wd_sae_commit(wpa_s);
+ if (pasn->trans_seq == 2)
+ return wpas_pasn_wd_sae_confirm(wpa_s);
+#endif /* CONFIG_SAE */
+ wpa_printf(MSG_ERROR,
+ "PASN: SAE: Cannot derive wrapped data");
+ return NULL;
+ case WPA_KEY_MGMT_FILS_SHA256:
+ case WPA_KEY_MGMT_FILS_SHA384:
+#ifdef CONFIG_FILS
+ return wpas_pasn_wd_fils_auth(wpa_s);
+#endif /* CONFIG_FILS */
+ case WPA_KEY_MGMT_FT_PSK:
+ case WPA_KEY_MGMT_FT_IEEE8021X:
+ case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
+ /*
+ * Wrapped data with these AKMs is optional and is only needed
+ * for further validation of FT security parameters. For now do
+ * not use them.
+ */
+ return NULL;
+ default:
+ wpa_printf(MSG_ERROR,
+ "PASN: TODO: Wrapped data for akmp=0x%x",
+ pasn->akmp);
+ return NULL;
+ }
+}
+
+
+static u8 wpas_pasn_get_wrapped_data_format(struct wpas_pasn *pasn)
+{
+ if (pasn->using_pmksa)
+ return WPA_PASN_WRAPPED_DATA_NO;
+
+ /* Note: Valid AKMP is expected to already be validated */
+ switch (pasn->akmp) {
+ case WPA_KEY_MGMT_SAE:
+ return WPA_PASN_WRAPPED_DATA_SAE;
+ case WPA_KEY_MGMT_FILS_SHA256:
+ case WPA_KEY_MGMT_FILS_SHA384:
+ return WPA_PASN_WRAPPED_DATA_FILS_SK;
+ case WPA_KEY_MGMT_FT_PSK:
+ case WPA_KEY_MGMT_FT_IEEE8021X:
+ case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
+ /*
+ * Wrapped data with these AKMs is optional and is only needed
+ * for further validation of FT security parameters. For now do
+ * not use them.
+ */
+ return WPA_PASN_WRAPPED_DATA_NO;
+ case WPA_KEY_MGMT_PASN:
+ default:
+ return WPA_PASN_WRAPPED_DATA_NO;
+ }
+}
+
+
+static struct wpabuf * wpas_pasn_build_auth_1(struct wpa_supplicant *wpa_s)
+{
+ struct wpas_pasn *pasn = &wpa_s->pasn;
+ struct wpabuf *buf, *pubkey = NULL, *wrapped_data_buf = NULL;
+ const u8 *pmkid;
+ u8 wrapped_data;
+ int ret;
+ u16 capab;
+
+ wpa_printf(MSG_DEBUG, "PASN: Building frame 1");
+
+ if (pasn->trans_seq)
+ return NULL;
+
+ buf = wpabuf_alloc(1500);
+ if (!buf)
+ goto fail;
+
+ /* Get public key */
+ pubkey = crypto_ecdh_get_pubkey(pasn->ecdh, 0);
+ pubkey = wpabuf_zeropad(pubkey, crypto_ecdh_prime_len(pasn->ecdh));
+ if (!pubkey) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed to get pubkey");
+ goto fail;
+ }
+
+ wrapped_data = wpas_pasn_get_wrapped_data_format(pasn);
+
+ wpa_pasn_build_auth_header(buf, pasn->bssid,
+ wpa_s->own_addr, pasn->bssid,
+ pasn->trans_seq + 1, WLAN_STATUS_SUCCESS);
+
+ pmkid = NULL;
+ if (wpa_key_mgmt_ft(pasn->akmp)) {
+ ret = wpa_pasn_ft_derive_pmk_r1(wpa_s->wpa, pasn->akmp,
+ pasn->bssid,
+ pasn->pmk_r1,
+ &pasn->pmk_r1_len,
+ pasn->pmk_r1_name);
+ if (ret) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: FT: Failed to derive keys");
+ goto fail;
+ }
+
+ pmkid = pasn->pmk_r1_name;
+ } else if (wrapped_data != WPA_PASN_WRAPPED_DATA_NO) {
+ struct rsn_pmksa_cache_entry *pmksa;
+
+ pmksa = wpa_sm_pmksa_cache_get(wpa_s->wpa, pasn->bssid,
+ NULL, NULL, pasn->akmp);
+ if (pmksa)
+ pmkid = pmksa->pmkid;
+
+ /*
+ * Note: Even when PMKSA is available, also add wrapped data as
+ * it is possible that the PMKID is no longer valid at the AP.
+ */
+ wrapped_data_buf = wpas_pasn_get_wrapped_data(wpa_s);
+ }
+
+ if (wpa_pasn_add_rsne(buf, pmkid, pasn->akmp, pasn->cipher) < 0)
+ goto fail;
+
+ if (!wrapped_data_buf)
+ wrapped_data = WPA_PASN_WRAPPED_DATA_NO;
+
+ wpa_pasn_add_parameter_ie(buf, pasn->group, wrapped_data,
+ pubkey, NULL, -1);
+
+ if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0)
+ goto fail;
+
+ /* Add own RNSXE */
+ /* TODO: How to handle protected TWT and SAE H2E? */
+ capab = 0;
+ if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF)
+ capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF);
+ if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_RTT)
+ capab |= BIT(WLAN_RSNX_CAPAB_SECURE_RTT);
+ if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_PROT_RANGE_NEG)
+ capab |= BIT(WLAN_RSNX_CAPAB_PROT_RANGE_NEG);
+ wpa_pasn_add_rsnxe(buf, capab);
+
+ ret = pasn_auth_frame_hash(pasn->akmp, pasn->cipher,
+ wpabuf_head_u8(buf) + IEEE80211_HDRLEN,
+ wpabuf_len(buf) - IEEE80211_HDRLEN,
+ pasn->hash);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed to compute hash");
+ goto fail;
+ }
+
+ pasn->trans_seq++;
+
+ wpabuf_free(wrapped_data_buf);
+ wpabuf_free(pubkey);
+
+ wpa_printf(MSG_DEBUG, "PASN: Frame 1: Success");
+ return buf;
+fail:
+ pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ wpabuf_free(wrapped_data_buf);
+ wpabuf_free(pubkey);
+ wpabuf_free(buf);
+ return NULL;
+}
+
+
+static struct wpabuf * wpas_pasn_build_auth_3(struct wpa_supplicant *wpa_s)
+{
+ struct wpas_pasn *pasn = &wpa_s->pasn;
+ struct wpabuf *buf, *wrapped_data_buf = NULL;
+ u8 mic[WPA_PASN_MAX_MIC_LEN];
+ u8 mic_len, data_len;
+ const u8 *data;
+ u8 *ptr;
+ u8 wrapped_data;
+ int ret;
+
+ wpa_printf(MSG_DEBUG, "PASN: Building frame 3");
+
+ if (pasn->trans_seq != 2)
+ return NULL;
+
+ buf = wpabuf_alloc(1500);
+ if (!buf)
+ goto fail;
+
+ wrapped_data = wpas_pasn_get_wrapped_data_format(pasn);
+
+ wpa_pasn_build_auth_header(buf, pasn->bssid,
+ wpa_s->own_addr, pasn->bssid,
+ pasn->trans_seq + 1, WLAN_STATUS_SUCCESS);
+
+ wrapped_data_buf = wpas_pasn_get_wrapped_data(wpa_s);
+
+ if (!wrapped_data_buf)
+ wrapped_data = WPA_PASN_WRAPPED_DATA_NO;
+
+ wpa_pasn_add_parameter_ie(buf, pasn->group, wrapped_data,
+ NULL, NULL, -1);
+
+ if (wpa_pasn_add_wrapped_data(buf, wrapped_data_buf) < 0)
+ goto fail;
+ wpabuf_free(wrapped_data_buf);
+ wrapped_data_buf = NULL;
+
+ /* Add the MIC */
+ mic_len = pasn_mic_len(pasn->akmp, pasn->cipher);
+ wpabuf_put_u8(buf, WLAN_EID_MIC);
+ wpabuf_put_u8(buf, mic_len);
+ ptr = wpabuf_put(buf, mic_len);
+
+ os_memset(ptr, 0, mic_len);
+
+ data = wpabuf_head_u8(buf) + IEEE80211_HDRLEN;
+ data_len = wpabuf_len(buf) - IEEE80211_HDRLEN;
+
+ ret = pasn_mic(pasn->ptk.kck, pasn->akmp, pasn->cipher,
+ wpa_s->own_addr, pasn->bssid,
+ pasn->hash, mic_len * 2, data, data_len, mic);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: frame 3: Failed MIC calculation");
+ goto fail;
+ }
+
+ os_memcpy(ptr, mic, mic_len);
+
+ pasn->trans_seq++;
+
+ wpa_printf(MSG_DEBUG, "PASN: frame 3: Success");
+ return buf;
+fail:
+ pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ wpabuf_free(wrapped_data_buf);
+ wpabuf_free(buf);
+ return NULL;
+}
+
+
+static void wpas_pasn_reset(struct wpa_supplicant *wpa_s)
+{
+ struct wpas_pasn *pasn = &wpa_s->pasn;
+
+ wpa_printf(MSG_DEBUG, "PASN: Reset");
+
+ crypto_ecdh_deinit(pasn->ecdh);
+ pasn->ecdh = NULL;
+
+ wpas_pasn_cancel_auth_work(wpa_s);
+ wpa_s->pasn_auth_work = NULL;
+
+ eloop_cancel_timeout(wpas_pasn_auth_work_timeout, wpa_s, NULL);
+
+ pasn->akmp = 0;
+ pasn->cipher = 0;
+ pasn->group = 0;
+ pasn->trans_seq = 0;
+ pasn->pmk_len = 0;
+ pasn->using_pmksa = false;
+
+ forced_memzero(pasn->pmk, sizeof(pasn->pmk));
+ forced_memzero(&pasn->ptk, sizeof(pasn->ptk));
+ forced_memzero(&pasn->hash, sizeof(pasn->hash));
+
+ wpabuf_free(pasn->beacon_rsne_rsnxe);
+ pasn->beacon_rsne_rsnxe = NULL;
+
+#ifdef CONFIG_SAE
+ sae_clear_data(&pasn->sae);
+#endif /* CONFIG_SAE */
+
+#ifdef CONFIG_FILS
+ os_memset(&pasn->fils, 0, sizeof(pasn->fils));
+#endif /* CONFIG_FILS*/
+
+#ifdef CONFIG_IEEE80211R
+ forced_memzero(pasn->pmk_r1, sizeof(pasn->pmk_r1));
+ pasn->pmk_r1_len = 0;
+ os_memset(pasn->pmk_r1_name, 0, sizeof(pasn->pmk_r1_name));
+#endif /* CONFIG_IEEE80211R */
+ pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+}
+
+
+static int wpas_pasn_set_pmk(struct wpa_supplicant *wpa_s,
+ struct wpa_ie_data *rsn_data,
+ struct wpa_pasn_params_data *pasn_data,
+ struct wpabuf *wrapped_data)
+{
+ static const u8 pasn_default_pmk[] = {'P', 'M', 'K', 'z'};
+ struct wpas_pasn *pasn = &wpa_s->pasn;
+
+ os_memset(pasn->pmk, 0, sizeof(pasn->pmk));
+ pasn->pmk_len = 0;
+
+ if (pasn->akmp == WPA_KEY_MGMT_PASN) {
+ wpa_printf(MSG_DEBUG, "PASN: Using default PMK");
+
+ pasn->pmk_len = WPA_PASN_PMK_LEN;
+ os_memcpy(pasn->pmk, pasn_default_pmk,
+ sizeof(pasn_default_pmk));
+ return 0;
+ }
+
+ if (wpa_key_mgmt_ft(pasn->akmp)) {
+#ifdef CONFIG_IEEE80211R
+ wpa_printf(MSG_DEBUG, "PASN: FT: Using PMK-R1");
+ pasn->pmk_len = pasn->pmk_r1_len;
+ os_memcpy(pasn->pmk, pasn->pmk_r1, pasn->pmk_r1_len);
+ pasn->using_pmksa = true;
+ return 0;
+#else /* CONFIG_IEEE80211R */
+ wpa_printf(MSG_DEBUG, "PASN: FT: Not supported");
+ return -1;
+#endif /* CONFIG_IEEE80211R */
+ }
+
+ if (rsn_data->num_pmkid) {
+ struct rsn_pmksa_cache_entry *pmksa;
+
+ pmksa = wpa_sm_pmksa_cache_get(wpa_s->wpa, pasn->bssid,
+ rsn_data->pmkid, NULL,
+ pasn->akmp);
+ if (pmksa) {
+ wpa_printf(MSG_DEBUG, "PASN: Using PMKSA");
+
+ pasn->pmk_len = pmksa->pmk_len;
+ os_memcpy(pasn->pmk, pmksa->pmk, pmksa->pmk_len);
+ pasn->using_pmksa = true;
+
+ return 0;
+ }
+ }
+
+#ifdef CONFIG_SAE
+ if (pasn->akmp == WPA_KEY_MGMT_SAE) {
+ int ret;
+
+ ret = wpas_pasn_wd_sae_rx(wpa_s, wrapped_data);
+ if (ret) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: Failed processing SAE wrapped data");
+ pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "PASN: Success deriving PMK with SAE");
+ pasn->pmk_len = PMK_LEN;
+ os_memcpy(pasn->pmk, pasn->sae.pmk, PMK_LEN);
+
+ wpa_pasn_pmksa_cache_add(wpa_s->wpa, pasn->pmk,
+ pasn->pmk_len, pasn->sae.pmkid,
+ pasn->bssid, pasn->akmp);
+ return 0;
+ }
+#endif /* CONFIG_SAE */
+
+#ifdef CONFIG_FILS
+ if (pasn->akmp == WPA_KEY_MGMT_FILS_SHA256 ||
+ pasn->akmp == WPA_KEY_MGMT_FILS_SHA384) {
+ int ret;
+
+ ret = wpas_pasn_wd_fils_rx(wpa_s, wrapped_data);
+ if (ret) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: Failed processing FILS wrapped data");
+ pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ return -1;
+ }
+
+ return 0;
+ }
+#endif /* CONFIG_FILS */
+
+ /* TODO: Derive PMK based on wrapped data */
+ wpa_printf(MSG_DEBUG, "PASN: Missing implementation to derive PMK");
+ pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ return -1;
+}
+
+
+static int wpas_pasn_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ int akmp, int cipher, u16 group, int freq,
+ const u8 *beacon_rsne, u8 beacon_rsne_len,
+ const u8 *beacon_rsnxe, u8 beacon_rsnxe_len,
+ int network_id)
+{
+ struct wpas_pasn *pasn = &wpa_s->pasn;
+ struct wpa_ssid *ssid = NULL;
+ struct wpabuf *frame;
+ int ret;
+
+ /* TODO: Currently support only ECC groups */
+ if (!dragonfly_suitable_group(group, 1)) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: Reject unsuitable group %u", group);
+ return -1;
+ }
+
+ ssid = wpa_config_get_network(wpa_s->conf, network_id);
+
+ switch (akmp) {
+ case WPA_KEY_MGMT_PASN:
+ break;
+#ifdef CONFIG_SAE
+ case WPA_KEY_MGMT_SAE:
+ if (!ssid) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: No network profile found for SAE");
+ return -1;
+ }
+ pasn->sae.state = SAE_NOTHING;
+ pasn->sae.send_confirm = 0;
+ pasn->ssid = ssid;
+ break;
+#endif /* CONFIG_SAE */
+#ifdef CONFIG_FILS
+ case WPA_KEY_MGMT_FILS_SHA256:
+ case WPA_KEY_MGMT_FILS_SHA384:
+ pasn->ssid = ssid;
+ break;
+#endif /* CONFIG_FILS */
+#ifdef CONFIG_IEEE80211R
+ case WPA_KEY_MGMT_FT_PSK:
+ case WPA_KEY_MGMT_FT_IEEE8021X:
+ case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
+ break;
+#endif /* CONFIG_IEEE80211R */
+ default:
+ wpa_printf(MSG_ERROR, "PASN: Unsupported AKMP=0x%x", akmp);
+ return -1;
+ }
+
+ pasn->ecdh = crypto_ecdh_init(group);
+ if (!pasn->ecdh) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed to init ECDH");
+ goto fail;
+ }
+
+ pasn->beacon_rsne_rsnxe = wpabuf_alloc(beacon_rsne_len +
+ beacon_rsnxe_len);
+ if (!pasn->beacon_rsne_rsnxe) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed storing beacon RSNE/RSNXE");
+ goto fail;
+ }
+
+ wpabuf_put_data(pasn->beacon_rsne_rsnxe, beacon_rsne, beacon_rsne_len);
+ if (beacon_rsnxe && beacon_rsnxe_len)
+ wpabuf_put_data(pasn->beacon_rsne_rsnxe, beacon_rsnxe,
+ beacon_rsnxe_len);
+
+ pasn->akmp = akmp;
+ pasn->cipher = cipher;
+ pasn->group = group;
+ pasn->freq = freq;
+ os_memcpy(pasn->bssid, bssid, ETH_ALEN);
+
+ wpa_printf(MSG_DEBUG,
+ "PASN: Init: " MACSTR " akmp=0x%x, cipher=0x%x, group=%u",
+ MAC2STR(pasn->bssid), pasn->akmp, pasn->cipher,
+ pasn->group);
+
+ frame = wpas_pasn_build_auth_1(wpa_s);
+ if (!frame) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed building 1st auth frame");
+ goto fail;
+ }
+
+ ret = wpa_drv_send_mlme(wpa_s, wpabuf_head(frame), wpabuf_len(frame), 0,
+ pasn->freq, 1000);
+
+ wpabuf_free(frame);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed sending 1st auth frame");
+ goto fail;
+ }
+
+ eloop_register_timeout(2, 0, wpas_pasn_auth_work_timeout, wpa_s, NULL);
+ return 0;
+
+fail:
+ return -1;
+}
+
+
+static struct wpa_bss * wpas_pasn_allowed(struct wpa_supplicant *wpa_s,
+ const u8 *bssid, int akmp, int cipher)
+{
+ struct wpa_bss *bss;
+ const u8 *rsne;
+ struct wpa_ie_data rsne_data;
+ int ret;
+
+ if (os_memcmp(wpa_s->bssid, bssid, ETH_ALEN) == 0) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: Not doing authentication with current BSS");
+ return NULL;
+ }
+
+ bss = wpa_bss_get_bssid(wpa_s, bssid);
+ if (!bss) {
+ wpa_printf(MSG_DEBUG, "PASN: BSS not found");
+ return NULL;
+ }
+
+ rsne = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+ if (!rsne) {
+ wpa_printf(MSG_DEBUG, "PASN: BSS without RSNE");
+ return NULL;
+ }
+
+ ret = wpa_parse_wpa_ie(rsne, *(rsne + 1) + 2, &rsne_data);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed parsing RSNE data");
+ return NULL;
+ }
+
+ if (!(rsne_data.key_mgmt & akmp) ||
+ !(rsne_data.pairwise_cipher & cipher)) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: AP does not support requested AKMP or cipher");
+ return NULL;
+ }
+
+ return bss;
+}
+
+
+static void wpas_pasn_auth_start_cb(struct wpa_radio_work *work, int deinit)
+{
+ struct wpa_supplicant *wpa_s = work->wpa_s;
+ struct wpa_pasn_auth_work *awork = work->ctx;
+ struct wpa_bss *bss;
+ const u8 *rsne, *rsnxe;
+ int ret;
+
+ wpa_printf(MSG_DEBUG, "PASN: auth_start_cb: deinit=%d", deinit);
+
+ if (deinit) {
+ if (work->started) {
+ eloop_cancel_timeout(wpas_pasn_auth_work_timeout,
+ wpa_s, NULL);
+ wpa_s->pasn_auth_work = NULL;
+ }
+ os_free(awork);
+ return;
+ }
+
+ /*
+ * It is possible that by the time the callback is called, the PASN
+ * authentication is not allowed, e.g., a connection with the AP was
+ * established.
+ */
+ bss = wpas_pasn_allowed(wpa_s, awork->bssid, awork->akmp,
+ awork->cipher);
+ if (!bss) {
+ wpa_printf(MSG_DEBUG, "PASN: auth_start_cb: Not allowed");
+ goto fail;
+ }
+
+ rsne = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+ if (!rsne) {
+ wpa_printf(MSG_DEBUG, "PASN: BSS without RSNE");
+ goto fail;
+ }
+
+ rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX);
+
+ ret = wpas_pasn_start(wpa_s, awork->bssid, awork->akmp, awork->cipher,
+ awork->group, bss->freq, rsne, *(rsne + 1) + 2,
+ rsnxe, rsnxe ? *(rsnxe + 1) + 2 : 0,
+ awork->network_id);
+ if (ret) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: Failed to start PASN authentication");
+ goto fail;
+ }
+
+ wpa_s->pasn_auth_work = work;
+ return;
+fail:
+ os_free(awork);
+ work->ctx = NULL;
+ radio_work_done(work);
+}
+
+
+int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s, const u8 *bssid,
+ int akmp, int cipher, u16 group, int network_id)
+{
+ struct wpa_pasn_auth_work *awork;
+ struct wpa_bss *bss;
+
+ wpa_printf(MSG_DEBUG, "PASN: Start: " MACSTR " akmp=0x%x, cipher=0x%x",
+ MAC2STR(bssid), akmp, cipher);
+
+ /*
+ * TODO: Consider modifying the offchannel logic to handle additional
+ * Management frames other then Action frames. For now allow PASN only
+ * with drivers that support off-channel TX.
+ */
+ if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX)) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: Driver does not support offchannel TX");
+ return -1;
+ }
+
+ if (radio_work_pending(wpa_s, "pasn-start-auth")) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: send_auth: Work is already pending");
+ return -1;
+ }
+
+ if (wpa_s->pasn_auth_work) {
+ wpa_printf(MSG_DEBUG, "PASN: send_auth: Already in progress");
+ return -1;
+ }
+
+ bss = wpas_pasn_allowed(wpa_s, bssid, akmp, cipher);
+ if (!bss)
+ return -1;
+
+ wpas_pasn_reset(wpa_s);
+
+ awork = os_zalloc(sizeof(*awork));
+ if (!awork)
+ return -1;
+
+ os_memcpy(awork->bssid, bssid, ETH_ALEN);
+ awork->akmp = akmp;
+ awork->cipher = cipher;
+ awork->group = group;
+ awork->network_id = network_id;
+
+ if (radio_add_work(wpa_s, bss->freq, "pasn-start-auth", 1,
+ wpas_pasn_auth_start_cb, awork) < 0) {
+ os_free(awork);
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "PASN: Auth work successfully added");
+ return 0;
+}
+
+
+void wpas_pasn_auth_stop(struct wpa_supplicant *wpa_s)
+{
+ struct wpas_pasn *pasn = &wpa_s->pasn;
+
+ if (!wpa_s->pasn.ecdh)
+ return;
+
+ wpa_printf(MSG_DEBUG, "PASN: Stopping authentication");
+
+ wpas_pasn_auth_status(wpa_s, pasn->bssid, pasn->akmp, pasn->cipher,
+ pasn->status);
+
+ wpas_pasn_reset(wpa_s);
+}
+
+
+int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
+ const struct ieee80211_mgmt *mgmt, size_t len)
+{
+ struct wpas_pasn *pasn = &wpa_s->pasn;
+ struct ieee802_11_elems elems;
+ struct wpa_ie_data rsn_data;
+ struct wpa_pasn_params_data pasn_params;
+ struct wpabuf *wrapped_data = NULL, *secret = NULL, *frame = NULL;
+ u8 mic[WPA_PASN_MAX_MIC_LEN], out_mic[WPA_PASN_MAX_MIC_LEN];
+ u8 mic_len;
+ u16 status;
+ int ret;
+ u16 fc = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
+ (WLAN_FC_STYPE_AUTH << 4));
+
+ if (!wpa_s->pasn_auth_work || !mgmt ||
+ len < offsetof(struct ieee80211_mgmt, u.auth.variable))
+ return -2;
+
+ /* Not an Authentication frame; do nothing */
+ if ((mgmt->frame_control & fc) != fc)
+ return -2;
+
+ /* Not our frame; do nothing */
+ if (os_memcmp(mgmt->da, wpa_s->own_addr, ETH_ALEN) != 0 ||
+ os_memcmp(mgmt->sa, pasn->bssid, ETH_ALEN) != 0 ||
+ os_memcmp(mgmt->bssid, pasn->bssid, ETH_ALEN) != 0)
+ return -2;
+
+ /* Not PASN; do nothing */
+ if (mgmt->u.auth.auth_alg != host_to_le16(WLAN_AUTH_PASN))
+ return -2;
+
+ if (mgmt->u.auth.auth_transaction !=
+ host_to_le16(pasn->trans_seq + 1)) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: RX: Invalid transaction sequence: (%u != %u)",
+ le_to_host16(mgmt->u.auth.auth_transaction),
+ pasn->trans_seq + 1);
+ return -1;
+ }
+
+ status = le_to_host16(mgmt->u.auth.status_code);
+
+ if (status != WLAN_STATUS_SUCCESS &&
+ status != WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: Authentication rejected - status=%u", status);
+ pasn->status = status;
+ wpas_pasn_auth_stop(wpa_s);
+ return -1;
+ }
+
+ if (ieee802_11_parse_elems(mgmt->u.auth.variable,
+ len - offsetof(struct ieee80211_mgmt,
+ u.auth.variable),
+ &elems, 0) == ParseFailed) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: Failed parsing Authentication frame");
+ goto fail;
+ }
+
+ /* Check that the MIC IE exists. Save it and zero out the memory */
+ mic_len = pasn_mic_len(pasn->akmp, pasn->cipher);
+ if (status == WLAN_STATUS_SUCCESS) {
+ if (!elems.mic || elems.mic_len != mic_len) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: Invalid MIC. Expecting len=%u",
+ mic_len);
+ goto fail;
+ } else {
+ os_memcpy(mic, elems.mic, mic_len);
+ /* TODO: Clean this up.. Should not be modifying the
+ * received message buffer. */
+ os_memset((u8 *) elems.mic, 0, mic_len);
+ }
+ }
+
+ if (!elems.pasn_params || !elems.pasn_params_len) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: Missing PASN Parameters IE");
+ goto fail;
+ }
+
+ ret = wpa_pasn_parse_parameter_ie(elems.pasn_params - 3,
+ elems.pasn_params_len + 3,
+ true, &pasn_params);
+ if (ret) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: Failed validation PASN of Parameters IE");
+ goto fail;
+ }
+
+ /* TODO: handle comeback flow */
+ if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: Authentication temporarily rejected");
+ goto fail;
+ }
+
+ ret = wpa_parse_wpa_ie(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
+ &rsn_data);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed parsing RNSE");
+ goto fail;
+ }
+
+ ret = wpa_pasn_validate_rsne(&rsn_data);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed validating RSNE");
+ goto fail;
+ }
+
+ if (pasn->akmp != rsn_data.key_mgmt ||
+ pasn->cipher != rsn_data.pairwise_cipher) {
+ wpa_printf(MSG_DEBUG, "PASN: Mismatch in AKMP/cipher");
+ goto fail;
+ }
+
+ if (pasn->group != pasn_params.group) {
+ wpa_printf(MSG_DEBUG, "PASN: Mismatch in group");
+ goto fail;
+ }
+
+ if (!pasn_params.pubkey || !pasn_params.pubkey_len) {
+ wpa_printf(MSG_DEBUG, "PASN: Invalid public key");
+ goto fail;
+ }
+
+ secret = crypto_ecdh_set_peerkey(pasn->ecdh, 0,
+ pasn_params.pubkey,
+ pasn_params.pubkey_len);
+
+ if (!secret) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed to derive shared secret");
+ goto fail;
+ }
+
+ if (pasn_params.wrapped_data_format != WPA_PASN_WRAPPED_DATA_NO) {
+ wrapped_data = ieee802_11_defrag(&elems,
+ WLAN_EID_EXTENSION,
+ WLAN_EID_EXT_WRAPPED_DATA);
+
+ if (!wrapped_data) {
+ wpa_printf(MSG_DEBUG, "PASN: Missing wrapped data");
+ goto fail;
+ }
+ }
+
+ ret = wpas_pasn_set_pmk(wpa_s, &rsn_data, &pasn_params, wrapped_data);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed to set PMK");
+ goto fail;
+ }
+
+ ret = pasn_pmk_to_ptk(pasn->pmk, pasn->pmk_len,
+ wpa_s->own_addr, pasn->bssid,
+ wpabuf_head(secret), wpabuf_len(secret),
+ &pasn->ptk, pasn->akmp, pasn->cipher,
+ WPA_KDK_MAX_LEN);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed to derive PTK");
+ goto fail;
+ }
+
+ wpabuf_free(wrapped_data);
+ wrapped_data = NULL;
+ wpabuf_free(secret);
+ secret = NULL;
+
+ /* Verify the MIC */
+ ret = pasn_mic(pasn->ptk.kck, pasn->akmp, pasn->cipher,
+ pasn->bssid, wpa_s->own_addr,
+ wpabuf_head(pasn->beacon_rsne_rsnxe),
+ wpabuf_len(pasn->beacon_rsne_rsnxe),
+ (u8 *) &mgmt->u.auth,
+ len - offsetof(struct ieee80211_mgmt, u.auth),
+ out_mic);
+
+ wpa_hexdump_key(MSG_DEBUG, "PASN: Frame MIC", mic, mic_len);
+ if (ret || os_memcmp(mic, out_mic, mic_len) != 0) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed MIC verification");
+ goto fail;
+ }
+
+ pasn->trans_seq++;
+
+ wpa_printf(MSG_DEBUG, "PASN: Success verifying Authentication frame");
+
+ frame = wpas_pasn_build_auth_3(wpa_s);
+ if (!frame) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed building 3rd auth frame");
+ goto fail;
+ }
+
+ ret = wpa_drv_send_mlme(wpa_s, wpabuf_head(frame), wpabuf_len(frame), 0,
+ pasn->freq, 100);
+ wpabuf_free(frame);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed sending 3st auth frame");
+ goto fail;
+ }
+
+ wpa_printf(MSG_DEBUG, "PASN: Success sending last frame. Store PTK");
+
+ ptksa_cache_add(wpa_s->ptksa, pasn->bssid, pasn->cipher,
+ dot11RSNAConfigPMKLifetime, &pasn->ptk);
+
+ forced_memzero(&pasn->ptk, sizeof(pasn->ptk));
+
+ pasn->status = WLAN_STATUS_SUCCESS;
+ return 0;
+fail:
+ wpa_printf(MSG_DEBUG, "PASN: Failed RX processing - terminating");
+ wpabuf_free(wrapped_data);
+ wpabuf_free(secret);
+
+ /*
+ * TODO: In case of an error the standard allows to silently drop
+ * the frame and terminate the authentication exchange. However, better
+ * reply to the AP with an error status.
+ */
+ pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ wpas_pasn_auth_stop(wpa_s);
+ return -1;
+}
+
+
+int wpas_pasn_auth_tx_status(struct wpa_supplicant *wpa_s,
+ const u8 *data, size_t data_len, u8 acked)
+
+{
+ struct wpas_pasn *pasn = &wpa_s->pasn;
+ const struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) data;
+ u16 fc = host_to_le16((WLAN_FC_TYPE_MGMT << 2) |
+ (WLAN_FC_STYPE_AUTH << 4));
+
+ wpa_printf(MSG_DEBUG, "PASN: auth_tx_status: acked=%u", acked);
+
+ if (!wpa_s->pasn_auth_work) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: auth_tx_status: no work in progress");
+ return -1;
+ }
+
+ if (!mgmt ||
+ data_len < offsetof(struct ieee80211_mgmt, u.auth.variable))
+ return -1;
+
+ /* Not an authentication frame; do nothing */
+ if ((mgmt->frame_control & fc) != fc)
+ return -1;
+
+ /* Not our frame; do nothing */
+ if (os_memcmp(mgmt->da, pasn->bssid, ETH_ALEN) ||
+ os_memcmp(mgmt->sa, wpa_s->own_addr, ETH_ALEN) ||
+ os_memcmp(mgmt->bssid, pasn->bssid, ETH_ALEN))
+ return -1;
+
+ /* Not PASN; do nothing */
+ if (mgmt->u.auth.auth_alg != host_to_le16(WLAN_AUTH_PASN))
+ return -1;
+
+ if (mgmt->u.auth.auth_transaction != host_to_le16(pasn->trans_seq)) {
+ wpa_printf(MSG_ERROR,
+ "PASN: Invalid transaction sequence: (%u != %u)",
+ pasn->trans_seq,
+ le_to_host16(mgmt->u.auth.auth_transaction));
+ return 0;
+ }
+
+ wpa_printf(MSG_ERROR,
+ "PASN: auth with trans_seq=%u, acked=%u", pasn->trans_seq,
+ acked);
+
+ /*
+ * Even if the frame was not acked, do not treat this is an error, and
+ * try to complete the flow, relying on the PASN timeout callback to
+ * clean up.
+ */
+ if (pasn->trans_seq == 3) {
+ wpa_printf(MSG_DEBUG, "PASN: auth complete with: " MACSTR,
+ MAC2STR(pasn->bssid));
+ /*
+ * Either frame was not ACKed or it was ACKed but the trans_seq
+ * != 1, i.e., not expecting an RX frame, so we are done.
+ */
+ wpas_pasn_auth_stop(wpa_s);
+ }
+
+ return 0;
+}
diff --git a/wpa_supplicant/robust_av.c b/wpa_supplicant/robust_av.c
index 1280f5d..f6da56e 100644
--- a/wpa_supplicant/robust_av.c
+++ b/wpa_supplicant/robust_av.c
@@ -48,18 +48,13 @@ void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av,
int wpas_send_mscs_req(struct wpa_supplicant *wpa_s)
{
struct wpabuf *buf;
- const u8 *ext_capab = NULL;
size_t buf_len;
int ret;
if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid)
return 0;
- if (wpa_s->current_bss)
- ext_capab = wpa_bss_get_ie(wpa_s->current_bss,
- WLAN_EID_EXT_CAPAB);
-
- if (!ext_capab || ext_capab[1] < 11 || !(ext_capab[12] & 0x20)) {
+ if (!wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS)) {
wpa_dbg(wpa_s, MSG_INFO,
"AP does not support MSCS - could not send MSCS Req");
return -1;
diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c
index a9c7b90..cf107eb 100644
--- a/wpa_supplicant/rrm.c
+++ b/wpa_supplicant/rrm.c
@@ -556,14 +556,14 @@ static int * wpas_add_channels(const struct oper_class_map *op,
static int * wpas_op_class_freqs(const struct oper_class_map *op,
struct hostapd_hw_modes *mode, int active)
{
- u8 channels_80mhz_5ghz[] = { 42, 58, 106, 122, 138, 155 };
- u8 channels_160mhz_5ghz[] = { 50, 114 };
+ u8 channels_80mhz_5ghz[] = { 42, 58, 106, 122, 138, 155, 171 };
+ u8 channels_160mhz_5ghz[] = { 50, 114, 163 };
u8 channels_80mhz_6ghz[] = { 7, 23, 39, 55, 71, 87, 103, 119, 135, 151,
167, 183, 199, 215 };
u8 channels_160mhz_6ghz[] = { 15, 47, 79, 111, 143, 175, 207 };
const u8 *channels = NULL;
size_t num_chan = 0;
- int is_6ghz = is_6ghz_op_class(op->op_class);
+ bool is_6ghz = is_6ghz_op_class(op->op_class);
/*
* When adding all channels in the operating class, 80 + 80 MHz
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 78371d3..c53474d 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -521,7 +521,7 @@ void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s)
{
struct wpabuf *default_ies = NULL;
u8 ext_capab[18];
- int ext_capab_len;
+ int ext_capab_len, frame_id;
enum wpa_driver_if_type type = WPA_IF_STATION;
#ifdef CONFIG_P2P
@@ -545,6 +545,20 @@ void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s)
wpas_mbo_scan_ie(wpa_s, default_ies);
#endif /* CONFIG_MBO */
+ if (type == WPA_IF_P2P_CLIENT)
+ frame_id = VENDOR_ELEM_PROBE_REQ_P2P;
+ else
+ frame_id = VENDOR_ELEM_PROBE_REQ;
+
+ if (wpa_s->vendor_elem[frame_id]) {
+ size_t len;
+
+ len = wpabuf_len(wpa_s->vendor_elem[frame_id]);
+ if (len > 0 && wpabuf_resize(&default_ies, len) == 0)
+ wpabuf_put_buf(default_ies,
+ wpa_s->vendor_elem[frame_id]);
+ }
+
if (default_ies)
wpa_drv_set_default_scan_ies(wpa_s, wpabuf_head(default_ies),
wpabuf_len(default_ies));
@@ -670,30 +684,38 @@ static int non_p2p_network_enabled(struct wpa_supplicant *wpa_s)
#endif /* CONFIG_P2P */
-static void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s,
- enum hostapd_hw_mode band,
- struct wpa_driver_scan_params *params,
- int is_6ghz)
+int wpa_add_scan_freqs_list(struct wpa_supplicant *wpa_s,
+ enum hostapd_hw_mode band,
+ struct wpa_driver_scan_params *params, bool is_6ghz)
{
/* Include only supported channels for the specified band */
struct hostapd_hw_modes *mode;
- int count, i;
+ int num_chans = 0;
+ int *freqs, i;
mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band, is_6ghz);
- if (mode == NULL) {
- /* No channels supported in this band - use empty list */
- params->freqs = os_zalloc(sizeof(int));
- return;
+ if (!mode)
+ return -1;
+
+ if (params->freqs) {
+ while (params->freqs[num_chans])
+ num_chans++;
}
- params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
- if (params->freqs == NULL)
- return;
- for (count = 0, i = 0; i < mode->num_channels; i++) {
+ freqs = os_realloc(params->freqs,
+ (num_chans + mode->num_channels + 1) * sizeof(int));
+ if (!freqs)
+ return -1;
+
+ params->freqs = freqs;
+ for (i = 0; i < mode->num_channels; i++) {
if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED)
continue;
- params->freqs[count++] = mode->channels[i].freq;
+ params->freqs[num_chans++] = mode->channels[i].freq;
}
+ params->freqs[num_chans] = 0;
+
+ return 0;
}
@@ -704,12 +726,16 @@ static void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s,
return; /* unknown what channels the driver supports */
if (params->freqs)
return; /* already using a limited channel set */
- if (wpa_s->setband == WPA_SETBAND_5G)
- wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A,
- params, 0);
- else if (wpa_s->setband == WPA_SETBAND_2G)
- wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G,
- params, 0);
+
+ if (wpa_s->setband_mask & WPA_SETBAND_5G)
+ wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params,
+ 0);
+ if (wpa_s->setband_mask & WPA_SETBAND_2G)
+ wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, params,
+ 0);
+ if (wpa_s->setband_mask & WPA_SETBAND_6G)
+ wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params,
+ 1);
}
@@ -1201,7 +1227,12 @@ ssid_list_set:
wpa_setband_scan_freqs(wpa_s, &params);
/* See if user specified frequencies. If so, scan only those. */
- if (wpa_s->conf->freq_list && !params.freqs) {
+ if (wpa_s->last_scan_req == INITIAL_SCAN_REQ &&
+ wpa_s->conf->initial_freq_list && !params.freqs) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "Optimize scan based on conf->initial_freq_list");
+ int_array_concat(&params.freqs, wpa_s->conf->initial_freq_list);
+ } else if (wpa_s->conf->freq_list && !params.freqs) {
wpa_dbg(wpa_s, MSG_DEBUG,
"Optimize scan based on conf->freq_list");
int_array_concat(&params.freqs, wpa_s->conf->freq_list);
diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h
index c9ce2ce..8eb5c73 100644
--- a/wpa_supplicant/scan.h
+++ b/wpa_supplicant/scan.h
@@ -86,5 +86,9 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s,
const u8 *ies, size_t ies_len, int rate,
int snr);
void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s);
+int wpa_add_scan_freqs_list(struct wpa_supplicant *wpa_s,
+ enum hostapd_hw_mode band,
+ struct wpa_driver_scan_params *params,
+ bool is_6ghz);
#endif /* SCAN_H */
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 9b4eeb9..c6cef5b 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -1881,13 +1881,11 @@ pfs_fail:
#endif /* CONFIG_DPP2 */
wpa_s->mscs_setup_done = false;
- if (wpa_s->current_bss && wpa_s->robust_av.valid_config) {
+ if (wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS) &&
+ wpa_s->robust_av.valid_config) {
struct wpabuf *mscs_ie;
size_t mscs_ie_len, buf_len, *wpa_ie_len, max_ie_len;
- if (!wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS))
- goto mscs_fail;
-
buf_len = 3 + /* MSCS descriptor IE header */
1 + /* Request type */
2 + /* User priority control */
@@ -2462,7 +2460,7 @@ static void wpa_obss_scan_freqs_list(struct wpa_supplicant *wpa_s,
int start, end;
mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
- HOSTAPD_MODE_IEEE80211G, 0);
+ HOSTAPD_MODE_IEEE80211G, false);
if (mode == NULL) {
/* No channels supported in this band - use empty list */
params->freqs = os_zalloc(sizeof(int));
diff --git a/wpa_supplicant/vs2005/eapol_test/eapol_test.vcproj b/wpa_supplicant/vs2005/eapol_test/eapol_test.vcproj
index af7b3fe..c92b8fd 100755
--- a/wpa_supplicant/vs2005/eapol_test/eapol_test.vcproj
+++ b/wpa_supplicant/vs2005/eapol_test/eapol_test.vcproj
@@ -215,7 +215,7 @@
>
</File>
<File
- RelativePath="..\..\blacklist.c"
+ RelativePath="..\..\bssid_ignore.c"
>
</File>
<File
@@ -231,6 +231,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\utils\config.c"
+ >
+ </File>
+ <File
RelativePath="..\..\config.c"
>
</File>
diff --git a/wpa_supplicant/vs2005/wpa_supplicant/wpa_supplicant.vcproj b/wpa_supplicant/vs2005/wpa_supplicant/wpa_supplicant.vcproj
index 51acab9..10c05b5 100755
--- a/wpa_supplicant/vs2005/wpa_supplicant/wpa_supplicant.vcproj
+++ b/wpa_supplicant/vs2005/wpa_supplicant/wpa_supplicant.vcproj
@@ -215,7 +215,7 @@
>
</File>
<File
- RelativePath="..\..\blacklist.c"
+ RelativePath="..\..\bssid_ignore.c"
>
</File>
<File
@@ -231,6 +231,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\utils\config.c"
+ >
+ </File>
+ <File
RelativePath="..\..\config.c"
>
</File>
diff --git a/wpa_supplicant/vs2005/wpasvc/wpasvc.vcproj b/wpa_supplicant/vs2005/wpasvc/wpasvc.vcproj
index 6fd8af8..82d9033 100755
--- a/wpa_supplicant/vs2005/wpasvc/wpasvc.vcproj
+++ b/wpa_supplicant/vs2005/wpasvc/wpasvc.vcproj
@@ -215,7 +215,7 @@
>
</File>
<File
- RelativePath="..\..\blacklist.c"
+ RelativePath="..\..\bssid_ignore.c"
>
</File>
<File
@@ -231,6 +231,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\utils\config.c"
+ >
+ </File>
+ <File
RelativePath="..\..\config.c"
>
</File>
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index 19f1eca..c4c6651 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -552,7 +552,7 @@ static int wnm_nei_get_chan(struct wpa_supplicant *wpa_s, u8 op_class, u8 chan)
freq = 2407 + chan * 5;
else if (chan == 14)
freq = 2484;
- else if (chan >= 36 && chan <= 169)
+ else if (chan >= 36 && chan <= 177)
freq = 5000 + chan * 5;
}
return freq;
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 813e4b3..b98a833 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -493,7 +493,8 @@ static char ** wpa_cli_complete_set(const char *str, int pos)
"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
"sae_groups", "dtim_period", "beacon_int",
"ap_vendor_elements", "ignore_old_scan_res", "freq_list",
- "scan_cur_freq", "sched_scan_interval",
+ "scan_cur_freq", "scan_res_valid_for_connect",
+ "sched_scan_interval",
"tdls_external_control", "osu_dir", "wowlan_triggers",
"p2p_search_delay", "mac_addr", "rand_addr_lifetime",
"preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
@@ -589,7 +590,8 @@ static char ** wpa_cli_complete_get(const char *str, int pos)
"wps_nfc_dev_pw_id", "ext_password_backend",
"p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
"dtim_period", "beacon_int", "ignore_old_scan_res",
- "scan_cur_freq", "sched_scan_interval",
+ "scan_cur_freq", "scan_res_valid_for_connect",
+ "sched_scan_interval",
"sched_scan_start_delay",
"tdls_external_control", "osu_dir", "wowlan_triggers",
"p2p_search_delay", "mac_addr", "rand_addr_lifetime",
@@ -1288,9 +1290,10 @@ static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
-static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
+static int wpa_cli_cmd_bssid_ignore(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
{
- return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
+ return wpa_cli_cmd(ctrl, "BSSID_IGNORE", 0, argc, argv);
}
@@ -1406,8 +1409,8 @@ static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
static const char *network_fields[] = {
- "ssid", "scan_ssid", "bssid", "bssid_blacklist",
- "bssid_whitelist", "psk", "proto", "key_mgmt",
+ "ssid", "scan_ssid", "bssid", "bssid_ignore",
+ "bssid_accept", "psk", "proto", "key_mgmt",
"bg_scan_period", "pairwise", "group", "auth_alg", "scan_freq",
"freq_list", "max_oper_chwidth", "ht40", "vht", "vht_center_freq1",
"vht_center_freq2", "ht", "edmg",
@@ -3066,6 +3069,20 @@ static int wpa_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc,
#ifdef CONFIG_DPP2
+static int wpa_cli_cmd_dpp_controller_start(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "DPP_CONTROLLER_START", 1, argc, argv);
+}
+
+
+static int wpa_cli_cmd_dpp_controller_stop(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_ctrl_command(ctrl, "DPP_CONTROLLER_STOP");
+}
+
+
static int wpa_cli_cmd_dpp_chirp(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
@@ -3158,6 +3175,30 @@ static int wpa_cli_cmd_all_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
}
+#ifdef CONFIG_PASN
+
+static int wpa_cli_cmd_pasn_auth_start(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "PASN_AUTH_START", 4, argc, argv);
+}
+
+
+static int wpa_cli_cmd_pasn_auth_stop(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "PASN_AUTH_STOP", 0, argc, argv);
+}
+
+static int wpa_cli_cmd_ptksa_cache_list(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ return wpa_cli_cmd(ctrl, "PTKSA_CACHE_LIST", 0, argc, argv);
+}
+
+#endif /* CONFIG_PASN */
+
+
enum wpa_cli_cmd_flags {
cli_cmd_flag_none = 0x00,
cli_cmd_flag_sensitive = 0x01
@@ -3284,11 +3325,15 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
{ "bssid", wpa_cli_cmd_bssid, wpa_cli_complete_network_id,
cli_cmd_flag_none,
"<network id> <BSSID> = set preferred BSSID for an SSID" },
- { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
+ { "bssid_ignore", wpa_cli_cmd_bssid_ignore, wpa_cli_complete_bss,
+ cli_cmd_flag_none,
+ "<BSSID> = add a BSSID to the list of temporarily ignored BSSs\n"
+ "bssid_ignore clear = clear the list of temporarily ignored BSSIDs\n"
+ "bssid_ignore = display the list of temporarily ignored BSSIDs" },
+ { "blacklist", /* deprecated alias for bssid_ignore */
+ wpa_cli_cmd_bssid_ignore, wpa_cli_complete_bss,
cli_cmd_flag_none,
- "<BSSID> = add a BSSID to the blacklist\n"
- "blacklist clear = clear the blacklist\n"
- "blacklist = display the blacklist" },
+ "= deprecated alias for bssid_ignore" },
{ "log_level", wpa_cli_cmd_log_level, NULL,
cli_cmd_flag_none,
"<level> [<timestamp>] = update the log level/timestamp\n"
@@ -3820,6 +3865,12 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
cli_cmd_flag_none,
"*|<id> = remove DPP pkex information" },
#ifdef CONFIG_DPP2
+ { "dpp_controller_start", wpa_cli_cmd_dpp_controller_start, NULL,
+ cli_cmd_flag_none,
+ "[tcp_port=<port>] [role=..] = start DPP controller" },
+ { "dpp_controller_stop", wpa_cli_cmd_dpp_controller_stop, NULL,
+ cli_cmd_flag_none,
+ "= stop DPP controller" },
{ "dpp_chirp", wpa_cli_cmd_dpp_chirp, NULL,
cli_cmd_flag_none,
"own=<BI ID> iter=<count> = start DPP chirp" },
@@ -3830,6 +3881,17 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
#endif /* CONFIG_DPP */
{ "all_bss", wpa_cli_cmd_all_bss, NULL, cli_cmd_flag_none,
"= list all BSS entries (scan results)" },
+#ifdef CONFIG_PASN
+ { "pasn_auth_start", wpa_cli_cmd_pasn_auth_start, NULL,
+ cli_cmd_flag_none,
+ "bssid=<BSSID> akmp=<WPA key mgmt> cipher=<WPA cipher> group=<group> nid=<network id> = Start PASN authentication" },
+ { "pasn_auth_stop", wpa_cli_cmd_pasn_auth_stop, NULL,
+ cli_cmd_flag_none,
+ "= Stop PASN authentication" },
+ { "ptksa_cache_list", wpa_cli_cmd_ptksa_cache_list, NULL,
+ cli_cmd_flag_none,
+ "= Get the PTKSA Cache" },
+#endif /* CONFIG_PASN */
{ NULL, NULL, NULL, cli_cmd_flag_none, NULL }
};
@@ -4152,6 +4214,8 @@ static void wpa_cli_action_process(const char *msg)
wpa_cli_exec(action_file, ifname, pos);
} else if (str_starts(pos, WPS_EVENT_ACTIVE)) {
wpa_cli_exec(action_file, ifname, pos);
+ } else if (str_starts(pos, WPS_EVENT_OVERLAP)) {
+ wpa_cli_exec(action_file, ifname, pos);
} else if (str_starts(pos, WPS_EVENT_PIN_ACTIVE)) {
wpa_cli_exec(action_file, ifname, pos);
} else if (str_starts(pos, WPS_EVENT_CANCEL)) {
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index ddd43e5..e1497e1 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -41,9 +41,10 @@
#include "common/hw_features_common.h"
#include "common/gas_server.h"
#include "common/dpp.h"
+#include "common/ptksa_cache.h"
#include "p2p/p2p.h"
#include "fst/fst.h"
-#include "blacklist.h"
+#include "bssid_ignore.h"
#include "wpas_glue.h"
#include "wps_supplicant.h"
#include "ibss_rsn.h"
@@ -222,7 +223,7 @@ static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx)
bssid = wpa_s->pending_bssid;
wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.",
MAC2STR(bssid));
- wpa_blacklist_add(wpa_s, bssid);
+ wpa_bssid_ignore_add(wpa_s, bssid);
wpa_sm_notify_disassoc(wpa_s->wpa);
wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
wpa_s->reassociate = 1;
@@ -290,7 +291,7 @@ void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s)
{
wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout");
eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
- wpa_blacklist_del(wpa_s, wpa_s->bssid);
+ wpa_bssid_ignore_del(wpa_s, wpa_s->bssid);
os_free(wpa_s->last_con_fail_realm);
wpa_s->last_con_fail_realm = NULL;
wpa_s->last_con_fail_realm_len = 0;
@@ -573,9 +574,15 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
wmm_ac_clear_saved_tspecs(wpa_s);
pmksa_candidate_free(wpa_s->wpa);
+ ptksa_cache_deinit(wpa_s->ptksa);
+ wpa_s->ptksa = NULL;
wpa_sm_deinit(wpa_s->wpa);
wpa_s->wpa = NULL;
- wpa_blacklist_clear(wpa_s);
+ wpa_bssid_ignore_clear(wpa_s);
+
+#ifdef CONFIG_PASN
+ wpas_pasn_auth_stop(wpa_s);
+#endif /* CONFIG_PASN */
wpa_bss_deinit(wpa_s);
@@ -726,6 +733,10 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
dpp_global_deinit(wpa_s->dpp);
wpa_s->dpp = NULL;
#endif /* CONFIG_DPP */
+
+#ifdef CONFIG_PASN
+ wpas_pasn_auth_stop(wpa_s);
+#endif /* CONFIG_PASN */
}
@@ -1088,13 +1099,19 @@ static void wpa_supplicant_terminate(int sig, void *signal_ctx)
void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s)
{
enum wpa_states old_state = wpa_s->wpa_state;
+ enum wpa_states new_state;
+
+ if (old_state == WPA_SCANNING)
+ new_state = WPA_SCANNING;
+ else
+ new_state = WPA_DISCONNECTED;
wpa_s->pairwise_cipher = 0;
wpa_s->group_cipher = 0;
wpa_s->mgmt_group_cipher = 0;
wpa_s->key_mgmt = 0;
if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED)
- wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
+ wpa_supplicant_set_state(wpa_s, new_state);
if (wpa_s->wpa_state != old_state)
wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state);
@@ -1189,7 +1206,7 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s)
wpa_s->reassociate = 1;
wpa_supplicant_req_scan(wpa_s, 0, 0);
}
- wpa_blacklist_clear(wpa_s);
+ wpa_bssid_ignore_clear(wpa_s);
wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed");
return 0;
}
@@ -1639,7 +1656,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
wpas_get_ssid_pmf(wpa_s, ssid));
#ifdef CONFIG_OCV
- wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
+ (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
+ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCV, ssid->ocv);
#endif /* CONFIG_OCV */
sae_pwe = wpa_s->conf->sae_pwe;
if (ssid->sae_password_id && sae_pwe != 3)
@@ -2126,6 +2145,24 @@ static void wpa_s_clear_sae_rejected(struct wpa_supplicant *wpa_s)
}
+int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Could not restore permanent MAC address");
+ return -1;
+ }
+ wpa_s->mac_addr_changed = 0;
+ if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "Could not update MAC address information");
+ return -1;
+ }
+ wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
+ return 0;
+}
+
+
static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit);
/**
@@ -2186,18 +2223,8 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
return;
wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
} else if (rand_style == 0 && wpa_s->mac_addr_changed) {
- if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) {
- wpa_msg(wpa_s, MSG_INFO,
- "Could not restore permanent MAC address");
- return;
- }
- wpa_s->mac_addr_changed = 0;
- if (wpa_supplicant_update_mac_addr(wpa_s) < 0) {
- wpa_msg(wpa_s, MSG_INFO,
- "Could not update MAC address information");
+ if (wpas_restore_permanent_mac_addr(wpa_s) < 0)
return;
- }
- wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address");
}
wpa_s->last_ssid = ssid;
@@ -2419,6 +2446,8 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s,
if (!mode)
return;
+ freq->channel = channel;
+
is_24ghz = hw_mode == HOSTAPD_MODE_IEEE80211G ||
hw_mode == HOSTAPD_MODE_IEEE80211B;
@@ -3193,13 +3222,11 @@ pfs_fail:
wpa_ie_len += wpa_s->rsnxe_len;
}
- if (bss && wpa_s->robust_av.valid_config) {
+ if (wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS) &&
+ wpa_s->robust_av.valid_config) {
struct wpabuf *mscs_ie;
size_t mscs_ie_len, buf_len;
- if (!wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS))
- goto mscs_fail;
-
buf_len = 3 + /* MSCS descriptor IE header */
1 + /* Request type */
2 + /* User priority control */
@@ -3395,7 +3422,7 @@ get_supported_edmg(struct wpa_supplicant *wpa_s,
if (hw_mode == NUM_HOSTAPD_MODES)
goto fail;
- mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, 0);
+ mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false);
if (!mode)
goto fail;
@@ -3487,6 +3514,20 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
os_memset(&params, 0, sizeof(params));
wpa_s->reassociate = 0;
wpa_s->eap_expected_failure = 0;
+
+ /* Starting new association, so clear the possibly used WPA IE from the
+ * previous association. */
+ wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
+ wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
+ wpa_s->rsnxe_len = 0;
+ wpa_s->mscs_setup_done = false;
+
+ wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
+ if (!wpa_ie) {
+ wpas_connect_work_done(wpa_s);
+ return;
+ }
+
if (bss &&
(!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) {
#ifdef CONFIG_IEEE80211R
@@ -3535,19 +3576,6 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
wpa_supplicant_cancel_scan(wpa_s);
- /* Starting new association, so clear the possibly used WPA IE from the
- * previous association. */
- wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
- wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0);
- wpa_s->rsnxe_len = 0;
- wpa_s->mscs_setup_done = false;
-
- wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
- if (!wpa_ie) {
- wpas_connect_work_done(wpa_s);
- return;
- }
-
wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL);
use_crypt = 1;
cipher_pairwise = wpa_s->pairwise_cipher;
@@ -5111,6 +5139,7 @@ wpa_supplicant_alloc(struct wpa_supplicant *parent)
wpa_s->parent = parent ? parent : wpa_s;
wpa_s->p2pdev = wpa_s->parent;
wpa_s->sched_scanning = 0;
+ wpa_s->setband_mask = WPA_SETBAND_AUTO;
dl_list_init(&wpa_s->bss_tmp_disallowed);
dl_list_init(&wpa_s->fils_hlp_req);
@@ -5855,7 +5884,7 @@ static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
dl_list_for_each(tmp, &radio->work, struct wpa_radio_work,
list) {
if (os_strcmp(tmp->type, "scan") == 0 &&
- radio->external_scan_running &&
+ external_scan_running(radio) &&
(((struct wpa_driver_scan_params *)
tmp->ctx)->only_new_results ||
tmp->wpa_s->clear_driver_scan_cache))
@@ -5911,7 +5940,7 @@ static struct wpa_radio_work * radio_work_get_next_work(struct wpa_radio *radio)
* rejected by kernel.
*/
if (os_strcmp(tmp->type, "scan") == 0 &&
- radio->external_scan_running &&
+ external_scan_running(radio) &&
(((struct wpa_driver_scan_params *)
tmp->ctx)->only_new_results ||
tmp->wpa_s->clear_driver_scan_cache))
@@ -5950,7 +5979,7 @@ static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx)
if (work->started)
return; /* already started and still in progress */
- if (wpa_s && wpa_s->radio->external_scan_running) {
+ if (wpa_s && external_scan_running(wpa_s->radio)) {
wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes");
return;
}
@@ -6046,6 +6075,10 @@ static void radio_remove_interface(struct wpa_supplicant *wpa_s)
wpa_s->ifname, radio->name);
dl_list_del(&wpa_s->radio_list);
radio_remove_works(wpa_s, NULL, 0);
+ /* If the interface that triggered the external scan was removed, the
+ * external scan is no longer running. */
+ if (wpa_s == radio->external_scan_req_interface)
+ radio->external_scan_req_interface = NULL;
wpa_s->radio = NULL;
if (!dl_list_empty(&radio->ifaces))
return; /* Interfaces remain for this radio */
@@ -6667,8 +6700,12 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s,
wpa_s->disconnected = 1;
if (wpa_s->drv_priv) {
- /* Don't deauthenticate if WoWLAN is enabled */
- if (!wpa_drv_get_wowlan(wpa_s)) {
+ /*
+ * Don't deauthenticate if WoWLAN is enable and not explicitly
+ * been configured to disconnect.
+ */
+ if (!wpa_drv_get_wowlan(wpa_s) ||
+ wpa_s->conf->wowlan_disconnect_on_deinit) {
wpa_supplicant_deauthenticate(
wpa_s, WLAN_REASON_DEAUTH_LEAVING);
@@ -7369,7 +7406,7 @@ static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s)
continue;
if (bss->ssid_len == cbss->ssid_len &&
os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 &&
- !wpa_blacklist_is_blacklisted(wpa_s, bss->bssid)) {
+ !wpa_bssid_ignore_is_listed(wpa_s, bss->bssid)) {
add_freq(freqs, &num_freqs, bss->freq);
if (num_freqs == max_freqs)
break;
@@ -7399,7 +7436,7 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL);
/*
- * There is no point in blacklisting the AP if this event is
+ * There is no point in ignoring the AP temporarily if this event is
* generated based on local request to disconnect.
*/
if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) {
@@ -7416,13 +7453,13 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
}
/*
- * Add the failed BSSID into the blacklist and speed up next scan
+ * Add the failed BSSID into the ignore list and speed up next scan
* attempt if there could be other APs that could accept association.
*/
- count = wpa_blacklist_add(wpa_s, bssid);
+ count = wpa_bssid_ignore_add(wpa_s, bssid);
if (count == 1 && wpa_s->current_bss) {
/*
- * This BSS was not in the blacklist before. If there is
+ * This BSS was not in the ignore list before. If there is
* another BSS available for the same ESS, we should try that
* next. Otherwise, we may as well try this one once more
* before allowing other, likely worse, ESSes to be considered.
@@ -7431,7 +7468,7 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
if (freqs) {
wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS "
"has been seen; try it next");
- wpa_blacklist_add(wpa_s, bssid);
+ wpa_bssid_ignore_add(wpa_s, bssid);
/*
* On the next scan, go through only the known channels
* used in this ESS based on previous scans to speed up
@@ -8054,7 +8091,7 @@ int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
u16 num_modes, enum hostapd_hw_mode mode,
- int is_6ghz)
+ bool is_6ghz)
{
u16 i;
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 46f7875..e3ae771 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -366,7 +366,14 @@ fast_reauth=1
# Password (and passphrase, etc.) backend for external storage
# format: <backend name>[:<optional backend parameters>]
+# Test backend which stores passwords in memory. Should only be used for
+# development purposes.
#ext_password_backend=test:pw1=password|pw2=testing
+# File-based backend which reads passwords from a file. The parameter
+# identifies the file to read passwords from. The password file follows the
+# format of wpa_supplicant.conf and accepts simple `key=passphrase` formatted
+# passwords.
+#ext_password_backend=file:/path/to/passwords.conf
# Disable P2P functionality
@@ -458,6 +465,9 @@ fast_reauth=1
# 1: Scan current operating frequency if another VIF on the same radio
# is already associated.
+# Seconds to consider old scan results valid for association (default: 5)
+#scan_res_valid_for_connect=5
+
# MAC address policy default
# 0 = use permanent MAC address
# 1 = use random MAC address for each ESS connection
@@ -981,7 +991,8 @@ fast_reauth=1
# This is a countermeasure against multi-channel man-in-the-middle attacks.
# Enabling this automatically also enables ieee80211w, if not yet enabled.
# 0 = disabled (default)
-# 1 = enabled
+# 1 = enabled if wpa_supplicant's SME in use. Otherwise enabled only when the
+# driver indicates support for operating channel validation.
#ocv=1
#
# auth_alg: list of allowed IEEE 802.11 authentication algorithms
@@ -1482,8 +1493,11 @@ fast_reauth=1
# 2: do not allow PFS to be used
#dpp_pfs=0
-# Whether Beacon protection is enabled
-# This depends on management frame protection (ieee80211w) being enabled.
+# Whether beacon protection is enabled
+# This depends on management frame protection (ieee80211w) being enabled and
+# beacon protection support indication from the driver.
+# 0 = disabled (default)
+# 1 = enabled
#beacon_prot=0
# OWE DH Group
@@ -2006,12 +2020,12 @@ network={
key_mgmt=NONE
}
-# Example configuration blacklisting two APs - these will be ignored
+# Example configuration ignoring two APs - these will be ignored
# for this network.
network={
ssid="example"
psk="very secret passphrase"
- bssid_blacklist=02:11:22:33:44:55 02:22:aa:44:55:66
+ bssid_ignore=02:11:22:33:44:55 02:22:aa:44:55:66
}
# Example configuration limiting AP selection to a specific set of APs;
@@ -2019,7 +2033,7 @@ network={
network={
ssid="example"
psk="very secret passphrase"
- bssid_whitelist=02:55:ae:bc:00:00/ff:ff:ff:ff:00:00 00:00:77:66:55:44/00:00:ff:ff:ff:ff
+ bssid_accept=02:55:ae:bc:00:00/ff:ff:ff:ff:00:00 00:00:77:66:55:44/00:00:ff:ff:ff:ff
}
# Example config file that will only scan on channel 36.
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index ffaacf9..7d14b62 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -14,6 +14,8 @@
#include "common/defs.h"
#include "common/sae.h"
#include "common/wpa_ctrl.h"
+#include "crypto/sha384.h"
+#include "eapol_supp/eapol_supp_sm.h"
#include "wps/wps_defs.h"
#include "config_ssid.h"
#include "wmm_ac.h"
@@ -47,9 +49,6 @@ struct ctrl_iface_global_priv;
struct wpas_dbus_priv;
struct wpas_binder_priv;
-/* How many seconds to consider old scan results valid for association. */
-#define SCAN_RES_VALID_FOR_CONNECT 5
-
/**
* struct wpa_interface - Parameters for wpa_supplicant_add_iface()
*/
@@ -330,12 +329,23 @@ struct wpa_global {
struct wpa_radio {
char name[16]; /* from driver_ops get_radio_name() or empty if not
* available */
- unsigned int external_scan_running:1;
+ /** NULL if no external scan running. */
+ struct wpa_supplicant *external_scan_req_interface;
unsigned int num_active_works;
struct dl_list ifaces; /* struct wpa_supplicant::radio_list entries */
struct dl_list work; /* struct wpa_radio_work::list entries */
};
+/**
+ * Checks whether an external scan is running on a given radio.
+ * @radio: Pointer to radio struct
+ * Returns: true if an external scan is running, false otherwise.
+ */
+static inline bool external_scan_running(struct wpa_radio *radio)
+{
+ return radio && radio->external_scan_req_interface;
+}
+
#define MAX_ACTIVE_WORKS 2
@@ -514,6 +524,54 @@ struct robust_av_data {
bool valid_config;
};
+#ifdef CONFIG_PASN
+
+struct pasn_fils {
+ u8 nonce[FILS_NONCE_LEN];
+ u8 anonce[FILS_NONCE_LEN];
+ u8 session[FILS_SESSION_LEN];
+ u8 erp_pmkid[PMKID_LEN];
+ bool completed;
+};
+
+struct wpas_pasn {
+ int akmp;
+ int cipher;
+ u16 group;
+ int freq;
+
+ u8 trans_seq;
+ u8 status;
+
+ u8 bssid[ETH_ALEN];
+ size_t pmk_len;
+ u8 pmk[PMK_LEN_MAX];
+ bool using_pmksa;
+
+ u8 hash[SHA384_MAC_LEN];
+
+ struct wpabuf *beacon_rsne_rsnxe;
+ struct wpa_ptk ptk;
+ struct crypto_ecdh *ecdh;
+
+#ifdef CONFIG_SAE
+ struct sae_data sae;
+#endif /* CONFIG_SAE */
+
+ struct wpa_ssid *ssid;
+
+#ifdef CONFIG_FILS
+ struct pasn_fils fils;
+#endif /* CONFIG_FILS */
+
+#ifdef CONFIG_IEEE80211R
+ u8 pmk_r1[PMK_LEN_MAX];
+ size_t pmk_r1_len;
+ u8 pmk_r1_name[WPA_PMK_NAME_LEN];
+#endif /* CONFIG_IEEE80211R */
+};
+#endif /* CONFIG_PASN */
+
/**
* struct wpa_supplicant - Internal data for wpa_supplicant interface
*
@@ -594,7 +652,7 @@ struct wpa_supplicant {
struct wpa_ssid_value *disallow_aps_ssid;
size_t disallow_aps_ssid_count;
- enum set_band setband;
+ u32 setband_mask;
/* Preferred network for the next connection attempt */
struct wpa_ssid *next_ssid;
@@ -619,6 +677,7 @@ struct wpa_supplicant {
void (*scan_res_handler)(struct wpa_supplicant *wpa_s,
struct wpa_scan_results *scan_res);
+ void (*scan_res_fail_handler)(struct wpa_supplicant *wpa_s);
struct dl_list bss; /* struct wpa_bss::list */
struct dl_list bss_id; /* struct wpa_bss::list_id */
size_t num_bss;
@@ -638,6 +697,8 @@ struct wpa_supplicant {
int interface_removed; /* whether the network interface has been
* removed */
struct wpa_sm *wpa;
+ struct ptksa_cache *ptksa;
+
struct eapol_sm *eapol;
struct ctrl_iface_priv *ctrl_iface;
@@ -664,7 +725,7 @@ struct wpa_supplicant {
unsigned int keys_cleared; /* bitfield of key indexes that the driver is
* known not to be configured with a key */
- struct wpa_blacklist *blacklist;
+ struct wpa_bssid_ignore *bssid_ignore;
/* Number of connection failures since last successful connection */
unsigned int consecutive_conn_failures;
@@ -772,7 +833,7 @@ struct wpa_supplicant {
struct wps_er *wps_er;
unsigned int wps_run;
struct os_reltime wps_pin_start_time;
- int blacklist_cleared;
+ bool bssid_ignore_cleared;
struct wpabuf *pending_eapol_rx;
struct os_reltime pending_eapol_rx_time;
@@ -1331,6 +1392,11 @@ struct wpa_supplicant {
unsigned int multi_ap_fronthaul:1;
struct robust_av_data robust_av;
bool mscs_setup_done;
+
+#ifdef CONFIG_PASN
+ struct wpas_pasn pasn;
+ struct wpa_radio_work *pasn_auth_work;
+#endif /* CONFIG_PASN */
};
@@ -1359,6 +1425,7 @@ int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, struct wpa_ssid *ssid,
u8 *wpa_ie, size_t *wpa_ie_len);
+int wpas_restore_permanent_mac_addr(struct wpa_supplicant *wpa_s);
void wpa_supplicant_associate(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss,
struct wpa_ssid *ssid);
@@ -1620,7 +1687,7 @@ int wpas_sched_scan_plans_set(struct wpa_supplicant *wpa_s, const char *cmd);
struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes,
u16 num_modes, enum hostapd_hw_mode mode,
- int is_6ghz);
+ bool is_6ghz);
void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid,
unsigned int sec, int rssi_threshold);
@@ -1652,4 +1719,13 @@ void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s,
void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid,
const u8 *ies, size_t ies_len);
+int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s,
+ const u8 *bssid, int akmp, int cipher,
+ u16 group, int network_id);
+void wpas_pasn_auth_stop(struct wpa_supplicant *wpa_s);
+int wpas_pasn_auth_tx_status(struct wpa_supplicant *wpa_s,
+ const u8 *data, size_t data_len, u8 acked);
+int wpas_pasn_auth_rx(struct wpa_supplicant *wpa_s,
+ const struct ieee80211_mgmt *mgmt, size_t len);
+
#endif /* WPA_SUPPLICANT_I_H */
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index a9a66ba..240e3d2 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -16,6 +16,7 @@
#include "config.h"
#include "l2_packet/l2_packet.h"
#include "common/wpa_common.h"
+#include "common/ptksa_cache.h"
#include "wpa_supplicant_i.h"
#include "driver_i.h"
#include "rsn_supp/pmksa_cache.h"
@@ -777,6 +778,8 @@ static int wpa_supplicant_tdls_peer_addset(
const u8 *supp_rates, size_t supp_rates_len,
const struct ieee80211_ht_capabilities *ht_capab,
const struct ieee80211_vht_capabilities *vht_capab,
+ const struct ieee80211_he_capabilities *he_capab,
+ size_t he_capab_len,
u8 qosinfo, int wmm, const u8 *ext_capab, size_t ext_capab_len,
const u8 *supp_channels, size_t supp_channels_len,
const u8 *supp_oper_classes, size_t supp_oper_classes_len)
@@ -800,6 +803,8 @@ static int wpa_supplicant_tdls_peer_addset(
params.ht_capabilities = ht_capab;
params.vht_capabilities = vht_capab;
+ params.he_capab = he_capab;
+ params.he_capab_len = he_capab_len;
params.qosinfo = qosinfo;
params.listen_interval = 0;
params.supp_rates = supp_rates;
@@ -1341,6 +1346,15 @@ static void wpa_supplicant_transition_disable(void *_wpa_s, u8 bitmap)
#endif /* CONFIG_NO_CONFIG_WRITE */
}
+
+static void wpa_supplicant_store_ptk(void *ctx, u8 *addr, int cipher,
+ u32 life_time, const struct wpa_ptk *ptk)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+
+ ptksa_cache_add(wpa_s->ptksa, addr, cipher, life_time, ptk);
+}
+
#endif /* CONFIG_NO_WPA */
@@ -1348,9 +1362,20 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
{
#ifndef CONFIG_NO_WPA
struct wpa_sm_ctx *ctx;
+
+ wpa_s->ptksa = ptksa_cache_init();
+ if (!wpa_s->ptksa) {
+ wpa_printf(MSG_ERROR, "Failed to allocate PTKSA");
+ return -1;
+ }
+
ctx = os_zalloc(sizeof(*ctx));
if (ctx == NULL) {
wpa_printf(MSG_ERROR, "Failed to allocate WPA context.");
+
+ ptksa_cache_deinit(wpa_s->ptksa);
+ wpa_s->ptksa = NULL;
+
return -1;
}
@@ -1394,12 +1419,15 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
ctx->fils_hlp_rx = wpa_supplicant_fils_hlp_rx;
ctx->channel_info = wpa_supplicant_channel_info;
ctx->transition_disable = wpa_supplicant_transition_disable;
+ ctx->store_ptk = wpa_supplicant_store_ptk;
wpa_s->wpa = wpa_sm_init(ctx);
if (wpa_s->wpa == NULL) {
- wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
- "machine");
+ wpa_printf(MSG_ERROR,
+ "Failed to initialize WPA state machine");
os_free(ctx);
+ ptksa_cache_deinit(wpa_s->ptksa);
+ wpa_s->ptksa = NULL;
return -1;
}
#endif /* CONFIG_NO_WPA */
@@ -1449,7 +1477,16 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
conf.fils_cache_id =
wpa_bss_get_fils_cache_id(wpa_s->current_bss);
#endif /* CONFIG_FILS */
- conf.beacon_prot = ssid->beacon_prot;
+ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION) ||
+ (wpa_s->drv_flags2 &
+ WPA_DRIVER_FLAGS2_BEACON_PROTECTION_CLIENT))
+ conf.beacon_prot = ssid->beacon_prot;
+
+#ifdef CONFIG_PASN
+#ifdef CONFIG_TESTING_OPTIONS
+ conf.force_kdk_derivation = wpa_s->conf->force_kdk_derivation;
+#endif /* CONFIG_TESTING_OPTIONS */
+#endif /* CONFIG_PASN */
}
wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL);
}
diff --git a/wpa_supplicant/wpas_module_tests.c b/wpa_supplicant/wpas_module_tests.c
index 1c136f7..ce5398c 100644
--- a/wpa_supplicant/wpas_module_tests.c
+++ b/wpa_supplicant/wpas_module_tests.c
@@ -11,77 +11,77 @@
#include "utils/common.h"
#include "utils/module_tests.h"
#include "wpa_supplicant_i.h"
-#include "blacklist.h"
+#include "bssid_ignore.h"
-static int wpas_blacklist_module_tests(void)
+static int wpas_bssid_ignore_module_tests(void)
{
struct wpa_supplicant wpa_s;
int ret = -1;
os_memset(&wpa_s, 0, sizeof(wpa_s));
- wpa_blacklist_clear(&wpa_s);
+ wpa_bssid_ignore_clear(&wpa_s);
- if (wpa_blacklist_get(NULL, NULL) != NULL ||
- wpa_blacklist_get(NULL, (u8 *) "123456") != NULL ||
- wpa_blacklist_get(&wpa_s, NULL) != NULL ||
- wpa_blacklist_get(&wpa_s, (u8 *) "123456") != NULL)
+ if (wpa_bssid_ignore_get(NULL, NULL) != NULL ||
+ wpa_bssid_ignore_get(NULL, (u8 *) "123456") != NULL ||
+ wpa_bssid_ignore_get(&wpa_s, NULL) != NULL ||
+ wpa_bssid_ignore_get(&wpa_s, (u8 *) "123456") != NULL)
goto fail;
- if (wpa_blacklist_add(NULL, NULL) == 0 ||
- wpa_blacklist_add(NULL, (u8 *) "123456") == 0 ||
- wpa_blacklist_add(&wpa_s, NULL) == 0)
+ if (wpa_bssid_ignore_add(NULL, NULL) == 0 ||
+ wpa_bssid_ignore_add(NULL, (u8 *) "123456") == 0 ||
+ wpa_bssid_ignore_add(&wpa_s, NULL) == 0)
goto fail;
- if (wpa_blacklist_del(NULL, NULL) == 0 ||
- wpa_blacklist_del(NULL, (u8 *) "123456") == 0 ||
- wpa_blacklist_del(&wpa_s, NULL) == 0 ||
- wpa_blacklist_del(&wpa_s, (u8 *) "123456") == 0)
+ if (wpa_bssid_ignore_del(NULL, NULL) == 0 ||
+ wpa_bssid_ignore_del(NULL, (u8 *) "123456") == 0 ||
+ wpa_bssid_ignore_del(&wpa_s, NULL) == 0 ||
+ wpa_bssid_ignore_del(&wpa_s, (u8 *) "123456") == 0)
goto fail;
- if (wpa_blacklist_add(&wpa_s, (u8 *) "111111") < 0 ||
- wpa_blacklist_add(&wpa_s, (u8 *) "111111") < 0 ||
- wpa_blacklist_add(&wpa_s, (u8 *) "222222") < 0 ||
- wpa_blacklist_add(&wpa_s, (u8 *) "333333") < 0 ||
- wpa_blacklist_add(&wpa_s, (u8 *) "444444") < 0 ||
- wpa_blacklist_del(&wpa_s, (u8 *) "333333") < 0 ||
- wpa_blacklist_del(&wpa_s, (u8 *) "xxxxxx") == 0 ||
- wpa_blacklist_get(&wpa_s, (u8 *) "xxxxxx") != NULL ||
- wpa_blacklist_get(&wpa_s, (u8 *) "111111") == NULL ||
- wpa_blacklist_get(&wpa_s, (u8 *) "222222") == NULL ||
- wpa_blacklist_get(&wpa_s, (u8 *) "444444") == NULL ||
- wpa_blacklist_del(&wpa_s, (u8 *) "111111") < 0 ||
- wpa_blacklist_del(&wpa_s, (u8 *) "222222") < 0 ||
- wpa_blacklist_del(&wpa_s, (u8 *) "444444") < 0 ||
- wpa_blacklist_add(&wpa_s, (u8 *) "111111") < 0 ||
- wpa_blacklist_add(&wpa_s, (u8 *) "222222") < 0 ||
- wpa_blacklist_add(&wpa_s, (u8 *) "333333") < 0)
+ if (wpa_bssid_ignore_add(&wpa_s, (u8 *) "111111") < 0 ||
+ wpa_bssid_ignore_add(&wpa_s, (u8 *) "111111") < 0 ||
+ wpa_bssid_ignore_add(&wpa_s, (u8 *) "222222") < 0 ||
+ wpa_bssid_ignore_add(&wpa_s, (u8 *) "333333") < 0 ||
+ wpa_bssid_ignore_add(&wpa_s, (u8 *) "444444") < 0 ||
+ wpa_bssid_ignore_del(&wpa_s, (u8 *) "333333") < 0 ||
+ wpa_bssid_ignore_del(&wpa_s, (u8 *) "xxxxxx") == 0 ||
+ wpa_bssid_ignore_get(&wpa_s, (u8 *) "xxxxxx") != NULL ||
+ wpa_bssid_ignore_get(&wpa_s, (u8 *) "111111") == NULL ||
+ wpa_bssid_ignore_get(&wpa_s, (u8 *) "222222") == NULL ||
+ wpa_bssid_ignore_get(&wpa_s, (u8 *) "444444") == NULL ||
+ wpa_bssid_ignore_del(&wpa_s, (u8 *) "111111") < 0 ||
+ wpa_bssid_ignore_del(&wpa_s, (u8 *) "222222") < 0 ||
+ wpa_bssid_ignore_del(&wpa_s, (u8 *) "444444") < 0 ||
+ wpa_bssid_ignore_add(&wpa_s, (u8 *) "111111") < 0 ||
+ wpa_bssid_ignore_add(&wpa_s, (u8 *) "222222") < 0 ||
+ wpa_bssid_ignore_add(&wpa_s, (u8 *) "333333") < 0)
goto fail;
- wpa_blacklist_clear(&wpa_s);
+ wpa_bssid_ignore_clear(&wpa_s);
- if (wpa_blacklist_add(&wpa_s, (u8 *) "111111") < 0 ||
- wpa_blacklist_add(&wpa_s, (u8 *) "222222") < 0 ||
- wpa_blacklist_add(&wpa_s, (u8 *) "333333") < 0 ||
- wpa_blacklist_add(&wpa_s, (u8 *) "444444") < 0 ||
- !wpa_blacklist_is_blacklisted(&wpa_s, (u8 *) "111111") ||
- wpa_blacklist_del(&wpa_s, (u8 *) "111111") < 0 ||
- wpa_blacklist_is_blacklisted(&wpa_s, (u8 *) "111111") ||
- wpa_blacklist_add(&wpa_s, (u8 *) "111111") < 0)
+ if (wpa_bssid_ignore_add(&wpa_s, (u8 *) "111111") < 0 ||
+ wpa_bssid_ignore_add(&wpa_s, (u8 *) "222222") < 0 ||
+ wpa_bssid_ignore_add(&wpa_s, (u8 *) "333333") < 0 ||
+ wpa_bssid_ignore_add(&wpa_s, (u8 *) "444444") < 0 ||
+ !wpa_bssid_ignore_is_listed(&wpa_s, (u8 *) "111111") ||
+ wpa_bssid_ignore_del(&wpa_s, (u8 *) "111111") < 0 ||
+ wpa_bssid_ignore_is_listed(&wpa_s, (u8 *) "111111") ||
+ wpa_bssid_ignore_add(&wpa_s, (u8 *) "111111") < 0)
goto fail;
- wpa_blacklist_update(&wpa_s);
+ wpa_bssid_ignore_update(&wpa_s);
- if (!wpa_blacklist_is_blacklisted(&wpa_s, (u8 *) "111111"))
+ if (!wpa_bssid_ignore_is_listed(&wpa_s, (u8 *) "111111"))
goto fail;
ret = 0;
fail:
- wpa_blacklist_clear(&wpa_s);
+ wpa_bssid_ignore_clear(&wpa_s);
if (ret)
- wpa_printf(MSG_ERROR, "blacklist module test failure");
+ wpa_printf(MSG_ERROR, "bssid_ignore module test failure");
return ret;
}
@@ -93,7 +93,7 @@ int wpas_module_tests(void)
wpa_printf(MSG_INFO, "wpa_supplicant module tests");
- if (wpas_blacklist_module_tests() < 0)
+ if (wpas_bssid_ignore_module_tests() < 0)
ret = -1;
#ifdef CONFIG_WPS
diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c
index 613fe2b..029349b 100644
--- a/wpa_supplicant/wps_supplicant.c
+++ b/wpa_supplicant/wps_supplicant.c
@@ -26,7 +26,7 @@
#include "wpa_supplicant_i.h"
#include "driver_i.h"
#include "notify.h"
-#include "blacklist.h"
+#include "bssid_ignore.h"
#include "bss.h"
#include "scan.h"
#include "ap.h"
@@ -94,14 +94,14 @@ int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s)
wpa_printf(MSG_DEBUG, "WPS: PIN registration with " MACSTR
" did not succeed - continue trying to find "
"suitable AP", MAC2STR(bssid));
- wpa_blacklist_add(wpa_s, bssid);
+ wpa_bssid_ignore_add(wpa_s, bssid);
wpa_supplicant_deauthenticate(wpa_s,
WLAN_REASON_DEAUTH_LEAVING);
wpa_s->reassociate = 1;
wpa_supplicant_req_scan(wpa_s,
- wpa_s->blacklist_cleared ? 5 : 0, 0);
- wpa_s->blacklist_cleared = 0;
+ wpa_s->bssid_ignore_cleared ? 5 : 0, 0);
+ wpa_s->bssid_ignore_cleared = false;
return 1;
}
@@ -1139,7 +1139,7 @@ static void wpas_wps_reassoc(struct wpa_supplicant *wpa_s,
wpa_s->scan_runs = 0;
wpa_s->normal_scans = 0;
wpa_s->wps_success = 0;
- wpa_s->blacklist_cleared = 0;
+ wpa_s->bssid_ignore_cleared = false;
wpa_supplicant_cancel_sched_scan(wpa_s);
wpa_supplicant_req_scan(wpa_s, 0, 0);
@@ -2883,10 +2883,11 @@ static void wpas_wps_dump_ap_info(struct wpa_supplicant *wpa_s)
for (i = 0; i < wpa_s->num_wps_ap; i++) {
struct wps_ap_info *ap = &wpa_s->wps_ap[i];
- struct wpa_blacklist *e = wpa_blacklist_get(wpa_s, ap->bssid);
+ struct wpa_bssid_ignore *e = wpa_bssid_ignore_get(wpa_s,
+ ap->bssid);
wpa_printf(MSG_DEBUG, "WPS: AP[%d] " MACSTR " type=%d "
- "tries=%d last_attempt=%d sec ago blacklist=%d",
+ "tries=%d last_attempt=%d sec ago bssid_ignore=%d",
(int) i, MAC2STR(ap->bssid), ap->type, ap->tries,
ap->last_attempt.sec > 0 ?
(int) now.sec - (int) ap->last_attempt.sec : -1,
@@ -2948,7 +2949,7 @@ static void wpas_wps_update_ap_info_bss(struct wpa_supplicant *wpa_s,
MAC2STR(res->bssid), ap->type, type);
ap->type = type;
if (type != WPS_AP_NOT_SEL_REG)
- wpa_blacklist_del(wpa_s, ap->bssid);
+ wpa_bssid_ignore_del(wpa_s, ap->bssid);
}
ap->pbc_active = pbc_active;
if (uuid)