diff mbox series

D-Bus: add a signal for HS2.0 terms and conditions

Message ID 20240119155254.2784188-1-damiendejean@chromium.org
State Accepted
Headers show
Series D-Bus: add a signal for HS2.0 terms and conditions | expand

Commit Message

Damien Dejean Jan. 19, 2024, 3:52 p.m. UTC
Add HS20TermsAndConditions signal to D-Bus API to allow clients to be
notified when the network requires the acceptance of terms and
conditions. The URL of the T&C page is provided as a signal parameter.

Signed-off-by: Damien Dejean <damiendejean@chromium.org>
---
 doc/dbus.doxygen                 |  9 +++++
 tests/hwsim/test_dbus.py         | 64 +++++++++++++++++++++++++++++++-
 wpa_supplicant/dbus/dbus_new.c   | 47 +++++++++++++++++++++++
 wpa_supplicant/dbus/dbus_new.h   |  8 ++++
 wpa_supplicant/hs20_supplicant.c |  3 +-
 wpa_supplicant/notify.c          | 12 ++++++
 wpa_supplicant/notify.h          |  2 +
 7 files changed, 143 insertions(+), 2 deletions(-)

Comments

Jouni Malinen Jan. 20, 2024, 6:33 p.m. UTC | #1
On Fri, Jan 19, 2024 at 03:52:54PM +0000, Damien Dejean wrote:
> Add HS20TermsAndConditions signal to D-Bus API to allow clients to be
> notified when the network requires the acceptance of terms and
> conditions. The URL of the T&C page is provided as a signal parameter.

Thanks, applied.
diff mbox series

Patch

diff --git a/doc/dbus.doxygen b/doc/dbus.doxygen
index 386ecf2dc..4c5f5f9e9 100644
--- a/doc/dbus.doxygen
+++ b/doc/dbus.doxygen
@@ -1336,6 +1336,15 @@  fi.w1.wpa_supplicant1.CreateInterface.
 	<h3>PskMismatch ( )</h3>
 	<p>A possible PSK mismatch is identified.</p>
       </li>
+
+      <li>
+	<h3>HS20TermsAndConditions ( s : url )</h3>
+	<p>A terms and conditions page is present. This signal is delivered when the network requires acceptance of the terms and conditions.</p>
+	<dl>
+	  <dt>s : url</dt>
+	  <dd>URL of the terms and conditions page.</dd>
+	</dl>
+      </li>
     </ul>
 
 
diff --git a/tests/hwsim/test_dbus.py b/tests/hwsim/test_dbus.py
index fc1c64982..4dee2277b 100644
--- a/tests/hwsim/test_dbus.py
+++ b/tests/hwsim/test_dbus.py
@@ -28,7 +28,7 @@  from wpasupplicant import WpaSupplicant
 from utils import *
 from p2p_utils import *
 from test_ap_tdls import connect_2sta_open
-from test_ap_eap import check_altsubject_match_support
+from test_ap_eap import check_altsubject_match_support, check_eap_capa
 from test_nfc_p2p import set_ip_addr_info
 from test_wpas_mesh import check_mesh_support, add_open_mesh_network
 
@@ -6243,3 +6243,65 @@  def test_dbus_interworking(dev, apdev):
     with TestDbusInterworking(bus) as t:
         if not t.success():
             raise Exception("Expected signals not seen")
+
+def test_dbus_hs20_terms_and_conditions(dev, apdev):
+    "D-Bus HS2.0 Terms and Conditions acceptance"
+    check_eap_capa(dev[0], "MSCHAPV2")
+
+    (bus, wpa_obj, path, if_obj) = prepare_dbus(dev[0])
+    iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE)
+
+    bssid = apdev[0]['bssid']
+    params = {"ssid": "test-hs20", "hessid": bssid, "wpa": "2",
+              "rsn_pairwise": "CCMP", "wpa_key_mgmt": "WPA-EAP",
+              "ieee80211w": "1", "ieee8021x": "1",
+              "auth_server_addr": "127.0.0.1", "auth_server_port": "1812",
+              "auth_server_shared_secret": "radius", "interworking": "1",
+              "access_network_type": "14", "internet": "1", "asra": "0",
+              "esr": "0", "uesa": "0", "venue_group": "7", "venue_type": "1",
+              "venue_name": ["eng:Example venue", "fin:Esimerkkipaikka"],
+              "roaming_consortium": ["112233", "1020304050", "010203040506",
+              "fedcba"], "domain_name": "example.com,another.example.com",
+              "nai_realm": ["0,example.com,13[5:6],21[2:4][5:7]",
+              "0,another.example.com"], "hs20": "1",
+              "hs20_wan_metrics": "01:8000:1000:80:240:3000",
+              "hs20_conn_capab": ["1:0:2", "6:22:1", "17:5060:0"],
+              "hs20_operating_class": "5173", "anqp_3gpp_cell_net": "244,91",
+              "hs20_t_c_filename": "terms-and-conditions",
+              "hs20_t_c_timestamp": "123456789"}
+
+    hapd = hostapd.add_ap(apdev[0], params)
+
+    class TestDbusInterworking(TestDbus):
+        def __init__(self, bus):
+            TestDbus.__init__(self, bus)
+            self.hs20_t_and_c_seen = False
+
+        def __enter__(self):
+            gobject.timeout_add(1, self.run_connect)
+            gobject.timeout_add(15000, self.timeout)
+            self.add_signal(self.hs20TermsAndConditions, WPAS_DBUS_IFACE,
+                            "HS20TermsAndConditions")
+            self.loop.run()
+            return self
+
+        def hs20TermsAndConditions(self, t_c_url):
+            logger.debug("hs20TermsAndConditions: url=%s" % (t_c_url))
+            url = "https://example.com/t_and_c?addr=%s&ap=123" % dev[0].own_addr()
+            if url in t_c_url:
+                self.hs20_t_and_c_seen = True
+
+        def run_connect(self, *args):
+            dev[0].hs20_enable()
+            dev[0].connect("test-hs20", proto="RSN", key_mgmt="WPA-EAP", eap="TTLS",
+                           identity="hs20-t-c-test", password="password",
+                           ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2",
+                           ieee80211w='2', scan_freq="2412")
+            return False
+
+        def success(self):
+            return self.hs20_t_and_c_seen
+
+    with TestDbusInterworking(bus) as t:
+        if not t.success():
+            raise Exception("Expected signals not seen")
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 8fc29b398..8ef0837f5 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -4304,6 +4304,14 @@  static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
 	  }
 	},
 #endif /* CONFIG_INTERWORKING */
+#ifdef CONFIG_HS20
+	{ "HS20TermsAndConditions", WPAS_DBUS_NEW_IFACE_INTERFACE,
+	  {
+		  {"url", "s", ARG_OUT},
+		  END_ARGS
+	  }
+	},
+#endif /* CONFIG_HS20 */
 	{ NULL, NULL, { END_ARGS } }
 };
 
@@ -5142,3 +5150,42 @@  int wpas_dbus_unregister_persistent_group(struct wpa_supplicant *wpa_s,
 }
 
 #endif /* CONFIG_P2P */
+
+
+#ifdef CONFIG_HS20
+
+/**
+ * wpas_dbus_signal_hs20_t_c_acceptance - Signals a terms and conditions was
+ * received.
+ *
+ * @wpa_s: %wpa_supplicant network interface data
+ * @url: URL of the terms and conditions acceptance page.
+ */
+
+void wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
+					  const char *url)
+{
+	struct wpas_dbus_priv *iface;
+	DBusMessage *msg;
+
+	iface = wpa_s->global->dbus;
+
+	/* Do nothing if the control interface is not turned on */
+	if (!iface || !wpa_s->dbus_new_path)
+		return;
+
+	msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+				      WPAS_DBUS_NEW_IFACE_INTERFACE,
+				      "HS20TermsAndConditions");
+	if (!msg)
+		return;
+
+	if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &url,
+				     DBUS_TYPE_INVALID))
+		dbus_connection_send(iface->con, msg, NULL);
+	else
+		wpa_printf(MSG_ERROR, "dbus: Failed to construct signal");
+	dbus_message_unref(msg);
+}
+
+#endif /* CONFIG_HS20 */
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index 5c5d85506..b653f10f9 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -279,6 +279,8 @@  void wpas_dbus_signal_interworking_ap_added(struct wpa_supplicant *wpa_s,
 					    int bh, int bss_load,
 					    int conn_capab);
 void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s);
+void wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
+					  const char *url);
 
 #else /* CONFIG_CTRL_IFACE_DBUS_NEW */
 
@@ -650,6 +652,12 @@  void wpas_dbus_signal_interworking_select_done(struct wpa_supplicant *wpa_s)
 {
 }
 
+static inline
+void wpas_dbus_signal_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
+					  const char *url)
+{
+}
+
 #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
 
 #endif /* CTRL_IFACE_DBUS_H_NEW */
diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c
index 4a25753a0..6a584651e 100644
--- a/wpa_supplicant/hs20_supplicant.c
+++ b/wpa_supplicant/hs20_supplicant.c
@@ -26,6 +26,7 @@ 
 #include "interworking.h"
 #include "hs20_supplicant.h"
 #include "base64.h"
+#include "notify.h"
 
 
 #define OSU_MAX_ITEMS 10
@@ -1336,7 +1337,7 @@  void hs20_rx_t_c_acceptance(struct wpa_supplicant *wpa_s, const char *url)
 		return;
 	}
 
-	wpa_msg(wpa_s, MSG_INFO, HS20_T_C_ACCEPTANCE "%s", url);
+	wpas_notify_hs20_t_c_acceptance(wpa_s, url);
 }
 
 
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index a74fb621b..4b3a88c2f 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -1026,3 +1026,15 @@  void wpas_notify_signal_change(struct wpa_supplicant *wpa_s)
 {
 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_SIGNAL_CHANGE);
 }
+
+
+#ifdef CONFIG_HS20
+
+void wpas_notify_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
+				     const char *url)
+{
+	wpa_msg(wpa_s, MSG_INFO, HS20_T_C_ACCEPTANCE "%s", url);
+	wpas_dbus_signal_hs20_t_c_acceptance(wpa_s, url);
+}
+
+#endif /* CONFIG_HS20 */
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index efb9efa07..2a0cf097a 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -169,5 +169,7 @@  void wpas_notify_interworking_select_done(struct wpa_supplicant *wpa_s);
 void wpas_notify_pmk_cache_added(struct wpa_supplicant *wpa_s,
 				 struct rsn_pmksa_cache_entry *entry);
 void wpas_notify_signal_change(struct wpa_supplicant *wpa_s);
+void wpas_notify_hs20_t_c_acceptance(struct wpa_supplicant *wpa_s,
+				     const char *url);
 
 #endif /* NOTIFY_H */