From 275e5c5e62c2ac41512924f8459e4cd4855a4487 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 9 Feb 2011 18:09:47 -0600 Subject: [PATCH] keyfile: handle different connections with the same ID Since keyfile uses the connection's ID as the filename by default, we could run into a situation where two connections with the same ID are visible to different users. We don't want one connection overwriting the other in that case, so we need to pick a new name for one of them. Append the connection's UUID to the end to minimize the risk of further conflicts for that name. --- .../plugins/keyfile/nm-keyfile-connection.c | 7 ++-- system-settings/plugins/keyfile/writer.c | 32 ++++++++++++++++--- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/system-settings/plugins/keyfile/nm-keyfile-connection.c b/system-settings/plugins/keyfile/nm-keyfile-connection.c index 048cd0cd4f..23618f7c2b 100644 --- a/system-settings/plugins/keyfile/nm-keyfile-connection.c +++ b/system-settings/plugins/keyfile/nm-keyfile-connection.c @@ -114,12 +114,11 @@ commit_changes (NMSettingsConnection *connection, return; } - if (g_strcmp0 (priv->path, path)) { - /* Update the filename if it changed */ + /* Update the filename if it changed */ + if (path) { g_free (priv->path); priv->path = path; - } else - g_free (path); + } NM_SETTINGS_CONNECTION_CLASS (nm_keyfile_connection_parent_class)->commit_changes (connection, callback, diff --git a/system-settings/plugins/keyfile/writer.c b/system-settings/plugins/keyfile/writer.c index 87772cdf8e..5bea8348dc 100644 --- a/system-settings/plugins/keyfile/writer.c +++ b/system-settings/plugins/keyfile/writer.c @@ -700,7 +700,7 @@ _internal_write_connection (NMConnection *connection, char *data; gsize len; gboolean success = FALSE; - char *filename, *path; + char *filename = NULL, *path; const char *id; if (out_path) @@ -721,9 +721,28 @@ _internal_write_connection (NMConnection *connection, filename = _writer_id_to_filename (id); path = g_build_filename (keyfile_dir, filename, NULL); - g_free (filename); - /* If the file already exists */ + /* If a file with this path already exists (but isn't the existing path + * of the connection) then we need another name. Multiple connections + * can have the same ID (ie if two connections with the same ID are visible + * to different users) but of course can't have the same path. Yeah, + * there's a race here, but there's not a lot we can do about it, and + * we shouldn't get more than one connection with the same UUID either. + */ + if (g_file_test (path, G_FILE_TEST_EXISTS) && (g_strcmp0 (path, existing_path) != 0)) { + /* A keyfile with this connection's ID already exists. Pick another name. */ + g_free (path); + + path = g_strdup_printf ("%s/%s-%s", keyfile_dir, filename, nm_connection_get_uuid (connection)); + if (g_file_test (path, G_FILE_TEST_EXISTS)) { + /* Hmm, this is odd. Give up. */ + g_set_error (error, KEYFILE_PLUGIN_ERROR, 0, + "%s.%d: could not find suitable keyfile file name (%s already used)", + __FILE__, __LINE__, path); + g_free (path); + goto out; + } + } g_file_set_contents (path, data, len, error); if (chown (path, owner_uid, owner_grp) < 0) { @@ -738,14 +757,17 @@ _internal_write_connection (NMConnection *connection, __LINE__, path, errno); unlink (path); } else { - if (out_path) - *out_path = g_strdup (path); + if (out_path && g_strcmp0 (existing_path, path)) { + *out_path = path; /* pass path out to caller */ + path = NULL; + } success = TRUE; } } g_free (path); out: + g_free (filename); g_free (data); g_key_file_free (key_file); return success;