summary refs log tree commit diff
path: root/src/settings/plugins/keyfile/nms-keyfile-reader.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/settings/plugins/keyfile/nms-keyfile-reader.c')
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-reader.c93
1 files changed, 63 insertions, 30 deletions
diff --git a/src/settings/plugins/keyfile/nms-keyfile-reader.c b/src/settings/plugins/keyfile/nms-keyfile-reader.c
index cb4b8379..580a857a 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-reader.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-reader.c
@@ -28,6 +28,7 @@
 #include "nm-keyfile-internal.h"
 
 #include "NetworkManagerUtils.h"
+#include "nms-keyfile-utils.h"
 
 /*****************************************************************************/
 
@@ -102,53 +103,87 @@ _handler_read (GKeyFile *keyfile,
 NMConnection *
 nms_keyfile_reader_from_keyfile (GKeyFile *key_file,
                                  const char *filename,
+                                 const char *base_dir,
+                                 const char *profile_dir,
                                  gboolean verbose,
                                  GError **error)
 {
+	NMConnection *connection;
 	HandlerReadData data = {
 		.verbose = verbose,
 	};
+	gs_free char *base_dir_free = NULL;
+	gs_free char *profile_filename_free = NULL;
+	gs_free char *filename_id = NULL;
+	const char *profile_filename = NULL;
+
+	nm_assert (filename && filename[0]);
+	nm_assert (!base_dir || base_dir[0] == '/');
+	nm_assert (!profile_dir || profile_dir[0] == '/');
+
+	if (base_dir)
+		nm_assert (!strchr (filename, '/'));
+	else {
+		const char *s;
+
+		nm_assert (filename[0] == '/');
+
+		/* @base_dir may be NULL, in which case @filename must be an absolute path,
+		 * and the directory is taken as the @base_dir. */
+		s = strrchr (filename, '/');
+		base_dir = nm_strndup_a (255, filename, s - filename, &base_dir_free);
+		if (   !profile_dir
+		    || nm_streq (base_dir, profile_dir))
+			profile_filename = filename;
+		filename = &s[1];
+	}
+
+	connection = nm_keyfile_read (key_file, base_dir, _handler_read, &data, error);
+	if (!connection)
+		return NULL;
+
+	if (g_str_has_suffix (filename, NMS_KEYFILE_PATH_SUFFIX_NMCONNECTION)) {
+		gsize l = strlen (filename);
 
-	return nm_keyfile_read (key_file, filename, NULL, _handler_read, &data, error);
+		if (l > NM_STRLEN (NMS_KEYFILE_PATH_SUFFIX_NMCONNECTION))
+			filename_id = g_strndup (filename, l - NM_STRLEN (NMS_KEYFILE_PATH_SUFFIX_NMCONNECTION));
+	}
+
+	nm_keyfile_read_ensure_id (connection, filename_id ?: filename);
+
+	if (!profile_filename) {
+		profile_filename_free = g_build_filename (profile_dir ?: base_dir, filename, NULL);
+		profile_filename = profile_filename_free;
+	}
+	nm_keyfile_read_ensure_uuid (connection, profile_filename);
+
+	return connection;
 }
 
 NMConnection *
-nms_keyfile_reader_from_file (const char *filename, GError **error)
+nms_keyfile_reader_from_file (const char *full_filename,
+                              const char *profile_dir,
+                              GError **error)
 {
-	GKeyFile *key_file;
-	struct stat statbuf;
+	gs_unref_keyfile GKeyFile *key_file = NULL;
 	NMConnection *connection = NULL;
 	GError *verify_error = NULL;
 
-	if (stat (filename, &statbuf) != 0 || !S_ISREG (statbuf.st_mode)) {
-		g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
-		                     "File did not exist or was not a regular file");
-		return NULL;
-	}
+	nm_assert (full_filename && full_filename[0] == '/');
+	nm_assert (!profile_dir || profile_dir[0] == '/');
 
-	if (!NM_FLAGS_HAS (nm_utils_get_testing (), NM_UTILS_TEST_NO_KEYFILE_OWNER_CHECK)) {
-		if (statbuf.st_mode & 0077) {
-			g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
-			             "File permissions (%o) were insecure",
-			             statbuf.st_mode);
-			return NULL;
-		}
-
-		if (statbuf.st_uid != 0) {
-			g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
-			             "File owner (%o) is insecure",
-			             statbuf.st_mode);
-			return NULL;
-		}
-	}
+	if (!nms_keyfile_utils_check_file_permissions (full_filename,
+	                                               NULL,
+	                                               error))
+		return NULL;
 
 	key_file = g_key_file_new ();
-	if (!g_key_file_load_from_file (key_file, filename, G_KEY_FILE_NONE, error))
-		goto out;
+	if (!g_key_file_load_from_file (key_file, full_filename, G_KEY_FILE_NONE, error))
+		return NULL;
 
-	connection = nms_keyfile_reader_from_keyfile (key_file, filename, TRUE, error);
+	connection = nms_keyfile_reader_from_keyfile (key_file, full_filename, NULL, profile_dir, TRUE, error);
 	if (!connection)
-		goto out;
+		return NULL;
 
 	/* Normalize and verify the connection */
 	if (!nm_connection_normalize (connection, NULL, NULL, &verify_error)) {
@@ -160,8 +195,6 @@ nms_keyfile_reader_from_file (const char *filename, GError **error)
 		connection = NULL;
 	}
 
-out:
-	g_key_file_free (key_file);
 	return connection;
 }