summary refs log tree commit diff
path: root/src/settings/nm-settings-connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/settings/nm-settings-connection.c')
-rw-r--r--src/settings/nm-settings-connection.c208
1 files changed, 26 insertions, 182 deletions
diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c
index 6f47e14d..8d1f9583 100644
--- a/src/settings/nm-settings-connection.c
+++ b/src/settings/nm-settings-connection.c
@@ -23,8 +23,6 @@
 
 #include "nm-settings-connection.h"
 
-#include <string.h>
-
 #include "c-list/src/c-list.h"
 
 #include "nm-common-macros.h"
@@ -208,141 +206,6 @@ nm_settings_connection_get_last_secret_agent_version_id (NMSettingsConnection *s
 
 /*****************************************************************************/
 
-/* Return TRUE to keep, FALSE to drop */
-typedef gboolean (*ForEachSecretFunc) (NMSettingSecretFlags flags,
-                                       gpointer user_data);
-
-/* Returns always a non-NULL, non-floating variant that must
- * be unrefed by the caller. */
-static GVariant *
-for_each_secret (NMConnection *self,
-                 GVariant *secrets,
-                 gboolean remove_non_secrets,
-                 ForEachSecretFunc callback,
-                 gpointer callback_data)
-{
-	GVariantBuilder secrets_builder, setting_builder;
-	GVariantIter secrets_iter, *setting_iter;
-	const char *setting_name;
-
-	/* This function, given a dict of dicts representing new secrets of
-	 * an NMConnection, walks through each toplevel dict (which represents a
-	 * NMSetting), and for each setting, walks through that setting dict's
-	 * properties.  For each property that's a secret, it will check that
-	 * secret's flags in the backing NMConnection object, and call a supplied
-	 * callback.
-	 *
-	 * The one complexity is that the VPN setting's 'secrets' property is
-	 * *also* a dict (since the key/value pairs are arbitrary and known
-	 * only to the VPN plugin itself).  That means we have three levels of
-	 * dicts that we potentially have to traverse here.  When we hit the
-	 * VPN setting's 'secrets' property, we special-case that and iterate over
-	 * each item in that 'secrets' dict, calling the supplied callback
-	 * each time.
-	 */
-
-	g_return_val_if_fail (callback, NULL);
-
-	g_variant_iter_init (&secrets_iter, secrets);
-	g_variant_builder_init (&secrets_builder, NM_VARIANT_TYPE_CONNECTION);
-	while (g_variant_iter_next (&secrets_iter, "{&sa{sv}}", &setting_name, &setting_iter)) {
-		NMSetting *setting;
-		const char *secret_name;
-		GVariant *val;
-
-		setting = nm_connection_get_setting_by_name (self, setting_name);
-		if (setting == NULL) {
-			g_variant_iter_free (setting_iter);
-			continue;
-		}
-
-		g_variant_builder_init (&setting_builder, NM_VARIANT_TYPE_SETTING);
-		while (g_variant_iter_next (setting_iter, "{&sv}", &secret_name, &val)) {
-			NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
-
-			/* VPN secrets need slightly different treatment here since the
-			 * "secrets" property is actually a hash table of secrets.
-			 */
-			if (NM_IS_SETTING_VPN (setting) && !g_strcmp0 (secret_name, NM_SETTING_VPN_SECRETS)) {
-				GVariantBuilder vpn_secrets_builder;
-				GVariantIter vpn_secrets_iter;
-				const char *vpn_secret_name, *secret;
-
-				/* Iterate through each secret from the VPN dict in the overall secrets dict */
-				g_variant_builder_init (&vpn_secrets_builder, G_VARIANT_TYPE ("a{ss}"));
-				g_variant_iter_init (&vpn_secrets_iter, val);
-				while (g_variant_iter_next (&vpn_secrets_iter, "{&s&s}", &vpn_secret_name, &secret)) {
-					if (!nm_setting_get_secret_flags (setting, vpn_secret_name, &secret_flags, NULL)) {
-						if (!remove_non_secrets)
-							g_variant_builder_add (&vpn_secrets_builder, "{ss}", vpn_secret_name, secret);
-						continue;
-					}
-
-					if (callback (secret_flags, callback_data))
-						g_variant_builder_add (&vpn_secrets_builder, "{ss}", vpn_secret_name, secret);
-				}
-
-				g_variant_builder_add (&setting_builder, "{sv}",
-				                       secret_name, g_variant_builder_end (&vpn_secrets_builder));
-			} else {
-				if (!nm_setting_get_secret_flags (setting, secret_name, &secret_flags, NULL)) {
-					if (!remove_non_secrets)
-						g_variant_builder_add (&setting_builder, "{sv}", secret_name, val);
-					continue;
-				}
-				if (callback (secret_flags, callback_data))
-					g_variant_builder_add (&setting_builder, "{sv}", secret_name, val);
-			}
-			g_variant_unref (val);
-		}
-
-		g_variant_iter_free (setting_iter);
-		g_variant_builder_add (&secrets_builder, "{sa{sv}}", setting_name, &setting_builder);
-	}
-
-	return g_variant_ref_sink (g_variant_builder_end (&secrets_builder));
-}
-
-typedef gboolean (*FindSecretFunc) (NMSettingSecretFlags flags,
-                                    gpointer user_data);
-
-typedef struct {
-	FindSecretFunc find_func;
-	gpointer find_func_data;
-	gboolean found;
-} FindSecretData;
-
-static gboolean
-find_secret_for_each_func (NMSettingSecretFlags flags,
-                           gpointer user_data)
-{
-	FindSecretData *data = user_data;
-
-	if (!data->found)
-		data->found = data->find_func (flags, data->find_func_data);
-	return FALSE;
-}
-
-static gboolean
-find_secret (NMConnection *self,
-             GVariant *secrets,
-             FindSecretFunc callback,
-             gpointer callback_data)
-{
-	FindSecretData data;
-	GVariant *dummy;
-
-	data.find_func = callback;
-	data.find_func_data = callback_data;
-	data.found = FALSE;
-
-	dummy = for_each_secret (self, secrets, FALSE, find_secret_for_each_func, &data);
-	g_variant_unref (dummy);
-	return data.found;
-}
-
-/*****************************************************************************/
-
 static void
 set_visible (NMSettingsConnection *self, gboolean new_visible)
 {
@@ -790,7 +653,7 @@ out:
 		else if (new_connection)
 			_LOGI ("write: successfully updated (%s)", logmsg_change);
 		else
-			_LOGI ("write: successfully commited (%s)", logmsg_change);
+			_LOGI ("write: successfully committed (%s)", logmsg_change);
 	}
 	return TRUE;
 }
@@ -938,8 +801,8 @@ typedef struct {
 } ForEachSecretFlags;
 
 static gboolean
-validate_secret_flags (NMSettingSecretFlags flags,
-                       gpointer user_data)
+validate_secret_flags_cb (NMSettingSecretFlags flags,
+                          gpointer user_data)
 {
 	ForEachSecretFlags *cmp_flags = user_data;
 
@@ -950,6 +813,18 @@ validate_secret_flags (NMSettingSecretFlags flags,
 	return TRUE;
 }
 
+static GVariant *
+validate_secret_flags (NMConnection *connection,
+                       GVariant *secrets,
+                       ForEachSecretFlags *cmp_flags)
+{
+	return g_variant_ref_sink (_nm_connection_for_each_secret (connection,
+	                                                           secrets,
+	                                                           TRUE,
+	                                                           validate_secret_flags_cb,
+	                                                           cmp_flags));
+}
+
 static gboolean
 secret_is_system_owned (NMSettingSecretFlags flags,
                         gpointer user_data)
@@ -992,7 +867,7 @@ get_cmp_flags (NMSettingsConnection *self, /* only needed for logging */
 		 * save those system-owned secrets.  If not, discard them and use the
 		 * existing secrets, or fail the connection.
 		 */
-		*agent_had_system = find_secret (connection, secrets, secret_is_system_owned, NULL);
+		*agent_had_system = _nm_connection_find_secret (connection, secrets, secret_is_system_owned, NULL);
 		if (*agent_had_system) {
 			if (flags == NM_SECRET_AGENT_GET_SECRETS_FLAG_NONE) {
 				/* No user interaction was allowed when requesting secrets; the
@@ -1151,14 +1026,14 @@ get_secrets_done_cb (NMAgentManager *manager,
 	/* Update the connection with our existing secrets from backing storage */
 	nm_connection_clear_secrets (nm_settings_connection_get_connection (self));
 	if (!dict || nm_connection_update_secrets (nm_settings_connection_get_connection (self), setting_name, dict, &local)) {
-		GVariant *filtered_secrets;
+		gs_unref_variant GVariant *filtered_secrets = NULL;
 
 		/* Update the connection with the agent's secrets; by this point if any
 		 * system-owned secrets exist in 'secrets' the agent that provided them
 		 * will have been authenticated, so those secrets can replace the existing
 		 * system secrets.
 		 */
-		filtered_secrets = for_each_secret (nm_settings_connection_get_connection (self), secrets, TRUE, validate_secret_flags, &cmp_flags);
+		filtered_secrets = validate_secret_flags (nm_settings_connection_get_connection (self), secrets, &cmp_flags);
 		if (nm_connection_update_secrets (nm_settings_connection_get_connection (self), setting_name, filtered_secrets, &local)) {
 			/* Now that all secrets are updated, copy and cache new secrets,
 			 * then save them to backing storage.
@@ -1194,7 +1069,6 @@ get_secrets_done_cb (NMAgentManager *manager,
 			       call_id,
 			       local->message);
 		}
-		g_variant_unref (filtered_secrets);
 	} else {
 		_LOGD ("(%s:%p) failed to update with existing secrets: %s",
 		       setting_name,
@@ -1218,11 +1092,10 @@ get_secrets_done_cb (NMAgentManager *manager,
 		nm_connection_clear_secrets (applied_connection);
 
 		if (!dict || nm_connection_update_secrets (applied_connection, setting_name, dict, NULL)) {
-			GVariant *filtered_secrets;
+			gs_unref_variant GVariant *filtered_secrets = NULL;
 
-			filtered_secrets = for_each_secret (applied_connection, secrets, TRUE, validate_secret_flags, &cmp_flags);
+			filtered_secrets = validate_secret_flags (applied_connection, secrets, &cmp_flags);
 			nm_connection_update_secrets (applied_connection, setting_name, filtered_secrets, NULL);
-			g_variant_unref (filtered_secrets);
 		}
 	}
 
@@ -1338,7 +1211,7 @@ nm_settings_connection_get_secrets (NMSettingsConnection *self,
 	/* we remember the current version-id of the secret-agents. The version-id is strictly increasing,
 	 * as new agents register the number. We know hence, that this request was made against a certain
 	 * set of secret-agents.
-	 * If after making this request a new secret-agent registeres, the version-id increases.
+	 * If after making this request a new secret-agent registers, the version-id increases.
 	 * Then we know that the this request probably did not yet include the latest secret-agent. */
 	priv->last_secret_agent_version_id = nm_agent_manager_get_agent_version_id (priv->agent_mgr);
 
@@ -1660,38 +1533,6 @@ typedef struct {
 } UpdateInfo;
 
 static void
-has_some_secrets_cb (NMSetting *setting,
-                     const char *key,
-                     const GValue *value,
-                     GParamFlags flags,
-                     gpointer user_data)
-{
-	GParamSpec *pspec;
-
-	if (NM_IS_SETTING_VPN (setting)) {
-		if (nm_setting_vpn_get_num_secrets (NM_SETTING_VPN(setting)))
-			*((gboolean *) user_data) = TRUE;
-		return;
-	}
-
-	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 *self)
-{
-	gboolean has_secrets = FALSE;
-
-	nm_connection_for_each_setting_value (self, 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);
@@ -1758,7 +1599,7 @@ update_auth_cb (NMSettingsConnection *self,
 	}
 
 	if (info->new_settings) {
-		if (!any_secrets_present (info->new_settings)) {
+		if (!_nm_connection_aggregate (info->new_settings, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)) {
 			/* 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.
@@ -1910,6 +1751,9 @@ settings_connection_update (NMSettingsConnection *self,
 			                                           &error);
 			if (!tmp)
 				goto error;
+
+			if (!nm_connection_verify_secrets (tmp, &error))
+				goto error;
 		}
 	}
 
@@ -2809,7 +2653,7 @@ _autoconnect_retries_set (NMSettingsConnection *self,
 		/* NOTE: the blocked time must be identical for all connections, otherwise
 		 * the tracking of resetting the retry count in NMPolicy needs adjustment
 		 * in _connection_autoconnect_retries_set() (as it would need to re-evaluate
-		 * the next-timeout everytime a connection gets blocked). */
+		 * the next-timeout every time a connection gets blocked). */
 		priv->autoconnect_retries_blocked_until = nm_utils_get_monotonic_timestamp_s () + AUTOCONNECT_RESET_RETRIES_TIMER;
 	}
 }