From c36200a225aefb2a3919618e75682646899b82c0 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 3 Apr 2013 11:48:04 -0500 Subject: [PATCH] keyfile: use 'ethernet', 'wifi' and 'wifi-security' group names (bgo #696940) Add these aliases for the setting names '802-3-ethernet', '802-11-wireless', and '802-11-wireless-security' and write them by default. It's much friendlier for administrators to type, and a lot less ugly. Also works for: [connection] type=ethernet --- src/settings/plugins/keyfile/reader.c | 83 ++++-- .../keyfile/tests/keyfiles/Makefile.am | 4 +- .../tests/keyfiles/Test_New_Wired_Group_Name | 13 + .../keyfiles/Test_New_Wireless_Group_Names | 17 ++ .../plugins/keyfile/tests/test-keyfile.c | 262 +++++++++++++++++- src/settings/plugins/keyfile/utils.c | 176 ++++++++++++ src/settings/plugins/keyfile/utils.h | 49 ++++ src/settings/plugins/keyfile/writer.c | 74 +++-- 8 files changed, 628 insertions(+), 50 deletions(-) create mode 100644 src/settings/plugins/keyfile/tests/keyfiles/Test_New_Wired_Group_Name create mode 100644 src/settings/plugins/keyfile/tests/keyfiles/Test_New_Wireless_Group_Names diff --git a/src/settings/plugins/keyfile/reader.c b/src/settings/plugins/keyfile/reader.c index 0b204eb48..f8ec87e50 100644 --- a/src/settings/plugins/keyfile/reader.c +++ b/src/settings/plugins/keyfile/reader.c @@ -45,6 +45,31 @@ #include "nm-system-config-interface.h" #include "reader.h" #include "common.h" +#include "utils.h" + +/* Some setting properties also contain setting names, such as + * NMSettingConnection's 'type' property (which specifies the base type of the + * connection, eg ethernet or wifi) or the 802-11-wireless setting's + * 'security' property which specifies whether or not the AP requires + * encrpytion. This function handles translating those properties' values + * to the real setting name if they are an alias. + */ +static void +setting_alias_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const char *keyfile_path) +{ + const char *setting_name = nm_setting_get_name (setting); + char *s; + const char *key_setting_name; + + s = nm_keyfile_plugin_kf_get_string (keyfile, setting_name, key, NULL); + if (s) { + key_setting_name = nm_keyfile_plugin_get_setting_name_for_alias (s); + g_object_set (G_OBJECT (setting), + key, key_setting_name ? key_setting_name : s, + NULL); + g_free (s); + } +} static gboolean read_array_of_uint (GKeyFile *file, @@ -56,7 +81,7 @@ read_array_of_uint (GKeyFile *file, int i; gint *tmp; - tmp = g_key_file_get_integer_list (file, nm_setting_get_name (setting), key, &length, NULL); + tmp = nm_keyfile_plugin_kf_get_integer_list (file, nm_setting_get_name (setting), key, &length, NULL); array = g_array_sized_new (FALSE, FALSE, sizeof (guint32), length); g_return_val_if_fail (array != NULL, FALSE); @@ -284,7 +309,7 @@ read_one_ip_address_or_route (GKeyFile *file, gpointer result; char *address_str, *plen_str, *gateway_str, *metric_str, *value, *current, *error; - current = value = g_key_file_get_string (file, setting_name, key_name, NULL); + current = value = nm_keyfile_plugin_kf_get_string (file, setting_name, key_name, NULL); if (!value) return NULL; @@ -418,7 +443,7 @@ ip4_dns_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const ch char **list, **iter; int ret; - list = g_key_file_get_string_list (keyfile, setting_name, key, &length, NULL); + list = nm_keyfile_plugin_kf_get_string_list (keyfile, setting_name, key, &length, NULL); if (!list || !g_strv_length (list)) return; @@ -451,7 +476,7 @@ ip6_dns_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, const ch char **list, **iter; int ret; - list = g_key_file_get_string_list (keyfile, setting_name, key, &length, NULL); + list = nm_keyfile_plugin_kf_get_string_list (keyfile, setting_name, key, &length, NULL); if (!list || !g_strv_length (list)) return; @@ -489,7 +514,7 @@ mac_address_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, cons gsize length; int i, type; - p = tmp_string = g_key_file_get_string (keyfile, setting_name, key, NULL); + p = tmp_string = nm_keyfile_plugin_kf_get_string (keyfile, setting_name, key, NULL); if (tmp_string) { /* Look for enough ':' characters to signify a MAC address */ i = 0; @@ -508,7 +533,7 @@ mac_address_parser (NMSetting *setting, const char *key, GKeyFile *keyfile, cons if (array == NULL) { /* Old format; list of ints */ - tmp_list = g_key_file_get_integer_list (keyfile, setting_name, key, &length, NULL); + tmp_list = nm_keyfile_plugin_kf_get_integer_list (keyfile, setting_name, key, &length, NULL); type = nm_utils_hwaddr_type (length); if (type < 0) { array = g_byte_array_sized_new (length); @@ -546,12 +571,12 @@ read_hash_of_string (GKeyFile *file, NMSetting *setting, const char *key) char *value; const char *setting_name = nm_setting_get_name (setting); - keys = g_key_file_get_keys (file, setting_name, NULL, NULL); + keys = nm_keyfile_plugin_kf_get_keys (file, setting_name, NULL, NULL); if (!keys || !*keys) return; for (iter = keys; *iter; iter++) { - value = g_key_file_get_string (file, setting_name, *iter, NULL); + value = nm_keyfile_plugin_kf_get_string (file, setting_name, *iter, NULL); if (!value) continue; @@ -595,7 +620,7 @@ get_uchar_array (GKeyFile *keyfile, /* New format: just a string * Old format: integer list; e.g. 11;25;38; */ - tmp_string = g_key_file_get_string (keyfile, setting_name, key, NULL); + tmp_string = nm_keyfile_plugin_kf_get_string (keyfile, setting_name, key, NULL); if (tmp_string) { GRegex *regex; GMatchInfo *match_info; @@ -620,7 +645,7 @@ get_uchar_array (GKeyFile *keyfile, if (!array) { /* Old format; list of ints */ - tmp_list = g_key_file_get_integer_list (keyfile, setting_name, key, &length, NULL); + tmp_list = nm_keyfile_plugin_kf_get_integer_list (keyfile, setting_name, key, &length, NULL); array = g_byte_array_sized_new (length); for (i = 0; i < length; i++) { int val = tmp_list[i]; @@ -821,6 +846,10 @@ typedef struct { * in struct in6_addr internally, but as string in keyfiles. */ static KeyParser key_parsers[] = { + { NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_TYPE, + TRUE, + setting_alias_parser }, { NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_ADDRESSES, FALSE, @@ -865,6 +894,10 @@ static KeyParser key_parsers[] = { NM_SETTING_WIRELESS_BSSID, TRUE, mac_address_parser }, + { NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_SEC, + TRUE, + setting_alias_parser }, { NM_SETTING_BLUETOOTH_SETTING_NAME, NM_SETTING_BLUETOOTH_BDADDR, TRUE, @@ -964,7 +997,7 @@ read_one_setting_value (NMSetting *setting, * like IP addresses and routes where more than one value is actually * encoded by the setting property, this won't be true. */ - if (check_for_key && !g_key_file_has_key (info->keyfile, setting_name, key, &err)) { + if (check_for_key && !nm_keyfile_plugin_kf_has_key (info->keyfile, setting_name, key, &err)) { /* Key doesn't exist or an error ocurred, thus nothing to do. */ if (err) { g_warning ("Error loading setting '%s' value: %s", setting_name, err->message); @@ -986,30 +1019,30 @@ read_one_setting_value (NMSetting *setting, if (type == G_TYPE_STRING) { char *str_val; - str_val = g_key_file_get_string (info->keyfile, setting_name, key, NULL); + str_val = nm_keyfile_plugin_kf_get_string (info->keyfile, setting_name, key, NULL); g_object_set (setting, key, str_val, NULL); g_free (str_val); } else if (type == G_TYPE_UINT) { int int_val; - int_val = g_key_file_get_integer (info->keyfile, setting_name, key, NULL); + int_val = nm_keyfile_plugin_kf_get_integer (info->keyfile, setting_name, key, NULL); if (int_val < 0) g_warning ("Casting negative value (%i) to uint", int_val); g_object_set (setting, key, int_val, NULL); } else if (type == G_TYPE_INT) { int int_val; - int_val = g_key_file_get_integer (info->keyfile, setting_name, key, NULL); + int_val = nm_keyfile_plugin_kf_get_integer (info->keyfile, setting_name, key, NULL); g_object_set (setting, key, int_val, NULL); } else if (type == G_TYPE_BOOLEAN) { gboolean bool_val; - bool_val = g_key_file_get_boolean (info->keyfile, setting_name, key, NULL); + bool_val = nm_keyfile_plugin_kf_get_boolean (info->keyfile, setting_name, key, NULL); g_object_set (setting, key, bool_val, NULL); } else if (type == G_TYPE_CHAR) { int int_val; - int_val = g_key_file_get_integer (info->keyfile, setting_name, key, NULL); + int_val = nm_keyfile_plugin_kf_get_integer (info->keyfile, setting_name, key, NULL); if (int_val < G_MININT8 || int_val > G_MAXINT8) g_warning ("Casting value (%i) to char", int_val); @@ -1018,7 +1051,7 @@ read_one_setting_value (NMSetting *setting, char *tmp_str; guint64 uint_val; - tmp_str = g_key_file_get_value (info->keyfile, setting_name, key, NULL); + tmp_str = nm_keyfile_plugin_kf_get_value (info->keyfile, setting_name, key, NULL); uint_val = g_ascii_strtoull (tmp_str, NULL, 10); g_free (tmp_str); g_object_set (setting, key, uint_val, NULL); @@ -1028,7 +1061,7 @@ read_one_setting_value (NMSetting *setting, gsize length; int i; - tmp = g_key_file_get_integer_list (info->keyfile, setting_name, key, &length, NULL); + tmp = nm_keyfile_plugin_kf_get_integer_list (info->keyfile, setting_name, key, &length, NULL); array = g_byte_array_sized_new (length); for (i = 0; i < length; i++) { @@ -1052,7 +1085,7 @@ read_one_setting_value (NMSetting *setting, int i; GSList *list = NULL; - sa = g_key_file_get_string_list (info->keyfile, setting_name, key, &length, NULL); + sa = nm_keyfile_plugin_kf_get_string_list (info->keyfile, setting_name, key, &length, NULL); for (i = 0; i < length; i++) list = g_slist_prepend (list, sa[i]); @@ -1075,16 +1108,18 @@ read_one_setting_value (NMSetting *setting, } static NMSetting * -read_setting (GKeyFile *file, const char *keyfile_path, const char *setting_name) +read_setting (GKeyFile *file, const char *keyfile_path, const char *group) { NMSetting *setting; ReadInfo info = { file, keyfile_path }; + const char *alias; - setting = nm_connection_create_setting (setting_name); + alias = nm_keyfile_plugin_get_setting_name_for_alias (group); + setting = nm_connection_create_setting (alias ? alias : group); if (setting) nm_setting_enumerate_values (setting, read_one_setting_value, &info); else - g_warning ("Invalid setting name '%s'", setting_name); + g_warning ("Invalid setting name '%s'", group); return setting; } @@ -1094,11 +1129,11 @@ read_vpn_secrets (GKeyFile *file, NMSettingVPN *s_vpn) { char **keys, **iter; - keys = g_key_file_get_keys (file, VPN_SECRETS_GROUP, NULL, NULL); + keys = nm_keyfile_plugin_kf_get_keys (file, VPN_SECRETS_GROUP, NULL, NULL); for (iter = keys; *iter; iter++) { char *secret; - secret = g_key_file_get_string (file, VPN_SECRETS_GROUP, *iter, NULL); + secret = nm_keyfile_plugin_kf_get_string (file, VPN_SECRETS_GROUP, *iter, NULL); if (secret) { nm_setting_vpn_add_secret (s_vpn, *iter, secret); g_free (secret); diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.am b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.am index 759b29f43..46cf7c5c7 100644 --- a/src/settings/plugins/keyfile/tests/keyfiles/Makefile.am +++ b/src/settings/plugins/keyfile/tests/keyfiles/Makefile.am @@ -16,7 +16,9 @@ KEYFILES = \ Test_Wired_TLS_Path_Missing \ Test_InfiniBand_Connection \ Test_Bridge_Main \ - Test_Bridge_Component + Test_Bridge_Component \ + Test_New_Wired_Group_Name \ + Test_New_Wireless_Group_Names CERTS = \ test-ca-cert.pem \ diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_New_Wired_Group_Name b/src/settings/plugins/keyfile/tests/keyfiles/Test_New_Wired_Group_Name new file mode 100644 index 000000000..f27cd4a34 --- /dev/null +++ b/src/settings/plugins/keyfile/tests/keyfiles/Test_New_Wired_Group_Name @@ -0,0 +1,13 @@ + +[connection] +id=Test Wired Connection +uuid=4e80a56d-c99f-4aad-a6dd-b449bc398c57 +type=ethernet + +[ethernet] +mac-address=00:11:22:33:44:55 +mtu=1400 + +[ipv4] +method=auto + diff --git a/src/settings/plugins/keyfile/tests/keyfiles/Test_New_Wireless_Group_Names b/src/settings/plugins/keyfile/tests/keyfiles/Test_New_Wireless_Group_Names new file mode 100644 index 000000000..0752f56df --- /dev/null +++ b/src/settings/plugins/keyfile/tests/keyfiles/Test_New_Wireless_Group_Names @@ -0,0 +1,17 @@ +[connection] +id=Test New Wireless Group Names +uuid=2f962388-e5f3-45af-a62c-ac220b8f7baa +type=wifi + +[wifi] +ssid=foobar +mode=infrastructure +security=wifi-security + +[wifi-security] +key-mgmt=wpa-psk +psk=s3cu4e passphrase + +[ipv4] +method=auto + diff --git a/src/settings/plugins/keyfile/tests/test-keyfile.c b/src/settings/plugins/keyfile/tests/test-keyfile.c index 309c71af0..f51298c77 100644 --- a/src/settings/plugins/keyfile/tests/test-keyfile.c +++ b/src/settings/plugins/keyfile/tests/test-keyfile.c @@ -1223,7 +1223,7 @@ test_write_string_ssid (void) keyfile = g_key_file_new (); ASSERT (g_key_file_load_from_file (keyfile, testfile, 0, NULL) == TRUE, "string-ssid-verify", "failed to load keyfile to verify"); - tmp = g_key_file_get_string (keyfile, NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_SSID, NULL); + tmp = g_key_file_get_string (keyfile, "wifi", NM_SETTING_WIRELESS_SSID, NULL); ASSERT (tmp, "string-ssid-verify", "failed to load 'ssid' key from file"); ASSERT (strlen (tmp) == sizeof (tmpssid), "string-ssid-verify", "reread SSID and expected were different sizes"); @@ -1345,7 +1345,7 @@ test_write_intlist_ssid (void) g_assert_no_error (error); g_assert (success); - intlist = g_key_file_get_integer_list (keyfile, NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_SSID, &len, &error); + intlist = g_key_file_get_integer_list (keyfile, "wifi", NM_SETTING_WIRELESS_SSID, &len, &error); g_assert_no_error (error); g_assert (intlist); g_assert_cmpint (len, ==, sizeof (tmpssid)); @@ -1501,7 +1501,7 @@ test_write_intlike_ssid (void) g_assert_no_error (error); g_assert (success); - tmp = g_key_file_get_string (keyfile, NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_SSID, &error); + tmp = g_key_file_get_string (keyfile, "wifi", NM_SETTING_WIRELESS_SSID, &error); g_assert_no_error (error); g_assert (tmp); g_assert_cmpstr (tmp, ==, "101"); @@ -1589,7 +1589,7 @@ test_write_intlike_ssid_2 (void) g_assert_no_error (error); g_assert (success); - tmp = g_key_file_get_string (keyfile, NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_SSID, &error); + tmp = g_key_file_get_string (keyfile, "wifi", NM_SETTING_WIRELESS_SSID, &error); g_assert_no_error (error); g_assert (tmp); g_assert_cmpstr (tmp, ==, "11\\;12\\;13\\;"); @@ -2998,6 +2998,255 @@ test_write_bridge_component (void) g_object_unref (connection); } +static void +test_read_new_wired_group_name (void) +{ + NMConnection *connection; + NMSettingWired *s_wired; + const GByteArray *array; + guint8 expected_mac[ETH_ALEN] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55 }; + GError *error = NULL; + gboolean success; + + connection = nm_keyfile_plugin_connection_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); + + /* 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); + + array = nm_setting_wired_get_mac_address (s_wired); + g_assert (array); + g_assert_cmpint (array->len, ==, ETH_ALEN); + g_assert_cmpint (memcmp (array->data, expected_mac, sizeof (expected_mac)), ==, 0); + + g_object_unref (connection); +} + +static void +test_write_new_wired_group_name (void) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWired *s_wired; + char *uuid; + gboolean success; + NMConnection *reread; + char *testfile = NULL; + GError *error = NULL; + pid_t owner_grp; + uid_t owner_uid; + GKeyFile *kf; + char *s; + gint mtu; + + connection = nm_connection_new (); + g_assert (connection); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + g_assert (s_con); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write Wired New Group Name", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, + NULL); + g_free (uuid); + + /* Wired setting */ + s_wired = (NMSettingWired *) nm_setting_wired_new (); + g_assert (s_wired); + g_object_set (s_wired, NM_SETTING_WIRED_MTU, 1400, NULL); + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + + /* Write out the connection */ + owner_uid = geteuid (); + owner_grp = getegid (); + success = nm_keyfile_plugin_write_test_connection (connection, TEST_SCRATCH_DIR, owner_uid, owner_grp, &testfile, &error); + g_assert_no_error (error); + g_assert (success); + g_assert (testfile); + + /* Read the connection back in and compare it to the one we just wrote out */ + reread = nm_keyfile_plugin_connection_from_file (testfile, &error); + g_assert_no_error (error); + g_assert (reread); + g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT)); + + /* Look at the keyfile itself to ensure we wrote out the new group names and type */ + kf = g_key_file_new (); + success = g_key_file_load_from_file (kf, testfile, G_KEY_FILE_NONE, &error); + g_assert_no_error (error); + g_assert (success); + + s = g_key_file_get_string (kf, NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_TYPE, &error); + g_assert_no_error (error); + g_assert_cmpstr (s, ==, "ethernet"); + g_free (s); + + mtu = g_key_file_get_integer (kf, "ethernet", NM_SETTING_WIRED_MTU, &error); + g_assert_no_error (error); + g_assert_cmpint (mtu, ==, 1400); + + unlink (testfile); + g_free (testfile); + + g_object_unref (reread); + g_object_unref (connection); +} + +static void +test_read_new_wireless_group_names (void) +{ + NMConnection *connection; + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + const GByteArray *array; + const char *expected_ssid = "foobar"; + GError *error = NULL; + gboolean success; + + connection = nm_keyfile_plugin_connection_from_file (TEST_KEYFILES_DIR"/Test_New_Wireless_Group_Names", &error); + g_assert_no_error (error); + g_assert (connection); + success = nm_connection_verify (connection, &error); + g_assert_no_error (error); + g_assert (success); + + /* Wifi setting */ + s_wifi = nm_connection_get_setting_wireless (connection); + g_assert (s_wifi); + + array = nm_setting_wireless_get_ssid (s_wifi); + g_assert (array); + g_assert_cmpint (array->len, ==, strlen (expected_ssid)); + g_assert_cmpint (memcmp (array->data, expected_ssid, array->len), ==, 0); + + g_assert_cmpstr (nm_setting_wireless_get_mode (s_wifi), ==, NM_SETTING_WIRELESS_MODE_INFRA); + + g_assert_cmpstr (nm_setting_wireless_get_security (s_wifi), ==, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME); + + /* Wifi security setting */ + s_wsec = nm_connection_get_setting_wireless_security (connection); + g_assert (s_wsec); + g_assert_cmpstr (nm_setting_wireless_security_get_key_mgmt (s_wsec), ==, "wpa-psk"); + g_assert_cmpstr (nm_setting_wireless_security_get_psk (s_wsec), ==, "s3cu4e passphrase"); + + g_object_unref (connection); +} + +static void +test_write_new_wireless_group_names (void) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWireless *s_wifi; + NMSettingWirelessSecurity *s_wsec; + char *uuid; + GByteArray *ssid; + unsigned char tmpssid[] = { 0x31, 0x33, 0x33, 0x37 }; + const char *expected_psk = "asdfasdfasdfa12315"; + gboolean success; + NMConnection *reread; + char *testfile = NULL; + GError *error = NULL; + pid_t owner_grp; + uid_t owner_uid; + GKeyFile *kf; + char *s; + + connection = nm_connection_new (); + + /* Connection setting */ + + s_con = (NMSettingConnection *) nm_setting_connection_new (); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write New Wireless Group Names", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + g_free (uuid); + + /* WiFi setting */ + s_wifi = (NMSettingWireless *) nm_setting_wireless_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wifi)); + + ssid = g_byte_array_sized_new (sizeof (tmpssid)); + g_byte_array_append (ssid, &tmpssid[0], sizeof (tmpssid)); + g_object_set (s_wifi, + NM_SETTING_WIRELESS_SSID, ssid, + NM_SETTING_WIRELESS_SEC, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, + NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA, + NULL); + g_byte_array_free (ssid, TRUE); + + /* WiFi security setting */ + s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new (); + nm_connection_add_setting (connection, NM_SETTING (s_wsec)); + g_object_set (s_wsec, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-psk", + NM_SETTING_WIRELESS_SECURITY_PSK, expected_psk, + NULL); + + /* Write out the connection */ + owner_uid = geteuid (); + owner_grp = getegid (); + success = nm_keyfile_plugin_write_test_connection (connection, TEST_SCRATCH_DIR, owner_uid, owner_grp, &testfile, &error); + g_assert_no_error (error); + g_assert (success); + + g_assert (testfile); + + /* Read the connection back in and compare it to the one we just wrote out */ + reread = nm_keyfile_plugin_connection_from_file (testfile, &error); + g_assert_no_error (error); + g_assert (reread); + g_assert (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT)); + + /* Look at the keyfile itself to ensure we wrote out the new group names and type */ + kf = g_key_file_new (); + success = g_key_file_load_from_file (kf, testfile, G_KEY_FILE_NONE, &error); + g_assert_no_error (error); + g_assert (success); + + s = g_key_file_get_string (kf, NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_TYPE, &error); + g_assert_no_error (error); + g_assert_cmpstr (s, ==, "wifi"); + g_free (s); + + s = g_key_file_get_string (kf, "wifi", NM_SETTING_WIRELESS_MODE, &error); + g_assert_no_error (error); + g_assert_cmpstr (s, ==, NM_SETTING_WIRELESS_MODE_INFRA); + g_free (s); + + s = g_key_file_get_string (kf, "wifi", NM_SETTING_WIRELESS_SEC, &error); + g_assert_no_error (error); + g_assert_cmpstr (s, ==, "wifi-security"); + g_free (s); + + s = g_key_file_get_string (kf, "wifi-security", NM_SETTING_WIRELESS_SECURITY_PSK, &error); + g_assert_no_error (error); + g_assert_cmpstr (s, ==, expected_psk); + g_free (s); + + unlink (testfile); + g_free (testfile); + + g_object_unref (reread); + g_object_unref (connection); +} + int main (int argc, char **argv) { @@ -3055,6 +3304,11 @@ int main (int argc, char **argv) test_read_bridge_component (); test_write_bridge_component (); + test_read_new_wired_group_name (); + test_write_new_wired_group_name (); + test_read_new_wireless_group_names (); + test_write_new_wireless_group_names (); + base = g_path_get_basename (argv[0]); fprintf (stdout, "%s: SUCCESS\n", base); g_free (base); diff --git a/src/settings/plugins/keyfile/utils.c b/src/settings/plugins/keyfile/utils.c index f35311722..6935e2471 100644 --- a/src/settings/plugins/keyfile/utils.c +++ b/src/settings/plugins/keyfile/utils.c @@ -22,6 +22,9 @@ #include #include #include "utils.h" +#include +#include +#include static const char temp_letters[] = @@ -103,3 +106,176 @@ nm_keyfile_plugin_utils_should_ignore_file (const char *filename) return ignore; } +typedef struct { + const char *setting; + const char *alias; +} SettingAlias; + +static const SettingAlias alias_list[] = { + { NM_SETTING_WIRED_SETTING_NAME, "ethernet" }, + { NM_SETTING_WIRELESS_SETTING_NAME, "wifi" }, + { NM_SETTING_WIRELESS_SECURITY_SETTING_NAME, "wifi-security" }, +}; + +const char * +nm_keyfile_plugin_get_alias_for_setting_name (const char *setting_name) +{ + guint i; + + g_return_val_if_fail (setting_name != NULL, NULL); + + for (i = 0; i < G_N_ELEMENTS (alias_list); i++) { + if (strcmp (setting_name, alias_list[i].setting) == 0) + return alias_list[i].alias; + } + return NULL; +} + +const char * +nm_keyfile_plugin_get_setting_name_for_alias (const char *alias) +{ + guint i; + + g_return_val_if_fail (alias != NULL, NULL); + + for (i = 0; i < G_N_ELEMENTS (alias_list); i++) { + if (strcmp (alias, alias_list[i].alias) == 0) + return alias_list[i].setting; + } + return NULL; +} + +/**********************************************************************/ + +/* List helpers */ +#define DEFINE_KF_LIST_WRAPPER(stype, get_ctype, set_ctype) \ +get_ctype \ +nm_keyfile_plugin_kf_get_##stype##_list (GKeyFile *kf, \ + const char *group, \ + const char *key, \ + gsize *out_length, \ + GError **error) \ +{ \ + get_ctype list; \ + const char *alias; \ + GError *local = NULL; \ + \ + list = g_key_file_get_##stype##_list (kf, group, key, out_length, &local); \ + if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { \ + alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \ + if (alias) { \ + g_clear_error (&local); \ + list = g_key_file_get_##stype##_list (kf, alias, key, out_length, &local); \ + } \ + } \ + if (local) \ + g_propagate_error (error, local); \ + return list; \ +} \ + \ +void \ +nm_keyfile_plugin_kf_set_##stype##_list (GKeyFile *kf, \ + const char *group, \ + const char *key, \ + set_ctype list[], \ + gsize length) \ +{ \ + const char *alias; \ + \ + alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \ + g_key_file_set_##stype##_list (kf, alias ? alias : group, key, list, length); \ +} + +DEFINE_KF_LIST_WRAPPER(integer, gint*, gint); +DEFINE_KF_LIST_WRAPPER(string, gchar **, const gchar* const); + +/* Single value helpers */ +#define DEFINE_KF_WRAPPER(stype, get_ctype, set_ctype) \ +get_ctype \ +nm_keyfile_plugin_kf_get_##stype (GKeyFile *kf, \ + const char *group, \ + const char *key, \ + GError **error) \ +{ \ + get_ctype val; \ + const char *alias; \ + GError *local = NULL; \ + \ + val = g_key_file_get_##stype (kf, group, key, &local); \ + if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { \ + alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \ + if (alias) { \ + g_clear_error (&local); \ + val = g_key_file_get_##stype (kf, alias, key, &local); \ + } \ + } \ + if (local) \ + g_propagate_error (error, local); \ + return val; \ +} \ + \ +void \ +nm_keyfile_plugin_kf_set_##stype (GKeyFile *kf, \ + const char *group, \ + const char *key, \ + set_ctype value) \ +{ \ + const char *alias; \ + \ + alias = nm_keyfile_plugin_get_alias_for_setting_name (group); \ + g_key_file_set_##stype (kf, alias ? alias : group, key, value); \ +} + +DEFINE_KF_WRAPPER(string, gchar*, const gchar*); +DEFINE_KF_WRAPPER(integer, gint, gint); +DEFINE_KF_WRAPPER(boolean, gboolean, gboolean); +DEFINE_KF_WRAPPER(value, gchar*, const gchar*); + + +gchar ** +nm_keyfile_plugin_kf_get_keys (GKeyFile *kf, + const char *group, + gsize *out_length, + GError **error) +{ + gchar **keys; + const char *alias; + GError *local = NULL; + + keys = g_key_file_get_keys (kf, group, out_length, &local); + if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { + alias = nm_keyfile_plugin_get_alias_for_setting_name (group); + if (alias) { + g_clear_error (&local); + keys = g_key_file_get_keys (kf, alias, out_length, &local); + } + } + if (local) + g_propagate_error (error, local); + return keys; +} + +gboolean +nm_keyfile_plugin_kf_has_key (GKeyFile *kf, + const char *group, + const char *key, + GError **error) +{ + gboolean has; + const char *alias; + GError *local = NULL; + + has = g_key_file_has_key (kf, group, key, &local); + if (g_error_matches (local, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_GROUP_NOT_FOUND)) { + alias = nm_keyfile_plugin_get_alias_for_setting_name (group); + if (alias) { + g_clear_error (&local); + has = g_key_file_has_key (kf, alias, key, &local); + } + } + if (local) + g_propagate_error (error, local); + return has; +} + + diff --git a/src/settings/plugins/keyfile/utils.h b/src/settings/plugins/keyfile/utils.h index 68e6e56f2..9a2e485bc 100644 --- a/src/settings/plugins/keyfile/utils.h +++ b/src/settings/plugins/keyfile/utils.h @@ -26,5 +26,54 @@ gboolean nm_keyfile_plugin_utils_should_ignore_file (const char *filename); +const char *nm_keyfile_plugin_get_alias_for_setting_name (const char *setting_name); + +const char *nm_keyfile_plugin_get_setting_name_for_alias (const char *alias); + +/*********************************************************/ + +/* List helpers */ +#define DEFINE_KF_LIST_WRAPPER_PROTO(stype, get_ctype, set_ctype) \ +get_ctype nm_keyfile_plugin_kf_get_##stype##_list (GKeyFile *kf, \ + const char *group, \ + const char *key, \ + gsize *out_length, \ + GError **error); \ +\ +void nm_keyfile_plugin_kf_set_##stype##_list (GKeyFile *kf, \ + const char *group, \ + const char *key, \ + set_ctype list[], \ + gsize length); +DEFINE_KF_LIST_WRAPPER_PROTO(integer, gint*, gint) +DEFINE_KF_LIST_WRAPPER_PROTO(string, gchar**, const gchar* const) + +/* Single-value helpers */ +#define DEFINE_KF_WRAPPER_PROTO(stype, get_ctype, set_ctype) \ +get_ctype nm_keyfile_plugin_kf_get_##stype (GKeyFile *kf, \ + const char *group, \ + const char *key, \ + GError **error); \ +\ +void nm_keyfile_plugin_kf_set_##stype (GKeyFile *kf, \ + const char *group, \ + const char *key, \ + set_ctype value); +DEFINE_KF_WRAPPER_PROTO(string, gchar*, const gchar*) +DEFINE_KF_WRAPPER_PROTO(integer, gint, gint) +DEFINE_KF_WRAPPER_PROTO(boolean, gboolean, gboolean) +DEFINE_KF_WRAPPER_PROTO(value, gchar*, const gchar*) + +/* Misc */ +gchar ** nm_keyfile_plugin_kf_get_keys (GKeyFile *kf, + const char *group, + gsize *out_length, + GError **error); + +gboolean nm_keyfile_plugin_kf_has_key (GKeyFile *kf, + const char *group, + const char *key, + GError **error); + #endif /* _UTILS_H_ */ diff --git a/src/settings/plugins/keyfile/writer.c b/src/settings/plugins/keyfile/writer.c index 0b8c15929..d8c2d4f45 100644 --- a/src/settings/plugins/keyfile/writer.c +++ b/src/settings/plugins/keyfile/writer.c @@ -46,6 +46,32 @@ #include "nm-glib-compat.h" #include "writer.h" #include "common.h" +#include "utils.h" + +/* Some setting properties also contain setting names, such as + * NMSettingConnection's 'type' property (which specifies the base type of the + * connection, eg ethernet or wifi) or the 802-11-wireless setting's + * 'security' property which specifies whether or not the AP requires + * encrpytion. This function handles translating those properties' values + * from the real setting name to the more-readable alias. + */ +static void +setting_alias_writer (GKeyFile *file, + const char *keyfile_dir, + const char *uuid, + NMSetting *setting, + const char *key, + const GValue *value) +{ + const char *str, *alias; + + str = g_value_get_string (value); + alias = nm_keyfile_plugin_get_alias_for_setting_name (str); + nm_keyfile_plugin_kf_set_string (file, + nm_setting_get_name (setting), + key, + alias ? alias : str); +} static gboolean write_array_of_uint (GKeyFile *file, @@ -65,7 +91,7 @@ write_array_of_uint (GKeyFile *file, for (i = 0; i < array->len; i++) tmp_array[i] = g_array_index (array, int, i); - g_key_file_set_integer_list (file, nm_setting_get_name (setting), key, tmp_array, array->len); + nm_keyfile_plugin_kf_set_integer_list (file, nm_setting_get_name (setting), key, tmp_array, array->len); g_free (tmp_array); return TRUE; } @@ -102,7 +128,7 @@ ip4_dns_writer (GKeyFile *file, list[num++] = g_strdup (buf); } - g_key_file_set_string_list (file, nm_setting_get_name (setting), key, (const char **) list, num); + nm_keyfile_plugin_kf_set_string_list (file, nm_setting_get_name (setting), key, (const char **) list, num); g_strfreev (list); } @@ -149,7 +175,7 @@ write_ip4_values (GKeyFile *file, if (success) { key_name = g_strdup_printf ("%s%d", key, j + 1); - g_key_file_set_string (file, setting_name, key_name, output->str); + nm_keyfile_plugin_kf_set_string (file, setting_name, key_name, output->str); g_free (key_name); } @@ -232,7 +258,7 @@ ip6_dns_writer (GKeyFile *file, list[num++] = g_strdup (buf); } - g_key_file_set_string_list (file, nm_setting_get_name (setting), key, (const char **) list, num); + nm_keyfile_plugin_kf_set_string_list (file, nm_setting_get_name (setting), key, (const char **) list, num); g_strfreev (list); } @@ -337,7 +363,7 @@ ip6_addr_writer (GKeyFile *file, if (ip6_addr) { /* Write it out */ key_name = g_strdup_printf ("address%d", j++); - g_key_file_set_string (file, setting_name, key_name, ip6_addr); + nm_keyfile_plugin_kf_set_string (file, setting_name, key_name, ip6_addr); g_free (key_name); g_free (ip6_addr); } @@ -380,7 +406,7 @@ ip6_route_writer (GKeyFile *file, /* Write it out */ key_name = g_strdup_printf ("route%d", j++); - g_key_file_set_string (file, setting_name, key_name, output->str); + nm_keyfile_plugin_kf_set_string (file, setting_name, key_name, output->str); g_free (key_name); g_string_free (output, TRUE); @@ -415,7 +441,7 @@ mac_address_writer (GKeyFile *file, } mac = nm_utils_hwaddr_ntoa (array->data, type); - g_key_file_set_string (file, setting_name, key, mac); + nm_keyfile_plugin_kf_set_string (file, setting_name, key, mac); g_free (mac); } @@ -453,7 +479,7 @@ write_hash_of_string (GKeyFile *file, } if (write_item) - g_key_file_set_string (file, group_name, property, data); + nm_keyfile_plugin_kf_set_string (file, group_name, property, data); } } @@ -505,13 +531,13 @@ ssid_writer (GKeyFile *file, ssid[j++] = array->data[i]; } } - g_key_file_set_string (file, setting_name, key, ssid); + nm_keyfile_plugin_kf_set_string (file, setting_name, key, ssid); g_free (ssid); } else { tmp_array = g_new (gint, array->len); for (i = 0; i < array->len; i++) tmp_array[i] = (int) array->data[i]; - g_key_file_set_integer_list (file, setting_name, key, tmp_array, array->len); + nm_keyfile_plugin_kf_set_integer_list (file, setting_name, key, tmp_array, array->len); g_free (tmp_array); } } @@ -537,7 +563,7 @@ password_raw_writer (GKeyFile *file, tmp_array = g_new (gint, array->len); for (i = 0; i < array->len; i++) tmp_array[i] = (int) array->data[i]; - g_key_file_set_integer_list (file, setting_name, key, tmp_array, array->len); + nm_keyfile_plugin_kf_set_integer_list (file, setting_name, key, tmp_array, array->len); g_free (tmp_array); } @@ -702,7 +728,7 @@ cert_writer (GKeyFile *file, path++; } - g_key_file_set_string (file, setting_name, key, path); + nm_keyfile_plugin_kf_set_string (file, setting_name, key, path); } else if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { const GByteArray *blob; gboolean success; @@ -732,7 +758,7 @@ cert_writer (GKeyFile *file, success = write_cert_key_file (new_path, blob, &error); if (success) { /* Write the path value to the keyfile */ - g_key_file_set_string (file, setting_name, key, new_path); + nm_keyfile_plugin_kf_set_string (file, setting_name, key, new_path); } else { g_warning ("Failed to write certificate/key %s: %s", new_path, error->message); g_error_free (error); @@ -760,6 +786,9 @@ typedef struct { * in struct in6_addr internally, but as string in keyfiles. */ static KeyWriter key_writers[] = { + { NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_TYPE, + setting_alias_writer }, { NM_SETTING_IP4_CONFIG_SETTING_NAME, NM_SETTING_IP4_CONFIG_ADDRESSES, ip4_addr_writer }, @@ -784,6 +813,9 @@ static KeyWriter key_writers[] = { { NM_SETTING_WIRED_SETTING_NAME, NM_SETTING_WIRED_CLONED_MAC_ADDRESS, mac_address_writer }, + { NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_SEC, + setting_alias_writer }, { NM_SETTING_WIRELESS_SETTING_NAME, NM_SETTING_WIRELESS_MAC_ADDRESS, mac_address_writer }, @@ -895,21 +927,21 @@ write_setting_value (NMSetting *setting, str = g_value_get_string (value); if (str) - g_key_file_set_string (info->keyfile, setting_name, key, str); + nm_keyfile_plugin_kf_set_string (info->keyfile, setting_name, key, str); } else if (type == G_TYPE_UINT) - g_key_file_set_integer (info->keyfile, setting_name, key, (int) g_value_get_uint (value)); + nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (int) g_value_get_uint (value)); else if (type == G_TYPE_INT) - g_key_file_set_integer (info->keyfile, setting_name, key, g_value_get_int (value)); + nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, g_value_get_int (value)); else if (type == G_TYPE_UINT64) { char *numstr; numstr = g_strdup_printf ("%" G_GUINT64_FORMAT, g_value_get_uint64 (value)); - g_key_file_set_value (info->keyfile, setting_name, key, numstr); + nm_keyfile_plugin_kf_set_value (info->keyfile, setting_name, key, numstr); g_free (numstr); } else if (type == G_TYPE_BOOLEAN) { - g_key_file_set_boolean (info->keyfile, setting_name, key, g_value_get_boolean (value)); + nm_keyfile_plugin_kf_set_boolean (info->keyfile, setting_name, key, g_value_get_boolean (value)); } else if (type == G_TYPE_CHAR) { - g_key_file_set_integer (info->keyfile, setting_name, key, (int) g_value_get_schar (value)); + nm_keyfile_plugin_kf_set_integer (info->keyfile, setting_name, key, (int) g_value_get_schar (value)); } else if (type == DBUS_TYPE_G_UCHAR_ARRAY) { GByteArray *array; @@ -922,7 +954,7 @@ write_setting_value (NMSetting *setting, for (i = 0; i < array->len; i++) tmp_array[i] = (int) array->data[i]; - g_key_file_set_integer_list (info->keyfile, setting_name, key, tmp_array, array->len); + nm_keyfile_plugin_kf_set_integer_list (info->keyfile, setting_name, key, tmp_array, array->len); g_free (tmp_array); } } else if (type == DBUS_TYPE_G_LIST_OF_STRING) { @@ -938,7 +970,7 @@ write_setting_value (NMSetting *setting, for (iter = list; iter; iter = iter->next) array[i++] = iter->data; - g_key_file_set_string_list (info->keyfile, setting_name, key, (const gchar **const) array, i); + nm_keyfile_plugin_kf_set_string_list (info->keyfile, setting_name, key, (const gchar **const) array, i); g_free (array); } } else if (type == DBUS_TYPE_G_MAP_OF_STRING) {