diff options
| author | Michael Biebl <biebl@debian.org> | 2021-10-01 23:05:04 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2021-10-01 23:05:04 +0200 |
| commit | e74c568b07b50b97873fb4ee1d776dedefbd54d6 (patch) | |
| tree | 3469f17ea9af91f7ff169b890633bda68b0cf76e /src/libnm-core-impl/tests/test-keyfile.c | |
| parent | bfe522304da217296e2a61040f58e35ec5d6f3f2 (diff) | |
New upstream version 1.32.12 upstream/1.32.12
Diffstat (limited to 'src/libnm-core-impl/tests/test-keyfile.c')
| -rw-r--r-- | src/libnm-core-impl/tests/test-keyfile.c | 909 |
1 files changed, 909 insertions, 0 deletions
diff --git a/src/libnm-core-impl/tests/test-keyfile.c b/src/libnm-core-impl/tests/test-keyfile.c new file mode 100644 index 00000000..ba7d783b --- /dev/null +++ b/src/libnm-core-impl/tests/test-keyfile.c @@ -0,0 +1,909 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2015 Red Hat, Inc. + */ + +#include "libnm-core-impl/nm-default-libnm-core.h" + +#include "libnm-glib-aux/nm-json-aux.h" +#include "libnm-core-intern/nm-keyfile-utils.h" +#include "libnm-core-intern/nm-keyfile-internal.h" +#include "nm-simple-connection.h" +#include "nm-setting-connection.h" +#include "nm-setting-wired.h" +#include "nm-setting-8021x.h" +#include "nm-setting-team.h" +#include "nm-setting-user.h" +#include "nm-setting-proxy.h" + +#include "libnm-glib-aux/nm-test-utils.h" + +#define TEST_CERT_DIR NM_BUILD_SRCDIR "/src/libnm-core-impl/tests/certs" +#define TEST_WIRED_TLS_CA_CERT TEST_CERT_DIR "/test-ca-cert.pem" +#define TEST_WIRED_TLS_PRIVKEY TEST_CERT_DIR "/test-key-and-cert.pem" +#define TEST_WIRED_TLS_TPM2KEY TEST_CERT_DIR "/test-tpm2wrapped-key.pem" + +/*****************************************************************************/ + +static void +do_test_encode_key_full(GKeyFile * kf, + const char *name, + const char *key, + const char *key_decode_encode) +{ + gs_free char *to_free1 = NULL; + gs_free char *to_free2 = NULL; + const char * key2; + const char * name2; + + g_assert(key); + + if (name) { + key2 = nm_keyfile_key_encode(name, &to_free1); + g_assert(key2); + g_assert(NM_STRCHAR_ALL(key2, ch, (guchar) ch < 127)); + g_assert_cmpstr(key2, ==, key); + + /* try to add the encoded key to the keyfile. We expect + * no g_critical warning about invalid key. */ + g_key_file_set_value(kf, "group", key, "dummy"); + } + + name2 = nm_keyfile_key_decode(key, &to_free2); + if (name) + g_assert_cmpstr(name2, ==, name); + else { + key2 = nm_keyfile_key_encode(name2, &to_free1); + g_assert(key2); + g_assert(NM_STRCHAR_ALL(key2, ch, (guchar) ch < 127)); + if (key_decode_encode) + g_assert_cmpstr(key2, ==, key_decode_encode); + g_key_file_set_value(kf, "group", key2, "dummy"); + } +} + +#define do_test_encode_key_bijection(kf, name, key) \ + do_test_encode_key_full(kf, "" name, "" key, NULL) +#define do_test_encode_key_identity(kf, name) do_test_encode_key_full(kf, "" name, "" name, NULL) +#define do_test_encode_key_decode_surjection(kf, key, key_decode_encode) \ + do_test_encode_key_full(kf, NULL, "" key, "" key_decode_encode) + +static void +test_encode_key(void) +{ + nm_auto_unref_keyfile GKeyFile *kf = g_key_file_new(); + + do_test_encode_key_identity(kf, "a"); + do_test_encode_key_bijection(kf, "", "\\00"); + do_test_encode_key_bijection(kf, " ", "\\20"); + do_test_encode_key_bijection(kf, "\\ ", "\\\\20"); + do_test_encode_key_identity(kf, "\\0"); + do_test_encode_key_identity(kf, "\\a"); + do_test_encode_key_identity(kf, "\\0g"); + do_test_encode_key_bijection(kf, "\\0f", "\\5C0f"); + do_test_encode_key_bijection(kf, "\\0f ", "\\5C0f\\20"); + do_test_encode_key_bijection(kf, " \\0f ", "\\20\\5C0f\\20"); + do_test_encode_key_bijection(kf, "\xF5", "\\F5"); + do_test_encode_key_bijection(kf, "\x7F", "\\7F"); + do_test_encode_key_bijection(kf, "\x1f", "\\1F"); + do_test_encode_key_bijection(kf, " ", "\\20\\20"); + do_test_encode_key_bijection(kf, " ", "\\20 \\20"); + do_test_encode_key_decode_surjection(kf, "f\\20c", "f c"); + do_test_encode_key_decode_surjection(kf, "\\20\\20\\20", "\\20 \\20"); + + do_test_encode_key_bijection(kf, "\t", "\\09"); + do_test_encode_key_bijection(kf, "\t=x", "\\09\\3Dx"); + do_test_encode_key_bijection( + kf, + "(nm-openvpn-auth-dialog:10283): GdkPixbuf-DEBUG: \tCopy pixels == false", + "(nm-openvpn-auth-dialog:10283): GdkPixbuf-DEBUG: \\09Copy pixels \\3D\\3D false"); +} + +/*****************************************************************************/ + +#define CLEAR(con, keyfile) \ + G_STMT_START \ + { \ + NMConnection **_con = (con); \ + GKeyFile ** _keyfile = (keyfile); \ + \ + g_clear_object(_con); \ + nm_clear_pointer(_keyfile, g_key_file_unref); \ + } \ + G_STMT_END + +static void +_assert_gbytes(GBytes *bytes, gconstpointer data, gssize len) +{ + g_assert((data && len > 0) || !len || (data && len == -1)); + + if (len == -1) + len = strlen(data); + + if (!len) + g_assert(!bytes); + + g_assert(nm_utils_gbytes_equal_mem(bytes, data, len)); +} + +static GKeyFile * +_keyfile_load_from_data(const char *str) +{ + GError * error = NULL; + gboolean success; + GKeyFile *keyfile; + + g_assert(str); + + keyfile = g_key_file_new(); + success = g_key_file_load_from_data(keyfile, str, strlen(str), G_KEY_FILE_NONE, &error); + g_assert_no_error(error); + g_assert(success); + + return keyfile; +} + +static GKeyFile * +_nm_keyfile_write(NMConnection *connection, NMKeyfileWriteHandler handler, void *user_data) +{ + GError * error = NULL; + GKeyFile *kf; + + g_assert(NM_IS_CONNECTION(connection)); + + kf = nm_keyfile_write(connection, NM_KEYFILE_HANDLER_FLAGS_NONE, handler, user_data, &error); + g_assert_no_error(error); + g_assert(kf); + return kf; +} + +static NMConnection * +_nm_keyfile_read(GKeyFile * keyfile, + const char * keyfile_name, + NMKeyfileReadHandler read_handler, + void * read_data, + gboolean needs_normalization) +{ + GError * error = NULL; + NMConnection *con; + gs_free char *filename = NULL; + gs_free char *base_dir = NULL; + + g_assert(keyfile); + g_assert(!keyfile_name || (keyfile_name[0] == '/')); + + base_dir = g_path_get_dirname(keyfile_name); + filename = g_path_get_basename(keyfile_name); + + con = nm_keyfile_read(keyfile, + base_dir, + NM_KEYFILE_HANDLER_FLAGS_NONE, + read_handler, + read_data, + &error); + g_assert_no_error(error); + g_assert(NM_IS_CONNECTION(con)); + + nm_keyfile_read_ensure_id(con, filename); + nm_keyfile_read_ensure_uuid(con, keyfile_name); + + if (needs_normalization) { + nmtst_assert_connection_verifies_after_normalization(con, 0, 0); + nmtst_connection_normalize(con); + } else { + { + NMSettingConnection *s_con; + + /* a non-slave connection must have a proxy setting, but + * keyfile reader does not add that (unless a [proxy] section + * is present. */ + s_con = nm_connection_get_setting_connection(con); + if (s_con && !nm_setting_connection_get_master(s_con) + && !nm_connection_get_setting_proxy(con)) + nm_connection_add_setting(con, nm_setting_proxy_new()); + } + nmtst_assert_connection_verifies_without_normalization(con); + } + return con; +} + +static void +_keyfile_convert(NMConnection ** con, + GKeyFile ** keyfile, + const char * keyfile_name, + NMKeyfileReadHandler read_handler, + void * read_data, + NMKeyfileWriteHandler write_handler, + void * write_data, + gboolean needs_normalization) +{ + NMConnection * c0; + GKeyFile * k0; + gs_unref_object NMConnection *c0_k1_c2 = NULL, *k0_c1 = NULL, *k0_c1_k2_c3 = NULL; + nm_auto_unref_keyfile GKeyFile *k0_c1_k2 = NULL, *c0_k1 = NULL, *c0_k1_c2_k3 = NULL; + + /* convert from @con to @keyfile and check that we can make + * full round trips and obtaining the same result. */ + + g_assert(con); + g_assert(keyfile); + g_assert(*con || *keyfile); + + c0 = *con; + k0 = *keyfile; + + if (c0) { + c0_k1 = _nm_keyfile_write(c0, write_handler, write_data); + c0_k1_c2 = _nm_keyfile_read(c0_k1, keyfile_name, read_handler, read_data, FALSE); + c0_k1_c2_k3 = _nm_keyfile_write(c0_k1_c2, write_handler, write_data); + + g_assert(_nm_keyfile_equal(c0_k1, c0_k1_c2_k3, TRUE)); + } + if (k0) { + NMSetting8021x *s1, *s2; + + k0_c1 = _nm_keyfile_read(k0, keyfile_name, read_handler, read_data, needs_normalization); + 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 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); + s2 = nm_connection_get_setting_802_1x(k0_c1_k2_c3); + if (s1 || s2) { + g_assert_cmpint(nm_setting_802_1x_get_ca_cert_scheme(s1), + ==, + nm_setting_802_1x_get_ca_cert_scheme(s2)); + switch (nm_setting_802_1x_get_ca_cert_scheme(s1)) { + case NM_SETTING_802_1X_CK_SCHEME_PATH: + { + const char *p1 = nm_setting_802_1x_get_ca_cert_path(s1); + const char *p2 = nm_setting_802_1x_get_ca_cert_path(s2); + + nmtst_assert_resolve_relative_path_equals(p1, p2); + if (strcmp(p1, p2) != 0) { + gs_free char * puri = NULL; + gs_unref_bytes GBytes *pfile = NULL; + + g_assert(p1[0] != '/' && p2[0] == '/'); + + /* one of the paths is a relative path and the other is absolute. This is an + * expected difference. + * Make the paths of s2 identical to s1... */ + puri = g_strconcat(NM_SETTING_802_1X_CERT_SCHEME_PREFIX_PATH, p1, NULL); + pfile = g_bytes_new(puri, strlen(puri) + 1); + g_object_set(s2, NM_SETTING_802_1X_CA_CERT, pfile, NULL); + } + } break; + case NM_SETTING_802_1X_CK_SCHEME_BLOB: + { + GBytes *b1, *b2; + + b1 = nm_setting_802_1x_get_ca_cert_blob(s1); + b2 = nm_setting_802_1x_get_ca_cert_blob(s2); + g_assert(b1); + g_assert(b2); + g_assert(g_bytes_equal(b1, b2)); + break; + } + default: + break; + } + } + + nmtst_assert_connection_equals(k0_c1, FALSE, k0_c1_k2_c3, FALSE); + } + + if (!k0) + *keyfile = g_key_file_ref(c0_k1); + else if (!c0) + *con = g_object_ref(k0_c1); + else { + /* finally, if both a keyfile and a connection are given, assert that they are equal + * after a round of conversion. */ + g_assert(_nm_keyfile_equal(c0_k1, k0_c1_k2, TRUE)); + nmtst_assert_connection_equals(k0_c1, FALSE, c0_k1_c2, FALSE); + } +} + +/*****************************************************************************/ + +static void +_test_8021x_cert_check(NMConnection * con, + NMSetting8021xCKScheme expected_scheme, + const void * value, + gssize val_len) +{ + GKeyFile * keyfile = NULL; + NMSetting8021x *s_8021x; + gs_free char * kval = NULL; + + _keyfile_convert(&con, &keyfile, "/_test_8021x_cert_check/foo", NULL, NULL, NULL, NULL, FALSE); + + s_8021x = nm_connection_get_setting_802_1x(con); + + g_assert(nm_setting_802_1x_get_ca_cert_scheme(s_8021x) == expected_scheme); + + if (expected_scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) { + const char *path = nm_setting_802_1x_get_ca_cert_path(s_8021x); + + g_assert_cmpstr(path, ==, value); + g_assert(val_len == -1 || strlen(path) == val_len); + + kval = g_key_file_get_string(keyfile, "802-1x", "ca-cert", NULL); + g_assert(kval); + g_assert_cmpstr(kval, ==, value); + } else if (expected_scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) { + GBytes * blob = nm_setting_802_1x_get_ca_cert_blob(s_8021x); + gs_free char *file_blob = NULL; + + if (val_len == -1) { + gsize l; + gboolean success; + + success = g_file_get_contents(value, &file_blob, &l, NULL); + g_assert(success); + + value = file_blob; + val_len = l; + } + + g_assert(blob); + g_assert(nm_utils_gbytes_equal_mem(blob, value, val_len)); + + kval = g_key_file_get_string(keyfile, "802-1x", "ca-cert", NULL); + g_assert(kval); + g_assert(g_str_has_prefix(kval, NM_KEYFILE_CERT_SCHEME_PREFIX_BLOB)); + } + + g_key_file_unref(keyfile); +} + +static void +_test_8021x_cert_check_blob_full(NMConnection *con, const void *data, gsize len) +{ + GBytes * bytes; + NMSetting8021x *s_8021x = nm_connection_get_setting_802_1x(con); + + bytes = g_bytes_new(data, len); + g_object_set(s_8021x, NM_SETTING_802_1X_CA_CERT, bytes, NULL); + _test_8021x_cert_check(con, + NM_SETTING_802_1X_CK_SCHEME_BLOB, + g_bytes_get_data(bytes, NULL), + g_bytes_get_size(bytes)); + g_bytes_unref(bytes); +} +#define _test_8021x_cert_check_blob(con, data) \ + _test_8021x_cert_check_blob_full(con, data, NM_STRLEN(data)) + +static void +_test_8021x_cert_from_files(const char *cert, const char *key) +{ + NMSetting8021x *s_8021x; + gs_unref_object NMConnection *con = + nmtst_create_minimal_connection("test-cert", NULL, NM_SETTING_WIRED_SETTING_NAME, NULL); + GError * error = NULL; + gboolean success; + NMSetting8021xCKScheme scheme = NM_SETTING_802_1X_CK_SCHEME_PATH; + gs_free char *full_TEST_WIRED_TLS_CA_CERT = nmtst_file_resolve_relative_path(cert, NULL); + gs_free char *full_TEST_WIRED_TLS_PRIVKEY = nmtst_file_resolve_relative_path(key, NULL); + + /* test writing/reading of certificates of NMSetting8021x */ + + /* create a valid connection with NMSetting8021x */ + s_8021x = (NMSetting8021x *) nm_setting_802_1x_new(); + nm_setting_802_1x_add_eap_method(s_8021x, "tls"); + g_object_set(s_8021x, NM_SETTING_802_1X_IDENTITY, "Bill Smith", NULL); + success = + nm_setting_802_1x_set_ca_cert(s_8021x, full_TEST_WIRED_TLS_CA_CERT, scheme, NULL, &error); + g_assert_no_error(error); + g_assert(success); + success = nm_setting_802_1x_set_client_cert(s_8021x, + full_TEST_WIRED_TLS_CA_CERT, + scheme, + NULL, + &error); + g_assert_no_error(error); + g_assert(success); + success = nm_setting_802_1x_set_private_key(s_8021x, + full_TEST_WIRED_TLS_PRIVKEY, + "test1", + scheme, + NULL, + &error); + g_assert_no_error(error); + g_assert(success); + + /* 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); + nmtst_connection_normalize(con); + + _test_8021x_cert_check(con, scheme, full_TEST_WIRED_TLS_CA_CERT, -1); + + scheme = NM_SETTING_802_1X_CK_SCHEME_BLOB; + success = + nm_setting_802_1x_set_ca_cert(s_8021x, full_TEST_WIRED_TLS_CA_CERT, scheme, NULL, &error); + g_assert_no_error(error); + g_assert(success); + _test_8021x_cert_check(con, scheme, full_TEST_WIRED_TLS_CA_CERT, -1); + + _test_8021x_cert_check_blob(con, "a"); + _test_8021x_cert_check_blob(con, "\0"); + _test_8021x_cert_check_blob(con, "10"); + _test_8021x_cert_check_blob(con, "data:;base64,a"); + _test_8021x_cert_check_blob_full(con, "data:;base64,a", NM_STRLEN("data:;base64,a") + 1); + _test_8021x_cert_check_blob(con, "data:;base64,file://a"); + _test_8021x_cert_check_blob(con, "123"); +} + +static void +test_8021x_cert(void) +{ + _test_8021x_cert_from_files(TEST_WIRED_TLS_CA_CERT, TEST_WIRED_TLS_PRIVKEY); +} + +static void +test_8021x_cert_tpm2key(void) +{ + _test_8021x_cert_from_files(TEST_WIRED_TLS_CA_CERT, TEST_WIRED_TLS_TPM2KEY); +} + +/*****************************************************************************/ + +static void +test_8021x_cert_read(void) +{ + GKeyFile * keyfile = NULL; + gs_unref_object NMConnection *con = NULL; + NMSetting8021x * s_8021x; + + con = nmtst_create_connection_from_keyfile("[connection]\n" + "type=ethernet", + "/test_8021x_cert_read/test0"); + CLEAR(&con, &keyfile); + + keyfile = _keyfile_load_from_data("[connection]\n" + "type=ethernet"); + _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test1", NULL, NULL, NULL, NULL, TRUE); + CLEAR(&con, &keyfile); + + keyfile = _keyfile_load_from_data( + "[connection]\n" + "type=802-3-ethernet\n" + + "[802-1x]\n" + "eap=tls;\n" + "identity=Bill Smith\n" + "ca-cert=48;130;2;52;48;130;1;161;2;16;2;173;102;126;78;69;254;94;87;111;60;152;25;94;221;" + "192;48;13;6;9;42;134;72;134;247;13;1;1;2;5;0;48;95;49;11;48;9;6;3;85;4;6;19;2;85;83;49;32;" + "48;30;6;3;85;4;10;19;23;82;83;65;32;68;97;116;97;32;83;101;99;117;114;105;116;121;44;32;" + "73;110;99;46;49;46;48;44;6;3;85;4;11;19;37;83;101;99;117;114;101;32;83;101;114;118;101;" + "114;32;67;101;114;116;105;102;105;99;97;116;105;111;110;32;65;117;116;104;111;114;105;116;" + "121;48;30;23;13;57;52;49;49;48;57;48;48;48;48;48;48;90;23;13;49;48;48;49;48;55;50;51;53;" + "57;53;57;90;48;95;49;11;48;9;6;3;85;4;6;19;2;85;83;49;32;48;30;6;3;85;4;10;19;23;82;83;65;" + "32;68;97;116;97;32;83;101;99;117;114;105;116;121;44;32;73;110;99;46;49;46;48;44;6;3;85;4;" + "11;19;37;83;101;99;117;114;101;32;83;101;114;118;101;114;32;67;101;114;116;105;102;105;99;" + "97;116;105;111;110;32;65;117;116;104;111;114;105;116;121;48;129;155;48;13;6;9;42;134;72;" + "134;247;13;1;1;1;5;0;3;129;137;0;48;129;133;2;126;0;146;206;122;193;174;131;62;90;170;137;" + "131;87;172;37;1;118;12;173;174;142;44;55;206;235;53;120;100;84;3;229;132;64;81;201;191;" + "143;8;226;138;130;8;210;22;134;55;85;233;177;33;2;173;118;104;129;154;5;162;75;201;75;37;" + "102;34;86;108;136;7;143;247;129;89;109;132;7;101;112;19;113;118;62;155;119;76;227;80;137;" + "86;152;72;185;29;167;41;26;19;46;74;17;89;156;30;21;213;73;84;44;115;58;105;130;177;151;" + "57;156;109;112;103;72;229;221;45;214;200;30;123;2;3;1;0;1;48;13;6;9;42;134;72;134;247;13;" + "1;1;2;5;0;3;126;0;101;221;126;225;178;236;176;226;58;224;236;113;70;154;25;17;184;211;199;" + "160;180;3;64;38;2;62;9;156;225;18;179;209;90;246;55;165;183;97;3;182;91;22;105;59;198;68;" + "8;12;136;83;12;107;151;73;199;62;53;220;108;185;187;170;223;92;187;58;47;147;96;182;169;" + "75;77;242;32;247;205;95;127;100;123;142;220;0;92;215;250;119;202;57;22;89;111;14;234;211;" + "181;131;127;77;77;66;86;118;180;201;95;4;248;56;248;235;210;95;117;95;205;123;252;229;142;" + "128;124;252;80;\n" + "client-cert=102;105;108;101;58;47;47;47;104;111;109;101;47;100;99;98;119;47;68;101;115;" + "107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;" + "109;0;\n" + "private-key=102;105;108;101;58;47;47;47;104;111;109;101;47;100;99;98;119;47;68;101;115;" + "107;116;111;112;47;99;101;114;116;105;110;102;114;97;47;99;108;105;101;110;116;46;112;101;" + "109;0;\n" + "private-key-password=12345testing\n"); + _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, TRUE); + CLEAR(&con, &keyfile); + + keyfile = + _keyfile_load_from_data("[connection]\n" + "type=802-3-ethernet\n" + + "[802-1x]\n" + "eap=tls;\n" + "identity=Bill Smith\n" + /* unqualified strings are only recognized as path up to 500 chars*/ + "ca-cert=" + "/11111111111111111111111111111111111111111111111111111111111111111" + "1111111111111111111111111111111111" + "/11111111111111111111111111111111111111111111111111111111111111111" + "1111111111111111111111111111111111" + "/11111111111111111111111111111111111111111111111111111111111111111" + "1111111111111111111111111111111111" + "/11111111111111111111111111111111111111111111111111111111111111111" + "1111111111111111111111111111111111" + "/11111111111111111111111111111111111111111111111111111111111111111" + "111111111111111111111111111111111\n" + "client-cert=/" + "222222222222222222222222222222222222222222222222222222222222222222" + "222222222222222222222222222222221" + "/22222222222222222222222222222222222222222222222222222222222222222" + "2222222222222222222222222222222221" + "/22222222222222222222222222222222222222222222222222222222222222222" + "2222222222222222222222222222222221" + "/22222222222222222222222222222222222222222222222222222222222222222" + "2222222222222222222222222222222221" + "/22222222222222222222222222222222222222222222222222222222222222222" + "2222222222222222222222222222222222\n" + "private-key=file://" + "/33333333333333333333333333333333333333333333333333333333333333333" + "3333333333333333333333333333333331" + "/33333333333333333333333333333333333333333333333333333333333333333" + "3333333333333333333333333333333331" + "/33333333333333333333333333333333333333333333333333333333333333333" + "3333333333333333333333333333333331" + "/33333333333333333333333333333333333333333333333333333333333333333" + "3333333333333333333333333333333331" + "/33333333333333333333333333333333333333333333333333333333333333333" + "333333333333333333333333333333333111111\n" + "private-key-password=12345testing\n"); + _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, TRUE); + s_8021x = nm_connection_get_setting_802_1x(con); + + g_assert(nm_setting_802_1x_get_ca_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); + g_assert(g_str_has_prefix(nm_setting_802_1x_get_ca_cert_path(s_8021x), "/111111111111")); + g_assert_cmpint(strlen(nm_setting_802_1x_get_ca_cert_path(s_8021x)), ==, 499); + + g_assert(nm_setting_802_1x_get_client_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); + g_assert( + g_str_has_prefix(g_bytes_get_data(nm_setting_802_1x_get_client_cert_blob(s_8021x), NULL), + "/2222222222")); + g_assert_cmpint(g_bytes_get_size(nm_setting_802_1x_get_client_cert_blob(s_8021x)), + ==, + 500 + 1 /* keyfile reader adds a trailing NUL */); + + g_assert(nm_setting_802_1x_get_private_key_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); + g_assert(g_str_has_prefix(nm_setting_802_1x_get_private_key_path(s_8021x), "/333333333")); + g_assert_cmpint(strlen(nm_setting_802_1x_get_private_key_path(s_8021x)), ==, 505); + CLEAR(&con, &keyfile); + + keyfile = _keyfile_load_from_data("[connection]\n" + "type=802-3-ethernet\n" + + "[802-1x]\n" + "eap=tls;\n" + "identity=Bill Smith\n" + "ca-cert=/\n" + "client-cert=a.pem\n" + "private-key=data:;base64,aGFsbG8=\n" // hallo + "private-key-password=12345testing\n"); + _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, TRUE); + s_8021x = nm_connection_get_setting_802_1x(con); + + g_assert(nm_setting_802_1x_get_ca_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); + g_assert_cmpstr(nm_setting_802_1x_get_ca_cert_path(s_8021x), ==, "/"); + + g_assert(nm_setting_802_1x_get_client_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); + g_assert_cmpstr(nm_setting_802_1x_get_client_cert_path(s_8021x), + ==, + "/test_8021x_cert_read/a.pem"); + + g_assert(nm_setting_802_1x_get_private_key_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); + _assert_gbytes(nm_setting_802_1x_get_private_key_blob(s_8021x), "hallo", -1); + CLEAR(&con, &keyfile); + + keyfile = _keyfile_load_from_data("[connection]\n" + "type=802-3-ethernet\n" + + "[802-1x]\n" + "eap=tls;\n" + "identity=Bill Smith\n" + "ca-cert=file://data:;base64,x\n" + "client-cert=abc.der\n" + "private-key=abc.deR\n" + "private-key-password=12345testing\n"); + _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, TRUE); + s_8021x = nm_connection_get_setting_802_1x(con); + + g_assert(nm_setting_802_1x_get_ca_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); + g_assert_cmpstr(nm_setting_802_1x_get_ca_cert_path(s_8021x), ==, "data:;base64,x"); + + g_assert(nm_setting_802_1x_get_client_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_PATH); + g_assert_cmpstr(nm_setting_802_1x_get_client_cert_path(s_8021x), + ==, + "/test_8021x_cert_read/abc.der"); + + g_assert(nm_setting_802_1x_get_private_key_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); + _assert_gbytes(nm_setting_802_1x_get_private_key_blob(s_8021x), "abc.deR\0", 8); + CLEAR(&con, &keyfile); + + keyfile = + _keyfile_load_from_data("[connection]\n" + "type=802-3-ethernet\n" + + "[802-1x]\n" + "eap=tls;\n" + "identity=Bill Smith\n" + "ca-cert=104;97;108;108;111;\n" /* "hallo" without trailing NUL */ + "client-cert=104;097;108;108;111;0;\n" + "private-key=hallo\n" + "private-key-password=12345testing\n"); + _keyfile_convert(&con, &keyfile, "/test_8021x_cert_read/test2", NULL, NULL, NULL, NULL, TRUE); + s_8021x = nm_connection_get_setting_802_1x(con); + + g_assert(nm_setting_802_1x_get_ca_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); + _assert_gbytes(nm_setting_802_1x_get_ca_cert_blob(s_8021x), "hallo", 5); + + g_assert(nm_setting_802_1x_get_client_cert_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); + _assert_gbytes(nm_setting_802_1x_get_client_cert_blob(s_8021x), "hallo\0", 6); + + g_assert(nm_setting_802_1x_get_private_key_scheme(s_8021x) == NM_SETTING_802_1X_CK_SCHEME_BLOB); + _assert_gbytes(nm_setting_802_1x_get_private_key_blob(s_8021x), "hallo\0", 6); + CLEAR(&con, &keyfile); +} + +static void +test_team_conf_read_valid(void) +{ + GKeyFile * keyfile = NULL; + gs_unref_object NMConnection *con = NULL; + NMSettingTeam * s_team; + + con = nmtst_create_connection_from_keyfile("[connection]\n" + "type=team\n" + "interface-name=nm-team1\n" + "[team]\n" + "config={\"foo\":\"bar\"}", + "/test_team_conf_read/valid"); + + g_assert(con); + s_team = nm_connection_get_setting_team(con); + g_assert(s_team); + g_assert_cmpstr(nm_setting_team_get_config(s_team), ==, "{\"foo\":\"bar\"}"); + + CLEAR(&con, &keyfile); +} + +static void +test_team_conf_read_invalid(void) +{ + GKeyFile * keyfile = NULL; + gs_unref_object NMConnection *con = NULL; + NMSettingTeam * s_team; + + if (!nm_json_vt()) { + g_test_skip("team test requires JSON validation"); + return; + } + + con = nmtst_create_connection_from_keyfile("[connection]\n" + "type=team\n" + "interface-name=nm-team1\n" + "[team]\n" + "config={foobar}", + "/test_team_conf_read/invalid"); + + g_assert(con); + s_team = nm_connection_get_setting_team(con); + g_assert(s_team); + g_assert(nm_setting_team_get_config(s_team) == NULL); + + CLEAR(&con, &keyfile); +} + +/*****************************************************************************/ + +static void +test_user_1(void) +{ + nm_auto_unref_keyfile GKeyFile *keyfile = NULL; + gs_unref_object NMConnection *con = NULL; + NMSettingUser * s_user; + + con = nmtst_create_connection_from_keyfile("[connection]\n" + "id=t\n" + "type=ethernet\n" + "\n" + "[user]\n" + "my-value.x=value1\n" + "", + "/test_user_1/invalid"); + g_assert(con); + s_user = NM_SETTING_USER(nm_connection_get_setting(con, NM_TYPE_SETTING_USER)); + g_assert(s_user); + g_assert_cmpstr(nm_setting_user_get_data(s_user, "my-value.x"), ==, "value1"); + + CLEAR(&con, &keyfile); + + con = nmtst_create_minimal_connection("user-2", + "8b85fb8d-3070-48ba-93d9-53eee231d9a2", + NM_SETTING_WIRED_SETTING_NAME, + NULL); + s_user = NM_SETTING_USER(nm_setting_user_new()); + +#define _USER_SET_DATA(s_user, key, val) \ + G_STMT_START \ + { \ + GError * _error = NULL; \ + gboolean _success; \ + \ + _success = nm_setting_user_set_data((s_user), (key), (val), &_error); \ + nmtst_assert_success(_success, _error); \ + } \ + G_STMT_END + +#define _USER_SET_DATA_X(s_user, key) _USER_SET_DATA(s_user, key, "val=" key "") + + _USER_SET_DATA(s_user, "my.val1", ""); + _USER_SET_DATA_X(s_user, "my.val2"); + _USER_SET_DATA_X(s_user, "my.v__al3"); + _USER_SET_DATA_X(s_user, "my._v"); + _USER_SET_DATA_X(s_user, "my.v+"); + _USER_SET_DATA_X(s_user, "my.Av"); + _USER_SET_DATA_X(s_user, "MY.AV"); + _USER_SET_DATA_X(s_user, "MY.8V"); + _USER_SET_DATA_X(s_user, "MY.8-V"); + _USER_SET_DATA_X(s_user, "MY.8_V"); + _USER_SET_DATA_X(s_user, "MY.8+V"); + _USER_SET_DATA_X(s_user, "MY.8/V"); + _USER_SET_DATA_X(s_user, "MY.8=V"); + _USER_SET_DATA_X(s_user, "MY.-"); + _USER_SET_DATA_X(s_user, "MY._"); + _USER_SET_DATA_X(s_user, "MY.+"); + _USER_SET_DATA_X(s_user, "MY./"); + _USER_SET_DATA_X(s_user, "MY.="); + _USER_SET_DATA_X(s_user, "my.keys.1"); + _USER_SET_DATA_X(s_user, "my.other.KEY.42"); + + nm_connection_add_setting(con, NM_SETTING(s_user)); + nmtst_connection_normalize(con); + + _keyfile_convert(&con, &keyfile, "/test_user_1/foo", NULL, NULL, NULL, NULL, FALSE); +} + +/*****************************************************************************/ + +static void +test_vpn_1(void) +{ + nm_auto_unref_keyfile GKeyFile *keyfile = NULL; + gs_unref_object NMConnection *con = NULL; + NMSettingVpn * s_vpn; + + con = nmtst_create_connection_from_keyfile("[connection]\n" + "id=t\n" + "type=vpn\n" + "\n" + "[vpn]\n" + "service-type=a.b.c\n" + "vpn-key-1=value1\n" + "", + "/test_vpn_1/invalid"); + g_assert(con); + s_vpn = NM_SETTING_VPN(nm_connection_get_setting(con, NM_TYPE_SETTING_VPN)); + g_assert(s_vpn); + g_assert_cmpstr(nm_setting_vpn_get_data_item(s_vpn, "vpn-key-1"), ==, "value1"); + + CLEAR(&con, &keyfile); +} + +/*****************************************************************************/ + +static void +test_bridge_vlans(void) +{ + nm_auto_unref_keyfile GKeyFile *keyfile = NULL; + gs_unref_object NMConnection *con = NULL; + NMSettingBridge * s_bridge; + NMBridgeVlan * vlan; + guint16 vid, vid_end; + + con = nmtst_create_connection_from_keyfile("[connection]\n" + "id=t\n" + "type=bridge\n" + "interface-name=br4\n" + "\n" + "[bridge]\n" + "vlans=900 , 1 pvid untagged, 100-123 untagged\n" + "", + "/test_bridge_port/vlans"); + s_bridge = NM_SETTING_BRIDGE(nm_connection_get_setting(con, NM_TYPE_SETTING_BRIDGE)); + g_assert(s_bridge); + g_assert_cmpuint(nm_setting_bridge_get_num_vlans(s_bridge), ==, 3); + + vlan = nm_setting_bridge_get_vlan(s_bridge, 0); + g_assert(vlan); + nm_bridge_vlan_get_vid_range(vlan, &vid, &vid_end); + g_assert_cmpuint(vid, ==, 1); + g_assert_cmpuint(vid_end, ==, 1); + g_assert_cmpint(nm_bridge_vlan_is_pvid(vlan), ==, TRUE); + g_assert_cmpint(nm_bridge_vlan_is_untagged(vlan), ==, TRUE); + + vlan = nm_setting_bridge_get_vlan(s_bridge, 1); + g_assert(vlan); + nm_bridge_vlan_get_vid_range(vlan, &vid, &vid_end); + g_assert_cmpuint(vid, ==, 100); + g_assert_cmpuint(vid_end, ==, 123); + g_assert_cmpint(nm_bridge_vlan_is_pvid(vlan), ==, FALSE); + g_assert_cmpint(nm_bridge_vlan_is_untagged(vlan), ==, TRUE); + + vlan = nm_setting_bridge_get_vlan(s_bridge, 2); + g_assert(vlan); + nm_bridge_vlan_get_vid_range(vlan, &vid, &vid_end); + g_assert_cmpuint(vid, ==, 900); + g_assert_cmpuint(vid_end, ==, 900); + g_assert_cmpint(nm_bridge_vlan_is_pvid(vlan), ==, FALSE); + g_assert_cmpint(nm_bridge_vlan_is_untagged(vlan), ==, FALSE); + + CLEAR(&con, &keyfile); +} + +static void +test_bridge_port_vlans(void) +{ + nm_auto_unref_keyfile GKeyFile *keyfile = NULL; + gs_unref_object NMConnection *con = NULL; + NMSettingBridgePort * s_port; + NMBridgeVlan * vlan; + guint16 vid_start, vid_end; + + con = nmtst_create_connection_from_keyfile("[connection]\n" + "id=t\n" + "type=dummy\n" + "interface-name=dummy1\n" + "master=br0\n" + "slave-type=bridge\n" + "\n" + "[bridge-port]\n" + "vlans=4094 pvid , 10-20 untagged\n" + "", + "/test_bridge_port/vlans"); + s_port = NM_SETTING_BRIDGE_PORT(nm_connection_get_setting(con, NM_TYPE_SETTING_BRIDGE_PORT)); + g_assert(s_port); + g_assert_cmpuint(nm_setting_bridge_port_get_num_vlans(s_port), ==, 2); + + vlan = nm_setting_bridge_port_get_vlan(s_port, 0); + g_assert(vlan); + nm_bridge_vlan_get_vid_range(vlan, &vid_start, &vid_end); + g_assert_cmpuint(vid_start, ==, 10); + g_assert_cmpuint(vid_end, ==, 20); + g_assert_cmpint(nm_bridge_vlan_is_pvid(vlan), ==, FALSE); + g_assert_cmpint(nm_bridge_vlan_is_untagged(vlan), ==, TRUE); + + vlan = nm_setting_bridge_port_get_vlan(s_port, 1); + g_assert(vlan); + nm_bridge_vlan_get_vid_range(vlan, &vid_start, &vid_end); + g_assert_cmpuint(vid_start, ==, 4094); + g_assert_cmpuint(vid_end, ==, 4094); + g_assert_cmpint(nm_bridge_vlan_is_pvid(vlan), ==, TRUE); + g_assert_cmpint(nm_bridge_vlan_is_untagged(vlan), ==, FALSE); + + CLEAR(&con, &keyfile); +} + +/*****************************************************************************/ + +NMTST_DEFINE(); + +int +main(int argc, char **argv) +{ + nmtst_init(&argc, &argv, TRUE); + + g_test_add_func("/core/keyfile/encode_key", test_encode_key); + g_test_add_func("/core/keyfile/test_8021x_cert", test_8021x_cert); + g_test_add_func("/core/keyfile/test_8021x_cert_tpm2key", test_8021x_cert_tpm2key); + g_test_add_func("/core/keyfile/test_8021x_cert_read", test_8021x_cert_read); + g_test_add_func("/core/keyfile/test_team_conf_read/valid", test_team_conf_read_valid); + g_test_add_func("/core/keyfile/test_team_conf_read/invalid", test_team_conf_read_invalid); + g_test_add_func("/core/keyfile/test_user/1", test_user_1); + g_test_add_func("/core/keyfile/test_vpn/1", test_vpn_1); + g_test_add_func("/core/keyfile/bridge/vlans", test_bridge_vlans); + g_test_add_func("/core/keyfile/bridge-port/vlans", test_bridge_port_vlans); + + return g_test_run(); +} |