diff options
author | Thomas Haller <thaller@redhat.com> | 2018-10-25 16:37:43 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2018-10-25 16:37:43 +0200 |
commit | f120bbc7a81982690a3f656cfa8156b1aaee40f0 (patch) | |
tree | df63445e26d09a5e23bd014509582d853869dd2d | |
parent | ec37e18c64ac480fc7c7699e45005894c27c8416 (diff) | |
parent | 9bc33a687ea6eafa7c9e5cb97a31f7880596d0c1 (diff) | |
download | NetworkManager-f120bbc7a81982690a3f656cfa8156b1aaee40f0.tar.gz |
libnm/vpn: merge branch 'th/read-vpn-plugins-tests'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/30
-rw-r--r-- | config.h.meson | 4 | ||||
-rw-r--r-- | configure.ac | 6 | ||||
-rw-r--r-- | libnm/nm-vpn-service-plugin.c | 8 | ||||
-rw-r--r-- | libnm/tests/test-general.c | 274 | ||||
-rw-r--r-- | meson.build | 1 | ||||
-rw-r--r-- | shared/nm-utils/nm-test-utils.h | 1 |
6 files changed, 291 insertions, 3 deletions
diff --git a/config.h.meson b/config.h.meson index e79f9dcb54..c8f9805526 100644 --- a/config.h.meson +++ b/config.h.meson @@ -19,6 +19,10 @@ /* Gettext package */ #mesondefine GETTEXT_PACKAGE +/* Define to 1 if you have the declaration of `memfd_create', and to 0 if you + don't. */ +#mesondefine HAVE_DECL_MEMFD_CREATE + /* Define to 1 if you have the declaration of `reallocarray', and to 0 if you don't. */ #mesondefine HAVE_DECL_REALLOCARRAY diff --git a/configure.ac b/configure.ac index 946f6b35e5..aac2a32340 100644 --- a/configure.ac +++ b/configure.ac @@ -81,6 +81,12 @@ AC_CHECK_DECLS([ #include <malloc.h> ]]) +AC_CHECK_DECLS([ + memfd_create], + [], [], [[ +#include <sys/mman.h> +]]) + AC_CHECK_HEADERS(sys/auxv.h) AC_CHECK_DECLS([getrandom], diff --git a/libnm/nm-vpn-service-plugin.c b/libnm/nm-vpn-service-plugin.c index 8d6c43a260..ed9da7f787 100644 --- a/libnm/nm-vpn-service-plugin.c +++ b/libnm/nm-vpn-service-plugin.c @@ -810,15 +810,14 @@ nm_vpn_service_plugin_read_vpn_details (int fd, errno = 0; nr = read (fd, &c, 1); - if (nr == -1) { + if (nr < 0) { if (errno == EAGAIN) { g_usleep (100); continue; } break; } - - if (c != '\n') { + if (nr > 0 && c != '\n') { g_string_append_c (line, c); continue; } @@ -879,6 +878,9 @@ nm_vpn_service_plugin_read_vpn_details (int fd, } g_string_truncate (line, 0); + + if (nr == 0) + break; } if (success) { diff --git a/libnm/tests/test-general.c b/libnm/tests/test-general.c index 5959a4e62f..410087af64 100644 --- a/libnm/tests/test-general.c +++ b/libnm/tests/test-general.c @@ -20,8 +20,16 @@ #include "nm-default.h" +#if defined (HAVE_DECL_MEMFD_CREATE) && HAVE_DECL_MEMFD_CREATE +#include <linux/memfd.h> +#endif + +#include <sys/mman.h> + #include "nm-libnm-utils.h" +#include "nm-vpn-service-plugin.h" + #include "nm-utils/nm-test-utils.h" /*****************************************************************************/ @@ -2158,6 +2166,271 @@ test_fixup_product_string (void) /*****************************************************************************/ +static int +_memfd_create (const char *name) +{ +#if defined (HAVE_DECL_MEMFD_CREATE) && HAVE_DECL_MEMFD_CREATE + return memfd_create (name, MFD_CLOEXEC); +#endif + return -1; +} + +typedef struct { + const char *key; + const char *val; +} ReadVpnDetailData; + +#define READ_VPN_DETAIL_DATA(...) \ + ((ReadVpnDetailData []) { __VA_ARGS__ }) + +static gboolean +_do_read_vpn_details_impl1 (const char *file, + int line, + int memfd, + char *mem, + gsize len, + const ReadVpnDetailData *expected_data, + guint expected_data_len, + const ReadVpnDetailData *expected_secrets, + guint expected_secrets_len) +{ + gssize written; + off_t lseeked; + gs_unref_hashtable GHashTable *data = NULL; + gs_unref_hashtable GHashTable *secrets = NULL; + + written = write (memfd, mem, len); + g_assert_cmpint (written, ==, (gssize) len); + + lseeked = lseek (memfd, 0, SEEK_SET); + g_assert_cmpint (lseeked, ==, 0); + + if (!nm_vpn_service_plugin_read_vpn_details (memfd, + &data, + &secrets)) { + g_assert (!data); + g_assert (!secrets); + g_assert_cmpint (expected_data_len, ==, 0); + g_assert_cmpint (expected_secrets_len, ==, 0); + return TRUE; + } + +#define _assert_hash(hash, expected, expected_len) \ + G_STMT_START { \ + GHashTable *_hash = (hash); \ + guint _expected_len = (expected_len); \ + const ReadVpnDetailData *_expected = (expected); \ + GHashTableIter _iter; \ + const char *_k, *_v; \ + guint _i; \ + \ + g_assert (_hash); \ + \ + g_hash_table_iter_init (&_iter, _hash); \ + while (g_hash_table_iter_next (&_iter, (gpointer *) &_k, (gpointer *) &_v)) { \ + for (_i = 0; _i < _expected_len; _i++) { \ + if (nm_streq (_expected[_i].key, _k)) \ + break; \ + } \ + if (_i >= _expected_len) \ + g_error ("%s:%d: hash '%s' contains unexpected data key '%s' with value '%s'", file, line, G_STRINGIFY (hash), _k, _v); \ + } \ + \ + for (_i = 0; _i < _expected_len; _i++) { \ + const ReadVpnDetailData *_d = &_expected[_i]; \ + \ + g_assert (_d->key); \ + g_assert (_d->val); \ + _v = g_hash_table_lookup (_hash, _d->key); \ + if (!nm_streq0 (_v, _d->val)) \ + g_error ("%s:%d: hash '%s' contains data key '%s' with value %s%s%s but we expected '%s'", file, line, G_STRINGIFY (hash), _d->key, NM_PRINT_FMT_QUOTE_STRING (_v), _d->val); \ + } \ + \ + g_assert_cmpint (g_hash_table_size (_hash), ==, _expected_len); \ + } G_STMT_END + + _assert_hash (data, expected_data, expected_data_len); + _assert_hash (secrets, expected_secrets, expected_secrets_len); + +#undef _assert_hash + return TRUE; +} + +#define _do_read_vpn_details_impl0(str, expected_data, expected_data_len, expected_secrets, expected_secrets_len, pre_setup_cmd) \ + G_STMT_START { \ + nm_auto_close int _memfd = _memfd_create ("libnm-test-read-vpn-details"); \ + \ + if (_memfd < 0) \ + g_test_skip ("cannot create memfd"); \ + else { \ + { pre_setup_cmd ; } \ + _do_read_vpn_details_impl1 (__FILE__, \ + __LINE__, \ + _memfd, \ + ""str"", \ + NM_STRLEN (str), \ + expected_data, \ + expected_data_len, \ + expected_secrets, \ + expected_secrets_len); \ + } \ + } G_STMT_END + +#define _do_read_vpn_details_empty(str) \ + _do_read_vpn_details_impl0 (str, \ + NULL, \ + 0, \ + NULL, \ + 0, \ + { } ) + +#define _do_read_vpn_details(str, expected_data, expected_secrets, pre_setup_cmd) \ + _do_read_vpn_details_impl0 (str, \ + expected_data, \ + G_N_ELEMENTS (expected_data), \ + expected_secrets, \ + G_N_ELEMENTS (expected_secrets), \ + pre_setup_cmd) + +static void +test_nm_vpn_service_plugin_read_vpn_details (void) +{ + _do_read_vpn_details_empty (""); + _do_read_vpn_details_empty ("hallo"); + _do_read_vpn_details_empty ("DONE"); + _do_read_vpn_details_empty ("DONE\n"); + _do_read_vpn_details_empty ("DONE\0"); + _do_read_vpn_details_empty ("\0DONE\0"); + + _do_read_vpn_details ("" + "DATA_KEY=some-key\n" + "DATA_VAL=string\n" + "\n" + "DATA_KEY=some-other-key\n" + "DATA_VAL=val2\n" + "\n" + "SECRET_KEY=some-secret\n" + "SECRET_VAL=val3\n" + "\n" + "DONE\n" + "\n" + "", + READ_VPN_DETAIL_DATA ( + { "some-key", "string" }, + { "some-other-key", "val2" }, + ), + READ_VPN_DETAIL_DATA ( + { "some-secret", "val3" }, + ), + ); + + _do_read_vpn_details ("" + "DATA_KEY=some-key\n" + "DATA_VAL=string\n" + "DONE\n", + READ_VPN_DETAIL_DATA ( + { "some-key", "string" }, + ), + READ_VPN_DETAIL_DATA (), + ); + + _do_read_vpn_details ("" + "DATA_KEY=some-key\n" + "DATA_VAL=string\n" + "=continued after a line break\n" + "SECRET_KEY=key names\n" + "=can have\n" + "=continuations too\n" + "bogus1=\n" + "SECRET_VAL=value\n" + "bogus=value\n" + "bogus=\n" + "DATA_VAL=x\n" + "DATA_KEY=\n" + "DATA_VAL=\n" + "DATA_VAL=y\n" + "DATA_KEY=y\n" + "DATA_KEY=y\n" + "DATA_KEY=z\n" + "SECRET_KEY=s1\n" + "DATA_VAL=z\n" + "SECRET_VAL=S1\n" + "\n" + "DONE\n" + "", + READ_VPN_DETAIL_DATA ( + { "some-key", "string\ncontinued after a line break" }, + ), + READ_VPN_DETAIL_DATA ( + { "key names\ncan have\ncontinuations too", "value" }, + ), + NMTST_EXPECT_LIBNM_WARNING ("DATA_VAL= not preceded by DATA_KEY=") + ); + + _do_read_vpn_details ("" + "DATA_KEY=some-key\n" + "DATA_VAL=string\n" + "=continued after a line break\n" + "SECRET_KEY=key names\n" + "=can have\n" + "=continuations too\n" + "SECRET_VAL=value\n" + "", + READ_VPN_DETAIL_DATA ( + { "some-key", "string\ncontinued after a line break" }, + ), + READ_VPN_DETAIL_DATA ( + { "key names\ncan have\ncontinuations too", "value" }, + ), + ); + + _do_read_vpn_details ("" + "DATA_KEY=some-key\n" + "DATA_VAL=string\n" + "\n" + "DATA_KEY=some\n" + "=key-2\n" + "DATA_VAL=val2\n" + "\n" + "DATA_KEY=key3\0" + "=key-2\n" + "DATA_VAL=val3\n" + "\n" + "SECRET_KEY=some-secret\n" + "SECRET_VAL=val3\n" + "\n" + "SECRET_KEY=\n" + "SECRET_VAL=val3\n" + "\n" + "SECRET_KEY=keyx\n" + "SECRET_VAL=\n" + "\n" + "SECRET_KEY=ke\xc0yx\n" + "SECRET_VAL=inval\n" + "\n" + "SECRET_KEY=key-inval\n" + "SECRET_VAL=in\xc1val\n" + "\n" + "DONE\n" + "\n" + "", + READ_VPN_DETAIL_DATA ( + { "some\nkey-2", "val2" }, + { "some-key", "string" }, + { "key3", "val3" }, + ), + READ_VPN_DETAIL_DATA ( + { "some-secret", "val3" }, + { "", "val3" }, + { "keyx", "" }, + { "ke\xc0yx", "inval" }, + { "key-inval", "in\xc1val" }, + ), + ); +} + +/*****************************************************************************/ + NMTST_DEFINE (); int main (int argc, char **argv) @@ -2166,6 +2439,7 @@ int main (int argc, char **argv) g_test_add_func ("/libnm/general/fixup_product_string", test_fixup_product_string); g_test_add_func ("/libnm/general/fixup_vendor_string", test_fixup_vendor_string); + g_test_add_func ("/libnm/general/nm_vpn_service_plugin_read_vpn_details", test_nm_vpn_service_plugin_read_vpn_details); return g_test_run (); } diff --git a/meson.build b/meson.build index c7c0bfc589..9bfc6bb3ee 100644 --- a/meson.build +++ b/meson.build @@ -115,6 +115,7 @@ config_h.set('HAVE_SECURE_GETENV', cc.has_function('secure_getenv')) config_h.set('HAVE___SECURE_GETENV', cc.has_function('__secure_getenv')) config_h.set10('HAVE_DECL_REALLOCARRAY', cc.has_function('reallocarray', prefix: '#include <malloc.h>')) config_h.set10('HAVE_DECL_EXPLICIT_BZERO', cc.has_function('explicit_bzero', prefix: '#include <string.h>')) +config_h.set10('HAVE_DECL_MEMFD_CREATE', cc.has_function('memfd_create', prefix: '#include <sys/mman.h>')) # types config_h.set('SIZEOF_DEV_T', cc.sizeof('dev_t', prefix: '#include <sys/types.h>')) diff --git a/shared/nm-utils/nm-test-utils.h b/shared/nm-utils/nm-test-utils.h index 89bd111992..4a329f1534 100644 --- a/shared/nm-utils/nm-test-utils.h +++ b/shared/nm-utils/nm-test-utils.h @@ -700,6 +700,7 @@ nmtst_test_quick (void) #else #define NMTST_EXPECT_LIBNM(level, msg) NMTST_EXPECT ("libnm", level, msg) +#define NMTST_EXPECT_LIBNM_WARNING(msg) NMTST_EXPECT_LIBNM (G_LOG_LEVEL_WARNING, msg) #define NMTST_EXPECT_LIBNM_CRITICAL(msg) NMTST_EXPECT_LIBNM (G_LOG_LEVEL_CRITICAL, msg) #endif |