From 62dc214033492f97c382aaa029da4730a8f04346 Mon Sep 17 00:00:00 2001 From: Andrew Zaborowski Date: Sat, 22 May 2021 18:51:34 +0200 Subject: [PATCH 1/2] iwd: Fix conversion of user certificate path in EAP settings Fix a copy-paste error when converting NMSettingsConnection profiles to IWD network config format. Fixes: 9d22ae7981d7 ('wifi: Add utilities for writing IWD connection profiles') --- src/core/devices/wifi/nm-wifi-utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/devices/wifi/nm-wifi-utils.c b/src/core/devices/wifi/nm-wifi-utils.c index 9250e6dd42..c486d239a5 100644 --- a/src/core/devices/wifi/nm-wifi-utils.c +++ b/src/core/devices/wifi/nm-wifi-utils.c @@ -1057,7 +1057,7 @@ eap_certs_to_iwd_config(GKeyFile * file, : nm_setting_802_1x_get_ca_cert_scheme(s_8021x); NMSetting8021xCKScheme client_cert_scheme = phase2 ? nm_setting_802_1x_get_phase2_client_cert_scheme(s_8021x) - : nm_setting_802_1x_get_ca_cert_scheme(s_8021x); + : nm_setting_802_1x_get_client_cert_scheme(s_8021x); NMSetting8021xCKScheme key_scheme; NMSettingSecretFlags key_password_flags; const char * ca_path = phase2 ? nm_setting_802_1x_get_phase2_ca_path(s_8021x) From b86d83860ebeac9a0e1aecdd5f82526befd63d4e Mon Sep 17 00:00:00 2001 From: Andrew Zaborowski Date: Sat, 22 May 2021 18:46:38 +0200 Subject: [PATCH 2/2] iwd: Add default "auto" value for [main].iwd-config-path Since the [main].iwd-config-path functionality, where NM watches for NMSettingsConnection changes and update IWD network config files with new settings, has proven to work without issues so far, enable it by default. Instead of hardcoding /var/lib/iwd as the value, and since the value can't be probed at NM compile time, query it from IWD's recently- added D-Bus interface for settings when [main].iwd-config-path is either missing or set to the new value "auto". --- man/NetworkManager.conf.xml | 25 ++++--- src/core/devices/wifi/nm-iwd-manager.c | 96 ++++++++++++++++++++++++-- src/core/devices/wifi/nm-iwd-manager.h | 1 + 3 files changed, 106 insertions(+), 16 deletions(-) diff --git a/man/NetworkManager.conf.xml b/man/NetworkManager.conf.xml index d8fce34d6e..1a23498322 100644 --- a/man/NetworkManager.conf.xml +++ b/man/NetworkManager.conf.xml @@ -497,17 +497,24 @@ no-auto-default=* iwd-config-path - If the value points to an existing directory, Network - Manager will attempt to write copies of new or modified - Wi-Fi connection profiles, converted into the IWD - format, into this directory thus making IWD connection - properties editable. This will only happen if the IWD - backend is active meaning that at least one Wi-Fi device - must exist. + If the value is "auto" (the default), IWD is queried for its + current state directory when it appears on D-Bus -- the + directory where IWD keeps its network configuration files -- + usually /var/lib/iwd. NetworkManager will then attempt to + write copies of new or modified Wi-Fi connection profiles, + converted into the IWD format, into this directory thus making + IWD connection properties editable. NM will overwrite existing + files without preserving their contents. - This allows editing connection profile settings such as - the 802.1x configuration using Network Manager clients. + The path can also be overriden by pointing to a specific + existing and writable directory. On the other hand setting + this to an empty string or any other value disables the + profile conversion mechanism. + + + This mechanism allows editing connection profile settings such + as the 802.1x configuration using NetworkManager clients. Without it such changes have no effect in IWD. diff --git a/src/core/devices/wifi/nm-iwd-manager.c b/src/core/devices/wifi/nm-iwd-manager.c index b65022c346..f904ece227 100644 --- a/src/core/devices/wifi/nm-iwd-manager.c +++ b/src/core/devices/wifi/nm-iwd-manager.c @@ -47,6 +47,7 @@ typedef struct { char * agent_path; GHashTable * known_networks; NMDeviceIwd * last_agent_call_device; + char * last_state_dir; } NMIwdManagerPrivate; struct _NMIwdManager { @@ -452,6 +453,21 @@ iwd_config_write(GKeyFile * config, return nm_utils_file_set_contents(filepath, data, length, 0600, times, NULL, error); } +static const char * +get_config_path(NMIwdManager *self) +{ + NMIwdManagerPrivate *priv = NM_IWD_MANAGER_GET_PRIVATE(self); + const char * path = nm_config_data_get_iwd_config_path(NM_CONFIG_GET_DATA); + + if (!path || nm_streq0(path, "auto")) + return priv->last_state_dir; + + if (path[0] != '\0' && g_file_test(path, G_FILE_TEST_IS_DIR)) + return path; + + return NULL; +} + static void sett_conn_changed(NMSettingsConnection * sett_conn, guint update_reason, @@ -487,8 +503,8 @@ sett_conn_changed(NMSettingsConnection * sett_conn, if (NM_FLAGS_HAS(flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)) return; - iwd_dir = nm_config_data_get_iwd_config_path(NM_CONFIG_GET_DATA); - if (!iwd_dir || iwd_dir[0] == '\0' || !g_file_test(iwd_dir, G_FILE_TEST_IS_DIR)) { + iwd_dir = get_config_path(nm_iwd_manager_get()); + if (!iwd_dir) { gboolean nm_autoconnectable = nm_setting_connection_get_autoconnect(s_conn); gboolean iwd_autoconnectable = get_property_bool(data->known_network, "AutoConnect", TRUE); @@ -1119,8 +1135,8 @@ try_delete_file: if (mirror_connection(self, &id, FALSE, NULL)) return; - iwd_dir = nm_config_data_get_iwd_config_path(NM_CONFIG_GET_DATA); - if (!iwd_dir || iwd_dir[0] == '\0' || !g_file_test(iwd_dir, G_FILE_TEST_IS_DIR)) + iwd_dir = get_config_path(self); + if (!iwd_dir) return; filename = nm_wifi_utils_get_iwd_config_filename(id.name, ssid_len, id.security); @@ -1147,8 +1163,8 @@ connection_added(NMSettings *settings, NMSettingsConnection *sett_conn, gpointer if (!nm_streq(nm_settings_connection_get_connection_type(sett_conn), "802-11-wireless")) return; - iwd_dir = nm_config_data_get_iwd_config_path(NM_CONFIG_GET_DATA); - if (!iwd_dir || iwd_dir[0] == '\0' || !g_file_test(iwd_dir, G_FILE_TEST_IS_DIR)) + iwd_dir = get_config_path(self); + if (!iwd_dir) return; /* If this is a generated connection it may be ourselves creating it and @@ -1392,6 +1408,56 @@ object_compare_interfaces(gconstpointer a, gconstpointer b) return rank_a - rank_b; } +static void +get_daemon_info_cb(GObject *source, GAsyncResult *res, gpointer user_data) +{ + NMIwdManager * self = user_data; + NMIwdManagerPrivate *priv; + gs_unref_variant GVariant *properties = NULL; + gs_free_error GError *error = NULL; + GVariantIter * properties_iter; + const char * key; + GVariant * value; + + properties = g_dbus_proxy_call_finish(G_DBUS_PROXY(source), res, &error); + if (!properties) { + if (nm_utils_error_is_cancelled(error)) + return; + + nm_log_warn(LOGD_WIFI, "iwd: Daemon.GetInfo() failed: %s", error->message); + return; + } + + priv = NM_IWD_MANAGER_GET_PRIVATE(self); + + if (!g_variant_is_of_type(properties, G_VARIANT_TYPE("(a{sv})"))) { + _LOGE("Daemon.GetInfo returned type %s instead of (a{sv})", + g_variant_get_type_string(properties)); + return; + } + + g_variant_get(properties, "(a{sv})", &properties_iter); + + while (g_variant_iter_next(properties_iter, "{&sv}", &key, &value)) { + if (nm_streq(key, "StateDirectory")) { + if (!g_variant_is_of_type(value, G_VARIANT_TYPE_STRING)) { + _LOGE("Daemon.GetInfo property %s is typed '%s' instead of 's'", + key, + g_variant_get_type_string(value)); + goto next; + } + + nm_clear_g_free(&priv->last_state_dir); + priv->last_state_dir = g_variant_dup_string(value, NULL); + } + +next: + g_variant_unref(value); + } + + g_variant_iter_free(properties_iter); +} + static void got_object_manager(GObject *object, GAsyncResult *result, gpointer user_data) { @@ -1429,7 +1495,8 @@ got_object_manager(GObject *object, GAsyncResult *result, gpointer user_data) } if (_om_has_name_owner(object_manager)) { - GList *objects, *iter; + GList * objects, *iter; + gs_unref_object GDBusInterface *daemon = NULL; priv->running = true; @@ -1455,6 +1522,19 @@ got_object_manager(GObject *object, GAsyncResult *result, gpointer user_data) if (priv->agent_id) register_agent(self); + + daemon = g_dbus_object_manager_get_interface(object_manager, + "/net/connman/iwd", /* IWD 1.15+ */ + NM_IWD_DAEMON_INTERFACE); + if (daemon) + g_dbus_proxy_call(G_DBUS_PROXY(daemon), + "GetInfo", + g_variant_new("()"), + G_DBUS_CALL_FLAGS_NONE, + -1, + priv->cancellable, + get_daemon_info_cb, + self); } } @@ -1615,6 +1695,8 @@ dispose(GObject *object) priv->last_agent_call_device = NULL; + nm_clear_g_free(&priv->last_state_dir); + G_OBJECT_CLASS(nm_iwd_manager_parent_class)->dispose(object); } diff --git a/src/core/devices/wifi/nm-iwd-manager.h b/src/core/devices/wifi/nm-iwd-manager.h index 466f67c766..e794e66127 100644 --- a/src/core/devices/wifi/nm-iwd-manager.h +++ b/src/core/devices/wifi/nm-iwd-manager.h @@ -13,6 +13,7 @@ #define NM_IWD_BUS_TYPE G_BUS_TYPE_SYSTEM #define NM_IWD_SERVICE "net.connman.iwd" +#define NM_IWD_DAEMON_INTERFACE "net.connman.iwd.Daemon" #define NM_IWD_AGENT_MANAGER_INTERFACE "net.connman.iwd.AgentManager" #define NM_IWD_WIPHY_INTERFACE "net.connman.iwd.Adapter" #define NM_IWD_DEVICE_INTERFACE "net.connman.iwd.Device"