about summary refs log tree commit diff
path: root/src/settings/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/settings/plugins')
-rwxr-xr-xsrc/settings/plugins/ibft/tests/iscsiadm-test-bad-dns121
-rwxr-xr-xsrc/settings/plugins/ibft/tests/iscsiadm-test-bad-dns221
-rwxr-xr-xsrc/settings/plugins/ibft/tests/iscsiadm-test-bad-entry20
-rwxr-xr-xsrc/settings/plugins/ibft/tests/iscsiadm-test-bad-gateway21
-rwxr-xr-xsrc/settings/plugins/ibft/tests/iscsiadm-test-bad-ipaddr21
-rwxr-xr-xsrc/settings/plugins/ibft/tests/iscsiadm-test-bad-record18
-rwxr-xr-xsrc/settings/plugins/ibft/tests/iscsiadm-test-dhcp33
-rwxr-xr-xsrc/settings/plugins/ibft/tests/iscsiadm-test-static35
-rwxr-xr-xsrc/settings/plugins/ibft/tests/iscsiadm-test-vlan19
-rw-r--r--src/settings/plugins/ifcfg-rh/meson.build9
-rw-r--r--src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c2
-rw-r--r--src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c20
-rw-r--r--src/settings/plugins/ifupdown/tests/test-ifupdown.c4
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-connection.c8
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-connection.h3
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-plugin.c141
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-reader.c85
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-reader.h6
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-utils.c100
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-utils.h16
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-writer.c32
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-writer.h1
-rw-r--r--src/settings/plugins/keyfile/tests/test-keyfile.c403
23 files changed, 405 insertions, 634 deletions
diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-dns1 b/src/settings/plugins/ibft/tests/iscsiadm-test-bad-dns1
deleted file mode 100755
index 54f02da6..00000000
--- a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-dns1
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-
-cat << EOF
-# BEGIN RECORD
-iface.initiatorname = iqn.pjones6
-iface.hwaddress = 00:33:21:98:b9:f0
-iface.bootproto = STATIC
-iface.ipaddress = 192.168.32.72
-iface.subnet_mask = 255.255.252.0
-iface.gateway = 192.168.35.254
-iface.primary_dns = 10000.500.250.1
-iface.secondary_dns = 10.16.255.3
-iface.vlan_id = 0
-iface.net_ifacename = eth0
-node.name = iqn.0.2008-11.com.blahblah:iscsi0
-node.conn[0].address = 10.16.52.16
-node.conn[0].port = 3260
-node.boot_lun = 00000000
-# END RECORD
-EOF
-
diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-dns2 b/src/settings/plugins/ibft/tests/iscsiadm-test-bad-dns2
deleted file mode 100755
index ebd7a9ca..00000000
--- a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-dns2
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-
-cat << EOF
-# BEGIN RECORD
-iface.initiatorname = iqn.pjones6
-iface.hwaddress = 00:33:21:98:b9:f0
-iface.bootproto = STATIC
-iface.ipaddress = 192.168.32.72
-iface.subnet_mask = 255.255.252.0
-iface.gateway = 192.168.35.254
-iface.primary_dns = 10.16.255.2
-iface.secondary_dns = blah.foo.bar.baz
-iface.vlan_id = 0
-iface.net_ifacename = eth0
-node.name = iqn.0.2008-11.com.blahblah:iscsi0
-node.conn[0].address = 10.16.52.16
-node.conn[0].port = 3260
-node.boot_lun = 00000000
-# END RECORD
-EOF
-
diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-entry b/src/settings/plugins/ibft/tests/iscsiadm-test-bad-entry
deleted file mode 100755
index 4e326048..00000000
--- a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-entry
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/bash
-
-cat << EOF
-# BEGIN RECORD
-iface.initiatorname = iqn.pjones6
-iface.hwaddress = 00:33:21:98:b9:f0
-iface.bootproto = STATIC
-iface.ipaddress 192.168.32.72
-iface.subnet_mask = 255.255.252.0
-iface.gateway = 192.168.35.254
-iface.primary_dns = 10.16.255.2
-iface.secondary_dns = 10.16.255.3
-iface.vlan_id = 0
-iface.net_ifacename = eth0
-node.name = iqn.0.2008-11.com.blahblah:iscsi0
-node.conn[0].address = 10.16.52.16
-node.conn[0].port = 3260
-node.boot_lun = 00000000
-# END RECORD
-
diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-gateway b/src/settings/plugins/ibft/tests/iscsiadm-test-bad-gateway
deleted file mode 100755
index 5390a6c3..00000000
--- a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-gateway
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-
-cat << EOF
-# BEGIN RECORD
-iface.initiatorname = iqn.pjones6
-iface.hwaddress = 00:33:21:98:b9:f0
-iface.bootproto = STATIC
-iface.ipaddress = 192.168.32.72
-iface.subnet_mask = 255.255.252.0
-iface.gateway = bb.cc.dd.ee
-iface.primary_dns = 10.16.255.2
-iface.secondary_dns = 10.16.255.3
-iface.vlan_id = 0
-iface.net_ifacename = eth0
-node.name = iqn.0.2008-11.com.blahblah:iscsi0
-node.conn[0].address = 10.16.52.16
-node.conn[0].port = 3260
-node.boot_lun = 00000000
-# END RECORD
-EOF
-
diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-ipaddr b/src/settings/plugins/ibft/tests/iscsiadm-test-bad-ipaddr
deleted file mode 100755
index b41cd1f1..00000000
--- a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-ipaddr
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-
-cat << EOF
-# BEGIN RECORD
-iface.initiatorname = iqn.pjones6
-iface.hwaddress = 00:33:21:98:b9:f0
-iface.bootproto = STATIC
-iface.ipaddress = aa.bb.cc.dd
-iface.subnet_mask = 255.255.252.0
-iface.gateway = 192.168.35.254
-iface.primary_dns = 10.16.255.2
-iface.secondary_dns = 10.16.255.3
-iface.vlan_id = 0
-iface.net_ifacename = eth0
-node.name = iqn.0.2008-11.com.blahblah:iscsi0
-node.conn[0].address = 10.16.52.16
-node.conn[0].port = 3260
-node.boot_lun = 00000000
-# END RECORD
-EOF
-
diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-record b/src/settings/plugins/ibft/tests/iscsiadm-test-bad-record
deleted file mode 100755
index 22b34e6f..00000000
--- a/src/settings/plugins/ibft/tests/iscsiadm-test-bad-record
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/bash
-
-cat << EOF
-# BEGIN RECORD
-iface.initiatorname = iqn.pjones6
-iface.hwaddress = 00:33:21:98:b9:f0
-iface.bootproto = DHCP
-iface.gateway = 10.16.52.254
-iface.primary_dns = 10.16.255.2
-iface.secondary_dns = 10.16.255.3
-iface.vlan_id = 0
-iface.net_ifacename = eth0
-node.name = iqn.0.2008-11.com.blahblah:iscsi0
-node.conn[0].address = 10.16.52.16
-node.conn[0].port = 3260
-node.boot_lun = 00000000
-EOF
-
diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-dhcp b/src/settings/plugins/ibft/tests/iscsiadm-test-dhcp
deleted file mode 100755
index 556b0586..00000000
--- a/src/settings/plugins/ibft/tests/iscsiadm-test-dhcp
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/bash
-
-cat << EOF
-# BEGIN RECORD
-iface.initiatorname = iqn.pjones6
-iface.hwaddress = 00:33:21:98:b9:f0
-iface.bootproto = DHCP
-iface.gateway = 10.16.52.254
-iface.primary_dns = 10.16.255.2
-iface.secondary_dns = 10.16.255.3
-iface.vlan_id = 0
-iface.net_ifacename = eth0
-node.name = iqn.0.2008-11.com.blahblah:iscsi0
-node.conn[0].address = 10.16.52.16
-node.conn[0].port = 3260
-node.boot_lun = 00000000
-# END RECORD
-# BEGIN RECORD
-iface.initiatorname = iqn.pjones6
-iface.hwaddress = 00:33:21:98:b9:f1
-iface.bootproto = DHCP
-iface.gateway = 10.16.52.254
-iface.primary_dns = 10.16.255.2
-iface.secondary_dns = 10.16.255.3
-iface.vlan_id = 0
-iface.net_ifacename = eth1
-node.name = iqn.1.2008-11.com.blahblah:iscsi1
-node.conn[0].address = 10.16.52.16
-node.conn[0].port = 3260
-node.boot_lun = 00000000
-# END RECORD
-EOF
-
diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-static b/src/settings/plugins/ibft/tests/iscsiadm-test-static
deleted file mode 100755
index 51711480..00000000
--- a/src/settings/plugins/ibft/tests/iscsiadm-test-static
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/bash
-
-cat << EOF
-# BEGIN RECORD
-iface.initiatorname = iqn.pjones6
-iface.hwaddress = 00:33:21:98:b9:f0
-iface.bootproto = STATIC
-iface.ipaddress = 192.168.32.72
-iface.subnet_mask = 255.255.252.0
-iface.gateway = 192.168.35.254
-iface.primary_dns = 10.16.255.2
-iface.secondary_dns = 10.16.255.3
-iface.vlan_id = 0
-iface.net_ifacename = eth0
-node.name = iqn.0.2008-11.com.blahblah:iscsi0
-node.conn[0].address = 10.16.52.16
-node.conn[0].port = 3260
-node.boot_lun = 00000000
-# END RECORD
-# BEGIN RECORD
-iface.initiatorname = iqn.pjones6
-iface.hwaddress = 00:33:21:98:b9:f1
-iface.bootproto = DHCP
-iface.gateway = 10.16.52.254
-iface.primary_dns = 10.16.255.2
-iface.secondary_dns = 10.16.255.3
-iface.vlan_id = 0
-iface.net_ifacename = eth1
-node.name = iqn.1.2008-11.com.blahblah:iscsi1
-node.conn[0].address = 10.16.52.16
-node.conn[0].port = 3260
-node.boot_lun = 00000000
-# END RECORD
-EOF
-
diff --git a/src/settings/plugins/ibft/tests/iscsiadm-test-vlan b/src/settings/plugins/ibft/tests/iscsiadm-test-vlan
deleted file mode 100755
index 59b80bd0..00000000
--- a/src/settings/plugins/ibft/tests/iscsiadm-test-vlan
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/bash
-
-cat << EOF
-# BEGIN RECORD 6.2.0.873-21
-iface.initiatorname = iqn.2010-04.org.ipxe:d05faa97-c4be-44f6-a723-efde9aa399a0
-iface.transport_name = tcp
-iface.hwaddress = 00:33:21:98:b9:f0
-iface.bootproto = STATIC
-iface.ipaddress = 192.168.6.200
-iface.subnet_mask = 255.255.255.0
-iface.vlan_id = 123
-iface.net_ifacename = eth0
-node.name = iqn.2003-01.org.x:disk1
-node.conn[0].address = 192.168.6.32
-node.conn[0].port = 3260
-node.boot_lun = 01000000
-# END RECORD
-EOF
-
diff --git a/src/settings/plugins/ifcfg-rh/meson.build b/src/settings/plugins/ifcfg-rh/meson.build
index e4bce09b..e84ae80c 100644
--- a/src/settings/plugins/ifcfg-rh/meson.build
+++ b/src/settings/plugins/ifcfg-rh/meson.build
@@ -63,6 +63,15 @@ check-local-symbols-settings-ifcfg-rh: src/settings/plugins/ifcfg-rh/libnm-setti
   $(call check_so_symbols,$(builddir)/src/settings/plugins/ifcfg-rh/.libs/libnm-settings-plugin-ifcfg-rh.so)
 '''
 
+install_data(
+  ['nm-ifup', 'nm-ifdown'],
+  install_dir: nm_libexecdir,
+  install_mode: 'rwxr-xr-x',
+)
+
+meson.add_install_script('sh', '-c',
+                         'mkdir -p $DESTDIR/@0@/sysconfig/network-scripts'.format(nm_sysconfdir))
+
 if enable_tests
   subdir('tests')
 endif
diff --git a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
index 0c0dd64e..472bb8a6 100644
--- a/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
+++ b/src/settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c
@@ -9054,7 +9054,7 @@ test_team_reread_slave (void)
 	        "id=142\n"
 	        "ingress-priority-map=\n"
 	        "parent=enp31s0f1\n"
-	        , "/test_team_reread_slave", NULL);
+	        , "/test_team_reread_slave");
 
 	/* to double-check keyfile syntax, re-create the connection by hand. */
 	connection_2 = nmtst_create_minimal_connection ("team-slave-enp31s0f1-142", "74f435bb-ede4-415a-9d48-f580b60eba04", NM_SETTING_VLAN_SETTING_NAME, &s_con);
diff --git a/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c b/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c
index d926829f..73ecc2f9 100644
--- a/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c
+++ b/src/settings/plugins/ifupdown/nms-ifupdown-interface-parser.c
@@ -126,17 +126,17 @@ _recursive_ifparser (if_parser *parser, const char *eni_file, int quiet)
 	/* Check if interfaces file exists and open it */
 	if (!g_file_test (eni_file, G_FILE_TEST_EXISTS)) {
 		if (!quiet)
-			_LOGW ("interfaces file %s doesn't exist\n", eni_file);
+			_LOGW ("interfaces file %s doesn't exist", eni_file);
 		return;
 	}
 	inp = fopen (eni_file, "re");
 	if (inp == NULL) {
 		if (!quiet)
-			_LOGW ("Can't open %s\n", eni_file);
+			_LOGW ("Can't open %s", eni_file);
 		return;
 	}
 	if (!quiet)
-		_LOGI ("      interface-parser: parsing file %s\n", eni_file);
+		_LOGI ("      interface-parser: parsing file %s", eni_file);
 
 	while (!feof (inp)) {
 		char *token[128]; /* 255 chars can only be split into 127 tokens */
@@ -154,7 +154,7 @@ _recursive_ifparser (if_parser *parser, const char *eni_file, int quiet)
 		if (!feof (inp) && len > 0 &&  line[len-1] != '\n') {
 			if (!skip_long_line) {
 				if (!quiet)
-					_LOGW ("Skipping over-long-line '%s...'\n", line);
+					_LOGW ("Skipping over-long-line '%s...'", line);
 			}
 			skip_long_line = 1;
 			continue;
@@ -192,7 +192,7 @@ _recursive_ifparser (if_parser *parser, const char *eni_file, int quiet)
 
 		if (toknum < 2) {
 			if (!quiet) {
-				_LOGW ("Can't parse interface line '%s'\n",
+				_LOGW ("Can't parse interface line '%s'",
 				       join_values_with_spaces (value, token));
 			}
 			skip_to_block = 1;
@@ -207,7 +207,7 @@ _recursive_ifparser (if_parser *parser, const char *eni_file, int quiet)
 		if (nm_streq (token[0], "iface")) {
 			if (toknum < 4) {
 				if (!quiet) {
-					_LOGW ("Can't parse iface line '%s'\n",
+					_LOGW ("Can't parse iface line '%s'",
 					       join_values_with_spaces (value, token));
 				}
 				continue;
@@ -254,7 +254,7 @@ _recursive_ifparser (if_parser *parser, const char *eni_file, int quiet)
 		else {
 			if (skip_to_block) {
 				if (!quiet) {
-					_LOGW ("ignoring out-of-block data '%s'\n",
+					_LOGW ("ignoring out-of-block data '%s'",
 					       join_values_with_spaces (value, token));
 				}
 			} else
@@ -264,7 +264,7 @@ _recursive_ifparser (if_parser *parser, const char *eni_file, int quiet)
 	fclose (inp);
 
 	if (!quiet)
-		_LOGI ("      interface-parser: finished parsing file %s\n", eni_file);
+		_LOGI ("      interface-parser: finished parsing file %s", eni_file);
 }
 
 static void
@@ -283,12 +283,12 @@ _ifparser_source (if_parser *parser, const char *path, const char *en_dir, int q
 		abs_path = g_build_filename (en_dir, path, NULL);
 
 	if (!quiet)
-		_LOGI ("      interface-parser: source line includes interfaces file(s) %s\n", abs_path);
+		_LOGI ("      interface-parser: source line includes interfaces file(s) %s", abs_path);
 
 	/* ifupdown uses WRDE_NOCMD for wordexp. */
 	if (wordexp (abs_path, &we, WRDE_NOCMD)) {
 		if (!quiet)
-			_LOGW ("word expansion for %s failed\n", abs_path);
+			_LOGW ("word expansion for %s failed", abs_path);
 	} else {
 		for (i = 0; i < we.we_wordc; i++) {
 			if (dir) {
diff --git a/src/settings/plugins/ifupdown/tests/test-ifupdown.c b/src/settings/plugins/ifupdown/tests/test-ifupdown.c
index e96350c0..82ee1c4a 100644
--- a/src/settings/plugins/ifupdown/tests/test-ifupdown.c
+++ b/src/settings/plugins/ifupdown/tests/test-ifupdown.c
@@ -144,7 +144,7 @@ compare_expected_to_ifparser (if_parser *parser, Expected *e)
 
 		g_assert (b->type && n->type);
 		g_assert_cmpstr (b->type, ==, n->type);
-		g_assert (b->name && n->name);
+		g_assert (b->name);
 		g_assert_cmpstr (b->name, ==, n->name);
 
 		g_assert_cmpint (g_slist_length (b->keys), ==, ifparser_get_num_info (n));
@@ -153,7 +153,7 @@ compare_expected_to_ifparser (if_parser *parser, Expected *e)
 		c_list_for_each_entry (m, &n->data_lst_head, data_lst) {
 			ExpectedKey *k = kiter->data;
 
-			g_assert (k->key && m->key);
+			g_assert (k->key);
 			g_assert_cmpstr (k->key, ==, m->key);
 			g_assert (k->data && m->data);
 			g_assert_cmpstr (k->data, ==, m->data);
diff --git a/src/settings/plugins/keyfile/nms-keyfile-connection.c b/src/settings/plugins/keyfile/nms-keyfile-connection.c
index 64e94b26..7511f206 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-connection.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-connection.c
@@ -66,6 +66,7 @@ commit_changes (NMSettingsConnection *connection,
 	nm_assert (!out_logmsg_change || !*out_logmsg_change);
 
 	if (!nms_keyfile_writer_connection (new_connection,
+	                                    TRUE,
 	                                    nm_settings_connection_get_filename (connection),
 	                                    NM_FLAGS_ALL (commit_reason,   NM_SETTINGS_CONNECTION_COMMIT_REASON_USER_ACTION
 	                                                                 | NM_SETTINGS_CONNECTION_COMMIT_REASON_ID_CHANGED),
@@ -123,6 +124,7 @@ nms_keyfile_connection_init (NMSKeyfileConnection *connection)
 NMSKeyfileConnection *
 nms_keyfile_connection_new (NMConnection *source,
                             const char *full_path,
+                            const char *profile_dir,
                             GError **error)
 {
 	GObject *object;
@@ -130,13 +132,15 @@ nms_keyfile_connection_new (NMConnection *source,
 	const char *uuid;
 	gboolean update_unsaved = TRUE;
 
-	g_assert (source || full_path);
+	nm_assert (source || full_path);
+	nm_assert (!full_path || full_path[0] == '/');
+	nm_assert (!profile_dir || profile_dir[0] == '/');
 
 	/* If we're given a connection already, prefer that instead of re-reading */
 	if (source)
 		tmp = g_object_ref (source);
 	else {
-		tmp = nms_keyfile_reader_from_file (full_path, error);
+		tmp = nms_keyfile_reader_from_file (full_path, profile_dir, error);
 		if (!tmp)
 			return NULL;
 
diff --git a/src/settings/plugins/keyfile/nms-keyfile-connection.h b/src/settings/plugins/keyfile/nms-keyfile-connection.h
index f96d7590..0773ced0 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-connection.h
+++ b/src/settings/plugins/keyfile/nms-keyfile-connection.h
@@ -37,7 +37,8 @@ typedef struct _NMSKeyfileConnectionClass NMSKeyfileConnectionClass;
 GType nms_keyfile_connection_get_type (void);
 
 NMSKeyfileConnection *nms_keyfile_connection_new (NMConnection *source,
-                                                  const char *filename,
+                                                  const char *full_path,
+                                                  const char *profile_dir,
                                                   GError **error);
 
 #endif /* __NMS_KEYFILE_CONNECTION_H__ */
diff --git a/src/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/settings/plugins/keyfile/nms-keyfile-plugin.c
index 89b89467..346b78c0 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-plugin.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-plugin.c
@@ -171,6 +171,7 @@ update_connection (NMSKeyfilePlugin *self,
 	NMSKeyfileConnection *connection_by_uuid;
 	GError *local = NULL;
 	const char *uuid;
+	int dir_len;
 
 	g_return_val_if_fail (!source || NM_IS_CONNECTION (source), NULL);
 	g_return_val_if_fail (full_path || source, NULL);
@@ -178,7 +179,23 @@ update_connection (NMSKeyfilePlugin *self,
 	if (full_path)
 		_LOGD ("loading from file \"%s\"...", full_path);
 
-	connection_new = nms_keyfile_connection_new (source, full_path, &local);
+	if (g_str_has_prefix (full_path, nms_keyfile_utils_get_path ())) {
+		dir_len = strlen (nms_keyfile_utils_get_path ());
+	} else if (g_str_has_prefix (full_path, NM_CONFIG_KEYFILE_PATH_IN_MEMORY)) {
+		dir_len = NM_STRLEN (NM_CONFIG_KEYFILE_PATH_IN_MEMORY);
+	} else {
+		/* Just make sure the file name is not going go pass the following check. */
+		dir_len = strlen (full_path);
+	}
+
+	if (   full_path[dir_len] != '/'
+	    || strchr (full_path + dir_len + 1, '/') != NULL) {
+		g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED,
+		                     "File not in recognized system-connections directory");
+		return FALSE;
+	}
+
+	connection_new = nms_keyfile_connection_new (source, full_path, nms_keyfile_utils_get_path (), &local);
 	if (!connection_new) {
 		/* Error; remove the connection */
 		if (source)
@@ -305,7 +322,7 @@ dir_changed (GFileMonitor *monitor,
 	gboolean exists;
 
 	full_path = g_file_get_path (file);
-	if (nms_keyfile_utils_should_ignore_file (full_path)) {
+	if (nms_keyfile_utils_should_ignore_file (full_path, FALSE)) {
 		g_free (full_path);
 		return;
 	}
@@ -411,13 +428,35 @@ _sort_paths (const char **f1, const char **f2, GHashTable *paths)
 }
 
 static void
+_read_dir (GPtrArray *filenames,
+           const char *path,
+           gboolean require_extension)
+{
+	GDir *dir;
+	const char *item;
+	GError *error = NULL;
+
+	dir = g_dir_open (path, 0, &error);
+	if (!dir) {
+		_LOGD ("cannot read directory '%s': %s", path, error->message);
+		g_clear_error (&error);
+		return;
+	}
+
+	while ((item = g_dir_read_name (dir))) {
+		if (nms_keyfile_utils_should_ignore_file (item, require_extension))
+			continue;
+		g_ptr_array_add (filenames, g_build_filename (path, item, NULL));
+	}
+	g_dir_close (dir);
+}
+
+
+static void
 read_connections (NMSettingsPlugin *config)
 {
 	NMSKeyfilePlugin *self = NMS_KEYFILE_PLUGIN (config);
 	NMSKeyfilePluginPrivate *priv = NMS_KEYFILE_PLUGIN_GET_PRIVATE (self);
-	GDir *dir;
-	GError *error = NULL;
-	const char *item;
 	GHashTable *alive_connections;
 	GHashTableIter iter;
 	NMSKeyfileConnection *connection;
@@ -426,24 +465,12 @@ read_connections (NMSettingsPlugin *config)
 	GPtrArray *filenames;
 	GHashTable *paths;
 
-	dir = g_dir_open (nms_keyfile_utils_get_path (), 0, &error);
-	if (!dir) {
-		_LOGW ("cannot read directory '%s': %s",
-		             nms_keyfile_utils_get_path (),
-		             error->message);
-		g_clear_error (&error);
-		return;
-	}
+	filenames = g_ptr_array_new_with_free_func (g_free);
 
-	alive_connections = g_hash_table_new (nm_direct_hash, NULL);
+	_read_dir (filenames, NM_CONFIG_KEYFILE_PATH_IN_MEMORY, TRUE);
+	_read_dir (filenames, nms_keyfile_utils_get_path (), FALSE);
 
-	filenames = g_ptr_array_new_with_free_func (g_free);
-	while ((item = g_dir_read_name (dir))) {
-		if (nms_keyfile_utils_should_ignore_file (item))
-			continue;
-		g_ptr_array_add (filenames, g_build_filename (nms_keyfile_utils_get_path (), item, NULL));
-	}
-	g_dir_close (dir);
+	alive_connections = g_hash_table_new (nm_direct_hash, NULL);
 
 	/* While reloading, we don't replace connections that we already loaded while
 	 * iterating over the files.
@@ -496,19 +523,61 @@ get_connections (NMSettingsPlugin *config)
 }
 
 static gboolean
+_file_is_in_path (const char *abs_filename,
+                  const char *abs_path)
+{
+	gsize l;
+
+	/* FIXME: ensure that both paths are at least normalized (coalescing ".",
+	 * duplicate '/', and trailing '/'). */
+
+	nm_assert (abs_filename && abs_filename[0] == '/');
+	nm_assert (abs_path && abs_path[0] == '/');
+
+	l = strlen (abs_path);
+	if (strncmp (abs_filename, abs_path, l) != 0)
+		return FALSE;
+
+	abs_filename += l;
+	while (abs_filename[0] == '/')
+		abs_filename++;
+
+	if (!abs_filename[0])
+		return FALSE;
+
+	if (strchr (abs_filename, '/'))
+		return FALSE;
+
+	return TRUE;
+}
+
+static gboolean
 load_connection (NMSettingsPlugin *config,
                  const char *filename)
 {
 	NMSKeyfilePlugin *self = NMS_KEYFILE_PLUGIN ((NMSKeyfilePlugin *) config);
 	NMSKeyfileConnection *connection;
-	int dir_len = strlen (nms_keyfile_utils_get_path ());
+	gboolean require_extension;
 
-	if (   strncmp (filename, nms_keyfile_utils_get_path (), dir_len) != 0
-	    || filename[dir_len] != '/'
-	    || strchr (filename + dir_len + 1, '/') != NULL)
+	/* the test whether to require a file extension tries to figure out whether
+	 * the provided filename is inside /etc or /run.
+	 *
+	 * However, on Posix a filename just resolves to an Inode, and there can
+	 * be any kind of paths that point to the same Inode. It's not generally possible
+	 * to check for that (unless, we would stat all files in the target directory
+	 * and see whether their inode matches).
+	 *
+	 * So, when loading the file do something simpler: require that the path
+	 * starts with the well-known prefix. This rejects symlinks or hard links
+	 * which would actually also point to the same file. */
+	if (_file_is_in_path (filename, nms_keyfile_utils_get_path ()))
+		require_extension = FALSE;
+	else if (_file_is_in_path (filename, NM_CONFIG_KEYFILE_PATH_IN_MEMORY))
+		require_extension = TRUE;
+	else
 		return FALSE;
 
-	if (nms_keyfile_utils_should_ignore_file (filename + dir_len + 1))
+	if (nms_keyfile_utils_should_ignore_file (filename, require_extension))
 		return FALSE;
 
 	connection = update_connection (self, NULL, filename, find_by_path (self, filename), TRUE, NULL, NULL);
@@ -532,16 +601,16 @@ add_connection (NMSettingsPlugin *config,
 	gs_free char *path = NULL;
 	gs_unref_object NMConnection *reread = NULL;
 
-	if (save_to_disk) {
-		if (!nms_keyfile_writer_connection (connection,
-		                                    NULL,
-		                                    FALSE,
-		                                    &path,
-		                                    &reread,
-		                                    NULL,
-		                                    error))
-			return NULL;
-	}
+	if (!nms_keyfile_writer_connection (connection,
+	                                    save_to_disk,
+	                                    NULL,
+	                                    FALSE,
+	                                    &path,
+	                                    &reread,
+	                                    NULL,
+	                                    error))
+		return NULL;
+
 	return NM_SETTINGS_CONNECTION (update_connection (self, reread ?: connection, path, NULL, FALSE, NULL, error));
 }
 
diff --git a/src/settings/plugins/keyfile/nms-keyfile-reader.c b/src/settings/plugins/keyfile/nms-keyfile-reader.c
index 71578686..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,51 +103,85 @@ _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);
+
+		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);
 
-	return nm_keyfile_read (key_file, filename, NULL, _handler_read, &data, error);
+	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)
 {
 	gs_unref_keyfile GKeyFile *key_file = NULL;
-	struct stat statbuf;
 	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))
+	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)
 		return NULL;
 
diff --git a/src/settings/plugins/keyfile/nms-keyfile-reader.h b/src/settings/plugins/keyfile/nms-keyfile-reader.h
index b60c1e69..c0fb06d1 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-reader.h
+++ b/src/settings/plugins/keyfile/nms-keyfile-reader.h
@@ -26,9 +26,13 @@
 
 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 *nms_keyfile_reader_from_file (const char *filename, GError **error);
+NMConnection *nms_keyfile_reader_from_file (const char *full_filename,
+                                            const char *profile_dir,
+                                            GError **error);
 
 #endif /* __NMS_KEYFILE_READER_H__ */
diff --git a/src/settings/plugins/keyfile/nms-keyfile-utils.c b/src/settings/plugins/keyfile/nms-keyfile-utils.c
index 03f06670..c3bfcdee 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-utils.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-utils.c
@@ -24,6 +24,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <sys/stat.h>
 
 #include "nm-setting-wired.h"
 #include "nm-setting-wireless.h"
@@ -55,18 +56,11 @@ check_mkstemp_suffix (const char *path)
 }
 
 static gboolean
-check_prefix (const char *base, const char *tag)
+check_prefix_dot (const char *base)
 {
-	int len, tag_len;
+	nm_assert (base && base[0]);
 
-	g_return_val_if_fail (base != NULL, TRUE);
-	g_return_val_if_fail (tag != NULL, TRUE);
-
-	len = strlen (base);
-	tag_len = strlen (tag);
-	if ((len > tag_len) && !g_ascii_strncasecmp (base, tag, tag_len))
-		return TRUE;
-	return FALSE;
+	return base[0] == '.';
 }
 
 static gboolean
@@ -90,7 +84,7 @@ check_suffix (const char *base, const char *tag)
 #define DER_TAG ".der"
 
 gboolean
-nms_keyfile_utils_should_ignore_file (const char *filename)
+nms_keyfile_utils_should_ignore_file (const char *filename, gboolean require_extension)
 {
 	gs_free char *base = NULL;
 
@@ -101,7 +95,7 @@ nms_keyfile_utils_should_ignore_file (const char *filename)
 
 	/* Ignore hidden and backup files */
 	/* should_ignore_file() must mirror escape_filename() */
-	if (check_prefix (base, ".") || check_suffix (base, "~"))
+	if (check_prefix_dot (base) || check_suffix (base, "~"))
 		return TRUE;
 	/* Ignore temporary files */
 	if (check_mkstemp_suffix (base))
@@ -110,18 +104,87 @@ nms_keyfile_utils_should_ignore_file (const char *filename)
 	if (check_suffix (base, PEM_TAG) || check_suffix (base, DER_TAG))
 		return TRUE;
 
+	if (require_extension) {
+		gsize l = strlen (base);
+
+		if (   l <= NM_STRLEN (NMS_KEYFILE_PATH_SUFFIX_NMCONNECTION)
+		    || !g_str_has_suffix (base, NMS_KEYFILE_PATH_SUFFIX_NMCONNECTION))
+			return TRUE;
+	}
+
 	return FALSE;
 }
 
+/*****************************************************************************/
+
+gboolean
+nms_keyfile_utils_check_file_permissions_stat (const struct stat *st,
+                                               GError **error)
+{
+	g_return_val_if_fail (st, FALSE);
+
+	if (!S_ISREG (st->st_mode)) {
+		g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+		                     "file is not a regular file");
+		return FALSE;
+	}
+
+	if (!NM_FLAGS_HAS (nm_utils_get_testing (), NM_UTILS_TEST_NO_KEYFILE_OWNER_CHECK)) {
+		if (st->st_uid != 0) {
+			g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+			             "File owner (%lld) is insecure",
+			             (long long) st->st_uid);
+			return FALSE;
+		}
+
+		if (st->st_mode & 0077) {
+			g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+			             "File permissions (%03o) are insecure",
+			             st->st_mode);
+			return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+gboolean
+nms_keyfile_utils_check_file_permissions (const char *filename,
+                                          struct stat *out_st,
+                                          GError **error)
+{
+	struct stat st;
+	int errsv;
+
+	g_return_val_if_fail (filename && filename[0] == '/', FALSE);
+
+	if (stat (filename, &st) != 0) {
+		errsv = errno;
+		g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
+		             "cannot access file: %s", g_strerror (errsv));
+		return FALSE;
+	}
+
+	if (!nms_keyfile_utils_check_file_permissions_stat (&st, error))
+		return FALSE;
+
+	NM_SET_OUT (out_st, st);
+	return TRUE;
+}
+
+/*****************************************************************************/
+
 char *
-nms_keyfile_utils_escape_filename (const char *filename)
+nms_keyfile_utils_escape_filename (const char *filename,
+                                   gboolean with_extension)
 {
 	GString *str;
 	const char *f = filename;
-	const char ESCAPE_CHAR = '*';
-
 	/* keyfile used to escape with '*', do not change that behavior.
-	 * But for newly added escapings, use '_' instead. */
+	 *
+	 * But for newly added escapings, use '_' instead.
+	 * Also, @with_extension is new-style. */
+	const char ESCAPE_CHAR = with_extension ? '_' : '*';
 	const char ESCAPE_CHAR2 = '_';
 
 	g_return_val_if_fail (filename && filename[0], NULL);
@@ -138,7 +201,7 @@ nms_keyfile_utils_escape_filename (const char *filename)
 
 	/* escape_filename() must avoid anything that should_ignore_file() would reject.
 	 * We can escape here more aggressivly then what we would read back. */
-	if (check_prefix (str->str, "."))
+	if (check_prefix_dot (str->str))
 		str->str[0] = ESCAPE_CHAR2;
 	if (check_suffix (str->str, "~"))
 		str->str[str->len - 1] = ESCAPE_CHAR2;
@@ -147,6 +210,9 @@ nms_keyfile_utils_escape_filename (const char *filename)
 	    || check_suffix (str->str, DER_TAG))
 		g_string_append_c (str, ESCAPE_CHAR2);
 
+	if (with_extension)
+		g_string_append (str, NMS_KEYFILE_PATH_SUFFIX_NMCONNECTION);
+
 	return g_string_free (str, FALSE);;
 }
 
diff --git a/src/settings/plugins/keyfile/nms-keyfile-utils.h b/src/settings/plugins/keyfile/nms-keyfile-utils.h
index d5ddb8d5..297dd4ea 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-utils.h
+++ b/src/settings/plugins/keyfile/nms-keyfile-utils.h
@@ -23,16 +23,28 @@
 
 #include "NetworkManagerUtils.h"
 
+#define NM_CONFIG_KEYFILE_PATH_IN_MEMORY NMRUNDIR "/system-connections"
+
+#define NMS_KEYFILE_PATH_SUFFIX_NMCONNECTION      ".nmconnection"
+
 #define NMS_KEYFILE_CONNECTION_LOG_PATH(path)  ((path) ?: "in-memory")
 #define NMS_KEYFILE_CONNECTION_LOG_FMT         "%s (%s,\"%s\")"
 #define NMS_KEYFILE_CONNECTION_LOG_ARG(con)    NMS_KEYFILE_CONNECTION_LOG_PATH (nm_settings_connection_get_filename ((NMSettingsConnection *) (con))), nm_settings_connection_get_uuid ((NMSettingsConnection *) (con)), nm_settings_connection_get_id ((NMSettingsConnection *) (con))
 #define NMS_KEYFILE_CONNECTION_LOG_FMTD        "%s (%s,\"%s\",%p)"
 #define NMS_KEYFILE_CONNECTION_LOG_ARGD(con)   NMS_KEYFILE_CONNECTION_LOG_PATH (nm_settings_connection_get_filename ((NMSettingsConnection *) (con))), nm_settings_connection_get_uuid ((NMSettingsConnection *) (con)), nm_settings_connection_get_id ((NMSettingsConnection *) (con)), (con)
 
-gboolean nms_keyfile_utils_should_ignore_file (const char *filename);
+gboolean nms_keyfile_utils_should_ignore_file (const char *filename, gboolean require_extension);
 
-char *nms_keyfile_utils_escape_filename (const char *filename);
+char *nms_keyfile_utils_escape_filename (const char *filename, gboolean with_extension);
 
 const char *nms_keyfile_utils_get_path (void);
 
+struct stat;
+gboolean nms_keyfile_utils_check_file_permissions_stat (const struct stat *st,
+                                                        GError **error);
+
+gboolean nms_keyfile_utils_check_file_permissions (const char *filename,
+                                                   struct stat *out_st,
+                                                   GError **error);
+
 #endif /* __NMS_KEYFILE_UTILS_H__ */
diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.c b/src/settings/plugins/keyfile/nms-keyfile-writer.c
index 194b97d4..df26ea60 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-writer.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-writer.c
@@ -172,6 +172,8 @@ _handler_write (NMConnection *connection,
 static gboolean
 _internal_write_connection (NMConnection *connection,
                             const char *keyfile_dir,
+                            const char *profile_dir,
+                            gboolean with_extension,
                             uid_t owner_uid,
                             pid_t owner_grp,
                             const char *existing_path,
@@ -189,10 +191,14 @@ _internal_write_connection (NMConnection *connection,
 	WriteInfo info = { 0 };
 	GError *local_err = NULL;
 	int errsv;
+	gboolean rename = force_rename;
 
 	g_return_val_if_fail (!out_path || !*out_path, FALSE);
 	g_return_val_if_fail (keyfile_dir && keyfile_dir[0] == '/', FALSE);
 
+	if (existing_path && !g_str_has_prefix (existing_path, keyfile_dir))
+		rename = TRUE;
+
 	switch (_nm_connection_verify (connection, error)) {
 	case NM_SETTING_VERIFY_NORMALIZABLE:
 		nm_assert_not_reached ();
@@ -221,10 +227,10 @@ _internal_write_connection (NMConnection *connection,
 	/* If we have existing file path, use it. Else generate one from
 	 * connection's ID.
 	 */
-	if (existing_path != NULL && !force_rename) {
+	if (existing_path != NULL && !rename) {
 		path = g_strdup (existing_path);
 	} else {
-		char *filename_escaped = nms_keyfile_utils_escape_filename (id);
+		char *filename_escaped = nms_keyfile_utils_escape_filename (id, with_extension);
 
 		path = g_build_filename (keyfile_dir, filename_escaped, NULL);
 		g_free (filename_escaped);
@@ -250,7 +256,7 @@ _internal_write_connection (NMConnection *connection,
 			else
 				filename = g_strdup_printf ("%s-%s-%u", id, nm_connection_get_uuid (connection), i);
 
-			filename_escaped = nms_keyfile_utils_escape_filename (filename);
+			filename_escaped = nms_keyfile_utils_escape_filename (filename, with_extension);
 
 			g_free (path);
 			path = g_strdup_printf ("%s/%s", keyfile_dir, filename_escaped);
@@ -304,7 +310,7 @@ _internal_write_connection (NMConnection *connection,
 		gs_unref_object NMConnection *reread = NULL;
 		gboolean reread_same = FALSE;
 
-		reread = nms_keyfile_reader_from_keyfile (key_file, path, FALSE, NULL);
+		reread = nms_keyfile_reader_from_keyfile (key_file, path, NULL, profile_dir, FALSE, NULL);
 
 		nm_assert (NM_IS_CONNECTION (reread));
 
@@ -337,6 +343,7 @@ _internal_write_connection (NMConnection *connection,
 
 gboolean
 nms_keyfile_writer_connection (NMConnection *connection,
+                               gboolean save_to_disk,
                                const char *existing_path,
                                gboolean force_rename,
                                char **out_path,
@@ -344,9 +351,19 @@ nms_keyfile_writer_connection (NMConnection *connection,
                                gboolean *out_reread_same,
                                GError **error)
 {
+	const char *keyfile_dir;
+
+	if (save_to_disk)
+		keyfile_dir = nms_keyfile_utils_get_path ();
+	else
+		keyfile_dir = NM_CONFIG_KEYFILE_PATH_IN_MEMORY;
+
 	return _internal_write_connection (connection,
+	                                   keyfile_dir,
 	                                   nms_keyfile_utils_get_path (),
-	                                   0, 0,
+	                                   TRUE,
+	                                   0,
+	                                   0,
 	                                   existing_path,
 	                                   force_rename,
 	                                   out_path,
@@ -367,7 +384,10 @@ nms_keyfile_writer_test_connection (NMConnection *connection,
 {
 	return _internal_write_connection (connection,
 	                                   keyfile_dir,
-	                                   owner_uid, owner_grp,
+	                                   keyfile_dir,
+	                                   FALSE,
+	                                   owner_uid,
+	                                   owner_grp,
 	                                   NULL,
 	                                   FALSE,
 	                                   out_path,
diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.h b/src/settings/plugins/keyfile/nms-keyfile-writer.h
index ac41dfa2..030fb7cc 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-writer.h
+++ b/src/settings/plugins/keyfile/nms-keyfile-writer.h
@@ -25,6 +25,7 @@
 #include "nm-connection.h"
 
 gboolean nms_keyfile_writer_connection (NMConnection *connection,
+                                        gboolean save_to_disk,
                                         const char *existing_path,
                                         gboolean force_rename,
                                         char **out_path,
diff --git a/src/settings/plugins/keyfile/tests/test-keyfile.c b/src/settings/plugins/keyfile/tests/test-keyfile.c
index b4c6b1e2..4a0e01b3 100644
--- a/src/settings/plugins/keyfile/tests/test-keyfile.c
+++ b/src/settings/plugins/keyfile/tests/test-keyfile.c
@@ -65,37 +65,32 @@ check_ip_route (NMSettingIPConfig *config, int idx, const char *destination, int
 	g_assert_cmpint (nm_ip_route_get_metric (route), ==, metric);
 }
 
-static NMConnection *
-keyfile_read_connection_from_file (const char *filename)
-{
-	gs_free_error GError *error = NULL;
-	NMConnection *connection;
-
-	g_assert (filename);
-
-	connection = nms_keyfile_reader_from_file (filename, &error);
-	g_assert_no_error (error);
-
-	nmtst_assert_connection_verifies_without_normalization (connection);
-
-	return connection;
-}
+#define keyfile_read_connection_from_file(full_filename) \
+({ \
+	gs_free_error GError *_error = NULL; \
+	NMConnection *_connection; \
+	\
+	g_assert (full_filename && full_filename[0] == '/'); \
+	\
+	_connection = nms_keyfile_reader_from_file (full_filename, \
+	                                            NULL, \
+	                                            (nmtst_get_rand_int () % 2) ? &_error : NULL); \
+	nmtst_assert_success (_connection, _error); \
+	nmtst_assert_connection_verifies_without_normalization (_connection); \
+	\
+	_connection; \
+})
 
 static void
 assert_reread (NMConnection *connection, gboolean normalize_connection, const char *testfile)
 {
 	gs_unref_object NMConnection *reread = NULL;
 	gs_unref_object NMConnection *connection_clone = NULL;
-	GError *error = NULL;
-	GError **p_error = (nmtst_get_rand_int () % 2) ? &error : NULL;
 	NMSettingConnection *s_con;
 
 	g_assert (NM_IS_CONNECTION (connection));
-	g_assert (testfile && testfile[0]);
 
-	reread = nms_keyfile_reader_from_file (testfile, p_error);
-	g_assert_no_error (error);
-	g_assert (NM_IS_CONNECTION (reread));
+	reread = keyfile_read_connection_from_file (testfile);
 
 	if (   !normalize_connection
 	    && (s_con = nm_connection_get_setting_connection (connection))
@@ -229,10 +224,8 @@ test_read_valid_wired_connection (void)
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
 	NMIPRoute *route;
-	gs_free_error GError *error = NULL;
 	const char *mac;
 	char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
-	gboolean success;
 
 	NMTST_EXPECT_NM_INFO ("*ipv4.addresses:*semicolon at the end*addresses1*");
 	NMTST_EXPECT_NM_INFO ("*ipv4.addresses:*semicolon at the end*addresses2*");
@@ -249,16 +242,9 @@ test_read_valid_wired_connection (void)
 	NMTST_EXPECT_NM_INFO ("*ipv6.address*semicolon at the end*address7*");
 	NMTST_EXPECT_NM_INFO ("*ipv6.routes*semicolon at the end*routes1*");
 	NMTST_EXPECT_NM_INFO ("*ipv6.route*semicolon at the end*route6*");
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Wired_Connection", &error);
-	g_assert_no_error (error);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_Connection");
 	g_test_assert_expected_messages ();
-	g_assert (connection);
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	/* ===== CONNECTION SETTING ===== */
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
 	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Test Wired Connection");
@@ -266,7 +252,6 @@ test_read_valid_wired_connection (void)
 	g_assert_cmpuint (nm_setting_connection_get_timestamp (s_con), ==, 6654332);
 	g_assert (nm_setting_connection_get_autoconnect (s_con));
 
-	/* ===== WIRED SETTING ===== */
 	s_wired = nm_connection_get_setting_wired (connection);
 	g_assert (s_wired);
 
@@ -275,7 +260,6 @@ test_read_valid_wired_connection (void)
 	g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac_address, sizeof (expected_mac_address)));
 	g_assert_cmpint (nm_setting_wired_get_mtu (s_wired), ==, 1400);
 
-	/* ===== IPv4 SETTING ===== */
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
 	g_assert (s_ip4);
 	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_MANUAL);
@@ -324,7 +308,6 @@ test_read_valid_wired_connection (void)
 	nmtst_assert_route_attribute_boolean (route, NM_IP_ROUTE_ATTRIBUTE_LOCK_CWND, TRUE);
 	nmtst_assert_route_attribute_string  (route, NM_IP_ROUTE_ATTRIBUTE_SRC, "7.7.7.7");
 
-	/* ===== IPv6 SETTING ===== */
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
 	g_assert (s_ip6);
 
@@ -535,32 +518,22 @@ test_read_ip6_wired_connection (void)
 	NMSettingWired *s_wired;
 	NMSettingIPConfig *s_ip4;
 	NMSettingIPConfig *s_ip6;
-	gs_free_error GError *error = NULL;
-	gboolean success;
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Wired_Connection_IP6", NULL);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_Connection_IP6");
 
-	/* ===== CONNECTION SETTING ===== */
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
 	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Test Wired Connection IP6");
 	g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, "4e80a56d-c99f-4aad-a6dd-b449bc398c57");
 
-	/* ===== WIRED SETTING ===== */
 	s_wired = nm_connection_get_setting_wired (connection);
 	g_assert (s_wired);
 
-	/* ===== IPv4 SETTING ===== */
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
 	g_assert (s_ip4);
 	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_DISABLED);
 	g_assert_cmpint (nm_setting_ip_config_get_num_addresses (s_ip4), ==, 0);
 
-	/* ===== IPv6 SETTING ===== */
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
 	g_assert (s_ip6);
 	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip6), ==, NM_SETTING_IP6_CONFIG_METHOD_MANUAL);
@@ -638,28 +611,20 @@ test_read_wired_mac_case (void)
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingConnection *s_con;
 	NMSettingWired *s_wired;
-	gs_free_error GError *error = NULL;
 	const char *mac;
 	char expected_mac_address[ETH_ALEN] = { 0x00, 0x11, 0xaa, 0xbb, 0xcc, 0x55 };
-	gboolean success;
 
 	NMTST_EXPECT_NM_INFO ("*ipv4.addresses*semicolon at the end*addresses1*");
 	NMTST_EXPECT_NM_INFO ("*ipv4.addresses*semicolon at the end*addresses2*");
 	NMTST_EXPECT_NM_INFO ("*ipv6.routes*semicolon at the end*routes1*");
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Wired_Connection_MAC_Case", NULL);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_Connection_MAC_Case");
 	g_test_assert_expected_messages ();
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
 
-	/* ===== CONNECTION SETTING ===== */
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
 	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Test Wired Connection MAC Case");
 	g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, "4e80a56d-c99f-4aad-a6dd-b449bc398c57");
 
-	/* ===== WIRED SETTING ===== */
 	s_wired = nm_connection_get_setting_wired (connection);
 	g_assert (s_wired);
 	mac = nm_setting_wired_get_mac_address (s_wired);
@@ -672,29 +637,19 @@ test_read_mac_old_format (void)
 {
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingWired *s_wired;
-	gs_free_error GError *error = NULL;
-	gboolean success;
 	const char *mac;
 	char expected_mac[ETH_ALEN] = { 0x00, 0x11, 0xaa, 0xbb, 0xcc, 0x55 };
 	char expected_cloned_mac[ETH_ALEN] = { 0x00, 0x16, 0xaa, 0xbb, 0xcc, 0xfe };
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_MAC_Old_Format", &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_MAC_Old_Format");
 
 	s_wired = nm_connection_get_setting_wired (connection);
 	g_assert (s_wired);
 
-	/* MAC address */
 	mac = nm_setting_wired_get_mac_address (s_wired);
 	g_assert (mac);
 	g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac, ETH_ALEN));
 
-	/* Cloned MAC address */
 	mac = nm_setting_wired_get_cloned_mac_address (s_wired);
 	g_assert (mac);
 	g_assert (nm_utils_hwaddr_matches (mac, -1, expected_cloned_mac, ETH_ALEN));
@@ -705,20 +660,12 @@ test_read_mac_ib_old_format (void)
 {
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingInfiniband *s_ib;
-	gs_free_error GError *error = NULL;
-	gboolean success;
 	const char *mac;
 	guint8 expected_mac[INFINIBAND_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
-		0x77, 0x88, 0x99, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89,
-		0x90 };
+	    0x77, 0x88, 0x99, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89,
+	    0x90 };
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_MAC_IB_Old_Format", &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_MAC_IB_Old_Format");
 
 	s_ib = nm_connection_get_setting_infiniband (connection);
 	g_assert (s_ib);
@@ -736,18 +683,11 @@ test_read_valid_wireless_connection (void)
 	NMSettingConnection *s_con;
 	NMSettingWireless *s_wireless;
 	NMSettingIPConfig *s_ip4;
-	gs_free_error GError *error = NULL;
 	const char *bssid;
 	const guint8 expected_bssid[ETH_ALEN] = { 0x00, 0x1a, 0x33, 0x44, 0x99, 0x82 };
-	gboolean success;
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Wireless_Connection", NULL);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Wireless_Connection");
 
-	/* ===== CONNECTION SETTING ===== */
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
 	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "Test Wireless Connection");
@@ -755,14 +695,12 @@ test_read_valid_wireless_connection (void)
 	g_assert_cmpuint (nm_setting_connection_get_timestamp (s_con), ==, 1226604314);
 	g_assert (nm_setting_connection_get_autoconnect (s_con) == FALSE);
 
-	/* ===== WIRELESS SETTING ===== */
 	s_wireless = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wireless);
 	bssid = nm_setting_wireless_get_bssid (s_wireless);
 	g_assert (bssid);
 	g_assert (nm_utils_hwaddr_matches (bssid, -1, expected_bssid, sizeof (expected_bssid)));
 
-	/* ===== IPv4 SETTING ===== */
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
 	g_assert (s_ip4);
 	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
@@ -838,24 +776,19 @@ test_read_string_ssid (void)
 {
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingWireless *s_wireless;
-	gs_free_error GError *error = NULL;
 	GBytes *ssid;
 	const guint8 *ssid_data;
 	gsize ssid_len;
 	const char *expected_ssid = "blah blah ssid 1234";
-	gboolean success;
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_String_SSID", NULL);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_String_SSID");
 
-	/* ===== WIRELESS SETTING ===== */
 	s_wireless = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wireless);
+
 	ssid = nm_setting_wireless_get_ssid (s_wireless);
 	g_assert (ssid);
+
 	ssid_data = g_bytes_get_data (ssid, &ssid_len);
 	g_assert_cmpmem (ssid_data, ssid_len, expected_ssid, strlen (expected_ssid));
 }
@@ -922,22 +855,13 @@ test_read_intlist_ssid (void)
 {
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingWireless *s_wifi;
-	gs_free_error GError *error = NULL;
-	gboolean success;
 	GBytes *ssid;
 	const guint8 *ssid_data;
 	gsize ssid_len;
 	const char *expected_ssid = "blah1234";
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Intlist_SSID", &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Intlist_SSID");
 
-	/* SSID */
 	s_wifi = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wifi);
 
@@ -1015,16 +939,10 @@ test_read_intlike_ssid (void)
 {
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingWireless *s_wifi;
-	gs_free_error GError *error = NULL;
-	gboolean success;
 	GBytes *ssid;
 	const char *expected_ssid = "101";
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Intlike_SSID", &error);
-	nmtst_assert_success (connection, error);
-
-	success = nm_connection_verify (connection, &error);
-	nmtst_assert_success (success, error);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Intlike_SSID");
 
 	s_wifi = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wifi);
@@ -1039,16 +957,10 @@ test_read_intlike_ssid_2 (void)
 {
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingWireless *s_wifi;
-	gs_free_error GError *error = NULL;
-	gboolean success;
 	GBytes *ssid;
 	const char *expected_ssid = "11;12;13;";
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Intlike_SSID_2", &error);
-	nmtst_assert_success (connection, error);
-
-	success = nm_connection_verify (connection, &error);
-	nmtst_assert_success (success, error);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Intlike_SSID_2");
 
 	s_wifi = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wifi);
@@ -1183,24 +1095,16 @@ test_read_bt_dun_connection (void)
 	NMSettingBluetooth *s_bluetooth;
 	NMSettingSerial *s_serial;
 	NMSettingGsm *s_gsm;
-	gs_free_error GError *error = NULL;
 	const char *bdaddr;
 	const guint8 expected_bdaddr[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
-	gboolean success;
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/ATT_Data_Connect_BT", NULL);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/ATT_Data_Connect_BT");
 
-	/* ===== CONNECTION SETTING ===== */
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
 	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "AT&T Data Connect BT");
 	g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, "089130ab-ce28-46e4-ad77-d44869b03d19");
 
-	/* ===== BLUETOOTH SETTING ===== */
 	s_bluetooth = nm_connection_get_setting_bluetooth (connection);
 	g_assert (s_bluetooth);
 	bdaddr = nm_setting_bluetooth_get_bdaddr (s_bluetooth);
@@ -1208,14 +1112,12 @@ test_read_bt_dun_connection (void)
 	g_assert (nm_utils_hwaddr_matches (bdaddr, -1, expected_bdaddr, sizeof (expected_bdaddr)));
 	g_assert_cmpstr (nm_setting_bluetooth_get_connection_type (s_bluetooth), ==, NM_SETTING_BLUETOOTH_TYPE_DUN);
 
-	/* ===== GSM SETTING ===== */
 	s_gsm = nm_connection_get_setting_gsm (connection);
 	g_assert (s_gsm);
 	g_assert_cmpstr (nm_setting_gsm_get_apn (s_gsm), ==, "ISP.CINGULAR");
 	g_assert_cmpstr (nm_setting_gsm_get_username (s_gsm), ==, "ISP@CINGULARGPRS.COM");
 	g_assert_cmpstr (nm_setting_gsm_get_password (s_gsm), ==, "CINGULAR1");
 
-	/* ===== SERIAL SETTING ===== */
 	s_serial = nm_connection_get_setting_serial (connection);
 	g_assert (s_serial);
 	g_assert (nm_setting_serial_get_parity (s_serial) == NM_SETTING_SERIAL_PARITY_ODD);
@@ -1288,28 +1190,17 @@ test_read_gsm_connection (void)
 	NMSettingConnection *s_con;
 	NMSettingSerial *s_serial;
 	NMSettingGsm *s_gsm;
-	gs_free_error GError *error = NULL;
-	gboolean success;
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/ATT_Data_Connect_Plain", &error);
-	g_assert_no_error (error);
-	g_assert (connection);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/ATT_Data_Connect_Plain");
 
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
-
-	/* ===== CONNECTION SETTING ===== */
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
 	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, "AT&T Data Connect");
 	g_assert_cmpstr (nm_setting_connection_get_connection_type (s_con), ==, NM_SETTING_GSM_SETTING_NAME);
 
-	/* ===== BLUETOOTH SETTING ===== */
 	/* Plain GSM, so no BT setting expected */
 	g_assert (nm_connection_get_setting_bluetooth (connection) == NULL);
 
-	/* ===== GSM SETTING ===== */
 	s_gsm = nm_connection_get_setting_gsm (connection);
 	g_assert (s_gsm);
 	g_assert_cmpstr (nm_setting_gsm_get_apn (s_gsm), ==, "ISP.CINGULAR");
@@ -1321,7 +1212,6 @@ test_read_gsm_connection (void)
 	g_assert_cmpstr (nm_setting_gsm_get_sim_id (s_gsm), ==, "89148000000060671234");
 	g_assert_cmpstr (nm_setting_gsm_get_sim_operator_id (s_gsm), ==, "310260");
 
-	/* ===== SERIAL SETTING ===== */
 	s_serial = nm_connection_get_setting_serial (connection);
 	g_assert (s_serial);
 	g_assert_cmpint (nm_setting_serial_get_parity (s_serial), ==, NM_SETTING_SERIAL_PARITY_ODD);
@@ -1387,25 +1277,16 @@ test_read_wired_8021x_tls_blob_connection (void)
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingWired *s_wired;
 	NMSetting8021x *s_8021x;
-	gs_free_error GError *error = NULL;
 	const char *tmp;
-	gboolean success;
 	GBytes *blob;
 
 	NMTST_EXPECT_NM_WARN ("keyfile: 802-1x.client-cert: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*");
 	NMTST_EXPECT_NM_WARN ("keyfile: 802-1x.private-key: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*");
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Blob", &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Blob");
 
-	/* ===== Wired Setting ===== */
 	s_wired = nm_connection_get_setting_wired (connection);
 	g_assert (s_wired != NULL);
 
-	/* ===== 802.1x Setting ===== */
 	s_8021x = nm_connection_get_setting_802_1x (connection);
 	g_assert (s_8021x != NULL);
 
@@ -1445,25 +1326,16 @@ test_read_wired_8021x_tls_bad_path_connection (void)
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingWired *s_wired;
 	NMSetting8021x *s_8021x;
-	gs_free_error GError *error = NULL;
 	const char *tmp;
 	char *tmp2;
-	gboolean success;
 
 	NMTST_EXPECT_NM_WARN ("*does not exist*");
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Path_Missing", &error);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Path_Missing");
 	g_test_assert_expected_messages ();
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
 
-	/* ===== Wired Setting ===== */
 	s_wired = nm_connection_get_setting_wired (connection);
 	g_assert (s_wired != NULL);
 
-	/* ===== 802.1x Setting ===== */
 	s_8021x = nm_connection_get_setting_802_1x (connection);
 	g_assert (s_8021x != NULL);
 
@@ -1499,25 +1371,16 @@ test_read_wired_8021x_tls_old_connection (void)
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingWired *s_wired;
 	NMSetting8021x *s_8021x;
-	gs_free_error GError *error = NULL;
 	const char *tmp;
-	gboolean success;
 
 	NMTST_EXPECT_NM_WARN ("keyfile: 802-1x.ca-cert: certificate or key file '/CASA/dcbw/Desktop/certinfra/CA/eaptest_ca_cert.pem' does not exist*");
 	NMTST_EXPECT_NM_WARN ("keyfile: 802-1x.client-cert: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*");
 	NMTST_EXPECT_NM_WARN ("keyfile: 802-1x.private-key: certificate or key file '/CASA/dcbw/Desktop/certinfra/client.pem' does not exist*");
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Old", &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_Old");
 
-	/* ===== Wired Setting ===== */
 	s_wired = nm_connection_get_setting_wired (connection);
 	g_assert (s_wired != NULL);
 
-	/* ===== 802.1x Setting ===== */
 	s_8021x = nm_connection_get_setting_802_1x (connection);
 	g_assert (s_8021x != NULL);
 
@@ -1547,23 +1410,14 @@ test_read_wired_8021x_tls_new_connection (void)
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingWired *s_wired;
 	NMSetting8021x *s_8021x;
-	gs_free_error GError *error = NULL;
 	const char *tmp;
 	char *tmp2;
-	gboolean success;
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_New", &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Wired_TLS_New");
 
-	/* ===== Wired Setting ===== */
 	s_wired = nm_connection_get_setting_wired (connection);
 	g_assert (s_wired != NULL);
 
-	/* ===== 802.1x Setting ===== */
 	s_8021x = nm_connection_get_setting_802_1x (connection);
 	g_assert (s_8021x != NULL);
 
@@ -1684,7 +1538,6 @@ test_write_wired_8021x_tls_connection_path (void)
 	char *tmp, *tmp2;
 	gboolean success;
 	gs_free char *testfile = NULL;
-	gs_free_error GError *error = NULL;
 	gs_unref_keyfile GKeyFile *keyfile = NULL;
 	gboolean relative = FALSE;
 	gboolean reread_same = FALSE;
@@ -1701,12 +1554,7 @@ test_write_wired_8021x_tls_connection_path (void)
 	g_clear_object (&reread);
 
 	/* Read the connection back in and compare it to the one we just wrote out */
-	reread = nms_keyfile_reader_from_file (testfile, &error);
-	if (!reread) {
-		g_assert (error);
-		g_warning ("Failed to re-read test connection: %s", error->message);
-		g_assert (reread);
-	}
+	reread = keyfile_read_connection_from_file (testfile);
 
 	success = nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT);
 	if (!reread) {
@@ -1772,7 +1620,6 @@ test_write_wired_8021x_tls_connection_blob (void)
 	char *new_priv_key;
 	const char *uuid;
 	gboolean reread_same = FALSE;
-	gs_free_error GError *error = NULL;
 	GBytes *password_raw;
 
 #define PASSWORD_RAW "password-raw\0test"
@@ -1817,12 +1664,7 @@ test_write_wired_8021x_tls_connection_blob (void)
 	g_assert (g_file_test (new_priv_key, G_FILE_TEST_EXISTS));
 
 	/* Read the connection back in and compare it to the one we just wrote out */
-	reread = nms_keyfile_reader_from_file (testfile, &error);
-	if (!reread) {
-		g_assert (error);
-		g_warning ("Failed to re-read test connection: %s", error->message);
-		g_assert (reread);
-	}
+	reread = keyfile_read_connection_from_file (testfile);
 
 	/* Ensure the re-read connection's certificates use the path scheme */
 	s_8021x = nm_connection_get_setting_802_1x (reread);
@@ -1862,29 +1704,20 @@ test_read_infiniband_connection (void)
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingConnection *s_con;
 	NMSettingInfiniband *s_ib;
-	gs_free_error GError *error = NULL;
 	const char *mac;
 	guint8 expected_mac[INFINIBAND_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66,
-		0x77, 0x88, 0x99, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89,
-		0x90 };
+	    0x77, 0x88, 0x99, 0x01, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89,
+	    0x90 };
 	const char *expected_id = "Test InfiniBand Connection";
 	const char *expected_uuid = "4e80a56d-c99f-4aad-a6dd-b449bc398c57";
-	gboolean success;
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_InfiniBand_Connection", &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_InfiniBand_Connection");
 
-	/* Connection setting */
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
 	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
 	g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, expected_uuid);
 
-	/* InfiniBand setting */
 	s_ib = nm_connection_get_setting_infiniband (connection);
 	g_assert (s_ib);
 
@@ -1952,31 +1785,21 @@ test_read_bridge_main (void)
 	NMSettingConnection *s_con;
 	NMSettingIPConfig *s_ip4;
 	NMSettingBridge *s_bridge;
-	gs_free_error GError *error = NULL;
 	const char *expected_id = "Test Bridge Main";
 	const char *expected_uuid = "8f061643-fe41-4d4c-a8d9-097d26e2ad3a";
-	gboolean success;
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Bridge_Main", &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Bridge_Main");
 
-	/* Connection setting */
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
 	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
 	g_assert_cmpstr (nm_setting_connection_get_uuid (s_con), ==, expected_uuid);
 	g_assert_cmpstr (nm_setting_connection_get_interface_name (s_con), ==, "br0");
 
-	/* IPv4 setting */
 	s_ip4 = nm_connection_get_setting_ip4_config (connection);
 	g_assert (s_ip4);
 	g_assert_cmpstr (nm_setting_ip_config_get_method (s_ip4), ==, NM_SETTING_IP4_CONFIG_METHOD_AUTO);
 
-	/* Bridge setting */
 	s_bridge = nm_connection_get_setting_bridge (connection);
 	g_assert (s_bridge);
 	g_assert_cmpuint (nm_setting_bridge_get_forward_delay (s_bridge), ==, 2);
@@ -2049,19 +1872,11 @@ test_read_bridge_component (void)
 	NMSettingWired *s_wired;
 	const char *mac;
 	guint8 expected_mac[ETH_ALEN] = { 0x00, 0x22, 0x15, 0x59, 0x62, 0x97 };
-	gs_free_error GError *error = NULL;
 	const char *expected_id = "Test Bridge Component";
 	const char *expected_uuid = "d7b4f96c-c45e-4298-bef8-f48574f8c1c0";
-	gboolean success;
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_Bridge_Component", &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_Bridge_Component");
 
-	/* Connection setting */
 	s_con = nm_connection_get_setting_connection (connection);
 	g_assert (s_con);
 	g_assert_cmpstr (nm_setting_connection_get_id (s_con), ==, expected_id);
@@ -2069,14 +1884,12 @@ test_read_bridge_component (void)
 	g_assert_cmpstr (nm_setting_connection_get_master (s_con), ==, "br0");
 	g_assert (nm_setting_connection_is_slave_type (s_con, NM_SETTING_BRIDGE_SETTING_NAME));
 
-	/* Wired setting */
 	s_wired = nm_connection_get_setting_wired (connection);
 	g_assert (s_wired);
 	mac = nm_setting_wired_get_mac_address (s_wired);
 	g_assert (mac);
 	g_assert (nm_utils_hwaddr_matches (mac, -1, expected_mac, sizeof (expected_mac)));
 
-	/* BridgePort setting */
 	s_port = nm_connection_get_setting_bridge_port (connection);
 	g_assert (s_port);
 	g_assert (nm_setting_bridge_port_get_hairpin_mode (s_port));
@@ -2141,17 +1954,9 @@ test_read_new_wired_group_name (void)
 	NMSettingWired *s_wired;
 	const char *mac;
 	guint8 expected_mac[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 };
-	gs_free_error GError *error = NULL;
-	gboolean success;
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR"/Test_New_Wired_Group_Name", &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_New_Wired_Group_Name");
 
-	/* Wired setting */
 	s_wired = nm_connection_get_setting_wired (connection);
 	g_assert (s_wired);
 	g_assert_cmpint (nm_setting_wired_get_mtu (s_wired), ==, 1400);
@@ -2221,14 +2026,8 @@ test_read_new_wireless_group_names (void)
 	NMSettingWirelessSecurity *s_wsec;
 	GBytes *ssid;
 	const char *expected_ssid = "foobar";
-	gs_free_error GError *error = NULL;
-	gboolean success;
-
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR"/Test_New_Wireless_Group_Names", &error);
-	nmtst_assert_success (connection, error);
 
-	success = nm_connection_verify (connection, &error);
-	nmtst_assert_success (success, error);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_New_Wireless_Group_Names");
 
 	s_wifi = nm_connection_get_setting_wireless (connection);
 	g_assert (s_wifi);
@@ -2323,17 +2122,9 @@ test_read_missing_vlan_setting (void)
 {
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingVlan *s_vlan;
-	gs_free_error GError *error = NULL;
-	gboolean success;
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR"/Test_Missing_Vlan_Setting", &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_Missing_Vlan_Setting");
 
-	/* Ensure the VLAN setting exists */
 	s_vlan = nm_connection_get_setting_vlan (connection);
 	g_assert (s_vlan);
 	g_assert_cmpint (nm_setting_vlan_get_id (s_vlan), ==, 0);
@@ -2345,17 +2136,9 @@ test_read_missing_vlan_flags (void)
 {
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingVlan *s_vlan;
-	gs_free_error GError *error = NULL;
-	gboolean success;
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR"/Test_Missing_Vlan_Flags", &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_Missing_Vlan_Flags");
 
-	/* Ensure the VLAN setting exists */
 	s_vlan = nm_connection_get_setting_vlan (connection);
 	g_assert (s_vlan);
 
@@ -2368,19 +2151,15 @@ static void
 test_read_missing_id_uuid (void)
 {
 	gs_unref_object NMConnection *connection = NULL;
-	gs_free_error GError *error = NULL;
-	gboolean success;
+	gs_free char *expected_uuid = NULL;
+	const char *FILENAME = TEST_KEYFILES_DIR"/Test_Missing_ID_UUID";
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR"/Test_Missing_ID_UUID", &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	expected_uuid = _nm_utils_uuid_generate_from_strings ("keyfile", FILENAME, NULL);
+
+	connection = keyfile_read_connection_from_file (FILENAME);
 
-	/* Ensure the ID and UUID properties are there */
 	g_assert_cmpstr (nm_connection_get_id (connection), ==, "Test_Missing_ID_UUID");
-	g_assert (nm_connection_get_uuid (connection));
+	g_assert_cmpstr (nm_connection_get_uuid (connection), ==, expected_uuid);
 }
 
 static void
@@ -2468,17 +2247,9 @@ test_read_enum_property (void)
 {
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingIPConfig *s_ip6;
-	gs_free_error GError *error = NULL;
-	gboolean success;
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR"/Test_Enum_Property", &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_Enum_Property");
 
-	/* IPv6 setting */
 	s_ip6 = nm_connection_get_setting_ip6_config (connection);
 	g_assert (s_ip6);
 	g_assert_cmpint (nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (s_ip6)), ==, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR);
@@ -2528,17 +2299,9 @@ test_read_flags_property (void)
 {
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingGsm *s_gsm;
-	gs_free_error GError *error = NULL;
-	gboolean success;
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR"/Test_Flags_Property", &error);
-	g_assert_no_error (error);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR"/Test_Flags_Property");
 
-	/* GSM setting */
 	s_gsm = nm_connection_get_setting_gsm (connection);
 	g_assert (s_gsm);
 	g_assert_cmpint (nm_setting_gsm_get_password_flags (s_gsm), ==,
@@ -2591,14 +2354,8 @@ test_read_tc_config (void)
 	NMTCQdisc *qdisc1, *qdisc2;
 	NMTCAction *action1, *action2;
 	NMTCTfilter *tfilter1, *tfilter2;
-	gs_free_error GError *error = NULL;
-	gboolean success;
 
-	connection = nms_keyfile_reader_from_file (TEST_KEYFILES_DIR "/Test_TC_Config", NULL);
-	g_assert (connection);
-	success = nm_connection_verify (connection, &error);
-	g_assert_no_error (error);
-	g_assert (success);
+	connection = keyfile_read_connection_from_file (TEST_KEYFILES_DIR "/Test_TC_Config");
 
 	s_tc = nm_connection_get_setting_tc_config (connection);
 	g_assert (s_tc);
@@ -2703,49 +2460,51 @@ test_write_tc_config (void)
 /*****************************************************************************/
 
 static void
-_escape_filename (const char *filename, gboolean would_be_ignored)
+_escape_filename (gboolean with_extension, const char *filename, gboolean would_be_ignored)
 {
 	gs_free char *esc = NULL;
 
 	g_assert (filename && filename[0]);
 
-	if (!!would_be_ignored != !!nms_keyfile_utils_should_ignore_file (filename)) {
+	if (!!would_be_ignored != !!nms_keyfile_utils_should_ignore_file (filename, with_extension)) {
 		if (would_be_ignored)
 			g_error ("We expect filename \"%s\" to be ignored, but it isn't", filename);
 		else
 			g_error ("We expect filename \"%s\" not to be ignored, but it is", filename);
 	}
 
-	esc = nms_keyfile_utils_escape_filename (filename);
+	esc = nms_keyfile_utils_escape_filename (filename, with_extension);
 	g_assert (esc && esc[0]);
 	g_assert (!strchr (esc, '/'));
 
-	if (nms_keyfile_utils_should_ignore_file (esc))
+	if (nms_keyfile_utils_should_ignore_file (esc, with_extension))
 		g_error ("Escaping filename \"%s\" yielded \"%s\", but this is ignored", filename, esc);
 }
 
 static void
 test_nm_keyfile_plugin_utils_escape_filename (void)
 {
-	_escape_filename ("ab", FALSE);
-	_escape_filename (".vim-file.swp", TRUE);
-	_escape_filename (".vim-file.Swp", TRUE);
-	_escape_filename (".vim-file.SWP", TRUE);
-	_escape_filename (".vim-file.swpx", TRUE);
-	_escape_filename (".vim-file.Swpx", TRUE);
-	_escape_filename (".vim-file.SWPX", TRUE);
-	_escape_filename (".pem-file.pem", TRUE);
-	_escape_filename (".pem-file.Pem", TRUE);
-	_escape_filename (".pem-file.PEM", TRUE);
-	_escape_filename (".pem-file.der", TRUE);
-	_escape_filename (".pem-file.Der", TRUE);
-	_escape_filename (".mkstemp.ABCEDF", TRUE);
-	_escape_filename (".mkstemp.abcdef", TRUE);
-	_escape_filename (".mkstemp.123456", TRUE);
-	_escape_filename (".mkstemp.A23456", TRUE);
-	_escape_filename (".#emacs-locking", TRUE);
-	_escape_filename ("file-with-tilde~", TRUE);
-	_escape_filename (".file-with-dot", TRUE);
+	_escape_filename (FALSE, "ab", FALSE);
+	_escape_filename (FALSE, ".vim-file.swp", TRUE);
+	_escape_filename (FALSE, ".vim-file.Swp", TRUE);
+	_escape_filename (FALSE, ".vim-file.SWP", TRUE);
+	_escape_filename (FALSE, ".vim-file.swpx", TRUE);
+	_escape_filename (FALSE, ".vim-file.Swpx", TRUE);
+	_escape_filename (FALSE, ".vim-file.SWPX", TRUE);
+	_escape_filename (FALSE, ".pem-file.pem", TRUE);
+	_escape_filename (FALSE, ".pem-file.Pem", TRUE);
+	_escape_filename (FALSE, ".pem-file.PEM", TRUE);
+	_escape_filename (FALSE, ".pem-file.der", TRUE);
+	_escape_filename (FALSE, ".pem-file.Der", TRUE);
+	_escape_filename (FALSE, ".mkstemp.ABCEDF", TRUE);
+	_escape_filename (FALSE, ".mkstemp.abcdef", TRUE);
+	_escape_filename (FALSE, ".mkstemp.123456", TRUE);
+	_escape_filename (FALSE, ".mkstemp.A23456", TRUE);
+	_escape_filename (FALSE, ".#emacs-locking", TRUE);
+	_escape_filename (FALSE, "file-with-tilde~", TRUE);
+	_escape_filename (FALSE, ".file-with-dot", TRUE);
+
+	_escape_filename (TRUE, "lala", TRUE);
 }
 
 /*****************************************************************************/