Attention is currently required from: flichtenheld, plaisthos. Hello plaisthos,
I'd like you to reexamine a change. Please visit http://gerrit.openvpn.net/c/openvpn/+/468?usp=email to look at the new patch set (#3). Change subject: test_user_pass: new UT for get_user_pass ...................................................................... test_user_pass: new UT for get_user_pass UTs for basic functionality, without management functions. v2: - add CMake support - add GHA support for both MSVC and mingw v3: - fix distcheck by adding input/ directory to dist Change-Id: I193aef06912f01426dd4ac298aadfab97dd75a35 Signed-off-by: Frank Lichtenheld <fr...@lichtenheld.com> --- M .github/workflows/build.yaml M CMakeLists.txt M src/openvpn/syshead.h M tests/unit_tests/openvpn/Makefile.am A tests/unit_tests/openvpn/input/user_only.txt A tests/unit_tests/openvpn/input/user_pass.txt A tests/unit_tests/openvpn/test_user_pass.c 7 files changed, 314 insertions(+), 2 deletions(-) git pull ssh://gerrit.openvpn.net:29418/openvpn refs/changes/68/468/3 diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 4393f5c..d7cc01c 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -85,11 +85,13 @@ fail-fast: false matrix: arch: [x86, x64] - test: [argv, auth_token, buffer, cryptoapi, crypto, misc, ncp, packet_id, pkt, provider, tls_crypt] + test: [argv, auth_token, buffer, cryptoapi, crypto, misc, ncp, packet_id, pkt, provider, tls_crypt, user_pass] runs-on: windows-latest name: "mingw unittest ${{ matrix.test }} - ${{ matrix.arch }} - OSSL" steps: + - name: Checkout OpenVPN + uses: actions/checkout@v3 - name: Retrieve mingw unittest uses: actions/download-artifact@v3 with: @@ -97,6 +99,8 @@ path: unittests - name: Run ${{ matrix.test }} unit test run: ./unittests/test_${{ matrix.test }}.exe + env: + srcdir: "${{ github.workspace }}/tests/unit_tests/openvpn" ubuntu: strategy: diff --git a/CMakeLists.txt b/CMakeLists.txt index 577bc5d..3f96354 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -561,6 +561,7 @@ "test_packet_id" "test_pkt" "test_provider" + "test_user_pass" ) if (WIN32) @@ -619,6 +620,9 @@ # test_networking needs special environment if (NOT ${test_name} STREQUAL "test_networking") add_test(${test_name} ${test_name}) + # for compat with autotools make check + set_tests_properties(${test_name} PROPERTIES + ENVIRONMENT "srcdir=${CMAKE_CURRENT_SOURCE_DIR}/tests/unit_tests/openvpn") endif () add_executable(${test_name} tests/unit_tests/openvpn/${test_name}.c @@ -713,6 +717,15 @@ src/openvpn/base64.c ) + target_sources(test_user_pass PRIVATE + tests/unit_tests/openvpn/mock_get_random.c + tests/unit_tests/openvpn/mock_win32_execve.c + src/openvpn/base64.c + src/openvpn/console.c + src/openvpn/env_set.c + src/openvpn/run_command.c + ) + if (TARGET test_argv) target_link_options(test_argv PRIVATE -Wl,--wrap=parse_line) target_sources(test_argv PRIVATE diff --git a/src/openvpn/syshead.h b/src/openvpn/syshead.h index 7181b94..d89d2b5 100644 --- a/src/openvpn/syshead.h +++ b/src/openvpn/syshead.h @@ -522,4 +522,10 @@ #define ENABLE_MEMSTATS #endif +#ifdef _MSC_VER +#ifndef PATH_MAX +#define PATH_MAX MAX_PATH +#endif +#endif + #endif /* ifndef SYSHEAD_H */ diff --git a/tests/unit_tests/openvpn/Makefile.am b/tests/unit_tests/openvpn/Makefile.am index ef45b11..6199b4a 100644 --- a/tests/unit_tests/openvpn/Makefile.am +++ b/tests/unit_tests/openvpn/Makefile.am @@ -1,5 +1,7 @@ AUTOMAKE_OPTIONS = foreign +EXTRA_DIST = input + test_binaries= if HAVE_LD_WRAP_SUPPORT @@ -7,7 +9,7 @@ endif test_binaries += crypto_testdriver packet_id_testdriver auth_token_testdriver ncp_testdriver misc_testdriver \ - pkt_testdriver + pkt_testdriver user_pass_testdriver if HAVE_LD_WRAP_SUPPORT if !WIN32 test_binaries += tls_crypt_testdriver @@ -214,6 +216,22 @@ $(top_srcdir)/src/openvpn/base64.c +user_pass_testdriver_CFLAGS = @TEST_CFLAGS@ \ + -I$(top_srcdir)/include -I$(top_srcdir)/src/compat -I$(top_srcdir)/src/openvpn +user_pass_testdriver_LDFLAGS = @TEST_LDFLAGS@ + +user_pass_testdriver_SOURCES = test_user_pass.c mock_msg.c \ + $(top_srcdir)/src/openvpn/buffer.c \ + $(top_srcdir)/src/openvpn/console.c \ + $(top_srcdir)/src/openvpn/env_set.c \ + mock_win32_execve.c \ + $(top_srcdir)/src/openvpn/run_command.c \ + mock_get_random.c \ + $(top_srcdir)/src/openvpn/platform.c \ + $(top_srcdir)/src/openvpn/win32-util.c \ + $(top_srcdir)/src/openvpn/base64.c + + ncp_testdriver_CFLAGS = @TEST_CFLAGS@ \ -I$(top_srcdir)/include -I$(top_srcdir)/src/compat -I$(top_srcdir)/src/openvpn \ $(OPTIONAL_CRYPTO_CFLAGS) diff --git a/tests/unit_tests/openvpn/input/user_only.txt b/tests/unit_tests/openvpn/input/user_only.txt new file mode 100644 index 0000000..3ca0db3 --- /dev/null +++ b/tests/unit_tests/openvpn/input/user_only.txt @@ -0,0 +1 @@ +fuser diff --git a/tests/unit_tests/openvpn/input/user_pass.txt b/tests/unit_tests/openvpn/input/user_pass.txt new file mode 100644 index 0000000..31b38ef --- /dev/null +++ b/tests/unit_tests/openvpn/input/user_pass.txt @@ -0,0 +1,2 @@ +fuser +fpassword diff --git a/tests/unit_tests/openvpn/test_user_pass.c b/tests/unit_tests/openvpn/test_user_pass.c new file mode 100644 index 0000000..edd566a --- /dev/null +++ b/tests/unit_tests/openvpn/test_user_pass.c @@ -0,0 +1,268 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2023 Selva Nair <selva.n...@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 2 of the License, + * or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#undef ENABLE_SYSTEMD + +#include "syshead.h" +#include "manage.h" + +#include <stdlib.h> +#include <string.h> +#include <setjmp.h> +#include <cmocka.h> + +#include "misc.c" + +struct management *management; /* global */ + +/* mocking */ +bool +query_user_exec_builtin(void) +{ + /* Loop through configured query_user slots */ + for (int i = 0; i < QUERY_USER_NUMSLOTS && query_user[i].response != NULL; i++) + { + check_expected(query_user[i].prompt); + strncpy(query_user[i].response, mock_ptr_type(char *), query_user[i].response_len); + } + + return mock(); +} +void +management_auth_failure(struct management *man, const char *type, const char *reason) +{ + (void) man; + (void) type; + (void) reason; + assert_true(0); +} +bool +management_query_user_pass(struct management *man, + struct user_pass *up, + const char *type, + const unsigned int flags, + const char *static_challenge) +{ + (void) man; + (void) up; + (void) type; + (void) flags; + (void) static_challenge; + assert_true(0); + return false; +} +/* stubs for some unused functions instead of pulling in too many dependencies */ +int +parse_line(const char *line, char **p, const int n, const char *file, + const int line_num, int msglevel, struct gc_arena *gc) +{ + assert_true(0); + return 0; +} + +/* tooling */ +static void +reset_user_pass(struct user_pass *up) +{ + up->defined = false; + up->token_defined = false; + up->nocache = false; + strcpy(up->username, "user"); + strcpy(up->password, "password"); +} + +static void +test_get_user_pass_defined(void **state) +{ + struct user_pass up = { 0 }; + reset_user_pass(&up); + up.defined = true; + assert_true(get_user_pass_cr(&up, NULL, "UT", 0, NULL)); +} + +static void +test_get_user_pass_needok(void **state) +{ + struct user_pass up = { 0 }; + reset_user_pass(&up); + unsigned int flags = GET_USER_PASS_NEED_OK; + + expect_string(query_user_exec_builtin, query_user[i].prompt, "NEED-OK|UT|user:"); + will_return(query_user_exec_builtin, ""); + will_return(query_user_exec_builtin, true); + /*FIXME: query_user_exec() called even though nothing queued */ + will_return(query_user_exec_builtin, true); + assert_true(get_user_pass_cr(&up, NULL, "UT", flags, NULL)); + assert_true(up.defined); + assert_string_equal(up.password, "ok"); + + reset_user_pass(&up); + + expect_string(query_user_exec_builtin, query_user[i].prompt, "NEED-OK|UT|user:"); + will_return(query_user_exec_builtin, "cancel"); + will_return(query_user_exec_builtin, true); + /*FIXME: query_user_exec() called even though nothing queued */ + will_return(query_user_exec_builtin, true); + assert_true(get_user_pass_cr(&up, NULL, "UT", flags, NULL)); + assert_true(up.defined); + assert_string_equal(up.password, "cancel"); +} + +static void +test_get_user_pass_inline_creds(void **state) +{ + struct user_pass up = { 0 }; + reset_user_pass(&up); + unsigned int flags = GET_USER_PASS_INLINE_CREDS; + + /*FIXME: query_user_exec() called even though nothing queued */ + will_return(query_user_exec_builtin, true); + assert_true(get_user_pass_cr(&up, "iuser\nipassword", "UT", flags, NULL)); + assert_true(up.defined); + assert_string_equal(up.username, "iuser"); + assert_string_equal(up.password, "ipassword"); + + reset_user_pass(&up); + + expect_string(query_user_exec_builtin, query_user[i].prompt, "Enter UT Password:"); + will_return(query_user_exec_builtin, "cpassword"); + will_return(query_user_exec_builtin, true); + /* will try to retrieve missing password from stdin */ + assert_true(get_user_pass_cr(&up, "iuser", "UT", flags, NULL)); + assert_true(up.defined); + assert_string_equal(up.username, "iuser"); + assert_string_equal(up.password, "cpassword"); + + reset_user_pass(&up); + + flags |= GET_USER_PASS_PASSWORD_ONLY; + /*FIXME: query_user_exec() called even though nothing queued */ + will_return(query_user_exec_builtin, true); + assert_true(get_user_pass_cr(&up, "ipassword\n", "UT", flags, NULL)); + assert_true(up.defined); + assert_string_equal(up.username, "user"); + assert_string_equal(up.password, "ipassword"); + + reset_user_pass(&up); + + flags |= GET_USER_PASS_PASSWORD_ONLY; + expect_string(query_user_exec_builtin, query_user[i].prompt, "Enter UT Password:"); + will_return(query_user_exec_builtin, "cpassword"); + will_return(query_user_exec_builtin, true); + /* will try to retrieve missing password from stdin */ + assert_true(get_user_pass_cr(&up, "", "UT", flags, NULL)); + assert_true(up.defined); + assert_string_equal(up.username, "user"); + assert_string_equal(up.password, "cpassword"); +} + +static void +test_get_user_pass_authfile_stdin(void **state) +{ + struct user_pass up = { 0 }; + reset_user_pass(&up); + unsigned int flags = 0; + + expect_string(query_user_exec_builtin, query_user[i].prompt, "Enter UT Username:"); + expect_string(query_user_exec_builtin, query_user[i].prompt, "Enter UT Password:"); + will_return(query_user_exec_builtin, "cuser"); + will_return(query_user_exec_builtin, "cpassword"); + will_return(query_user_exec_builtin, true); + assert_true(get_user_pass_cr(&up, "stdin", "UT", flags, NULL)); + assert_true(up.defined); + assert_string_equal(up.username, "cuser"); + assert_string_equal(up.password, "cpassword"); + + reset_user_pass(&up); + + flags |= GET_USER_PASS_PASSWORD_ONLY; + expect_string(query_user_exec_builtin, query_user[i].prompt, "Enter UT Password:"); + will_return(query_user_exec_builtin, "cpassword"); + will_return(query_user_exec_builtin, true); + assert_true(get_user_pass_cr(&up, "stdin", "UT", flags, NULL)); + assert_true(up.defined); + assert_string_equal(up.username, "user"); + assert_string_equal(up.password, "cpassword"); +} + +static void +test_get_user_pass_authfile_file(void **state) +{ + struct user_pass up = { 0 }; + reset_user_pass(&up); + unsigned int flags = 0; + + const char *srcdir = getenv("srcdir"); + assert_non_null(srcdir); + char authfile[PATH_MAX] = { 0 }; + + snprintf(authfile, PATH_MAX, "%s/%s", srcdir, "input/user_pass.txt"); + /*FIXME: query_user_exec() called even though nothing queued */ + will_return(query_user_exec_builtin, true); + assert_true(get_user_pass_cr(&up, authfile, "UT", flags, NULL)); + assert_true(up.defined); + assert_string_equal(up.username, "fuser"); + assert_string_equal(up.password, "fpassword"); + + reset_user_pass(&up); + + snprintf(authfile, PATH_MAX, "%s/%s", srcdir, "input/user_only.txt"); + expect_string(query_user_exec_builtin, query_user[i].prompt, "Enter UT Password:"); + will_return(query_user_exec_builtin, "cpassword"); + will_return(query_user_exec_builtin, true); + /* will try to retrieve missing password from stdin */ + assert_true(get_user_pass_cr(&up, authfile, "UT", flags, NULL)); + assert_true(up.defined); + assert_string_equal(up.username, "fuser"); + assert_string_equal(up.password, "cpassword"); + + reset_user_pass(&up); + + flags |= GET_USER_PASS_PASSWORD_ONLY; + snprintf(authfile, PATH_MAX, "%s/%s", srcdir, "input/user_only.txt"); + /*FIXME: query_user_exec() called even though nothing queued */ + will_return(query_user_exec_builtin, true); + assert_true(get_user_pass_cr(&up, authfile, "UT", flags, NULL)); + assert_true(up.defined); + assert_string_equal(up.username, "user"); + assert_string_equal(up.password, "fuser"); +} + +const struct CMUnitTest user_pass_tests[] = { + cmocka_unit_test(test_get_user_pass_defined), + cmocka_unit_test(test_get_user_pass_needok), + cmocka_unit_test(test_get_user_pass_inline_creds), + cmocka_unit_test(test_get_user_pass_authfile_stdin), + cmocka_unit_test(test_get_user_pass_authfile_file), +}; + +int +main(void) +{ + return cmocka_run_group_tests(user_pass_tests, NULL, NULL); +} -- To view, visit http://gerrit.openvpn.net/c/openvpn/+/468?usp=email To unsubscribe, or for help writing mail filters, visit http://gerrit.openvpn.net/settings Gerrit-Project: openvpn Gerrit-Branch: master Gerrit-Change-Id: I193aef06912f01426dd4ac298aadfab97dd75a35 Gerrit-Change-Number: 468 Gerrit-PatchSet: 3 Gerrit-Owner: flichtenheld <fr...@lichtenheld.com> Gerrit-Reviewer: plaisthos <arne-open...@rfc2549.org> Gerrit-CC: openvpn-devel <openvpn-devel@lists.sourceforge.net> Gerrit-Attention: plaisthos <arne-open...@rfc2549.org> Gerrit-Attention: flichtenheld <fr...@lichtenheld.com> Gerrit-MessageType: newpatchset
_______________________________________________ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel