[PATCH] Add a default-secret-flags property to NMSettingVPN



This adds a default-secret-flags property, as previously suggested on
the mailing list. Shortly, the rationale is as follows: The OpenConnect
plugin does not know in advance what and how many secrets it will be
storing, this information is available only to the auth-dialog, which
can not modify the VPN data map. Thus, all secrets that need to be saved
by the auth-dialog, will be saved in plain text. Saving the password to
encrypted user storage is only possible by directly interfacing with the
storage backend, like the OpenConnect GNOME auth dialog does with
GNOME-keyring, or hacking a special case for some specific OpenConnect
server configuration. By using this new property, OpenConnect (and
possibly other VPN plugins with similar requirements) could use
NetworkManager's existing facilities for secret storage.
>From 417cc0418c38f46c7bbb5a441bc80aa9e0019adf Mon Sep 17 00:00:00 2001
From: Ilia Kats <ilia-kats gmx net>
Date: Sat, 2 Feb 2013 22:21:12 +0100
Subject: [PATCH] Add a default-secret-flags property to NMSettingVPN

The new property indicates the default secret flag to be applied
to new secrets passed from the secret agent, e.g. enabling
secret agents to store OpenConnect passwords.
---
 libnm-util/libnm-util.ver             |    1 +
 libnm-util/nm-setting-vpn.c           |   45 ++++++++++++++++++++++-
 libnm-util/nm-setting-vpn.h           |   65 +++++++++++++++++----------------
 src/settings/nm-settings-connection.c |   27 +++++++-------
 src/settings/plugins/keyfile/reader.c |    4 +-
 src/settings/plugins/keyfile/writer.c |   10 +++--
 6 files changed, 100 insertions(+), 52 deletions(-)

diff --git a/libnm-util/libnm-util.ver b/libnm-util/libnm-util.ver
index e40531e..5e3e287 100644
--- a/libnm-util/libnm-util.ver
+++ b/libnm-util/libnm-util.ver
@@ -430,6 +430,7 @@ global:
 	nm_setting_vpn_foreach_data_item;
 	nm_setting_vpn_foreach_secret;
 	nm_setting_vpn_get_data_item;
+	nm_setting_vpn_get_default_secret_flags;
 	nm_setting_vpn_get_num_data_items;
 	nm_setting_vpn_get_num_secrets;
 	nm_setting_vpn_get_secret;
diff --git a/libnm-util/nm-setting-vpn.c b/libnm-util/nm-setting-vpn.c
index 0acd9a5..35d31dd 100644
--- a/libnm-util/nm-setting-vpn.c
+++ b/libnm-util/nm-setting-vpn.c
@@ -99,6 +99,12 @@ typedef struct {
 	 * freed with g_free().  Should contain secrets only.
 	 */
 	GHashTable *secrets;
+
+	/* Default secret flags to be applied to new secrets
+	 * that are passed by the secret agent and do not have
+	 * the corresponding flags property in the data map.
+	 */
+	NMSettingSecretFlags default_secret_flags;
 } NMSettingVPNPrivate;
 
 enum {
@@ -107,6 +113,7 @@ enum {
 	PROP_USER_NAME,
 	PROP_DATA,
 	PROP_SECRETS,
+	PROP_DEFAULT_SECRET_FLAGS,
 
 	LAST_PROP
 };
@@ -376,6 +383,19 @@ nm_setting_vpn_foreach_secret (NMSettingVPN *setting,
 	foreach_item_helper (NM_SETTING_VPN_GET_PRIVATE (setting)->secrets, func, user_data);
 }
 
+/**
+ * nm_setting_vpn_get_default_secret_flags:
+ * @setting: the #NMSettingVPN
+ *
+ * Returns the default secret flags
+ **/
+NMSettingSecretFlags
+nm_setting_vpn_get_default_secret_flags (NMSettingVPN *setting)
+{
+	g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NM_SETTING_SECRET_FLAG_NONE);
+	return NM_SETTING_VPN_GET_PRIVATE (setting)->default_secret_flags;
+}
+
 static gboolean
 verify (NMSetting *setting, GSList *all_settings, GError **error)
 {
@@ -641,7 +661,7 @@ clear_secrets_with_flags (NMSetting *setting,
 	/* Iterate through secrets hash and check each entry */
 	g_hash_table_iter_init (&iter, priv->secrets);
 	while (g_hash_table_iter_next (&iter, (gpointer) &secret, NULL)) {
-		NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE;
+		NMSettingSecretFlags flags = priv->default_secret_flags;
 
 		nm_setting_get_secret_flags (setting, secret, &flags, NULL);
 		if (func (setting, pspec->name, flags, user_data) == TRUE)
@@ -720,6 +740,9 @@ set_property (GObject *object, guint prop_id,
 		if (new_hash)
 			g_hash_table_foreach (new_hash, copy_hash, priv->secrets);
 		break;
+	case PROP_DEFAULT_SECRET_FLAGS:
+		priv->default_secret_flags = g_value_get_uint(value);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -746,6 +769,9 @@ get_property (GObject *object, guint prop_id,
 	case PROP_SECRETS:
 		g_value_set_boxed (value, priv->secrets);
 		break;
+	case PROP_DEFAULT_SECRET_FLAGS:
+		g_value_set_uint (value, priv->default_secret_flags);
+		break;
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
@@ -848,5 +874,22 @@ nm_setting_vpn_class_init (NMSettingVPNClass *setting_class)
 							   "  Both keys and values must be strings.",
 							   DBUS_TYPE_G_MAP_OF_STRING,
 							   G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE | NM_SETTING_PARAM_SECRET));
+
+	/**
+	 * NMSettingVPN:default-secret-flags:
+	 *
+	 * Default secret flags to apply to new secrets passed by a secret agent that
+	 * were not in the secrets map and do not have a flag set.
+	 **/
+	g_object_class_install_property (object_class, PROP_DEFAULT_SECRET_FLAGS,
+									 g_param_spec_uint (NM_SETTING_VPN_DEFAULT_SECRET_FLAGS,
+														"Default secret flags",
+							 "Default secret flags to apply to new secrets passed by a "
+							 "secret agent that were not in the secrets map and do not "
+							 "have a flag set.",
+							 NM_SETTING_SECRET_FLAG_NONE,
+							 NM_SETTING_SECRET_FLAGS_ALL,
+							 NM_SETTING_SECRET_FLAG_NONE,
+							 G_PARAM_READWRITE | NM_SETTING_PARAM_SERIALIZE));
 }
 
diff --git a/libnm-util/nm-setting-vpn.h b/libnm-util/nm-setting-vpn.h
index dfd9810..466fda4 100644
--- a/libnm-util/nm-setting-vpn.h
+++ b/libnm-util/nm-setting-vpn.h
@@ -55,10 +55,11 @@ typedef enum {
 #define NM_SETTING_VPN_ERROR nm_setting_vpn_error_quark ()
 GQuark nm_setting_vpn_error_quark (void);
 
-#define NM_SETTING_VPN_SERVICE_TYPE "service-type"
-#define NM_SETTING_VPN_USER_NAME    "user-name"
-#define NM_SETTING_VPN_DATA         "data"
-#define NM_SETTING_VPN_SECRETS      "secrets"
+#define NM_SETTING_VPN_SERVICE_TYPE         "service-type"
+#define NM_SETTING_VPN_USER_NAME            "user-name"
+#define NM_SETTING_VPN_DATA                 "data"
+#define NM_SETTING_VPN_SECRETS              "secrets"
+#define NM_SETTING_VPN_DEFAULT_SECRET_FLAGS "default-secret-flags"
 
 typedef struct {
 	NMSetting parent;
@@ -85,34 +86,34 @@ typedef void (*NMVPNIterFunc) (const char *key, const char *value, gpointer user
 
 GType nm_setting_vpn_get_type (void);
 
-NMSetting        *nm_setting_vpn_new               (void);
-const char       *nm_setting_vpn_get_service_type  (NMSettingVPN *setting);
-const char       *nm_setting_vpn_get_user_name     (NMSettingVPN *setting);
-
-guint32           nm_setting_vpn_get_num_data_items (NMSettingVPN *setting);
-void              nm_setting_vpn_add_data_item     (NMSettingVPN *setting,
-                                                    const char *key,
-                                                    const char *item);
-const char *      nm_setting_vpn_get_data_item     (NMSettingVPN *setting,
-                                                    const char *key);
-void              nm_setting_vpn_remove_data_item  (NMSettingVPN *setting,
-                                                    const char *key);
-void              nm_setting_vpn_foreach_data_item (NMSettingVPN *setting,
-                                                    NMVPNIterFunc func,
-                                                    gpointer user_data);
-
-guint32           nm_setting_vpn_get_num_secrets   (NMSettingVPN *setting);
-void              nm_setting_vpn_add_secret        (NMSettingVPN *setting,
-                                                    const char *key,
-                                                    const char *secret);
-const char *      nm_setting_vpn_get_secret        (NMSettingVPN *setting,
-                                                    const char *key);
-void              nm_setting_vpn_remove_secret     (NMSettingVPN *setting,
-                                                    const char *key);
-void              nm_setting_vpn_foreach_secret    (NMSettingVPN *setting,
-                                                    NMVPNIterFunc func,
-                                                    gpointer user_data);
-
+NMSetting           *nm_setting_vpn_new               (void);
+const char          *nm_setting_vpn_get_service_type  (NMSettingVPN *setting);
+const char          *nm_setting_vpn_get_user_name     (NMSettingVPN *setting);
+
+guint32              nm_setting_vpn_get_num_data_items (NMSettingVPN *setting);
+void                 nm_setting_vpn_add_data_item     (NMSettingVPN *setting,
+                                                       const char *key,
+                                                       const char *item);
+const char *         nm_setting_vpn_get_data_item     (NMSettingVPN *setting,
+                                                       const char *key);
+void                 nm_setting_vpn_remove_data_item  (NMSettingVPN *setting,
+                                                       const char *key);
+void                 nm_setting_vpn_foreach_data_item (NMSettingVPN *setting,
+                                                       NMVPNIterFunc func,
+                                                       gpointer user_data);
+
+guint32              nm_setting_vpn_get_num_secrets   (NMSettingVPN *setting);
+void                 nm_setting_vpn_add_secret        (NMSettingVPN *setting,
+                                                       const char *key,
+                                                       const char *secret);
+const char *         nm_setting_vpn_get_secret        (NMSettingVPN *setting,
+                                                      const char *key);
+void                 nm_setting_vpn_remove_secret     (NMSettingVPN *setting,
+                                                       const char *key);
+void                 nm_setting_vpn_foreach_secret    (NMSettingVPN *setting,
+                                                       NMVPNIterFunc func,
+                                                       gpointer user_data);
+NMSettingSecretFlags nm_setting_vpn_get_default_secret_flags (NMSettingVPN *setting);
 G_END_DECLS
 
 #endif /* NM_SETTING_VPN_H */
diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c
index f0cfc3f..df262cc 100644
--- a/src/settings/nm-settings-connection.c
+++ b/src/settings/nm-settings-connection.c
@@ -171,11 +171,12 @@ for_each_secret (NMConnection *connection,
 			 */
 			if (NM_IS_SETTING_VPN (setting) && (g_strcmp0 (secret_name, NM_SETTING_VPN_SECRETS) == 0)) {
 				GHashTableIter vpn_secrets_iter;
-
+				NMSettingSecretFlags default_secret_flags = nm_setting_vpn_get_default_secret_flags((NMSettingVPN*)setting);
 				/* Iterate through each secret from the VPN hash in the overall secrets hash */
 				g_hash_table_iter_init (&vpn_secrets_iter, g_value_get_boxed (val));
+
 				while (g_hash_table_iter_next (&vpn_secrets_iter, (gpointer) &secret_name, NULL)) {
-					secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+					secret_flags = default_secret_flags;
 					nm_setting_get_secret_flags (setting, secret_name, &secret_flags, NULL);
 					if (callback (&vpn_secrets_iter, secret_flags, callback_data) == FALSE)
 						return;
@@ -742,7 +743,7 @@ agent_secrets_done_cb (NMAgentManager *manager,
 		 * system secrets.
 		 */
 		if (nm_connection_update_secrets (NM_CONNECTION (self), setting_name, secrets, &local)) {
-			/* Now that all secrets are updated, copy and cache new secrets, 
+			/* Now that all secrets are updated, copy and cache new secrets,
 			 * then save them to backing storage.
 			 */
 			update_system_secrets_cache (self);
@@ -807,7 +808,7 @@ agent_secrets_done_cb (NMAgentManager *manager,
  *
  * Returns: a call ID which may be used to cancel the ongoing secrets request
  **/
-guint32 
+guint32
 nm_settings_connection_get_secrets (NMSettingsConnection *self,
                                     gboolean filter_by_uid,
                                     gulong uid,
@@ -882,7 +883,7 @@ nm_settings_connection_cancel_secrets (NMSettingsConnection *self,
 
 /**** User authorization **************************************/
 
-typedef void (*AuthCallback) (NMSettingsConnection *connection, 
+typedef void (*AuthCallback) (NMSettingsConnection *connection,
                               DBusGMethodInvocation *context,
                               gulong sender_uid,
                               GError *error,
@@ -1049,7 +1050,7 @@ check_writable (NMConnection *connection, GError **error)
 }
 
 static void
-get_settings_auth_cb (NMSettingsConnection *self, 
+get_settings_auth_cb (NMSettingsConnection *self,
                       DBusGMethodInvocation *context,
                       gulong sender_uid,
                       GError *error,
@@ -1272,7 +1273,7 @@ con_delete_cb (NMSettingsConnection *connection,
 }
 
 static void
-delete_auth_cb (NMSettingsConnection *self, 
+delete_auth_cb (NMSettingsConnection *self,
                 DBusGMethodInvocation *context,
                 gulong sender_uid,
                 GError *error,
@@ -1308,7 +1309,7 @@ impl_settings_connection_delete (NMSettingsConnection *self,
                                  DBusGMethodInvocation *context)
 {
 	GError *error = NULL;
-	
+
 	if (!check_writable (NM_CONNECTION (self), &error)) {
 		dbus_g_method_return_error (context, error);
 		g_error_free (error);
@@ -1351,7 +1352,7 @@ dbus_get_agent_secrets_cb (NMSettingsConnection *self,
 }
 
 static void
-dbus_secrets_auth_cb (NMSettingsConnection *self, 
+dbus_secrets_auth_cb (NMSettingsConnection *self,
                       DBusGMethodInvocation *context,
                       gulong sender_uid,
                       GError *error,
@@ -1474,7 +1475,7 @@ nm_settings_connection_update_timestamp (NMSettingsConnection *connection,
 	tmp = g_strdup_printf ("%" G_GUINT64_FORMAT, timestamp);
 	g_key_file_set_value (timestamps_file, "timestamps", connection_uuid, tmp);
 	g_free (tmp);
- 
+
 	data = g_key_file_to_data (timestamps_file, &len, &error);
 	if (data) {
 		g_file_set_contents (SETTINGS_TIMESTAMPS_FILE, data, len, &error);
@@ -1845,7 +1846,7 @@ nm_settings_connection_class_init (NMSettingsConnectionClass *class)
 		                       G_PARAM_READABLE));
 
 	/* Signals */
-	signals[UPDATED] = 
+	signals[UPDATED] =
 		g_signal_new (NM_SETTINGS_CONNECTION_UPDATED,
 		              G_TYPE_FROM_CLASS (class),
 		              G_SIGNAL_RUN_FIRST,
@@ -1854,7 +1855,7 @@ nm_settings_connection_class_init (NMSettingsConnectionClass *class)
 		              g_cclosure_marshal_VOID__VOID,
 		              G_TYPE_NONE, 0);
 
-	signals[REMOVED] = 
+	signals[REMOVED] =
 		g_signal_new (NM_SETTINGS_CONNECTION_REMOVED,
 		              G_TYPE_FROM_CLASS (class),
 		              G_SIGNAL_RUN_FIRST,
@@ -1864,7 +1865,7 @@ nm_settings_connection_class_init (NMSettingsConnectionClass *class)
 		              G_TYPE_NONE, 0);
 
 	/* Not exported */
-	signals[UNREGISTER] = 
+	signals[UNREGISTER] =
 		g_signal_new ("unregister",
 		              G_TYPE_FROM_CLASS (class),
 		              G_SIGNAL_RUN_FIRST,
diff --git a/src/settings/plugins/keyfile/reader.c b/src/settings/plugins/keyfile/reader.c
index 6ddf50d..a9cb063 100644
--- a/src/settings/plugins/keyfile/reader.c
+++ b/src/settings/plugins/keyfile/reader.c
@@ -380,7 +380,7 @@ ip_address_or_route_parser (NMSetting *setting, const char *key, GKeyFile *keyfi
 
 	for (i = -1; i < 1000; i++) {
 		const char **key_basename;
-		
+
 		for (key_basename = key_names; *key_basename; key_basename++) {
 			char *key_name;
 			gpointer item;
@@ -553,7 +553,7 @@ read_hash_of_string (GKeyFile *file, NMSetting *setting, const char *key)
 			continue;
 
 		if (NM_IS_SETTING_VPN (setting)) {
-			if (strcmp (*iter, NM_SETTING_VPN_SERVICE_TYPE))
+			if (strcmp (*iter, NM_SETTING_VPN_SERVICE_TYPE) || strcmp (*iter, NM_SETTING_VPN_DEFAULT_SECRET_FLAGS))
 				nm_setting_vpn_add_data_item (NM_SETTING_VPN (setting), *iter, value);
 		}
 		g_free (value);
diff --git a/src/settings/plugins/keyfile/writer.c b/src/settings/plugins/keyfile/writer.c
index 0b8c159..114b120 100644
--- a/src/settings/plugins/keyfile/writer.c
+++ b/src/settings/plugins/keyfile/writer.c
@@ -429,11 +429,13 @@ write_hash_of_string (GKeyFile *file,
 	const char *property = NULL, *data = NULL;
 	const char *group_name = nm_setting_get_name (setting);
 	gboolean vpn_secrets = FALSE;
+	NMSettingSecretFlags default_secret_flags;
 
 	/* Write VPN secrets out to a different group to keep them separate */
 	if (NM_IS_SETTING_VPN (setting) && !strcmp (key, NM_SETTING_VPN_SECRETS)) {
 		group_name = VPN_SECRETS_GROUP;
 		vpn_secrets = TRUE;
+		default_secret_flags = nm_setting_vpn_get_default_secret_flags((NMSettingVPN*)setting);
 	}
 
 	g_hash_table_iter_init (&iter, (GHashTable *) g_value_get_boxed (value));
@@ -445,7 +447,7 @@ write_hash_of_string (GKeyFile *file,
 		 * or owned by a user's secret agent.
 		 */
 		if (vpn_secrets) {
-			NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+			NMSettingSecretFlags secret_flags = default_secret_flags;
 
 			nm_setting_get_secret_flags (setting, property, &secret_flags, NULL);
 			if (secret_flags != NM_SETTING_SECRET_FLAG_NONE)
@@ -756,7 +758,7 @@ typedef struct {
 /* A table of keys that require further parsing/conversion because they are
  * stored in a format that can't be automatically read using the key's type.
  * i.e. IPv4 addresses, which are stored in NetworkManager as guint32, but are
- * stored in keyfiles as strings, eg "10.1.1.2" or IPv6 addresses stored 
+ * stored in keyfiles as strings, eg "10.1.1.2" or IPv6 addresses stored
  * in struct in6_addr internally, but as string in keyfiles.
  */
 static KeyWriter key_writers[] = {
@@ -945,11 +947,11 @@ write_setting_value (NMSetting *setting,
 		write_hash_of_string (info->keyfile, setting, key, value);
 	} else if (type == DBUS_TYPE_G_UINT_ARRAY) {
 		if (!write_array_of_uint (info->keyfile, setting, key, value)) {
-			g_warning ("Unhandled setting property type (write) '%s/%s' : '%s'", 
+			g_warning ("Unhandled setting property type (write) '%s/%s' : '%s'",
 					 setting_name, key, g_type_name (type));
 		}
 	} else {
-		g_warning ("Unhandled setting property type (write) '%s/%s' : '%s'", 
+		g_warning ("Unhandled setting property type (write) '%s/%s' : '%s'",
 				 setting_name, key, g_type_name (type));
 	}
 }
-- 
1.7.10.4



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]