From 54a5f4513b5d137c299c21e37f27245eae7d5c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Klime=C5=A1?= Date: Thu, 11 Sep 2014 09:09:12 +0200 Subject: settings: do not clear secrets on Update() without any secrets (bgo #728920) When a connection is updated by Update() and the new settings contain *no* secrets, leave the previous secrets untouched. This makes updating connection parameters much easier. Users (clients) need not to bother with secrets when they only want adjust a parameter. Use case: - GetSettings() - modify the settings - Update() E.g. nmcli con mod my-wifi connection.zone home https://bugzilla.gnome.org/show_bug.cgi?id=728920 --- src/settings/nm-settings-connection.c | 70 +++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 7 deletions(-) diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index 9fa2801dd3..c0e6794a85 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -15,8 +15,8 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * (C) Copyright 2008 Novell, Inc. - * (C) Copyright 2008 - 2013 Red Hat, Inc. + * Copyright 2008 Novell, Inc. + * Copyright 2008 - 2014 Red Hat, Inc. */ #include "config.h" @@ -1208,6 +1208,54 @@ typedef struct { gboolean save_to_disk; } UpdateInfo; +static void +has_some_secrets_cb (NMSetting *setting, + const char *key, + const GValue *value, + GParamFlags flags, + gpointer user_data) +{ + GParamSpec *pspec; + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (G_OBJECT (setting)), key); + if (pspec) { + if ( (flags & NM_SETTING_PARAM_SECRET) + && !g_param_value_defaults (pspec, (GValue *)value)) + *((gboolean *) user_data) = TRUE; + } +} + +static gboolean +any_secrets_present (NMConnection *connection) +{ + gboolean has_secrets = FALSE; + + nm_connection_for_each_setting_value (connection, has_some_secrets_cb, &has_secrets); + return has_secrets; +} + +static void +cached_secrets_to_connection (NMSettingsConnection *self, NMConnection *connection) +{ + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); + GVariant *secrets_dict; + + if (priv->agent_secrets) { + secrets_dict = nm_connection_to_dbus (priv->agent_secrets, NM_CONNECTION_SERIALIZE_ONLY_SECRETS); + if (secrets_dict) { + (void) nm_connection_update_secrets (connection, NULL, secrets_dict, NULL); + g_variant_unref (secrets_dict); + } + } + if (priv->system_secrets) { + secrets_dict = nm_connection_to_dbus (priv->system_secrets, NM_CONNECTION_SERIALIZE_ONLY_SECRETS); + if (secrets_dict) { + (void) nm_connection_update_secrets (connection, NULL, secrets_dict, NULL); + g_variant_unref (secrets_dict); + } + } +} + static void update_complete (NMSettingsConnection *self, UpdateInfo *info, @@ -1264,11 +1312,19 @@ update_auth_cb (NMSettingsConnection *self, return; } - /* Cache the new secrets from the agent, as stuff like inotify-triggered - * changes to connection's backing config files will blow them away if - * they're in the main connection. - */ - update_agent_secrets_cache (self, info->new_settings); + if (!any_secrets_present (info->new_settings)) { + /* If the new connection has no secrets, we do not want to remove all + * secrets, rather we keep all the existing ones. Do that by merging + * them in to the new connection. + */ + cached_secrets_to_connection (self, info->new_settings); + } else { + /* Cache the new secrets from the agent, as stuff like inotify-triggered + * changes to connection's backing config files will blow them away if + * they're in the main connection. + */ + update_agent_secrets_cache (self, info->new_settings); + } if (info->save_to_disk) { nm_settings_connection_replace_and_commit (self, -- cgit v1.2.1 From 502eb2daf9f3e390547aac38c42b24ea1ae75df7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Klime=C5=A1?= Date: Thu, 11 Sep 2014 10:07:47 +0200 Subject: core: add ClearSecrets() D-Bus call It clears all secrets in a connection. --- introspection/nm-settings-connection.xml | 8 ++++ src/settings/nm-settings-connection.c | 76 +++++++++++++++++++++++++++++--- 2 files changed, 78 insertions(+), 6 deletions(-) diff --git a/introspection/nm-settings-connection.xml b/introspection/nm-settings-connection.xml index b5bd2cd0e0..b02762d6be 100644 --- a/introspection/nm-settings-connection.xml +++ b/introspection/nm-settings-connection.xml @@ -93,6 +93,14 @@ + + + Clear the secrets belonging to this network connection profile. + + + + + Saves a "dirty" connection (that had previously been diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c index c0e6794a85..6b0d38c738 100644 --- a/src/settings/nm-settings-connection.c +++ b/src/settings/nm-settings-connection.c @@ -66,6 +66,9 @@ static void impl_settings_connection_get_secrets (NMSettingsConnection *connecti const gchar *setting_name, DBusGMethodInvocation *context); +static void impl_settings_connection_clear_secrets (NMSettingsConnection *connection, + DBusGMethodInvocation *context); + #include "nm-settings-connection-glue.h" static void nm_settings_connection_connection_interface_init (NMConnectionInterface *iface); @@ -1577,11 +1580,11 @@ dbus_get_agent_secrets_cb (NMSettingsConnection *self, } static void -dbus_secrets_auth_cb (NMSettingsConnection *self, - DBusGMethodInvocation *context, - NMAuthSubject *subject, - GError *error, - gpointer user_data) +dbus_get_secrets_auth_cb (NMSettingsConnection *self, + DBusGMethodInvocation *context, + NMAuthSubject *subject, + GError *error, + gpointer user_data) { NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); char *setting_name = user_data; @@ -1625,7 +1628,7 @@ impl_settings_connection_get_secrets (NMSettingsConnection *self, context, subject, get_modify_permission_basic (self), - dbus_secrets_auth_cb, + dbus_get_secrets_auth_cb, g_strdup (setting_name)); g_object_unref (subject); } else { @@ -1634,6 +1637,67 @@ impl_settings_connection_get_secrets (NMSettingsConnection *self, } } +static void +clear_secrets_cb (NMSettingsConnection *self, + GError *error, + gpointer user_data) +{ + DBusGMethodInvocation *context = (DBusGMethodInvocation *) user_data; + + if (error) + dbus_g_method_return_error (context, error); + else + dbus_g_method_return (context); +} + +static void +dbus_clear_secrets_auth_cb (NMSettingsConnection *self, + DBusGMethodInvocation *context, + NMAuthSubject *subject, + GError *error, + gpointer user_data) +{ + NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self); + + if (error) + dbus_g_method_return_error (context, error); + else { + /* Clear secrets in connection and caches */ + nm_connection_clear_secrets (NM_CONNECTION (self)); + if (priv->system_secrets) + nm_connection_clear_secrets (priv->system_secrets); + if (priv->agent_secrets) + nm_connection_clear_secrets (priv->agent_secrets); + + /* Tell agents to remove secrets for this connection */ + nm_agent_manager_delete_secrets (priv->agent_mgr, NM_CONNECTION (self)); + + nm_settings_connection_commit_changes (self, clear_secrets_cb, context); + } +} + +static void +impl_settings_connection_clear_secrets (NMSettingsConnection *self, + DBusGMethodInvocation *context) +{ + NMAuthSubject *subject; + GError *error = NULL; + + subject = _new_auth_subject (context, &error); + if (subject) { + auth_start (self, + context, + subject, + get_modify_permission_basic (self), + dbus_clear_secrets_auth_cb, + NULL); + g_object_unref (subject); + } else { + dbus_g_method_return_error (context, error); + g_error_free (error); + } +} + /**************************************************************/ void -- cgit v1.2.1