diff options
author | Dan Winship <danw@redhat.com> | 2015-01-15 12:19:06 -0500 |
---|---|---|
committer | Dan Winship <danw@redhat.com> | 2015-01-15 14:46:30 -0500 |
commit | 76d9fc91671c50646ecde3de934da47af623a0a1 (patch) | |
tree | b34a9f55b43cc457bda873233f0a3b67bd1934fc | |
parent | d80e100179d408a754402d1c688052cd45bf7bfa (diff) | |
download | NetworkManager-76d9fc91671c50646ecde3de934da47af623a0a1.tar.gz |
libnm-core: validate property types from D-Bus (rh #1182567)
In _nm_setting_new_from_dbus(), verify that the properties have the
right types, and return an error if not. (In particular, don't crash
if someone tries to assign a GBytes-valued property a non-'ay' value.)
-rw-r--r-- | libnm-core/nm-setting.c | 54 | ||||
-rw-r--r-- | libnm-core/tests/test-general.c | 178 |
2 files changed, 225 insertions, 7 deletions
diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index 4ecfb02494..a80de22061 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -660,17 +660,40 @@ get_property_for_dbus (NMSetting *setting, return dbus_value; } -static void -set_property_from_dbus (const NMSettingProperty *property, GVariant *src_value, GValue *dst_value) +static gboolean +set_property_from_dbus (const NMSettingProperty *property, + GVariant *src_value, + GValue *dst_value) { g_return_if_fail (property->param_spec != NULL); - if (property->from_dbus) + if (property->from_dbus) { + if (!g_variant_type_equal (g_variant_get_type (src_value), property->dbus_type)) + return FALSE; + property->from_dbus (src_value, dst_value); - else if (dst_value->g_type == G_TYPE_BYTES) + } else if (dst_value->g_type == G_TYPE_BYTES) { + if (!g_variant_is_of_type (src_value, G_VARIANT_TYPE_BYTESTRING)) + return FALSE; + _nm_utils_bytes_from_dbus (src_value, dst_value); - else - g_dbus_gvariant_to_gvalue (src_value, dst_value); + } else { + GValue tmp = G_VALUE_INIT; + + g_dbus_gvariant_to_gvalue (src_value, &tmp); + if (G_VALUE_TYPE (&tmp) == G_VALUE_TYPE (dst_value)) + *dst_value = tmp; + else { + gboolean success; + + success = g_value_transform (&tmp, dst_value); + g_value_unset (&tmp); + if (!success) + return FALSE; + } + } + + return TRUE; } @@ -798,6 +821,21 @@ _nm_setting_new_from_dbus (GType setting_type, value = g_variant_lookup_value (setting_dict, property->name, NULL); if (value && property->set_func) { + if (!g_variant_type_equal (g_variant_get_type (value), property->dbus_type)) { + property_type_error: + g_set_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY, + _("can't set property of type '%s' from value of type '%s'"), + property->dbus_type ? + g_variant_type_peek_string (property->dbus_type) : + g_type_name (property->param_spec->value_type), + g_variant_get_type_string (value)); + g_prefix_error (error, "%s.%s: ", nm_setting_get_name (setting), property->name); + + g_variant_unref (value); + g_object_unref (setting); + return NULL; + } + property->set_func (setting, connection_dict, property->name, @@ -810,7 +848,9 @@ _nm_setting_new_from_dbus (GType setting_type, GValue object_value = { 0, }; g_value_init (&object_value, property->param_spec->value_type); - set_property_from_dbus (property, value, &object_value); + if (!set_property_from_dbus (property, value, &object_value)) + goto property_type_error; + g_object_set_property (G_OBJECT (setting), property->param_spec->name, &object_value); g_value_unset (&object_value); } diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index d309c8005f..04e2a8e654 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -1140,6 +1140,183 @@ test_setting_new_from_dbus_enum (void) g_object_unref (s_serial); } +static void +test_setting_new_from_dbus_bad (void) +{ + NMSetting *setting; + NMConnection *conn; + GBytes *ssid; + GPtrArray *addrs; + GVariant *orig_dict, *dict; + GError *error = NULL; + + /* We want to test: + * - ordinary scalar properties + * - string properties + * - GBytes-valued properties (which are handled specially by set_property_from_dbus()) + * - enum/flags-valued properties + * - overridden properties + * - transformed properties + * + * No single setting class has examples of all of these, so we need two settings. + */ + + conn = nm_simple_connection_new (); + + setting = nm_setting_connection_new (); + g_object_set (setting, + NM_SETTING_CONNECTION_ID, "test", + NM_SETTING_CONNECTION_UUID, "83c5a841-1759-4cdb-bfce-8d4087956497", + NULL); + nm_connection_add_setting (conn, setting); + + setting = nm_setting_wireless_new (); + ssid = g_bytes_new ("my-ssid", 7); + g_object_set (setting, + /* scalar */ + NM_SETTING_WIRELESS_RATE, 100, + /* string */ + NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA, + /* GBytes */ + NM_SETTING_WIRELESS_SSID, ssid, + /* transformed */ + NM_SETTING_WIRELESS_BSSID, "00:11:22:33:44:55", + NULL); + g_bytes_unref (ssid); + nm_connection_add_setting (conn, setting); + + setting = nm_setting_ip6_config_new (); + addrs = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_ip_address_unref); + g_ptr_array_add (addrs, nm_ip_address_new (AF_INET6, "1234::5678", 64, NULL)); + g_object_set (setting, + /* enum */ + NM_SETTING_IP6_CONFIG_IP6_PRIVACY, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_PUBLIC_ADDR, + /* overridden */ + NM_SETTING_IP_CONFIG_ADDRESSES, addrs, + /* (needed in order to verify()) */ + NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP6_CONFIG_METHOD_AUTO, + NULL); + g_ptr_array_unref (addrs); + nm_connection_add_setting (conn, setting); + + orig_dict = nm_connection_to_dbus (conn, NM_CONNECTION_SERIALIZE_ALL); + g_object_unref (conn); + + /* sanity-check */ + conn = nm_simple_connection_new_from_dbus (orig_dict, &error); + g_assert_no_error (error); + g_assert (conn); + g_object_unref (conn); + + /* Compatible mismatches */ + + dict = g_variant_ref (orig_dict); + NMTST_VARIANT_EDITOR (dict, + NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_RATE, + "i", 10); + ); + conn = nm_simple_connection_new_from_dbus (dict, &error); + g_assert (conn); + g_assert_no_error (error); + setting = nm_connection_get_setting (conn, NM_TYPE_SETTING_WIRELESS); + g_assert (setting); + g_assert_cmpint (nm_setting_wireless_get_rate (NM_SETTING_WIRELESS (setting)), ==, 10); + g_object_unref (conn); + g_variant_unref (dict); + + dict = g_variant_ref (orig_dict); + NMTST_VARIANT_EDITOR (dict, + NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_IP6_PRIVACY, + "i", NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR); + ); + conn = nm_simple_connection_new_from_dbus (dict, &error); + g_assert (conn); + g_assert_no_error (error); + setting = nm_connection_get_setting (conn, NM_TYPE_SETTING_IP6_CONFIG); + g_assert (setting); + g_assert_cmpint (nm_setting_ip6_config_get_ip6_privacy (NM_SETTING_IP6_CONFIG (setting)), ==, NM_SETTING_IP6_CONFIG_PRIVACY_PREFER_TEMP_ADDR); + g_object_unref (conn); + g_variant_unref (dict); + + /* Incompatible mismatches */ + + dict = g_variant_ref (orig_dict); + NMTST_VARIANT_EDITOR (dict, + NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_RATE, + "s", "ten"); + ); + conn = nm_simple_connection_new_from_dbus (dict, &error); + g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert (g_str_has_prefix (error->message, "802-11-wireless.rate:")); + g_clear_error (&error); + g_variant_unref (dict); + + dict = g_variant_ref (orig_dict); + NMTST_VARIANT_EDITOR (dict, + NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_MODE, + "b", FALSE); + ); + conn = nm_simple_connection_new_from_dbus (dict, &error); + g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert (g_str_has_prefix (error->message, "802-11-wireless.mode:")); + g_clear_error (&error); + g_variant_unref (dict); + + dict = g_variant_ref (orig_dict); + NMTST_VARIANT_EDITOR (dict, + NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_SSID, + "s", "fred"); + ); + conn = nm_simple_connection_new_from_dbus (dict, &error); + g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert (g_str_has_prefix (error->message, "802-11-wireless.ssid:")); + g_clear_error (&error); + g_variant_unref (dict); + + dict = g_variant_ref (orig_dict); + NMTST_VARIANT_EDITOR (dict, + NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_BSSID, + "i", 42); + ); + conn = nm_simple_connection_new_from_dbus (dict, &error); + g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert (g_str_has_prefix (error->message, "802-11-wireless.bssid:")); + g_clear_error (&error); + g_variant_unref (dict); + + dict = g_variant_ref (orig_dict); + NMTST_VARIANT_EDITOR (dict, + NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP6_CONFIG_IP6_PRIVACY, + "s", "private"); + ); + conn = nm_simple_connection_new_from_dbus (dict, &error); + g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert (g_str_has_prefix (error->message, "ipv6.ip6-privacy:")); + g_clear_error (&error); + g_variant_unref (dict); + + dict = g_variant_ref (orig_dict); + NMTST_VARIANT_EDITOR (dict, + NMTST_VARIANT_CHANGE_PROPERTY (NM_SETTING_IP6_CONFIG_SETTING_NAME, + NM_SETTING_IP_CONFIG_ADDRESSES, + "s", "1234::5678"); + ); + conn = nm_simple_connection_new_from_dbus (dict, &error); + g_assert_error (error, NM_CONNECTION_ERROR, NM_CONNECTION_ERROR_INVALID_PROPERTY); + g_assert (g_str_has_prefix (error->message, "ipv6.addresses:")); + g_clear_error (&error); + g_variant_unref (dict); + + g_variant_unref (orig_dict); +} + static NMConnection * new_test_connection (void) { @@ -3901,6 +4078,7 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/test_setting_new_from_dbus", test_setting_new_from_dbus); g_test_add_func ("/core/general/test_setting_new_from_dbus_transform", test_setting_new_from_dbus_transform); g_test_add_func ("/core/general/test_setting_new_from_dbus_enum", test_setting_new_from_dbus_enum); + g_test_add_func ("/core/general/test_setting_new_from_dbus_bad", test_setting_new_from_dbus_bad); g_test_add_func ("/core/general/test_connection_replace_settings", test_connection_replace_settings); g_test_add_func ("/core/general/test_connection_replace_settings_from_connection", test_connection_replace_settings_from_connection); g_test_add_func ("/core/general/test_connection_replace_settings_bad", test_connection_replace_settings_bad); |