summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTIONS2
-rw-r--r--COPYING2
-rw-r--r--README2
-rw-r--r--debian/changelog9
-rw-r--r--debian/config/hostapd/kfreebsd2
-rw-r--r--debian/config/hostapd/linux2
-rw-r--r--debian/config/wpasupplicant/kfreebsd2
-rw-r--r--debian/config/wpasupplicant/linux2
-rw-r--r--debian/gbp.conf2
-rw-r--r--debian/patches/dbus-available-sta.patch350
-rw-r--r--debian/upstream/signing-key.asc36
-rwxr-xr-xdebian/uscan-hook2
-rw-r--r--debian/watch2
-rw-r--r--hostapd/ChangeLog55
-rw-r--r--hostapd/README2
-rw-r--r--hostapd/config_file.c23
-rw-r--r--hostapd/ctrl_iface.c47
-rw-r--r--hostapd/defconfig2
-rw-r--r--hostapd/hostapd.conf5
-rw-r--r--hostapd/hostapd_cli.c6
-rw-r--r--hostapd/main.c29
-rw-r--r--hs20/client/oma_dm_client.c6
-rw-r--r--hs20/client/osu_client.c61
-rw-r--r--hs20/server/hs20_spp_server.c4
-rw-r--r--hs20/server/spp_server.c136
-rw-r--r--hs20/server/spp_server.h1
-rw-r--r--hs20/server/sql.txt7
-rw-r--r--hs20/server/www/remediation-pw.php41
-rw-r--r--hs20/server/www/remediation.php45
-rw-r--r--hs20/server/www/signup.php15
-rw-r--r--hs20/server/www/spp.php6
-rw-r--r--hs20/server/www/users.php19
-rw-r--r--src/ap/ap_config.c1
-rw-r--r--src/ap/ap_config.h4
-rw-r--r--src/ap/ap_drv_ops.c3
-rw-r--r--src/ap/authsrv.c36
-rw-r--r--src/ap/beacon.c23
-rw-r--r--src/ap/dpp_hostapd.c38
-rw-r--r--src/ap/drv_callbacks.c20
-rw-r--r--src/ap/eap_user_db.c2
-rw-r--r--src/ap/gas_serv.c43
-rw-r--r--src/ap/gas_serv.h2
-rw-r--r--src/ap/hostapd.c60
-rw-r--r--src/ap/hostapd.h12
-rw-r--r--src/ap/hs20.c3
-rw-r--r--src/ap/hw_features.c3
-rw-r--r--src/ap/ieee802_11.c36
-rw-r--r--src/ap/ieee802_11_shared.c17
-rw-r--r--src/ap/ieee802_1x.c2
-rw-r--r--src/ap/vlan_init.c14
-rw-r--r--src/ap/wnm_ap.c83
-rw-r--r--src/ap/wnm_ap.h2
-rw-r--r--src/ap/wpa_auth_ft.c2
-rw-r--r--src/ap/wpa_auth_ie.c9
-rw-r--r--src/common/dpp.c61
-rw-r--r--src/common/gas_server.c6
-rw-r--r--src/common/ieee802_11_defs.h11
-rw-r--r--src/common/qca-vendor.h324
-rw-r--r--src/common/version.h2
-rw-r--r--src/common/wpa_common.c2
-rw-r--r--src/common/wpa_ctrl.h7
-rw-r--r--src/crypto/crypto_openssl.c1
-rw-r--r--src/crypto/tls.h13
-rw-r--r--src/crypto/tls_gnutls.c8
-rw-r--r--src/crypto/tls_internal.c8
-rw-r--r--src/crypto/tls_none.c7
-rw-r--r--src/crypto/tls_openssl.c41
-rw-r--r--src/crypto/tls_wolfssl.c8
-rw-r--r--src/drivers/driver.h15
-rw-r--r--src/drivers/driver_atheros.c8
-rw-r--r--src/drivers/driver_macsec_linux.c4
-rw-r--r--src/drivers/driver_macsec_qca.c2
-rw-r--r--src/drivers/driver_nl80211.c116
-rw-r--r--src/drivers/driver_nl80211.h4
-rw-r--r--src/drivers/driver_nl80211_capa.c10
-rw-r--r--src/drivers/driver_nl80211_event.c14
-rw-r--r--src/drivers/driver_nl80211_monitor.c11
-rw-r--r--src/drivers/driver_nl80211_scan.c3
-rw-r--r--src/drivers/driver_wext.c4
-rw-r--r--src/drivers/driver_wired.c20
-rw-r--r--src/eap_peer/eap_pwd.c8
-rw-r--r--src/eap_server/eap.h1
-rw-r--r--src/eap_server/eap_i.h1
-rw-r--r--src/eap_server/eap_server.c12
-rw-r--r--src/eap_server/eap_server_tls_common.c5
-rw-r--r--src/radius/radius_server.c26
-rw-r--r--src/rsn_supp/tdls.c10
-rw-r--r--src/rsn_supp/wpa.c2
-rw-r--r--src/utils/browser-wpadebug.c5
-rw-r--r--src/utils/wpa_debug.c26
-rw-r--r--wpa_supplicant/ChangeLog70
-rw-r--r--wpa_supplicant/README2
-rw-r--r--wpa_supplicant/bss.c2
-rw-r--r--wpa_supplicant/bss.h1
-rw-r--r--wpa_supplicant/config.c9
-rw-r--r--wpa_supplicant/config.h9
-rw-r--r--wpa_supplicant/config_file.c4
-rw-r--r--wpa_supplicant/config_ssid.h10
-rw-r--r--wpa_supplicant/ctrl_iface.c30
-rw-r--r--wpa_supplicant/dbus/dbus_new.c12
-rw-r--r--wpa_supplicant/dbus/dbus_new.h1
-rw-r--r--wpa_supplicant/dbus/dbus_new_handlers.c65
-rw-r--r--wpa_supplicant/dbus/dbus_new_handlers.h2
-rw-r--r--wpa_supplicant/defconfig2
-rw-r--r--wpa_supplicant/doc/docbook/eapol_test.sgml2
-rw-r--r--wpa_supplicant/doc/docbook/wpa_background.sgml2
-rw-r--r--wpa_supplicant/doc/docbook/wpa_cli.sgml2
-rw-r--r--wpa_supplicant/doc/docbook/wpa_gui.sgml2
-rw-r--r--wpa_supplicant/doc/docbook/wpa_passphrase.sgml2
-rw-r--r--wpa_supplicant/doc/docbook/wpa_priv.sgml2
-rw-r--r--wpa_supplicant/doc/docbook/wpa_supplicant.sgml2
-rw-r--r--wpa_supplicant/dpp_supplicant.c63
-rw-r--r--wpa_supplicant/dpp_supplicant.h2
-rw-r--r--wpa_supplicant/events.c41
-rwxr-xr-xwpa_supplicant/examples/wps-ap-cli6
-rw-r--r--wpa_supplicant/hs20_supplicant.c41
-rw-r--r--wpa_supplicant/interworking.c4
-rw-r--r--wpa_supplicant/mesh_mpm.c5
-rw-r--r--wpa_supplicant/scan.c126
-rw-r--r--wpa_supplicant/sme.c168
-rw-r--r--wpa_supplicant/wnm_sta.c110
-rw-r--r--wpa_supplicant/wnm_sta.h9
-rw-r--r--wpa_supplicant/wpa_cli.c4
-rw-r--r--wpa_supplicant/wpa_supplicant.c39
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h6
125 files changed, 2462 insertions, 541 deletions
diff --git a/CONTRIBUTIONS b/CONTRIBUTIONS
index 1dc7547..053e8ec 100644
--- a/CONTRIBUTIONS
+++ b/CONTRIBUTIONS
@@ -140,7 +140,7 @@ The license terms used for hostap.git files
Modified BSD license (no advertisement clause):
-Copyright (c) 2002-2017, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2002-2018, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
Redistribution and use in source and binary forms, with or without
diff --git a/COPYING b/COPYING
index 945bdc0..55815d4 100644
--- a/COPYING
+++ b/COPYING
@@ -1,7 +1,7 @@
wpa_supplicant and hostapd
--------------------------
-Copyright (c) 2002-2017, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2002-2018, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
diff --git a/README b/README
index 43b684c..6586d72 100644
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
wpa_supplicant and hostapd
--------------------------
-Copyright (c) 2002-2017, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2002-2018, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
These programs are licensed under the BSD license (the one with
diff --git a/debian/changelog b/debian/changelog
index 008e84d..26e1743 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,12 @@
+wpa (2:2.7-1) experimental; urgency=medium
+
+ * New upstream version 2.7.
+ * Enable FILS.
+ * Add debian/upstream/signing-key.asc, update debian/watch to
+ verify PGP signatures on tarballs.
+
+ -- Andrej Shadura <andrewsh@debian.org> Mon, 03 Dec 2018 19:36:56 +0100
+
wpa (2:2.7~git20181004+1dd66fc-1) experimental; urgency=medium
* New upstream snapshot 2.7~git20181004+1dd66fc.
diff --git a/debian/config/hostapd/kfreebsd b/debian/config/hostapd/kfreebsd
index a08cc5a..5c0e8f5 100644
--- a/debian/config/hostapd/kfreebsd
+++ b/debian/config/hostapd/kfreebsd
@@ -365,7 +365,7 @@ LIBS += -ldl
# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
# Note: This is an experimental and not yet complete implementation. This
# should not be enabled for production use.
-#CONFIG_FILS=y
+CONFIG_FILS=y
# FILS shared key authentication with PFS
#CONFIG_FILS_SK_PFS=y
diff --git a/debian/config/hostapd/linux b/debian/config/hostapd/linux
index 2bd683a..3070f34 100644
--- a/debian/config/hostapd/linux
+++ b/debian/config/hostapd/linux
@@ -358,7 +358,7 @@ CONFIG_ACS=y
# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
# Note: This is an experimental and not yet complete implementation. This
# should not be enabled for production use.
-#CONFIG_FILS=y
+CONFIG_FILS=y
# FILS shared key authentication with PFS
#CONFIG_FILS_SK_PFS=y
diff --git a/debian/config/wpasupplicant/kfreebsd b/debian/config/wpasupplicant/kfreebsd
index 33f4fc2..504cdb0 100644
--- a/debian/config/wpasupplicant/kfreebsd
+++ b/debian/config/wpasupplicant/kfreebsd
@@ -569,7 +569,7 @@ LIBS += -ldl
# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
# Note: This is an experimental and not yet complete implementation. This
# should not be enabled for production use.
-#CONFIG_FILS=y
+CONFIG_FILS=y
# FILS shared key authentication with PFS
#CONFIG_FILS_SK_PFS=y
diff --git a/debian/config/wpasupplicant/linux b/debian/config/wpasupplicant/linux
index a7a709c..691f0ba 100644
--- a/debian/config/wpasupplicant/linux
+++ b/debian/config/wpasupplicant/linux
@@ -563,7 +563,7 @@ CONFIG_ACS=y
# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
# Note: This is an experimental and not yet complete implementation. This
# should not be enabled for production use.
-#CONFIG_FILS=y
+CONFIG_FILS=y
# FILS shared key authentication with PFS
#CONFIG_FILS_SK_PFS=y
diff --git a/debian/gbp.conf b/debian/gbp.conf
index 6c268aa..d1d69b1 100644
--- a/debian/gbp.conf
+++ b/debian/gbp.conf
@@ -1,3 +1,3 @@
[DEFAULT]
debian-branch=debian/experimental
-upstream-branch=upstream/snapshots
+upstream-branch=upstream/latest
diff --git a/debian/patches/dbus-available-sta.patch b/debian/patches/dbus-available-sta.patch
index de4af53..e699090 100644
--- a/debian/patches/dbus-available-sta.patch
+++ b/debian/patches/dbus-available-sta.patch
@@ -1,26 +1,19 @@
-From: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
-Date: Mon, 7 May 2018 15:36:30 +0200
-Subject: [PATCH] dbus: Expose connected stations on D-Bus
+From 0709a1b6878d60d0512f65905106166f06c4c405 Mon Sep 17 00:00:00 2001
+From: Andrej Shadura <andrew.shadura@collabora.co.uk>
+Date: Sun, 7 Oct 2018 11:49:19 +0200
+Subject: [PATCH v2 1/2] dbus: Use dbus_bool_t, not int for boolean function
+ arguments
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
-Make it possible to list connected stations in AP mode over D-Bus, along
-with some of their properties: rx/tx packets, bytes, capabilities, etc.
-
-Signed-off-by: Mathieu Trudel-Lapierre <mathieu.trudel-lapierre@canonical.com>
-
-Rebased by Julian Andres Klode <juliank@ubuntu.com> and updated to use
-the new getter API.
-
-Further modified by Andrej Shadura to not error out when not in AP mode.
-
-Signed-off-by: Andrej Shadura <andrewsh@debian.org>
+Properties argument specifies whether to add object’s properties
+or not, hence it doesn’t need to be int.
+Signed-off-by: Andrej Shadura <andrew.shadura@collabora.co.uk>
---
- wpa_supplicant/dbus/dbus_new.c | 245 +++++++++++++++++--
- wpa_supplicant/dbus/dbus_new.h | 25 ++
- wpa_supplicant/dbus/dbus_new_handlers.c | 313 ++++++++++++++++++++++++
- wpa_supplicant/dbus/dbus_new_handlers.h | 14 ++
- wpa_supplicant/notify.c | 6 +
- 5 files changed, 589 insertions(+), 14 deletions(-)
+ wpa_supplicant/dbus/dbus_new.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -32,17 +25,129 @@ Signed-off-by: Andrej Shadura <andrewsh@debian.org>
#ifdef CONFIG_AP /* until needed by something else */
-@@ -2151,6 +2152,9 @@
+@@ -128,7 +129,7 @@
+ * Notify listeners about event related with interface
+ */
+ static void wpas_dbus_signal_interface(struct wpa_supplicant *wpa_s,
+- const char *sig_name, int properties)
++ const char *sig_name, dbus_bool_t properties)
+ {
+ struct wpas_dbus_priv *iface;
+ DBusMessage *msg;
+@@ -230,7 +231,7 @@
+ */
+ static void wpas_dbus_signal_bss(struct wpa_supplicant *wpa_s,
+ const char *bss_obj_path,
+- const char *sig_name, int properties)
++ const char *sig_name, dbus_bool_t properties)
+ {
+ struct wpas_dbus_priv *iface;
+ DBusMessage *msg;
+@@ -364,7 +365,7 @@
+ */
+ static void wpas_dbus_signal_network(struct wpa_supplicant *wpa_s,
+ int id, const char *sig_name,
+- int properties)
++ dbus_bool_t properties)
+ {
+ struct wpas_dbus_priv *iface;
+ DBusMessage *msg;
+@@ -1077,6 +1078,75 @@
+ }
+
+
++/**
++ * wpas_dbus_signal_station - Send an event signal related to a station object
++ * @wpa_s: %wpa_supplicant network interface data
++ * @station_obj_path: Station object path
++ * @sig_name: signal name - StationAdded or StationRemoved
++ * @properties: Whether to add second argument with object properties
++ *
++ * Notify listeners about event related with station
++ */
++static void wpas_dbus_signal_station(struct wpa_supplicant *wpa_s,
++ const char *station_obj_path,
++ const char *sig_name, dbus_bool_t properties)
++{
++ struct wpas_dbus_priv *iface;
++ DBusMessage *msg;
++ DBusMessageIter iter;
++
++ iface = wpa_s->global->dbus;
++
++ /* Do nothing if the control interface is not turned on */
++ if (iface == NULL || !wpa_s->dbus_new_path)
++ return;
++
++ msg = dbus_message_new_signal(wpa_s->dbus_new_path,
++ WPAS_DBUS_NEW_IFACE_INTERFACE, sig_name);
++ if (msg == NULL)
++ return;
++
++ if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
++ &station_obj_path) ||
++ (properties &&
++ !wpa_dbus_get_object_properties(iface, station_obj_path,
++ WPAS_DBUS_NEW_IFACE_STA,
++ &iter)))
++ wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
++ else
++ dbus_connection_send(iface->con, msg, NULL);
++ dbus_message_unref(msg);
++}
++
++
++/**
++ * wpas_dbus_signal_station_added - Send a Station added signal
++ * @wpa_s: %wpa_supplicant network interface data
++ * @station_obj_path: new Station object path
++ *
++ * Notify listeners about adding new Station
++ */
++static void wpas_dbus_signal_station_added(struct wpa_supplicant *wpa_s,
++ const char *station_obj_path)
++{
++ wpas_dbus_signal_station(wpa_s, station_obj_path, "StationAdded", TRUE);
++}
++
++
++/**
++ * wpas_dbus_signal_station_removed - Send a Station removed signal
++ * @wpa_s: %wpa_supplicant network interface data
++ * @station_obj_path: Station object path
++ *
++ * Notify listeners about removing Station
++ */
++static void wpas_dbus_signal_station_removed(struct wpa_supplicant *wpa_s,
++ const char *station_obj_path)
++{
++ wpas_dbus_signal_station(wpa_s, station_obj_path, "StationRemoved", FALSE);
++}
++
++
+ #ifdef CONFIG_P2P
+
+ /**
+@@ -1882,7 +1952,7 @@
+ */
+ static void wpas_dbus_signal_persistent_group(struct wpa_supplicant *wpa_s,
+ int id, const char *sig_name,
+- int properties)
++ dbus_bool_t properties)
+ {
+ struct wpas_dbus_priv *iface;
+ DBusMessage *msg;
+@@ -2151,6 +2221,9 @@
case WPAS_DBUS_PROP_BSSS:
prop = "BSSs";
break;
-+ case WPAS_DBUS_PROP_STAS:
++ case WPAS_DBUS_PROP_STATIONS:
+ prop = "Stations";
+ break;
case WPAS_DBUS_PROP_CURRENT_AUTH_MODE:
prop = "CurrentAuthMode";
break;
-@@ -2244,6 +2248,39 @@
+@@ -2244,6 +2317,39 @@
/**
@@ -82,7 +187,7 @@ Signed-off-by: Andrej Shadura <andrewsh@debian.org>
* wpas_dbus_signal_debug_level_changed - Signals change of debug param
* @global: wpa_global structure
*
-@@ -2857,6 +2894,164 @@
+@@ -2857,6 +2963,166 @@
}
@@ -148,7 +253,7 @@ Signed-off-by: Andrej Shadura <andrewsh@debian.org>
+ const u8 *sta)
+{
+ struct wpas_dbus_priv *ctrl_iface;
-+ char sta_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
++ char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+
+ /* Do nothing if the control interface is not turned on */
+ if (wpa_s == NULL || wpa_s->global == NULL)
@@ -157,19 +262,20 @@ Signed-off-by: Andrej Shadura <andrewsh@debian.org>
+ if (ctrl_iface == NULL)
+ return 0;
+
-+ os_snprintf(sta_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
++ os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+ "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
+ wpa_s->dbus_new_path, MAC2STR(sta));
+
+ wpa_printf(MSG_DEBUG, "dbus: Unregister STA object '%s'",
-+ sta_obj_path);
-+ if (wpa_dbus_unregister_object_per_iface(ctrl_iface, sta_obj_path)) {
++ station_obj_path);
++ if (wpa_dbus_unregister_object_per_iface(ctrl_iface, station_obj_path)) {
+ wpa_printf(MSG_ERROR, "dbus: Cannot unregister STA object %s",
-+ sta_obj_path);
++ station_obj_path);
+ return -1;
+ }
+
-+ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STAS);
++ wpas_dbus_signal_station_added(wpa_s, station_obj_path);
++ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
+
+ return 0;
+}
@@ -189,7 +295,7 @@ Signed-off-by: Andrej Shadura <andrewsh@debian.org>
+{
+ struct wpas_dbus_priv *ctrl_iface;
+ struct wpa_dbus_object_desc *obj_desc;
-+ char sta_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
++ char station_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+ struct sta_handler_args *arg;
+
+ /* Do nothing if the control interface is not turned on */
@@ -199,7 +305,7 @@ Signed-off-by: Andrej Shadura <andrewsh@debian.org>
+ if (ctrl_iface == NULL)
+ return 0;
+
-+ os_snprintf(sta_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
++ os_snprintf(station_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+ "%s/" WPAS_DBUS_NEW_STAS_PART "/" COMPACT_MACSTR,
+ wpa_s->dbus_new_path, MAC2STR(sta));
+
@@ -225,16 +331,17 @@ Signed-off-by: Andrej Shadura <andrewsh@debian.org>
+ wpas_dbus_sta_signals);
+
+ wpa_printf(MSG_DEBUG, "dbus: Register STA object '%s'",
-+ sta_obj_path);
-+ if (wpa_dbus_register_object_per_iface(ctrl_iface, sta_obj_path,
++ station_obj_path);
++ if (wpa_dbus_register_object_per_iface(ctrl_iface, station_obj_path,
+ wpa_s->ifname, obj_desc)) {
+ wpa_printf(MSG_ERROR,
+ "Cannot register STA dbus object %s.",
-+ sta_obj_path);
++ station_obj_path);
+ goto err;
+ }
+
-+ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STAS);
++ wpas_dbus_signal_station_removed(wpa_s, station_obj_path);
++ wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATIONS);
+
+ return 0;
+
@@ -247,7 +354,7 @@ Signed-off-by: Andrej Shadura <andrewsh@debian.org>
static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
{ "Scan", WPAS_DBUS_NEW_IFACE_INTERFACE,
(WPADBusMethodHandler) wpas_dbus_handler_scan,
-@@ -3501,6 +3696,11 @@
+@@ -3501,6 +3767,11 @@
NULL
},
#endif /* CONFIG_MESH */
@@ -259,6 +366,104 @@ Signed-off-by: Andrej Shadura <andrewsh@debian.org>
{ NULL, NULL, NULL, NULL, NULL, NULL }
};
+@@ -3770,6 +4041,19 @@
+ END_ARGS
+ }
+ },
++ { "StationAdded", WPAS_DBUS_NEW_IFACE_INTERFACE,
++ {
++ { "path", "o", ARG_OUT },
++ { "properties", "a{sv}", ARG_OUT },
++ END_ARGS
++ }
++ },
++ { "StationRemoved", WPAS_DBUS_NEW_IFACE_INTERFACE,
++ {
++ { "path", "o", ARG_OUT },
++ END_ARGS
++ }
++ },
+ { "NetworkRequest", WPAS_DBUS_NEW_IFACE_INTERFACE,
+ {
+ { "path", "o", ARG_OUT },
+@@ -4078,7 +4362,7 @@
+ */
+ static void wpas_dbus_signal_peer(struct wpa_supplicant *wpa_s,
+ const u8 *dev_addr, const char *interface,
+- const char *sig_name, int properties)
++ const char *sig_name, dbus_bool_t properties)
+ {
+ struct wpas_dbus_priv *iface;
+ DBusMessage *msg;
+--- a/wpa_supplicant/dbus/dbus_new.h
++++ b/wpa_supplicant/dbus/dbus_new.h
+@@ -12,6 +12,7 @@
+
+ #include "common/defs.h"
+ #include "p2p/p2p.h"
++#include "ap/sta_info.h"
+
+ struct wpa_global;
+ struct wpa_supplicant;
+@@ -29,6 +30,7 @@
+ WPAS_DBUS_PROP_CURRENT_NETWORK,
+ WPAS_DBUS_PROP_CURRENT_AUTH_MODE,
+ WPAS_DBUS_PROP_BSSS,
++ WPAS_DBUS_PROP_STATIONS,
+ WPAS_DBUS_PROP_DISCONNECT_REASON,
+ WPAS_DBUS_PROP_ASSOC_STATUS_CODE,
+ };
+@@ -46,6 +48,10 @@
+ WPAS_DBUS_BSS_PROP_AGE,
+ };
+
++enum wpas_dbus_sta_prop {
++ WPAS_DBUS_STA_PROP_ADDRESS,
++};
++
+ #define WPAS_DBUS_OBJECT_PATH_MAX 150
+
+ #define WPAS_DBUS_NEW_SERVICE "fi.w1.wpa_supplicant1"
+@@ -62,6 +68,9 @@
+ #define WPAS_DBUS_NEW_BSSIDS_PART "BSSs"
+ #define WPAS_DBUS_NEW_IFACE_BSS WPAS_DBUS_NEW_INTERFACE ".BSS"
+
++#define WPAS_DBUS_NEW_STAS_PART "Stations"
++#define WPAS_DBUS_NEW_IFACE_STA WPAS_DBUS_NEW_INTERFACE ".Station"
++
+ #define WPAS_DBUS_NEW_IFACE_P2PDEVICE \
+ WPAS_DBUS_NEW_IFACE_INTERFACE ".P2PDevice"
+
+@@ -164,6 +173,10 @@
+ u8 bssid[ETH_ALEN], unsigned int id);
+ int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
+ u8 bssid[ETH_ALEN], unsigned int id);
++int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s,
++ const u8 *sta);
++int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s,
++ const u8 *sta);
+ void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
+ const char *name);
+ void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
+@@ -345,6 +358,18 @@
+ {
+ return 0;
+ }
++
++static inline int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s,
++ const u8 *sta)
++{
++ return 0;
++}
++
++static inline int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s,
++ const u8 *sta)
++{
++ return 0;
++}
+
+ static inline void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
+ const char *name)
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -22,6 +22,10 @@
@@ -618,82 +823,13 @@ Signed-off-by: Andrej Shadura <andrewsh@debian.org>
DECLARE_ACCESSOR(wpas_dbus_getter_bss_bssid);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_ssid);
DECLARE_ACCESSOR(wpas_dbus_getter_bss_privacy);
---- a/wpa_supplicant/dbus/dbus_new.h
-+++ b/wpa_supplicant/dbus/dbus_new.h
-@@ -12,6 +12,7 @@
-
- #include "common/defs.h"
- #include "p2p/p2p.h"
-+#include "ap/sta_info.h"
-
- struct wpa_global;
- struct wpa_supplicant;
-@@ -29,6 +30,7 @@
- WPAS_DBUS_PROP_CURRENT_NETWORK,
- WPAS_DBUS_PROP_CURRENT_AUTH_MODE,
- WPAS_DBUS_PROP_BSSS,
-+ WPAS_DBUS_PROP_STAS,
- WPAS_DBUS_PROP_DISCONNECT_REASON,
- WPAS_DBUS_PROP_ASSOC_STATUS_CODE,
- };
-@@ -46,6 +48,10 @@
- WPAS_DBUS_BSS_PROP_AGE,
- };
-
-+enum wpas_dbus_sta_prop {
-+ WPAS_DBUS_STA_PROP_ADDRESS,
-+};
-+
- #define WPAS_DBUS_OBJECT_PATH_MAX 150
-
- #define WPAS_DBUS_NEW_SERVICE "fi.w1.wpa_supplicant1"
-@@ -62,6 +68,9 @@
- #define WPAS_DBUS_NEW_BSSIDS_PART "BSSs"
- #define WPAS_DBUS_NEW_IFACE_BSS WPAS_DBUS_NEW_INTERFACE ".BSS"
-
-+#define WPAS_DBUS_NEW_STAS_PART "Stations"
-+#define WPAS_DBUS_NEW_IFACE_STA WPAS_DBUS_NEW_INTERFACE ".Station"
-+
- #define WPAS_DBUS_NEW_IFACE_P2PDEVICE \
- WPAS_DBUS_NEW_IFACE_INTERFACE ".P2PDevice"
-
-@@ -164,6 +173,10 @@
- u8 bssid[ETH_ALEN], unsigned int id);
- int wpas_dbus_register_bss(struct wpa_supplicant *wpa_s,
- u8 bssid[ETH_ALEN], unsigned int id);
-+int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s,
-+ const u8 *sta);
-+int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s,
-+ const u8 *sta);
- void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
- const char *name);
- void wpas_dbus_signal_blob_removed(struct wpa_supplicant *wpa_s,
-@@ -345,6 +358,18 @@
- {
- return 0;
- }
-+
-+static inline int wpas_dbus_unregister_sta(struct wpa_supplicant *wpa_s,
-+ const u8 *sta)
-+{
-+ return 0;
-+}
-+
-+static inline int wpas_dbus_register_sta(struct wpa_supplicant *wpa_s,
-+ const u8 *sta)
-+{
-+ return 0;
-+}
-
- static inline void wpas_dbus_signal_blob_added(struct wpa_supplicant *wpa_s,
- const char *name)
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -720,6 +720,9 @@
wpas_dbus_signal_p2p_peer_joined(wpa_s, p2p_dev_addr);
#endif /* CONFIG_P2P */
-+ /* Unregister the station */
++ /* Register the station */
+ wpas_dbus_register_sta(wpa_s, sta);
+
/* Notify listeners a new station has been authorized */
diff --git a/debian/upstream/signing-key.asc b/debian/upstream/signing-key.asc
new file mode 100644
index 0000000..2896588
--- /dev/null
+++ b/debian/upstream/signing-key.asc
@@ -0,0 +1,36 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQGiBDoydw4RBAC9vfqCsU+dgrxUSdGf70zrEAIBxcjeqHusovztR65XOWE0ccjm
+QS2TVgJM+OzYg9FJG7DuLQZDwhR10BZKJfG97fNyZVBCoO90bEcTufn96oceJlz/
+MHmy99+i6wYdIKYzvmaxcC1QPhENr1scgin9nMiW1MTPJ7sSgjDqd0QPVwCgmaZU
+pzhKRusR5E/MmgI2kz73Ui0D/03lVNypkQTbuBp1q71YqT9qjO8+5kXU5QXJhel0
+qUgJHcu3rdnIVaiANw1qauMM0DtnRKOtcaZntn03sFNnaJRx0JlmLa/cMP0nm1kP
+nR6Q3Cruz7InJnJZDXGsGH/ku4OcYLUJ8UgqzaO0J5o66j7pxQQDo1UAs4PQaoYq
+/ECbA/9B6b3TzuHdqUgS/g2AYTc5MU+i92ydrBv2g9SPuH78m/X4YicGR1HF7yNi
+J/hiVa/axBUHpXE4vW0Bndj1bN4sctFeGGezGRaLiiggZkBBNnL8nF5eZebLvPrv
+4kr8Cchz+lGF5UFNVyLWwi/I5CSUqUtSXOD1Q9WcXoqJcrE2brQXSm91bmkgTWFs
+aW5lbiA8akB3MS5maT6IYgQTEQIAIgIbIwYLCQgHAwIEFQIIAwMWAgECHgECF4AF
+AkZbB/QCGQEACgkQK270Mu/IlfpuGACfd0WargWDeja0VW+R9TSKjRIfO1cAn1A8
+nkiso1bg/CvU56wSvpU4MpF6tBlKb3VuaSBNYWxpbmVuIDxqbUBraXIubnU+iF8E
+ExECAB8FAkZbB5sCGyMGCwkIBwMCBBUCCAMDFgIBAh4BAheAAAoJECtu9DLvyJX6
+BmAAnRSeK5z2ClLwuV5i1CtP9w2v85TkAJ9XLkaqrNqX4yDxoHqbEpHkHZ6d17Qg
+Sm91bmkgTWFsaW5lbiA8am1Aam0uZXBpdGVzdC5maT6IVwQTEQIAFwUCOjJ3DgUL
+BwoDBAMVAwIDFgIBAheAAAoJECtu9DLvyJX6jS8AnixjTt+aerNHx8woqO7WGGqQ
+h15YAJ4iIDUXZ/vQZny1FG/ewzE/rdUVmrQiSm91bmkgTWFsaW5lbiA8amttYWxp
+bmVAY2MuaHV0LmZpPohXBBMRAgAXBQI6Mn1JBQsHCgMEAxUDAgMWAgECF4AACgkQ
+K270Mu/IlfqZmQCeN9xC1eqSD3xiUa/z+SMA2Gd5NvkAnRuwbogLyTyBb8HqC1Lx
+ISWkTSBvuQINBDoyd1sQCAC8qbv50m22q9hhs54GMD+Xemg0dHiHuuTtVPYugJqT
+SlhSS8QJBdulR8hYYDGHbTzjB/ksiQFOcISZZ+zQRIGqLbNldf6taGUTIhZkIh09
+0RYLXCYoMFB8XLBOaLVRy7SMwsPXdbIRkT9v9CzMjZcTUVjwObQKRpTie0JZhc//
+CUmY76scpRY5ifDXT9NOr5uMA3W5FI1AFc3d856BYhdnhcuJn+QQS+Xsj3r2vpVz
+YHoS+nT0nQ9iwmqPtRHep+t1cudqEouaWT8tpXkSB0Y0MjOPyGnNDkg9om3gj5QK
+zMDcQCxCVTHjqVUrmW6Bs2Rm2YVMBu/TIG4E9hEK8Ma/AAMFB/4pOot8lGbAJcov
+gtSEvna6WyOnFtmC8UCXJyf1MnzzLAO6Fvf8cz16ig2o+7bgKiQeWxwd7LJEicv2
+kD33fZl3OqSZbNdfsOxB9g+jtWC+vOXGKzr6Pi7fIBXgkhxF/eWbhFg7Kj4rd+jB
+I9F7uK/wPyY8JivH8vy2w6Boipc3S7qcUn5Gk58w0EuZrAHSGKt9QWd/p7ppIfgg
+mbc77YFWzM/z9fiMWp4+YIJkEH6unz3+91qQXUC4JGL6QMnsIoieqoAk/6rHMCTf
+hFSvQxuhxpLUI+PT9sAvIBZLZta6hvIiYVpSTzZxiVmuioVHUhPVQdcpO5Mrr1VH
+DwC+ZH8miEYEGBECAAYFAjoyd1sACgkQK270Mu/IlfrRCACfWEtm3et85knJeUK2
+ApdQ54Evxn4AoIYi35jctzD/SfJzPiE15zTRS8NN
+=UdTW
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/debian/uscan-hook b/debian/uscan-hook
index fbe2d7a..8321437 100755
--- a/debian/uscan-hook
+++ b/debian/uscan-hook
@@ -3,7 +3,7 @@ set -e
# This script is invoked by uscan after downloading a new tarball
-if [ "x$1" != "x--upstream-version" ] || [ $# != 3 ]; then
+if [ "$1" != "--upstream-version" ] || [ $# != 3 ]; then
echo "invalid arguments: $*" >&2
exit 2
fi
diff --git a/debian/watch b/debian/watch
index 8eae097..b78d8d5 100644
--- a/debian/watch
+++ b/debian/watch
@@ -2,4 +2,4 @@
# We need to generate a merged wpa tarball from wpa_supplicant and hostapd,
# so use our own script instead of uupdate.
version=3
-http://w1.fi/releases/hostapd-([\.0-9]+)\.tar\.gz debian debian/uscan-hook
+opts=pgpmode=auto http://w1.fi/releases/hostapd-([\.0-9]+)\.tar\.gz debian debian/uscan-hook
diff --git a/hostapd/ChangeLog b/hostapd/ChangeLog
index d2b669b..f1366b4 100644
--- a/hostapd/ChangeLog
+++ b/hostapd/ChangeLog
@@ -1,5 +1,60 @@
ChangeLog for hostapd
+2018-12-02 - v2.7
+ * fixed WPA packet number reuse with replayed messages and key
+ reinstallation
+ [http://w1.fi/security/2017-1/] (CVE-2017-13082)
+ * added support for FILS (IEEE 802.11ai) shared key authentication
+ * added support for OWE (Opportunistic Wireless Encryption, RFC 8110;
+ and transition mode defined by WFA)
+ * added support for DPP (Wi-Fi Device Provisioning Protocol)
+ * FT:
+ - added local generation of PMK-R0/PMK-R1 for FT-PSK
+ (ft_psk_generate_local=1)
+ - replaced inter-AP protocol with a cleaner design that is more
+ easily extensible; this breaks backward compatibility and requires
+ all APs in the ESS to be updated at the same time to maintain FT
+ functionality
+ - added support for wildcard R0KH/R1KH
+ - replaced r0_key_lifetime (minutes) parameter with
+ ft_r0_key_lifetime (seconds)
+ - fixed wpa_psk_file use for FT-PSK
+ - fixed FT-SAE PMKID matching
+ - added expiration to PMK-R0 and PMK-R1 cache
+ - added IEEE VLAN support (including tagged VLANs)
+ - added support for SHA384 based AKM
+ * SAE
+ - fixed some PMKSA caching cases with SAE
+ - added support for configuring SAE password separately of the
+ WPA2 PSK/passphrase
+ - added option to require MFP for SAE associations
+ (sae_require_pmf=1)
+ - fixed PTK and EAPOL-Key integrity and key-wrap algorithm selection
+ for SAE;
+ note: this is not backwards compatible, i.e., both the AP and
+ station side implementations will need to be update at the same
+ time to maintain interoperability
+ - added support for Password Identifier
+ * hostapd_cli: added support for command history and completion
+ * added support for requesting beacon report
+ * large number of other fixes, cleanup, and extensions
+ * added option to configure EAPOL-Key retry limits
+ (wpa_group_update_count and wpa_pairwise_update_count)
+ * removed all PeerKey functionality
+ * fixed nl80211 AP mode configuration regression with Linux 4.15 and
+ newer
+ * added support for using wolfSSL cryptographic library
+ * fixed some 20/40 MHz coexistence cases where the BSS could drop to
+ 20 MHz even when 40 MHz would be allowed
+ * Hotspot 2.0
+ - added support for setting Venue URL ANQP-element (venue_url)
+ - added support for advertising Hotspot 2.0 operator icons
+ - added support for Roaming Consortium Selection element
+ - added support for Terms and Conditions
+ - added support for OSEN connection in a shared RSN BSS
+ * added support for using OpenSSL 1.1.1
+ * added EAP-pwd server support for salted passwords
+
2016-10-02 - v2.6
* fixed EAP-pwd last fragment validation
[http://w1.fi/security/2015-7/] (CVE-2015-5314)
diff --git a/hostapd/README b/hostapd/README
index 298391b..ae53176 100644
--- a/hostapd/README
+++ b/hostapd/README
@@ -2,7 +2,7 @@ hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP
Authenticator and RADIUS authentication server
================================================================
-Copyright (c) 2002-2017, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2002-2018, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
This program is licensed under the BSD license (the one with
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index b1ab13e..b26da71 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2049,6 +2049,24 @@ static int hs20_parse_osu_nai(struct hostapd_bss_config *bss,
}
+static int hs20_parse_osu_nai2(struct hostapd_bss_config *bss,
+ char *pos, int line)
+{
+ if (bss->last_osu == NULL) {
+ wpa_printf(MSG_ERROR, "Line %d: Unexpected OSU field", line);
+ return -1;
+ }
+
+ os_free(bss->last_osu->osu_nai2);
+ bss->last_osu->osu_nai2 = os_strdup(pos);
+ if (bss->last_osu->osu_nai2 == NULL)
+ return -1;
+ bss->hs20_osu_providers_nai_count++;
+
+ return 0;
+}
+
+
static int hs20_parse_osu_method_list(struct hostapd_bss_config *bss, char *pos,
int line)
{
@@ -3761,6 +3779,9 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "osu_nai") == 0) {
if (hs20_parse_osu_nai(bss, pos, line) < 0)
return 1;
+ } else if (os_strcmp(buf, "osu_nai2") == 0) {
+ if (hs20_parse_osu_nai2(bss, pos, line) < 0)
+ return 1;
} else if (os_strcmp(buf, "osu_method_list") == 0) {
if (hs20_parse_osu_method_list(bss, pos, line) < 0)
return 1;
@@ -4087,6 +4108,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
line, pos);
return 1;
}
+ } else if (os_strcmp(buf, "coloc_intf_reporting") == 0) {
+ bss->coloc_intf_reporting = atoi(pos);
#endif /* CONFIG_OWE */
} else {
wpa_printf(MSG_ERROR,
diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c
index 2d68e88..75f12e5 100644
--- a/hostapd/ctrl_iface.c
+++ b/hostapd/ctrl_iface.c
@@ -992,6 +992,42 @@ fail:
return ret;
}
+
+static int hostapd_ctrl_iface_coloc_intf_req(struct hostapd_data *hapd,
+ const char *cmd)
+{
+ u8 addr[ETH_ALEN];
+ struct sta_info *sta;
+ const char *pos;
+ unsigned int auto_report, timeout;
+
+ if (hwaddr_aton(cmd, addr)) {
+ wpa_printf(MSG_DEBUG, "Invalid STA MAC address");
+ return -1;
+ }
+
+ sta = ap_get_sta(hapd, addr);
+ if (!sta) {
+ wpa_printf(MSG_DEBUG, "Station " MACSTR
+ " not found for Collocated Interference Request",
+ MAC2STR(addr));
+ return -1;
+ }
+
+ pos = cmd + 17;
+ if (*pos != ' ')
+ return -1;
+ pos++;
+ auto_report = atoi(pos);
+ pos = os_strchr(pos, ' ');
+ if (!pos)
+ return -1;
+ pos++;
+ timeout = atoi(pos);
+
+ return wnm_send_coloc_intf_req(hapd, sta, auto_report, timeout);
+}
+
#endif /* CONFIG_WNM_AP */
@@ -1386,6 +1422,12 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd)
hostapd_disassoc_deny_mac(hapd);
} else if (os_strcasecmp(cmd, "accept_mac_file") == 0) {
hostapd_disassoc_accept_mac(hapd);
+ } else if (os_strncmp(cmd, "wme_ac_", 7) == 0 ||
+ os_strncmp(cmd, "wmm_ac_", 7) == 0) {
+ hapd->parameter_set_count++;
+ if (ieee802_11_update_beacons(hapd->iface))
+ wpa_printf(MSG_DEBUG,
+ "Failed to update beacons with WMM parameters");
}
}
@@ -2092,7 +2134,7 @@ static int hostapd_ctrl_set_key(struct hostapd_data *hapd, const char *cmd)
if (!pos)
return -1;
pos++;
- if (hexstr2bin(pos, seq, sizeof(6)) < 0)
+ if (hexstr2bin(pos, seq, sizeof(seq)) < 0)
return -1;
pos += 2 * 6;
if (*pos != ' ')
@@ -2955,6 +2997,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
} else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
if (hostapd_ctrl_iface_bss_tm_req(hapd, buf + 11))
reply_len = -1;
+ } else if (os_strncmp(buf, "COLOC_INTF_REQ ", 15) == 0) {
+ if (hostapd_ctrl_iface_coloc_intf_req(hapd, buf + 15))
+ reply_len = -1;
#endif /* CONFIG_WNM_AP */
} else if (os_strcmp(buf, "GET_CONFIG") == 0) {
reply_len = hostapd_ctrl_iface_get_config(hapd, reply,
diff --git a/hostapd/defconfig b/hostapd/defconfig
index c67c662..77a894d 100644
--- a/hostapd/defconfig
+++ b/hostapd/defconfig
@@ -31,7 +31,7 @@ CONFIG_DRIVER_NL80211=y
#CONFIG_LIBNL20=y
# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
-#CONFIG_LIBNL32=y
+CONFIG_LIBNL32=y
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 70f9713..a005217 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -2227,12 +2227,15 @@ own_ip_addr=127.0.0.1
# OSU Providers
# One or more sets of following parameter. Each OSU provider is started by the
# mandatory osu_server_uri item. The other parameters add information for the
-# last added OSU provider.
+# last added OSU provider. osu_nai specifies the OSU_NAI value for OSEN
+# authentication when using a standalone OSU BSS. osu_nai2 specifies the OSU_NAI
+# value for OSEN authentication when using a shared BSS (Single SSID) for OSU.
#
#osu_server_uri=https://example.com/osu/
#osu_friendly_name=eng:Example operator
#osu_friendly_name=fin:Esimerkkipalveluntarjoaja
#osu_nai=anonymous@example.com
+#osu_nai2=anonymous@example.com
#osu_method_list=1 0
#osu_icon=icon32
#osu_icon=icon64
diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c
index fbec5d2..489da39 100644
--- a/hostapd/hostapd_cli.c
+++ b/hostapd/hostapd_cli.c
@@ -1,6 +1,6 @@
/*
* hostapd - command line interface for hostapd daemon
- * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -21,7 +21,7 @@
static const char *const hostapd_cli_version =
"hostapd_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi> and contributors";
static struct wpa_ctrl *ctrl_conn;
static int hostapd_cli_quit = 0;
@@ -1637,7 +1637,7 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "dpp_configurator_remove", hostapd_cli_cmd_dpp_configurator_remove,
NULL,
"*|<id> = remove DPP configurator" },
- { "dpp_configurator_remove", hostapd_cli_cmd_dpp_configurator_get_key,
+ { "dpp_configurator_get_key", hostapd_cli_cmd_dpp_configurator_get_key,
NULL,
"<id> = Get DPP configurator's private key" },
{ "dpp_pkex_add", hostapd_cli_cmd_dpp_pkex_add, NULL,
diff --git a/hostapd/main.c b/hostapd/main.c
index cbeb607..414dfe4 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -1,6 +1,6 @@
/*
* hostapd / main()
- * Copyright (c) 2002-2017, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2002-2018, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -253,7 +253,7 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
*
* This function is used to parse configuration file for a full interface (one
* or more BSSes sharing the same radio) and allocate memory for the BSS
- * interfaces. No actiual driver operations are started.
+ * interfaces. No actual driver operations are started.
*/
static struct hostapd_iface *
hostapd_interface_init(struct hapd_interfaces *interfaces, const char *if_name,
@@ -456,7 +456,7 @@ static void show_version(void)
"hostapd v" VERSION_STR "\n"
"User space daemon for IEEE 802.11 AP management,\n"
"IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
- "Copyright (c) 2002-2017, Jouni Malinen <j@w1.fi> "
+ "Copyright (c) 2002-2018, Jouni Malinen <j@w1.fi> "
"and contributors\n");
}
@@ -873,27 +873,8 @@ int main(int argc, char *argv[])
*/
interfaces.terminate_on_error = interfaces.count;
for (i = 0; i < interfaces.count; i++) {
- if (hostapd_driver_init(interfaces.iface[i]))
- goto out;
-#ifdef CONFIG_MBO
- for (j = 0; j < interfaces.iface[i]->num_bss; j++) {
- struct hostapd_data *hapd = interfaces.iface[i]->bss[j];
-
- if (hapd && (hapd->conf->oce & OCE_STA_CFON) &&
- (interfaces.iface[i]->drv_flags &
- WPA_DRIVER_FLAGS_OCE_STA_CFON))
- hapd->enable_oce = OCE_STA_CFON;
-
- if (hapd && (hapd->conf->oce & OCE_AP) &&
- (interfaces.iface[i]->drv_flags &
- WPA_DRIVER_FLAGS_OCE_STA_CFON)) {
- /* TODO: Need to add OCE-AP support */
- wpa_printf(MSG_ERROR,
- "OCE-AP feature is not yet supported");
- }
- }
-#endif /* CONFIG_MBO */
- if (hostapd_setup_interface(interfaces.iface[i]))
+ if (hostapd_driver_init(interfaces.iface[i]) ||
+ hostapd_setup_interface(interfaces.iface[i]))
goto out;
}
diff --git a/hs20/client/oma_dm_client.c b/hs20/client/oma_dm_client.c
index 5854b72..d75c845 100644
--- a/hs20/client/oma_dm_client.c
+++ b/hs20/client/oma_dm_client.c
@@ -111,6 +111,12 @@ static xml_node_t * oma_dm_build_hdr(struct hs20_osu_client *ctx,
xml_node_t *syncml, *synchdr;
xml_namespace_t *ns;
+ if (!ctx->devid) {
+ wpa_printf(MSG_ERROR,
+ "DevId from devinfo.xml is not available - cannot use OMA DM");
+ return NULL;
+ }
+
syncml = xml_node_create_root(ctx->xml, "SYNCML:SYNCML1.2", NULL, &ns,
"SyncML");
diff --git a/hs20/client/osu_client.c b/hs20/client/osu_client.c
index b8791b6..636e106 100644
--- a/hs20/client/osu_client.c
+++ b/hs20/client/osu_client.c
@@ -436,7 +436,7 @@ static int cmd_dl_polupd_ca(struct hs20_osu_client *ctx, const char *pps_fname,
if (node == NULL) {
wpa_printf(MSG_INFO, "No Policy/PolicyUpdate/TrustRoot/CertURL found from PPS");
xml_node_free(ctx->xml, pps);
- return -1;
+ return -2;
}
ret = download_cert(ctx, node, ca_fname);
@@ -463,7 +463,7 @@ static int cmd_dl_aaa_ca(struct hs20_osu_client *ctx, const char *pps_fname,
if (node == NULL) {
wpa_printf(MSG_INFO, "No AAAServerTrustRoot/CertURL found from PPS");
xml_node_free(ctx->xml, pps);
- return -1;
+ return -2;
}
aaa = xml_node_first_child(ctx->xml, node);
@@ -485,7 +485,7 @@ static int download_trust_roots(struct hs20_osu_client *ctx,
{
char *dir, *pos;
char fname[300];
- int ret;
+ int ret, ret1;
dir = os_strdup(pps_fname);
if (dir == NULL)
@@ -500,9 +500,13 @@ static int download_trust_roots(struct hs20_osu_client *ctx,
snprintf(fname, sizeof(fname), "%s/ca.pem", dir);
ret = cmd_dl_osu_ca(ctx, pps_fname, fname);
snprintf(fname, sizeof(fname), "%s/polupd-ca.pem", dir);
- cmd_dl_polupd_ca(ctx, pps_fname, fname);
+ ret1 = cmd_dl_polupd_ca(ctx, pps_fname, fname);
+ if (ret == 0 && ret1 == -1)
+ ret = -1;
snprintf(fname, sizeof(fname), "%s/aaa-ca.pem", dir);
- cmd_dl_aaa_ca(ctx, pps_fname, fname);
+ ret1 = cmd_dl_aaa_ca(ctx, pps_fname, fname);
+ if (ret == 0 && ret1 == -1)
+ ret = -1;
os_free(dir);
@@ -1987,6 +1991,7 @@ struct osu_data {
char osu_ssid[33];
char osu_ssid2[33];
char osu_nai[256];
+ char osu_nai2[256];
struct osu_lang_text friendly_name[MAX_OSU_VALS];
size_t friendly_name_count;
struct osu_lang_text serv_desc[MAX_OSU_VALS];
@@ -2057,6 +2062,12 @@ static struct osu_data * parse_osu_providers(const char *fname, size_t *count)
continue;
}
+ if (os_strncmp(buf, "osu_nai2=", 9) == 0) {
+ os_snprintf(last->osu_nai2, sizeof(last->osu_nai2),
+ "%s", buf + 9);
+ continue;
+ }
+
if (strncmp(buf, "friendly_name=", 14) == 0) {
struct osu_lang_text *txt;
if (last->friendly_name_count == MAX_OSU_VALS)
@@ -2134,7 +2145,7 @@ static struct osu_data * parse_osu_providers(const char *fname, size_t *count)
static int osu_connect(struct hs20_osu_client *ctx, const char *bssid,
const char *ssid, const char *ssid2, const char *url,
unsigned int methods, int no_prod_assoc,
- const char *osu_nai)
+ const char *osu_nai, const char *osu_nai2)
{
int id;
const char *ifname = ctx->ifname;
@@ -2166,6 +2177,8 @@ static int osu_connect(struct hs20_osu_client *ctx, const char *bssid,
return -1;
if (set_network_quoted(ifname, id, "ssid", ssid) < 0)
return -1;
+ if (ssid2)
+ osu_nai = osu_nai2;
if (osu_nai && os_strlen(osu_nai) > 0) {
char dir[255], fname[300];
if (getcwd(dir, sizeof(dir)) == NULL)
@@ -2184,6 +2197,10 @@ static int osu_connect(struct hs20_osu_client *ctx, const char *bssid,
set_network_quoted(ifname, id, "identity", osu_nai) < 0 ||
set_network_quoted(ifname, id, "ca_cert", fname) < 0)
return -1;
+ } else if (ssid2) {
+ wpa_printf(MSG_INFO, "No OSU_NAI set for RSN[OSEN]");
+ write_summary(ctx, "No OSU_NAI set for RSN[OSEN]");
+ return -1;
} else {
if (set_network(ifname, id, "key_mgmt", "NONE") < 0)
return -1;
@@ -2363,6 +2380,8 @@ static int cmd_osu_select(struct hs20_osu_client *ctx, const char *dir,
fprintf(f, "SSID2: %s<br>\n", last->osu_ssid2);
if (last->osu_nai[0])
fprintf(f, "NAI: %s<br>\n", last->osu_nai);
+ if (last->osu_nai2[0])
+ fprintf(f, "NAI2: %s<br>\n", last->osu_nai2);
fprintf(f, "URL: %s<br>\n"
"methods:%s%s<br>\n"
"</small></p>\n",
@@ -2449,7 +2468,8 @@ selected:
ret = osu_connect(ctx, last->bssid, last->osu_ssid,
last->osu_ssid2,
last->url, last->methods,
- no_prod_assoc, last->osu_nai);
+ no_prod_assoc, last->osu_nai,
+ last->osu_nai2);
}
} else
ret = -1;
@@ -3048,24 +3068,17 @@ static int init_ctx(struct hs20_osu_client *ctx)
return -1;
devinfo = node_from_file(ctx->xml, "devinfo.xml");
- if (!devinfo) {
- wpa_printf(MSG_ERROR, "devinfo.xml not found");
- return -1;
- }
-
- devid = get_node(ctx->xml, devinfo, "DevId");
- if (devid) {
- char *tmp = xml_node_get_text(ctx->xml, devid);
- if (tmp) {
- ctx->devid = os_strdup(tmp);
- xml_node_get_text_free(ctx->xml, tmp);
+ if (devinfo) {
+ devid = get_node(ctx->xml, devinfo, "DevId");
+ if (devid) {
+ char *tmp = xml_node_get_text(ctx->xml, devid);
+
+ if (tmp) {
+ ctx->devid = os_strdup(tmp);
+ xml_node_get_text_free(ctx->xml, tmp);
+ }
}
- }
- xml_node_free(ctx->xml, devinfo);
-
- if (ctx->devid == NULL) {
- wpa_printf(MSG_ERROR, "Could not fetch DevId from devinfo.xml");
- return -1;
+ xml_node_free(ctx->xml, devinfo);
}
ctx->http = http_init_ctx(ctx, ctx->xml);
diff --git a/hs20/server/hs20_spp_server.c b/hs20/server/hs20_spp_server.c
index 591f66b..abd6867 100644
--- a/hs20/server/hs20_spp_server.c
+++ b/hs20/server/hs20_spp_server.c
@@ -70,6 +70,10 @@ static int process(struct hs20_svc *ctx)
ctx->addr = getenv("HS20ADDR");
if (ctx->addr)
debug_print(ctx, 1, "Connection from %s", ctx->addr);
+ ctx->test = getenv("HS20TEST");
+ if (ctx->test)
+ debug_print(ctx, 1, "Requested test functionality: %s",
+ ctx->test);
user = getenv("HS20USER");
if (user && strlen(user) == 0)
diff --git a/hs20/server/spp_server.c b/hs20/server/spp_server.c
index c3681ee..e5af4c2 100644
--- a/hs20/server/spp_server.c
+++ b/hs20/server/spp_server.c
@@ -69,14 +69,14 @@ static int db_add_session(struct hs20_svc *ctx,
else
addr[0] = '\0';
sql = sqlite3_mprintf("INSERT INTO sessions(timestamp,id,user,realm,"
- "operation,password,redirect_uri,mac_addr) "
+ "operation,password,redirect_uri,mac_addr,test) "
"VALUES "
"(strftime('%%Y-%%m-%%d %%H:%%M:%%f','now'),"
- "%Q,%Q,%Q,%d,%Q,%Q,%Q)",
+ "%Q,%Q,%Q,%d,%Q,%Q,%Q,%Q)",
sessionid, user ? user : "", realm ? realm : "",
operation, pw ? pw : "",
redirect_uri ? redirect_uri : "",
- addr);
+ addr, ctx->test);
if (sql == NULL)
return -1;
debug_print(ctx, 1, "DB: %s", sql);
@@ -336,6 +336,29 @@ static void add_text_node_conf(struct hs20_svc *ctx, const char *realm,
}
+static void add_text_node_conf_corrupt(struct hs20_svc *ctx, const char *realm,
+ xml_node_t *parent, const char *name,
+ const char *field)
+{
+ char *val;
+
+ val = db_get_osu_config_val(ctx, realm, field);
+ if (val) {
+ size_t len;
+
+ len = os_strlen(val);
+ if (len > 0) {
+ if (val[len - 1] == '0')
+ val[len - 1] = '1';
+ else
+ val[len - 1] = '0';
+ }
+ }
+ xml_node_create_text(ctx->xml, parent, NULL, name, val ? val : "");
+ os_free(val);
+}
+
+
static int new_password(char *buf, int buflen)
{
int i;
@@ -540,7 +563,8 @@ static xml_node_t * build_username_password(struct hs20_svc *ctx,
static int add_username_password(struct hs20_svc *ctx, xml_node_t *cred,
- const char *user, const char *pw)
+ const char *user, const char *pw,
+ int machine_managed)
{
xml_node_t *node;
@@ -548,7 +572,8 @@ static int add_username_password(struct hs20_svc *ctx, xml_node_t *cred,
if (node == NULL)
return -1;
- add_text_node(ctx, node, "MachineManaged", "TRUE");
+ add_text_node(ctx, node, "MachineManaged",
+ machine_managed ? "TRUE" : "FALSE");
add_text_node(ctx, node, "SoftTokenApp", "");
add_eap_ttls(ctx, node);
@@ -573,7 +598,7 @@ static void add_creation_date(struct hs20_svc *ctx, xml_node_t *cred)
static xml_node_t * build_credential_pw(struct hs20_svc *ctx,
const char *user, const char *realm,
- const char *pw)
+ const char *pw, int machine_managed)
{
xml_node_t *cred;
@@ -583,7 +608,7 @@ static xml_node_t * build_credential_pw(struct hs20_svc *ctx,
return NULL;
}
add_creation_date(ctx, cred);
- if (add_username_password(ctx, cred, user, pw) < 0) {
+ if (add_username_password(ctx, cred, user, pw, machine_managed) < 0) {
xml_node_free(ctx->xml, cred);
return NULL;
}
@@ -600,7 +625,7 @@ static xml_node_t * build_credential(struct hs20_svc *ctx,
if (new_password(new_pw, new_pw_len) < 0)
return NULL;
debug_print(ctx, 1, "Update password to '%s'", new_pw);
- return build_credential_pw(ctx, user, realm, new_pw);
+ return build_credential_pw(ctx, user, realm, new_pw, 1);
}
@@ -710,8 +735,23 @@ static xml_node_t * build_sub_rem_resp(struct hs20_svc *ctx,
cred = build_credential_cert(ctx, real_user ? real_user : user,
realm, cert);
} else {
- cred = build_credential(ctx, real_user ? real_user : user,
- realm, new_pw, sizeof(new_pw));
+ char *pw;
+
+ pw = db_get_session_val(ctx, user, realm, session_id,
+ "password");
+ if (pw && pw[0]) {
+ debug_print(ctx, 1, "New password from the user: '%s'",
+ pw);
+ snprintf(new_pw, sizeof(new_pw), "%s", pw);
+ free(pw);
+ cred = build_credential_pw(ctx,
+ real_user ? real_user : user,
+ realm, new_pw, 0);
+ } else {
+ cred = build_credential(ctx,
+ real_user ? real_user : user,
+ realm, new_pw, sizeof(new_pw));
+ }
}
free(real_user);
if (!cred) {
@@ -728,7 +768,7 @@ static xml_node_t * build_sub_rem_resp(struct hs20_svc *ctx,
}
snprintf(buf, sizeof(buf),
- "./Wi-Fi/%s/PerProviderSubscription/Credential1/Credential",
+ "./Wi-Fi/%s/PerProviderSubscription/Cred01/Credential",
realm);
if (add_update_node(ctx, spp_node, ns, buf, cred) < 0) {
@@ -794,7 +834,7 @@ static xml_node_t * policy_remediation(struct hs20_svc *ctx,
return NULL;
snprintf(buf, sizeof(buf),
- "./Wi-Fi/%s/PerProviderSubscription/Credential1/Policy",
+ "./Wi-Fi/%s/PerProviderSubscription/Cred01/Policy",
realm);
if (add_update_node(ctx, spp_node, ns, buf, policy) < 0) {
@@ -947,8 +987,10 @@ static xml_node_t * hs20_subscription_remediation(struct hs20_svc *ctx,
redirect_uri);
else if (type && strcmp(type, "policy") == 0)
ret = policy_remediation(ctx, user, realm, session_id, dmacc);
- else
+ else if (type && strcmp(type, "machine") == 0)
ret = machine_remediation(ctx, user, realm, session_id, dmacc);
+ else
+ ret = no_sub_rem(ctx, user, realm, session_id);
free(type);
return ret;
@@ -1050,7 +1092,7 @@ static xml_node_t * hs20_policy_update(struct hs20_svc *ctx,
return NULL;
snprintf(buf, sizeof(buf),
- "./Wi-Fi/%s/PerProviderSubscription/Credential1/Policy",
+ "./Wi-Fi/%s/PerProviderSubscription/Cred01/Policy",
realm);
if (add_update_node(ctx, spp_node, ns, buf, policy) < 0) {
@@ -1222,9 +1264,9 @@ static char * db_get_osu_config_val(struct hs20_svc *ctx, const char *realm,
static xml_node_t * build_pps(struct hs20_svc *ctx,
const char *user, const char *realm,
const char *pw, const char *cert,
- int machine_managed)
+ int machine_managed, const char *test)
{
- xml_node_t *pps, *c, *trust, *aaa, *aaa1, *upd, *homesp;
+ xml_node_t *pps, *c, *trust, *aaa, *aaa1, *upd, *homesp, *p;
xml_node_t *cred, *eap, *userpw;
pps = xml_node_create_root(ctx->xml, NULL, NULL, NULL,
@@ -1234,7 +1276,7 @@ static xml_node_t * build_pps(struct hs20_svc *ctx,
add_text_node(ctx, pps, "UpdateIdentifier", "1");
- c = xml_node_create(ctx->xml, pps, NULL, "Credential1");
+ c = xml_node_create(ctx->xml, pps, NULL, "Cred01");
add_text_node(ctx, c, "CredentialPriority", "1");
@@ -1242,18 +1284,51 @@ static xml_node_t * build_pps(struct hs20_svc *ctx,
aaa1 = xml_node_create(ctx->xml, aaa, NULL, "AAA1");
add_text_node_conf(ctx, realm, aaa1, "CertURL",
"aaa_trust_root_cert_url");
- add_text_node_conf(ctx, realm, aaa1, "CertSHA256Fingerprint",
- "aaa_trust_root_cert_fingerprint");
+ if (test && os_strcmp(test, "corrupt_aaa_hash") == 0) {
+ debug_print(ctx, 1,
+ "TEST: Corrupt PPS/Cred*/AAAServerTrustRoot/Root*/CertSHA256FingerPrint");
+ add_text_node_conf_corrupt(ctx, realm, aaa1,
+ "CertSHA256Fingerprint",
+ "aaa_trust_root_cert_fingerprint");
+ } else {
+ add_text_node_conf(ctx, realm, aaa1, "CertSHA256Fingerprint",
+ "aaa_trust_root_cert_fingerprint");
+ }
+
+ if (test && os_strcmp(test, "corrupt_polupd_hash") == 0) {
+ debug_print(ctx, 1,
+ "TEST: Corrupt PPS/Cred*/Policy/PolicyUpdate/Trustroot/CertSHA256FingerPrint");
+ p = xml_node_create(ctx->xml, c, NULL, "Policy");
+ upd = xml_node_create(ctx->xml, p, NULL, "PolicyUpdate");
+ add_text_node(ctx, upd, "UpdateInterval", "30");
+ add_text_node(ctx, upd, "UpdateMethod", "SPP-ClientInitiated");
+ add_text_node(ctx, upd, "Restriction", "Unrestricted");
+ add_text_node_conf(ctx, realm, upd, "URI", "policy_url");
+ trust = xml_node_create(ctx->xml, upd, NULL, "TrustRoot");
+ add_text_node_conf(ctx, realm, trust, "CertURL",
+ "policy_trust_root_cert_url");
+ add_text_node_conf_corrupt(ctx, realm, trust,
+ "CertSHA256Fingerprint",
+ "policy_trust_root_cert_fingerprint");
+ }
upd = xml_node_create(ctx->xml, c, NULL, "SubscriptionUpdate");
add_text_node(ctx, upd, "UpdateInterval", "4294967295");
- add_text_node(ctx, upd, "UpdateMethod", "ClientInitiated");
+ add_text_node(ctx, upd, "UpdateMethod", "SPP-ClientInitiated");
add_text_node(ctx, upd, "Restriction", "HomeSP");
add_text_node_conf(ctx, realm, upd, "URI", "spp_http_auth_url");
trust = xml_node_create(ctx->xml, upd, NULL, "TrustRoot");
add_text_node_conf(ctx, realm, trust, "CertURL", "trust_root_cert_url");
- add_text_node_conf(ctx, realm, trust, "CertSHA256Fingerprint",
- "trust_root_cert_fingerprint");
+ if (test && os_strcmp(test, "corrupt_subrem_hash") == 0) {
+ debug_print(ctx, 1,
+ "TEST: Corrupt PPS/Cred*/SubscriptionUpdate/Trustroot/CertSHA256FingerPrint");
+ add_text_node_conf_corrupt(ctx, realm, trust,
+ "CertSHA256Fingerprint",
+ "trust_root_cert_fingerprint");
+ } else {
+ add_text_node_conf(ctx, realm, trust, "CertSHA256Fingerprint",
+ "trust_root_cert_fingerprint");
+ }
homesp = xml_node_create(ctx->xml, c, NULL, "HomeSP");
add_text_node_conf(ctx, realm, homesp, "FriendlyName", "friendly_name");
@@ -1337,7 +1412,7 @@ static xml_node_t * hs20_user_input_registration(struct hs20_svc *ctx,
xml_node_t *pps, *tnds;
char buf[400];
char *str;
- char *user, *realm, *pw, *type, *mm;
+ char *user, *realm, *pw, *type, *mm, *test;
const char *status;
int cert = 0;
int machine_managed = 0;
@@ -1396,9 +1471,15 @@ static xml_node_t * hs20_user_input_registration(struct hs20_svc *ctx,
return NULL;
fingerprint = db_get_session_val(ctx, NULL, NULL, session_id, "cert");
+ test = db_get_session_val(ctx, NULL, NULL, session_id, "test");
+ if (test)
+ debug_print(ctx, 1, "TEST: Requested special behavior: %s",
+ test);
pps = build_pps(ctx, user, realm, pw,
- fingerprint ? fingerprint : NULL, machine_managed);
+ fingerprint ? fingerprint : NULL, machine_managed,
+ test);
free(fingerprint);
+ free(test);
if (!pps) {
xml_node_free(ctx->xml, spp_node);
free(user);
@@ -1469,7 +1550,7 @@ static xml_node_t * hs20_user_input_free_remediation(struct hs20_svc *ctx,
return NULL;
}
- cred = build_credential_pw(ctx, free_account, realm, pw);
+ cred = build_credential_pw(ctx, free_account, realm, pw, 1);
free(free_account);
free(pw);
if (!cred) {
@@ -1484,7 +1565,7 @@ static xml_node_t * hs20_user_input_free_remediation(struct hs20_svc *ctx,
return NULL;
snprintf(buf, sizeof(buf),
- "./Wi-Fi/%s/PerProviderSubscription/Credential1/Credential",
+ "./Wi-Fi/%s/PerProviderSubscription/Cred01/Credential",
realm);
if (add_update_node(ctx, spp_node, ns, buf, cred) < 0) {
@@ -2181,6 +2262,9 @@ static xml_node_t * hs20_spp_update_response(struct hs20_svc *ctx,
"", dmacc);
free(val);
}
+ if (oper == POLICY_UPDATE)
+ db_update_val(ctx, user, realm, "polupd_done", "1",
+ dmacc);
ret = build_spp_exchange_complete(
ctx, session_id,
"Exchange complete, release TLS connection", NULL);
diff --git a/hs20/server/spp_server.h b/hs20/server/spp_server.h
index 7b27be3..3556f5c 100644
--- a/hs20/server/spp_server.h
+++ b/hs20/server/spp_server.h
@@ -16,6 +16,7 @@ struct hs20_svc {
FILE *debug_log;
sqlite3 *db;
const char *addr;
+ const char *test;
};
diff --git a/hs20/server/sql.txt b/hs20/server/sql.txt
index 2ecd9c2..666ef13 100644
--- a/hs20/server/sql.txt
+++ b/hs20/server/sql.txt
@@ -23,7 +23,8 @@ CREATE TABLE sessions(
devdetail TEXT,
cert TEXT,
cert_pem TEXT,
- mac_addr TEXT
+ mac_addr TEXT,
+ test TEXT
);
CREATE index sessions_id_index ON sessions(id);
@@ -53,7 +54,9 @@ CREATE TABLE users(
cert TEXT,
cert_pem TEXT,
t_c_timestamp INTEGER,
- mac_addr TEXT
+ mac_addr TEXT,
+ last_msk TEXT,
+ polupd_done TEXT,
);
CREATE TABLE wildcards(
diff --git a/hs20/server/www/remediation-pw.php b/hs20/server/www/remediation-pw.php
new file mode 100644
index 0000000..76fdccb
--- /dev/null
+++ b/hs20/server/www/remediation-pw.php
@@ -0,0 +1,41 @@
+<?php
+
+require('config.php');
+
+$db = new PDO($osu_db);
+if (!$db) {
+ die($sqliteerror);
+}
+
+if (isset($_POST["id"]))
+ $id = preg_replace("/[^a-fA-F0-9]/", "", $_POST["id"]);
+else
+ die("Missing session id");
+
+$pw = $_POST["password"];
+if (strlen($id) < 32 || !isset($pw)) {
+ die("Invalid POST data");
+}
+
+$row = $db->query("SELECT rowid,* FROM sessions WHERE id='$id'")->fetch();
+if ($row == false) {
+ die("Session not found");
+}
+$user = $row['user'];
+$realm = $row['realm'];
+
+$uri = $row['redirect_uri'];
+$rowid = $row['rowid'];
+
+if (!$db->exec("UPDATE sessions SET password='$pw' WHERE rowid=$rowid")) {
+ die("Failed to update session database");
+}
+
+$db->exec("INSERT INTO eventlog(user,realm,sessionid,timestamp,notes) " .
+ "VALUES ('$user', '$realm', '$id', " .
+ "strftime('%Y-%m-%d %H:%M:%f','now'), " .
+ "'completed user input response for subscription remediation')");
+
+header("Location: $uri", true, 302);
+
+?>
diff --git a/hs20/server/www/remediation.php b/hs20/server/www/remediation.php
index 392a7bd..3628065 100644
--- a/hs20/server/www/remediation.php
+++ b/hs20/server/www/remediation.php
@@ -6,13 +6,50 @@
<?php
-echo "SessionID: " . $_GET["session_id"] . "<br>\n";
+require('config.php');
-echo "<a href=\"redirect.php?id=" . $_GET["session_id"] . "\">Complete user subscription remediation</a><br>\n";
+$db = new PDO($osu_db);
+if (!$db) {
+ die($sqliteerror);
+}
-?>
+if (isset($_GET["session_id"]))
+ $id = preg_replace("/[^a-fA-F0-9]/", "", $_GET["session_id"]);
+else
+ $id = 0;
+echo "SessionID: " . $id . "<br>\n";
+
+$row = $db->query("SELECT * FROM sessions WHERE id='$id'")->fetch();
+if ($row == false) {
+ die("Session not found");
+}
+
+$username = $row['user'];
+echo "User: " . $username . "@" . $row['realm'] . "<br>\n";
+
+$user = $db->query("SELECT machine_managed,methods FROM users WHERE identity='$username'")->fetch();
+if ($user == false) {
+ die("User not found");
+}
-This will provide a new machine-generated password.
+echo "<hr><br>\n";
+
+$cert = $user['methods'] == "TLS" || strncmp($username, "cert-", 5) == 0;
+
+if ($cert) {
+ echo "<a href=\"redirect.php?id=" . $_GET["session_id"] . "\">Complete user subscription remediation</a><br>\n";
+} else if ($user['machine_managed'] == "1") {
+ echo "<a href=\"redirect.php?id=" . $_GET["session_id"] . "\">Complete user subscription remediation</a><br>\n";
+ echo "This will provide a new machine-generated password.<br>\n";
+} else {
+ echo "<form action=\"remediation-pw.php\" method=\"POST\">\n";
+ echo "<input type=\"hidden\" name=\"id\" value=\"$id\">\n";
+ echo "New password: <input type=\"password\" name=\"password\"><br>\n";
+ echo "<input type=\"submit\" value=\"Change password\">\n";
+ echo "</form>\n";
+}
+
+?>
</body>
</html>
diff --git a/hs20/server/www/signup.php b/hs20/server/www/signup.php
index aeb2f68..80a9d40 100644
--- a/hs20/server/www/signup.php
+++ b/hs20/server/www/signup.php
@@ -15,19 +15,30 @@ if (!$db) {
die($sqliteerror);
}
-$row = $db->query("SELECT realm FROM sessions WHERE id='$id'")->fetch();
+$row = $db->query("SELECT realm,test FROM sessions WHERE id='$id'")->fetch();
if ($row == false) {
die("Session not found for id: $id");
}
$realm = $row['realm'];
+$test = $row['test'];
+
+if (strlen($test) > 0) {
+ echo "<p style=\"color:#FF0000\">Special test functionality: $test</red></big></p>\n";
+}
echo "<h3>Sign up for a subscription - $realm</h3>\n";
+echo "<p>This page can be used to select between three different types of subscriptions for testing purposes.</p>\n";
+
+echo "<h4>Option 1 - shared free access credential</h4>\n";
+
$row = $db->query("SELECT value FROM osu_config WHERE realm='$realm' AND field='free_account'")->fetch();
if ($row && strlen($row['value']) > 0) {
echo "<p><a href=\"free.php?session_id=$id\">Sign up for free access</a></p>\n";
}
+echo "<h4>Option 2 - username/password credential</h4>\n";
+
echo "<form action=\"add-mo.php\" method=\"POST\">\n";
echo "<input type=\"hidden\" name=\"id\" value=\"$id\">\n";
?>
@@ -39,6 +50,8 @@ Password: <input type="password" name="password"><br>
</form>
<?php
+echo "<h4>Option 3 - client certificate credential</h4>\n";
+
echo "<p><a href=\"cert-enroll.php?id=$id\">Enroll a client certificate</a></p>\n"
?>
diff --git a/hs20/server/www/spp.php b/hs20/server/www/spp.php
index 002d028..f10e5ab 100644
--- a/hs20/server/www/spp.php
+++ b/hs20/server/www/spp.php
@@ -20,6 +20,11 @@ if (isset($_GET["realm"])) {
die("Realm not specified");
}
+if (isset($_GET["test"]))
+ $test = PREG_REPLACE("/[^0-9a-zA-Z\_\-]/i", '', $_GET["test"]);
+else
+ $test = "";
+
unset($user);
putenv("HS20CERT");
@@ -100,6 +105,7 @@ $postdata = file_get_contents("php://input");
putenv("HS20POST=$postdata");
$addr = $_SERVER["REMOTE_ADDR"];
putenv("HS20ADDR=$addr");
+putenv("HS20TEST=$test");
$last = exec("$osu_root/spp/hs20_spp_server -r$osu_root -f/tmp/hs20_spp_server.log", $output, $ret);
diff --git a/hs20/server/www/users.php b/hs20/server/www/users.php
index b6c6298..f546de3 100644
--- a/hs20/server/www/users.php
+++ b/hs20/server/www/users.php
@@ -191,6 +191,9 @@ if ($rem == "") {
}
echo "<br>\n";
+if (strncmp($row['identity'], "cert-", 5) != 0)
+ echo "Machine managed: " . ($row['machine_managed'] == "1" ? "TRUE" : "FALSE") . "<br>\n";
+
echo "<form>Policy: <select name=\"policy\" " .
"onChange=\"window.location='users.php?cmd=policy&id=" .
$row['rowid'] . "&policy=' + this.value;\">\n";
@@ -313,10 +316,10 @@ if ($id == 0 && $cmd != 'eventlog') {
echo "[<a href=\"users.php?cmd=eventlog&limit=50\">Eventlog</a>] ";
echo "<br>\n";
-echo "<table border=1>\n";
-echo "<tr><th>User<th>Realm<th>Remediation<th>Policy<th>Account type<th>Phase 2 method(s)<th>DevId<th>MAC Address<th>T&C\n";
+echo "<table border=1 cellspacing=0 cellpadding=0>\n";
+echo "<tr><th>User<th>Realm<th><small>Remediation</small><th>Policy<th><small>Account type</small><th><small>Phase 2 method(s)</small><th>DevId<th>MAC Address<th>T&C\n";
-$res = $db->query('SELECT rowid,* FROM users WHERE phase2=1');
+$res = $db->query('SELECT rowid,* FROM users WHERE phase2=1 ORDER BY identity');
foreach ($res as $row) {
echo "<tr><td><a href=\"users.php?id=" . $row['rowid'] . "\"> " .
$row['identity'] . " </a>";
@@ -324,7 +327,7 @@ foreach ($res as $row) {
$rem = $row['remediation'];
echo "<td>";
if ($rem == "") {
- echo "Not required";
+ echo "-";
} else if ($rem == "user") {
echo "User";
} else if ($rem == "policy") {
@@ -339,18 +342,18 @@ foreach ($res as $row) {
echo "<td>shared";
else
echo "<td>default";
- echo "<td>" . $row['methods'];
+ echo "<td><small>" . $row['methods'] . "</small>";
echo "<td>";
$xml = xml_parser_create();
xml_parse_into_struct($xml, $row['devinfo'], $devinfo);
foreach($devinfo as $k) {
if ($k['tag'] == 'DEVID') {
- echo $k['value'];
+ echo "<small>" . $k['value'] . "</small>";
break;
}
}
- echo "<td>" . $row['mac_addr'];
- echo "<td>" . $row['t_c_timestamp'];
+ echo "<td><small>" . $row['mac_addr'] . "</small>";
+ echo "<td><small>" . $row['t_c_timestamp'] . "</small>";
echo "\n";
}
echo "</table>\n";
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 820cba9..f9b6f29 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -631,6 +631,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf)
os_free(p->icons[j]);
os_free(p->icons);
os_free(p->osu_nai);
+ os_free(p->osu_nai2);
os_free(p->service_desc);
}
os_free(conf->hs20_osu_providers);
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 5b71126..778366d 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -585,10 +585,12 @@ struct hostapd_bss_config {
char **icons;
size_t icons_count;
char *osu_nai;
+ char *osu_nai2;
unsigned int service_desc_count;
struct hostapd_lang_string *service_desc;
} *hs20_osu_providers, *last_osu;
size_t hs20_osu_providers_count;
+ size_t hs20_osu_providers_nai_count;
char **hs20_operator_icon;
size_t hs20_operator_icon_count;
unsigned int hs20_deauth_req_timeout;
@@ -682,6 +684,8 @@ struct hostapd_bss_config {
char owe_transition_ifname[IFNAMSIZ + 1];
int *owe_groups;
#endif /* CONFIG_OWE */
+
+ int coloc_intf_reporting;
};
/**
diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c
index 728d7f0..067cf86 100644
--- a/src/ap/ap_drv_ops.c
+++ b/src/ap/ap_drv_ops.c
@@ -176,7 +176,8 @@ int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
#endif /* CONFIG_HS20 */
#ifdef CONFIG_MBO
- if (hapd->conf->mbo_enabled || hapd->enable_oce) {
+ if (hapd->conf->mbo_enabled ||
+ OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) {
pos = hostapd_eid_mbo(hapd, buf, sizeof(buf));
if (add_buf_data(&beacon, buf, pos - buf) < 0 ||
add_buf_data(&proberesp, buf, pos - buf) < 0 ||
diff --git a/src/ap/authsrv.c b/src/ap/authsrv.c
index 66d255c..95d004e 100644
--- a/src/ap/authsrv.c
+++ b/src/ap/authsrv.c
@@ -155,6 +155,40 @@ static int hostapd_setup_radius_srv(struct hostapd_data *hapd)
#endif /* RADIUS_SERVER */
+#ifdef EAP_TLS_FUNCS
+static void authsrv_tls_event(void *ctx, enum tls_event ev,
+ union tls_event_data *data)
+{
+ switch (ev) {
+ case TLS_CERT_CHAIN_SUCCESS:
+ wpa_printf(MSG_DEBUG, "authsrv: remote certificate verification success");
+ break;
+ case TLS_CERT_CHAIN_FAILURE:
+ wpa_printf(MSG_INFO, "authsrv: certificate chain failure: reason=%d depth=%d subject='%s' err='%s'",
+ data->cert_fail.reason,
+ data->cert_fail.depth,
+ data->cert_fail.subject,
+ data->cert_fail.reason_txt);
+ break;
+ case TLS_PEER_CERTIFICATE:
+ wpa_printf(MSG_DEBUG, "authsrv: peer certificate: depth=%d serial_num=%s subject=%s",
+ data->peer_cert.depth,
+ data->peer_cert.serial_num ? data->peer_cert.serial_num : "N/A",
+ data->peer_cert.subject);
+ break;
+ case TLS_ALERT:
+ if (data->alert.is_local)
+ wpa_printf(MSG_DEBUG, "authsrv: local TLS alert: %s",
+ data->alert.description);
+ else
+ wpa_printf(MSG_DEBUG, "authsrv: remote TLS alert: %s",
+ data->alert.description);
+ break;
+ }
+}
+#endif /* EAP_TLS_FUNCS */
+
+
int authsrv_init(struct hostapd_data *hapd)
{
#ifdef EAP_TLS_FUNCS
@@ -167,6 +201,8 @@ int authsrv_init(struct hostapd_data *hapd)
os_memset(&conf, 0, sizeof(conf));
conf.tls_session_lifetime = hapd->conf->tls_session_lifetime;
conf.tls_flags = hapd->conf->tls_flags;
+ conf.event_cb = authsrv_tls_event;
+ conf.cb_ctx = hapd;
hapd->ssl_ctx = tls_init(&conf);
if (hapd->ssl_ctx == NULL) {
wpa_printf(MSG_ERROR, "Failed to initialize TLS");
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 7d079d2..59bd4af 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -453,8 +453,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
/* Extended supported rates */
pos = hostapd_eid_ext_supp_rates(hapd, pos);
- /* RSN, MDIE, WPA */
- pos = hostapd_eid_wpa(hapd, pos, epos - pos);
+ /* RSN, MDIE */
+ if (hapd->conf->wpa != WPA_PROTO_WPA)
+ pos = hostapd_eid_wpa(hapd, pos, epos - pos);
pos = hostapd_eid_bss_load(hapd, pos, epos - pos);
@@ -517,6 +518,10 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
pos = hostapd_eid_vendor_vht(hapd, pos);
#endif /* CONFIG_IEEE80211AC */
+ /* WPA */
+ if (hapd->conf->wpa == WPA_PROTO_WPA)
+ pos = hostapd_eid_wpa(hapd, pos, epos - pos);
+
/* Wi-Fi Alliance WMM */
pos = hostapd_eid_wmm(hapd, pos);
@@ -1152,9 +1157,11 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
/* Extended supported rates */
tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos);
- /* RSN, MDIE, WPA */
- tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE -
- tailpos);
+ /* RSN, MDIE */
+ if (hapd->conf->wpa != WPA_PROTO_WPA)
+ tailpos = hostapd_eid_wpa(hapd, tailpos,
+ tail + BEACON_TAIL_BUF_SIZE -
+ tailpos);
tailpos = hostapd_eid_rm_enabled_capab(hapd, tailpos,
tail + BEACON_TAIL_BUF_SIZE -
@@ -1223,6 +1230,12 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
tailpos = hostapd_eid_vendor_vht(hapd, tailpos);
#endif /* CONFIG_IEEE80211AC */
+ /* WPA */
+ if (hapd->conf->wpa == WPA_PROTO_WPA)
+ tailpos = hostapd_eid_wpa(hapd, tailpos,
+ tail + BEACON_TAIL_BUF_SIZE -
+ tailpos);
+
/* Wi-Fi Alliance WMM */
tailpos = hostapd_eid_wmm(hapd, tailpos);
diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c
index 4ec044e..149f389 100644
--- a/src/ap/dpp_hostapd.c
+++ b/src/ap/dpp_hostapd.c
@@ -505,9 +505,9 @@ static void hostapd_dpp_set_testing_options(struct hostapd_data *hapd,
}
-static void hostapd_dpp_set_configurator(struct hostapd_data *hapd,
- struct dpp_authentication *auth,
- const char *cmd)
+static int hostapd_dpp_set_configurator(struct hostapd_data *hapd,
+ struct dpp_authentication *auth,
+ const char *cmd)
{
const char *pos, *end;
struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL;
@@ -521,7 +521,7 @@ static void hostapd_dpp_set_configurator(struct hostapd_data *hapd,
char *group_id = NULL;
if (!cmd)
- return;
+ return 0;
wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
pos = os_strstr(cmd, " ssid=");
@@ -618,10 +618,12 @@ static void hostapd_dpp_set_configurator(struct hostapd_data *hapd,
conf_ap->akm = DPP_AKM_PSK;
if (psk_set) {
os_memcpy(conf_ap->psk, psk, PMK_LEN);
- } else {
+ } else if (pass_len > 0) {
conf_ap->passphrase = os_strdup(pass);
if (!conf_ap->passphrase)
goto fail;
+ } else {
+ goto fail;
}
} else if (os_strstr(cmd, " conf=ap-dpp")) {
conf_ap->akm = DPP_AKM_DPP;
@@ -663,13 +665,15 @@ static void hostapd_dpp_set_configurator(struct hostapd_data *hapd,
auth->conf_ap = conf_ap;
auth->conf = conf;
os_free(group_id);
- return;
+ return 0;
fail:
- wpa_printf(MSG_DEBUG, "DPP: Failed to set configurator parameters");
+ wpa_msg(hapd->msg_ctx, MSG_INFO,
+ "DPP: Failed to set configurator parameters");
dpp_configuration_free(conf_sta);
dpp_configuration_free(conf_ap);
os_free(group_id);
+ return -1;
}
@@ -842,7 +846,11 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd)
if (!hapd->dpp_auth)
goto fail;
hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
- hostapd_dpp_set_configurator(hapd, hapd->dpp_auth, cmd);
+ if (hostapd_dpp_set_configurator(hapd, hapd->dpp_auth, cmd) < 0) {
+ dpp_auth_deinit(hapd->dpp_auth);
+ hapd->dpp_auth = NULL;
+ goto fail;
+ }
hapd->dpp_auth->neg_freq = neg_freq;
@@ -967,8 +975,12 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src,
return;
}
hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth);
- hostapd_dpp_set_configurator(hapd, hapd->dpp_auth,
- hapd->dpp_configurator_params);
+ if (hostapd_dpp_set_configurator(hapd, hapd->dpp_auth,
+ hapd->dpp_configurator_params) < 0) {
+ dpp_auth_deinit(hapd->dpp_auth);
+ hapd->dpp_auth = NULL;
+ return;
+ }
os_memcpy(hapd->dpp_auth->peer_mac_addr, src, ETH_ALEN);
wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR
@@ -1892,9 +1904,9 @@ int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd)
return -1;
curve = get_param(cmd, " curve=");
- hostapd_dpp_set_configurator(hapd, auth, cmd);
-
- if (dpp_configurator_own_config(auth, curve, 1) == 0) {
+ hostapd_dpp_set_testing_options(hapd, auth);
+ if (hostapd_dpp_set_configurator(hapd, auth, cmd) == 0 &&
+ dpp_configurator_own_config(auth, curve, 1) == 0) {
hostapd_dpp_handle_config_obj(hapd, auth);
ret = 0;
}
diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c
index 98a2eec..a726a6f 100644
--- a/src/ap/drv_callbacks.c
+++ b/src/ap/drv_callbacks.c
@@ -338,10 +338,14 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
goto fail;
}
#ifdef CONFIG_IEEE80211W
- if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
+ if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
+ (WLAN_STA_ASSOC | WLAN_STA_MFP) &&
+ !sta->sa_query_timed_out &&
sta->sa_query_count > 0)
ap_check_sa_query_timeout(hapd, sta);
- if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
+ if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
+ (WLAN_STA_ASSOC | WLAN_STA_MFP) &&
+ !sta->sa_query_timed_out &&
(sta->auth_alg != WLAN_AUTH_FT)) {
/*
* STA has already been associated with MFP and SA
@@ -1068,19 +1072,23 @@ static void hostapd_action_rx(struct hostapd_data *hapd,
struct sta_info *sta;
size_t plen __maybe_unused;
u16 fc;
+ u8 *action __maybe_unused;
- if (drv_mgmt->frame_len < 24 + 1)
+ if (drv_mgmt->frame_len < IEEE80211_HDRLEN + 2 + 1)
return;
- plen = drv_mgmt->frame_len - 24 - 1;
+ plen = drv_mgmt->frame_len - IEEE80211_HDRLEN - 1;
mgmt = (struct ieee80211_mgmt *) drv_mgmt->frame;
fc = le_to_host16(mgmt->frame_control);
if (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_ACTION)
return; /* handled by the driver */
- wpa_printf(MSG_DEBUG, "RX_ACTION cat %d action plen %d",
- mgmt->u.action.category, (int) plen);
+ action = (u8 *) &mgmt->u.action.u;
+ wpa_printf(MSG_DEBUG, "RX_ACTION category %u action %u sa " MACSTR
+ " da " MACSTR " plen %d",
+ mgmt->u.action.category, *action,
+ MAC2STR(mgmt->sa), MAC2STR(mgmt->da), (int) plen);
sta = ap_get_sta(hapd, mgmt->sa);
if (sta == NULL) {
diff --git a/src/ap/eap_user_db.c b/src/ap/eap_user_db.c
index fab307f..296d5c2 100644
--- a/src/ap/eap_user_db.c
+++ b/src/ap/eap_user_db.c
@@ -92,7 +92,7 @@ static int get_user_cb(void *ctx, int argc, char *argv[], char *col[])
} else if (os_strcmp(col[i], "remediation") == 0 && argv[i]) {
user->remediation = strlen(argv[i]) > 0;
} else if (os_strcmp(col[i], "t_c_timestamp") == 0 && argv[i]) {
- user->t_c_timestamp = strtol(argv[i], 0, 10);
+ user->t_c_timestamp = strtol(argv[i], NULL, 10);
}
}
diff --git a/src/ap/gas_serv.c b/src/ap/gas_serv.c
index 04fb3e1..a7df810 100644
--- a/src/ap/gas_serv.c
+++ b/src/ap/gas_serv.c
@@ -181,6 +181,8 @@ static void anqp_add_hs_capab_list(struct hostapd_data *hapd,
wpabuf_put_u8(buf, HS20_STYPE_OPERATING_CLASS);
if (hapd->conf->hs20_osu_providers_count)
wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_LIST);
+ if (hapd->conf->hs20_osu_providers_nai_count)
+ wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_NAI_LIST);
if (hapd->conf->hs20_icons_count)
wpabuf_put_u8(buf, HS20_STYPE_ICON_REQUEST);
if (hapd->conf->hs20_operator_icon_count)
@@ -817,6 +819,40 @@ static void anqp_add_osu_providers_list(struct hostapd_data *hapd,
}
+static void anqp_add_osu_provider_nai(struct wpabuf *buf,
+ struct hs20_osu_provider *p)
+{
+ /* OSU_NAI for shared BSS (Single SSID) */
+ if (p->osu_nai2) {
+ wpabuf_put_u8(buf, os_strlen(p->osu_nai2));
+ wpabuf_put_str(buf, p->osu_nai2);
+ } else {
+ wpabuf_put_u8(buf, 0);
+ }
+}
+
+
+static void anqp_add_osu_providers_nai_list(struct hostapd_data *hapd,
+ struct wpabuf *buf)
+{
+ if (hapd->conf->hs20_osu_providers_nai_count) {
+ size_t i;
+ u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
+ wpabuf_put_be24(buf, OUI_WFA);
+ wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
+ wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_NAI_LIST);
+ wpabuf_put_u8(buf, 0); /* Reserved */
+
+ for (i = 0; i < hapd->conf->hs20_osu_providers_count; i++) {
+ anqp_add_osu_provider_nai(
+ buf, &hapd->conf->hs20_osu_providers[i]);
+ }
+
+ gas_anqp_set_element_len(buf, len);
+ }
+}
+
+
static void anqp_add_icon_binary_file(struct hostapd_data *hapd,
struct wpabuf *buf,
const u8 *name, size_t name_len)
@@ -1024,6 +1060,8 @@ gas_serv_build_gas_resp_payload(struct hostapd_data *hapd,
anqp_add_icon_binary_file(hapd, buf, icon_name, icon_name_len);
if (request & ANQP_REQ_OPERATOR_ICON_METADATA)
anqp_add_operator_icon_metadata(hapd, buf);
+ if (request & ANQP_REQ_OSU_PROVIDERS_NAI_LIST)
+ anqp_add_osu_providers_nai_list(hapd, buf);
#endif /* CONFIG_HS20 */
#ifdef CONFIG_MBO
@@ -1216,6 +1254,11 @@ static void rx_anqp_hs_query_list(struct hostapd_data *hapd, u8 subtype,
"Operator Icon Metadata",
hapd->conf->hs20_operator_icon_count, qi);
break;
+ case HS20_STYPE_OSU_PROVIDERS_NAI_LIST:
+ set_anqp_req(ANQP_REQ_OSU_PROVIDERS_NAI_LIST,
+ "OSU Providers NAI List",
+ hapd->conf->hs20_osu_providers_nai_count, qi);
+ break;
default:
wpa_printf(MSG_DEBUG, "ANQP: Unsupported HS 2.0 subtype %u",
subtype);
diff --git a/src/ap/gas_serv.h b/src/ap/gas_serv.h
index 0afdcb1..2cf1817 100644
--- a/src/ap/gas_serv.h
+++ b/src/ap/gas_serv.h
@@ -62,6 +62,8 @@
(0x10000 << HS20_STYPE_ICON_REQUEST)
#define ANQP_REQ_OPERATOR_ICON_METADATA \
(0x10000 << HS20_STYPE_OPERATOR_ICON_METADATA)
+#define ANQP_REQ_OSU_PROVIDERS_NAI_LIST \
+ (0x10000 << HS20_STYPE_OSU_PROVIDERS_NAI_LIST)
/* The first MBO ANQP-element can be included in the optimized bitmap. */
#define ANQP_REQ_MBO_CELL_DATA_CONN_PREF \
(BIT(29) << MBO_ANQP_SUBTYPE_CELL_CONN_PREF)
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index 23d2720..7501bac 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -176,8 +176,27 @@ static void hostapd_clear_old(struct hostapd_iface *iface)
}
+static int hostapd_iface_conf_changed(struct hostapd_config *newconf,
+ struct hostapd_config *oldconf)
+{
+ size_t i;
+
+ if (newconf->num_bss != oldconf->num_bss)
+ return 1;
+
+ for (i = 0; i < newconf->num_bss; i++) {
+ if (os_strcmp(newconf->bss[i]->iface,
+ oldconf->bss[i]->iface) != 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+
int hostapd_reload_config(struct hostapd_iface *iface)
{
+ struct hapd_interfaces *interfaces = iface->interfaces;
struct hostapd_data *hapd = iface->bss[0];
struct hostapd_config *newconf, *oldconf;
size_t j;
@@ -200,6 +219,35 @@ int hostapd_reload_config(struct hostapd_iface *iface)
hostapd_clear_old(iface);
oldconf = hapd->iconf;
+ if (hostapd_iface_conf_changed(newconf, oldconf)) {
+ char *fname;
+ int res;
+
+ wpa_printf(MSG_DEBUG,
+ "Configuration changes include interface/BSS modification - force full disable+enable sequence");
+ fname = os_strdup(iface->config_fname);
+ if (!fname) {
+ hostapd_config_free(newconf);
+ return -1;
+ }
+ hostapd_remove_iface(interfaces, hapd->conf->iface);
+ iface = hostapd_init(interfaces, fname);
+ os_free(fname);
+ hostapd_config_free(newconf);
+ if (!iface) {
+ wpa_printf(MSG_ERROR,
+ "Failed to initialize interface on config reload");
+ return -1;
+ }
+ iface->interfaces = interfaces;
+ interfaces->iface[interfaces->count] = iface;
+ interfaces->count++;
+ res = hostapd_enable_iface(iface);
+ if (res < 0)
+ wpa_printf(MSG_ERROR,
+ "Failed to enable interface on config reload");
+ return res;
+ }
iface->conf = newconf;
for (j = 0; j < iface->num_bss; j++) {
@@ -2620,6 +2668,11 @@ int hostapd_disable_iface(struct hostapd_iface *hapd_iface)
!!(hapd_iface->drv_flags &
WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
+#ifdef NEED_AP_MLME
+ for (j = 0; j < hapd_iface->num_bss; j++)
+ hostapd_cleanup_cs_params(hapd_iface->bss[j]);
+#endif /* NEED_AP_MLME */
+
/* same as hostapd_interface_deinit without deinitializing ctrl-iface */
for (j = 0; j < hapd_iface->num_bss; j++) {
struct hostapd_data *hapd = hapd_iface->bss[j];
@@ -2677,7 +2730,7 @@ hostapd_config_alloc(struct hapd_interfaces *interfaces, const char *ifname,
if (conf == NULL) {
wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for "
"configuration", __func__);
- return NULL;
+ return NULL;
}
if (driver) {
@@ -3428,7 +3481,6 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface,
const struct hostapd_freq_params *freq_params)
{
int vht_seg0_idx = 0, vht_seg1_idx = 0, vht_bw = VHT_CHANWIDTH_USE_HT;
- unsigned int i;
wpa_printf(MSG_DEBUG, "Restarting all CSA-related BSSes");
@@ -3470,10 +3522,8 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface,
/*
* cs_params must not be cleared earlier because the freq_params
* argument may actually point to one of these.
+ * These params will be cleared during interface disable below.
*/
- for (i = 0; i < iface->num_bss; i++)
- hostapd_cleanup_cs_params(iface->bss[i]);
-
hostapd_disable_iface(iface);
hostapd_enable_iface(iface);
}
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 9a520f3..d304c11 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -14,6 +14,13 @@
#include "ap_config.h"
#include "drivers/driver.h"
+#define OCE_STA_CFON_ENABLED(hapd) \
+ ((hapd->conf->oce & OCE_STA_CFON) && \
+ (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON))
+#define OCE_AP_ENABLED(hapd) \
+ ((hapd->conf->oce & OCE_AP) && \
+ (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_OCE_AP))
+
struct wpa_ctrl_dst;
struct radius_server_data;
struct upnp_wps_device_sm;
@@ -324,11 +331,6 @@ struct hostapd_data {
#ifdef CONFIG_MBO
unsigned int mbo_assoc_disallow;
- /**
- * enable_oce - Enable OCE if it is enabled by user and device also
- * supports OCE.
- */
- u8 enable_oce;
#endif /* CONFIG_MBO */
struct dl_list nr_db;
diff --git a/src/ap/hs20.c b/src/ap/hs20.c
index 98d016d..e265569 100644
--- a/src/ap/hs20.c
+++ b/src/ap/hs20.c
@@ -184,13 +184,14 @@ int hs20_send_wnm_notification_t_c(struct hostapd_data *hapd,
{
struct wpabuf *buf;
int ret;
- size_t url_len = os_strlen(url);
+ size_t url_len;
if (!url) {
wpa_printf(MSG_INFO, "HS 2.0: No T&C Server URL available");
return -1;
}
+ url_len = os_strlen(url);
if (5 + url_len > 255) {
wpa_printf(MSG_INFO,
"HS 2.0: Too long T&C Server URL for WNM-Notification: '%s'",
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
index 84e74ee..5279abc 100644
--- a/src/ap/hw_features.c
+++ b/src/ap/hw_features.c
@@ -679,7 +679,8 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface)
if (!ieee80211n_supported_ht_capab(iface))
return -1;
#ifdef CONFIG_IEEE80211AC
- if (!ieee80211ac_supported_vht_capab(iface))
+ if (iface->conf->ieee80211ac &&
+ !ieee80211ac_supported_vht_capab(iface))
return -1;
#endif /* CONFIG_IEEE80211AC */
ret = ieee80211n_check_40mhz(iface);
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index d8b34fa..f9bb99d 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1665,9 +1665,11 @@ ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr,
is_probe_req);
if (res == HOSTAPD_ACL_REJECT) {
- wpa_printf(MSG_INFO,
- "Station " MACSTR " not allowed to authenticate",
- MAC2STR(addr));
+ if (!is_probe_req)
+ wpa_printf(MSG_DEBUG,
+ "Station " MACSTR
+ " not allowed to authenticate",
+ MAC2STR(addr));
return HOSTAPD_ACL_REJECT;
}
@@ -2583,10 +2585,14 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
if (resp != WLAN_STATUS_SUCCESS)
return resp;
#ifdef CONFIG_IEEE80211W
- if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
+ if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
+ (WLAN_STA_ASSOC | WLAN_STA_MFP) &&
+ !sta->sa_query_timed_out &&
sta->sa_query_count > 0)
ap_check_sa_query_timeout(hapd, sta);
- if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out &&
+ if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) ==
+ (WLAN_STA_ASSOC | WLAN_STA_MFP) &&
+ !sta->sa_query_timed_out &&
(!reassoc || sta->auth_alg != WLAN_AUTH_FT)) {
/*
* STA has already been associated with MFP and SA
@@ -2916,7 +2922,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
#endif /* CONFIG_IEEE80211R_AP */
#ifdef CONFIG_OWE
- if (sta && (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE))
+ if (sta && status_code == WLAN_STATUS_SUCCESS &&
+ (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE))
p = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, p,
buf + buflen - p,
ies, ies_len);
@@ -3063,7 +3070,7 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
#ifdef CONFIG_OWE
if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
- sta && sta->owe_ecdh &&
+ sta && sta->owe_ecdh && status_code == WLAN_STATUS_SUCCESS &&
wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE) {
struct wpabuf *pub;
@@ -3746,9 +3753,9 @@ static int handle_action(struct hostapd_data *hapd,
unsigned int freq)
{
struct sta_info *sta;
- sta = ap_get_sta(hapd, mgmt->sa);
+ u8 *action __maybe_unused;
- if (len < IEEE80211_HDRLEN + 1) {
+ if (len < IEEE80211_HDRLEN + 2 + 1) {
hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_DEBUG,
"handle_action - too short payload (len=%lu)",
@@ -3756,6 +3763,14 @@ static int handle_action(struct hostapd_data *hapd,
return 0;
}
+ action = (u8 *) &mgmt->u.action.u;
+ wpa_printf(MSG_DEBUG, "RX_ACTION category %u action %u sa " MACSTR
+ " da " MACSTR " len %d freq %u",
+ mgmt->u.action.category, *action,
+ MAC2STR(mgmt->sa), MAC2STR(mgmt->da), (int) len, freq);
+
+ sta = ap_get_sta(hapd, mgmt->sa);
+
if (mgmt->u.action.category != WLAN_ACTION_PUBLIC &&
(sta == NULL || !(sta->flags & WLAN_STA_ASSOC))) {
wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored Action "
@@ -4052,7 +4067,8 @@ static void handle_auth_cb(struct hostapd_data *hapd,
sta = ap_get_sta(hapd, mgmt->da);
if (!sta) {
- wpa_printf(MSG_INFO, "handle_auth_cb: STA " MACSTR " not found",
+ wpa_printf(MSG_DEBUG, "handle_auth_cb: STA " MACSTR
+ " not found",
MAC2STR(mgmt->da));
return;
}
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index a3f8609..49e9bf8 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -178,6 +178,10 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
case 1: /* Bits 8-15 */
if (hapd->conf->proxy_arp)
*pos |= 0x10; /* Bit 12 - Proxy ARP */
+ if (hapd->conf->coloc_intf_reporting) {
+ /* Bit 13 - Collocated Interference Reporting */
+ *pos |= 0x20;
+ }
break;
case 2: /* Bits 16-23 */
if (hapd->conf->wnm_sleep_mode)
@@ -548,7 +552,8 @@ u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len)
u8 mbo[9], *mbo_pos = mbo;
u8 *pos = eid;
- if (!hapd->conf->mbo_enabled && !hapd->enable_oce)
+ if (!hapd->conf->mbo_enabled &&
+ !OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd))
return eid;
if (hapd->conf->mbo_enabled) {
@@ -564,12 +569,11 @@ u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len)
*mbo_pos++ = hapd->mbo_assoc_disallow;
}
- if (hapd->enable_oce & (OCE_AP | OCE_STA_CFON)) {
+ if (OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) {
u8 ctrl;
ctrl = OCE_RELEASE;
- if ((hapd->enable_oce & (OCE_AP | OCE_STA_CFON)) ==
- OCE_STA_CFON)
+ if (OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd))
ctrl |= OCE_IS_STA_CFON;
*mbo_pos++ = OCE_ATTR_ID_CAPA_IND;
@@ -587,7 +591,8 @@ u8 hostapd_mbo_ie_len(struct hostapd_data *hapd)
{
u8 len;
- if (!hapd->conf->mbo_enabled && !hapd->enable_oce)
+ if (!hapd->conf->mbo_enabled &&
+ !OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd))
return 0;
/*
@@ -599,7 +604,7 @@ u8 hostapd_mbo_ie_len(struct hostapd_data *hapd)
len += 3 + (hapd->mbo_assoc_disallow ? 3 : 0);
/* OCE capability indication attribute (3) */
- if (hapd->enable_oce & (OCE_AP | OCE_STA_CFON))
+ if (OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd))
len += 3;
return len;
diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c
index 985f8b7..185279f 100644
--- a/src/ap/ieee802_1x.c
+++ b/src/ap/ieee802_1x.c
@@ -683,6 +683,8 @@ void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd,
#ifdef CONFIG_HS20
if (hapd->conf->hs20) {
u8 ver = 1; /* Release 2 */
+ if (HS20_VERSION > 0x10)
+ ver = 2; /* Release 3 */
if (!radius_msg_add_wfa(
msg, RADIUS_VENDOR_ATTR_WFA_HS20_AP_VERSION,
&ver, 1)) {
diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
index 31e4fc6..01fecee 100644
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -138,6 +138,8 @@ int vlan_init(struct hostapd_data *hapd)
!hapd->conf->vlan) {
/* dynamic vlans enabled but no (or empty) vlan_file given */
struct hostapd_vlan *vlan;
+ int ret;
+
vlan = os_zalloc(sizeof(*vlan));
if (vlan == NULL) {
wpa_printf(MSG_ERROR, "Out of memory while assigning "
@@ -146,8 +148,16 @@ int vlan_init(struct hostapd_data *hapd)
}
vlan->vlan_id = VLAN_ID_WILDCARD;
- os_snprintf(vlan->ifname, sizeof(vlan->ifname), "%s.#",
- hapd->conf->iface);
+ ret = os_snprintf(vlan->ifname, sizeof(vlan->ifname), "%s.#",
+ hapd->conf->iface);
+ if (ret >= (int) sizeof(vlan->ifname)) {
+ wpa_printf(MSG_WARNING,
+ "VLAN: Interface name was truncated to %s",
+ vlan->ifname);
+ } else if (ret < 0) {
+ os_free(vlan);
+ return ret;
+ }
vlan->next = hapd->conf->vlan;
hapd->conf->vlan = vlan;
}
diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c
index 710fe50..1e8f58b 100644
--- a/src/ap/wnm_ap.c
+++ b/src/ap/wnm_ap.c
@@ -453,6 +453,48 @@ static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd,
}
+static void ieee802_11_rx_wnm_coloc_intf_report(struct hostapd_data *hapd,
+ const u8 *addr, const u8 *buf,
+ size_t len)
+{
+ u8 dialog_token;
+ char *hex;
+ size_t hex_len;
+
+ if (!hapd->conf->coloc_intf_reporting) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Ignore unexpected Collocated Interference Report from "
+ MACSTR, MAC2STR(addr));
+ return;
+ }
+
+ if (len < 1) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Ignore too short Collocated Interference Report from "
+ MACSTR, MAC2STR(addr));
+ return;
+ }
+ dialog_token = *buf++;
+ len--;
+
+ wpa_printf(MSG_DEBUG,
+ "WNM: Received Collocated Interference Report frame from "
+ MACSTR " (dialog_token=%u)",
+ MAC2STR(addr), dialog_token);
+ wpa_hexdump(MSG_MSGDUMP, "WNM: Collocated Interference Report Elements",
+ buf, len);
+
+ hex_len = 2 * len + 1;
+ hex = os_malloc(hex_len);
+ if (!hex)
+ return;
+ wpa_snprintf_hex(hex, hex_len, buf, len);
+ wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, COLOC_INTF_REPORT MACSTR " %d %s",
+ MAC2STR(addr), dialog_token, hex);
+ os_free(hex);
+}
+
+
int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len)
{
@@ -483,6 +525,10 @@ int ieee802_11_rx_wnm_action_ap(struct hostapd_data *hapd,
ieee802_11_rx_wnm_notification_req(hapd, mgmt->sa, payload,
plen);
return 0;
+ case WNM_COLLOCATED_INTERFERENCE_REPORT:
+ ieee802_11_rx_wnm_coloc_intf_report(hapd, mgmt->sa, payload,
+ plen);
+ return 0;
}
wpa_printf(MSG_DEBUG, "WNM: Unsupported WNM Action %u from " MACSTR,
@@ -681,3 +727,40 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
return 0;
}
+
+
+int wnm_send_coloc_intf_req(struct hostapd_data *hapd, struct sta_info *sta,
+ unsigned int auto_report, unsigned int timeout)
+{
+ u8 buf[100], *pos;
+ struct ieee80211_mgmt *mgmt;
+ u8 dialog_token = 1;
+
+ if (auto_report > 3 || timeout > 63)
+ return -1;
+ os_memset(buf, 0, sizeof(buf));
+ mgmt = (struct ieee80211_mgmt *) buf;
+ mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+ WLAN_FC_STYPE_ACTION);
+ os_memcpy(mgmt->da, sta->addr, ETH_ALEN);
+ os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN);
+ os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN);
+ mgmt->u.action.category = WLAN_ACTION_WNM;
+ mgmt->u.action.u.coloc_intf_req.action =
+ WNM_COLLOCATED_INTERFERENCE_REQ;
+ mgmt->u.action.u.coloc_intf_req.dialog_token = dialog_token;
+ mgmt->u.action.u.coloc_intf_req.req_info = auto_report | (timeout << 2);
+ pos = &mgmt->u.action.u.coloc_intf_req.req_info;
+ pos++;
+
+ wpa_printf(MSG_DEBUG, "WNM: Sending Collocated Interference Request to "
+ MACSTR " (dialog_token=%u auto_report=%u timeout=%u)",
+ MAC2STR(sta->addr), dialog_token, auto_report, timeout);
+ if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Failed to send Collocated Interference Request frame");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/ap/wnm_ap.h b/src/ap/wnm_ap.h
index 56d0f88..1806ba0 100644
--- a/src/ap/wnm_ap.h
+++ b/src/ap/wnm_ap.h
@@ -24,5 +24,7 @@ int wnm_send_bss_tm_req(struct hostapd_data *hapd, struct sta_info *sta,
const u8 *nei_rep, size_t nei_rep_len,
const u8 *mbo_attrs, size_t mbo_len);
void ap_sta_reset_steer_flag_timer(void *eloop_ctx, void *timeout_ctx);
+int wnm_send_coloc_intf_req(struct hostapd_data *hapd, struct sta_info *sta,
+ unsigned int auto_report, unsigned int timeout);
#endif /* WNM_AP_H */
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index e8d46ab..f6792e0 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -1451,7 +1451,7 @@ static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth,
now.sec;
else if (session_timeout && r1->session_timeout)
*session_timeout = 1;
- else
+ else if (session_timeout)
*session_timeout = 0;
return 0;
}
diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c
index 421dd5a..cdcc5de 100644
--- a/src/ap/wpa_auth_ie.c
+++ b/src/ap/wpa_auth_ie.c
@@ -751,6 +751,7 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
#ifdef CONFIG_SAE
if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_OPTIONAL &&
+ wpa_auth->conf.sae_require_mfp &&
wpa_key_mgmt_sae(sm->wpa_key_mgmt) &&
!(data.capabilities & WPA_CAPABILITY_MFPC)) {
wpa_printf(MSG_DEBUG,
@@ -1067,7 +1068,11 @@ u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm,
const u8 *req_ies, size_t req_ies_len)
{
int res;
- struct wpa_auth_config *conf = &sm->wpa_auth->conf;
+ struct wpa_auth_config *conf;
+
+ if (!sm)
+ return pos;
+ conf = &sm->wpa_auth->conf;
#ifdef CONFIG_TESTING_OPTIONS
if (conf->own_ie_override_len) {
@@ -1081,7 +1086,7 @@ u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm,
}
#endif /* CONFIG_TESTING_OPTIONS */
- res = wpa_write_rsn_ie(&sm->wpa_auth->conf, pos, max_len,
+ res = wpa_write_rsn_ie(conf, pos, max_len,
sm->pmksa ? sm->pmksa->pmkid : NULL);
if (res < 0)
return pos;
diff --git a/src/common/dpp.c b/src/common/dpp.c
index 677f586..e715e04 100644
--- a/src/common/dpp.c
+++ b/src/common/dpp.c
@@ -2854,7 +2854,7 @@ static int dpp_auth_build_resp_status(struct dpp_authentication *auth,
i_pubkey_hash = test_hash;
} else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) {
wpa_printf(MSG_INFO, "DPP: TESTING - no Status");
- status = -1;
+ status = 255;
} else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) {
wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce");
i_nonce = NULL;
@@ -3457,7 +3457,7 @@ dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
}
#endif /* CONFIG_TESTING_OPTIONS */
- if (!auth->initiator) {
+ if (!auth->initiator || !auth->peer_bi) {
dpp_auth_fail(auth, "Unexpected Authentication Response");
return NULL;
}
@@ -3638,7 +3638,7 @@ dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr,
goto fail;
}
- if (auth->own_bi && auth->peer_bi) {
+ if (auth->own_bi) {
/* Mutual authentication */
if (dpp_auth_derive_l_initiator(auth) < 0)
goto fail;
@@ -3846,7 +3846,7 @@ int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
}
#endif /* CONFIG_TESTING_OPTIONS */
- if (auth->initiator) {
+ if (auth->initiator || !auth->own_bi) {
dpp_auth_fail(auth, "Unexpected Authentication Confirm");
return -1;
}
@@ -3904,7 +3904,7 @@ int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr,
"Initiator Bootstrapping Key Hash mismatch");
return -1;
}
- } else if (auth->own_bi && auth->peer_bi) {
+ } else if (auth->peer_bi) {
/* Mutual authentication and peer did not include its
* Bootstrapping Key Hash attribute. */
dpp_auth_fail(auth,
@@ -4757,7 +4757,7 @@ static EVP_PKEY * dpp_parse_jwk(struct json_token *jwk,
goto fail;
}
if (os_strcmp(token->string, "EC") != 0) {
- wpa_printf(MSG_DEBUG, "DPP: Unexpected JWK kty '%s",
+ wpa_printf(MSG_DEBUG, "DPP: Unexpected JWK kty '%s'",
token->string);
goto fail;
}
@@ -6586,6 +6586,32 @@ static int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp,
}
+static int dpp_pkex_identifier_match(const u8 *attr_id, u16 attr_id_len,
+ const char *identifier)
+{
+ if (!attr_id && identifier) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: No PKEX code identifier received, but expected one");
+ return 0;
+ }
+
+ if (attr_id && !identifier) {
+ wpa_printf(MSG_DEBUG,
+ "DPP: PKEX code identifier received, but not expecting one");
+ return 0;
+ }
+
+ if (attr_id && identifier &&
+ (os_strlen(identifier) != attr_id_len ||
+ os_memcmp(identifier, attr_id, attr_id_len) != 0)) {
+ wpa_printf(MSG_DEBUG, "DPP: PKEX code identifier mismatch");
+ return 0;
+ }
+
+ return 1;
+}
+
+
struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
struct dpp_bootstrap_info *bi,
const u8 *own_mac,
@@ -6630,19 +6656,11 @@ struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx,
}
#endif /* CONFIG_TESTING_OPTIONS */
+ attr_id_len = 0;
attr_id = dpp_get_attr(buf, len, DPP_ATTR_CODE_IDENTIFIER,
&attr_id_len);
- if (!attr_id && identifier) {
- wpa_printf(MSG_DEBUG,
- "DPP: No PKEX code identifier received, but expected one");
+ if (!dpp_pkex_identifier_match(attr_id, attr_id_len, identifier))
return NULL;
- }
- if (attr_id && identifier &&
- (os_strlen(identifier) != attr_id_len ||
- os_memcmp(identifier, attr_id, attr_id_len) != 0)) {
- wpa_printf(MSG_DEBUG, "DPP: PKEX code identifier mismatch");
- return NULL;
- }
attr_group = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
&attr_group_len);
@@ -7014,16 +7032,11 @@ struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex,
return NULL;
}
+ attr_id_len = 0;
attr_id = dpp_get_attr(buf, buflen, DPP_ATTR_CODE_IDENTIFIER,
&attr_id_len);
- if (!attr_id && pkex->identifier) {
- wpa_printf(MSG_DEBUG,
- "DPP: No PKEX code identifier received, but expected one");
- return NULL;
- }
- if (attr_id && pkex->identifier &&
- (os_strlen(pkex->identifier) != attr_id_len ||
- os_memcmp(pkex->identifier, attr_id, attr_id_len) != 0)) {
+ if (!dpp_pkex_identifier_match(attr_id, attr_id_len,
+ pkex->identifier)) {
dpp_pkex_fail(pkex, "PKEX code identifier mismatch");
return NULL;
}
diff --git a/src/common/gas_server.c b/src/common/gas_server.c
index b258675..ca46758 100644
--- a/src/common/gas_server.c
+++ b/src/common/gas_server.c
@@ -97,8 +97,10 @@ gas_server_send_resp(struct gas_server *gas, struct gas_server_handler *handler,
return;
response = os_zalloc(sizeof(*response));
- if (!response)
+ if (!response) {
+ wpabuf_free(query_resp);
return;
+ }
wpa_printf(MSG_DEBUG, "DPP: Allocated GAS response @%p", response);
response->freq = freq;
response->handler = handler;
@@ -119,6 +121,7 @@ gas_server_send_resp(struct gas_server *gas, struct gas_server_handler *handler,
handler->adv_proto_id_len +
resp_frag_len);
if (!resp) {
+ wpabuf_free(query_resp);
gas_server_free_response(response);
return;
}
@@ -257,6 +260,7 @@ gas_server_handle_rx_comeback_req(struct gas_server_response *response)
handler->adv_proto_id_len +
resp_frag_len);
if (!resp) {
+ dl_list_del(&response->list);
gas_server_free_response(response);
return;
}
diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index e03a095..762e731 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -922,6 +922,16 @@ struct ieee80211_mgmt {
u8 variable[];
} STRUCT_PACKED bss_tm_query;
struct {
+ u8 action; /* 11 */
+ u8 dialog_token;
+ u8 req_info;
+ } STRUCT_PACKED coloc_intf_req;
+ struct {
+ u8 action; /* 12 */
+ u8 dialog_token;
+ u8 variable[];
+ } STRUCT_PACKED coloc_intf_report;
+ struct {
u8 action; /* 15 */
u8 variable[];
} STRUCT_PACKED slf_prot_action;
@@ -1331,6 +1341,7 @@ enum wmm_ac {
#define HS20_STYPE_ICON_REQUEST 10
#define HS20_STYPE_ICON_BINARY_FILE 11
#define HS20_STYPE_OPERATOR_ICON_METADATA 12
+#define HS20_STYPE_OSU_PROVIDERS_NAI_LIST 13
#define HS20_DGAF_DISABLED 0x01
#define HS20_PPS_MO_ID_PRESENT 0x02
diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h
index 72140f3..7c75d08 100644
--- a/src/common/qca-vendor.h
+++ b/src/common/qca-vendor.h
@@ -158,6 +158,11 @@ enum qca_radiotap_vendor_ids {
* timer value. Uses the attributes defines in
* enum qca_wlan_vendor_attr_ocb_get_tsf_resp.
*
+ * @QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES: Command/event to update the
+ * link properties of the respective interface. As an event, is used
+ * to notify the connected station's status. The attributes for this
+ * command are defined in enum qca_wlan_vendor_attr_link_properties.
+ *
* @QCA_NL80211_VENDOR_SUBCMD_P2P_LISTEN_OFFLOAD_START: Command used to
* start the P2P Listen offload function in device and pass the listen
* channel, period, interval, count, device types, and vendor specific
@@ -469,6 +474,31 @@ enum qca_radiotap_vendor_ids {
* qca_wlan_vendor_attr_roam_scan. Some drivers may not send these events
* in few cases, e.g., if the host processor is sleeping when this event
* is generated in firmware.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG: This command is used to
+ * configure parameters per peer to capture Channel Frequency Response
+ * (CFR) and enable Periodic CFR capture. The attributes for this command
+ * are defined in enum qca_wlan_vendor_peer_cfr_capture_attr.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT: Event to indicate changes
+ * in throughput dynamically. The driver estimates the throughput based on
+ * number of packets being transmitted/received per second and indicates
+ * the changes in throughput to user space. Userspace tools can use this
+ * information to configure kernel's TCP parameters in order to achieve
+ * peak throughput. Optionally, the driver will also send guidance on
+ * modifications to kernel's TCP parameters which can be referred by
+ * userspace tools. The attributes used with this event are defined in enum
+ * qca_wlan_vendor_attr_throughput_change.
+ *
+ * @QCA_NL80211_VENDOR_SUBCMD_COEX_CONFIG: This command is used to set
+ * priorities among different types of traffic during coex scenarios.
+ * Current supported prioritization is among WLAN/BT/ZIGBEE with different
+ * profiles mentioned in enum qca_coex_config_profiles. The associated
+ * attributes used with this command are defined in enum
+ * qca_vendor_attr_coex_config.
+ *
+ * Based on the config provided, FW will boost the weight and prioritize
+ * the traffic for that subsystem (WLAN/BT/Zigbee).
*/
enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0,
@@ -630,6 +660,9 @@ enum qca_nl80211_vendor_subcmds {
QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER = 170,
QCA_NL80211_VENDOR_SUBCMD_NAN_EXT = 171,
QCA_NL80211_VENDOR_SUBCMD_ROAM_SCAN_EVENT = 172,
+ QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG = 173,
+ QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT = 174,
+ QCA_NL80211_VENDOR_SUBCMD_COEX_CONFIG = 175,
};
enum qca_wlan_vendor_attr {
@@ -4945,6 +4978,10 @@ enum qca_wlan_vendor_attr_ndp_params {
* and ndp confirm.
*/
QCA_WLAN_VENDOR_ATTR_NDP_TRANSPORT_PROTOCOL = 29,
+ /* Unsigned 8-bit value indicating if NDP remote peer supports NAN NDPE.
+ * 1:support 0:not support
+ */
+ QCA_WLAN_VENDOR_ATTR_PEER_NDPE_SUPPORT = 30,
/* keep last */
QCA_WLAN_VENDOR_ATTR_NDP_PARAMS_AFTER_LAST,
@@ -5403,6 +5440,23 @@ enum qca_wlan_he_mac_padding_dur {
QCA_WLAN_HE_16US_OF_PROCESS_TIME = 2,
};
+/**
+ * enum qca_wlan_he_om_ctrl_ch_bw - HE OM control field BW configuration
+ *
+ * Indicates the HE Operating mode control channel width setting value.
+ *
+ * @QCA_WLAN_HE_OM_CTRL_BW_20M: Primary 20 MHz
+ * @QCA_WLAN_HE_OM_CTRL_BW_40M: Primary 40 MHz
+ * @QCA_WLAN_HE_OM_CTRL_BW_80M: Primary 80 MHz
+ * @QCA_WLAN_HE_OM_CTRL_BW_160M: 160 MHz and 80+80 MHz
+ */
+enum qca_wlan_he_om_ctrl_ch_bw {
+ QCA_WLAN_HE_OM_CTRL_BW_20M = 0,
+ QCA_WLAN_HE_OM_CTRL_BW_40M = 1,
+ QCA_WLAN_HE_OM_CTRL_BW_80M = 2,
+ QCA_WLAN_HE_OM_CTRL_BW_160M = 3,
+};
+
/* Attributes for data used by
* QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION
*/
@@ -5594,6 +5648,61 @@ enum qca_wlan_vendor_attr_wifi_test_config {
*/
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_RESUME = 26,
+ /* 8-bit unsigned value to set the HE operating mode control
+ * (OM CTRL) Channel Width subfield.
+ * The Channel Width subfield indicates the operating channel width
+ * supported by the STA for both reception and transmission.
+ * Uses the enum qca_wlan_he_om_ctrl_ch_bw values.
+ * This setting is cleared with the
+ * QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG
+ * flag attribute to reset defaults.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_BW = 27,
+
+ /* 8-bit unsigned value to configure the number of spatial
+ * streams in HE operating mode control field.
+ * This setting is cleared with the
+ * QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG
+ * flag attribute to reset defaults.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_NSS = 28,
+
+ /* Flag attribute to configure the UL MU disable bit in
+ * HE operating mode control field.
+ * This setting is cleared with the
+ * QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG
+ * flag attribute to reset defaults.
+ * This attribute is used to configure the testbed device.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_OM_CTRL_UL_MU_DISABLE = 29,
+
+ /* Flag attribute to clear the previously set HE operating mode
+ * control field configuration.
+ * This attribute is used to configure the testbed device to reset
+ * defaults to clear any previously set HE operating mode control
+ * field configuration.
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_CLEAR_HE_OM_CTRL_CONFIG = 30,
+
+ /* 8-bit unsigned value to configure HE single user PPDU
+ * transmission. By default this setting is disabled and it
+ * is disabled in the reset defaults of the device configuration.
+ * This attribute is used to configure the testbed device.
+ * 1-enable, 0-disable
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TX_SUPPDU = 31,
+
+ /* 8-bit unsigned value to configure action frame transmission
+ * in HE trigger based PPDU transmission.
+ * By default this setting is disabled and it is disabled in
+ * the reset defaults of the device configuration.
+ * This attribute is used to configure the testbed device.
+ * 1-enable, 0-disable
+ */
+ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_ACTION_TX_TB_PPDU = 32,
+
/* keep last */
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST,
QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX =
@@ -5920,4 +6029,219 @@ enum qca_wlan_vendor_attr_roam_scan {
QCA_WLAN_VENDOR_ATTR_ROAM_SCAN_AFTER_LAST - 1,
};
+/**
+ * enum qca_wlan_vendor_cfr_method - QCA vendor CFR methods used by
+ * attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD as part of vendor
+ * command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG.
+ */
+enum qca_wlan_vendor_cfr_method {
+ /* CFR method using QOS Null frame */
+ QCA_WLAN_VENDOR_CFR_METHOD_QOS_NULL = 0,
+};
+
+/**
+ * enum qca_wlan_vendor_peer_cfr_capture_attr - Used by the vendor command
+ * QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG to configure peer
+ * Channel Frequency Response capture parameters and enable periodic CFR
+ * capture.
+ */
+enum qca_wlan_vendor_peer_cfr_capture_attr {
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_INVALID = 0,
+ /* 6-byte MAC address of the peer.
+ * This attribute is mandatory.
+ */
+ QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR = 1,
+ /* Enable peer CFR Capture, flag attribute.
+ * This attribute is mandatory to enable peer CFR capture.
+ * If this attribute is not present, peer CFR capture is disabled.
+ */
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE = 2,
+ /* BW of measurement, attribute uses the values in enum nl80211_chan_width
+ * Supported values: 20, 40, 80, 80+80, 160.
+ * Note that all targets may not support all bandwidths.
+ * u8 attribute. This attribute is mandatory if attribute
+ * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used.
+ */
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH = 3,
+ /* Periodicity of CFR measurement in msec.
+ * Periodicity should be a multiple of Base timer.
+ * Current Base timer value supported is 10 msecs (default).
+ * 0 for one shot capture. u32 attribute.
+ * This attribute is mandatory if attribute
+ * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used.
+ */
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY = 4,
+ /* Method used to capture Channel Frequency Response.
+ * Attribute uses the values defined in enum qca_wlan_vendor_cfr_method.
+ * u8 attribute. This attribute is mandatory if attribute
+ * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used.
+ */
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD = 5,
+ /* Enable periodic CFR capture, flag attribute.
+ * This attribute is mandatory to enable Periodic CFR capture.
+ * If this attribute is not present, periodic CFR capture is disabled.
+ */
+ QCA_WLAN_VENDOR_ATTR_PERIODIC_CFR_CAPTURE_ENABLE = 6,
+
+ /* Keep last */
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_MAX =
+ QCA_WLAN_VENDOR_ATTR_PEER_CFR_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_throughput_level - Current throughput level
+ *
+ * Indicates the current level of throughput calculated by the driver. The
+ * driver may choose different thresholds to decide whether the throughput level
+ * is low or medium or high based on variety of parameters like physical link
+ * capacity of the current connection, the number of packets being dispatched
+ * per second, etc. The throughput level events might not be consistent with the
+ * actual current throughput value being observed.
+ *
+ * @QCA_WLAN_THROUGHPUT_LEVEL_LOW: Low level of throughput
+ * @QCA_WLAN_THROUGHPUT_LEVEL_MEDIUM: Medium level of throughput
+ * @QCA_WLAN_THROUGHPUT_LEVEL_HIGH: High level of throughput
+ */
+enum qca_wlan_throughput_level {
+ QCA_WLAN_THROUGHPUT_LEVEL_LOW = 0,
+ QCA_WLAN_THROUGHPUT_LEVEL_MEDIUM = 1,
+ QCA_WLAN_THROUGHPUT_LEVEL_HIGH = 2,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_throughput_change - Vendor subcmd attributes to
+ * report throughput changes from the driver to user space. enum values are used
+ * for netlink attributes sent with
+ * %QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT sub command.
+ */
+enum qca_wlan_vendor_attr_throughput_change {
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_INVALID = 0,
+ /* Indicates the direction of throughput in which the change is being
+ * reported. u8 attribute. Value is 0 for TX and 1 for RX.
+ */
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_DIRECTION = 1,
+ /* Indicates the newly observed throughput level. enum
+ * qca_wlan_throughput_level describes the possible range of values.
+ * u8 attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_THROUGHPUT_LEVEL = 2,
+ /* Indicates the driver's guidance on the new value to be set to
+ * kernel's TCP parameter tcp_limit_output_bytes. u32 attribute. The
+ * driver may optionally include this attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_LIMIT_OUTPUT_BYTES = 3,
+ /* Indicates the driver's guidance on the new value to be set to
+ * kernel's TCP parameter tcp_adv_win_scale. s8 attribute. Possible
+ * values are from -31 to 31. The driver may optionally include this
+ * attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_ADV_WIN_SCALE = 4,
+ /* Indicates the driver's guidance on the new value to be set to
+ * kernel's TCP parameter tcp_delack_seg. u32 attribute. The driver may
+ * optionally include this attribute.
+ */
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_DELACK_SEG = 5,
+
+ /* keep last */
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_MAX =
+ QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_coex_config_profiles - This enum defines different types of
+ * traffic streams that can be prioritized one over the other during coex
+ * scenarios.
+ * The types defined in this enum are categorized in the below manner.
+ * 0 - 31 values corresponds to WLAN
+ * 32 - 63 values corresponds to BT
+ * 64 - 95 values corresponds to Zigbee
+ * @QCA_WIFI_STA_DISCOVERY: Prioritize discovery frames for WLAN STA
+ * @QCA_WIFI_STA_CONNECTION: Prioritize connection frames for WLAN STA
+ * @QCA_WIFI_STA_CLASS_3_MGMT: Prioritize class 3 mgmt frames for WLAN STA
+ * @QCA_WIFI_STA_DATA : Prioritize data frames for WLAN STA
+ * @QCA_WIFI_STA_ALL: Priritize all frames for WLAN STA
+ * @QCA_WIFI_SAP_DISCOVERY: Prioritize discovery frames for WLAN SAP
+ * @QCA_WIFI_SAP_CONNECTION: Prioritize connection frames for WLAN SAP
+ * @QCA_WIFI_SAP_CLASS_3_MGMT: Prioritize class 3 mgmt frames for WLAN SAP
+ * @QCA_WIFI_SAP_DATA: Prioritize data frames for WLAN SAP
+ * @QCA_WIFI_SAP_ALL: Prioritize all frames for WLAN SAP
+ * @QCA_BT_A2DP: Prioritize BT A2DP
+ * @QCA_BT_BLE: Prioritize BT BLE
+ * @QCA_BT_SCO: Prioritize BT SCO
+ * @QCA_ZB_LOW: Prioritize Zigbee Low
+ * @QCA_ZB_HIGH: Prioritize Zigbee High
+ */
+enum qca_coex_config_profiles {
+ /* 0 - 31 corresponds to WLAN */
+ QCA_WIFI_STA_DISCOVERY = 0,
+ QCA_WIFI_STA_CONNECTION = 1,
+ QCA_WIFI_STA_CLASS_3_MGMT = 2,
+ QCA_WIFI_STA_DATA = 3,
+ QCA_WIFI_STA_ALL = 4,
+ QCA_WIFI_SAP_DISCOVERY = 5,
+ QCA_WIFI_SAP_CONNECTION = 6,
+ QCA_WIFI_SAP_CLASS_3_MGMT = 7,
+ QCA_WIFI_SAP_DATA = 8,
+ QCA_WIFI_SAP_ALL = 9,
+ /* 32 - 63 corresponds to BT */
+ QCA_BT_A2DP = 32,
+ QCA_BT_BLE = 33,
+ QCA_BT_SCO = 34,
+ /* 64 - 95 corresponds to Zigbee */
+ QCA_ZB_LOW = 64,
+ QCA_ZB_HIGH = 65
+};
+
+/**
+ * enum qca_vendor_attr_coex_config - Specifies vendor coex config attributes
+ *
+ * @QCA_VENDOR_ATTR_COEX_CONFIG_PROFILES: This attribute contains variable
+ * length array of 8-bit values from enum qca_coex_config_profiles.
+ * FW will prioritize the profiles in the order given in the array encapsulated
+ * in this attribute.
+ * For example:
+ * -----------------------------------------------------------------------
+ * | 1 | 34 | 32 | 65 |
+ * -----------------------------------------------------------------------
+ * If the attribute contains the values defined in above array then it means
+ * 1) Wifi STA connection has priority over BT_SCO, BT_A2DP and ZIGBEE HIGH.
+ * 2) BT_SCO has priority over BT_A2DP.
+ * 3) BT_A2DP has priority over ZIGBEE HIGH.
+ * Profiles which are not listed in this array shall not be preferred over the
+ * profiles which are listed in the array as a part of this attribute.
+ */
+enum qca_vendor_attr_coex_config {
+ QCA_VENDOR_ATTR_COEX_CONFIG_INVALID = 0,
+ QCA_VENDOR_ATTR_COEX_CONFIG_PROFILES = 1,
+
+ /* Keep last */
+ QCA_VENDOR_ATTR_COEX_CONFIG_AFTER_LAST,
+ QCA_VENDOR_ATTR_COEX_CONFIG_MAX =
+ QCA_VENDOR_ATTR_COEX_CONFIG_AFTER_LAST - 1,
+};
+
+/**
+ * enum qca_wlan_vendor_attr_link_properties - Represent the link properties.
+ *
+ * @QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR: MAC address of the peer
+ * (STA/AP) for the connected link.
+ * @QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS: Attribute containing a
+ * &struct nl80211_sta_flag_update for the respective connected link. MAC
+ * address of the peer represented by
+ * QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR.
+ */
+enum qca_wlan_vendor_attr_link_properties {
+ QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_INVALID = 0,
+ /* 1 - 3 are reserved */
+ QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_MAC_ADDR = 4,
+ QCA_WLAN_VENDOR_ATTR_LINK_PROPERTIES_STA_FLAGS = 5,
+
+ /* Keep last */
+ QCA_VENDOR_ATTR_LINK_PROPERTIES_AFTER_LAST,
+ QCA_VENDOR_ATTR_LINK_PROPERTIES_MAX =
+ QCA_VENDOR_ATTR_LINK_PROPERTIES_AFTER_LAST - 1,
+};
+
#endif /* QCA_VENDOR_H */
diff --git a/src/common/version.h b/src/common/version.h
index 16c1004..2f47903 100644
--- a/src/common/version.h
+++ b/src/common/version.h
@@ -9,6 +9,6 @@
#define GIT_VERSION_STR_POSTFIX ""
#endif /* GIT_VERSION_STR_POSTFIX */
-#define VERSION_STR "2.7-devel" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
+#define VERSION_STR "2.7" VERSION_STR_POSTFIX GIT_VERSION_STR_POSTFIX
#endif /* VERSION_H */
diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c
index 14c5769..2d98904 100644
--- a/src/common/wpa_common.c
+++ b/src/common/wpa_common.c
@@ -1202,6 +1202,8 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
pos = rsn_ie + 6;
left = rsn_ie_len - 6;
+ data->group_cipher = WPA_CIPHER_GTK_NOT_USED;
+ data->key_mgmt = WPA_KEY_MGMT_OSEN;
data->proto = WPA_PROTO_OSEN;
} else {
const struct rsn_ie_hdr *hdr;
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 4ee6400..f65077e 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -332,6 +332,13 @@ extern "C" {
/* BSS Transition Management Response frame received */
#define BSS_TM_RESP "BSS-TM-RESP "
+/* Collocated Interference Request frame received;
+ * parameters: <dialog token> <automatic report enabled> <report timeout> */
+#define COLOC_INTF_REQ "COLOC-INTF-REQ "
+/* Collocated Interference Report frame received;
+ * parameters: <STA address> <dialog token> <hexdump of report elements> */
+#define COLOC_INTF_REPORT "COLOC-INTF-REPORT "
+
/* MBO IE with cellular data connection preference received */
#define MBO_CELL_PREFERENCE "MBO-CELL-PREFERENCE "
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index f4cff43..f89053a 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -29,6 +29,7 @@
#include "sha1.h"
#include "sha256.h"
#include "sha384.h"
+#include "sha512.h"
#include "md5.h"
#include "aes_wrap.h"
#include "crypto.h"
diff --git a/src/crypto/tls.h b/src/crypto/tls.h
index 585db8b..481b346 100644
--- a/src/crypto/tls.h
+++ b/src/crypto/tls.h
@@ -64,6 +64,7 @@ union tls_event_data {
size_t hash_len;
const char *altsubject[TLS_MAX_ALT_SUBJECT];
int num_altsubject;
+ const char *serial_num;
} peer_cert;
struct {
@@ -253,6 +254,18 @@ void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn);
int tls_connection_established(void *tls_ctx, struct tls_connection *conn);
/**
+ * tls_connection_peer_serial_num - Fetch peer certificate serial number
+ * @tls_ctx: TLS context data from tls_init()
+ * @conn: Connection context data from tls_connection_init()
+ * Returns: Allocated string buffer containing the peer certificate serial
+ * number or %NULL on error.
+ *
+ * The caller is responsible for freeing the returned buffer with os_free().
+ */
+char * tls_connection_peer_serial_num(void *tls_ctx,
+ struct tls_connection *conn);
+
+/**
* tls_connection_shutdown - Shutdown TLS connection
* @tls_ctx: TLS context data from tls_init()
* @conn: Connection context data from tls_connection_init()
diff --git a/src/crypto/tls_gnutls.c b/src/crypto/tls_gnutls.c
index 7ee3fa3..36dafd2 100644
--- a/src/crypto/tls_gnutls.c
+++ b/src/crypto/tls_gnutls.c
@@ -295,6 +295,14 @@ int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
}
+char * tls_connection_peer_serial_num(void *tls_ctx,
+ struct tls_connection *conn)
+{
+ /* TODO */
+ return NULL;
+}
+
+
int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
{
struct tls_global *global = ssl_ctx;
diff --git a/src/crypto/tls_internal.c b/src/crypto/tls_internal.c
index c7cb5de..d289c94 100644
--- a/src/crypto/tls_internal.c
+++ b/src/crypto/tls_internal.c
@@ -177,6 +177,14 @@ int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
}
+char * tls_connection_peer_serial_num(void *tls_ctx,
+ struct tls_connection *conn)
+{
+ /* TODO */
+ return NULL;
+}
+
+
int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
{
#ifdef CONFIG_TLS_INTERNAL_CLIENT
diff --git a/src/crypto/tls_none.c b/src/crypto/tls_none.c
index dd5681e..5d0c6bd 100644
--- a/src/crypto/tls_none.c
+++ b/src/crypto/tls_none.c
@@ -45,6 +45,13 @@ int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
}
+char * tls_connection_peer_serial_num(void *tls_ctx,
+ struct tls_connection *conn)
+{
+ return NULL;
+}
+
+
int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
{
return -1;
diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c
index 79ac909..0d5ebda 100644
--- a/src/crypto/tls_openssl.c
+++ b/src/crypto/tls_openssl.c
@@ -111,6 +111,12 @@ static int RSA_bits(const RSA *r)
return BN_num_bits(r->n);
}
#endif /* CONFIG_SUITEB */
+
+
+static const unsigned char * ASN1_STRING_get0_data(const ASN1_STRING *x)
+{
+ return ASN1_STRING_data((ASN1_STRING *) x);
+}
#endif
#ifdef ANDROID
@@ -1540,6 +1546,31 @@ int tls_connection_established(void *ssl_ctx, struct tls_connection *conn)
}
+char * tls_connection_peer_serial_num(void *tls_ctx,
+ struct tls_connection *conn)
+{
+ ASN1_INTEGER *ser;
+ char *serial_num;
+ size_t len;
+
+ if (!conn->peer_cert)
+ return NULL;
+
+ ser = X509_get_serialNumber(conn->peer_cert);
+ if (!ser)
+ return NULL;
+
+ len = ASN1_STRING_length(ser) * 2 + 1;
+ serial_num = os_malloc(len);
+ if (!serial_num)
+ return NULL;
+ wpa_snprintf_hex_uppercase(serial_num, len,
+ ASN1_STRING_get0_data(ser),
+ ASN1_STRING_length(ser));
+ return serial_num;
+}
+
+
int tls_connection_shutdown(void *ssl_ctx, struct tls_connection *conn)
{
if (conn == NULL)
@@ -1824,6 +1855,8 @@ static void openssl_tls_cert_event(struct tls_connection *conn,
GENERAL_NAME *gen;
void *ext;
stack_index_t i;
+ ASN1_INTEGER *ser;
+ char serial_num[128];
#ifdef CONFIG_SHA256
u8 hash[32];
#endif /* CONFIG_SHA256 */
@@ -1852,6 +1885,14 @@ static void openssl_tls_cert_event(struct tls_connection *conn,
ev.peer_cert.depth = depth;
ev.peer_cert.subject = subject;
+ ser = X509_get_serialNumber(err_cert);
+ if (ser) {
+ wpa_snprintf_hex_uppercase(serial_num, sizeof(serial_num),
+ ASN1_STRING_get0_data(ser),
+ ASN1_STRING_length(ser));
+ ev.peer_cert.serial_num = serial_num;
+ }
+
ext = X509_get_ext_d2i(err_cert, NID_subject_alt_name, NULL, NULL);
for (i = 0; ext && i < sk_GENERAL_NAME_num(ext); i++) {
char *pos;
diff --git a/src/crypto/tls_wolfssl.c b/src/crypto/tls_wolfssl.c
index 9544e2f..cc8c704 100644
--- a/src/crypto/tls_wolfssl.c
+++ b/src/crypto/tls_wolfssl.c
@@ -347,6 +347,14 @@ int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
}
+char * tls_connection_peer_serial_num(void *tls_ctx,
+ struct tls_connection *conn)
+{
+ /* TODO */
+ return NULL;
+}
+
+
int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
{
WOLFSSL_SESSION *session;
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 22a37cc..4ac9f16 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1577,6 +1577,8 @@ struct wpa_driver_capa {
#define WPA_DRIVER_FLAGS_OCE_STA_CFON 0x0020000000000000ULL
/** Driver supports MFP-optional in the connect command */
#define WPA_DRIVER_FLAGS_MFP_OPTIONAL 0x0040000000000000ULL
+/** Driver is a self-managed regulatory device */
+#define WPA_DRIVER_FLAGS_SELF_MANAGED_REGULATORY 0x0080000000000000ULL
u64 flags;
#define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \
@@ -1911,8 +1913,21 @@ enum chan_width {
CHAN_WIDTH_UNKNOWN
};
+#define WPA_INVALID_NOISE 9999
+
/**
* struct wpa_signal_info - Information about channel signal quality
+ * @frequency: control frequency
+ * @above_threshold: true if the above threshold was crossed
+ * (relevant for a CQM event)
+ * @current_signal: in dBm
+ * @avg_signal: in dBm
+ * @avg_beacon_signal: in dBm
+ * @current_noise: %WPA_INVALID_NOISE if not supported
+ * @current_txrate: current TX rate
+ * @chanwidth: channel width
+ * @center_frq1: center frequency for the first segment
+ * @center_frq2: center frequency for the second segment (if relevant)
*/
struct wpa_signal_info {
u32 frequency;
diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c
index 16c2ae9..62f5baa 100644
--- a/src/drivers/driver_atheros.c
+++ b/src/drivers/driver_atheros.c
@@ -1329,11 +1329,11 @@ atheros_wireless_event_wireless_custom(struct atheros_driver_data *drv,
}
atheros_raw_receive(drv, NULL,
(u8 *) custom + MGMT_FRAM_TAG_SIZE, len);
- } else if (os_strncmp(custom, "Manage.auth ", 12) == 0) {
+ } else if (os_strncmp(custom, "Manage.auth ", 12) == 0) {
/* Format: "Manage.auth <frame len>" | zero padding | frame */
int len = atoi(custom + 12);
- if (len < 0 ||
- MGMT_FRAM_TAG_SIZE + len > end - custom) {
+ if (len < 0 ||
+ MGMT_FRAM_TAG_SIZE + len > end - custom) {
wpa_printf(MSG_DEBUG,
"Invalid Manage.auth event length %d", len);
return;
@@ -1342,7 +1342,7 @@ atheros_wireless_event_wireless_custom(struct atheros_driver_data *drv,
(u8 *) custom + MGMT_FRAM_TAG_SIZE, len);
#endif /* CONFIG_IEEE80211W || CONFIG_IEEE80211R || CONFIG_FILS */
#ifdef ATHEROS_USE_RAW_RECEIVE
- } else if (os_strncmp(custom, "Manage.action ", 14) == 0) {
+ } else if (os_strncmp(custom, "Manage.action ", 14) == 0) {
/* Format: "Manage.assoc_req <frame len>" | zero padding | frame
*/
int len = atoi(custom + 14);
diff --git a/src/drivers/driver_macsec_linux.c b/src/drivers/driver_macsec_linux.c
index e89b3ba..4f6629f 100644
--- a/src/drivers/driver_macsec_linux.c
+++ b/src/drivers/driver_macsec_linux.c
@@ -639,7 +639,7 @@ static int do_dump(struct macsec_drv_data *drv, u8 txsa, u64 rxsci, u8 rxsa,
DRV_PREFIX "failed to communicate: %d (%s)",
ret, nl_geterror(-ret));
- ctx->cb_arg.pn = 0;
+ ctx->cb_arg.pn = NULL;
out_free_msg:
nlmsg_free(msg);
@@ -1009,7 +1009,7 @@ static struct rtnl_link * lookup_sc(struct nl_cache *cache, int parent, u64 sci)
*/
static int macsec_drv_create_transmit_sc(
void *priv, struct transmit_sc *sc,
- enum confidentiality_offset conf_offset)
+ unsigned int conf_offset)
{
struct macsec_drv_data *drv = priv;
struct rtnl_link *link;
diff --git a/src/drivers/driver_macsec_qca.c b/src/drivers/driver_macsec_qca.c
index e397950..8372393 100644
--- a/src/drivers/driver_macsec_qca.c
+++ b/src/drivers/driver_macsec_qca.c
@@ -383,7 +383,7 @@ static int macsec_qca_get_transmit_next_pn(void *priv, struct transmit_sa *sa)
}
-int macsec_qca_set_transmit_next_pn(void *priv, struct transmit_sa *sa)
+static int macsec_qca_set_transmit_next_pn(void *priv, struct transmit_sa *sa)
{
struct macsec_qca_data *drv = priv;
int ret = 0;
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 39a02d3..871a5d0 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -40,6 +40,29 @@
#include "driver_nl80211.h"
+/* support for extack if compilation headers are too old */
+#ifndef NETLINK_EXT_ACK
+#define NETLINK_EXT_ACK 11
+enum nlmsgerr_attrs {
+ NLMSGERR_ATTR_UNUSED,
+ NLMSGERR_ATTR_MSG,
+ NLMSGERR_ATTR_OFFS,
+ NLMSGERR_ATTR_COOKIE,
+
+ __NLMSGERR_ATTR_MAX,
+ NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1
+};
+#endif
+#ifndef NLM_F_CAPPED
+#define NLM_F_CAPPED 0x100
+#endif
+#ifndef NLM_F_ACK_TLVS
+#define NLM_F_ACK_TLVS 0x200
+#endif
+#ifndef SOL_NETLINK
+#define SOL_NETLINK 270
+#endif
+
#ifndef CONFIG_LIBNL20
/*
* libnl 1.1 has a bug, it tries to allocate socket numbers densely
@@ -302,8 +325,35 @@ static int finish_handler(struct nl_msg *msg, void *arg)
static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
void *arg)
{
+ struct nlmsghdr *nlh = (struct nlmsghdr *) err - 1;
+ int len = nlh->nlmsg_len;
+ struct nlattr *attrs;
+ struct nlattr *tb[NLMSGERR_ATTR_MAX + 1];
int *ret = arg;
+ int ack_len = sizeof(*nlh) + sizeof(int) + sizeof(*nlh);
+
*ret = err->error;
+
+ if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS))
+ return NL_SKIP;
+
+ if (!(nlh->nlmsg_flags & NLM_F_CAPPED))
+ ack_len += err->msg.nlmsg_len - sizeof(*nlh);
+
+ if (len <= ack_len)
+ return NL_STOP;
+
+ attrs = (void *) ((unsigned char *) nlh + ack_len);
+ len -= ack_len;
+
+ nla_parse(tb, NLMSGERR_ATTR_MAX, attrs, len, NULL);
+ if (tb[NLMSGERR_ATTR_MSG]) {
+ len = strnlen((char *) nla_data(tb[NLMSGERR_ATTR_MSG]),
+ nla_len(tb[NLMSGERR_ATTR_MSG]));
+ wpa_printf(MSG_ERROR, "nl80211: kernel reports: %*s",
+ len, (char *) nla_data(tb[NLMSGERR_ATTR_MSG]));
+ }
+
return NL_SKIP;
}
@@ -342,7 +392,7 @@ static int send_and_recv(struct nl80211_global *global,
void *valid_data)
{
struct nl_cb *cb;
- int err = -ENOMEM;
+ int err = -ENOMEM, opt;
if (!msg)
return -ENOMEM;
@@ -351,6 +401,11 @@ static int send_and_recv(struct nl80211_global *global,
if (!cb)
goto out;
+ /* try to set NETLINK_EXT_ACK to 1, ignoring errors */
+ opt = 1;
+ setsockopt(nl_socket_get_fd(nl_handle), SOL_NETLINK,
+ NETLINK_EXT_ACK, &opt, sizeof(opt));
+
err = nl_send_auto_complete(nl_handle, msg);
if (err < 0)
goto out;
@@ -1414,7 +1469,7 @@ int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv,
{
struct nl_msg *msg;
- sig->current_signal = -9999;
+ sig->current_signal = -WPA_INVALID_NOISE;
sig->current_txrate = 0;
if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_STATION)) ||
@@ -1476,7 +1531,7 @@ int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv,
{
struct nl_msg *msg;
- sig_change->current_noise = 9999;
+ sig_change->current_noise = WPA_INVALID_NOISE;
sig_change->frequency = drv->assoc_freq;
msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY);
@@ -2145,6 +2200,11 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss)
/* WNM-Sleep Mode Response */
if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x11", 2) < 0)
ret = -1;
+#ifdef CONFIG_WNM
+ /* WNM - Collocated Interference Request */
+ if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x0b", 2) < 0)
+ ret = -1;
+#endif /* CONFIG_WNM */
#ifdef CONFIG_HS20
/* WNM-Notification */
@@ -3105,7 +3165,8 @@ static int nl80211_set_conn_keys(struct wpa_driver_associate_params *params,
int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
const u8 *addr, int cmd, u16 reason_code,
- int local_state_change)
+ int local_state_change,
+ struct nl_handle *nl_connect)
{
int ret;
struct nl_msg *msg;
@@ -3119,7 +3180,10 @@ int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
return -1;
}
- ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+ if (nl_connect)
+ ret = send_and_recv(drv->global, nl_connect, msg, NULL, NULL);
+ else
+ ret = send_and_recv_msgs(drv, msg, NULL, NULL);
if (ret) {
wpa_dbg(drv->ctx, MSG_DEBUG,
"nl80211: MLME command failed: reason=%u ret=%d (%s)",
@@ -3130,7 +3194,8 @@ int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
- int reason_code)
+ int reason_code,
+ struct nl_handle *nl_connect)
{
int ret;
int drv_associated = drv->associated;
@@ -3139,7 +3204,7 @@ static int wpa_driver_nl80211_disconnect(struct wpa_driver_nl80211_data *drv,
nl80211_mark_disconnected(drv);
/* Disconnect command doesn't need BSSID - it uses cached value */
ret = wpa_driver_nl80211_mlme(drv, NULL, NL80211_CMD_DISCONNECT,
- reason_code, 0);
+ reason_code, 0, nl_connect);
/*
* For locally generated disconnect, supplicant already generates a
* DEAUTH event, so ignore the event from NL80211.
@@ -3161,13 +3226,19 @@ static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss,
nl80211_mark_disconnected(drv);
return nl80211_leave_ibss(drv, 1);
}
- if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME))
- return wpa_driver_nl80211_disconnect(drv, reason_code);
+ if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) {
+ struct nl_handle *nl_connect = NULL;
+
+ if (bss->use_nl_connect)
+ nl_connect = bss->nl_connect;
+ return wpa_driver_nl80211_disconnect(drv, reason_code,
+ nl_connect);
+ }
wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)",
__func__, MAC2STR(addr), reason_code);
nl80211_mark_disconnected(drv);
ret = wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE,
- reason_code, 0);
+ reason_code, 0, NULL);
/*
* For locally generated deauthenticate, supplicant already generates a
* DEAUTH event, so ignore the event from NL80211.
@@ -5582,7 +5653,7 @@ static int wpa_driver_nl80211_connect(
"disconnecting before reassociation "
"attempt");
if (wpa_driver_nl80211_disconnect(
- drv, WLAN_REASON_PREV_AUTH_NOT_VALID))
+ drv, WLAN_REASON_PREV_AUTH_NOT_VALID, nl_connect))
return -1;
ret = wpa_driver_nl80211_try_connect(drv, params, nl_connect);
}
@@ -5613,8 +5684,13 @@ static int wpa_driver_nl80211_associate(
if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0)
return -1;
- if (params->auth_alg & WPA_AUTH_ALG_SAE)
+ if (params->auth_alg & WPA_AUTH_ALG_SAE) {
nl_connect = bss->nl_connect;
+ bss->use_nl_connect = 1;
+ } else {
+ bss->use_nl_connect = 0;
+ }
+
return wpa_driver_nl80211_connect(drv, params, nl_connect);
}
@@ -6221,6 +6297,7 @@ static int i802_set_tx_queue_params(void *priv, int queue, int aifs,
struct wpa_driver_nl80211_data *drv = bss->drv;
struct nl_msg *msg;
struct nlattr *txq, *params;
+ int res;
msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_WIPHY);
if (!msg)
@@ -6266,7 +6343,11 @@ static int i802_set_tx_queue_params(void *priv, int queue, int aifs,
nla_nest_end(msg, txq);
- if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
+ res = send_and_recv_msgs(drv, msg, NULL, NULL);
+ wpa_printf(MSG_DEBUG,
+ "nl80211: TX queue param set: queue=%d aifs=%d cw_min=%d cw_max=%d burst_time=%d --> res=%d",
+ queue, aifs, cw_min, cw_max, burst_time, res);
+ if (res == 0)
return 0;
msg = NULL;
fail:
@@ -6525,8 +6606,15 @@ static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
struct wpa_driver_nl80211_data *drv = bss->drv;
char name[IFNAMSIZ + 1];
union wpa_event_data event;
+ int ret;
+
+ ret = os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid);
+ if (ret >= (int) sizeof(name))
+ wpa_printf(MSG_WARNING,
+ "nl80211: WDS interface name was truncated");
+ else if (ret < 0)
+ return ret;
- os_snprintf(name, sizeof(name), "%s.sta%d", bss->ifname, aid);
if (ifname_wds)
os_strlcpy(ifname_wds, name, IFNAMSIZ + 1);
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index 5ac0c7d..bc562ba 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -66,6 +66,7 @@ struct i802_bss {
unsigned int wdev_id_set:1;
unsigned int added_if:1;
unsigned int static_ap:1;
+ unsigned int use_nl_connect:1;
u8 addr[ETH_ALEN];
@@ -252,7 +253,8 @@ int wpa_driver_nl80211_set_mode(struct i802_bss *bss,
enum nl80211_iftype nlmode);
int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
const u8 *addr, int cmd, u16 reason_code,
- int local_state_change);
+ int local_state_change,
+ struct nl_handle *nl_connect);
int nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv);
void nl80211_remove_monitor_interface(struct wpa_driver_nl80211_data *drv);
diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c
index a51b50d..7b360d2 100644
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -818,6 +818,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg)
capa->max_csa_counters =
nla_get_u8(tb[NL80211_ATTR_MAX_CSA_COUNTERS]);
+ if (tb[NL80211_ATTR_WIPHY_SELF_MANAGED_REG])
+ capa->flags |= WPA_DRIVER_FLAGS_SELF_MANAGED_REGULATORY;
+
return NL_SKIP;
}
@@ -1918,6 +1921,13 @@ static int nl80211_set_regulatory_flags(struct wpa_driver_nl80211_data *drv,
return -ENOMEM;
nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG);
+ if (drv->capa.flags & WPA_DRIVER_FLAGS_SELF_MANAGED_REGULATORY) {
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, drv->wiphy_idx)) {
+ nlmsg_free(msg);
+ return -1;
+ }
+ }
+
return send_and_recv_msgs(drv, msg, nl80211_get_reg, results);
}
diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c
index 5b8efbc..205b4cd 100644
--- a/src/drivers/driver_nl80211_event.c
+++ b/src/drivers/driver_nl80211_event.c
@@ -754,12 +754,12 @@ static void mlme_event_deauth_disassoc(struct wpa_driver_nl80211_data *drv,
* disconnection event for the old AP may show up after
* we have started connection with the new AP.
*/
- wpa_printf(MSG_DEBUG,
- "nl80211: Ignore deauth/disassoc event from old AP "
- MACSTR
- " when already connecting with " MACSTR,
- MAC2STR(bssid),
- MAC2STR(drv->auth_attempt_bssid));
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Ignore deauth/disassoc event from old AP "
+ MACSTR
+ " when already connecting with " MACSTR,
+ MAC2STR(bssid),
+ MAC2STR(drv->auth_attempt_bssid));
return;
}
@@ -2271,7 +2271,7 @@ static void nl80211_sta_opmode_change_event(struct wpa_driver_nl80211_data *drv,
ed.sta_opmode.addr = nla_data(tb[NL80211_ATTR_MAC]);
if (tb[NL80211_ATTR_SMPS_MODE]) {
- smps_mode = nla_get_u32(tb[NL80211_ATTR_SMPS_MODE]);
+ smps_mode = nla_get_u8(tb[NL80211_ATTR_SMPS_MODE]);
switch (smps_mode) {
case NL80211_SMPS_OFF:
ed.sta_opmode.smps_mode = SMPS_OFF;
diff --git a/src/drivers/driver_nl80211_monitor.c b/src/drivers/driver_nl80211_monitor.c
index 9376d11..f25cd79 100644
--- a/src/drivers/driver_nl80211_monitor.c
+++ b/src/drivers/driver_nl80211_monitor.c
@@ -361,8 +361,17 @@ int nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv)
*/
snprintf(buf, IFNAMSIZ, "mon-%s", drv->first_bss->ifname + 4);
} else {
+ int ret;
+
/* Non-P2P interface with AP functionality. */
- snprintf(buf, IFNAMSIZ, "mon.%s", drv->first_bss->ifname);
+ ret = os_snprintf(buf, IFNAMSIZ, "mon.%s",
+ drv->first_bss->ifname);
+ if (ret >= (int) sizeof(buf))
+ wpa_printf(MSG_DEBUG,
+ "nl80211: Monitor interface name has been truncated to %s",
+ buf);
+ else if (ret < 0)
+ return ret;
}
buf[IFNAMSIZ - 1] = '\0';
diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c
index 86501f4..33a8d35 100644
--- a/src/drivers/driver_nl80211_scan.c
+++ b/src/drivers/driver_nl80211_scan.c
@@ -866,7 +866,8 @@ static void clear_state_mismatch(struct wpa_driver_nl80211_data *drv,
"mismatch (" MACSTR ")", MAC2STR(addr));
wpa_driver_nl80211_mlme(drv, addr,
NL80211_CMD_DEAUTHENTICATE,
- WLAN_REASON_PREV_AUTH_NOT_VALID, 1);
+ WLAN_REASON_PREV_AUTH_NOT_VALID, 1,
+ NULL);
}
}
diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
index 933b8d9..20abaab 100644
--- a/src/drivers/driver_wext.c
+++ b/src/drivers/driver_wext.c
@@ -2428,8 +2428,8 @@ static int wpa_driver_wext_signal_poll(void *priv, struct wpa_signal_info *si)
struct iwreq iwr;
os_memset(si, 0, sizeof(*si));
- si->current_signal = -9999;
- si->current_noise = 9999;
+ si->current_signal = -WPA_INVALID_NOISE;
+ si->current_noise = WPA_INVALID_NOISE;
si->chanwidth = CHAN_WIDTH_UNKNOWN;
os_memset(&iwr, 0, sizeof(iwr));
diff --git a/src/drivers/driver_wired.c b/src/drivers/driver_wired.c
index 7e09dcf..c7537b7 100644
--- a/src/drivers/driver_wired.c
+++ b/src/drivers/driver_wired.c
@@ -96,16 +96,16 @@ static void handle_data(void *ctx, unsigned char *buf, size_t len)
hdr = (struct ieee8023_hdr *) buf;
switch (ntohs(hdr->ethertype)) {
- case ETH_P_PAE:
- wpa_printf(MSG_MSGDUMP, "Received EAPOL packet");
- sa = hdr->src;
- os_memset(&event, 0, sizeof(event));
- event.new_sta.addr = sa;
- wpa_supplicant_event(ctx, EVENT_NEW_STA, &event);
-
- pos = (u8 *) (hdr + 1);
- left = len - sizeof(*hdr);
- drv_event_eapol_rx(ctx, sa, pos, left);
+ case ETH_P_PAE:
+ wpa_printf(MSG_MSGDUMP, "Received EAPOL packet");
+ sa = hdr->src;
+ os_memset(&event, 0, sizeof(event));
+ event.new_sta.addr = sa;
+ wpa_supplicant_event(ctx, EVENT_NEW_STA, &event);
+
+ pos = (u8 *) (hdr + 1);
+ left = len - sizeof(*hdr);
+ drv_event_eapol_rx(ctx, sa, pos, left);
break;
default:
diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c
index 90ac3cf..761c16a 100644
--- a/src/eap_peer/eap_pwd.c
+++ b/src/eap_peer/eap_pwd.c
@@ -696,7 +696,7 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
const struct wpabuf *reqData,
const u8 *payload, size_t payload_len)
{
- struct crypto_hash *hash;
+ struct crypto_hash *hash = NULL;
u32 cs;
u16 grp;
u8 conf[SHA256_MAC_LEN], *cruft = NULL, *ptr;
@@ -783,6 +783,7 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
/* random function fin */
eap_pwd_h_final(hash, conf);
+ hash = NULL;
ptr = (u8 *) payload;
if (os_memcmp_const(conf, ptr, SHA256_MAC_LEN)) {
@@ -836,6 +837,7 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data,
/* all done */
eap_pwd_h_final(hash, conf);
+ hash = NULL;
if (compute_keys(data->grp, data->k,
data->my_scalar, data->server_scalar, conf, ptr,
@@ -860,6 +862,10 @@ fin:
} else {
eap_pwd_state(data, SUCCESS_ON_FRAG_COMPLETION);
}
+
+ /* clean allocated memory */
+ if (hash)
+ eap_pwd_h_final(hash, conf);
}
diff --git a/src/eap_server/eap.h b/src/eap_server/eap.h
index bb3641f..4fbc661 100644
--- a/src/eap_server/eap.h
+++ b/src/eap_server/eap.h
@@ -152,6 +152,7 @@ void eap_sm_notify_cached(struct eap_sm *sm);
void eap_sm_pending_cb(struct eap_sm *sm);
int eap_sm_method_pending(struct eap_sm *sm);
const u8 * eap_get_identity(struct eap_sm *sm, size_t *len);
+const char * eap_get_serial_num(struct eap_sm *sm);
struct eap_eapol_interface * eap_get_interface(struct eap_sm *sm);
void eap_server_clear_identity(struct eap_sm *sm);
void eap_server_mschap_rx_callback(struct eap_sm *sm, const char *source,
diff --git a/src/eap_server/eap_i.h b/src/eap_server/eap_i.h
index 3d6f8d5..cf8a9f0 100644
--- a/src/eap_server/eap_i.h
+++ b/src/eap_server/eap_i.h
@@ -159,6 +159,7 @@ struct eap_sm {
void *eap_method_priv;
u8 *identity;
size_t identity_len;
+ char *serial_num;
/* Whether Phase 2 method should validate identity match */
int require_identity_match;
int lastId; /* Identifier used in the last EAP-Packet */
diff --git a/src/eap_server/eap_server.c b/src/eap_server/eap_server.c
index c9da72e..38a1b5c 100644
--- a/src/eap_server/eap_server.c
+++ b/src/eap_server/eap_server.c
@@ -1920,6 +1920,7 @@ void eap_server_sm_deinit(struct eap_sm *sm)
wpabuf_free(sm->lastReqData);
wpabuf_free(sm->eap_if.eapRespData);
os_free(sm->identity);
+ os_free(sm->serial_num);
os_free(sm->pac_opaque_encr_key);
os_free(sm->eap_fast_a_id);
os_free(sm->eap_fast_a_id_info);
@@ -1991,6 +1992,17 @@ const u8 * eap_get_identity(struct eap_sm *sm, size_t *len)
}
+/**
+ * eap_get_serial_num - Get the serial number of user certificate
+ * @sm: Pointer to EAP state machine allocated with eap_server_sm_init()
+ * Returns: Pointer to the serial number or %NULL if not available
+ */
+const char * eap_get_serial_num(struct eap_sm *sm)
+{
+ return sm->serial_num;
+}
+
+
void eap_erp_update_identity(struct eap_sm *sm, const u8 *eap, size_t len)
{
#ifdef CONFIG_ERP
diff --git a/src/eap_server/eap_server_tls_common.c b/src/eap_server/eap_server_tls_common.c
index 4f9cb08..0ae7867 100644
--- a/src/eap_server/eap_server_tls_common.c
+++ b/src/eap_server/eap_server_tls_common.c
@@ -341,6 +341,11 @@ int eap_server_tls_phase1(struct eap_sm *sm, struct eap_ssl_data *data)
data->tls_v13 = os_strcmp(buf, "TLSv1.3") == 0;
}
+ if (!sm->serial_num &&
+ tls_connection_established(sm->ssl_ctx, data->conn))
+ sm->serial_num = tls_connection_peer_serial_num(sm->ssl_ctx,
+ data->conn);
+
return 0;
}
diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c
index b2fd9b7..e3afc0d 100644
--- a/src/radius/radius_server.c
+++ b/src/radius/radius_server.c
@@ -826,18 +826,28 @@ static void db_update_last_msk(struct radius_session *sess, const char *msk)
char *id_str = NULL;
const u8 *id;
size_t id_len;
+ const char *serial_num;
if (!sess->server->db)
return;
- id = eap_get_identity(sess->eap, &id_len);
- if (!id)
- return;
- id_str = os_malloc(id_len + 1);
- if (!id_str)
- return;
- os_memcpy(id_str, id, id_len);
- id_str[id_len] = '\0';
+ serial_num = eap_get_serial_num(sess->eap);
+ if (serial_num) {
+ id_len = 5 + os_strlen(serial_num) + 1;
+ id_str = os_malloc(id_len);
+ if (!id_str)
+ return;
+ os_snprintf(id_str, id_len, "cert-%s", serial_num);
+ } else {
+ id = eap_get_identity(sess->eap, &id_len);
+ if (!id)
+ return;
+ id_str = os_malloc(id_len + 1);
+ if (!id_str)
+ return;
+ os_memcpy(id_str, id, id_len);
+ id_str[id_len] = '\0';
+ }
sql = sqlite3_mprintf("UPDATE users SET last_msk=%Q WHERE identity=%Q",
msk, id_str);
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index 14b346a..345b0c8 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -2159,11 +2159,11 @@ static int wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
eloop_register_timeout(lifetime, 0, wpa_tdls_tpk_timeout,
sm, peer);
#ifdef CONFIG_TDLS_TESTING
- if (tdls_testing & TDLS_TESTING_NO_TPK_EXPIRATION) {
- wpa_printf(MSG_DEBUG, "TDLS: Testing - disable TPK "
- "expiration");
- eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
- }
+ if (tdls_testing & TDLS_TESTING_NO_TPK_EXPIRATION) {
+ wpa_printf(MSG_DEBUG,
+ "TDLS: Testing - disable TPK expiration");
+ eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
+ }
#endif /* CONFIG_TDLS_TESTING */
}
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 8e95cbd..e0c9130 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -1007,7 +1007,7 @@ static int wpa_supplicant_install_igtk(struct wpa_sm *sm,
}
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
- "WPA: IGTK keyid %d pn %02x%02x%02x%02x%02x%02x",
+ "WPA: IGTK keyid %d pn " COMPACT_MACSTR,
keyidx, MAC2STR(igtk->pn));
wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", igtk->igtk, len);
if (keyidx > 4095) {
diff --git a/src/utils/browser-wpadebug.c b/src/utils/browser-wpadebug.c
index 062e6fe..dfb4b67 100644
--- a/src/utils/browser-wpadebug.c
+++ b/src/utils/browser-wpadebug.c
@@ -97,6 +97,7 @@ int hs20_web_browser(const char *url)
if (pid == 0) {
/* run the external command in the child process */
char *argv[14];
+ char *envp[] = { "PATH=/system/bin:/vendor/bin", NULL };
argv[0] = "browser-wpadebug";
argv[1] = "start";
@@ -113,8 +114,8 @@ int hs20_web_browser(const char *url)
argv[12] = "-3"; /* USER_CURRENT_OR_SELF */
argv[13] = NULL;
- execv("/system/bin/am", argv);
- wpa_printf(MSG_ERROR, "execv: %s", strerror(errno));
+ execve("/system/bin/am", argv, envp);
+ wpa_printf(MSG_ERROR, "execve: %s", strerror(errno));
exit(0);
return -1;
}
diff --git a/src/utils/wpa_debug.c b/src/utils/wpa_debug.c
index 62758d8..a56462b 100644
--- a/src/utils/wpa_debug.c
+++ b/src/utils/wpa_debug.c
@@ -58,6 +58,10 @@ static int wpa_to_android_level(int level)
#ifndef CONFIG_NO_STDOUT_DEBUG
#ifdef CONFIG_DEBUG_FILE
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
static FILE *out_file = NULL;
#endif /* CONFIG_DEBUG_FILE */
@@ -539,6 +543,8 @@ int wpa_debug_reopen_file(void)
int wpa_debug_open_file(const char *path)
{
#ifdef CONFIG_DEBUG_FILE
+ int out_fd;
+
if (!path)
return 0;
@@ -548,10 +554,28 @@ int wpa_debug_open_file(const char *path)
last_path = os_strdup(path);
}
- out_file = fopen(path, "a");
+ out_fd = open(path, O_CREAT | O_APPEND | O_WRONLY,
+ S_IRUSR | S_IWUSR | S_IRGRP);
+ if (out_fd < 0) {
+ wpa_printf(MSG_ERROR,
+ "%s: Failed to open output file descriptor, using standard output",
+ __func__);
+ return -1;
+ }
+
+#ifdef __linux__
+ if (fcntl(out_fd, F_SETFD, FD_CLOEXEC) < 0) {
+ wpa_printf(MSG_DEBUG,
+ "%s: Failed to set FD_CLOEXEC - continue without: %s",
+ __func__, strerror(errno));
+ }
+#endif /* __linux__ */
+
+ out_file = fdopen(out_fd, "a");
if (out_file == NULL) {
wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open "
"output file, using standard output");
+ close(out_fd);
return -1;
}
#ifndef _WIN32
diff --git a/wpa_supplicant/ChangeLog b/wpa_supplicant/ChangeLog
index f28055f..bf4daaa 100644
--- a/wpa_supplicant/ChangeLog
+++ b/wpa_supplicant/ChangeLog
@@ -1,5 +1,75 @@
ChangeLog for wpa_supplicant
+2018-12-02 - v2.7
+ * fixed WPA packet number reuse with replayed messages and key
+ reinstallation
+ [https://w1.fi/security/2017-1/] (CVE-2017-13077, CVE-2017-13078,
+ CVE-2017-13079, CVE-2017-13080, CVE-2017-13081, CVE-2017-13082,
+ CVE-2017-13086, CVE-2017-13087, CVE-2017-13088)
+ * fixed unauthenticated EAPOL-Key decryption in wpa_supplicant
+ [https://w1.fi/security/2018-1/] (CVE-2018-14526)
+ * added support for FILS (IEEE 802.11ai) shared key authentication
+ * added support for OWE (Opportunistic Wireless Encryption, RFC 8110;
+ and transition mode defined by WFA)
+ * added support for DPP (Wi-Fi Device Provisioning Protocol)
+ * added support for RSA 3k key case with Suite B 192-bit level
+ * fixed Suite B PMKSA caching not to update PMKID during each 4-way
+ handshake
+ * fixed EAP-pwd pre-processing with PasswordHashHash
+ * added EAP-pwd client support for salted passwords
+ * fixed a regression in TDLS prohibited bit validation
+ * started to use estimated throughput to avoid undesired signal
+ strength based roaming decision
+ * MACsec/MKA:
+ - new macsec_linux driver interface support for the Linux
+ kernel macsec module
+ - number of fixes and extensions
+ * added support for external persistent storage of PMKSA cache
+ (PMKSA_GET/PMKSA_ADD control interface commands; and
+ MESH_PMKSA_GET/MESH_PMKSA_SET for the mesh case)
+ * fixed mesh channel configuration pri/sec switch case
+ * added support for beacon report
+ * large number of other fixes, cleanup, and extensions
+ * added support for randomizing local address for GAS queries
+ (gas_rand_mac_addr parameter)
+ * fixed EAP-SIM/AKA/AKA' ext auth cases within TLS tunnel
+ * added option for using random WPS UUID (auto_uuid=1)
+ * added SHA256-hash support for OCSP certificate matching
+ * fixed EAP-AKA' to add AT_KDF into Synchronization-Failure
+ * fixed a regression in RSN pre-authentication candidate selection
+ * added option to configure allowed group management cipher suites
+ (group_mgmt network profile parameter)
+ * removed all PeerKey functionality
+ * fixed nl80211 AP and mesh mode configuration regression with
+ Linux 4.15 and newer
+ * added ap_isolate configuration option for AP mode
+ * added support for nl80211 to offload 4-way handshake into the driver
+ * added support for using wolfSSL cryptographic library
+ * SAE
+ - added support for configuring SAE password separately of the
+ WPA2 PSK/passphrase
+ - fixed PTK and EAPOL-Key integrity and key-wrap algorithm selection
+ for SAE;
+ note: this is not backwards compatible, i.e., both the AP and
+ station side implementations will need to be update at the same
+ time to maintain interoperability
+ - added support for Password Identifier
+ - fixed FT-SAE PMKID matching
+ * Hotspot 2.0
+ - added support for fetching of Operator Icon Metadata ANQP-element
+ - added support for Roaming Consortium Selection element
+ - added support for Terms and Conditions
+ - added support for OSEN connection in a shared RSN BSS
+ - added support for fetching Venue URL information
+ * added support for using OpenSSL 1.1.1
+ * FT
+ - disabled PMKSA caching with FT since it is not fully functional
+ - added support for SHA384 based AKM
+ - added support for BIP ciphers BIP-CMAC-256, BIP-GMAC-128,
+ BIP-GMAC-256 in addition to previously supported BIP-CMAC-128
+ - fixed additional IE inclusion in Reassociation Request frame when
+ using FT protocol
+
2016-10-02 - v2.6
* fixed WNM Sleep Mode processing when PMF is not enabled
[http://w1.fi/security/2015-6/] (CVE-2015-5310)
diff --git a/wpa_supplicant/README b/wpa_supplicant/README
index 730714b..2a3265f 100644
--- a/wpa_supplicant/README
+++ b/wpa_supplicant/README
@@ -1,7 +1,7 @@
WPA Supplicant
==============
-Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi> and contributors
+Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi> and contributors
All Rights Reserved.
This program is licensed under the BSD license (the one with
diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c
index 5aa07ea..3a41db9 100644
--- a/wpa_supplicant/bss.c
+++ b/wpa_supplicant/bss.c
@@ -103,6 +103,7 @@ static struct wpa_bss_anqp * wpa_bss_anqp_clone(struct wpa_bss_anqp *anqp)
ANQP_DUP(hs20_operating_class);
ANQP_DUP(hs20_osu_providers_list);
ANQP_DUP(hs20_operator_icon_metadata);
+ ANQP_DUP(hs20_osu_providers_nai_list);
#endif /* CONFIG_HS20 */
#undef ANQP_DUP
@@ -187,6 +188,7 @@ static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp)
wpabuf_free(anqp->hs20_operating_class);
wpabuf_free(anqp->hs20_osu_providers_list);
wpabuf_free(anqp->hs20_operator_icon_metadata);
+ wpabuf_free(anqp->hs20_osu_providers_nai_list);
#endif /* CONFIG_HS20 */
os_free(anqp);
diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h
index 9179385..5251b2c 100644
--- a/wpa_supplicant/bss.h
+++ b/wpa_supplicant/bss.h
@@ -51,6 +51,7 @@ struct wpa_bss_anqp {
struct wpabuf *hs20_operating_class;
struct wpabuf *hs20_osu_providers_list;
struct wpabuf *hs20_operator_icon_metadata;
+ struct wpabuf *hs20_osu_providers_nai_list;
#endif /* CONFIG_HS20 */
};
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index dd7f603..c439606 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -3155,14 +3155,16 @@ static int wpa_config_set_cred_roaming_consortiums(struct wpa_cred *cred,
}
roaming_consortiums_len[num_roaming_consortiums] = len / 2;
num_roaming_consortiums++;
- if (num_roaming_consortiums > MAX_ROAMING_CONS) {
+
+ if (!end)
+ break;
+
+ if (num_roaming_consortiums >= MAX_ROAMING_CONS) {
wpa_printf(MSG_INFO,
"Too many roaming_consortiums OIs");
return -1;
}
- if (!end)
- break;
pos = end + 1;
}
@@ -4753,6 +4755,7 @@ static const struct global_parse_data global_fields[] = {
{ INT(gas_rand_addr_lifetime), 0 },
{ INT_RANGE(gas_rand_mac_addr, 0, 2), 0 },
{ INT_RANGE(dpp_config_processing, 0, 2), 0 },
+ { INT_RANGE(coloc_intf_reporting, 0, 1), 0 },
};
#undef FUNC
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index ad4dd88..cd7571f 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -1469,6 +1469,15 @@ struct wpa_config {
* profile automatically
*/
int dpp_config_processing;
+
+ /**
+ * coloc_intf_reporting - Colocated interference reporting
+ *
+ * dot11CoLocIntfReportingActivated
+ * 0 = disabled (false)
+ * 1 = enabled (true)
+ */
+ int coloc_intf_reporting;
};
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index aa73f9d..09115e1 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -1511,7 +1511,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
if (config->dpp_config_processing)
fprintf(f, "dpp_config_processing=%d\n",
config->dpp_config_processing);
-
+ if (config->coloc_intf_reporting)
+ fprintf(f, "coloc_intf_reporting=%d\n",
+ config->coloc_intf_reporting);
}
#endif /* CONFIG_NO_CONFIG_WRITE */
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 3000c43..d2a52d7 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -927,6 +927,16 @@ struct wpa_ssid {
* 1 = disable transition mode (allow connection only with OWE)
*/
int owe_only;
+
+ /**
+ * owe_transition_bss_select_count - OWE transition BSS select count
+ *
+ * This is an internally used variable (i.e., not used in external
+ * configuration) to track the number of selection attempts done for
+ * OWE BSS in transition mode. This allows fallback to an open BSS if
+ * the selection attempts for OWE BSS exceed the configured threshold.
+ */
+ int owe_transition_bss_select_count;
};
#endif /* CONFIG_SSID_H */
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index fe39c25..77a3133 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -750,6 +750,15 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
ret = wpas_ctrl_iface_set_ric_ies(wpa_s, value);
} else if (os_strcasecmp(cmd, "roaming") == 0) {
ret = wpa_drv_roaming(wpa_s, atoi(value), NULL);
+#ifdef CONFIG_WNM
+ } else if (os_strcasecmp(cmd, "coloc_intf_elems") == 0) {
+ struct wpabuf *elems;
+
+ elems = wpabuf_parse_bin(value);
+ if (!elems)
+ return -1;
+ wnm_set_coloc_intf_elems(wpa_s, elems);
+#endif /* CONFIG_WNM */
} else {
value[-1] = '=';
ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
@@ -4809,6 +4818,8 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
anqp->hs20_osu_providers_list);
pos = anqp_add_hex(pos, end, "hs20_operator_icon_metadata",
anqp->hs20_operator_icon_metadata);
+ pos = anqp_add_hex(pos, end, "hs20_osu_providers_nai_list",
+ anqp->hs20_osu_providers_nai_list);
#endif /* CONFIG_HS20 */
dl_list_for_each(elem, &anqp->anqp_elems,
@@ -7435,6 +7446,22 @@ static int wpas_ctrl_iface_wnm_bss_query(struct wpa_supplicant *wpa_s, char *cmd
list);
}
+
+static int wpas_ctrl_iface_coloc_intf_report(struct wpa_supplicant *wpa_s,
+ char *cmd)
+{
+ struct wpabuf *elems;
+ int ret;
+
+ elems = wpabuf_parse_bin(cmd);
+ if (!elems)
+ return -1;
+
+ ret = wnm_send_coloc_intf_report(wpa_s, 0, elems);
+ wpabuf_free(elems);
+ return ret;
+}
+
#endif /* CONFIG_WNM */
@@ -10421,6 +10448,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "WNM_BSS_QUERY ", 14) == 0) {
if (wpas_ctrl_iface_wnm_bss_query(wpa_s, buf + 14))
reply_len = -1;
+ } else if (os_strncmp(buf, "COLOC_INTF_REPORT ", 18) == 0) {
+ if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18))
+ reply_len = -1;
#endif /* CONFIG_WNM */
} else if (os_strcmp(buf, "FLUSH") == 0) {
wpa_supplicant_ctrl_iface_flush(wpa_s);
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index e0f16bb..d4deb0f 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -2131,11 +2131,6 @@ void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
case WPAS_DBUS_PROP_AP_SCAN:
prop = "ApScan";
break;
-#ifdef CONFIG_IEEE80211W
- case WPAS_DBUS_PROP_PMF:
- prop = "Pmf";
- break;
-#endif /* CONFIG_IEEE80211W */
case WPAS_DBUS_PROP_SCANNING:
prop = "Scanning";
break;
@@ -3307,13 +3302,6 @@ static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = {
wpas_dbus_setter_ap_scan,
NULL
},
-#ifdef CONFIG_IEEE80211W
- { "Pmf", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
- wpas_dbus_getter_pmf,
- wpas_dbus_setter_pmf,
- NULL
- },
-#endif /* CONFIG_IEEE80211W */
{ "BSSExpireAge", WPAS_DBUS_NEW_IFACE_INTERFACE, "u",
wpas_dbus_getter_bss_expire_age,
wpas_dbus_setter_bss_expire_age,
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index e68acb7..40ae133 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -22,7 +22,6 @@ struct wps_credential;
enum wpas_dbus_prop {
WPAS_DBUS_PROP_AP_SCAN,
- WPAS_DBUS_PROP_PMF,
WPAS_DBUS_PROP_SCANNING,
WPAS_DBUS_PROP_STATE,
WPAS_DBUS_PROP_CURRENT_BSS,
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c
index a3c98fa..94773b3 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers.c
@@ -980,8 +980,8 @@ 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[8] = { NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL };
+ const char *capabilities[10] = { NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL };
size_t num_items = 0;
#ifdef CONFIG_FILS
struct wpa_global *global = user_data;
@@ -1020,6 +1020,12 @@ dbus_bool_t wpas_dbus_getter_global_capabilities(
if (fils_sk_pfs_supported)
capabilities[num_items++] = "fils_sk_pfs";
#endif /* CONFIG_FILS */
+#ifdef CONFIG_IEEE80211R
+ capabilities[num_items++] = "ft";
+#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_SHA384
+ capabilities[num_items++] = "sha384";
+#endif /* CONFIG_SHA384 */
return wpas_dbus_simple_array_property_getter(iter,
DBUS_TYPE_STRING,
@@ -3012,61 +3018,6 @@ dbus_bool_t wpas_dbus_setter_ap_scan(
}
-#ifdef CONFIG_IEEE80211W
-
-/**
- * wpas_dbus_getter_pmf - Control PMF default
- * @iter: Pointer to incoming dbus message iter
- * @error: Location to store error on failure
- * @user_data: Function specific data
- * Returns: TRUE on success, FALSE on failure
- *
- * Getter function for "Pmf" property.
- */
-dbus_bool_t wpas_dbus_getter_pmf(
- const struct wpa_dbus_property_desc *property_desc,
- DBusMessageIter *iter, DBusError *error, void *user_data)
-{
- struct wpa_supplicant *wpa_s = user_data;
- dbus_uint32_t pmf = wpa_s->conf->pmf;
-
- return wpas_dbus_simple_property_getter(iter, DBUS_TYPE_UINT32,
- &pmf, error);
-}
-
-
-/**
- * wpas_dbus_setter_pmf - Control PMF default
- * @iter: Pointer to incoming dbus message iter
- * @error: Location to store error on failure
- * @user_data: Function specific data
- * Returns: TRUE on success, FALSE on failure
- *
- * Setter function for "Pmf" property.
- */
-dbus_bool_t wpas_dbus_setter_pmf(
- const struct wpa_dbus_property_desc *property_desc,
- DBusMessageIter *iter, DBusError *error, void *user_data)
-{
- struct wpa_supplicant *wpa_s = user_data;
- dbus_uint32_t pmf;
-
- if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_UINT32,
- &pmf))
- return FALSE;
-
- if (pmf > 2) {
- dbus_set_error_const(error, DBUS_ERROR_FAILED,
- "Pmf must be 0, 1, or 2");
- return FALSE;
- }
- wpa_s->conf->pmf = pmf;
- return TRUE;
-}
-
-#endif /* CONFIG_IEEE80211W */
-
-
/**
* wpas_dbus_getter_fast_reauth - Control fast
* reauthentication (TLS session resumption)
diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h
index 26652ad..6f952cc 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers.h
+++ b/wpa_supplicant/dbus/dbus_new_handlers.h
@@ -141,8 +141,6 @@ DECLARE_ACCESSOR(wpas_dbus_getter_state);
DECLARE_ACCESSOR(wpas_dbus_getter_scanning);
DECLARE_ACCESSOR(wpas_dbus_getter_ap_scan);
DECLARE_ACCESSOR(wpas_dbus_setter_ap_scan);
-DECLARE_ACCESSOR(wpas_dbus_getter_pmf);
-DECLARE_ACCESSOR(wpas_dbus_setter_pmf);
DECLARE_ACCESSOR(wpas_dbus_getter_fast_reauth);
DECLARE_ACCESSOR(wpas_dbus_setter_fast_reauth);
DECLARE_ACCESSOR(wpas_dbus_getter_disconnect_reason);
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index 08f5857..af281e5 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -44,7 +44,7 @@ CONFIG_DRIVER_NL80211=y
#CONFIG_LIBNL20=y
# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
-#CONFIG_LIBNL32=y
+CONFIG_LIBNL32=y
# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
diff --git a/wpa_supplicant/doc/docbook/eapol_test.sgml b/wpa_supplicant/doc/docbook/eapol_test.sgml
index 25cfd06..ae6bafe 100644
--- a/wpa_supplicant/doc/docbook/eapol_test.sgml
+++ b/wpa_supplicant/doc/docbook/eapol_test.sgml
@@ -194,7 +194,7 @@ eapol_test -ctest.conf -a127.0.0.1 -p1812 -ssecret -r1
</refsect1>
<refsect1>
<title>Legal</title>
- <para>wpa_supplicant is copyright (c) 2003-2017,
+ <para>wpa_supplicant is copyright (c) 2003-2018,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_background.sgml b/wpa_supplicant/doc/docbook/wpa_background.sgml
index fa94ae4..d3e4dbe 100644
--- a/wpa_supplicant/doc/docbook/wpa_background.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_background.sgml
@@ -90,7 +90,7 @@
<refsect1>
<title>Legal</title>
- <para>wpa_supplicant is copyright (c) 2003-2017,
+ <para>wpa_supplicant is copyright (c) 2003-2018,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_cli.sgml b/wpa_supplicant/doc/docbook/wpa_cli.sgml
index be3045a..766dd2c 100644
--- a/wpa_supplicant/doc/docbook/wpa_cli.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_cli.sgml
@@ -345,7 +345,7 @@ CTRL-REQ-OTP-2:Challenge 1235663 needed for SSID foobar
</refsect1>
<refsect1>
<title>Legal</title>
- <para>wpa_supplicant is copyright (c) 2003-2017,
+ <para>wpa_supplicant is copyright (c) 2003-2018,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_gui.sgml b/wpa_supplicant/doc/docbook/wpa_gui.sgml
index cee9ed6..91662d5 100644
--- a/wpa_supplicant/doc/docbook/wpa_gui.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_gui.sgml
@@ -91,7 +91,7 @@
</refsect1>
<refsect1>
<title>Legal</title>
- <para>wpa_supplicant is copyright (c) 2003-2017,
+ <para>wpa_supplicant is copyright (c) 2003-2018,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_passphrase.sgml b/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
index 6667a07..2f86b0b 100644
--- a/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_passphrase.sgml
@@ -62,7 +62,7 @@
</refsect1>
<refsect1>
<title>Legal</title>
- <para>wpa_supplicant is copyright (c) 2003-2017,
+ <para>wpa_supplicant is copyright (c) 2003-2018,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_priv.sgml b/wpa_supplicant/doc/docbook/wpa_priv.sgml
index 3796b93..4a5f319 100644
--- a/wpa_supplicant/doc/docbook/wpa_priv.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_priv.sgml
@@ -137,7 +137,7 @@ wpa_supplicant -i ath0 -c wpa_supplicant.conf
</refsect1>
<refsect1>
<title>Legal</title>
- <para>wpa_supplicant is copyright (c) 2003-2017,
+ <para>wpa_supplicant is copyright (c) 2003-2018,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
diff --git a/wpa_supplicant/doc/docbook/wpa_supplicant.sgml b/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
index 80b3878..eeb9c07 100644
--- a/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_supplicant.sgml
@@ -729,7 +729,7 @@ fi
</refsect1>
<refsect1>
<title>Legal</title>
- <para>wpa_supplicant is copyright (c) 2003-2017,
+ <para>wpa_supplicant is copyright (c) 2003-2018,
Jouni Malinen <email>j@w1.fi</email> and
contributors.
All Rights Reserved.</para>
diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c
index 899c4c2..7bc4661 100644
--- a/wpa_supplicant/dpp_supplicant.c
+++ b/wpa_supplicant/dpp_supplicant.c
@@ -527,9 +527,9 @@ static void wpas_dpp_set_testing_options(struct wpa_supplicant *wpa_s,
}
-static void wpas_dpp_set_configurator(struct wpa_supplicant *wpa_s,
- struct dpp_authentication *auth,
- const char *cmd)
+static int wpas_dpp_set_configurator(struct wpa_supplicant *wpa_s,
+ struct dpp_authentication *auth,
+ const char *cmd)
{
const char *pos, *end;
struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL;
@@ -543,7 +543,7 @@ static void wpas_dpp_set_configurator(struct wpa_supplicant *wpa_s,
char *group_id = NULL;
if (!cmd)
- return;
+ return 0;
wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd);
pos = os_strstr(cmd, " ssid=");
@@ -607,10 +607,12 @@ static void wpas_dpp_set_configurator(struct wpa_supplicant *wpa_s,
conf_sta->akm = DPP_AKM_PSK;
if (psk_set) {
os_memcpy(conf_sta->psk, psk, PMK_LEN);
- } else {
+ } else if (pass_len > 0) {
conf_sta->passphrase = os_strdup(pass);
if (!conf_sta->passphrase)
goto fail;
+ } else {
+ goto fail;
}
} else if (os_strstr(cmd, " conf=sta-dpp")) {
conf_sta->akm = DPP_AKM_DPP;
@@ -684,13 +686,14 @@ static void wpas_dpp_set_configurator(struct wpa_supplicant *wpa_s,
auth->conf_ap = conf_ap;
auth->conf = conf;
os_free(group_id);
- return;
+ return 0;
fail:
- wpa_printf(MSG_DEBUG, "DPP: Failed to set configurator parameters");
+ wpa_msg(wpa_s, MSG_INFO, "DPP: Failed to set configurator parameters");
dpp_configuration_free(conf_sta);
dpp_configuration_free(conf_ap);
os_free(group_id);
+ return -1;
}
@@ -869,7 +872,11 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd)
if (!wpa_s->dpp_auth)
goto fail;
wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
- wpas_dpp_set_configurator(wpa_s, wpa_s->dpp_auth, cmd);
+ if (wpas_dpp_set_configurator(wpa_s, wpa_s->dpp_auth, cmd) < 0) {
+ dpp_auth_deinit(wpa_s->dpp_auth);
+ wpa_s->dpp_auth = NULL;
+ goto fail;
+ }
wpa_s->dpp_auth->neg_freq = neg_freq;
@@ -1015,29 +1022,6 @@ void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s)
}
-void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
- unsigned int freq)
-{
- if (!wpa_s->dpp_listen_freq && !wpa_s->dpp_pending_listen_freq)
- return;
-
- wpa_printf(MSG_DEBUG,
- "DPP: remain-on-channel callback (off_channel_freq=%u dpp_pending_listen_freq=%d roc_waiting_drv_freq=%d freq=%u)",
- wpa_s->off_channel_freq, wpa_s->dpp_pending_listen_freq,
- wpa_s->roc_waiting_drv_freq, freq);
- if (wpa_s->off_channel_freq &&
- wpa_s->off_channel_freq == wpa_s->dpp_pending_listen_freq) {
- wpa_printf(MSG_DEBUG, "DPP: Listen on %u MHz started", freq);
- wpa_s->dpp_pending_listen_freq = 0;
- } else {
- wpa_printf(MSG_DEBUG,
- "DPP: Ignore remain-on-channel callback (off_channel_freq=%u dpp_pending_listen_freq=%d freq=%u)",
- wpa_s->off_channel_freq,
- wpa_s->dpp_pending_listen_freq, freq);
- }
-}
-
-
void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
unsigned int freq)
{
@@ -1142,8 +1126,12 @@ static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src,
return;
}
wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth);
- wpas_dpp_set_configurator(wpa_s, wpa_s->dpp_auth,
- wpa_s->dpp_configurator_params);
+ if (wpas_dpp_set_configurator(wpa_s, wpa_s->dpp_auth,
+ wpa_s->dpp_configurator_params) < 0) {
+ dpp_auth_deinit(wpa_s->dpp_auth);
+ wpa_s->dpp_auth = NULL;
+ return;
+ }
os_memcpy(wpa_s->dpp_auth->peer_mac_addr, src, ETH_ALEN);
if (wpa_s->dpp_listen_freq &&
@@ -1346,7 +1334,8 @@ static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token,
wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
return;
}
- if (!resp || status_code != WLAN_STATUS_SUCCESS) {
+ if (result != GAS_QUERY_SUCCESS ||
+ !resp || status_code != WLAN_STATUS_SUCCESS) {
wpa_printf(MSG_DEBUG, "DPP: GAS query did not succeed");
goto fail;
}
@@ -2286,9 +2275,9 @@ int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd)
return -1;
curve = get_param(cmd, " curve=");
- wpas_dpp_set_configurator(wpa_s, auth, cmd);
-
- if (dpp_configurator_own_config(auth, curve, 0) == 0) {
+ wpas_dpp_set_testing_options(wpa_s, auth);
+ if (wpas_dpp_set_configurator(wpa_s, auth, cmd) == 0 &&
+ dpp_configurator_own_config(auth, curve, 0) == 0) {
wpas_dpp_handle_config_obj(wpa_s, auth);
ret = 0;
}
diff --git a/wpa_supplicant/dpp_supplicant.h b/wpa_supplicant/dpp_supplicant.h
index 9b539df..5a4f06e 100644
--- a/wpa_supplicant/dpp_supplicant.h
+++ b/wpa_supplicant/dpp_supplicant.h
@@ -19,8 +19,6 @@ int wpas_dpp_bootstrap_info(struct wpa_supplicant *wpa_s, int id,
int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd);
int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd);
void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s);
-void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
- unsigned int freq);
void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s,
unsigned int freq);
void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src,
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 349f819..37d429d 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -50,6 +50,9 @@
#include "dpp_supplicant.h"
+#define MAX_OWE_TRANSITION_BSS_SELECT_COUNT 5
+
+
#ifndef CONFIG_NO_SCAN_PROCESSING
static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
int new_scan, int own_request);
@@ -314,6 +317,7 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s)
wpas_rrm_reset(wpa_s);
wpa_s->wnmsleep_used = 0;
+ wnm_clear_coloc_intf_reporting(wpa_s);
#ifdef CONFIG_TESTING_OPTIONS
wpa_s->last_tk_alg = WPA_ALG_NONE;
@@ -703,6 +707,19 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s,
#ifdef CONFIG_OWE
if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) && !ssid->owe_only &&
!wpa_ie && !rsn_ie) {
+ if (wpa_s->owe_transition_select &&
+ wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE) &&
+ ssid->owe_transition_bss_select_count + 1 <=
+ MAX_OWE_TRANSITION_BSS_SELECT_COUNT) {
+ ssid->owe_transition_bss_select_count++;
+ if (debug_print)
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ " skip OWE transition BSS (selection count %d does not exceed %d)",
+ ssid->owe_transition_bss_select_count,
+ MAX_OWE_TRANSITION_BSS_SELECT_COUNT);
+ wpa_s->owe_transition_search = 1;
+ return 0;
+ }
if (debug_print)
wpa_dbg(wpa_s, MSG_DEBUG,
" allow in OWE transition mode");
@@ -1387,8 +1404,11 @@ wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s,
for (i = 0; i < wpa_s->last_scan_res_used; i++) {
struct wpa_bss *bss = wpa_s->last_scan_res[i];
+
+ wpa_s->owe_transition_select = 1;
*selected_ssid = wpa_scan_res_match(wpa_s, i, bss, group,
only_first_ssid, 1);
+ wpa_s->owe_transition_select = 0;
if (!*selected_ssid)
continue;
wpa_dbg(wpa_s, MSG_DEBUG, " selected BSS " MACSTR
@@ -1935,6 +1955,7 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
if (wpa_s->p2p_mgmt)
return 0; /* no normal connection on p2p_mgmt interface */
+ wpa_s->owe_transition_search = 0;
selected = wpa_supplicant_pick_network(wpa_s, &ssid);
#ifdef CONFIG_MESH
@@ -2036,6 +2057,17 @@ static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s,
return 0;
}
#endif /* CONFIG_WPS */
+#ifdef CONFIG_OWE
+ if (wpa_s->owe_transition_search) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "OWE: Use shorter wait during transition mode search");
+ timeout_sec = 0;
+ timeout_usec = 500000;
+ wpa_supplicant_req_new_scan(wpa_s, timeout_sec,
+ timeout_usec);
+ return 0;
+ }
+#endif /* CONFIG_OWE */
if (wpa_supplicant_req_sched_scan(wpa_s))
wpa_supplicant_req_new_scan(wpa_s, timeout_sec,
timeout_usec);
@@ -3999,6 +4031,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
{
struct wpa_supplicant *wpa_s = ctx;
int resched;
+#ifndef CONFIG_NO_STDOUT_DEBUG
+ int level = MSG_DEBUG;
+#endif /* CONFIG_NO_STDOUT_DEBUG */
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED &&
event != EVENT_INTERFACE_ENABLED &&
@@ -4012,9 +4047,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
}
#ifndef CONFIG_NO_STDOUT_DEBUG
-{
- int level = MSG_DEBUG;
-
if (event == EVENT_RX_MGMT && data->rx_mgmt.frame_len >= 24) {
const struct ieee80211_hdr *hdr;
u16 fc;
@@ -4027,7 +4059,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpa_dbg(wpa_s, level, "Event %s (%d) received",
event_to_string(event), event);
-}
#endif /* CONFIG_NO_STDOUT_DEBUG */
switch (event) {
@@ -4054,6 +4085,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
}
#endif /* CONFIG_TESTING_OPTIONS */
wpa_supplicant_event_assoc(wpa_s, data);
+ wpa_s->assoc_status_code = WLAN_STATUS_SUCCESS;
if (data &&
(data->assoc_info.authorized ||
(!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
@@ -4308,6 +4340,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
#endif /* CONFIG_AP */
wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS);
+ wnm_clear_coloc_intf_reporting(wpa_s);
break;
#ifdef CONFIG_AP
#ifdef NEED_AP_MLME
diff --git a/wpa_supplicant/examples/wps-ap-cli b/wpa_supplicant/examples/wps-ap-cli
index cc2cff2..15d913e 100755
--- a/wpa_supplicant/examples/wps-ap-cli
+++ b/wpa_supplicant/examples/wps-ap-cli
@@ -14,12 +14,12 @@ pbc()
enter_pin()
{
echo "Enter a PIN from a station to be enrolled to the network."
- echo -n "Enrollee PIN: "
+ printf "Enrollee PIN: "
read pin
cpin=`$CLI wps_check_pin "$pin" | tail -1`
if [ "$cpin" = "FAIL-CHECKSUM" ]; then
echo "Checksum digit is not valid"
- echo -n "Do you want to use this PIN (y/n)? "
+ printf "Do you want to use this PIN (y/n)? "
read resp
case "$resp" in
y*)
@@ -52,7 +52,7 @@ main_menu()
echo "3: Show current configuration"
echo "0: Exit wps-ap-cli"
- echo -n "Command: "
+ printf "Command: "
read cmd
case "$cmd" in
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index e00c5af..f418790 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -54,6 +54,7 @@ struct osu_provider {
char server_uri[256];
u32 osu_methods; /* bit 0 = OMA-DM, bit 1 = SOAP-XML SPP */
char osu_nai[256];
+ char osu_nai2[256];
struct osu_lang_string friendly_name[OSU_MAX_ITEMS];
size_t friendly_name_count;
struct osu_lang_string serv_desc[OSU_MAX_ITEMS];
@@ -673,6 +674,15 @@ void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
wpabuf_alloc_copy(pos, slen);
}
break;
+ case HS20_STYPE_OSU_PROVIDERS_NAI_LIST:
+ wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR
+ " OSU Providers NAI List", MAC2STR(sa));
+ if (anqp) {
+ wpabuf_free(anqp->hs20_osu_providers_nai_list);
+ anqp->hs20_osu_providers_nai_list =
+ wpabuf_alloc_copy(pos, slen);
+ }
+ break;
default:
wpa_printf(MSG_DEBUG, "HS20: Unsupported subtype %u", subtype);
break;
@@ -759,6 +769,8 @@ static void hs20_osu_fetch_done(struct wpa_supplicant *wpa_s)
}
if (osu->osu_nai[0])
fprintf(f, "osu_nai=%s\n", osu->osu_nai);
+ if (osu->osu_nai2[0])
+ fprintf(f, "osu_nai2=%s\n", osu->osu_nai2);
for (j = 0; j < osu->friendly_name_count; j++) {
fprintf(f, "friendly_name=%s:%s\n",
osu->friendly_name[j].lang,
@@ -1103,6 +1115,35 @@ void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s)
"extra data after OSU Providers",
(int) (end - pos));
}
+
+ prov_anqp = bss->anqp->hs20_osu_providers_nai_list;
+ if (!prov_anqp)
+ continue;
+ wpa_printf(MSG_DEBUG,
+ "HS 2.0: Parsing OSU Providers NAI List from "
+ MACSTR, MAC2STR(bss->bssid));
+ wpa_hexdump_buf(MSG_DEBUG, "HS 2.0: OSU Providers NAI List",
+ prov_anqp);
+ pos = wpabuf_head(prov_anqp);
+ end = pos + wpabuf_len(prov_anqp);
+ num_providers = 0;
+ while (end - pos > 0) {
+ len = *pos++;
+ if (end - pos < len) {
+ wpa_printf(MSG_DEBUG,
+ "HS 2.0: Not enough room for OSU_NAI");
+ break;
+ }
+ if (num_providers >= wpa_s->osu_prov_count) {
+ wpa_printf(MSG_DEBUG,
+ "HS 2.0: Ignore unexpected OSU Provider NAI List entries");
+ break;
+ }
+ os_memcpy(wpa_s->osu_prov[num_providers].osu_nai2,
+ pos, len);
+ pos += len;
+ num_providers++;
+ }
}
wpa_s->fetch_osu_icon_in_progress = 1;
diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c
index f3f88d3..60c8be9 100644
--- a/wpa_supplicant/interworking.c
+++ b/wpa_supplicant/interworking.c
@@ -303,8 +303,10 @@ static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s,
wpabuf_put_u8(extra, HS20_STYPE_CONNECTION_CAPABILITY);
if (all)
wpabuf_put_u8(extra, HS20_STYPE_OPERATING_CLASS);
- if (all)
+ if (all) {
wpabuf_put_u8(extra, HS20_STYPE_OSU_PROVIDERS_LIST);
+ wpabuf_put_u8(extra, HS20_STYPE_OSU_PROVIDERS_NAI_LIST);
+ }
gas_anqp_set_element_len(extra, len_pos);
}
#endif /* CONFIG_HS20 */
diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c
index d166cfe..eafb0af 100644
--- a/wpa_supplicant/mesh_mpm.c
+++ b/wpa_supplicant/mesh_mpm.c
@@ -222,13 +222,14 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s,
if (!sta)
return;
- buf_len = 2 + /* capability info */
+ buf_len = 2 + /* Category and Action */
+ 2 + /* capability info */
2 + /* AID */
2 + 8 + /* supported rates */
2 + (32 - 8) +
2 + 32 + /* mesh ID */
2 + 7 + /* mesh config */
- 2 + 23 + /* peering management */
+ 2 + 24 + /* peering management */
2 + 96 + /* AMPE */
2 + 16; /* MIC */
#ifdef CONFIG_IEEE80211N
diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c
index 56d53fb..ee39e0c 100644
--- a/wpa_supplicant/scan.c
+++ b/wpa_supplicant/scan.c
@@ -677,6 +677,87 @@ static void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s,
}
+static void wpa_add_scan_ssid(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params,
+ size_t max_ssids, const u8 *ssid, size_t ssid_len)
+{
+ unsigned int j;
+
+ for (j = 0; j < params->num_ssids; j++) {
+ if (params->ssids[j].ssid_len == ssid_len &&
+ params->ssids[j].ssid &&
+ os_memcmp(params->ssids[j].ssid, ssid, ssid_len) == 0)
+ return; /* already in the list */
+ }
+
+ if (params->num_ssids + 1 > max_ssids) {
+ wpa_printf(MSG_DEBUG, "Over max scan SSIDs for manual request");
+ return;
+ }
+
+ wpa_printf(MSG_DEBUG, "Scan SSID (manual request): %s",
+ wpa_ssid_txt(ssid, ssid_len));
+
+ params->ssids[params->num_ssids].ssid = ssid;
+ params->ssids[params->num_ssids].ssid_len = ssid_len;
+ params->num_ssids++;
+}
+
+
+static void wpa_add_owe_scan_ssid(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params,
+ struct wpa_ssid *ssid, size_t max_ssids)
+{
+#ifdef CONFIG_OWE
+ struct wpa_bss *bss;
+
+ if (!(ssid->key_mgmt & WPA_KEY_MGMT_OWE))
+ return;
+
+ wpa_printf(MSG_DEBUG, "OWE: Look for transition mode AP. ssid=%s",
+ wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
+
+ dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
+ const u8 *owe, *pos, *end;
+ const u8 *owe_ssid;
+ size_t owe_ssid_len;
+
+ if (bss->ssid_len != ssid->ssid_len ||
+ os_memcmp(bss->ssid, ssid->ssid, ssid->ssid_len) != 0)
+ continue;
+
+ owe = wpa_bss_get_vendor_ie(bss, OWE_IE_VENDOR_TYPE);
+ if (!owe || owe[1] < 4)
+ continue;
+
+ pos = owe + 6;
+ end = owe + 2 + owe[1];
+
+ /* Must include BSSID and ssid_len */
+ if (end - pos < ETH_ALEN + 1)
+ return;
+
+ /* Skip BSSID */
+ pos += ETH_ALEN;
+ owe_ssid_len = *pos++;
+ owe_ssid = pos;
+
+ if ((size_t) (end - pos) < owe_ssid_len ||
+ owe_ssid_len > SSID_MAX_LEN)
+ return;
+
+ wpa_printf(MSG_DEBUG,
+ "OWE: scan_ssids: transition mode OWE ssid=%s",
+ wpa_ssid_txt(owe_ssid, owe_ssid_len));
+
+ wpa_add_scan_ssid(wpa_s, params, max_ssids,
+ owe_ssid, owe_ssid_len);
+ return;
+ }
+#endif /* CONFIG_OWE */
+}
+
+
static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s,
struct wpa_driver_scan_params *params,
size_t max_ssids)
@@ -691,33 +772,17 @@ static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s,
max_ssids = max_ssids > 1 ? max_ssids - 1 : max_ssids;
for (i = 0; i < wpa_s->scan_id_count; i++) {
- unsigned int j;
-
ssid = wpa_config_get_network(wpa_s->conf, wpa_s->scan_id[i]);
- if (!ssid || !ssid->scan_ssid)
+ if (!ssid)
continue;
-
- for (j = 0; j < params->num_ssids; j++) {
- if (params->ssids[j].ssid_len == ssid->ssid_len &&
- params->ssids[j].ssid &&
- os_memcmp(params->ssids[j].ssid, ssid->ssid,
- ssid->ssid_len) == 0)
- break;
- }
- if (j < params->num_ssids)
- continue; /* already in the list */
-
- if (params->num_ssids + 1 > max_ssids) {
- wpa_printf(MSG_DEBUG,
- "Over max scan SSIDs for manual request");
- break;
- }
-
- wpa_printf(MSG_DEBUG, "Scan SSID (manual request): %s",
- wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
- params->ssids[params->num_ssids].ssid = ssid->ssid;
- params->ssids[params->num_ssids].ssid_len = ssid->ssid_len;
- params->num_ssids++;
+ if (ssid->scan_ssid)
+ wpa_add_scan_ssid(wpa_s, params, max_ssids,
+ ssid->ssid, ssid->ssid_len);
+ /*
+ * Also add the SSID of the OWE BSS, to allow discovery of
+ * transition mode APs more quickly.
+ */
+ wpa_add_owe_scan_ssid(wpa_s, params, ssid, max_ssids);
}
wpa_s->scan_id_count = 0;
@@ -984,6 +1049,17 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
if (params.num_ssids + 1 >= max_ssids)
break;
}
+
+ if (!wpas_network_disabled(wpa_s, ssid)) {
+ /*
+ * Also add the SSID of the OWE BSS, to allow
+ * discovery of transition mode APs more
+ * quickly.
+ */
+ wpa_add_owe_scan_ssid(wpa_s, &params, ssid,
+ max_ssids);
+ }
+
ssid = ssid->next;
if (ssid == start)
break;
diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c
index 708a347..39c8069 100644
--- a/wpa_supplicant/sme.c
+++ b/wpa_supplicant/sme.c
@@ -72,7 +72,7 @@ static int sme_set_sae_group(struct wpa_supplicant *wpa_s)
if (sae_set_group(&wpa_s->sme.sae, group) == 0) {
wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected SAE group %d",
wpa_s->sme.sae.group);
- return 0;
+ return 0;
}
wpa_s->sme.sae_group_index++;
}
@@ -240,6 +240,8 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
u8 ext_capab[18];
int ext_capab_len;
int skip_auth;
+ u8 *wpa_ie;
+ size_t wpa_ie_len;
#ifdef CONFIG_MBO
const u8 *mbo_ie;
#endif /* CONFIG_MBO */
@@ -352,6 +354,20 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
wpas_connect_work_done(wpa_s);
return;
}
+#ifdef CONFIG_HS20
+ } else if (wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
+ (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
+ /* No PMKSA caching, but otherwise similar to RSN/WPA */
+ wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
+ if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
+ wpa_s->sme.assoc_req_ie,
+ &wpa_s->sme.assoc_req_ie_len)) {
+ wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA "
+ "key management and encryption suites");
+ wpas_connect_work_done(wpa_s);
+ return;
+ }
+#endif /* CONFIG_HS20 */
} else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) &&
wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
/*
@@ -391,6 +407,28 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
wpa_s->sme.assoc_req_ie_len = 0;
}
+ /* In case the WPA vendor IE is used, it should be placed after all the
+ * non-vendor IEs, as the lower layer expects the IEs to be ordered as
+ * defined in the standard. Store the WPA IE so it can later be
+ * inserted at the correct location.
+ */
+ wpa_ie = NULL;
+ wpa_ie_len = 0;
+ if (wpa_s->wpa_proto == WPA_PROTO_WPA) {
+ wpa_ie = os_memdup(wpa_s->sme.assoc_req_ie,
+ wpa_s->sme.assoc_req_ie_len);
+ if (wpa_ie) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Storing WPA IE");
+
+ wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
+ wpa_s->sme.assoc_req_ie_len = 0;
+ } else {
+ wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed copy WPA IE");
+ wpas_connect_work_done(wpa_s);
+ return;
+ }
+ }
+
#ifdef CONFIG_IEEE80211R
ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN);
if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN)
@@ -527,6 +565,26 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
}
#endif /* CONFIG_HS20 */
+ if (wpa_ie) {
+ size_t len;
+
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Reinsert WPA IE");
+
+ len = sizeof(wpa_s->sme.assoc_req_ie) -
+ wpa_s->sme.assoc_req_ie_len;
+
+ if (len > wpa_ie_len) {
+ os_memcpy(wpa_s->sme.assoc_req_ie +
+ wpa_s->sme.assoc_req_ie_len,
+ wpa_ie, wpa_ie_len);
+ wpa_s->sme.assoc_req_ie_len += wpa_ie_len;
+ } else {
+ wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Failed to add WPA IE");
+ }
+
+ os_free(wpa_ie);
+ }
+
if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) {
struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ];
size_t len;
@@ -837,10 +895,10 @@ static int sme_external_auth_build_buf(struct wpabuf *buf,
os_memcpy(resp->da, da, ETH_ALEN);
os_memcpy(resp->sa, sa, ETH_ALEN);
os_memcpy(resp->bssid, da, ETH_ALEN);
- resp->u.auth.auth_alg = WLAN_AUTH_SAE;
- resp->seq_ctrl = seq_num << 4;
- resp->u.auth.auth_transaction = auth_transaction;
- resp->u.auth.status_code = WLAN_STATUS_SUCCESS;
+ resp->u.auth.auth_alg = host_to_le16(WLAN_AUTH_SAE);
+ resp->seq_ctrl = host_to_le16(seq_num << 4);
+ resp->u.auth.auth_transaction = host_to_le16(auth_transaction);
+ resp->u.auth.status_code = host_to_le16(WLAN_STATUS_SUCCESS);
if (params)
wpabuf_put_buf(buf, params);
@@ -900,7 +958,8 @@ static void sme_handle_external_auth_start(struct wpa_supplicant *wpa_s,
for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
if (!wpas_network_disabled(wpa_s, ssid) &&
ssid_str_len == ssid->ssid_len &&
- os_memcmp(ssid_str, ssid->ssid, ssid_str_len) == 0)
+ os_memcmp(ssid_str, ssid->ssid, ssid_str_len) == 0 &&
+ (ssid->key_mgmt & WPA_KEY_MGMT_SAE))
break;
}
if (ssid)
@@ -1119,13 +1178,14 @@ void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
return;
}
- if (header->u.auth.auth_alg == WLAN_AUTH_SAE) {
+ if (le_to_host16(header->u.auth.auth_alg) == WLAN_AUTH_SAE) {
int res;
- res = sme_sae_auth(wpa_s, header->u.auth.auth_transaction,
- header->u.auth.status_code,
- header->u.auth.variable,
- len - auth_length, 1, header->sa);
+ res = sme_sae_auth(
+ wpa_s, le_to_host16(header->u.auth.auth_transaction),
+ le_to_host16(header->u.auth.status_code),
+ header->u.auth.variable,
+ len - auth_length, 1, header->sa);
if (res < 0) {
/* Notify failure to the driver */
sme_send_external_auth_status(
@@ -1460,14 +1520,18 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
if (wpa_s->current_ssid && wpa_s->current_ssid->owe_group) {
group = wpa_s->current_ssid->owe_group;
- } else {
+ } else if (wpa_s->assoc_status_code ==
+ WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
if (wpa_s->last_owe_group == 19)
group = 20;
else if (wpa_s->last_owe_group == 20)
group = 21;
else
group = OWE_DH_GROUP;
+ } else {
+ group = OWE_DH_GROUP;
}
+
wpa_s->last_owe_group = group;
wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
@@ -1499,6 +1563,8 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
params.wpa_ie = wpa_s->sme.assoc_req_ie_len ?
wpa_s->sme.assoc_req_ie : NULL;
params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
+ wpa_hexdump(MSG_DEBUG, "SME: Association Request IEs",
+ params.wpa_ie, params.wpa_ie_len);
params.pairwise_suite = wpa_s->pairwise_cipher;
params.group_suite = wpa_s->group_cipher;
params.mgmt_group_suite = wpa_s->mgmt_group_cipher;
@@ -1519,9 +1585,85 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, &params);
#endif /* CONFIG_VHT_OVERRIDES */
#ifdef CONFIG_IEEE80211R
- if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
+ if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies &&
+ get_ie(wpa_s->sme.ft_ies, wpa_s->sme.ft_ies_len,
+ WLAN_EID_RIC_DATA)) {
+ /* There seems to be a pretty inconvenient bug in the Linux
+ * kernel IE splitting functionality when RIC is used. For now,
+ * skip correct behavior in IE construction here (i.e., drop the
+ * additional non-FT-specific IEs) to avoid kernel issues. This
+ * is fine since RIC is used only for testing purposes in the
+ * current implementation. */
+ wpa_printf(MSG_INFO,
+ "SME: Linux kernel workaround - do not try to include additional IEs with RIC");
params.wpa_ie = wpa_s->sme.ft_ies;
params.wpa_ie_len = wpa_s->sme.ft_ies_len;
+ } else if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) {
+ const u8 *rm_en, *pos, *end;
+ size_t rm_en_len = 0;
+ u8 *rm_en_dup = NULL, *wpos;
+
+ /* Remove RSNE, MDE, FTE to allow them to be overridden with
+ * FT specific values */
+ remove_ie(wpa_s->sme.assoc_req_ie,
+ &wpa_s->sme.assoc_req_ie_len,
+ WLAN_EID_RSN);
+ remove_ie(wpa_s->sme.assoc_req_ie,
+ &wpa_s->sme.assoc_req_ie_len,
+ WLAN_EID_MOBILITY_DOMAIN);
+ remove_ie(wpa_s->sme.assoc_req_ie,
+ &wpa_s->sme.assoc_req_ie_len,
+ WLAN_EID_FAST_BSS_TRANSITION);
+ rm_en = get_ie(wpa_s->sme.assoc_req_ie,
+ wpa_s->sme.assoc_req_ie_len,
+ WLAN_EID_RRM_ENABLED_CAPABILITIES);
+ if (rm_en) {
+ /* Need to remove RM Enabled Capabilities element as
+ * well temporarily, so that it can be placed between
+ * RSNE and MDE. */
+ rm_en_len = 2 + rm_en[1];
+ rm_en_dup = os_memdup(rm_en, rm_en_len);
+ remove_ie(wpa_s->sme.assoc_req_ie,
+ &wpa_s->sme.assoc_req_ie_len,
+ WLAN_EID_RRM_ENABLED_CAPABILITIES);
+ }
+ wpa_hexdump(MSG_DEBUG,
+ "SME: Association Request IEs after FT IE removal",
+ wpa_s->sme.assoc_req_ie,
+ wpa_s->sme.assoc_req_ie_len);
+ if (wpa_s->sme.assoc_req_ie_len + wpa_s->sme.ft_ies_len +
+ rm_en_len > sizeof(wpa_s->sme.assoc_req_ie)) {
+ wpa_printf(MSG_ERROR,
+ "SME: Not enough buffer room for FT IEs in Association Request frame");
+ os_free(rm_en_dup);
+ return;
+ }
+
+ os_memmove(wpa_s->sme.assoc_req_ie + wpa_s->sme.ft_ies_len +
+ rm_en_len,
+ wpa_s->sme.assoc_req_ie,
+ wpa_s->sme.assoc_req_ie_len);
+ pos = wpa_s->sme.ft_ies;
+ end = pos + wpa_s->sme.ft_ies_len;
+ wpos = wpa_s->sme.assoc_req_ie;
+ if (*pos == WLAN_EID_RSN) {
+ os_memcpy(wpos, pos, 2 + pos[1]);
+ wpos += 2 + pos[1];
+ pos += 2 + pos[1];
+ }
+ if (rm_en_dup) {
+ os_memcpy(wpos, rm_en_dup, rm_en_len);
+ wpos += rm_en_len;
+ os_free(rm_en_dup);
+ }
+ os_memcpy(wpos, pos, end - pos);
+ wpa_s->sme.assoc_req_ie_len += wpa_s->sme.ft_ies_len +
+ rm_en_len;
+ params.wpa_ie = wpa_s->sme.assoc_req_ie;
+ params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len;
+ wpa_hexdump(MSG_DEBUG,
+ "SME: Association Request IEs after FT override",
+ params.wpa_ie, params.wpa_ie_len);
}
#endif /* CONFIG_IEEE80211R */
params.mode = mode;
diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c
index 7c410e7..6b68fc9 100644
--- a/wpa_supplicant/wnm_sta.c
+++ b/wpa_supplicant/wnm_sta.c
@@ -338,6 +338,9 @@ void wnm_deallocate_memory(struct wpa_supplicant *wpa_s)
wpa_s->wnm_num_neighbor_report = 0;
os_free(wpa_s->wnm_neighbor_report_elements);
wpa_s->wnm_neighbor_report_elements = NULL;
+
+ wpabuf_free(wpa_s->coloc_intf_elems);
+ wpa_s->coloc_intf_elems = NULL;
}
@@ -1717,6 +1720,46 @@ static void ieee802_11_rx_wnm_notif_req(struct wpa_supplicant *wpa_s,
}
+static void ieee802_11_rx_wnm_coloc_intf_req(struct wpa_supplicant *wpa_s,
+ const u8 *sa, const u8 *frm,
+ int len)
+{
+ u8 dialog_token, req_info, auto_report, timeout;
+
+ if (!wpa_s->conf->coloc_intf_reporting)
+ return;
+
+ /* Dialog Token [1] | Request Info [1] */
+
+ if (len < 2)
+ return;
+ dialog_token = frm[0];
+ req_info = frm[1];
+ auto_report = req_info & 0x03;
+ timeout = req_info >> 2;
+
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WNM: Received Collocated Interference Request (dialog_token %u auto_report %u timeout %u sa " MACSTR ")",
+ dialog_token, auto_report, timeout, MAC2STR(sa));
+
+ if (dialog_token == 0)
+ return; /* only nonzero values are used for request */
+
+ if (wpa_s->wpa_state != WPA_COMPLETED ||
+ os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG,
+ "WNM: Collocated Interference Request frame not from current AP - ignore it");
+ return;
+ }
+
+ wpa_msg(wpa_s, MSG_INFO, COLOC_INTF_REQ "%u %u %u",
+ dialog_token, auto_report, timeout);
+ wpa_s->coloc_intf_dialog_token = dialog_token;
+ wpa_s->coloc_intf_auto_report = auto_report;
+ wpa_s->coloc_intf_timeout = timeout;
+}
+
+
void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
const struct ieee80211_mgmt *mgmt, size_t len)
{
@@ -1750,8 +1793,75 @@ void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s,
case WNM_NOTIFICATION_REQ:
ieee802_11_rx_wnm_notif_req(wpa_s, mgmt->sa, pos, end - pos);
break;
+ case WNM_COLLOCATED_INTERFERENCE_REQ:
+ ieee802_11_rx_wnm_coloc_intf_req(wpa_s, mgmt->sa, pos,
+ end - pos);
+ break;
default:
wpa_printf(MSG_ERROR, "WNM: Unknown request");
break;
}
}
+
+
+int wnm_send_coloc_intf_report(struct wpa_supplicant *wpa_s, u8 dialog_token,
+ const struct wpabuf *elems)
+{
+ struct wpabuf *buf;
+ int ret;
+
+ if (wpa_s->wpa_state < WPA_ASSOCIATED || !elems)
+ return -1;
+
+ wpa_printf(MSG_DEBUG, "WNM: Send Collocated Interference Report to "
+ MACSTR " (dialog token %u)",
+ MAC2STR(wpa_s->bssid), dialog_token);
+
+ buf = wpabuf_alloc(3 + wpabuf_len(elems));
+ if (!buf)
+ return -1;
+
+ wpabuf_put_u8(buf, WLAN_ACTION_WNM);
+ wpabuf_put_u8(buf, WNM_COLLOCATED_INTERFERENCE_REPORT);
+ wpabuf_put_u8(buf, dialog_token);
+ wpabuf_put_buf(buf, elems);
+
+ ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+ wpa_s->own_addr, wpa_s->bssid,
+ wpabuf_head_u8(buf), wpabuf_len(buf), 0);
+ wpabuf_free(buf);
+ return ret;
+}
+
+
+void wnm_set_coloc_intf_elems(struct wpa_supplicant *wpa_s,
+ struct wpabuf *elems)
+{
+ wpabuf_free(wpa_s->coloc_intf_elems);
+ if (elems && wpabuf_len(elems) == 0) {
+ wpabuf_free(elems);
+ elems = NULL;
+ }
+ wpa_s->coloc_intf_elems = elems;
+
+ if (wpa_s->conf->coloc_intf_reporting && wpa_s->coloc_intf_elems &&
+ wpa_s->coloc_intf_dialog_token &&
+ (wpa_s->coloc_intf_auto_report == 1 ||
+ wpa_s->coloc_intf_auto_report == 3)) {
+ /* TODO: Check that there has not been less than
+ * wpa_s->coloc_intf_timeout * 200 TU from the last report.
+ */
+ wnm_send_coloc_intf_report(wpa_s,
+ wpa_s->coloc_intf_dialog_token,
+ wpa_s->coloc_intf_elems);
+ }
+}
+
+
+void wnm_clear_coloc_intf_reporting(struct wpa_supplicant *wpa_s)
+{
+#ifdef CONFIG_WNM
+ wpa_s->coloc_intf_dialog_token = 0;
+ wpa_s->coloc_intf_auto_report = 0;
+#endif /* CONFIG_WNM */
+}
diff --git a/wpa_supplicant/wnm_sta.h b/wpa_supplicant/wnm_sta.h
index 02cd1cd..29625f8 100644
--- a/wpa_supplicant/wnm_sta.h
+++ b/wpa_supplicant/wnm_sta.h
@@ -65,11 +65,16 @@ int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s,
int cand_list);
void wnm_deallocate_memory(struct wpa_supplicant *wpa_s);
+int wnm_send_coloc_intf_report(struct wpa_supplicant *wpa_s, u8 dialog_token,
+ const struct wpabuf *elems);
+void wnm_set_coloc_intf_elems(struct wpa_supplicant *wpa_s,
+ struct wpabuf *elems);
#ifdef CONFIG_WNM
int wnm_scan_process(struct wpa_supplicant *wpa_s, int reply_on_fail);
+void wnm_clear_coloc_intf_reporting(struct wpa_supplicant *wpa_s);
#else /* CONFIG_WNM */
@@ -79,6 +84,10 @@ static inline int wnm_scan_process(struct wpa_supplicant *wpa_s,
return 0;
}
+static inline void wnm_clear_coloc_intf_reporting(struct wpa_supplicant *wpa_s)
+{
+}
+
#endif /* CONFIG_WNM */
#endif /* WNM_STA_H */
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 05e3ebf..7793554 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -1,6 +1,6 @@
/*
* WPA Supplicant - command line interface for wpa_supplicant daemon
- * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -29,7 +29,7 @@
static const char *const wpa_cli_version =
"wpa_cli v" VERSION_STR "\n"
-"Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi> and contributors";
#define VENDOR_ELEM_FRAME_ID \
" 0: Probe Req (P2P), 1: Probe Resp (P2P) , 2: Probe Resp (GO), " \
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 4531c62..e587d7e 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -68,7 +68,7 @@
const char *const wpa_supplicant_version =
"wpa_supplicant v" VERSION_STR "\n"
-"Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi> and contributors";
+"Copyright (c) 2003-2018, Jouni Malinen <j@w1.fi> and contributors";
const char *const wpa_supplicant_license =
"This software may be distributed under the terms of the BSD license.\n"
@@ -1216,13 +1216,12 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0");
proto = WPA_PROTO_WPA;
#ifdef CONFIG_HS20
- } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN)) {
+ } else if (bss_osen && (ssid->proto & WPA_PROTO_OSEN) &&
+ wpa_parse_wpa_ie(bss_osen, 2 + bss_osen[1], &ie) == 0 &&
+ (ie.group_cipher & ssid->group_cipher) &&
+ (ie.pairwise_cipher & ssid->pairwise_cipher) &&
+ (ie.key_mgmt & ssid->key_mgmt)) {
wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: using OSEN");
- /* TODO: parse OSEN element */
- os_memset(&ie, 0, sizeof(ie));
- ie.group_cipher = WPA_CIPHER_CCMP;
- ie.pairwise_cipher = WPA_CIPHER_CCMP;
- ie.key_mgmt = WPA_KEY_MGMT_OSEN;
proto = WPA_PROTO_OSEN;
} else if (bss_rsn && (ssid->proto & WPA_PROTO_OSEN) &&
wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 &&
@@ -1645,6 +1644,10 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
case 0: /* Bits 0-7 */
break;
case 1: /* Bits 8-15 */
+ if (wpa_s->conf->coloc_intf_reporting) {
+ /* Bit 13 - Collocated Interference Reporting */
+ *pos |= 0x20;
+ }
break;
case 2: /* Bits 16-23 */
#ifdef CONFIG_WNM
@@ -2494,6 +2497,19 @@ static u8 * wpas_populate_assoc_ies(
os_free(wpa_ie);
return NULL;
}
+#ifdef CONFIG_HS20
+ } else if (bss && wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE) &&
+ (ssid->key_mgmt & WPA_KEY_MGMT_OSEN)) {
+ /* No PMKSA caching, but otherwise similar to RSN/WPA */
+ wpa_ie_len = max_wpa_ie_len;
+ if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
+ wpa_ie, &wpa_ie_len)) {
+ wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA "
+ "key management and encryption suites");
+ os_free(wpa_ie);
+ return NULL;
+ }
+#endif /* CONFIG_HS20 */
} else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss &&
wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) {
/*
@@ -2738,14 +2754,18 @@ static u8 * wpas_populate_assoc_ies(
if (ssid->owe_group) {
group = ssid->owe_group;
- } else {
+ } else if (wpa_s->assoc_status_code ==
+ WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) {
if (wpa_s->last_owe_group == 19)
group = 20;
else if (wpa_s->last_owe_group == 20)
group = 21;
else
group = OWE_DH_GROUP;
+ } else {
+ group = OWE_DH_GROUP;
}
+
wpa_s->last_owe_group = group;
wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
@@ -3307,6 +3327,7 @@ static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s,
return;
ssid->disabled = 0;
+ ssid->owe_transition_bss_select_count = 0;
wpas_clear_temp_disabled(wpa_s, ssid, 1);
wpas_notify_network_enabled_changed(wpa_s, ssid);
@@ -3571,6 +3592,8 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
wpa_s->disconnected = 0;
wpa_s->reassociate = 1;
wpa_s->last_owe_group = 0;
+ if (ssid)
+ ssid->owe_transition_bss_select_count = 0;
if (wpa_s->connect_without_scan ||
wpa_supplicant_fast_associate(wpa_s) != 1) {
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 9b8d1fa..8b749f4 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -743,6 +743,8 @@ struct wpa_supplicant {
unsigned int mac_addr_changed:1;
unsigned int added_vif:1;
unsigned int wnmsleep_used:1;
+ unsigned int owe_transition_select:1;
+ unsigned int owe_transition_search:1;
struct os_reltime last_mac_addr_change;
int last_mac_addr_style;
@@ -1057,6 +1059,10 @@ struct wpa_supplicant {
struct neighbor_report *wnm_neighbor_report_elements;
struct os_reltime wnm_cand_valid_until;
u8 wnm_cand_from_bss[ETH_ALEN];
+ struct wpabuf *coloc_intf_elems;
+ u8 coloc_intf_dialog_token;
+ u8 coloc_intf_auto_report;
+ u8 coloc_intf_timeout;
#ifdef CONFIG_MBO
unsigned int wnm_mbo_trans_reason_present:1;
u8 wnm_mbo_transition_reason;