summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@redhat.com>2015-01-15 12:19:06 -0500
committerDan Winship <danw@redhat.com>2015-01-15 14:46:30 -0500
commit76d9fc91671c50646ecde3de934da47af623a0a1 (patch)
treeb34a9f55b43cc457bda873233f0a3b67bd1934fc
parentd80e100179d408a754402d1c688052cd45bf7bfa (diff)
downloadNetworkManager-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.c54
-rw-r--r--libnm-core/tests/test-general.c178
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);