diff options
Diffstat (limited to 'libnm-core/tests')
| -rw-r--r-- | libnm-core/tests/meson.build | 14 | ||||
| -rw-r--r-- | libnm-core/tests/test-crypto.c | 1 | ||||
| -rw-r--r-- | libnm-core/tests/test-general.c | 405 | ||||
| -rw-r--r-- | libnm-core/tests/test-keyfile.c | 4 | ||||
| -rw-r--r-- | libnm-core/tests/test-secrets.c | 2 | ||||
| -rw-r--r-- | libnm-core/tests/test-setting.c | 692 | ||||
| -rw-r--r-- | libnm-core/tests/test-settings-defaults.c | 2 |
7 files changed, 1074 insertions, 46 deletions
diff --git a/libnm-core/tests/meson.build b/libnm-core/tests/meson.build index 627e6b53..7d772c80 100644 --- a/libnm-core/tests/meson.build +++ b/libnm-core/tests/meson.build @@ -14,7 +14,7 @@ enum = gnome.mkenums( sources: 'test-general-enums.h', identifier_prefix: nm_id_prefix, c_template: enum_types + '.c.template', - h_template: enum_types + '.h.template' + h_template: enum_types + '.h.template', ) test_units = [ @@ -24,7 +24,7 @@ test_units = [ 'test-keyfile', 'test-secrets', 'test-setting', - 'test-settings-defaults' + 'test-settings-defaults', ] test_cert_dir = join_paths(meson.current_source_dir(), 'certs') @@ -33,16 +33,20 @@ foreach test_unit: test_units exe = executable( 'libnm-core-' + test_unit, [test_unit + '.c'] + enum, - dependencies: nm_core_dep, + dependencies: [ + nm_core_dep, + libnm_systemd_shared_no_logging_dep, + ], c_args: [ '-DNETWORKMANAGER_COMPILATION_TEST', '-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_LIBNM_CORE', ], - link_with: libnm_core + link_with: libnm_core, ) test( 'libnm-core/' + test_unit, test_script, - args: test_args + [exe.full_path()] + args: test_args + [exe.full_path()], + timeout: default_test_timeout, ) endforeach diff --git a/libnm-core/tests/test-crypto.c b/libnm-core/tests/test-crypto.c index 6b63e6fd..4ac9679b 100644 --- a/libnm-core/tests/test-crypto.c +++ b/libnm-core/tests/test-crypto.c @@ -26,7 +26,6 @@ #include <unistd.h> #include <stdlib.h> #include <stdio.h> -#include <string.h> #include "nm-crypto-impl.h" #include "nm-utils.h" diff --git a/libnm-core/tests/test-general.c b/libnm-core/tests/test-general.c index 67b80098..7d97296a 100644 --- a/libnm-core/tests/test-general.c +++ b/libnm-core/tests/test-general.c @@ -23,8 +23,6 @@ #include "nm-default.h" -#include <string.h> - #include "nm-utils/c-list-util.h" #include "nm-utils/nm-enum-utils.h" @@ -755,10 +753,12 @@ vpn_check_empty_func (const char *key, const char *value, gpointer user_data) static void test_setting_vpn_items (void) { - gs_unref_object NMSettingVpn *s_vpn = NULL; + gs_unref_object NMConnection *connection = NULL; + NMSettingVpn *s_vpn; - s_vpn = (NMSettingVpn *) nm_setting_vpn_new (); - g_assert (s_vpn); + connection = nmtst_create_minimal_connection ("vpn-items", NULL, NM_SETTING_VPN_SETTING_NAME, NULL); + + s_vpn = nm_connection_get_setting_vpn (connection); nm_setting_vpn_add_data_item (s_vpn, "foobar1", "blahblah1"); nm_setting_vpn_add_data_item (s_vpn, "foobar2", "blahblah2"); @@ -772,7 +772,14 @@ test_setting_vpn_items (void) nm_setting_vpn_remove_data_item (s_vpn, "foobar3"); nm_setting_vpn_remove_data_item (s_vpn, "foobar4"); + g_assert (!_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); + g_assert (!_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL)); + nm_setting_vpn_add_secret (s_vpn, "foobar1", "blahblah1"); + + g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); + g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL)); + nm_setting_vpn_add_secret (s_vpn, "foobar2", "blahblah2"); nm_setting_vpn_add_secret (s_vpn, "foobar3", "blahblah3"); nm_setting_vpn_add_secret (s_vpn, "foobar4", "blahblah4"); @@ -782,8 +789,25 @@ test_setting_vpn_items (void) nm_setting_vpn_remove_secret (s_vpn, "foobar1"); nm_setting_vpn_remove_secret (s_vpn, "foobar2"); nm_setting_vpn_remove_secret (s_vpn, "foobar3"); + + g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); + g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL)); + + nm_setting_vpn_add_data_item (s_vpn, "foobar4-flags", "blahblah4"); + + g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL)); + + nm_setting_vpn_add_data_item (s_vpn, "foobar4-flags", "2"); + + g_assert (!_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL)); + nm_setting_vpn_remove_secret (s_vpn, "foobar4"); + g_assert (!_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); + g_assert (!_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL)); + + nm_setting_vpn_remove_data_item (s_vpn, "foobar4-flags"); + /* Try to add some blank values and make sure they are rejected */ NMTST_EXPECT_LIBNM_CRITICAL (NMTST_G_RETURN_MSG (key != NULL)); nm_setting_vpn_add_data_item (s_vpn, NULL, NULL); @@ -1351,8 +1375,6 @@ test_setting_gsm_apn_bad_chars (void) s_gsm = (NMSettingGsm *) nm_setting_gsm_new (); g_assert (s_gsm); - g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, "*99#", NULL); - /* Make sure a valid APN works */ g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar123.-baz", NULL); g_assert (nm_setting_verify (NM_SETTING (s_gsm), NULL, NULL)); @@ -1382,8 +1404,6 @@ test_setting_gsm_apn_underscore (void) s_gsm = (NMSettingGsm *) nm_setting_gsm_new (); g_assert (s_gsm); - g_object_set (s_gsm, NM_SETTING_GSM_NUMBER, "*99#", NULL); - /* 65-character long */ g_object_set (s_gsm, NM_SETTING_GSM_APN, "foobar_baz", NULL); nmtst_assert_setting_verifies (NM_SETTING (s_gsm)); @@ -1636,6 +1656,25 @@ test_connection_to_dbus_setting_name (void) s_wsec = make_test_wsec_setting ("connection-to-dbus-setting-name"); nm_connection_add_setting (connection, NM_SETTING (s_wsec)); + g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); + g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL)); + + g_object_set (s_wsec, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, NM_SETTING_SECRET_FLAG_NOT_SAVED, + NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_NOT_SAVED, + NULL); + + g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); + g_assert (!_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL)); + + g_object_set (s_wsec, + NM_SETTING_WIRELESS_SECURITY_WEP_KEY_FLAGS, NM_SETTING_SECRET_FLAG_NONE, + NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD_FLAGS, NM_SETTING_SECRET_FLAG_NONE, + NULL); + + g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SECRETS, NULL)); + g_assert (_nm_connection_aggregate (connection, NM_CONNECTION_AGGREGATE_ANY_SYSTEM_SECRET_FLAGS, NULL)); + dict = nm_connection_to_dbus (connection, NM_CONNECTION_SERIALIZE_ALL); /* Make sure the keys of the first level dict are setting names, not @@ -2946,7 +2985,6 @@ test_connection_good_base_types (void) setting = nm_setting_gsm_new (); g_object_set (setting, - NM_SETTING_GSM_NUMBER, "*99#", NM_SETTING_GSM_APN, "metered.billing.sucks", NULL); nm_connection_add_setting (connection, setting); @@ -3267,11 +3305,110 @@ test_data_compare_secrets_new (NMSettingSecretFlags secret_flags, } static void +_test_compare_secrets_check_diff (NMSetting *a, + NMSetting *b, + NMSettingCompareFlags flags, + gboolean exp_same_psk, + gboolean exp_same_psk_flags) +{ + gs_unref_hashtable GHashTable *h = NULL; + NMSettingDiffResult _RESULT_IN_A = NM_SETTING_DIFF_RESULT_IN_A; + NMSettingDiffResult _RESULT_IN_B = NM_SETTING_DIFF_RESULT_IN_B; + gboolean invert_results; + gboolean diff_result; + NMSettingSecretFlags a_psk_flags = nm_setting_wireless_security_get_psk_flags (NM_SETTING_WIRELESS_SECURITY (a)); + NMSettingSecretFlags b_psk_flags = nm_setting_wireless_security_get_psk_flags (NM_SETTING_WIRELESS_SECURITY (b)); + const char *a_psk = nm_setting_wireless_security_get_psk (NM_SETTING_WIRELESS_SECURITY (a)); + const char *b_psk = nm_setting_wireless_security_get_psk (NM_SETTING_WIRELESS_SECURITY (b)); + + g_assert (NM_IS_SETTING_WIRELESS_SECURITY (a)); + g_assert (NM_IS_SETTING_WIRELESS_SECURITY (b)); + + invert_results = nmtst_get_rand_bool (); + if (invert_results) { + _RESULT_IN_A = NM_SETTING_DIFF_RESULT_IN_B; + _RESULT_IN_B = NM_SETTING_DIFF_RESULT_IN_A; + } + + diff_result = nm_setting_diff (a, b, flags, invert_results, &h); + + g_assert (exp_same_psk_flags == (a_psk_flags == b_psk_flags)); + + if (nm_streq0 (a_psk, b_psk)) + g_assert (exp_same_psk); + else { + if (flags == NM_SETTING_COMPARE_FLAG_EXACT) + g_assert (!exp_same_psk); + else if (flags == NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS) { + if ( !NM_FLAGS_HAS (a_psk_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED) + && !NM_FLAGS_HAS (b_psk_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)) + g_assert (!exp_same_psk); + else if ( !NM_FLAGS_HAS (a_psk_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED) + && NM_FLAGS_HAS (b_psk_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)) + g_assert (!exp_same_psk); + else + g_assert (exp_same_psk); + } else if (flags == NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS) { + if ( !NM_FLAGS_HAS (a_psk_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED) + && !NM_FLAGS_HAS (b_psk_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED)) + g_assert (!exp_same_psk); + else if ( !NM_FLAGS_HAS (a_psk_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED) + && NM_FLAGS_HAS (b_psk_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED)) + g_assert (!exp_same_psk); + else + g_assert (exp_same_psk); + } else if (flags == NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS) + g_assert (exp_same_psk); + else + g_assert_not_reached (); + } + + g_assert (diff_result == (exp_same_psk && exp_same_psk_flags)); + g_assert (diff_result == (!h)); + + if (!diff_result) { + if (flags == NM_SETTING_COMPARE_FLAG_EXACT) + g_assert (!exp_same_psk); + else if ( NM_IN_SET (flags, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS, + NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS) + && (a_psk_flags != b_psk_flags) + && nm_setting_wireless_security_get_psk_flags (NM_SETTING_WIRELESS_SECURITY (a)) == NM_SETTING_SECRET_FLAG_NONE) + g_assert (!exp_same_psk); + else + g_assert (exp_same_psk); + + g_assert ((!exp_same_psk) == g_hash_table_contains (h, NM_SETTING_WIRELESS_SECURITY_PSK)); + if (!exp_same_psk) { + if (nm_setting_wireless_security_get_psk (NM_SETTING_WIRELESS_SECURITY (a))) + g_assert_cmpint (GPOINTER_TO_UINT (g_hash_table_lookup (h, NM_SETTING_WIRELESS_SECURITY_PSK)), ==, _RESULT_IN_A); + else + g_assert_cmpint (GPOINTER_TO_UINT (g_hash_table_lookup (h, NM_SETTING_WIRELESS_SECURITY_PSK)), ==, _RESULT_IN_B); + } + + g_assert ((!exp_same_psk_flags) == g_hash_table_contains (h, NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS)); + if (!exp_same_psk_flags) { + if (nm_setting_wireless_security_get_psk_flags (NM_SETTING_WIRELESS_SECURITY (a)) != NM_SETTING_SECRET_FLAG_NONE) + g_assert_cmpint (GPOINTER_TO_UINT (g_hash_table_lookup (h, NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS)), ==, _RESULT_IN_A); + else + g_assert_cmpint (GPOINTER_TO_UINT (g_hash_table_lookup (h, NM_SETTING_WIRELESS_SECURITY_PSK_FLAGS)), ==, _RESULT_IN_B); + } + + g_assert_cmpint (g_hash_table_size (h), ==, (!exp_same_psk) + (!exp_same_psk_flags)); + } + + g_assert (diff_result == nm_setting_compare (a, b, flags)); + g_assert (diff_result == nm_setting_compare (b, a, flags)); + +} + +static void test_setting_compare_secrets (gconstpointer test_data) { const TestDataCompareSecrets *data = test_data; - gs_unref_object NMSetting *old = NULL, *new = NULL; - gboolean success; + gs_unref_object NMConnection *conn_old = NULL; + gs_unref_object NMConnection *conn_new = NULL; + gs_unref_object NMSetting *old = NULL; + gs_unref_object NMSetting *new = NULL; /* Make sure that a connection with transient/unsaved secrets compares * successfully to the same connection without those secrets. @@ -3284,17 +3421,45 @@ test_setting_compare_secrets (gconstpointer test_data) NULL); nm_setting_set_secret_flags (old, NM_SETTING_WIRELESS_SECURITY_PSK, data->secret_flags, NULL); - /* Clear the PSK from the duplicated setting */ new = nm_setting_duplicate (old); - if (data->remove_secret) { + if (data->remove_secret) g_object_set (new, NM_SETTING_WIRELESS_SECURITY_PSK, NULL, NULL); - success = nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT); - g_assert (success == FALSE); + g_assert ((!data->remove_secret) == nm_setting_compare (old, new, NM_SETTING_COMPARE_FLAG_EXACT)); + g_assert ((!data->remove_secret) == nm_setting_compare (new, old, NM_SETTING_COMPARE_FLAG_EXACT)); + + _test_compare_secrets_check_diff (old, new, NM_SETTING_COMPARE_FLAG_EXACT, !data->remove_secret, TRUE); + _test_compare_secrets_check_diff (new, old, NM_SETTING_COMPARE_FLAG_EXACT, !data->remove_secret, TRUE); + + g_assert (nm_setting_compare (old, new, data->comp_flags)); + g_assert (nm_setting_compare (new, old, data->comp_flags)); + + _test_compare_secrets_check_diff (old, new, data->comp_flags, TRUE, TRUE); + _test_compare_secrets_check_diff (new, old, data->comp_flags, TRUE, TRUE); + + /* OK. Try again, but this time not only change the secret, also let the secret flags differ... */ + if (data->secret_flags != NM_SETTING_SECRET_FLAG_NONE) { + nm_setting_set_secret_flags (new, NM_SETTING_WIRELESS_SECURITY_PSK, NM_SETTING_SECRET_FLAG_NONE, NULL); + + _test_compare_secrets_check_diff (old, new, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, FALSE); + _test_compare_secrets_check_diff (new, old, NM_SETTING_COMPARE_FLAG_EXACT, FALSE, FALSE); + + _test_compare_secrets_check_diff (old, new, data->comp_flags, TRUE, FALSE); + _test_compare_secrets_check_diff (new, old, data->comp_flags, FALSE, FALSE); + + nm_setting_set_secret_flags (new, NM_SETTING_WIRELESS_SECURITY_PSK, data->secret_flags, NULL); } - success = nm_setting_compare (old, new, data->comp_flags); - g_assert (success); + conn_old = nmtst_create_minimal_connection ("test-compare-secrets", NULL, NM_SETTING_WIRELESS_SETTING_NAME, NULL); + nm_connection_add_setting (conn_old, nm_setting_duplicate (old)); + conn_new = nm_simple_connection_new_clone (conn_old); + nm_connection_add_setting (conn_new, nm_setting_duplicate (new)); + + g_assert ((!data->remove_secret) == nm_connection_compare (conn_old, conn_new, NM_SETTING_COMPARE_FLAG_EXACT)); + g_assert ((!data->remove_secret) == nm_connection_compare (conn_new, conn_old, NM_SETTING_COMPARE_FLAG_EXACT)); + + g_assert (nm_connection_compare (conn_old, conn_new, data->comp_flags)); + g_assert (nm_connection_compare (conn_new, conn_old, data->comp_flags)); } static void @@ -3473,6 +3638,41 @@ test_connection_changed_cb (NMConnection *connection, gboolean *data) *data = TRUE; } +static guint32 +_netmask_to_prefix (guint32 netmask) +{ + guint32 prefix; + guint8 v; + const guint8 *p = (guint8 *) &netmask; + + if (p[3]) { + prefix = 24; + v = p[3]; + } else if (p[2]) { + prefix = 16; + v = p[2]; + } else if (p[1]) { + prefix = 8; + v = p[1]; + } else { + prefix = 0; + v = p[0]; + } + + while (v) { + prefix++; + v <<= 1; + } + + g_assert_cmpint (prefix, <=, 32); + + /* we re-implemented the netmask-to-prefix code differently. Check + * that they agree. */ + g_assert_cmpint (prefix, ==, nm_utils_ip4_netmask_to_prefix (netmask)); + + return prefix; +} + static void test_ip4_prefix_to_netmask (void) { @@ -3480,7 +3680,7 @@ test_ip4_prefix_to_netmask (void) for (i = 0; i<=32; i++) { guint32 netmask = _nm_utils_ip4_prefix_to_netmask (i); - int plen = nm_utils_ip4_netmask_to_prefix (netmask); + int plen = _netmask_to_prefix (netmask); g_assert_cmpint (i, ==, plen); { @@ -3510,7 +3710,7 @@ test_ip4_netmask_to_prefix (void) guint32 netmask = _nm_utils_ip4_prefix_to_netmask (i); guint32 netmask_lowest_bit = netmask & ~_nm_utils_ip4_prefix_to_netmask (i-1); - g_assert_cmpint (i, ==, nm_utils_ip4_netmask_to_prefix (netmask)); + g_assert_cmpint (i, ==, _netmask_to_prefix (netmask)); for (j = 0; j < 2*i; j++) { guint32 r = g_rand_int (rand); @@ -3524,7 +3724,7 @@ test_ip4_netmask_to_prefix (void) /* create an invalid netmask with holes and check that the function * returns the longest prefix. */ - prefix_holey = nm_utils_ip4_netmask_to_prefix (netmask_holey); + prefix_holey = _netmask_to_prefix (netmask_holey); g_assert_cmpint (i, ==, prefix_holey); } @@ -5054,7 +5254,7 @@ test_setting_ip4_gateway (void) GVariantBuilder addrs_builder; GError *error = NULL; - g_assert_cmpstr (nm_utils_inet4_ntop (addr_vals_0[0], NULL), ==, "192.168.1.10"); + nmtst_assert_ip4_address (addr_vals_0[0], "192.168.1.10"); /* When serializing on the daemon side, ipv4.gateway is copied to the first * entry of ipv4.addresses @@ -5096,7 +5296,7 @@ test_setting_ip4_gateway (void) addr_array = g_variant_get_fixed_array (addr_var, &length, sizeof (guint32)); g_assert_cmpint (length, ==, 3); - g_assert_cmpstr (nm_utils_inet4_ntop (addr_array[2], NULL), ==, "192.168.1.1"); + nmtst_assert_ip4_address (addr_array[2], "192.168.1.1"); g_variant_unref (addr_var); } g_variant_unref (value); @@ -5203,7 +5403,7 @@ test_setting_ip6_gateway (void) gateway_bytes = g_variant_get_fixed_array (gateway_var, &length, 1); g_assert_cmpint (length, ==, 16); - g_assert_cmpstr (nm_utils_inet6_ntop ((struct in6_addr *) gateway_bytes, NULL), ==, "abcd::1"); + nmtst_assert_ip6_address ((struct in6_addr *) gateway_bytes, "abcd::1"); g_variant_unref (gateway_var); } g_variant_unref (value); @@ -5322,6 +5522,158 @@ test_setting_user_data (void) /*****************************************************************************/ +typedef union { + struct sockaddr sa; + struct sockaddr_in in; + struct sockaddr_in6 in6; +} SockAddrUnion; + +static void +_sock_addr_endpoint (const char *endpoint, + const char *host, + gint32 port) +{ + nm_auto_unref_sockaddrendpoint NMSockAddrEndpoint *ep = NULL; + const char *s_endpoint; + const char *s_host; + gint32 s_port; + SockAddrUnion sockaddr = { }; + + g_assert (endpoint); + g_assert (!host == (port == -1)); + g_assert (port >= -1 && port <= G_MAXUINT16); + + ep = nm_sock_addr_endpoint_new (endpoint); + g_assert (ep); + + s_endpoint = nm_sock_addr_endpoint_get_endpoint (ep); + s_host = nm_sock_addr_endpoint_get_host (ep); + s_port = nm_sock_addr_endpoint_get_port (ep); + g_assert_cmpstr (endpoint, ==, s_endpoint); + g_assert_cmpstr (host, ==, s_host); + g_assert_cmpint (port, ==, s_port); + + g_assert (!nm_sock_addr_endpoint_get_fixed_sockaddr (ep, &sockaddr)); + + if (endpoint[0] != ' ') { + gs_free char *endpoint2 = NULL; + + /* also test with a leading space */ + endpoint2 = g_strdup_printf (" %s", endpoint); + _sock_addr_endpoint (endpoint2, host, port); + } + + if (endpoint[0] && endpoint[strlen (endpoint) - 1] != ' ') { + gs_free char *endpoint2 = NULL; + + /* also test with a trailing space */ + endpoint2 = g_strdup_printf ("%s ", endpoint); + _sock_addr_endpoint (endpoint2, host, port); + } +} + +static void +_sock_addr_endpoint_fixed (const char *endpoint, + const char *host, + guint16 port, + guint scope_id) +{ + nm_auto_unref_sockaddrendpoint NMSockAddrEndpoint *ep = NULL; + const char *s_endpoint; + const char *s_host; + gint32 s_port; + int addr_family; + NMIPAddr addrbin; + SockAddrUnion sockaddr = { }; + + g_assert (endpoint); + g_assert (host); + g_assert (port > 0); + + if (!nm_utils_parse_inaddr_bin (AF_UNSPEC, host, &addr_family, &addrbin)) + g_assert_not_reached (); + + ep = nm_sock_addr_endpoint_new (endpoint); + g_assert (ep); + + s_endpoint = nm_sock_addr_endpoint_get_endpoint (ep); + s_host = nm_sock_addr_endpoint_get_host (ep); + s_port = nm_sock_addr_endpoint_get_port (ep); + g_assert_cmpstr (endpoint, ==, s_endpoint); + g_assert_cmpstr (NULL, !=, s_host); + g_assert_cmpint (port, ==, s_port); + + if (!nm_sock_addr_endpoint_get_fixed_sockaddr (ep, &sockaddr)) + g_assert_not_reached (); + + g_assert_cmpint (sockaddr.sa.sa_family, ==, addr_family); + if (addr_family == AF_INET) { + const SockAddrUnion s = { + .in = { + .sin_family = AF_INET, + .sin_addr = addrbin.addr4_struct, + .sin_port = htons (port), + }, + }; + + g_assert_cmpint (sockaddr.in.sin_addr.s_addr, ==, addrbin.addr4); + g_assert_cmpint (sockaddr.in.sin_port, ==, htons (port)); + g_assert (memcmp (&s, &sockaddr, sizeof (s.in)) == 0); + } else if (addr_family == AF_INET6) { + const SockAddrUnion s = { + .in6 = { + .sin6_family = AF_INET6, + .sin6_addr = addrbin.addr6, + .sin6_scope_id = scope_id, + .sin6_port = htons (port), + }, + }; + + g_assert (memcmp (&sockaddr.in6.sin6_addr, &addrbin, sizeof (addrbin.addr6)) == 0); + g_assert_cmpint (sockaddr.in6.sin6_port, ==, htons (port)); + g_assert_cmpint (sockaddr.in6.sin6_scope_id, ==, scope_id); + g_assert_cmpint (sockaddr.in6.sin6_flowinfo, ==, 0); + g_assert (memcmp (&s, &sockaddr, sizeof (s.in6)) == 0); + } else + g_assert_not_reached (); +} + +static void +test_sock_addr_endpoint (void) +{ + _sock_addr_endpoint ("", NULL, -1); + _sock_addr_endpoint (":", NULL, -1); + _sock_addr_endpoint ("a", NULL, -1); + _sock_addr_endpoint ("a:", NULL, -1); + _sock_addr_endpoint (":a", NULL, -1); + _sock_addr_endpoint ("[]:a", NULL, -1); + _sock_addr_endpoint ("[]a", NULL, -1); + _sock_addr_endpoint ("[]:", NULL, -1); + _sock_addr_endpoint ("[a]b", NULL, -1); + _sock_addr_endpoint ("[a:b", NULL, -1); + _sock_addr_endpoint ("[a[:b", NULL, -1); + _sock_addr_endpoint ("a:6", "a", 6); + _sock_addr_endpoint ("a:6", "a", 6); + _sock_addr_endpoint ("[a]:6", "a", 6); + _sock_addr_endpoint ("[a]:6", "a", 6); + _sock_addr_endpoint ("[a]:655", "a", 655); + _sock_addr_endpoint ("[ab]:][6", NULL, -1); + _sock_addr_endpoint ("[ab]:]:[6", NULL, -1); + _sock_addr_endpoint ("[a[]:b", NULL, -1); + _sock_addr_endpoint ("[192.169.6.x]:6", "192.169.6.x", 6); + _sock_addr_endpoint ("[192.169.6.x]:0", NULL, -1); + _sock_addr_endpoint ("192.169.6.7:0", NULL, -1); + + _sock_addr_endpoint_fixed ("192.169.6.7:6", "192.169.6.7", 6, 0); + _sock_addr_endpoint_fixed ("[192.169.6.7]:6", "192.169.6.7", 6, 0); + _sock_addr_endpoint_fixed ("[a:b::]:6", "a:b::", 6, 0); + _sock_addr_endpoint_fixed ("[a:b::%7]:6", "a:b::", 6, 7); + _sock_addr_endpoint_fixed ("a:b::1%75:6", "a:b::1", 6, 75); + _sock_addr_endpoint_fixed ("a:b::1%0:64", "a:b::1", 64, 0); +} + +/*****************************************************************************/ + static void test_hexstr2bin (void) { @@ -5687,7 +6039,7 @@ __test_uuid (const char *expected_uuid, const char *str, gssize slen, char *uuid static void test_nm_utils_uuid_generate_from_strings (void) { - const NMUuid uuid0 = { 0 }; + const NMUuid uuid0 = { }; g_assert_cmpmem (&uuid0, sizeof (uuid0), _uuid ("00000000-0000-0000-0000-000000000000"), 16); @@ -7535,6 +7887,8 @@ int main (int argc, char **argv) g_test_add_func ("/core/general/test_setting_compare_default_strv", test_setting_compare_default_strv); g_test_add_func ("/core/general/test_setting_user_data", test_setting_user_data); + g_test_add_func ("/core/general/test_sock_addr_endpoint", test_sock_addr_endpoint); + g_test_add_func ("/core/general/hexstr2bin", test_hexstr2bin); g_test_add_func ("/core/general/nm_strquote", test_nm_strquote); g_test_add_func ("/core/general/test_nm_utils_uuid_generate_from_string", test_nm_utils_uuid_generate_from_string); @@ -7564,4 +7918,3 @@ int main (int argc, char **argv) return g_test_run (); } - diff --git a/libnm-core/tests/test-keyfile.c b/libnm-core/tests/test-keyfile.c index 78e01ce9..9b9d1c04 100644 --- a/libnm-core/tests/test-keyfile.c +++ b/libnm-core/tests/test-keyfile.c @@ -249,7 +249,7 @@ _keyfile_convert (NMConnection **con, k0_c1_k2 = _nm_keyfile_write (k0_c1, write_handler, write_data); k0_c1_k2_c3 = _nm_keyfile_read (k0_c1_k2, keyfile_name, read_handler, read_data, FALSE); - /* It is a expeced behavior, that if @k0 contains a relative path ca-cert, @k0_c1 will + /* It is a expected behavior, that if @k0 contains a relative path ca-cert, @k0_c1 will * contain that path as relative. But @k0_c1_k2 and @k0_c1_k2_c3 will have absolute paths. * In this case, hack up @k0_c1_k2_c3 to contain the same relative path. */ s1 = nm_connection_get_setting_802_1x (k0_c1); @@ -417,7 +417,7 @@ test_8021x_cert (void) g_assert_no_error (error); g_assert (success); - /* test reseting ca-cert to different values and see whether we can write/read. */ + /* test resetting ca-cert to different values and see whether we can write/read. */ nm_connection_add_setting (con, NM_SETTING (s_8021x)); nmtst_assert_connection_verifies_and_normalizable (con); diff --git a/libnm-core/tests/test-secrets.c b/libnm-core/tests/test-secrets.c index d31c43d2..5debe5cf 100644 --- a/libnm-core/tests/test-secrets.c +++ b/libnm-core/tests/test-secrets.c @@ -21,8 +21,6 @@ #include "nm-default.h" -#include <string.h> - #include "nm-setting-8021x.h" #include "nm-setting-cdma.h" #include "nm-setting-connection.h" diff --git a/libnm-core/tests/test-setting.c b/libnm-core/tests/test-setting.c index 4e010feb..2011273a 100644 --- a/libnm-core/tests/test-setting.c +++ b/libnm-core/tests/test-setting.c @@ -20,7 +20,6 @@ #include "nm-default.h" #include <linux/pkt_sched.h> -#include <string.h> #include "nm-utils.h" #include "nm-utils-private.h" @@ -45,6 +44,101 @@ /*****************************************************************************/ +/* converts @dict to a connection. In this case, @dict must be good, without warnings, so that + * NM_SETTING_PARSE_FLAGS_STRICT and NM_SETTING_PARSE_FLAGS_BEST_EFFORT yield the exact same results. */ +static NMConnection * +_connection_new_from_dbus_strict (GVariant *dict, + gboolean normalize) +{ + gs_unref_object NMConnection *con_x_0 = NULL; + gs_unref_object NMConnection *con_x_s = NULL; + gs_unref_object NMConnection *con_x_e = NULL; + gs_unref_object NMConnection *con_n_0 = NULL; + gs_unref_object NMConnection *con_n_s = NULL; + gs_unref_object NMConnection *con_n_e = NULL; + gs_free_error GError *error = NULL; + guint i; + + g_assert (g_variant_is_of_type (dict, NM_VARIANT_TYPE_CONNECTION)); + + con_x_0 = _nm_simple_connection_new_from_dbus (dict, NM_SETTING_PARSE_FLAGS_NONE, &error); + nmtst_assert_success (NM_IS_CONNECTION (con_x_0), error); + + con_x_s = _nm_simple_connection_new_from_dbus (dict, NM_SETTING_PARSE_FLAGS_STRICT, &error); + nmtst_assert_success (NM_IS_CONNECTION (con_x_s), error); + + con_x_e = _nm_simple_connection_new_from_dbus (dict, NM_SETTING_PARSE_FLAGS_BEST_EFFORT, &error); + nmtst_assert_success (NM_IS_CONNECTION (con_x_e), error); + + con_n_0 = _nm_simple_connection_new_from_dbus (dict, NM_SETTING_PARSE_FLAGS_NORMALIZE, &error); + nmtst_assert_success (NM_IS_CONNECTION (con_n_0), error); + + con_n_s = _nm_simple_connection_new_from_dbus (dict, NM_SETTING_PARSE_FLAGS_STRICT | NM_SETTING_PARSE_FLAGS_NORMALIZE, &error); + nmtst_assert_success (NM_IS_CONNECTION (con_n_s), error); + + con_n_e = _nm_simple_connection_new_from_dbus (dict, NM_SETTING_PARSE_FLAGS_BEST_EFFORT | NM_SETTING_PARSE_FLAGS_NORMALIZE, &error); + nmtst_assert_success (NM_IS_CONNECTION (con_n_e), error); + + nmtst_assert_connection_verifies (con_x_0); + nmtst_assert_connection_verifies (con_x_e); + nmtst_assert_connection_verifies (con_x_s); + + nmtst_assert_connection_verifies_without_normalization (con_n_0); + nmtst_assert_connection_verifies_without_normalization (con_n_e); + nmtst_assert_connection_verifies_without_normalization (con_n_s); + + /* randomly compare some pairs that we created. They must all be equal, + * after accounting for normalization. */ + for (i = 0; i < 10; i++) { + NMConnection *cons[] = { con_x_0, con_x_s, con_x_e, con_n_0, con_n_s, con_n_e }; + guint idx_a = (nmtst_get_rand_int () % G_N_ELEMENTS (cons)); + guint idx_b = (nmtst_get_rand_int () % G_N_ELEMENTS (cons)); + gboolean normalize_a, normalize_b; + + if (idx_a <= 2 && idx_b <= 2) { + normalize_a = nmtst_get_rand_bool (); + normalize_b = normalize_a; + } else if (idx_a > 2 && idx_b > 2) { + normalize_a = nmtst_get_rand_bool (); + normalize_b = nmtst_get_rand_bool (); + } else { + normalize_a = (idx_a <= 2) ? TRUE : nmtst_get_rand_bool (); + normalize_b = (idx_b <= 2) ? TRUE : nmtst_get_rand_bool (); + } + nmtst_assert_connection_equals (cons[idx_a], normalize_a, cons[idx_b], normalize_b); + } + + return (normalize) + ? g_steal_pointer (&con_x_0) + : g_steal_pointer (&con_n_0); +} + +/*****************************************************************************/ + +static char * +_create_random_ipaddr (int addr_family, gboolean as_service) +{ + char delimiter = as_service ? ':' : '/'; + int num; + + if (addr_family == AF_UNSPEC) + addr_family = nmtst_rand_select (AF_INET, AF_INET6); + + g_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6)); + + if (as_service) + num = (nmtst_get_rand_int () % 1000) + 30000; + else + num = addr_family == AF_INET ? 32 : 128; + + if (addr_family == AF_INET) + return g_strdup_printf ("192.168.%u.%u%c%d", nmtst_get_rand_int () % 256, nmtst_get_rand_int () % 256, delimiter, num); + else + return g_strdup_printf ("a:b:c::%02x:%02x%c%d", nmtst_get_rand_int () % 256, nmtst_get_rand_int () % 256, delimiter, num); +} + +/*****************************************************************************/ + static void compare_blob_data (const char *test, const char *key_path, @@ -421,20 +515,17 @@ create_bond_connection (NMConnection **con, NMSettingBond **s_bond) } #define test_verify_options(exp, ...) \ - G_STMT_START { \ - const char *__opts[] = { __VA_ARGS__ , NULL }; \ - \ - _test_verify_options (__opts, exp); \ - } G_STMT_END + _test_verify_options (NM_MAKE_STRV (__VA_ARGS__), exp) static void -_test_verify_options (const char **options, gboolean expected_result) +_test_verify_options (const char *const *options, + gboolean expected_result) { gs_unref_object NMConnection *con = NULL; NMSettingBond *s_bond; GError *error = NULL; gboolean success; - const char **option; + const char *const *option; create_bond_connection (&con, &s_bond); @@ -1946,6 +2037,587 @@ test_tc_config_dbus (void) /*****************************************************************************/ +static GPtrArray * +_rndt_wg_peers_create (void) +{ + GPtrArray *wg_peers; + guint i, n; + + wg_peers = g_ptr_array_new_with_free_func ((GDestroyNotify) nm_wireguard_peer_unref); + + n = nmtst_get_rand_int () % 10; + for (i = 0; i < n; i++) { + NMWireGuardPeer *peer; + guint8 public_key_buf[NM_WIREGUARD_PUBLIC_KEY_LEN]; + guint8 preshared_key_buf[NM_WIREGUARD_SYMMETRIC_KEY_LEN]; + gs_free char *public_key = NULL; + gs_free char *preshared_key = NULL; + gs_free char *s_endpoint = NULL; + guint i_aip, n_aip; + + /* we don't bother to create a valid curve25519 public key. Of course, libnm cannot + * check whether the public key is bogus or not. Hence, for our purpose a random + * bogus key is good enough. */ + public_key = g_base64_encode (nmtst_rand_buf (NULL, public_key_buf, sizeof (public_key_buf)), sizeof (public_key_buf)); + + preshared_key = g_base64_encode (nmtst_rand_buf (NULL, preshared_key_buf, sizeof (preshared_key_buf)), sizeof (preshared_key_buf)); + + s_endpoint = _create_random_ipaddr (AF_UNSPEC, TRUE); + + peer = nm_wireguard_peer_new (); + if (!nm_wireguard_peer_set_public_key (peer, public_key, TRUE)) + g_assert_not_reached (); + + if (!nm_wireguard_peer_set_preshared_key (peer, nmtst_rand_select (NULL, preshared_key), TRUE)) + g_assert_not_reached (); + + nm_wireguard_peer_set_preshared_key_flags (peer, nmtst_rand_select (NM_SETTING_SECRET_FLAG_NONE, + NM_SETTING_SECRET_FLAG_NOT_SAVED, + NM_SETTING_SECRET_FLAG_AGENT_OWNED)); + + nm_wireguard_peer_set_persistent_keepalive (peer, + nmtst_rand_select ((guint32) 0, nmtst_get_rand_int ())); + + if (!nm_wireguard_peer_set_endpoint (peer, nmtst_rand_select (s_endpoint, NULL), TRUE)) + g_assert_not_reached (); + + n_aip = nmtst_rand_select (0, nmtst_get_rand_int () % 10); + for (i_aip = 0; i_aip < n_aip; i_aip++) { + gs_free char *aip = NULL; + + aip = _create_random_ipaddr (AF_UNSPEC, FALSE); + if (!nm_wireguard_peer_append_allowed_ip (peer, aip, FALSE)) + g_assert_not_reached (); + } + + g_assert (nm_wireguard_peer_is_valid (peer, TRUE, TRUE, NULL)); + + nm_wireguard_peer_seal (peer); + g_ptr_array_add (wg_peers, peer); + } + + return wg_peers; +} + +static const char * +_rndt_wg_peers_to_keyfile (GPtrArray *wg_peers, + gboolean strict, + char **out_str) +{ + nm_auto_free_gstring GString *gstr = NULL; + nm_auto_free_gstring GString *gstr_aip = NULL; + guint i, j; + + g_assert (wg_peers); + g_assert (out_str && !*out_str); + + nm_gstring_prepare (&gstr); + for (i = 0; i < wg_peers->len; i++) { + const NMWireGuardPeer *peer = wg_peers->pdata[i]; + gs_free char *s_endpoint = NULL; + gs_free char *s_preshared_key = NULL; + gs_free char *s_preshared_key_flags = NULL; + gs_free char *s_persistent_keepalive = NULL; + gs_free char *s_allowed_ips = NULL; + + if (nm_wireguard_peer_get_endpoint (peer)) + s_endpoint = g_strdup_printf ("endpoint=%s\n", nm_wireguard_peer_get_endpoint (peer)); + else if (!strict) + s_endpoint = g_strdup_printf ("endpoint=\n"); + + if ( nm_wireguard_peer_get_preshared_key (peer) + || !strict) { + if (nm_wireguard_peer_get_preshared_key_flags (peer) == NM_SETTING_SECRET_FLAG_NONE) + s_preshared_key = g_strdup_printf ("preshared-key=%s\n", nm_wireguard_peer_get_preshared_key (peer) ?: ""); + } + + if ( nm_wireguard_peer_get_preshared_key_flags (peer) != NM_SETTING_SECRET_FLAG_NOT_REQUIRED + || !strict) + s_preshared_key_flags = g_strdup_printf ("preshared-key-flags=%d\n", (int) nm_wireguard_peer_get_preshared_key_flags (peer)); + + if ( nm_wireguard_peer_get_persistent_keepalive (peer) != 0 + || !strict) + s_persistent_keepalive = g_strdup_printf ("persistent-keepalive=%u\n", nm_wireguard_peer_get_persistent_keepalive (peer)); + + if ( nm_wireguard_peer_get_allowed_ips_len (peer) > 0 + || !strict) { + nm_gstring_prepare (&gstr_aip); + for (j = 0; j < nm_wireguard_peer_get_allowed_ips_len (peer); j++) + g_string_append_printf (gstr_aip, "%s;", nm_wireguard_peer_get_allowed_ip (peer, j, NULL)); + s_allowed_ips = g_strdup_printf ("allowed-ips=%s\n", gstr_aip->str); + } + + if ( !s_endpoint + && !s_preshared_key + && !s_preshared_key_flags + && !s_persistent_keepalive + && !s_allowed_ips) + s_endpoint = g_strdup_printf ("endpoint=\n"); + + g_string_append_printf (gstr, + "\n" + "[wireguard-peer.%s]\n" + "%s" /* endpoint */ + "%s" /* preshared-key */ + "%s" /* preshared-key-flags */ + "%s" /* persistent-keepalive */ + "%s" /* allowed-ips */ + "", + nm_wireguard_peer_get_public_key (peer), + s_endpoint ?: "", + s_preshared_key ?: "", + s_preshared_key_flags ?: "", + s_persistent_keepalive ?: "", + s_allowed_ips ?: ""); + } + + return (*out_str = g_string_free (g_steal_pointer (&gstr), FALSE)); +} + +static void +_rndt_wg_peers_assert_equal (NMSettingWireGuard *s_wg, + GPtrArray *peers, + gboolean consider_persistent_secrets, + gboolean consider_all_secrets, + gboolean expect_no_secrets) +{ + guint i; + + g_assert (NM_IS_SETTING_WIREGUARD (s_wg)); + g_assert (peers); + + g_assert_cmpint (peers->len, ==, nm_setting_wireguard_get_peers_len (s_wg)); + + for (i = 0; i < peers->len; i++) { + const NMWireGuardPeer *a = peers->pdata[i]; + const NMWireGuardPeer *b = nm_setting_wireguard_get_peer (s_wg, i); + gboolean consider_secrets; + + g_assert (a); + g_assert (b); + + g_assert_cmpint (nm_wireguard_peer_cmp (a, b, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS), ==, 0); + + if ( consider_all_secrets + || !nm_wireguard_peer_get_preshared_key (a)) + consider_secrets = TRUE; + else if (nm_wireguard_peer_get_preshared_key (b)) + consider_secrets = TRUE; + else if ( consider_persistent_secrets + && nm_wireguard_peer_get_preshared_key_flags (b) == NM_SETTING_SECRET_FLAG_NONE) + consider_secrets = TRUE; + else + consider_secrets = FALSE; + + if (consider_secrets) { + g_assert_cmpstr (nm_wireguard_peer_get_preshared_key (a), ==, nm_wireguard_peer_get_preshared_key (b)); + g_assert_cmpint (nm_wireguard_peer_cmp (a, b, NM_SETTING_COMPARE_FLAG_EXACT), ==, 0); + } + + if (expect_no_secrets) + g_assert_cmpstr (nm_wireguard_peer_get_preshared_key (b), ==, NULL); + } +} + +static void +_rndt_wg_peers_fix_secrets (NMSettingWireGuard *s_wg, + GPtrArray *peers) +{ + guint i; + + g_assert (NM_IS_SETTING_WIREGUARD (s_wg)); + g_assert (peers); + + g_assert_cmpint (peers->len, ==, nm_setting_wireguard_get_peers_len (s_wg)); + + for (i = 0; i < peers->len; i++) { + const NMWireGuardPeer *a = peers->pdata[i]; + const NMWireGuardPeer *b = nm_setting_wireguard_get_peer (s_wg, i); + nm_auto_unref_wgpeer NMWireGuardPeer *b_clone = NULL; + + g_assert (a); + g_assert (b); + + g_assert_cmpint (nm_wireguard_peer_get_preshared_key_flags (a), ==, nm_wireguard_peer_get_preshared_key_flags (b)); + g_assert_cmpint (nm_wireguard_peer_cmp (a, b, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS), ==, 0); + + if (!nm_streq0 (nm_wireguard_peer_get_preshared_key (a), + nm_wireguard_peer_get_preshared_key (b))) { + g_assert_cmpstr (nm_wireguard_peer_get_preshared_key (a), !=, NULL); + g_assert_cmpstr (nm_wireguard_peer_get_preshared_key (b), ==, NULL); + g_assert (NM_IN_SET (nm_wireguard_peer_get_preshared_key_flags (a), NM_SETTING_SECRET_FLAG_AGENT_OWNED, + NM_SETTING_SECRET_FLAG_NOT_SAVED)); + b_clone = nm_wireguard_peer_new_clone (b, TRUE); + if (!nm_wireguard_peer_set_preshared_key (b_clone, nm_wireguard_peer_get_preshared_key (a), TRUE)) + g_assert_not_reached (); + nm_setting_wireguard_set_peer (s_wg, b_clone, i); + b = nm_setting_wireguard_get_peer (s_wg, i); + g_assert (b == b_clone); + } else { + if (nm_wireguard_peer_get_preshared_key (a)) { + g_assert (NM_IN_SET (nm_wireguard_peer_get_preshared_key_flags (a), NM_SETTING_SECRET_FLAG_NONE, + NM_SETTING_SECRET_FLAG_NOT_REQUIRED)); + } else { + g_assert (NM_IN_SET (nm_wireguard_peer_get_preshared_key_flags (a), NM_SETTING_SECRET_FLAG_AGENT_OWNED, + NM_SETTING_SECRET_FLAG_NONE, + NM_SETTING_SECRET_FLAG_NOT_SAVED, + NM_SETTING_SECRET_FLAG_NOT_REQUIRED)); + } + } + + g_assert_cmpstr (nm_wireguard_peer_get_preshared_key (a), ==, nm_wireguard_peer_get_preshared_key (b)); + g_assert_cmpint (nm_wireguard_peer_cmp (a, b, NM_SETTING_COMPARE_FLAG_EXACT), ==, 0); + } +} + +static void +test_roundtrip_conversion (gconstpointer test_data) +{ + const int MODE = GPOINTER_TO_INT (test_data); + const char *ID= nm_sprintf_bufa (100, "roundtip-conversion-%d", MODE); + const char *UUID= "63376701-b61e-4318-bf7e-664a1c1eeaab"; + const char *INTERFACE_NAME = nm_sprintf_bufa (100, "ifname%d", MODE); + guint32 ETH_MTU = nmtst_rand_select ((guint32) 0u, + nmtst_get_rand_int ()); + const char *WG_PRIVATE_KEY = nmtst_get_rand_bool () + ? "yGXGK+5bVnxSJUejH4vbpXbq+ZtaG4NB8IHRK/aVtE0=" + : NULL; + const NMSettingSecretFlags WG_PRIVATE_KEY_FLAGS = nmtst_rand_select (NM_SETTING_SECRET_FLAG_NONE, + NM_SETTING_SECRET_FLAG_NOT_SAVED, + NM_SETTING_SECRET_FLAG_AGENT_OWNED); + const guint WG_LISTEN_PORT = nmtst_rand_select (0u, + nmtst_get_rand_int () % 0x10000); + const guint WG_FWMARK = nmtst_rand_select (0u, + nmtst_get_rand_int ()); + gs_unref_ptrarray GPtrArray *kf_data_arr = g_ptr_array_new_with_free_func (g_free); + gs_unref_ptrarray GPtrArray *wg_peers = NULL; + const NMConnectionSerializationFlags dbus_serialization_flags[] = { + NM_CONNECTION_SERIALIZE_ALL, + NM_CONNECTION_SERIALIZE_NO_SECRETS, + NM_CONNECTION_SERIALIZE_ONLY_SECRETS, + }; + guint dbus_serialization_flags_idx; + gs_unref_object NMConnection *con = NULL; + gs_free_error GError *error = NULL; + gs_free char *tmp_str = NULL; + guint kf_data_idx; + NMSettingConnection *s_con = NULL; + NMSettingWired *s_eth = NULL; + NMSettingWireGuard *s_wg = NULL; + guint i; + + switch (MODE) { + case 0: + con = nmtst_create_minimal_connection (ID, UUID, NM_SETTING_WIRED_SETTING_NAME, &s_con); + g_object_set (s_con, + NM_SETTING_CONNECTION_INTERFACE_NAME, + INTERFACE_NAME, + NULL); + nmtst_connection_normalize (con); + + s_eth = NM_SETTING_WIRED (nm_connection_get_setting (con, NM_TYPE_SETTING_WIRED)); + g_assert (NM_IS_SETTING_WIRED (s_eth)); + + g_object_set (s_eth, + NM_SETTING_WIRED_MTU, + ETH_MTU, + NULL); + + g_ptr_array_add (kf_data_arr, + g_strdup_printf ("[connection]\n" + "id=%s\n" + "uuid=%s\n" + "type=ethernet\n" + "interface-name=%s\n" + "permissions=\n" + "\n" + "[ethernet]\n" + "mac-address-blacklist=\n" + "%s" /* mtu */ + "\n" + "[ipv4]\n" + "dns-search=\n" + "method=auto\n" + "\n" + "[ipv6]\n" + "addr-gen-mode=stable-privacy\n" + "dns-search=\n" + "method=auto\n" + "", + ID, + UUID, + INTERFACE_NAME, + (ETH_MTU != 0) + ? nm_sprintf_bufa (100, "mtu=%u\n", ETH_MTU) + : "")); + + g_ptr_array_add (kf_data_arr, + g_strdup_printf ("[connection]\n" + "id=%s\n" + "uuid=%s\n" + "type=ethernet\n" + "interface-name=%s\n" + "permissions=\n" + "\n" + "[ethernet]\n" + "mac-address-blacklist=\n" + "%s" /* mtu */ + "\n" + "[ipv4]\n" + "dns-search=\n" + "method=auto\n" + "\n" + "[ipv6]\n" + "addr-gen-mode=stable-privacy\n" + "dns-search=\n" + "method=auto\n" + "", + ID, + UUID, + INTERFACE_NAME, + (ETH_MTU != 0) + ? nm_sprintf_bufa (100, "mtu=%d\n", (int) ETH_MTU) + : "")); + + break; + + case 1: + con = nmtst_create_minimal_connection (ID, UUID, "wireguard", &s_con); + g_object_set (s_con, + NM_SETTING_CONNECTION_INTERFACE_NAME, + INTERFACE_NAME, + NULL); + nmtst_connection_normalize (con); + + s_wg = NM_SETTING_WIREGUARD (nm_connection_get_setting (con, NM_TYPE_SETTING_WIREGUARD)); + + g_ptr_array_add (kf_data_arr, + g_strdup_printf ("[connection]\n" + "id=%s\n" + "uuid=%s\n" + "type=wireguard\n" + "interface-name=%s\n" + "permissions=\n" + "\n" + "[ipv4]\n" + "dns-search=\n" + "method=disabled\n" + "\n" + "[ipv6]\n" + "addr-gen-mode=stable-privacy\n" + "dns-search=\n" + "method=ignore\n" + "", + ID, + UUID, + INTERFACE_NAME)); + break; + + case 2: + con = nmtst_create_minimal_connection (ID, UUID, "wireguard", &s_con); + g_object_set (s_con, + NM_SETTING_CONNECTION_INTERFACE_NAME, + INTERFACE_NAME, + NULL); + nmtst_connection_normalize (con); + + s_wg = NM_SETTING_WIREGUARD (nm_connection_get_setting (con, NM_TYPE_SETTING_WIREGUARD)); + g_object_set (s_wg, + NM_SETTING_WIREGUARD_PRIVATE_KEY, + WG_PRIVATE_KEY, + NM_SETTING_WIREGUARD_PRIVATE_KEY_FLAGS, + WG_PRIVATE_KEY_FLAGS, + NM_SETTING_WIREGUARD_LISTEN_PORT, + WG_LISTEN_PORT, + NM_SETTING_WIREGUARD_FWMARK, + WG_FWMARK, + NULL); + + wg_peers = _rndt_wg_peers_create (); + + for (i = 0; i < wg_peers->len; i++) + nm_setting_wireguard_append_peer (s_wg, wg_peers->pdata[i]); + + nm_clear_g_free (&tmp_str); + + g_ptr_array_add (kf_data_arr, + g_strdup_printf ("[connection]\n" + "id=%s\n" + "uuid=%s\n" + "type=wireguard\n" + "interface-name=%s\n" + "permissions=\n" + "%s" /* [wireguard] */ + "%s" /* fwmark */ + "%s" /* listen-port */ + "%s" /* private-key-flags */ + "%s" /* private-key */ + "%s" /* [wireguard-peers*] */ + "\n" + "[ipv4]\n" + "dns-search=\n" + "method=disabled\n" + "\n" + "[ipv6]\n" + "addr-gen-mode=stable-privacy\n" + "dns-search=\n" + "method=ignore\n" + "", + ID, + UUID, + INTERFACE_NAME, + ( ( (WG_FWMARK != 0) + || (WG_LISTEN_PORT != 0) + || (WG_PRIVATE_KEY_FLAGS != NM_SETTING_SECRET_FLAG_NONE) + || ( WG_PRIVATE_KEY + && WG_PRIVATE_KEY_FLAGS == NM_SETTING_SECRET_FLAG_NONE)) + ? "\n[wireguard]\n" + : ""), + ( (WG_FWMARK != 0) + ? nm_sprintf_bufa (100, "fwmark=%u\n", WG_FWMARK) + : ""), + ( (WG_LISTEN_PORT != 0) + ? nm_sprintf_bufa (100, "listen-port=%u\n", WG_LISTEN_PORT) + : ""), + ( (WG_PRIVATE_KEY_FLAGS != NM_SETTING_SECRET_FLAG_NONE) + ? nm_sprintf_bufa (100, "private-key-flags=%u\n", (guint) WG_PRIVATE_KEY_FLAGS) + : ""), + ( ( WG_PRIVATE_KEY + && WG_PRIVATE_KEY_FLAGS == NM_SETTING_SECRET_FLAG_NONE) + ? nm_sprintf_bufa (100, "private-key=%s\n", WG_PRIVATE_KEY) + : ""), + _rndt_wg_peers_to_keyfile (wg_peers, TRUE, &tmp_str))); + + _rndt_wg_peers_assert_equal (s_wg, wg_peers, TRUE, TRUE, FALSE); + break; + + default: + g_assert_not_reached (); + } + + /* the first kf_data_arr entry is special: it is the exact result of what we expect + * when converting @con to keyfile. Write @con to keyfile and compare the expected result + * literally. */ + { + gs_unref_keyfile GKeyFile *kf = NULL; + + kf = nm_keyfile_write (con, NULL, NULL, &error); + nmtst_assert_success (kf, error); + + /* the first kf_data_arr entry is special: it must be what the writer would + * produce again. */ + nmtst_keyfile_assert_data (kf, kf_data_arr->pdata[0], -1); + } + + /* check that reading any of kf_data_arr yields the same result that we expect. */ + for (kf_data_idx = 0; kf_data_idx < kf_data_arr->len; kf_data_idx++) { + gs_unref_object NMConnection *con2 = NULL; + NMSettingWireGuard *s_wg2 = NULL; + NMSettingWired *s_eth2 = NULL; + + con2 = nmtst_create_connection_from_keyfile (kf_data_arr->pdata[kf_data_idx], "/no/where/file.nmconnection"); + + switch (MODE) { + case 0: + s_eth2 = NM_SETTING_WIRED (nm_connection_get_setting (con2, NM_TYPE_SETTING_WIRED)); + g_assert (NM_IS_SETTING_WIRED (s_eth2)); + + if ( ETH_MTU > (guint32) G_MAXINT + && kf_data_idx == 1) { + /* older versions wrote values > 2^21 as signed integers, but the reader would + * always reject such negative values for G_TYPE_UINT. + * + * The test case kf_data_idx #1 still writes the values in the old style. + * The behavior was fixed, but such values are still rejected as invalid. + * + * Patch the setting so that the comparison below succeeds are usual. */ + g_assert_cmpint (nm_setting_wired_get_mtu (s_eth2), ==, 0); + g_object_set (s_eth2, + NM_SETTING_WIRED_MTU, + ETH_MTU, + NULL); + } + + g_assert_cmpint (nm_setting_wired_get_mtu (s_eth), ==, ETH_MTU); + g_assert_cmpint (nm_setting_wired_get_mtu (s_eth2), ==, ETH_MTU); + break; + + case 1: + s_wg2 = NM_SETTING_WIREGUARD (nm_connection_get_setting (con2, NM_TYPE_SETTING_WIREGUARD)); + g_assert (NM_IS_SETTING_WIREGUARD (s_wg2)); + + g_assert_cmpstr (nm_setting_wireguard_get_private_key (s_wg), ==, NULL); + g_assert_cmpstr (nm_setting_wireguard_get_private_key (s_wg2), ==, NULL); + break; + + case 2: + s_wg2 = NM_SETTING_WIREGUARD (nm_connection_get_setting (con2, NM_TYPE_SETTING_WIREGUARD)); + g_assert (NM_IS_SETTING_WIREGUARD (s_wg2)); + + /* the private key was lost due to the secret-flags. Patch it. */ + if (WG_PRIVATE_KEY_FLAGS != NM_SETTING_SECRET_FLAG_NONE) { + g_assert_cmpstr (nm_setting_wireguard_get_private_key (s_wg2), ==, NULL); + g_object_set (s_wg2, + NM_SETTING_WIREGUARD_PRIVATE_KEY, + WG_PRIVATE_KEY, + NULL); + } + + g_assert_cmpstr (nm_setting_wireguard_get_private_key (s_wg), ==, WG_PRIVATE_KEY); + g_assert_cmpstr (nm_setting_wireguard_get_private_key (s_wg2), ==, WG_PRIVATE_KEY); + + _rndt_wg_peers_assert_equal (s_wg2, wg_peers, TRUE, FALSE, FALSE); + _rndt_wg_peers_fix_secrets (s_wg2, wg_peers); + _rndt_wg_peers_assert_equal (s_wg2, wg_peers, TRUE, TRUE, FALSE); + break; + } + + nmtst_assert_connection_equals (con, nmtst_get_rand_bool (), con2, nmtst_get_rand_bool ()); + } + + for (dbus_serialization_flags_idx = 0; dbus_serialization_flags_idx < G_N_ELEMENTS (dbus_serialization_flags); dbus_serialization_flags_idx++) { + NMConnectionSerializationFlags flag = dbus_serialization_flags[dbus_serialization_flags_idx]; + gs_unref_variant GVariant *con_var = NULL; + gs_unref_object NMConnection *con2 = NULL; + NMSettingWireGuard *s_wg2 = NULL; + + con_var = nm_connection_to_dbus (con, flag); + g_assert (g_variant_is_of_type (con_var, NM_VARIANT_TYPE_CONNECTION)); + g_assert (g_variant_is_floating (con_var)); + g_variant_ref_sink (con_var); + + if (flag == NM_CONNECTION_SERIALIZE_ALL) { + con2 = _connection_new_from_dbus_strict (con_var, TRUE); + nmtst_assert_connection_equals (con, nmtst_get_rand_bool (), con2, nmtst_get_rand_bool ()); + + { + gs_unref_keyfile GKeyFile *kf = NULL; + + kf = nm_keyfile_write (con2, NULL, NULL, &error); + nmtst_assert_success (kf, error); + nmtst_keyfile_assert_data (kf, kf_data_arr->pdata[0], -1); + } + } + + switch (MODE) { + case 2: + if (flag == NM_CONNECTION_SERIALIZE_ALL) { + s_wg2 = NM_SETTING_WIREGUARD (nm_connection_get_setting (con2, NM_TYPE_SETTING_WIREGUARD)); + + if (flag == NM_CONNECTION_SERIALIZE_ALL) + _rndt_wg_peers_assert_equal (s_wg2, wg_peers, TRUE, TRUE, FALSE); + else if (flag == NM_CONNECTION_SERIALIZE_NO_SECRETS) + _rndt_wg_peers_assert_equal (s_wg2, wg_peers, FALSE, FALSE, TRUE); + else + g_assert_not_reached (); + } + break; + } + } +} + +/*****************************************************************************/ + NMTST_DEFINE (); int @@ -2022,5 +2694,9 @@ main (int argc, char **argv) g_test_add_func ("/libnm/settings/team-port/sycn_from_config_full", test_team_port_full_config); #endif + g_test_add_data_func ("/libnm/settings/roundtrip-conversion/general/0", GINT_TO_POINTER (0), test_roundtrip_conversion); + g_test_add_data_func ("/libnm/settings/roundtrip-conversion/wireguard/1", GINT_TO_POINTER (1), test_roundtrip_conversion); + g_test_add_data_func ("/libnm/settings/roundtrip-conversion/wireguard/2", GINT_TO_POINTER (2), test_roundtrip_conversion); + return g_test_run (); } diff --git a/libnm-core/tests/test-settings-defaults.c b/libnm-core/tests/test-settings-defaults.c index 95570b03..9e640543 100644 --- a/libnm-core/tests/test-settings-defaults.c +++ b/libnm-core/tests/test-settings-defaults.c @@ -21,8 +21,6 @@ #include "nm-default.h" -#include <string.h> - #include "nm-utils.h" #include "nm-setting-8021x.h" #include "nm-setting-cdma.h" |