summary refs log tree commit diff
path: root/libnm-core/nm-keyfile.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2018-09-23 10:10:27 +0200
committerMichael Biebl <biebl@debian.org>2018-09-23 10:10:27 +0200
commite126f3e804c35480c4f075777430419d6ece23da (patch)
tree5d5821ebcda8cd6ac34d2483bb3354910e508930 /libnm-core/nm-keyfile.c
parentc240974325c552cad177c457d6ff04e381fd77a3 (diff)
New upstream version 1.12.4 upstream/1.12.4
Diffstat (limited to 'libnm-core/nm-keyfile.c')
-rw-r--r--libnm-core/nm-keyfile.c453
1 files changed, 111 insertions, 342 deletions
diff --git a/libnm-core/nm-keyfile.c b/libnm-core/nm-keyfile.c
index c7d87869..c894e250 100644
--- a/libnm-core/nm-keyfile.c
+++ b/libnm-core/nm-keyfile.c
@@ -33,7 +33,6 @@
 #include <string.h>
 #include <linux/pkt_sched.h>
 
-#include "nm-utils/nm-secret-utils.h"
 #include "nm-common-macros.h"
 #include "nm-core-internal.h"
 #include "nm-keyfile-utils.h"
@@ -120,49 +119,6 @@ setting_alias_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *k
 }
 
 static void
-sriov_vfs_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
-{
-	const char *setting_name = nm_setting_get_name (setting);
-	gs_unref_ptrarray GPtrArray *vfs = NULL;
-	gs_strfreev char **keys = NULL;
-	gsize n_keys = 0;
-	int i;
-
-	keys = nm_keyfile_plugin_kf_get_keys (info->keyfile, setting_name, &n_keys, NULL);
-	if (!keys || n_keys == 0)
-		return;
-
-	vfs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_sriov_vf_unref);
-
-	for (i = 0; i < n_keys; i++) {
-		gs_free char *value = NULL;
-		NMSriovVF *vf;
-		const char *rest;
-
-		if (!g_str_has_prefix (keys[i], "vf."))
-			continue;
-
-		rest = &keys[i][3];
-
-		if (!NM_STRCHAR_ALL (rest, ch, g_ascii_isdigit (ch)))
-			continue;
-
-		value = nm_keyfile_plugin_kf_get_string (info->keyfile,
-		                                         setting_name,
-		                                         keys[i],
-		                                         NULL);
-
-		vf = _nm_utils_sriov_vf_from_strparts (rest, value, NULL);
-		if (vf)
-			g_ptr_array_add (vfs, vf);
-	}
-
-	g_object_set (G_OBJECT (setting),
-	              key, vfs,
-	              NULL);
-}
-
-static void
 read_array_of_uint (GKeyFile *file,
                     NMSetting *setting,
                     const char *key)
@@ -775,7 +731,7 @@ ip6_addr_gen_mode_parser (KeyfileReaderInfo *info, NMSetting *setting, const cha
 	} else
 		addr_gen_mode = NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE_EUI64;
 
-	g_object_set (G_OBJECT (setting), key, (int) addr_gen_mode, NULL);
+	g_object_set (G_OBJECT (setting), key, (gint) addr_gen_mode, NULL);
 }
 
 static void
@@ -940,7 +896,7 @@ unescape_semicolons (char *str)
 			i++;
 		str[j++] = str[i++];;
 	}
-	nm_explicit_bzero (&str[j], i - j);
+	str[j] = '\0';
 	return j;
 }
 
@@ -951,10 +907,9 @@ get_bytes (KeyfileReaderInfo *info,
            gboolean zero_terminate,
            gboolean unescape_semicolon)
 {
-	nm_auto_free_secret char *tmp_string = NULL;
+	gs_free char *tmp_string = NULL;
 	gboolean may_be_int_list = TRUE;
 	gsize length;
-	GBytes *result;
 
 	/* New format: just a string
 	 * Old format: integer list; e.g. 11;25;38;
@@ -988,11 +943,12 @@ get_bytes (KeyfileReaderInfo *info,
 
 	/* Try to parse the string as a integer list. */
 	if (may_be_int_list && length > 0) {
-		nm_auto_free_secret_buf NMSecretBuf *bin = NULL;
+		gs_free guint8 *bin_data = NULL;
 		const char *const s = tmp_string;
 		gsize i, d;
+		const gsize BIN_DATA_LEN = (length / 2 + 3);
 
-		bin = nm_secret_buf_new (length / 2 + 3);
+		bin_data = g_malloc (BIN_DATA_LEN);
 
 #define DIGIT(c) ((c) - '0')
 		i = 0;
@@ -1025,8 +981,8 @@ get_bytes (KeyfileReaderInfo *info,
 				break;
 			}
 
-			nm_assert (d < bin->len);
-			bin->bin[d++] = n;
+			bin_data[d++] = n;
+			nm_assert (d < BIN_DATA_LEN);
 
 			/* allow whitespace after the digit. */
 			while (g_ascii_isspace (s[i]))
@@ -1044,23 +1000,16 @@ get_bytes (KeyfileReaderInfo *info,
 		 * string format before. We expect that this conversion cannot fail. */
 		if (d > 0) {
 			/* note that @zero_terminate does not add a terminating '\0' to
-			 * binary data as an integer list. If the bytes are expressed as
-			 * an integer list, all potential NUL characters are supposed to
-			 * be included there explicitly.
+			 * binary data as an integer list.
 			 *
-			 * However, in the spirit of defensive programming, we do append a
-			 * NUL character to the buffer, although this character is hidden
-			 * and only a mitigation for bugs. */
-
-			if (d + 10 < bin->len) {
-				/* hm, too much unused memory. Copy the memory to a suitable
-				 * sized buffer. */
-				return nm_secret_copy_to_gbytes (bin->bin, d);
-			}
-
-			nm_assert (d < bin->len);
-			bin->bin[d] = '\0';
-			return nm_secret_buf_to_gbytes_take (g_steal_pointer (&bin), d);
+			 * But we add a '\0' to the bin_data pointer, just to avoid somebody
+			 * (erronously!) reading the binary data as C-string.
+			 *
+			 * @d itself does not entail the '\0'. */
+			nm_assert (d + 1 <= BIN_DATA_LEN);
+			bin_data = g_realloc (bin_data, d + 1);
+			bin_data[d] = '\0';
+			return g_bytes_new_take (g_steal_pointer (&bin_data), d);
 		}
 	}
 
@@ -1071,13 +1020,8 @@ get_bytes (KeyfileReaderInfo *info,
 		length++;
 	if (length == 0)
 		return NULL;
-
-	result = g_bytes_new_with_free_func (tmp_string,
-	                                     length,
-	                                     (GDestroyNotify) nm_free_secret,
-	                                     tmp_string);
-	tmp_string = NULL;
-	return result;
+	tmp_string = g_realloc (tmp_string, length + (zero_terminate ? 0 : 1));
+	return g_bytes_new_take (g_steal_pointer (&tmp_string), length);
 }
 
 static void
@@ -1121,12 +1065,12 @@ get_cert_path (const char *base_dir, const guint8 *cert_path, gsize cert_path_le
 	g_return_val_if_fail (base_dir != NULL, NULL);
 	g_return_val_if_fail (cert_path != NULL, NULL);
 
-	path = g_strndup ((char *) cert_path, cert_path_len);
+	base = path = g_malloc0 (cert_path_len + 1);
+	memcpy (path, cert_path, cert_path_len);
 
 	if (path[0] == '/')
 		return path;
 
-	base = path;
 	p = strrchr (path, '/');
 	if (p)
 		base = p + 1;
@@ -1160,9 +1104,8 @@ nm_keyfile_detect_unqualified_path_scheme (const char *base_dir,
 	const char *data = pdata;
 	gboolean exists = FALSE;
 	gsize validate_len;
-	gsize path_len, pathuri_len;
 	gs_free char *path = NULL;
-	gs_free char *pathuri = NULL;
+	GByteArray *tmp;
 
 	g_return_val_if_fail (base_dir && base_dir[0] == '/', NULL);
 
@@ -1205,16 +1148,18 @@ nm_keyfile_detect_unqualified_path_scheme (const char *base_dir,
 	 * When returning TRUE, we must also be sure that @data_len does not look like
 	 * the deprecated format of list of integers. With this implementation that is the
 	 * case, as long as @consider_exists is FALSE. */
-	path_len = strlen (path);
-	pathuri_len = (NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH) + 1) + path_len;
-	pathuri = g_new (char, pathuri_len);
-	memcpy (pathuri, NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH));
-	memcpy (&pathuri[NM_STRLEN (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH)], path, path_len + 1);
-	if (nm_setting_802_1x_check_cert_scheme (pathuri, pathuri_len, NULL) != NM_SETTING_802_1X_CK_SCHEME_PATH)
+	tmp = g_byte_array_sized_new (strlen (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH) + strlen (path) + 1);
+	g_byte_array_append (tmp, (const guint8 *) NM_KEYFILE_CERT_SCHEME_PREFIX_PATH, strlen (NM_KEYFILE_CERT_SCHEME_PREFIX_PATH));
+	g_byte_array_append (tmp, (const guint8 *) path, strlen (path) + 1);
+	if (nm_setting_802_1x_check_cert_scheme (tmp->data, tmp->len, NULL) != NM_SETTING_802_1X_CK_SCHEME_PATH) {
+		g_byte_array_unref (tmp);
 		return NULL;
+	}
+	g_free (path);
+	path = (char *) g_byte_array_free (tmp, FALSE);
 
 	NM_SET_OUT (out_exists, exists);
-	return g_steal_pointer (&pathuri);
+	return g_steal_pointer (&path);
 }
 
 #define HAS_SCHEME_PREFIX(bin, bin_len, scheme) \
@@ -1448,7 +1393,7 @@ qdisc_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
 {
 	const char *setting_name = nm_setting_get_name (setting);
 	GPtrArray *qdiscs;
-	gs_strfreev char **keys = NULL;
+	gs_strfreev gchar **keys = NULL;
 	gsize n_keys = 0;
 	int i;
 
@@ -1496,7 +1441,7 @@ tfilter_parser (KeyfileReaderInfo *info, NMSetting *setting, const char *key)
 {
 	const char *setting_name = nm_setting_get_name (setting);
 	GPtrArray *tfilters;
-	gs_strfreev char **keys = NULL;
+	gs_strfreev gchar **keys = NULL;
 	gsize n_keys = 0;
 	int i;
 
@@ -1565,37 +1510,6 @@ setting_alias_writer (KeyfileWriterInfo *info,
 }
 
 static void
-sriov_vfs_writer (KeyfileWriterInfo *info,
-                  NMSetting *setting,
-                  const char *key,
-                  const GValue *value)
-{
-	GPtrArray *vfs;
-	guint i;
-
-	vfs = g_value_get_boxed (value);
-	if (!vfs)
-		return;
-
-	for (i = 0; i < vfs->len; i++) {
-		const NMSriovVF *vf = vfs->pdata[i];
-		gs_free char *kf_value = NULL;
-		char kf_key[32];
-
-		kf_value = nm_utils_sriov_vf_to_str (vf, TRUE, NULL);
-		if (!kf_value)
-			continue;
-
-		nm_sprintf_buf (kf_key, "vf.%u", nm_sriov_vf_get_index (vf));
-
-		nm_keyfile_plugin_kf_set_string (info->keyfile,
-		                                 nm_setting_get_name (setting),
-		                                 kf_key,
-		                                 kf_value);
-	}
-}
-
-static void
 write_array_of_uint (GKeyFile *file,
                      NMSetting *setting,
                      const char *key,
@@ -1611,7 +1525,7 @@ write_array_of_uint (GKeyFile *file,
 
 	g_return_if_fail (g_array_get_element_size (array) == sizeof (guint));
 
-	tmp_array = g_new (int, array->len);
+	tmp_array = g_new (gint, array->len);
 	for (i = 0; i < array->len; i++) {
 		guint v = g_array_index (array, guint, i);
 
@@ -2108,16 +2022,18 @@ typedef struct {
 	})
 
 typedef struct {
+	const char *setting_name;
 	const ParseInfoProperty*const*properties;
 } ParseInfoSetting;
 
-#define PARSE_INFO_SETTING(setting_type, ...) \
-	[setting_type] = (&((const ParseInfoSetting) { \
+#define PARSE_INFO_SETTING(_setting_name, ...) \
+	{ \
+		.setting_name = _setting_name, \
 		__VA_ARGS__ \
-	}))
+	}
 
-static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_WIRELESS,
+static const ParseInfoSetting parse_infos[] = {
+	PARSE_INFO_SETTING (NM_SETTING_WIRELESS_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_WIRELESS_BSSID,
 				.parser        = mac_address_parser_ETHER,
@@ -2134,7 +2050,7 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_802_1X,
+	PARSE_INFO_SETTING (NM_SETTING_802_1X_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_802_1X_CA_CERT,
 				.parser        = cert_parser,
@@ -2166,7 +2082,7 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_WIRED,
+	PARSE_INFO_SETTING (NM_SETTING_WIRED_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_WIRED_CLONED_MAC_ADDRESS,
 				.parser        = mac_address_parser_ETHER_cloned,
@@ -2176,28 +2092,28 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_BLUETOOTH,
+	PARSE_INFO_SETTING (NM_SETTING_BLUETOOTH_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_BLUETOOTH_BDADDR,
 				.parser        = mac_address_parser_ETHER,
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_BOND,
+	PARSE_INFO_SETTING (NM_SETTING_BOND_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_BOND_OPTIONS,
 				.parser_no_check_key = TRUE,
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_BRIDGE,
+	PARSE_INFO_SETTING (NM_SETTING_BRIDGE_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_BRIDGE_MAC_ADDRESS,
 				.parser        = mac_address_parser_ETHER,
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_CONNECTION,
+	PARSE_INFO_SETTING (NM_SETTING_CONNECTION_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_CONNECTION_READ_ONLY,
 				.parser_skip   = TRUE,
@@ -2209,14 +2125,14 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_INFINIBAND,
+	PARSE_INFO_SETTING (NM_SETTING_INFINIBAND_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_INFINIBAND_MAC_ADDRESS,
 				.parser        = mac_address_parser_INFINIBAND,
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_IP4_CONFIG,
+	PARSE_INFO_SETTING (NM_SETTING_IP4_CONFIG_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_IP_CONFIG_ADDRESSES,
 				.parser_no_check_key = TRUE,
@@ -2238,7 +2154,7 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_IP6_CONFIG,
+	PARSE_INFO_SETTING (NM_SETTING_IP6_CONFIG_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_IP6_CONFIG_ADDR_GEN_MODE,
 				.parser_no_check_key = TRUE,
@@ -2266,23 +2182,14 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_SERIAL,
+	PARSE_INFO_SETTING (NM_SETTING_SERIAL_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_SERIAL_PARITY,
 				.parser        = parity_parser,
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_SRIOV,
-		PARSE_INFO_PROPERTIES (
-			PARSE_INFO_PROPERTY (NM_SETTING_SRIOV_VFS,
-				.parser_no_check_key = TRUE,
-				.parser        = sriov_vfs_parser,
-				.writer        = sriov_vfs_writer,
-			),
-		),
-	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_TC_CONFIG,
+	PARSE_INFO_SETTING (NM_SETTING_TC_CONFIG_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_TC_CONFIG_QDISCS,
 				.parser_no_check_key = TRUE,
@@ -2296,7 +2203,7 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_TEAM,
+	PARSE_INFO_SETTING (NM_SETTING_TEAM_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_TEAM_CONFIG,
 				.parser        = team_config_parser,
@@ -2363,7 +2270,7 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_TEAM_PORT,
+	PARSE_INFO_SETTING (NM_SETTING_TEAM_PORT_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_TEAM_CONFIG,
 				.parser        = team_config_parser,
@@ -2394,21 +2301,21 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_USER,
+	PARSE_INFO_SETTING (NM_SETTING_USER_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_USER_DATA,
 				.parser_no_check_key = TRUE,
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_VLAN,
+	PARSE_INFO_SETTING (NM_SETTING_VLAN_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_VLAN_FLAGS,
 				.writer_persist_default = TRUE,
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_VPN,
+	PARSE_INFO_SETTING (NM_SETTING_VPN_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_VPN_DATA,
 				.parser_no_check_key = TRUE,
@@ -2430,7 +2337,7 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 			),
 		),
 	),
-	PARSE_INFO_SETTING (NM_META_SETTING_TYPE_WIMAX,
+	PARSE_INFO_SETTING (NM_SETTING_WIMAX_SETTING_NAME,
 		PARSE_INFO_PROPERTIES (
 			PARSE_INFO_PROPERTY (NM_SETTING_WIMAX_MAC_ADDRESS,
 				.parser        = mac_address_parser_ETHER,
@@ -2440,24 +2347,21 @@ static const ParseInfoSetting *const parse_infos[_NM_META_SETTING_TYPE_NUM] = {
 };
 
 static const ParseInfoProperty *
-_parse_info_find (NMSetting *setting,
-                  const char *property_name,
-                  const char **out_setting_name)
+_parse_info_find (const char *setting_name, const char *property_name)
 {
-	const NMMetaSettingInfo *setting_info;
-	const ParseInfoSetting *pis;
 	gssize idx;
 
-#if NM_MORE_ASSERTS > 10
+#if NM_MORE_ASSERTS > 5
 	{
 		guint i, j;
 
 		for (i = 0; i < G_N_ELEMENTS (parse_infos); i++) {
-			pis = parse_infos[i];
-
-			if (!pis)
-				continue;
+			const ParseInfoSetting *pis = &parse_infos[i];
 
+			g_assert (pis->setting_name);
+			if (   i > 0
+				&& strcmp (pis[-1].setting_name, pis->setting_name) >= 0)
+				g_error ("Wrong order at index #%d: \"%s\" before \"%s\"", i - 1, pis[-1].setting_name, pis->setting_name);
 			g_assert (pis->properties);
 			g_assert (pis->properties[0]);
 			for (j = 0; pis->properties[j]; j++) {
@@ -2467,35 +2371,31 @@ _parse_info_find (NMSetting *setting,
 				g_assert (pip->property_name);
 				if (   j > 0
 				    && (pip0 = pis->properties[j - 1])
-				    && strcmp (pip0->property_name, pip->property_name) >= 0) {
-					g_error ("Wrong order at index #%d.%d: \"%s.%s\" before \"%s.%s\"",
-					         i, j - 1,
-					         nm_meta_setting_infos[i].setting_name, pip0->property_name,
-					         nm_meta_setting_infos[i].setting_name, pip->property_name);
-				}
+				    && strcmp (pip0->property_name, pip->property_name) >= 0)
+					g_error ("Wrong order at index #%d.%d: \"%s.%s\" before \"%s.%s\"", i, j - 1, pis->setting_name, pip0->property_name, pis->setting_name, pip->property_name);
 			}
 		}
 	}
 #endif
 
-	if (   !NM_IS_SETTING (setting)
-	    || !(setting_info = NM_SETTING_GET_CLASS (setting)->setting_info)) {
-		/* handle invalid setting objects gracefully. */
-		*out_setting_name = NULL;
-		return NULL;
-	}
-
-	*out_setting_name = setting_info->setting_name;
-
-	if ((pis = parse_infos[setting_info->meta_type])) {
-		G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (ParseInfoProperty, property_name) == 0);
-		idx = nm_utils_ptrarray_find_binary_search ((gconstpointer *) pis->properties,
-		                                            NM_PTRARRAY_LEN (pis->properties),
-		                                            &property_name,
-		                                            nm_strcmp_p_with_data,
-		                                            NULL,
-		                                            NULL,
-		                                            NULL);
+	G_STATIC_ASSERT_EXPR (G_STRUCT_OFFSET (ParseInfoSetting, setting_name) == 0);
+	idx = _nm_utils_array_find_binary_search (parse_infos,
+	                                          sizeof (ParseInfoSetting),
+	                                          G_N_ELEMENTS (parse_infos),
+	                                          &setting_name,
+	                                          nm_strcmp_p_with_data,
+	                                          NULL);
+	if (idx >= 0) {
+		const ParseInfoSetting *pis = &parse_infos[idx];
+
+		nm_assert (nm_streq (pis->setting_name, setting_name));
+		idx = _nm_utils_ptrarray_find_binary_search ((gconstpointer *) pis->properties,
+		                                             NM_PTRARRAY_LEN (pis->properties),
+		                                             &property_name,
+		                                             nm_strcmp_p_with_data,
+		                                             NULL,
+		                                             NULL,
+		                                             NULL);
 		if (idx >= 0)
 			return pis->properties[idx];
 	}
@@ -2526,9 +2426,9 @@ read_one_setting_value (NMSetting *setting,
 	if (!(flags & G_PARAM_WRITABLE))
 		return;
 
-	pip = _parse_info_find (setting, key, &setting_name);
+	setting_name = nm_setting_get_name (setting);
 
-	nm_assert (setting_name);
+	pip = _parse_info_find (setting_name, key);
 
 	if (   !pip
 	    && nm_streq (key, NM_SETTING_NAME))
@@ -2621,7 +2521,7 @@ read_one_setting_value (NMSetting *setting,
 		} else
 			g_object_set (setting, key, int_val, NULL);
 	} else if (type == G_TYPE_BYTES) {
-		int *tmp;
+		gint *tmp;
 		GByteArray *array;
 		GBytes *bytes;
 		gsize length;
@@ -2654,7 +2554,7 @@ read_one_setting_value (NMSetting *setting,
 		g_bytes_unref (bytes);
 		g_free (tmp);
 	} else if (type == G_TYPE_STRV) {
-		char **sa;
+		gchar **sa;
 		gsize length;
 
 		sa = nm_keyfile_plugin_kf_get_string_list (keyfile, setting_name, key, &length, NULL);
@@ -2680,11 +2580,11 @@ read_one_setting_value (NMSetting *setting,
 			}
 		}
 	} else if (G_VALUE_HOLDS_ENUM (value)) {
-		int int_val;
+		gint int_val;
 
 		int_val = nm_keyfile_plugin_kf_get_integer (keyfile, setting_name, key, &err);
 		if (!err)
-			g_object_set (setting, key, (int) int_val, NULL);
+			g_object_set (setting, key, (gint) int_val, NULL);
 	} else {
 		if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
 		                 _("unhandled setting property type '%s'"),
@@ -2696,8 +2596,6 @@ read_one_setting_value (NMSetting *setting,
 static NMSetting *
 read_setting (KeyfileReaderInfo *info)
 {
-	const NMSettInfoSetting *sett_info;
-	gs_unref_object NMSetting *setting = NULL;
 	const char *alias;
 	GType type;
 
@@ -2706,92 +2604,22 @@ read_setting (KeyfileReaderInfo *info)
 		alias = info->group;
 
 	type = nm_setting_lookup_type (alias);
-	if (!type) {
-		handle_warn (info, NULL, NM_KEYFILE_WARN_SEVERITY_WARN,
-		             _("invalid setting name '%s'"), info->group);
-		return NULL;
-	}
+	if (type) {
+		NMSetting *setting = g_object_new (type, NULL);
 
-	setting = g_object_new (type, NULL);
-
-	info->setting = setting;
-
-	sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting));
-
-	if (sett_info->detail.gendata_info) {
-		gs_free char **keys = NULL;
-		gsize i, n_keys;
-
-		keys = g_key_file_get_keys (info->keyfile, info->group, &n_keys, NULL);
-		if (n_keys > 0) {
-			GHashTable *h = _nm_setting_gendata_hash (setting, TRUE);
-
-			nm_utils_strv_sort (keys, n_keys);
-			for (i = 0; i < n_keys; i++) {
-				gs_free char *key = keys[i];
-				gs_free_error GError *local = NULL;
-				const GVariantType *variant_type;
-				GVariant *variant;
-
-				/* a GKeyfile can return duplicate keys, there is just no API to make sense
-				 * of them. Skip them. */
-				if (   i + 1 < n_keys
-				    && nm_streq (key, keys[i + 1]))
-					continue;
-
-				/* currently, the API is very simple. The setting class just returns
-				 * the desired variant type, and keyfile reader will try to parse
-				 * it accordingly. Note, that this does currently not allow, that
-				 * a particular key can contain different variant types, nor is it
-				 * very flexible in general.
-				 *
-				 * We add flexibility when we need it. Keep it simple for now. */
-				variant_type = sett_info->detail.gendata_info->get_variant_type (sett_info,
-				                                                                 key,
-				                                                                 &local);
-				if (!variant_type) {
-					if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
-					                  _("invalid key '%s.%s'"),
-					                  info->group, key))
-						break;
-					continue;
-				}
-
-				if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_BOOLEAN)) {
-					gboolean v;
-
-					v = g_key_file_get_boolean (info->keyfile,
-					                            info->group,
-					                            key,
-					                            &local);
-					if (local) {
-						if (!handle_warn (info, key, NM_KEYFILE_WARN_SEVERITY_WARN,
-						                  _("key '%s.%s' is not boolean"),
-						                  info->group, key))
-							break;
-						continue;
-					}
-					variant = g_variant_new_boolean (v);
-				} else {
-					nm_assert_not_reached ();
-					continue;
-				}
-
-				g_hash_table_insert (h,
-				                     g_steal_pointer (&key),
-				                     g_variant_take_ref (variant));
-			}
-			for (; i < n_keys; i++)
-				g_free (keys[i]);
-		}
-	} else
+		info->setting = setting;
 		nm_setting_enumerate_values (setting, read_one_setting_value, info);
+		info->setting = NULL;
+		if (!info->error)
+			return setting;
 
-	info->setting = NULL;
+		g_object_unref (setting);
+	} else {
+		handle_warn (info, NULL, NM_KEYFILE_WARN_SEVERITY_WARN,
+		             _("invalid setting name '%s'"), info->group);
+	}
 
-	if (info->error)
-		return NULL;
-	return g_steal_pointer (&setting);
+	return NULL;
 }
 
 static void
@@ -2846,7 +2674,7 @@ nm_keyfile_read (GKeyFile *keyfile,
 	gs_unref_object NMConnection *connection = NULL;
 	NMSettingConnection *s_con;
 	NMSetting *setting;
-	char **groups;
+	gchar **groups;
 	gsize length;
 	int i;
 	gboolean vpn_secrets = FALSE;
@@ -2866,7 +2694,7 @@ nm_keyfile_read (GKeyFile *keyfile,
 			base_dir = base_dir_free = g_get_current_dir ();
 		}
 	} else
-		g_return_val_if_fail (base_dir[0] == '/', NULL);
+		g_return_val_if_fail ("/", NULL);
 
 	connection = nm_simple_connection_new ();
 
@@ -2972,22 +2800,12 @@ write_setting_value (NMSetting *setting,
 	if (info->error)
 		return;
 
+	setting_name = nm_setting_get_name (setting);
+
 	pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key);
 	nm_assert (pspec);
 
-	pip = _parse_info_find (setting, key, &setting_name);
-
-	if (!setting_name) {
-		/* the setting type is unknown. That is highly unexpected
-		 * (and as this is currently only called from NetworkManager
-		 * daemon, not possible).
-		 *
-		 * Still, handle it gracefully, because later keyfile writer will become
-		 * public API of libnm, where @setting is (untrusted) user input.
-		 *
-		 * Gracefully here just means: ignore the setting. */
-		return;
-	}
+	pip = _parse_info_find (setting_name, key);
 
 	if (   !pip
 	    && nm_streq (key, NM_SETTING_NAME))
@@ -3061,7 +2879,7 @@ write_setting_value (NMSetting *setting,
 		char **array;
 
 		array = (char **) g_value_get_boxed (value);
-		nm_keyfile_plugin_kf_set_string_list (info->keyfile, setting_name, key, (const char **const) array, g_strv_length (array));
+		nm_keyfile_plugin_kf_set_string_list (info->keyfile, setting_name, key, (const gchar **const) array, g_strv_length (array));
 	} else if (type == G_TYPE_HASH_TABLE) {
 		write_hash_of_string (info->keyfile, setting, key, value);
 	} else if (type == G_TYPE_ARRAY) {
@@ -3070,7 +2888,7 @@ write_setting_value (NMSetting *setting,
 		/* Flags are guint but GKeyFile has no uint reader, just uint64 */
 		nm_keyfile_plugin_kf_set_uint64 (info->keyfile, setting_name, key, (guint64) g_value_get_flags (value));
 	} else if (G_VALUE_HOLDS_ENUM (value))
-		nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (int) g_value_get_enum (value));
+		nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (gint) g_value_get_enum (value));
 	else
 		g_warn_if_reached ();
 }
@@ -3082,8 +2900,6 @@ nm_keyfile_write (NMConnection *connection,
                   GError **error)
 {
 	KeyfileWriterInfo info = { 0 };
-	gs_free NMSetting **settings = NULL;
-	guint i, length = 0;
 
 	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
 	g_return_val_if_fail (!error || !*error, NULL);
@@ -3096,59 +2912,12 @@ nm_keyfile_write (NMConnection *connection,
 	info.error = NULL;
 	info.handler = handler;
 	info.user_data = user_data;
-
-	settings = nm_connection_get_settings (connection, &length);
-	for (i = 0; i < length; i++) {
-		const NMSettInfoSetting *sett_info;
-		NMSetting *setting = settings[i];
-
-		sett_info = _nm_sett_info_setting_get (NM_SETTING_GET_CLASS (setting));
-
-		if (sett_info->detail.gendata_info) {
-			guint k, n_keys;
-			const char *const*keys;
-
-			nm_assert (!nm_keyfile_plugin_get_alias_for_setting_name (sett_info->setting_class->setting_info->setting_name));
-
-			n_keys = _nm_setting_gendata_get_all (setting, &keys, NULL);
-
-			if (n_keys > 0) {
-				const char *setting_name = sett_info->setting_class->setting_info->setting_name;
-				GHashTable *h = _nm_setting_gendata_hash (setting, FALSE);
-
-				for (k = 0; k < n_keys; k++) {
-					const char *key = keys[k];
-					GVariant *v;
-
-					v = g_hash_table_lookup (h, key);
-
-					if (g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN)) {
-						g_key_file_set_boolean (info.keyfile,
-						                        setting_name,
-						                        key,
-						                        g_variant_get_boolean (v));
-					} else {
-						/* BUG: The variant type is not implemented. Since the connection
-						 * verifies, this can only mean we either wrongly didn't reject
-						 * the connection as invalid, or we didn't properly implement the
-						 * variant type. */
-						nm_assert_not_reached ();
-						continue;
-					}
-				}
-			}
-		} else
-			nm_setting_enumerate_values (setting, write_setting_value, &info);
-
-		if (info.error)
-			break;
-	}
+	nm_connection_for_each_setting_value (connection, write_setting_value, &info);
 
 	if (info.error) {
 		g_propagate_error (error, info.error);
 		g_key_file_unref (info.keyfile);
 		return NULL;
 	}
-
 	return info.keyfile;
 }