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.

PskMismatch ( )

A possible PSK mismatch is identified.

+ +
  • +

    HS20TermsAndConditions ( s : url )

    +

    A terms and conditions page is present. This signal is delivered when the network requires acceptance of the terms and conditions.

    +
    +
    s : url
    +
    URL of the terms and conditions page.
    +
    +
  • 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..00b38edf5 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,39 @@ 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..745234dda 100644 --- a/wpa_supplicant/notify.c +++ b/wpa_supplicant/notify.c @@ -1026,3 +1026,13 @@ 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 */