From 207f18f4fd63b8bd973db957b10438278b344c9f Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Mon, 2 Mar 2020 21:55:39 +0100 Subject: [PATCH 01/36] added dependency to libconfig --- .travis.yml | 1 + CMakeLists.txt | 3 +++ README.md | 6 ++++++ etc/webfused.conf | 31 +++++++++++++++++++++++++++++++ 4 files changed, 41 insertions(+) create mode 100644 etc/webfused.conf diff --git a/.travis.yml b/.travis.yml index 254ab38..d0368df 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,6 +24,7 @@ addons: - python3-setuptools - python3-wheel - ninja-build + - libconfig-dev before_install: diff --git a/CMakeLists.txt b/CMakeLists.txt index 1abb051..22eb7f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ pkg_check_modules(FUSE3 REQUIRED fuse3) pkg_check_modules(LWS REQUIRED libwebsockets) pkg_check_modules(JANSSON REQUIRED jansson) pkg_check_modules(UUID REQUIRED uuid) +pkg_check_modules(LIBCONFIG REQUIRED libconfig) pkg_check_modules(OPENSSL REQUIRED openssl) pkg_check_modules(WEBFUSE REQUIRED libwebfuse-adapter) @@ -35,6 +36,7 @@ add_library(userdb STATIC ) target_include_directories(userdb PUBLIC + ${LIBCONFIG_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIRS} ${JANSSON_INCLUDE_DIRS} ) @@ -48,6 +50,7 @@ add_executable(webfused target_link_libraries(webfused PUBLIC userdb + ${LIBCONFIG_LIBRARIES} ${OPENSSL_LIBRARIES} ${WEBFUSE_LIBRARIES} ${UUID_LIBRARIES} diff --git a/README.md b/README.md index 245413a..ab50b1e 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ To install dependecies, see below. - [libwebsockets](https://libwebsockets.org/) - [jansson](https://github.com/akheron/jansson) - [openssl](https://www.openssl.org/) +- [libconfig](https://hyperrealm.github.io/libconfig/) ### Installing dependencies @@ -76,3 +77,8 @@ To install libfuse, meson is needed. Please refer to [meson quick guide](https:/ cmake -DWITHOUT_TESTS=ON .. make sudo make install + +#### libconfig + + sudo apt update + sudo apt install libconfig-dev diff --git a/etc/webfused.conf b/etc/webfused.conf new file mode 100644 index 0000000..99f2f10 --- /dev/null +++ b/etc/webfused.conf @@ -0,0 +1,31 @@ +# Webfuse deamon configuration file + +version = { major = 1, minor = 0 } + +server: +{ + vhost_name = "localhost" + port = 8080 + + # tls: + # { + # certificate = "/etc/webfused/cert.pem" + # key = "/etc/webfused/key.pem" + # } + + # document_root = "/var/www" +} + +authentication: +{ + provider = "file" + settings: + { + file = "/etc/webfused/passwd" + } +} + +filesystems: +( + {name = "test", mount_point = "/tmp" } +) From 141c857d4edde8063f1592d00efe9af6cb9566fa Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Mon, 2 Mar 2020 22:18:25 +0100 Subject: [PATCH 02/36] added basic unit test --- CMakeLists.txt | 42 ++++++++++++++++++++++++++++++++++++++++++ README.md | 14 ++++++++++++++ test/test_config.cc | 13 +++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 test/test_config.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 22eb7f6..c97bb44 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,8 @@ cmake_minimum_required (VERSION 3.10) project(webfused VERSION 0.1.0 DESCRIPTION "Webfuse daemon") +option(WITHOUT_TESTS "disable unit tests" OFF) + set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) @@ -78,3 +80,43 @@ target_include_directories(webfuse-passwd PUBLIC target_compile_options(webfuse-passwd PUBLIC ${OPENSSL_CFLAGS_OTHER}) install(TARGETS webfuse-passwd DESTINATION bin) + +if(NOT WITHOUT_TESTS) + + +set(THREADS_PREFER_PTHREAD_FLAG ON) +find_package(Threads REQUIRED) + + +include (CTest) + +pkg_check_modules(GTEST gtest_main) +include(GoogleTest) +pkg_check_modules(GMOCK gmock) + +add_executable(alltests + test/test_config.cc +) + +target_include_directories(alltests PRIVATE + src + ${GMOCK_INCLUDE_DIRS} + ${GTEST_INCLUDE_DIRS} +) + +target_compile_options(alltests PRIVATE ${GMOCK_CFLAGS} ${GTEST_CFLAGS} "-pthread") + +target_link_libraries(alltests PRIVATE + ${LIBCONFIG_LIBRARIES} + ${GMOCK_LIBRARIES} + ${GTEST_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} +) + +# copy test data +configure_file(etc/webfused.conf webfused.conf COPYONLY) + +enable_testing() +gtest_discover_tests(alltests TEST_PREFIX alltests:) + +endif(NOT WITHOUT_TESTS) diff --git a/README.md b/README.md index ab50b1e..8ce0f5f 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ To install dependecies, see below. - [jansson](https://github.com/akheron/jansson) - [openssl](https://www.openssl.org/) - [libconfig](https://hyperrealm.github.io/libconfig/) +- [Google Test](https://github.com/google/googletest) *(Test only)* ### Installing dependencies @@ -82,3 +83,16 @@ To install libfuse, meson is needed. Please refer to [meson quick guide](https:/ sudo apt update sudo apt install libconfig-dev + +#### GoogleTest + +Installation of GoogleTest is optional webfuse library, but required to compile tests. + + wget -O gtest-1.10.0.tar.gz https://github.com/google/googletest/archive/release-1.10.0.tar.gz + tar -xf gtest-1.10.0.tar.gz + cd googletest-release-1.10.0 + mkdir .build + cd .build + cmake .. + make + sudo make install diff --git a/test/test_config.cc b/test/test_config.cc new file mode 100644 index 0000000..55d8e56 --- /dev/null +++ b/test/test_config.cc @@ -0,0 +1,13 @@ +#include +#include + +TEST(config, is_loadable) +{ + config_t config; + config_init(&config); + + int result = config_read_file(&config, "webfused.conf"); + ASSERT_EQ(CONFIG_TRUE, result); + + config_destroy(&config); +} \ No newline at end of file From 1c783e84eb66a0e409d2e37e3ccab03bf1c1d8bd Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Mon, 2 Mar 2020 22:31:11 +0100 Subject: [PATCH 03/36] added code coverage --- .travis.yml | 14 ++++++++++++-- CMakeLists.txt | 27 +++++++++++++++++++++++++++ README.md | 1 + cmake/coverage.cmake | 30 ++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 cmake/coverage.cmake diff --git a/.travis.yml b/.travis.yml index d0368df..814ffb5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,6 +26,13 @@ addons: - ninja-build - libconfig-dev +env: + matrix: + - BUILD_TYPE=Coverage CHECK_TARGET=check + - BUILD_TYPE=Debug CHECK_TARGET=memcheck + - BUILD_TPYE=Release CHECK_TARGET=check + - BUILD_TYPE=MinSizeRel CHECK_TARGET=check + before_install: - mkdir .deps @@ -80,7 +87,10 @@ before_install: before_script: - mkdir build - cd build - - cmake .. + - cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE .. script: - make \ No newline at end of file + make $CHECK_TARGET + +after_success: + - bash <(curl -s https://codecov.io/bash) \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index c97bb44..c8e6e7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(C_WARNINGS -Wall -Wextra) set(CMAKE_POSITION_INDEPENDENT_CODE ON) +set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_SOURCE_DIR}/cmake") +include(coverage) + add_library(userdb STATIC src/userdb/userdb.c ) @@ -119,4 +122,28 @@ configure_file(etc/webfused.conf webfused.conf COPYONLY) enable_testing() gtest_discover_tests(alltests TEST_PREFIX alltests:) +add_custom_target(check + ./alltests) +add_dependencies(check alltests) + +add_custom_target(memcheck + valgrind ./alltests) +add_dependencies(memcheck alltests) + +add_custom_target(coverage + mkdir -p coverage + COMMAND lcov --initial --capture --directory . --output-file coverage/lcov.info + COMMAND ./alltests + COMMAND lcov --capture --directory . --output-file coverage/lcov.info + COMMAND lcov --remove coverage/lcov.info '/usr/*' --output-file coverage/lcov.info +# COMMAND lcov --remove coverage/lcov.info '*/test/*' --output-file coverage/lcov.info +) +add_dependencies(coverage alltests) + +add_custom_target(coverage-report + COMMAND genhtml -branch-coverage --highlight --legend coverage/lcov.info --output-directory coverage/report +) +add_dependencies(coverage-report coverage) + + endif(NOT WITHOUT_TESTS) diff --git a/README.md b/README.md index 8ce0f5f..3164b7a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ [![Build Status](https://travis-ci.org/falk-werner/webfused.svg?branch=master)](https://travis-ci.org/falk-werner/webfused) +[![codecov](https://codecov.io/gh/falk-werner/webfused/branch/config_file/graph/badge.svg)](https://codecov.io/gh/falk-werner/webfused) # webfused diff --git a/cmake/coverage.cmake b/cmake/coverage.cmake new file mode 100644 index 0000000..35b6e0e --- /dev/null +++ b/cmake/coverage.cmake @@ -0,0 +1,30 @@ +set(CMAKE_C_FLAGS_COVERAGE + "${CMAKE_C_FLAGS_DEBUG} -pg --coverage -fprofile-arcs -ftest-coverage" + CACHE STRING "Flags used by the C compiler during coverage builds" + FORCE +) + +set(CMAKE_CXX_FLAGS_COVERAGE + "${CMAKE_CXX_FLAGS_DEBUG} -pg --coverage -fprofile-arcs -ftest-coverage" + CACHE STRING "Flags used by the C++ compiler during coverage builds." + FORCE +) + +set(CMAKE_EXE_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used for linking binaries during coverage builds." + FORCE +) + +set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used by the shared libraries linker during coverage builds." + FORCE +) + +mark_as_advanced( + CMAKE_C_FLAGS_COVERAGE + CMAKE_CXX_FLAGS_COVERAGE + CMAKE_EXE_LINKER_FLAGS_COVERAGE + CMAKE_SHARED_LINKER_FLAGS_COVERAGE +) \ No newline at end of file From 483874037802f221f2e098c7866a8f484b67cfba Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Mon, 2 Mar 2020 22:37:20 +0100 Subject: [PATCH 04/36] fix: added gtest --- .travis.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.travis.yml b/.travis.yml index 814ffb5..ab82f93 100644 --- a/.travis.yml +++ b/.travis.yml @@ -82,6 +82,17 @@ before_install: - sudo make install - cd .. - cd .. + # gtest + - wget https://github.com/google/googletest/archive/release-1.10.0.tar.gz + - tar -xf release-1.10.0.tar.gz + - cd googletest-release-1.10.0 + - mkdir .build + - cd .build + - cmake .. + - make + - sudo make install + - cd .. + - cd .. - cd .. before_script: From 7169cf9b5c7d3f7bccea690fee8b2a3706fb0f03 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Mon, 2 Mar 2020 22:44:22 +0100 Subject: [PATCH 05/36] added valgrind --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index ab82f93..872bb35 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,6 +25,7 @@ addons: - python3-wheel - ninja-build - libconfig-dev + - valgrind env: matrix: From d8e1fcd42699a3c2f7723d4f2cf595f62a30ed1a Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 8 Mar 2020 11:36:33 +0100 Subject: [PATCH 06/36] ignore .vscode --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 359c284..48e8b24 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /build/ -/.deps/ \ No newline at end of file +/.deps/ +/.vscode/ \ No newline at end of file From d304c843bc56601d19da84fcc6667c32a7332c69 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 8 Mar 2020 11:44:17 +0100 Subject: [PATCH 07/36] separated main --- CMakeLists.txt | 7 +++++-- src/{daemon/main.c => webfused/daemon.c} | 4 +++- src/webfused/daemon.h | 15 +++++++++++++++ src/webfused/main.c | 6 ++++++ 4 files changed, 29 insertions(+), 3 deletions(-) rename src/{daemon/main.c => webfused/daemon.c} (98%) create mode 100644 src/webfused/daemon.h create mode 100644 src/webfused/main.c diff --git a/CMakeLists.txt b/CMakeLists.txt index c8e6e7c..a6d5cb7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,12 +48,15 @@ target_include_directories(userdb PUBLIC target_compile_options(userdb PUBLIC ${OPENSSL_CFLAGS_OTHER}) +add_library(webfused-static STATIC + src/webfused/daemon.c) add_executable(webfused - src/daemon/main.c + src/webfused/main.c ) -target_link_libraries(webfused PUBLIC +target_link_libraries(webfused PUBLIC + webfused-static userdb ${LIBCONFIG_LIBRARIES} ${OPENSSL_LIBRARIES} diff --git a/src/daemon/main.c b/src/webfused/daemon.c similarity index 98% rename from src/daemon/main.c rename to src/webfused/daemon.c index 7e899dc..c338b29 100644 --- a/src/daemon/main.c +++ b/src/webfused/daemon.c @@ -1,3 +1,5 @@ +#include "webfused/daemon.h" + #include #include #include @@ -154,7 +156,7 @@ static void on_interrupt(int signal_id) shutdown_requested = true; } -int main(int argc, char * argv[]) +int wfd_daemon_run(int argc, char * argv[]) { struct args args; args.config = wf_server_config_create(); diff --git a/src/webfused/daemon.h b/src/webfused/daemon.h new file mode 100644 index 0000000..edf888c --- /dev/null +++ b/src/webfused/daemon.h @@ -0,0 +1,15 @@ +#ifndef WFD_DAEMON_H +#define WFD_DAEMON_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern int wfd_daemon_run(int argc, char * argv[]); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/webfused/main.c b/src/webfused/main.c new file mode 100644 index 0000000..6faf15d --- /dev/null +++ b/src/webfused/main.c @@ -0,0 +1,6 @@ +#include "webfused/daemon.h" + +int main(int argc, char * argv[]) +{ + return wfd_daemon_run(argc, argv); +} From b5943bd7b676de335dd96237352b1e102d9130f4 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 8 Mar 2020 16:14:55 +0100 Subject: [PATCH 08/36] added skeleton of config --- CMakeLists.txt | 6 +- src/webfused/config/config.c | 96 +++++++++++++++++++++++++ src/webfused/config/config.h | 64 +++++++++++++++++ src/webfused/config/config_intern.h | 25 +++++++ src/webfused/config/factory.c | 106 ++++++++++++++++++++++++++++ src/webfused/config/factory.h | 21 ++++++ test/test_config.cc | 56 +++++++++++++-- 7 files changed, 367 insertions(+), 7 deletions(-) create mode 100644 src/webfused/config/config.c create mode 100644 src/webfused/config/config.h create mode 100644 src/webfused/config/config_intern.h create mode 100644 src/webfused/config/factory.c create mode 100644 src/webfused/config/factory.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a6d5cb7..6e1d9a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,7 +49,10 @@ target_include_directories(userdb PUBLIC target_compile_options(userdb PUBLIC ${OPENSSL_CFLAGS_OTHER}) add_library(webfused-static STATIC - src/webfused/daemon.c) + src/webfused/daemon.c + src/webfused/config/config.c + src/webfused/config/factory.c +) add_executable(webfused src/webfused/main.c @@ -113,6 +116,7 @@ target_include_directories(alltests PRIVATE target_compile_options(alltests PRIVATE ${GMOCK_CFLAGS} ${GTEST_CFLAGS} "-pthread") target_link_libraries(alltests PRIVATE + webfused-static ${LIBCONFIG_LIBRARIES} ${GMOCK_LIBRARIES} ${GTEST_LIBRARIES} diff --git a/src/webfused/config/config.c b/src/webfused/config/config.c new file mode 100644 index 0000000..c2d13ef --- /dev/null +++ b/src/webfused/config/config.c @@ -0,0 +1,96 @@ +#include "webfused/config/config.h" +#include "webfused/config/config_intern.h" + +#include +#include + +#define WFD_CONFIG_DEFAULT_PORT (8080) +#define WFD_CONFIG_DEFAULT_VHOSTNAME ("localhost") + +extern struct wfd_config * +wfd_config_create(void) +{ + struct wfd_config * config = malloc(sizeof(struct wfd_config)); + config->port = WFD_CONFIG_DEFAULT_PORT; + config->vhost_name = strdup(WFD_CONFIG_DEFAULT_VHOSTNAME); + config->server_key = NULL; + config->server_cert = NULL; + config->server_doc_root = NULL; + + return config; +} + +void wfd_config_dispose( + struct wfd_config * config) +{ + free(config->vhost_name); + free(config->server_cert); + free(config->server_key); + free(config->server_doc_root); + free(config); + +} + +int +wfd_config_get_server_port( + struct wfd_config * config) +{ + return config->port; +} + +char const * +wfd_config_get_server_vhostname( + struct wfd_config * config) +{ + return config->vhost_name; +} + +char const * +wfd_config_get_server_cert( + struct wfd_config * config) +{ + return config->server_cert; +} + +char const * +wfd_config_get_server_key( + struct wfd_config * config) +{ + return config->server_key; +} + +char const * +wfd_config_get_server_document_root( + struct wfd_config * config) +{ + return config->server_doc_root; +} + +char const * +wfd_config_get_auth_provider( + struct wfd_config * config) +{ + return NULL; +} + +struct wfd_auth_settings * +wfd_config_get_auth_settings( + struct wfd_config * config) +{ + return NULL; +} + +size_t +wfd_config_get_filesystem_count( + struct wfd_config * config) +{ + return 0; +} + +struct wfd_filesystem_info * +wfd_confi_get_filesystem( + struct wfd_config * config, + size_t fs_index) +{ + return NULL; +} diff --git a/src/webfused/config/config.h b/src/webfused/config/config.h new file mode 100644 index 0000000..8480f4e --- /dev/null +++ b/src/webfused/config/config.h @@ -0,0 +1,64 @@ +#ifndef WFD_CONFIG_H +#define WFD_CONFIG_H + +#ifndef __cplusplus +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wfd_config; +struct wfd_auth_settins; +struct wfd_filesystem_info; + +extern void wfd_config_dispose( + struct wfd_config * config); + +extern int +wfd_config_get_server_port( + struct wfd_config * config); + +extern char const * +wfd_config_get_server_vhostname( + struct wfd_config * config); + +extern char const * +wfd_config_get_server_cert( + struct wfd_config * config); + +extern char const * +wfd_config_get_server_key( + struct wfd_config * config); + +extern char const * +wfd_config_get_server_document_root( + struct wfd_config * config); + +extern char const * +wfd_config_get_auth_provider( + struct wfd_config * config); + +extern struct wfd_auth_settings * +wfd_config_get_auth_settings( + struct wfd_config * config); + +extern size_t +wfd_config_get_filesystem_count( + struct wfd_config * config); + +extern struct wfd_filesystem_info * +wfd_confi_get_filesystem( + struct wfd_config * config, + size_t fs_index); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/webfused/config/config_intern.h b/src/webfused/config/config_intern.h new file mode 100644 index 0000000..792e957 --- /dev/null +++ b/src/webfused/config/config_intern.h @@ -0,0 +1,25 @@ +#ifndef WFD_CONFIG_INTERN_H +#define WFD_CONFIG_INTERN_H + +#ifdef _cplusplus +extern "C" +{ +#endif + +struct wfd_config +{ + char * vhost_name; + char * server_cert; + char * server_key; + char * server_doc_root; + int port; +}; + +extern struct wfd_config * +wfd_config_create(void); + +#ifdef _cplusplus +} +#endif + +#endif diff --git a/src/webfused/config/factory.c b/src/webfused/config/factory.c new file mode 100644 index 0000000..aeb5b78 --- /dev/null +++ b/src/webfused/config/factory.c @@ -0,0 +1,106 @@ +#include "webfused/config/factory.h" +#include "webfused/config/config_intern.h" +#include "webfused/config/config.h" + +#include +#include +#include + + +#if ((LIBCONFIG_VER_MAJOR != 1) || (LIBCONFIG_VER_MINOR < 5)) +#error "linconfig 1.5 or higher needed" +#endif + + +#define WFD_CONFIG_VERSION_MAJOR 1 +#define WFD_CONFIG_VERSION_MINOR 0 + +static bool +wfd_config_check_version( + config_t * config) +{ + int version_major; + int rc = config_lookup_int(config, "version.major", &version_major); + if (CONFIG_TRUE != rc) + { + // error: missing major version + return false; + } + + if (WFD_CONFIG_VERSION_MAJOR != version_major) + { + // error: incompatible version, expected WFD_CONFIG_VERSION_MAJOR + return false; + } + + int version_minor; + rc = config_lookup_int(config, "version.minor", &version_minor); + if (CONFIG_TRUE != rc) + { + // error: missing minor version + return false; + } + + if (WFD_CONFIG_VERSION_MINOR < version_minor) + { + // warn: some features might be disabled + } + else if (WFD_CONFIG_VERSION_MINOR > version_minor) + { + // info: use default values + } + + return true; +} + +static struct wfd_config * +wfd_config_load(config_t * config) +{ + struct wfd_config * result = wfd_config_create(); + + bool success = wfd_config_check_version(config); + + if (!success) + { + wfd_config_dispose(result); + result = NULL; + } + + return result; +} + +struct wfd_config * +wfd_config_load_file( + char const * filename) +{ + struct wfd_config * result = NULL; + + config_t config; + config_init(&config); + int rc = config_read_file(&config, filename); + if (CONFIG_TRUE == rc) + { + result = wfd_config_load(&config); + config_destroy(&config); + } + + return result; +} + +struct wfd_config * +wfd_config_load_string( + char const * contents) +{ + struct wfd_config * result = NULL; + + config_t config; + config_init(&config); + int rc = config_read_string(&config, contents); + if (CONFIG_TRUE == rc) + { + result = wfd_config_load(&config); + config_destroy(&config); + } + + return result; +} diff --git a/src/webfused/config/factory.h b/src/webfused/config/factory.h new file mode 100644 index 0000000..f058b4c --- /dev/null +++ b/src/webfused/config/factory.h @@ -0,0 +1,21 @@ +#ifndef WFD_CONFIG_FACTORY_H +#define WFD_CONFIG_FACTORY_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern struct wfd_config * +wfd_config_load_file( + char const * filename); + +extern struct wfd_config * +wfd_config_load_string( + char const * contents); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/test_config.cc b/test/test_config.cc index 55d8e56..63bae21 100644 --- a/test/test_config.cc +++ b/test/test_config.cc @@ -1,13 +1,57 @@ #include -#include + +#include "webfused/config/factory.h" +#include "webfused/config/config.h" TEST(config, is_loadable) { - config_t config; - config_init(&config); + struct wfd_config * config = wfd_config_load_file("webfused.conf"); + ASSERT_NE(nullptr, config); + + wfd_config_dispose(config); +} + +TEST(config, minimal_config) +{ + char const minimal[] = "version = { major = 1, minor = 0 }\n"; + struct wfd_config * config = wfd_config_load_string(minimal); + ASSERT_NE(nullptr, config); + + wfd_config_dispose(config); +} + +TEST(config, invalid_major_version_too_low) +{ + char const too_low[] = "version = { major = 0, minor = 0 }\n"; + + struct wfd_config * config = wfd_config_load_string(too_low); + ASSERT_EQ(nullptr, config); +} + +TEST(config, invalid_major_version_too_high) +{ + char const too_high[] = "version = { major = 2, minor = 0 }\n"; + + struct wfd_config * config = wfd_config_load_string(too_high); + ASSERT_EQ(nullptr, config); +} + +TEST(config, valid_older_minor) +{ + char const valid[] = "version = { major = 1, minor = -1 }\n"; + + struct wfd_config * config = wfd_config_load_string(valid); + ASSERT_NE(nullptr, config); + + wfd_config_dispose(config); +} + +TEST(config, valid_newer_minor) +{ + char const valid[] = "version = { major = 1, minor = 1 }\n"; - int result = config_read_file(&config, "webfused.conf"); - ASSERT_EQ(CONFIG_TRUE, result); + struct wfd_config * config = wfd_config_load_string(valid); + ASSERT_NE(nullptr, config); - config_destroy(&config); + wfd_config_dispose(config); } \ No newline at end of file From 03dc713649a45d9af6a9b1d88dc8e4278d4a77c7 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 8 Mar 2020 19:45:49 +0100 Subject: [PATCH 09/36] added logging support --- CMakeLists.txt | 2 + src/webfused/log/log.h | 58 +++++++++++++++ src/webfused/log/logger.c | 86 +++++++++++++++++++++ src/webfused/log/logger.h | 40 ++++++++++ test/test_log.cc | 152 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 338 insertions(+) create mode 100644 src/webfused/log/log.h create mode 100644 src/webfused/log/logger.c create mode 100644 src/webfused/log/logger.h create mode 100644 test/test_log.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e1d9a9..08b25f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,7 @@ add_library(webfused-static STATIC src/webfused/daemon.c src/webfused/config/config.c src/webfused/config/factory.c + src/webfused/log/logger.c ) add_executable(webfused @@ -105,6 +106,7 @@ pkg_check_modules(GMOCK gmock) add_executable(alltests test/test_config.cc + test/test_log.cc ) target_include_directories(alltests PRIVATE diff --git a/src/webfused/log/log.h b/src/webfused/log/log.h new file mode 100644 index 0000000..08a3b54 --- /dev/null +++ b/src/webfused/log/log.h @@ -0,0 +1,58 @@ +#ifndef WFD_LOG_H +#define WFD_LOG_H + +#ifndef __cplusplus +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifndef WFD_LOGLEVEL +#define WFD_LOGLEVEL WFD_LOGLEVEL_ALL +#endif + +#define WFD_LOGLEVEL_FATAL 1 +#define WFD_LOGLEVEL_ERROR 3 +#define WFD_LOGLEVEL_WARN 4 +#define WFD_LOGLEVEL_INFO 5 +#define WFD_LOGLEVEL_DEBUG 7 +#define WFD_LOGLEVEL_ALL 8 + +#define WFD_FATAL(...) \ + WFD_LOG(WFD_LOGLEVEL_FATAL, __VA_ARGS__) + +#define WFD_ERROR(...) \ + WFD_LOG(WFD_LOGLEVEL_ERROR, __VA_ARGS__) + +#define WFD_WARN(...) \ + WFD_LOG(WFD_LOGLEVEL_WARN, __VA_ARGS__) + +#define WFD_INFO(...) \ + WFD_LOG(WFD_LOGLEVEL_INFO, __VA_ARGS__) + +#define WFD_DEBUG(...) \ + WFD_LOG(WFD_LOGLEVEL_DEBUG, __VA_ARGS__) + +#define WFD_LOG(level, ...) \ + do { \ + if (WFD_LOGLEVEL >= (level)) { \ + wfd_log((level), __VA_ARGS__); \ + } \ + } while (0) + +extern void +wfd_log( + int level, + char const * format, + ...); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/webfused/log/logger.c b/src/webfused/log/logger.c new file mode 100644 index 0000000..2c15fbe --- /dev/null +++ b/src/webfused/log/logger.c @@ -0,0 +1,86 @@ +#include "webfused/log/logger.h" +#include "webfused/log/log.h" + +#include + +struct wfd_logger +{ + int level; + wfd_logger_log_fn * log; + wfd_logger_onclose_fn * onclose; + void * user_data; +}; + +static void wfd_logger_default_log( + void * user_data, + int level, + char const * format, + va_list args); + +static struct wfd_logger g_wfd_logger = +{ + .level = WFD_LOGLEVEL_ALL, + .log = &wfd_logger_default_log, + .onclose = NULL, + .user_data = NULL +}; + +void +wfd_logger_init( + int level, + wfd_logger_log_fn * log, + wfd_logger_onclose_fn * onclose, + void * user_data) +{ + wfd_logger_close(); + + g_wfd_logger.level = level; + g_wfd_logger.log = log; + g_wfd_logger.onclose = onclose; + g_wfd_logger.user_data = user_data; +} + +void +wfd_logger_close(void) +{ + if (NULL != g_wfd_logger.onclose) + { + g_wfd_logger.onclose(g_wfd_logger.user_data); + } + + g_wfd_logger.level = WFD_LOGLEVEL_ALL; + g_wfd_logger.log = &wfd_logger_default_log; + g_wfd_logger.onclose = NULL; + g_wfd_logger.user_data = NULL; +} + +void +wfd_log( + int level, + char const * format, + ...) +{ + if (g_wfd_logger.level >= level) + { + va_list args; + va_start(args, format); + g_wfd_logger.log( + g_wfd_logger.user_data, + level, + format, + args); + va_end(args); + } +} + +static void wfd_logger_default_log( + void * user_data, + int level, + char const * format, + va_list args) +{ + (void) user_data; + (void) level; + (void) format; + (void) args; +} diff --git a/src/webfused/log/logger.h b/src/webfused/log/logger.h new file mode 100644 index 0000000..2944b9c --- /dev/null +++ b/src/webfused/log/logger.h @@ -0,0 +1,40 @@ +#ifndef WFD_LOGGER_H +#define WFD_LOGGER_H + +#ifndef __cplusplus +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef void +wfd_logger_log_fn( + void * user_data, + int level, + char const * format, + va_list args); + +typedef void +wfd_logger_onclose_fn( + void * user_data); + +extern void +wfd_logger_init( + int level, + wfd_logger_log_fn * log, + wfd_logger_onclose_fn * onclose, + void * user_data); + +extern void +wfd_logger_close(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/test_log.cc b/test/test_log.cc new file mode 100644 index 0000000..57397f0 --- /dev/null +++ b/test/test_log.cc @@ -0,0 +1,152 @@ +#include +#include + +#include "webfused/log/logger.h" +#include "webfused/log/log.h" + +using ::testing::_; +using ::testing::StrEq; + +namespace +{ + +class ILogger +{ +public: + virtual ~ILogger() = default; + virtual void log(int level, char const * format, va_list args) = 0; + virtual void onclose() = 0; +}; + +class MockLogger: public ILogger +{ +public: + MOCK_METHOD3(log, void(int level, char const * format, va_list args)); + MOCK_METHOD0(onclose, void(void)); + + void * getUserData() + { + ILogger * logger = this; + return reinterpret_cast(logger); + } +}; + +} + +extern "C" +{ + +static void MockLogger_log( + void * user_data, + int level, + char const * format, + va_list args) +{ + ILogger * logger = reinterpret_cast(user_data); + logger->log(level, format, args); +} + +static void MockLogger_onclose( + void * user_data) +{ + ILogger * logger = reinterpret_cast(user_data); + logger->onclose(); +} + +} + +TEST(log, fatal) +{ + MockLogger logger; + + EXPECT_CALL(logger, log(WFD_LOGLEVEL_FATAL, StrEq("too bad"), _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + wfd_logger_init(WFD_LOGLEVEL_ALL, &MockLogger_log, &MockLogger_onclose, logger.getUserData()); + WFD_FATAL("too bad"); + wfd_logger_close(); +} + +TEST(log, error) +{ + MockLogger logger; + + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, StrEq("too bad"), _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + wfd_logger_init(WFD_LOGLEVEL_ALL, &MockLogger_log, &MockLogger_onclose, logger.getUserData()); + WFD_ERROR("too bad"); + wfd_logger_close(); +} + +TEST(log, warn) +{ + MockLogger logger; + + EXPECT_CALL(logger, log(WFD_LOGLEVEL_WARN, StrEq("too bad"), _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + wfd_logger_init(WFD_LOGLEVEL_ALL, &MockLogger_log, &MockLogger_onclose, logger.getUserData()); + WFD_WARN("too bad"); + wfd_logger_close(); +} + +TEST(log, info) +{ + MockLogger logger; + + EXPECT_CALL(logger, log(WFD_LOGLEVEL_INFO, StrEq("too bad"), _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + wfd_logger_init(WFD_LOGLEVEL_ALL, &MockLogger_log, &MockLogger_onclose, logger.getUserData()); + WFD_INFO("too bad"); + wfd_logger_close(); +} + +TEST(log, debug) +{ + MockLogger logger; + + EXPECT_CALL(logger, log(WFD_LOGLEVEL_DEBUG, StrEq("too bad"), _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + wfd_logger_init(WFD_LOGLEVEL_ALL, &MockLogger_log, &MockLogger_onclose, logger.getUserData()); + WFD_DEBUG("too bad"); + wfd_logger_close(); +} + +TEST(log, respect_loglevel) +{ + MockLogger logger; + + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + wfd_logger_init(WFD_LOGLEVEL_WARN, &MockLogger_log, &MockLogger_onclose, logger.getUserData()); + WFD_DEBUG("too bad"); + wfd_logger_close(); +} + +TEST(log, log_same_loglevel) +{ + MockLogger logger; + + EXPECT_CALL(logger, log(WFD_LOGLEVEL_WARN, StrEq("too bad"), _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + wfd_logger_init(WFD_LOGLEVEL_WARN, &MockLogger_log, &MockLogger_onclose, logger.getUserData()); + WFD_WARN("too bad"); + wfd_logger_close(); +} + +TEST(log, omit_onclose_if_nullptr) +{ + MockLogger logger; + + EXPECT_CALL(logger, log(WFD_LOGLEVEL_WARN, StrEq("too bad"), _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(0); + + wfd_logger_init(WFD_LOGLEVEL_WARN, &MockLogger_log, nullptr, logger.getUserData()); + WFD_WARN("too bad"); + wfd_logger_close(); +} From ad01f90bead056e7077cebabef52c8ff5961ad31 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 8 Mar 2020 20:29:08 +0100 Subject: [PATCH 10/36] log config errors --- CMakeLists.txt | 1 + src/webfused/config/factory.c | 13 +++--- test/mock_logger.cc | 58 +++++++++++++++++++++++++ test/mock_logger.hpp | 47 ++++++++++++++++++++ test/test_config.cc | 51 ++++++++++++++++++++++ test/test_log.cc | 82 ++++++++--------------------------- 6 files changed, 183 insertions(+), 69 deletions(-) create mode 100644 test/mock_logger.cc create mode 100644 test/mock_logger.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 08b25f1..52bf070 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -105,6 +105,7 @@ include(GoogleTest) pkg_check_modules(GMOCK gmock) add_executable(alltests + test/mock_logger.cc test/test_config.cc test/test_log.cc ) diff --git a/src/webfused/config/factory.c b/src/webfused/config/factory.c index aeb5b78..58cb8dc 100644 --- a/src/webfused/config/factory.c +++ b/src/webfused/config/factory.c @@ -1,6 +1,7 @@ #include "webfused/config/factory.h" #include "webfused/config/config_intern.h" #include "webfused/config/config.h" +#include "webfused/log/log.h" #include #include @@ -23,13 +24,15 @@ wfd_config_check_version( int rc = config_lookup_int(config, "version.major", &version_major); if (CONFIG_TRUE != rc) { - // error: missing major version + WFD_ERROR("failed to load config: missing version.major"); return false; } if (WFD_CONFIG_VERSION_MAJOR != version_major) { - // error: incompatible version, expected WFD_CONFIG_VERSION_MAJOR + WFD_ERROR("failed to load config: " + "incompatible versions: expected %d, but war %d", + WFD_CONFIG_VERSION_MAJOR, version_major); return false; } @@ -37,17 +40,17 @@ wfd_config_check_version( rc = config_lookup_int(config, "version.minor", &version_minor); if (CONFIG_TRUE != rc) { - // error: missing minor version + WFD_ERROR("failed to load config: missing version.minor"); return false; } if (WFD_CONFIG_VERSION_MINOR < version_minor) { - // warn: some features might be disabled + WFD_WARN("newer config detected: some features might be disabled"); } else if (WFD_CONFIG_VERSION_MINOR > version_minor) { - // info: use default values + WFD_INFO("old config detected: some features might use default values"); } return true; diff --git a/test/mock_logger.cc b/test/mock_logger.cc new file mode 100644 index 0000000..a36d89a --- /dev/null +++ b/test/mock_logger.cc @@ -0,0 +1,58 @@ +#include "mock_logger.hpp" +#include "webfused/log/logger.h" +#include "webfused/log/log.h" + +namespace webfused_test +{ + +MockLogger::MockLogger(bool omit_init) +: close_on_destruct(!omit_init) +{ + if (!omit_init) + { + wfd_logger_init( + WFD_LOGLEVEL_ALL, + &wfd_MockLogger_log, + &wfd_MockLogger_onclose, + getUserData()); + } +} + +MockLogger::~MockLogger() +{ + if (close_on_destruct) + { + wfd_logger_close(); + } +} + +void * MockLogger::getUserData() +{ + ILogger * logger = this; + return reinterpret_cast(logger); +} + +} + +extern "C" +{ +using webfused_test::ILogger; + +void wfd_MockLogger_log( + void * user_data, + int level, + char const * format, + va_list args) +{ + ILogger * logger = reinterpret_cast(user_data); + logger->log(level, format, args); +} + +void wfd_MockLogger_onclose( + void * user_data) +{ + ILogger * logger = reinterpret_cast(user_data); + logger->onclose(); +} + +} \ No newline at end of file diff --git a/test/mock_logger.hpp b/test/mock_logger.hpp new file mode 100644 index 0000000..3c3e381 --- /dev/null +++ b/test/mock_logger.hpp @@ -0,0 +1,47 @@ +#ifndef WFD_MOCK_LOGGER_HPP +#define WFD_MOCK_LOGGER_HPP + +#include +#include + +namespace webfused_test +{ + +class ILogger +{ +public: + virtual ~ILogger() = default; + virtual void log(int level, char const * format, va_list args) = 0; + virtual void onclose() = 0; +}; + +class MockLogger: public ILogger +{ +public: + explicit MockLogger(bool omit_init = false); + ~MockLogger() override; + MOCK_METHOD3(log, void(int level, char const * format, va_list args)); + MOCK_METHOD0(onclose, void(void)); + + void * getUserData(); +private: + bool close_on_destruct; +}; + +} + +extern "C" +{ + +extern void wfd_MockLogger_log( + void * user_data, + int level, + char const * format, + va_list args); + +extern void wfd_MockLogger_onclose( + void * user_data); + +} + +#endif diff --git a/test/test_config.cc b/test/test_config.cc index 63bae21..eb012bd 100644 --- a/test/test_config.cc +++ b/test/test_config.cc @@ -2,6 +2,13 @@ #include "webfused/config/factory.h" #include "webfused/config/config.h" +#include "webfused/log/logger.h" +#include "webfused/log/log.h" +#include "mock_logger.hpp" + + +using ::testing::_; +using ::webfused_test::MockLogger; TEST(config, is_loadable) { @@ -13,6 +20,10 @@ TEST(config, is_loadable) TEST(config, minimal_config) { + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + char const minimal[] = "version = { major = 1, minor = 0 }\n"; struct wfd_config * config = wfd_config_load_string(minimal); ASSERT_NE(nullptr, config); @@ -22,6 +33,10 @@ TEST(config, minimal_config) TEST(config, invalid_major_version_too_low) { + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + char const too_low[] = "version = { major = 0, minor = 0 }\n"; struct wfd_config * config = wfd_config_load_string(too_low); @@ -30,14 +45,46 @@ TEST(config, invalid_major_version_too_low) TEST(config, invalid_major_version_too_high) { + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + char const too_high[] = "version = { major = 2, minor = 0 }\n"; struct wfd_config * config = wfd_config_load_string(too_high); ASSERT_EQ(nullptr, config); } +TEST(config, invalid_missing_major_version) +{ + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + char const too_high[] = "version = { minor = 0 }\n"; + + struct wfd_config * config = wfd_config_load_string(too_high); + ASSERT_EQ(nullptr, config); +} + +TEST(config, invalid_missing_minor_version) +{ + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + char const too_high[] = "version = { major = 1 }\n"; + + struct wfd_config * config = wfd_config_load_string(too_high); + ASSERT_EQ(nullptr, config); +} + TEST(config, valid_older_minor) { + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_INFO, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + char const valid[] = "version = { major = 1, minor = -1 }\n"; struct wfd_config * config = wfd_config_load_string(valid); @@ -48,6 +95,10 @@ TEST(config, valid_older_minor) TEST(config, valid_newer_minor) { + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_WARN, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + char const valid[] = "version = { major = 1, minor = 1 }\n"; struct wfd_config * config = wfd_config_load_string(valid); diff --git a/test/test_log.cc b/test/test_log.cc index 57397f0..91ceb10 100644 --- a/test/test_log.cc +++ b/test/test_log.cc @@ -3,150 +3,104 @@ #include "webfused/log/logger.h" #include "webfused/log/log.h" +#include "mock_logger.hpp" using ::testing::_; using ::testing::StrEq; - -namespace -{ - -class ILogger -{ -public: - virtual ~ILogger() = default; - virtual void log(int level, char const * format, va_list args) = 0; - virtual void onclose() = 0; -}; - -class MockLogger: public ILogger -{ -public: - MOCK_METHOD3(log, void(int level, char const * format, va_list args)); - MOCK_METHOD0(onclose, void(void)); - - void * getUserData() - { - ILogger * logger = this; - return reinterpret_cast(logger); - } -}; - -} - -extern "C" -{ - -static void MockLogger_log( - void * user_data, - int level, - char const * format, - va_list args) -{ - ILogger * logger = reinterpret_cast(user_data); - logger->log(level, format, args); -} - -static void MockLogger_onclose( - void * user_data) -{ - ILogger * logger = reinterpret_cast(user_data); - logger->onclose(); -} - -} +using ::webfused_test::MockLogger; TEST(log, fatal) { - MockLogger logger; + MockLogger logger(true); EXPECT_CALL(logger, log(WFD_LOGLEVEL_FATAL, StrEq("too bad"), _)).Times(1); EXPECT_CALL(logger, onclose()).Times(1); - wfd_logger_init(WFD_LOGLEVEL_ALL, &MockLogger_log, &MockLogger_onclose, logger.getUserData()); + wfd_logger_init(WFD_LOGLEVEL_ALL, &wfd_MockLogger_log, &wfd_MockLogger_onclose, logger.getUserData()); WFD_FATAL("too bad"); wfd_logger_close(); } TEST(log, error) { - MockLogger logger; + MockLogger logger(true); EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, StrEq("too bad"), _)).Times(1); EXPECT_CALL(logger, onclose()).Times(1); - wfd_logger_init(WFD_LOGLEVEL_ALL, &MockLogger_log, &MockLogger_onclose, logger.getUserData()); + wfd_logger_init(WFD_LOGLEVEL_ALL, &wfd_MockLogger_log, &wfd_MockLogger_onclose, logger.getUserData()); WFD_ERROR("too bad"); wfd_logger_close(); } TEST(log, warn) { - MockLogger logger; + MockLogger logger(true); EXPECT_CALL(logger, log(WFD_LOGLEVEL_WARN, StrEq("too bad"), _)).Times(1); EXPECT_CALL(logger, onclose()).Times(1); - wfd_logger_init(WFD_LOGLEVEL_ALL, &MockLogger_log, &MockLogger_onclose, logger.getUserData()); + wfd_logger_init(WFD_LOGLEVEL_ALL, &wfd_MockLogger_log, &wfd_MockLogger_onclose, logger.getUserData()); WFD_WARN("too bad"); wfd_logger_close(); } TEST(log, info) { - MockLogger logger; + MockLogger logger(true); EXPECT_CALL(logger, log(WFD_LOGLEVEL_INFO, StrEq("too bad"), _)).Times(1); EXPECT_CALL(logger, onclose()).Times(1); - wfd_logger_init(WFD_LOGLEVEL_ALL, &MockLogger_log, &MockLogger_onclose, logger.getUserData()); + wfd_logger_init(WFD_LOGLEVEL_ALL, &wfd_MockLogger_log, &wfd_MockLogger_onclose, logger.getUserData()); WFD_INFO("too bad"); wfd_logger_close(); } TEST(log, debug) { - MockLogger logger; + MockLogger logger(true); EXPECT_CALL(logger, log(WFD_LOGLEVEL_DEBUG, StrEq("too bad"), _)).Times(1); EXPECT_CALL(logger, onclose()).Times(1); - wfd_logger_init(WFD_LOGLEVEL_ALL, &MockLogger_log, &MockLogger_onclose, logger.getUserData()); + wfd_logger_init(WFD_LOGLEVEL_ALL, &wfd_MockLogger_log, &wfd_MockLogger_onclose, logger.getUserData()); WFD_DEBUG("too bad"); wfd_logger_close(); } TEST(log, respect_loglevel) { - MockLogger logger; + MockLogger logger(true); EXPECT_CALL(logger, log(_, _, _)).Times(0); EXPECT_CALL(logger, onclose()).Times(1); - wfd_logger_init(WFD_LOGLEVEL_WARN, &MockLogger_log, &MockLogger_onclose, logger.getUserData()); + wfd_logger_init(WFD_LOGLEVEL_WARN, &wfd_MockLogger_log, &wfd_MockLogger_onclose, logger.getUserData()); WFD_DEBUG("too bad"); wfd_logger_close(); } TEST(log, log_same_loglevel) { - MockLogger logger; + MockLogger logger(true); EXPECT_CALL(logger, log(WFD_LOGLEVEL_WARN, StrEq("too bad"), _)).Times(1); EXPECT_CALL(logger, onclose()).Times(1); - wfd_logger_init(WFD_LOGLEVEL_WARN, &MockLogger_log, &MockLogger_onclose, logger.getUserData()); + wfd_logger_init(WFD_LOGLEVEL_WARN, &wfd_MockLogger_log, &wfd_MockLogger_onclose, logger.getUserData()); WFD_WARN("too bad"); wfd_logger_close(); } TEST(log, omit_onclose_if_nullptr) { - MockLogger logger; + MockLogger logger(true); EXPECT_CALL(logger, log(WFD_LOGLEVEL_WARN, StrEq("too bad"), _)).Times(1); EXPECT_CALL(logger, onclose()).Times(0); - wfd_logger_init(WFD_LOGLEVEL_WARN, &MockLogger_log, nullptr, logger.getUserData()); + wfd_logger_init(WFD_LOGLEVEL_WARN, &wfd_MockLogger_log, nullptr, logger.getUserData()); WFD_WARN("too bad"); wfd_logger_close(); } From 7e70d396f1554e31daf4693cbe91118805367131 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 8 Mar 2020 20:48:34 +0100 Subject: [PATCH 11/36] ignore tests for coverage --- codecov.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..2efff1f --- /dev/null +++ b/codecov.yml @@ -0,0 +1,2 @@ +ignore: + - test From d8670b742c9796d3801bce91f219be79ac5a8feb Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Mon, 9 Mar 2020 23:25:47 +0100 Subject: [PATCH 12/36] log syntax errors --- src/webfused/config/factory.c | 19 +++++++++++++++++-- test/test_config.cc | 12 ++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/webfused/config/factory.c b/src/webfused/config/factory.c index 58cb8dc..32837a9 100644 --- a/src/webfused/config/factory.c +++ b/src/webfused/config/factory.c @@ -84,8 +84,16 @@ wfd_config_load_file( if (CONFIG_TRUE == rc) { result = wfd_config_load(&config); - config_destroy(&config); } + else + { + WFD_ERROR("failed to load config: %s: %d: %s", + config_error_file(&config), + config_error_line(&config), + config_error_text(&config)); + } + config_destroy(&config); + return result; } @@ -102,8 +110,15 @@ wfd_config_load_string( if (CONFIG_TRUE == rc) { result = wfd_config_load(&config); - config_destroy(&config); } + else + { + WFD_ERROR("failed to load config: %d: %s", + config_error_line(&config), + config_error_text(&config)); + } + config_destroy(&config); + return result; } diff --git a/test/test_config.cc b/test/test_config.cc index eb012bd..49e8de4 100644 --- a/test/test_config.cc +++ b/test/test_config.cc @@ -31,6 +31,18 @@ TEST(config, minimal_config) wfd_config_dispose(config); } +TEST(config, invalid_config) +{ + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + char const syntax_error[] = "version.major = 1\n"; + + struct wfd_config * config = wfd_config_load_string(syntax_error); + ASSERT_EQ(nullptr, config); +} + TEST(config, invalid_major_version_too_low) { MockLogger logger; From 389c27c7eba47e46f5ceb5246c2ef1c56700998f Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Mon, 9 Mar 2020 23:59:36 +0100 Subject: [PATCH 13/36] read server config --- src/webfused/config/config.c | 62 ++++++++++- src/webfused/config/config.h | 5 + src/webfused/config/config_intern.h | 34 ++++-- src/webfused/config/factory.c | 47 +++++++- test/test_config.cc | 163 +++++++++++++++++++++++++++- 5 files changed, 299 insertions(+), 12 deletions(-) diff --git a/src/webfused/config/config.c b/src/webfused/config/config.c index c2d13ef..a994ffb 100644 --- a/src/webfused/config/config.c +++ b/src/webfused/config/config.c @@ -7,6 +7,15 @@ #define WFD_CONFIG_DEFAULT_PORT (8080) #define WFD_CONFIG_DEFAULT_VHOSTNAME ("localhost") +struct wfd_config +{ + char * vhost_name; + char * server_cert; + char * server_key; + char * server_doc_root; + int port; +}; + extern struct wfd_config * wfd_config_create(void) { @@ -28,7 +37,6 @@ void wfd_config_dispose( free(config->server_key); free(config->server_doc_root); free(config); - } int @@ -38,6 +46,14 @@ wfd_config_get_server_port( return config->port; } +void +wfd_config_set_server_port( + struct wfd_config * config, + int port) +{ + config->port = port; +} + char const * wfd_config_get_server_vhostname( struct wfd_config * config) @@ -45,6 +61,23 @@ wfd_config_get_server_vhostname( return config->vhost_name; } +void +wfd_config_set_server_vhostname( + struct wfd_config * config, + char const * vhost_name) +{ + free(config->vhost_name); + config->vhost_name = strdup(vhost_name); +} + +bool +wfd_config_is_server_tls_enabled( + struct wfd_config * config) +{ + return ((NULL != config->server_key) + && (NULL != config->server_cert)); +} + char const * wfd_config_get_server_cert( struct wfd_config * config) @@ -52,6 +85,15 @@ wfd_config_get_server_cert( return config->server_cert; } +void +wfd_config_set_server_cert( + struct wfd_config * config, + char const * cert) +{ + free(config->server_cert); + config->server_cert = strdup(cert); +} + char const * wfd_config_get_server_key( struct wfd_config * config) @@ -59,6 +101,15 @@ wfd_config_get_server_key( return config->server_key; } +void +wfd_config_set_server_key( + struct wfd_config * config, + char const * key) +{ + free(config->server_key); + config->server_key = strdup(key); +} + char const * wfd_config_get_server_document_root( struct wfd_config * config) @@ -66,6 +117,15 @@ wfd_config_get_server_document_root( return config->server_doc_root; } +void +wfd_config_set_server_document_root( + struct wfd_config * config, + char const * document_root) +{ + free(config->server_doc_root); + config->server_doc_root = strdup(document_root); +} + char const * wfd_config_get_auth_provider( struct wfd_config * config) diff --git a/src/webfused/config/config.h b/src/webfused/config/config.h index 8480f4e..813e2d4 100644 --- a/src/webfused/config/config.h +++ b/src/webfused/config/config.h @@ -2,6 +2,7 @@ #define WFD_CONFIG_H #ifndef __cplusplus +#include #include #else #include @@ -31,6 +32,10 @@ extern char const * wfd_config_get_server_cert( struct wfd_config * config); +extern bool +wfd_config_is_server_tls_enabled( + struct wfd_config * config); + extern char const * wfd_config_get_server_key( struct wfd_config * config); diff --git a/src/webfused/config/config_intern.h b/src/webfused/config/config_intern.h index 792e957..fee762a 100644 --- a/src/webfused/config/config_intern.h +++ b/src/webfused/config/config_intern.h @@ -6,18 +6,34 @@ extern "C" { #endif -struct wfd_config -{ - char * vhost_name; - char * server_cert; - char * server_key; - char * server_doc_root; - int port; -}; - extern struct wfd_config * wfd_config_create(void); +extern void +wfd_config_set_server_vhostname( + struct wfd_config * config, + char const * vhost_name); + +extern void +wfd_config_set_server_port( + struct wfd_config * config, + int port); + +extern void +wfd_config_set_server_cert( + struct wfd_config * config, + char const * cert); + +extern void +wfd_config_set_server_key( + struct wfd_config * config, + char const * key); + +extern void +wfd_config_set_server_document_root( + struct wfd_config * config, + char const * document_root); + #ifdef _cplusplus } #endif diff --git a/src/webfused/config/factory.c b/src/webfused/config/factory.c index 32837a9..11b1ff7 100644 --- a/src/webfused/config/factory.c +++ b/src/webfused/config/factory.c @@ -56,12 +56,57 @@ wfd_config_check_version( return true; } +static bool +wfd_config_read_server( + config_t * config, + struct wfd_config * result) +{ + char const * vhost_name; + int rc = config_lookup_string(config, "server.vhost_name", &vhost_name); + if (CONFIG_TRUE == rc) + { + wfd_config_set_server_vhostname(result, vhost_name); + } + + int port; + rc = config_lookup_int(config, "server.port", &port); + if (CONFIG_TRUE == rc) + { + wfd_config_set_server_port(result, port); + } + + char const * cert; + rc = config_lookup_string(config, "server.tls.certificate", &cert); + if (CONFIG_TRUE == rc) + { + wfd_config_set_server_cert(result, cert); + } + + char const * key; + rc = config_lookup_string(config, "server.tls.key", &key); + if (CONFIG_TRUE == rc) + { + wfd_config_set_server_key(result, key); + } + + char const * doc_root; + rc = config_lookup_string(config, "server.document_root", &doc_root); + if (CONFIG_TRUE == rc) + { + wfd_config_set_server_document_root(result, doc_root); + } + + return true; +} + static struct wfd_config * wfd_config_load(config_t * config) { struct wfd_config * result = wfd_config_create(); - bool success = wfd_config_check_version(config); + bool success = wfd_config_check_version(config) + && wfd_config_read_server(config, result) + ; if (!success) { diff --git a/test/test_config.cc b/test/test_config.cc index 49e8de4..59bdf63 100644 --- a/test/test_config.cc +++ b/test/test_config.cc @@ -117,4 +117,165 @@ TEST(config, valid_newer_minor) ASSERT_NE(nullptr, config); wfd_config_dispose(config); -} \ No newline at end of file +} + +TEST(config, default_values) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + char const minimal[] = "version = { major = 1, minor = 0 }\n"; + struct wfd_config * config = wfd_config_load_string(minimal); + ASSERT_NE(nullptr, config); + + ASSERT_EQ(8080, wfd_config_get_server_port(config)); + ASSERT_STREQ("localhost", wfd_config_get_server_vhostname(config)); + ASSERT_EQ(nullptr, wfd_config_get_server_cert(config)); + ASSERT_EQ(nullptr, wfd_config_get_server_key(config)); + ASSERT_EQ(nullptr, wfd_config_get_server_document_root(config)); + + wfd_config_dispose(config); +} + +TEST(config, vhost_name) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "server:\n" + "{\n" + " vhost_name = \"some.host\"\n" + "}\n" + ; + struct wfd_config * config = wfd_config_load_string(config_text); + ASSERT_NE(nullptr, config); + + ASSERT_STREQ("some.host", wfd_config_get_server_vhostname(config)); + + wfd_config_dispose(config); +} + +TEST(config, port) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "server:\n" + "{\n" + " port = 54321\n" + "}\n" + ; + struct wfd_config * config = wfd_config_load_string(config_text); + ASSERT_NE(nullptr, config); + + ASSERT_EQ(54321, wfd_config_get_server_port(config)); + + wfd_config_dispose(config); +} + +TEST(config, tls) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "server:\n" + "{\n" + " tls:\n" + " {\n" + " certificate = \"/path/to/cert.pem\"\n" + " key = \"/path/to/key.pem\"\n" + " }\n" + "}\n" + ; + struct wfd_config * config = wfd_config_load_string(config_text); + ASSERT_NE(nullptr, config); + + ASSERT_TRUE(wfd_config_is_server_tls_enabled(config)); + ASSERT_STREQ("/path/to/cert.pem", wfd_config_get_server_cert(config)); + ASSERT_STREQ("/path/to/key.pem", wfd_config_get_server_key(config)); + + wfd_config_dispose(config); +} + +TEST(config, tls_certificate) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "server:\n" + "{\n" + " tls:\n" + " {\n" + " certificate = \"/path/to/cert.pem\"\n" + " }\n" + "}\n" + ; + struct wfd_config * config = wfd_config_load_string(config_text); + ASSERT_NE(nullptr, config); + + ASSERT_FALSE(wfd_config_is_server_tls_enabled(config)); + ASSERT_STREQ("/path/to/cert.pem", wfd_config_get_server_cert(config)); + ASSERT_EQ(nullptr, wfd_config_get_server_key(config)); + + wfd_config_dispose(config); +} + +TEST(config, tls_key) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "server:\n" + "{\n" + " tls:\n" + " {\n" + " key = \"/path/to/key.pem\"\n" + " }\n" + "}\n" + ; + struct wfd_config * config = wfd_config_load_string(config_text); + ASSERT_NE(nullptr, config); + + ASSERT_FALSE(wfd_config_is_server_tls_enabled(config)); + ASSERT_EQ(nullptr, wfd_config_get_server_cert(config)); + ASSERT_STREQ("/path/to/key.pem", wfd_config_get_server_key(config)); + + wfd_config_dispose(config); +} + +TEST(config, document_root) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "server:\n" + "{\n" + " document_root = \"/var/www\"\n" + "}\n" + ; + struct wfd_config * config = wfd_config_load_string(config_text); + ASSERT_NE(nullptr, config); + + ASSERT_STREQ("/var/www", wfd_config_get_server_document_root(config)); + + wfd_config_dispose(config); +} From 79fa1f6cbf86048e9469d18fabd47d654e101070 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Tue, 10 Mar 2020 21:56:15 +0100 Subject: [PATCH 14/36] added authentication settings (stub) --- src/webfused/authentication/auth_settings.h | 30 +++++++++++++++++++ .../authentication/auth_settings_builder.h | 28 +++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 src/webfused/authentication/auth_settings.h create mode 100644 src/webfused/authentication/auth_settings_builder.h diff --git a/src/webfused/authentication/auth_settings.h b/src/webfused/authentication/auth_settings.h new file mode 100644 index 0000000..5e214c8 --- /dev/null +++ b/src/webfused/authentication/auth_settings.h @@ -0,0 +1,30 @@ +#ifndef WFD_AUTH_SETTINGS_H +#define WFD_AUTH_SETTINGS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wfd_auth_settings; + + +extern char const * +wfd_auth_settings_get_provider( + struct wfd_auth_settings * settings); + +extern char const * +wfd_auth_settings_get( + struct wfd_auth_settings * settings, + char const * key); + + + + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/src/webfused/authentication/auth_settings_builder.h b/src/webfused/authentication/auth_settings_builder.h new file mode 100644 index 0000000..6de12c7 --- /dev/null +++ b/src/webfused/authentication/auth_settings_builder.h @@ -0,0 +1,28 @@ +#ifndef WFD_AUTH_SETTINGS_BUILDER_H +#define WFD_AUTH_SETTINGS_BUILDER_H + +#ifdef __cplusplus +#endif + +extern struct wfd_auth_settings * +wfd_auth_settings_create(void); + +extern void +wfd_auth_settings_dispose( + struct wfd_auth_settings * settings); + +extern void +wfd_auth_settings_set_provider( + struct wfd_auth_settings * settings, + char const * provider); + +extern void +wfd_auth_settings_add( + struct wfd_auth_settings * settings, + char const * key, + char const * value); + +#ifdef __cplusplus +#endif + +#endif From 892dd6d177efe47d5fbf59afee18c3a8510acdb1 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 15 Mar 2020 21:48:45 +0100 Subject: [PATCH 15/36] use builder to load config --- CMakeLists.txt | 2 + src/webfused/config/builder.c | 42 +++++++++ src/webfused/config/builder.h | 79 ++++++++++++++++ src/webfused/config/factory.c | 45 ++++----- src/webfused/config/factory.h | 12 ++- test/mock_config_builder.cc | 76 +++++++++++++++ test/mock_config_builder.hpp | 36 +++++++ test/test_config.cc | 172 +++++++++++++--------------------- 8 files changed, 331 insertions(+), 133 deletions(-) create mode 100644 src/webfused/config/builder.c create mode 100644 src/webfused/config/builder.h create mode 100644 test/mock_config_builder.cc create mode 100644 test/mock_config_builder.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 52bf070..b2bce3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,7 @@ add_library(webfused-static STATIC src/webfused/daemon.c src/webfused/config/config.c src/webfused/config/factory.c + src/webfused/config/builder.c src/webfused/log/logger.c ) @@ -105,6 +106,7 @@ include(GoogleTest) pkg_check_modules(GMOCK gmock) add_executable(alltests + test/mock_config_builder.cc test/mock_logger.cc test/test_config.cc test/test_log.cc diff --git a/src/webfused/config/builder.c b/src/webfused/config/builder.c new file mode 100644 index 0000000..7d1c6c1 --- /dev/null +++ b/src/webfused/config/builder.c @@ -0,0 +1,42 @@ +#include "webfused/config/builder.h" + +void +wfd_config_builder_set_server_vhostname( + struct wfd_config_builder builder, + char const * vhost_name) +{ + builder.vtable->set_server_vhostname(builder.data, vhost_name); +} + +void +wfd_config_builder_set_server_port( + struct wfd_config_builder builder, + int port) +{ + builder.vtable->set_server_port(builder.data, port); +} + +void +wfd_config_builder_set_server_key( + struct wfd_config_builder builder, + char const * key_path) +{ + builder.vtable->set_server_key(builder.data, key_path); +} + +void +wfd_config_builder_set_server_cert( + struct wfd_config_builder builder, + char const * cert_path) +{ + builder.vtable->set_server_cert(builder.data, cert_path); +} + +void +wfd_config_builder_set_server_document_root( + struct wfd_config_builder builder, + char const * document_root) +{ + builder.vtable->set_server_document_root(builder.data, document_root); +} + diff --git a/src/webfused/config/builder.h b/src/webfused/config/builder.h new file mode 100644 index 0000000..0dbc753 --- /dev/null +++ b/src/webfused/config/builder.h @@ -0,0 +1,79 @@ +#ifndef WFD_CONFIG_BUILDER_H +#define WFD_CONFIG_BUILDER_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef void +wfd_config_builder_set_server_vhostname_fn( + void * data, + char const * vhost_name); + +typedef void +wfd_config_builder_set_server_port_fn( + void * data, + int port); + +typedef void +wfd_config_builder_set_server_key_fn( + void * data, + char const * key_path); + +typedef void +wfd_config_builder_set_server_cert_fn( + void * data, + char const * cert_path); + +typedef void +wfd_config_builder_set_server_document_root_fn( + void * data, + char const * document_root); + +struct wfd_config_builder_vtable +{ + wfd_config_builder_set_server_vhostname_fn * set_server_vhostname; + wfd_config_builder_set_server_port_fn * set_server_port; + wfd_config_builder_set_server_key_fn * set_server_key; + wfd_config_builder_set_server_cert_fn * set_server_cert; + wfd_config_builder_set_server_document_root_fn * set_server_document_root; +}; + +struct wfd_config_builder +{ + struct wfd_config_builder_vtable const * vtable; + void * data; +}; + +extern void +wfd_config_builder_set_server_vhostname( + struct wfd_config_builder builder, + char const * vhost_name); + +extern void +wfd_config_builder_set_server_port( + struct wfd_config_builder builder, + int port); + +extern void +wfd_config_builder_set_server_key( + struct wfd_config_builder builder, + char const * key_path); + +extern void +wfd_config_builder_set_server_cert( + struct wfd_config_builder builder, + char const * cert_path); + +extern void +wfd_config_builder_set_server_document_root( + struct wfd_config_builder builder, + char const * document_root); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/webfused/config/factory.c b/src/webfused/config/factory.c index 11b1ff7..36096a1 100644 --- a/src/webfused/config/factory.c +++ b/src/webfused/config/factory.c @@ -1,6 +1,4 @@ #include "webfused/config/factory.h" -#include "webfused/config/config_intern.h" -#include "webfused/config/config.h" #include "webfused/log/log.h" #include @@ -59,76 +57,72 @@ wfd_config_check_version( static bool wfd_config_read_server( config_t * config, - struct wfd_config * result) + struct wfd_config_builder builder) { char const * vhost_name; int rc = config_lookup_string(config, "server.vhost_name", &vhost_name); if (CONFIG_TRUE == rc) { - wfd_config_set_server_vhostname(result, vhost_name); + wfd_config_builder_set_server_vhostname(builder, vhost_name); } int port; rc = config_lookup_int(config, "server.port", &port); if (CONFIG_TRUE == rc) { - wfd_config_set_server_port(result, port); + wfd_config_builder_set_server_port(builder, port); } char const * cert; rc = config_lookup_string(config, "server.tls.certificate", &cert); if (CONFIG_TRUE == rc) { - wfd_config_set_server_cert(result, cert); + wfd_config_builder_set_server_cert(builder, cert); } char const * key; rc = config_lookup_string(config, "server.tls.key", &key); if (CONFIG_TRUE == rc) { - wfd_config_set_server_key(result, key); + wfd_config_builder_set_server_key(builder, key); } char const * doc_root; rc = config_lookup_string(config, "server.document_root", &doc_root); if (CONFIG_TRUE == rc) { - wfd_config_set_server_document_root(result, doc_root); + wfd_config_builder_set_server_document_root(builder, doc_root); } return true; } -static struct wfd_config * -wfd_config_load(config_t * config) +static bool +wfd_config_load( + struct wfd_config_builder builder, + config_t * config) { - struct wfd_config * result = wfd_config_create(); - bool success = wfd_config_check_version(config) - && wfd_config_read_server(config, result) + bool result = wfd_config_check_version(config) + && wfd_config_read_server(config, builder) ; - if (!success) - { - wfd_config_dispose(result); - result = NULL; - } - return result; } -struct wfd_config * +bool wfd_config_load_file( + struct wfd_config_builder builder, char const * filename) { - struct wfd_config * result = NULL; + bool result = false; config_t config; config_init(&config); int rc = config_read_file(&config, filename); if (CONFIG_TRUE == rc) { - result = wfd_config_load(&config); + result = wfd_config_load(builder, &config); } else { @@ -143,18 +137,19 @@ wfd_config_load_file( return result; } -struct wfd_config * +bool wfd_config_load_string( + struct wfd_config_builder builder, char const * contents) { - struct wfd_config * result = NULL; + bool result = false; config_t config; config_init(&config); int rc = config_read_string(&config, contents); if (CONFIG_TRUE == rc) { - result = wfd_config_load(&config); + result = wfd_config_load(builder, &config); } else { diff --git a/src/webfused/config/factory.h b/src/webfused/config/factory.h index f058b4c..f2dcd5d 100644 --- a/src/webfused/config/factory.h +++ b/src/webfused/config/factory.h @@ -1,17 +1,25 @@ #ifndef WFD_CONFIG_FACTORY_H #define WFD_CONFIG_FACTORY_H +#ifndef __cplusplus +#include +#endif + +#include "webfused/config/builder.h" + #ifdef __cplusplus extern "C" { #endif -extern struct wfd_config * +extern bool wfd_config_load_file( + struct wfd_config_builder builder, char const * filename); -extern struct wfd_config * +extern bool wfd_config_load_string( + struct wfd_config_builder builder, char const * contents); #ifdef __cplusplus diff --git a/test/mock_config_builder.cc b/test/mock_config_builder.cc new file mode 100644 index 0000000..90334b7 --- /dev/null +++ b/test/mock_config_builder.cc @@ -0,0 +1,76 @@ +#include "mock_config_builder.hpp" + +extern "C" +{ +using webfused_test::IConfigBuilder; + +static void +wfd_MockConifigBuilder_set_server_vhostname( + void * data, + char const * vhost_name) +{ + auto * builder = reinterpret_cast(data); + builder->setServerVhostname(vhost_name); +} + +static void +wfd_MockConifigBuilder_set_server_port( + void * data, + int port) +{ + auto * builder = reinterpret_cast(data); + builder->setServerPort(port); +} + +static void +wfd_MockConifigBuilder_set_server_key( + void * data, + char const * key_path) +{ + auto * builder = reinterpret_cast(data); + builder->setServerKey(key_path); +} + +static void +wfd_MockConifigBuilder_set_server_cert( + void * data, + char const * cert_path) +{ + auto * builder = reinterpret_cast(data); + builder->setServerCert(cert_path); +} + +static void +wfd_MockConifigBuilder_set_server_document_root( + void * data, + char const * document_root) +{ + auto * builder = reinterpret_cast(data); + builder->setServerDocumentRoot(document_root); +} + +static const wfd_config_builder_vtable wfd_MockConfigBuilder_vtable = +{ + &wfd_MockConifigBuilder_set_server_vhostname, + &wfd_MockConifigBuilder_set_server_port, + &wfd_MockConifigBuilder_set_server_key, + &wfd_MockConifigBuilder_set_server_cert, + &wfd_MockConifigBuilder_set_server_document_root +}; + +} + +namespace webfused_test +{ + struct wfd_config_builder MockConfigBuilder::getBuilder() + { + IConfigBuilder * config_builder = this; + + wfd_config_builder builder = { + &wfd_MockConfigBuilder_vtable, + reinterpret_cast(config_builder) + }; + + return builder; + } +} \ No newline at end of file diff --git a/test/mock_config_builder.hpp b/test/mock_config_builder.hpp new file mode 100644 index 0000000..4620bf0 --- /dev/null +++ b/test/mock_config_builder.hpp @@ -0,0 +1,36 @@ +#ifndef WFD_MOCK_CONFIG_BUILDER_HPP +#define WFD_MOCK_CONFIG_BUILDER_HPP + +#include +#include "webfused/config/builder.h" + +namespace webfused_test +{ + +class IConfigBuilder +{ +public: + virtual ~IConfigBuilder() = default; + virtual void setServerVhostname(char const * vhostname) = 0; + virtual void setServerPort(int port) = 0; + virtual void setServerKey(char const * key_path) = 0; + virtual void setServerCert(char const * cert_path) = 0; + virtual void setServerDocumentRoot(char const * document_root) = 0; +}; + +class MockConfigBuilder: public IConfigBuilder +{ +public: + ~MockConfigBuilder() override = default; + MOCK_METHOD1(setServerVhostname, void (char const * vhostname)); + MOCK_METHOD1(setServerPort, void (int port)); + MOCK_METHOD1(setServerKey, void (char const * key_path)); + MOCK_METHOD1(setServerCert, void (char const * cert_path)); + MOCK_METHOD1(setServerDocumentRoot, void (char const * document_root)); + + struct wfd_config_builder getBuilder(); +}; + +} + +#endif diff --git a/test/test_config.cc b/test/test_config.cc index 59bdf63..c0179b1 100644 --- a/test/test_config.cc +++ b/test/test_config.cc @@ -1,21 +1,26 @@ #include #include "webfused/config/factory.h" -#include "webfused/config/config.h" #include "webfused/log/logger.h" #include "webfused/log/log.h" #include "mock_logger.hpp" +#include "mock_config_builder.hpp" using ::testing::_; +using ::testing::StrictMock; +using ::testing::StrEq; using ::webfused_test::MockLogger; +using ::webfused_test::MockConfigBuilder; TEST(config, is_loadable) { - struct wfd_config * config = wfd_config_load_file("webfused.conf"); - ASSERT_NE(nullptr, config); + StrictMock builder; + EXPECT_CALL(builder, setServerVhostname(StrEq("localhost"))).Times(1); + EXPECT_CALL(builder, setServerPort(8080)).Times(1); - wfd_config_dispose(config); + bool result = wfd_config_load_file(builder.getBuilder(), "webfused.conf"); + ASSERT_TRUE(result); } TEST(config, minimal_config) @@ -24,11 +29,11 @@ TEST(config, minimal_config) EXPECT_CALL(logger, log(_, _, _)).Times(0); EXPECT_CALL(logger, onclose()).Times(1); - char const minimal[] = "version = { major = 1, minor = 0 }\n"; - struct wfd_config * config = wfd_config_load_string(minimal); - ASSERT_NE(nullptr, config); + StrictMock builder; - wfd_config_dispose(config); + char const minimal[] = "version = { major = 1, minor = 0 }\n"; + bool result = wfd_config_load_string(builder.getBuilder(), minimal); + ASSERT_TRUE(result); } TEST(config, invalid_config) @@ -37,10 +42,12 @@ TEST(config, invalid_config) EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); EXPECT_CALL(logger, onclose()).Times(1); + StrictMock builder; + char const syntax_error[] = "version.major = 1\n"; - struct wfd_config * config = wfd_config_load_string(syntax_error); - ASSERT_EQ(nullptr, config); + bool result = wfd_config_load_string(builder.getBuilder(), syntax_error); + ASSERT_FALSE(result); } TEST(config, invalid_major_version_too_low) @@ -49,10 +56,12 @@ TEST(config, invalid_major_version_too_low) EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); EXPECT_CALL(logger, onclose()).Times(1); + StrictMock builder; + char const too_low[] = "version = { major = 0, minor = 0 }\n"; - struct wfd_config * config = wfd_config_load_string(too_low); - ASSERT_EQ(nullptr, config); + bool result = wfd_config_load_string(builder.getBuilder(), too_low); + ASSERT_FALSE(result); } TEST(config, invalid_major_version_too_high) @@ -61,10 +70,12 @@ TEST(config, invalid_major_version_too_high) EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); EXPECT_CALL(logger, onclose()).Times(1); + StrictMock builder; + char const too_high[] = "version = { major = 2, minor = 0 }\n"; - struct wfd_config * config = wfd_config_load_string(too_high); - ASSERT_EQ(nullptr, config); + bool result = wfd_config_load_string(builder.getBuilder(), too_high); + ASSERT_FALSE(result); } TEST(config, invalid_missing_major_version) @@ -73,10 +84,12 @@ TEST(config, invalid_missing_major_version) EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); EXPECT_CALL(logger, onclose()).Times(1); + StrictMock builder; + char const too_high[] = "version = { minor = 0 }\n"; - struct wfd_config * config = wfd_config_load_string(too_high); - ASSERT_EQ(nullptr, config); + bool result = wfd_config_load_string(builder.getBuilder(), too_high); + ASSERT_FALSE(result); } TEST(config, invalid_missing_minor_version) @@ -85,10 +98,12 @@ TEST(config, invalid_missing_minor_version) EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); EXPECT_CALL(logger, onclose()).Times(1); + StrictMock builder; + char const too_high[] = "version = { major = 1 }\n"; - struct wfd_config * config = wfd_config_load_string(too_high); - ASSERT_EQ(nullptr, config); + bool result = wfd_config_load_string(builder.getBuilder(), too_high); + ASSERT_FALSE(result); } TEST(config, valid_older_minor) @@ -97,12 +112,12 @@ TEST(config, valid_older_minor) EXPECT_CALL(logger, log(WFD_LOGLEVEL_INFO, _, _)).Times(1); EXPECT_CALL(logger, onclose()).Times(1); - char const valid[] = "version = { major = 1, minor = -1 }\n"; + StrictMock builder; - struct wfd_config * config = wfd_config_load_string(valid); - ASSERT_NE(nullptr, config); + char const valid[] = "version = { major = 1, minor = -1 }\n"; - wfd_config_dispose(config); + bool result = wfd_config_load_string(builder.getBuilder(), valid); + ASSERT_TRUE(result); } TEST(config, valid_newer_minor) @@ -111,31 +126,12 @@ TEST(config, valid_newer_minor) EXPECT_CALL(logger, log(WFD_LOGLEVEL_WARN, _, _)).Times(1); EXPECT_CALL(logger, onclose()).Times(1); - char const valid[] = "version = { major = 1, minor = 1 }\n"; - - struct wfd_config * config = wfd_config_load_string(valid); - ASSERT_NE(nullptr, config); - - wfd_config_dispose(config); -} - -TEST(config, default_values) -{ - MockLogger logger; - EXPECT_CALL(logger, log(_, _, _)).Times(0); - EXPECT_CALL(logger, onclose()).Times(1); - - char const minimal[] = "version = { major = 1, minor = 0 }\n"; - struct wfd_config * config = wfd_config_load_string(minimal); - ASSERT_NE(nullptr, config); + StrictMock builder; - ASSERT_EQ(8080, wfd_config_get_server_port(config)); - ASSERT_STREQ("localhost", wfd_config_get_server_vhostname(config)); - ASSERT_EQ(nullptr, wfd_config_get_server_cert(config)); - ASSERT_EQ(nullptr, wfd_config_get_server_key(config)); - ASSERT_EQ(nullptr, wfd_config_get_server_document_root(config)); + char const valid[] = "version = { major = 1, minor = 1 }\n"; - wfd_config_dispose(config); + bool result = wfd_config_load_string(builder.getBuilder(), valid); + ASSERT_TRUE(result); } TEST(config, vhost_name) @@ -144,6 +140,9 @@ TEST(config, vhost_name) EXPECT_CALL(logger, log(_, _, _)).Times(0); EXPECT_CALL(logger, onclose()).Times(1); + StrictMock builder; + EXPECT_CALL(builder, setServerVhostname(StrEq("some.host"))).Times(1); + char const config_text[] = "version = { major = 1, minor = 0 }\n" "server:\n" @@ -151,12 +150,8 @@ TEST(config, vhost_name) " vhost_name = \"some.host\"\n" "}\n" ; - struct wfd_config * config = wfd_config_load_string(config_text); - ASSERT_NE(nullptr, config); - - ASSERT_STREQ("some.host", wfd_config_get_server_vhostname(config)); - - wfd_config_dispose(config); + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_TRUE(result); } TEST(config, port) @@ -165,46 +160,18 @@ TEST(config, port) EXPECT_CALL(logger, log(_, _, _)).Times(0); EXPECT_CALL(logger, onclose()).Times(1); - char const config_text[] = - "version = { major = 1, minor = 0 }\n" - "server:\n" - "{\n" - " port = 54321\n" - "}\n" - ; - struct wfd_config * config = wfd_config_load_string(config_text); - ASSERT_NE(nullptr, config); - - ASSERT_EQ(54321, wfd_config_get_server_port(config)); - - wfd_config_dispose(config); -} - -TEST(config, tls) -{ - MockLogger logger; - EXPECT_CALL(logger, log(_, _, _)).Times(0); - EXPECT_CALL(logger, onclose()).Times(1); + StrictMock builder; + EXPECT_CALL(builder, setServerPort(54321)).Times(1); char const config_text[] = "version = { major = 1, minor = 0 }\n" "server:\n" "{\n" - " tls:\n" - " {\n" - " certificate = \"/path/to/cert.pem\"\n" - " key = \"/path/to/key.pem\"\n" - " }\n" + " port = 54321\n" "}\n" ; - struct wfd_config * config = wfd_config_load_string(config_text); - ASSERT_NE(nullptr, config); - - ASSERT_TRUE(wfd_config_is_server_tls_enabled(config)); - ASSERT_STREQ("/path/to/cert.pem", wfd_config_get_server_cert(config)); - ASSERT_STREQ("/path/to/key.pem", wfd_config_get_server_key(config)); - - wfd_config_dispose(config); + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_TRUE(result); } TEST(config, tls_certificate) @@ -213,6 +180,9 @@ TEST(config, tls_certificate) EXPECT_CALL(logger, log(_, _, _)).Times(0); EXPECT_CALL(logger, onclose()).Times(1); + StrictMock builder; + EXPECT_CALL(builder, setServerCert(StrEq("/path/to/cert.pem"))).Times(1); + char const config_text[] = "version = { major = 1, minor = 0 }\n" "server:\n" @@ -223,14 +193,8 @@ TEST(config, tls_certificate) " }\n" "}\n" ; - struct wfd_config * config = wfd_config_load_string(config_text); - ASSERT_NE(nullptr, config); - - ASSERT_FALSE(wfd_config_is_server_tls_enabled(config)); - ASSERT_STREQ("/path/to/cert.pem", wfd_config_get_server_cert(config)); - ASSERT_EQ(nullptr, wfd_config_get_server_key(config)); - - wfd_config_dispose(config); + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_TRUE(result); } TEST(config, tls_key) @@ -239,6 +203,9 @@ TEST(config, tls_key) EXPECT_CALL(logger, log(_, _, _)).Times(0); EXPECT_CALL(logger, onclose()).Times(1); + StrictMock builder; + EXPECT_CALL(builder, setServerKey(StrEq("/path/to/key.pem"))).Times(1); + char const config_text[] = "version = { major = 1, minor = 0 }\n" "server:\n" @@ -249,14 +216,8 @@ TEST(config, tls_key) " }\n" "}\n" ; - struct wfd_config * config = wfd_config_load_string(config_text); - ASSERT_NE(nullptr, config); - - ASSERT_FALSE(wfd_config_is_server_tls_enabled(config)); - ASSERT_EQ(nullptr, wfd_config_get_server_cert(config)); - ASSERT_STREQ("/path/to/key.pem", wfd_config_get_server_key(config)); - - wfd_config_dispose(config); + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_TRUE(result); } TEST(config, document_root) @@ -265,6 +226,9 @@ TEST(config, document_root) EXPECT_CALL(logger, log(_, _, _)).Times(0); EXPECT_CALL(logger, onclose()).Times(1); + StrictMock builder; + EXPECT_CALL(builder, setServerDocumentRoot(StrEq("/var/www"))).Times(1); + char const config_text[] = "version = { major = 1, minor = 0 }\n" "server:\n" @@ -272,10 +236,6 @@ TEST(config, document_root) " document_root = \"/var/www\"\n" "}\n" ; - struct wfd_config * config = wfd_config_load_string(config_text); - ASSERT_NE(nullptr, config); - - ASSERT_STREQ("/var/www", wfd_config_get_server_document_root(config)); - - wfd_config_dispose(config); + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_TRUE(result); } From f3743a6e01b19240e01d34c330c6ff5e46448e70 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 15 Mar 2020 21:50:11 +0100 Subject: [PATCH 16/36] renamed test --- CMakeLists.txt | 2 +- test/{test_config.cc => test_config_factory.cc} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename test/{test_config.cc => test_config_factory.cc} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index b2bce3a..abc9913 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,7 +108,7 @@ pkg_check_modules(GMOCK gmock) add_executable(alltests test/mock_config_builder.cc test/mock_logger.cc - test/test_config.cc + test/test_config_factory.cc test/test_log.cc ) diff --git a/test/test_config.cc b/test/test_config_factory.cc similarity index 100% rename from test/test_config.cc rename to test/test_config_factory.cc From aaf8bcb6889a295c6b19ae7139f662a1d719efd2 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 15 Mar 2020 22:35:57 +0100 Subject: [PATCH 17/36] refactor: use builder to create config --- CMakeLists.txt | 3 + src/webfused/config/config.c | 167 ++++++++++------------------ src/webfused/config/config.h | 51 ++------- src/webfused/config/config_intern.h | 41 ------- test/test_config.cc | 20 ++++ 5 files changed, 93 insertions(+), 189 deletions(-) delete mode 100644 src/webfused/config/config_intern.h create mode 100644 test/test_config.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index abc9913..d91797d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,6 +109,7 @@ add_executable(alltests test/mock_config_builder.cc test/mock_logger.cc test/test_config_factory.cc + test/test_config.cc test/test_log.cc ) @@ -123,6 +124,8 @@ target_compile_options(alltests PRIVATE ${GMOCK_CFLAGS} ${GTEST_CFLAGS} "-pthrea target_link_libraries(alltests PRIVATE webfused-static ${LIBCONFIG_LIBRARIES} + ${WEBFUSE_LIBRARIES} + ${UUID_LIBRARIES} ${GMOCK_LIBRARIES} ${GTEST_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} diff --git a/src/webfused/config/config.c b/src/webfused/config/config.c index a994ffb..706e0ed 100644 --- a/src/webfused/config/config.c +++ b/src/webfused/config/config.c @@ -1,156 +1,107 @@ #include "webfused/config/config.h" -#include "webfused/config/config_intern.h" +#include "webfuse/adapter/server_config.h" #include -#include #define WFD_CONFIG_DEFAULT_PORT (8080) #define WFD_CONFIG_DEFAULT_VHOSTNAME ("localhost") struct wfd_config { - char * vhost_name; - char * server_cert; - char * server_key; - char * server_doc_root; - int port; + struct wf_server_config * server; }; -extern struct wfd_config * -wfd_config_create(void) -{ - struct wfd_config * config = malloc(sizeof(struct wfd_config)); - config->port = WFD_CONFIG_DEFAULT_PORT; - config->vhost_name = strdup(WFD_CONFIG_DEFAULT_VHOSTNAME); - config->server_key = NULL; - config->server_cert = NULL; - config->server_doc_root = NULL; - - return config; -} - -void wfd_config_dispose( - struct wfd_config * config) -{ - free(config->vhost_name); - free(config->server_cert); - free(config->server_key); - free(config->server_doc_root); - free(config); -} - -int -wfd_config_get_server_port( - struct wfd_config * config) +static void +wfd_config_set_server_vhostname( + void * data, + char const * vhost_name) { - return config->port; + struct wfd_config * config = data; + wf_server_config_set_vhostname(config->server, vhost_name); } -void +static void wfd_config_set_server_port( - struct wfd_config * config, + void * data, int port) { - config->port = port; + struct wfd_config * config = data; + wf_server_config_set_port(config->server, port); } -char const * -wfd_config_get_server_vhostname( - struct wfd_config * config) +static void +wfd_config_set_server_key( + void * data, + char const * key_path) { - return config->vhost_name; + struct wfd_config * config = data; + wf_server_config_set_keypath(config->server, key_path); } -void -wfd_config_set_server_vhostname( - struct wfd_config * config, - char const * vhost_name) +static void +wfd_config_set_server_cert( + void * data, + char const * cert_path) { - free(config->vhost_name); - config->vhost_name = strdup(vhost_name); + struct wfd_config * config = data; + wf_server_config_set_certpath(config->server, cert_path); } -bool -wfd_config_is_server_tls_enabled( - struct wfd_config * config) +static void +wfd_config_set_server_document_root( + void * data, + char const * document_root) { - return ((NULL != config->server_key) - && (NULL != config->server_cert)); + struct wfd_config * config = data; + wf_server_config_set_documentroot(config->server, document_root); } -char const * -wfd_config_get_server_cert( - struct wfd_config * config) +static const struct wfd_config_builder_vtable +wfd_config_vtable_config_builder = { - return config->server_cert; -} + .set_server_vhostname = &wfd_config_set_server_vhostname, + .set_server_port = &wfd_config_set_server_port, + .set_server_key = &wfd_config_set_server_key, + .set_server_cert = &wfd_config_set_server_cert, + .set_server_document_root = &wfd_config_set_server_document_root +}; -void -wfd_config_set_server_cert( - struct wfd_config * config, - char const * cert) +struct wfd_config * +wfd_config_create(void) { - free(config->server_cert); - config->server_cert = strdup(cert); -} + struct wfd_config * config = malloc(sizeof(struct wfd_config)); + config->server = wf_server_config_create(); + wf_server_config_set_vhostname(config->server, WFD_CONFIG_DEFAULT_VHOSTNAME); + wf_server_config_set_port(config->server, WFD_CONFIG_DEFAULT_PORT); -char const * -wfd_config_get_server_key( - struct wfd_config * config) -{ - return config->server_key; + return config; } void -wfd_config_set_server_key( - struct wfd_config * config, - char const * key) -{ - free(config->server_key); - config->server_key = strdup(key); -} - -char const * -wfd_config_get_server_document_root( +wfd_config_dispose( struct wfd_config * config) { - return config->server_doc_root; -} - -void -wfd_config_set_server_document_root( - struct wfd_config * config, - char const * document_root) -{ - free(config->server_doc_root); - config->server_doc_root = strdup(document_root); + wf_server_config_dispose(config->server); + free(config); } -char const * -wfd_config_get_auth_provider( +struct wfd_config_builder +wfd_config_get_builder( struct wfd_config * config) { - return NULL; -} + struct wfd_config_builder builder = + { + &wfd_config_vtable_config_builder, + config + }; -struct wfd_auth_settings * -wfd_config_get_auth_settings( - struct wfd_config * config) -{ - return NULL; + return builder; } -size_t -wfd_config_get_filesystem_count( +struct wf_server_config * +wfd_config_get_server_config( struct wfd_config * config) { - return 0; + return config->server; } -struct wfd_filesystem_info * -wfd_confi_get_filesystem( - struct wfd_config * config, - size_t fs_index) -{ - return NULL; -} diff --git a/src/webfused/config/config.h b/src/webfused/config/config.h index 813e2d4..b3fec87 100644 --- a/src/webfused/config/config.h +++ b/src/webfused/config/config.h @@ -1,6 +1,8 @@ #ifndef WFD_CONFIG_H #define WFD_CONFIG_H +#include "webfused/config/builder.h" + #ifndef __cplusplus #include #include @@ -14,54 +16,23 @@ extern "C" #endif struct wfd_config; -struct wfd_auth_settins; -struct wfd_filesystem_info; - -extern void wfd_config_dispose( - struct wfd_config * config); - -extern int -wfd_config_get_server_port( - struct wfd_config * config); - -extern char const * -wfd_config_get_server_vhostname( - struct wfd_config * config); - -extern char const * -wfd_config_get_server_cert( - struct wfd_config * config); - -extern bool -wfd_config_is_server_tls_enabled( - struct wfd_config * config); - -extern char const * -wfd_config_get_server_key( - struct wfd_config * config); +struct wf_server_config; -extern char const * -wfd_config_get_server_document_root( - struct wfd_config * config); +extern struct wfd_config * +wfd_config_create(void); -extern char const * -wfd_config_get_auth_provider( +extern void +wfd_config_dispose( struct wfd_config * config); -extern struct wfd_auth_settings * -wfd_config_get_auth_settings( +extern struct wfd_config_builder +wfd_config_get_builder( struct wfd_config * config); -extern size_t -wfd_config_get_filesystem_count( +extern struct wf_server_config * +wfd_config_get_server_config( struct wfd_config * config); -extern struct wfd_filesystem_info * -wfd_confi_get_filesystem( - struct wfd_config * config, - size_t fs_index); - - #ifdef __cplusplus } #endif diff --git a/src/webfused/config/config_intern.h b/src/webfused/config/config_intern.h deleted file mode 100644 index fee762a..0000000 --- a/src/webfused/config/config_intern.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WFD_CONFIG_INTERN_H -#define WFD_CONFIG_INTERN_H - -#ifdef _cplusplus -extern "C" -{ -#endif - -extern struct wfd_config * -wfd_config_create(void); - -extern void -wfd_config_set_server_vhostname( - struct wfd_config * config, - char const * vhost_name); - -extern void -wfd_config_set_server_port( - struct wfd_config * config, - int port); - -extern void -wfd_config_set_server_cert( - struct wfd_config * config, - char const * cert); - -extern void -wfd_config_set_server_key( - struct wfd_config * config, - char const * key); - -extern void -wfd_config_set_server_document_root( - struct wfd_config * config, - char const * document_root); - -#ifdef _cplusplus -} -#endif - -#endif diff --git a/test/test_config.cc b/test/test_config.cc new file mode 100644 index 0000000..b43b8a0 --- /dev/null +++ b/test/test_config.cc @@ -0,0 +1,20 @@ +#include +#include "webfused/config/config.h" + +TEST(config, server_config) +{ + wfd_config * config = wfd_config_create(); + ASSERT_NE(nullptr, config); + + wfd_config_builder builder = wfd_config_get_builder(config); + wfd_config_builder_set_server_vhostname(builder, "localhost"); + wfd_config_builder_set_server_port(builder, 8443); + wfd_config_builder_set_server_key(builder, "/path/to/key.pem"); + wfd_config_builder_set_server_cert(builder, "/path/to/cert.pem"); + wfd_config_builder_set_server_document_root(builder, "/var/www"); + + wf_server_config * server_config = wfd_config_get_server_config(config); + ASSERT_NE(nullptr, server_config); + + wfd_config_dispose(config); +} \ No newline at end of file From 4ae6665f665b291a243af414321ccc320f0f9599 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 15 Mar 2020 22:45:57 +0100 Subject: [PATCH 18/36] fix: set proper LD_LIBRARY_PATH to find libfuse3.so --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 872bb35..1c4cee4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -102,7 +102,8 @@ before_script: - cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE .. script: - make $CHECK_TARGET + - export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib" + - make $CHECK_TARGET after_success: - bash <(curl -s https://codecov.io/bash) \ No newline at end of file From c10771b28a80b832d165ff630800096f26bd5b22 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 15 Mar 2020 22:51:54 +0100 Subject: [PATCH 19/36] debug: locate libfuse3.so.3 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 1c4cee4..5b2b9c4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -102,6 +102,7 @@ before_script: - cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE .. script: + - find /usr -name libfuse3.so.3 - export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib" - make $CHECK_TARGET From fab2545df1682fa5a0670faff73b0a16b1b41bf0 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 15 Mar 2020 22:57:36 +0100 Subject: [PATCH 20/36] fix: fixed LD_LIBRARY_PATH --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5b2b9c4..cb75952 100644 --- a/.travis.yml +++ b/.travis.yml @@ -102,8 +102,7 @@ before_script: - cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE .. script: - - find /usr -name libfuse3.so.3 - - export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib" + - export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib:/usr/local/lib/x86_64-linux-gnu" - make $CHECK_TARGET after_success: From 2e81b8c23d1b106c9dc605b80dd4ec17c723a065 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Mon, 16 Mar 2020 21:50:31 +0100 Subject: [PATCH 21/36] parse authentication settings --- CMakeLists.txt | 9 +- src/webfused/auth/authenticator.c | 8 ++ src/webfused/auth/authenticator.h | 36 +++++++ src/webfused/auth/factory.c | 25 +++++ src/webfused/auth/factory.h | 25 +++++ src/webfused/auth/file_authenticator.c | 9 ++ src/webfused/auth/file_authenticator.h | 26 +++++ .../auth_settings.h => auth/settings.h} | 0 .../authentication/auth_settings_builder.h | 28 ------ src/webfused/config/auth_settings.c | 51 ++++++++++ src/webfused/config/auth_settings.h | 25 +++++ src/webfused/config/builder.c | 9 ++ src/webfused/config/builder.h | 17 ++++ src/webfused/config/factory.c | 47 ++++++++++ test/invalid.conf | 4 + test/mock_config_builder.cc | 31 ++++-- test/mock_config_builder.hpp | 2 + test/test_auth_factory.cc | 26 +++++ test/test_auth_settings.cc | 31 ++++++ test/test_config_factory.cc | 94 +++++++++++++++++++ 20 files changed, 464 insertions(+), 39 deletions(-) create mode 100644 src/webfused/auth/authenticator.c create mode 100644 src/webfused/auth/authenticator.h create mode 100644 src/webfused/auth/factory.c create mode 100644 src/webfused/auth/factory.h create mode 100644 src/webfused/auth/file_authenticator.c create mode 100644 src/webfused/auth/file_authenticator.h rename src/webfused/{authentication/auth_settings.h => auth/settings.h} (100%) delete mode 100644 src/webfused/authentication/auth_settings_builder.h create mode 100644 src/webfused/config/auth_settings.c create mode 100644 src/webfused/config/auth_settings.h create mode 100644 test/invalid.conf create mode 100644 test/test_auth_factory.cc create mode 100644 test/test_auth_settings.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index d91797d..b6af497 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,10 @@ add_library(webfused-static STATIC src/webfused/config/config.c src/webfused/config/factory.c src/webfused/config/builder.c + src/webfused/config/auth_settings.c + src/webfused/auth/authenticator.c + src/webfused/auth/factory.c + src/webfused/auth/file_authenticator.c src/webfused/log/logger.c ) @@ -110,6 +114,8 @@ add_executable(alltests test/mock_logger.cc test/test_config_factory.cc test/test_config.cc + test/test_auth_settings.cc + test/test_auth_factory.cc test/test_log.cc ) @@ -133,6 +139,7 @@ target_link_libraries(alltests PRIVATE # copy test data configure_file(etc/webfused.conf webfused.conf COPYONLY) +configure_file(test/invalid.conf invalid.conf COPYONLY) enable_testing() gtest_discover_tests(alltests TEST_PREFIX alltests:) @@ -151,7 +158,7 @@ add_custom_target(coverage COMMAND ./alltests COMMAND lcov --capture --directory . --output-file coverage/lcov.info COMMAND lcov --remove coverage/lcov.info '/usr/*' --output-file coverage/lcov.info -# COMMAND lcov --remove coverage/lcov.info '*/test/*' --output-file coverage/lcov.info + COMMAND lcov --remove coverage/lcov.info '*/test/*' --output-file coverage/lcov.info ) add_dependencies(coverage alltests) diff --git a/src/webfused/auth/authenticator.c b/src/webfused/auth/authenticator.c new file mode 100644 index 0000000..4e9342b --- /dev/null +++ b/src/webfused/auth/authenticator.c @@ -0,0 +1,8 @@ +#include "webfused/auth/authenticator.h" + +void +wfd_authenticator_dispose( + struct wfd_authenticator authenticator) +{ + authenticator.vtable->dispose(authenticator.data); +} diff --git a/src/webfused/auth/authenticator.h b/src/webfused/auth/authenticator.h new file mode 100644 index 0000000..2300b9e --- /dev/null +++ b/src/webfused/auth/authenticator.h @@ -0,0 +1,36 @@ +#ifndef WFD_AUTH_AUTHENTICATOR_H +#define WFD_AUTH_AUTHENTICATOR_H + +#include "webfuse/adapter/authenticate.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef void +wfd_authenticator_dispose_fn( + void * data); + +struct wfd_authenticator_vtable +{ + wfd_authenticator_dispose_fn * dispose; + wf_authenticate_fn * authenticate; +}; + +struct wfd_authenticator +{ + struct wfd_authenticator_vtable const * vtable; + void * data; +}; + +extern void +wfd_authenticator_dispose( + struct wfd_authenticator authenticator); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/webfused/auth/factory.c b/src/webfused/auth/factory.c new file mode 100644 index 0000000..b2744e0 --- /dev/null +++ b/src/webfused/auth/factory.c @@ -0,0 +1,25 @@ +#include "webfused/auth/factory.h" +#include "webfused/auth/settings.h" +#include "webfused/auth/file_authenticator.h" +#include "webfused/log/log.h" + +#include + +bool +wfd_authenticator_create( + struct wfd_auth_settings * settings, + struct wfd_authenticator * authenticator) +{ + bool result = false; + char const * provider_name = wfd_auth_settings_get_provider(settings); + if (0 == strcmp("file", provider_name)) + { + result = wfd_file_authenticator_create(settings, authenticator); + } + else + { + WFD_ERROR("failed to create authenticator: unknown type \"%s\"", provider_name); + } + + return result; +} diff --git a/src/webfused/auth/factory.h b/src/webfused/auth/factory.h new file mode 100644 index 0000000..5121b78 --- /dev/null +++ b/src/webfused/auth/factory.h @@ -0,0 +1,25 @@ +#ifndef WFD_AUTHENTICATION_FACTORY_H +#define WFD_AUTHENTICATION_FACTORY_H + +#ifndef __cplusplus +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wfd_authenticator; +struct wfd_auth_settings; + +extern bool +wfd_authenticator_create( + struct wfd_auth_settings * settings, + struct wfd_authenticator * authenticator); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/webfused/auth/file_authenticator.c b/src/webfused/auth/file_authenticator.c new file mode 100644 index 0000000..02ee81e --- /dev/null +++ b/src/webfused/auth/file_authenticator.c @@ -0,0 +1,9 @@ +#include "webfused/auth/file_authenticator.h" + +bool +wfd_file_authenticator_create( + struct wfd_auth_settings * settings, + struct wfd_authenticator * authenticator) +{ + return false; +} diff --git a/src/webfused/auth/file_authenticator.h b/src/webfused/auth/file_authenticator.h new file mode 100644 index 0000000..1ece0e3 --- /dev/null +++ b/src/webfused/auth/file_authenticator.h @@ -0,0 +1,26 @@ +#ifndef WFD_AUTH_FILE_AUTHENTICATOR_H +#define WFD_AUTH_FILE_AUTHENTICATOR_H + +#ifndef __cplusplus +#include +#endif + + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wfd_authenticator; +struct wfd_auth_settings; + +extern bool +wfd_file_authenticator_create( + struct wfd_auth_settings * settings, + struct wfd_authenticator * authenticator); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/webfused/authentication/auth_settings.h b/src/webfused/auth/settings.h similarity index 100% rename from src/webfused/authentication/auth_settings.h rename to src/webfused/auth/settings.h diff --git a/src/webfused/authentication/auth_settings_builder.h b/src/webfused/authentication/auth_settings_builder.h deleted file mode 100644 index 6de12c7..0000000 --- a/src/webfused/authentication/auth_settings_builder.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef WFD_AUTH_SETTINGS_BUILDER_H -#define WFD_AUTH_SETTINGS_BUILDER_H - -#ifdef __cplusplus -#endif - -extern struct wfd_auth_settings * -wfd_auth_settings_create(void); - -extern void -wfd_auth_settings_dispose( - struct wfd_auth_settings * settings); - -extern void -wfd_auth_settings_set_provider( - struct wfd_auth_settings * settings, - char const * provider); - -extern void -wfd_auth_settings_add( - struct wfd_auth_settings * settings, - char const * key, - char const * value); - -#ifdef __cplusplus -#endif - -#endif diff --git a/src/webfused/config/auth_settings.c b/src/webfused/config/auth_settings.c new file mode 100644 index 0000000..de319d3 --- /dev/null +++ b/src/webfused/config/auth_settings.c @@ -0,0 +1,51 @@ +#include "webfused/auth/settings.h" +#include "webfused/config/auth_settings.h" + +#include +#include +#include + +struct wfd_auth_settings +{ + char * provider_name; + struct config_setting_t * settings; +}; + +struct wfd_auth_settings * +wfd_auth_settings_create( + char const * provider_name, + struct config_setting_t * settings) +{ + struct wfd_auth_settings * auth_settings = malloc(sizeof(struct wfd_auth_settings)); + auth_settings->provider_name = strdup(provider_name); + auth_settings->settings = settings; + + return auth_settings; +} + +void +wfd_auth_settings_dispose( + struct wfd_auth_settings * settings) +{ + free(settings->provider_name); + free(settings); +} + +char const * +wfd_auth_settings_get_provider( + struct wfd_auth_settings * settings) +{ + return settings->provider_name; +} + +char const * +wfd_auth_settings_get( + struct wfd_auth_settings * settings, + char const * key) +{ + char const * result; + int rc = config_setting_lookup_string(settings->settings, key, &result); + + return (CONFIG_TRUE == rc) ? result : NULL; +} + diff --git a/src/webfused/config/auth_settings.h b/src/webfused/config/auth_settings.h new file mode 100644 index 0000000..dd2abfc --- /dev/null +++ b/src/webfused/config/auth_settings.h @@ -0,0 +1,25 @@ +#ifndef WFD_CONFIG_AUTH_SETTINGS_H +#define WFD_CONFIG_AUTH_SETTINGS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wfd_auth_settings; +struct config_setting_t; + +extern struct wfd_auth_settings * +wfd_auth_settings_create( + char const * provider_name, + struct config_setting_t * settings); + +extern void +wfd_auth_settings_dispose( + struct wfd_auth_settings * settings); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/webfused/config/builder.c b/src/webfused/config/builder.c index 7d1c6c1..e59c9d5 100644 --- a/src/webfused/config/builder.c +++ b/src/webfused/config/builder.c @@ -40,3 +40,12 @@ wfd_config_builder_set_server_document_root( builder.vtable->set_server_document_root(builder.data, document_root); } +bool +wfd_config_builder_add_auth_provider( + struct wfd_config_builder builder, + struct wfd_auth_settings * settings) +{ + return builder.vtable->add_auth_provider(builder.data, settings); +} + + diff --git a/src/webfused/config/builder.h b/src/webfused/config/builder.h index 0dbc753..0e75f2d 100644 --- a/src/webfused/config/builder.h +++ b/src/webfused/config/builder.h @@ -1,11 +1,17 @@ #ifndef WFD_CONFIG_BUILDER_H #define WFD_CONFIG_BUILDER_H +#ifndef __cplusplus +#include +#endif + #ifdef __cplusplus extern "C" { #endif +struct wfd_auth_settings; + typedef void wfd_config_builder_set_server_vhostname_fn( void * data, @@ -31,6 +37,11 @@ wfd_config_builder_set_server_document_root_fn( void * data, char const * document_root); +typedef bool +wfd_config_builder_add_auth_provider_fn( + void * data, + struct wfd_auth_settings * settings); + struct wfd_config_builder_vtable { wfd_config_builder_set_server_vhostname_fn * set_server_vhostname; @@ -38,6 +49,7 @@ struct wfd_config_builder_vtable wfd_config_builder_set_server_key_fn * set_server_key; wfd_config_builder_set_server_cert_fn * set_server_cert; wfd_config_builder_set_server_document_root_fn * set_server_document_root; + wfd_config_builder_add_auth_provider_fn * add_auth_provider; }; struct wfd_config_builder @@ -71,6 +83,11 @@ wfd_config_builder_set_server_document_root( struct wfd_config_builder builder, char const * document_root); +extern bool +wfd_config_builder_add_auth_provider( + struct wfd_config_builder builder, + struct wfd_auth_settings * settings); + #ifdef __cplusplus } diff --git a/src/webfused/config/factory.c b/src/webfused/config/factory.c index 36096a1..6be06bf 100644 --- a/src/webfused/config/factory.c +++ b/src/webfused/config/factory.c @@ -1,4 +1,5 @@ #include "webfused/config/factory.h" +#include "webfused/config/auth_settings.h" #include "webfused/log/log.h" #include @@ -97,6 +98,51 @@ wfd_config_read_server( return true; } +static bool +wfd_config_read_authentication( + config_t * config, + struct wfd_config_builder builder) +{ + bool result = true; + + bool hasAuthentication = (NULL != config_lookup(config, "authentication")); + if (hasAuthentication) + { + char const * provider_name = NULL; + { + int rc = config_lookup_string(config, "authentication.provider", &provider_name); + if (CONFIG_TRUE != rc) + { + WFD_ERROR("missing authentication provider"); + result = false; + } + } + + struct config_setting_t * settings = NULL; + if (result) + { + settings = config_lookup(config, "authentication.settings"); + if (NULL == settings) + { + WFD_ERROR("missing authentication settings"); + result = false; + } + } + + if (result) + { + struct wfd_auth_settings * auth_settings = wfd_auth_settings_create( + provider_name, settings); + + result = wfd_config_builder_add_auth_provider(builder, auth_settings); + wfd_auth_settings_dispose(auth_settings); + } + + } + + return result; +} + static bool wfd_config_load( struct wfd_config_builder builder, @@ -105,6 +151,7 @@ wfd_config_load( bool result = wfd_config_check_version(config) && wfd_config_read_server(config, builder) + && wfd_config_read_authentication(config, builder) ; return result; diff --git a/test/invalid.conf b/test/invalid.conf new file mode 100644 index 0000000..c7665f5 --- /dev/null +++ b/test/invalid.conf @@ -0,0 +1,4 @@ +# This config file is invalid, +# since "." is not allowed as separator + +version.major = 1 diff --git a/test/mock_config_builder.cc b/test/mock_config_builder.cc index 90334b7..0fb7f11 100644 --- a/test/mock_config_builder.cc +++ b/test/mock_config_builder.cc @@ -5,7 +5,7 @@ extern "C" using webfused_test::IConfigBuilder; static void -wfd_MockConifigBuilder_set_server_vhostname( +wfd_MockConfigBuilder_set_server_vhostname( void * data, char const * vhost_name) { @@ -14,7 +14,7 @@ wfd_MockConifigBuilder_set_server_vhostname( } static void -wfd_MockConifigBuilder_set_server_port( +wfd_MockConfigBuilder_set_server_port( void * data, int port) { @@ -23,7 +23,7 @@ wfd_MockConifigBuilder_set_server_port( } static void -wfd_MockConifigBuilder_set_server_key( +wfd_MockConfigBuilder_set_server_key( void * data, char const * key_path) { @@ -32,7 +32,7 @@ wfd_MockConifigBuilder_set_server_key( } static void -wfd_MockConifigBuilder_set_server_cert( +wfd_MockConfigBuilder_set_server_cert( void * data, char const * cert_path) { @@ -41,7 +41,7 @@ wfd_MockConifigBuilder_set_server_cert( } static void -wfd_MockConifigBuilder_set_server_document_root( +wfd_MockConfigBuilder_set_server_document_root( void * data, char const * document_root) { @@ -49,13 +49,24 @@ wfd_MockConifigBuilder_set_server_document_root( builder->setServerDocumentRoot(document_root); } +static bool +wfd_MockConfigBuilder_add_auth_provider( + void * data, + struct wfd_auth_settings * settings) +{ + auto * builder = reinterpret_cast(data); + builder->addAuthProvider(settings); +} + + static const wfd_config_builder_vtable wfd_MockConfigBuilder_vtable = { - &wfd_MockConifigBuilder_set_server_vhostname, - &wfd_MockConifigBuilder_set_server_port, - &wfd_MockConifigBuilder_set_server_key, - &wfd_MockConifigBuilder_set_server_cert, - &wfd_MockConifigBuilder_set_server_document_root + &wfd_MockConfigBuilder_set_server_vhostname, + &wfd_MockConfigBuilder_set_server_port, + &wfd_MockConfigBuilder_set_server_key, + &wfd_MockConfigBuilder_set_server_cert, + &wfd_MockConfigBuilder_set_server_document_root, + &wfd_MockConfigBuilder_add_auth_provider }; } diff --git a/test/mock_config_builder.hpp b/test/mock_config_builder.hpp index 4620bf0..7141c17 100644 --- a/test/mock_config_builder.hpp +++ b/test/mock_config_builder.hpp @@ -16,6 +16,7 @@ public: virtual void setServerKey(char const * key_path) = 0; virtual void setServerCert(char const * cert_path) = 0; virtual void setServerDocumentRoot(char const * document_root) = 0; + virtual bool addAuthProvider(wfd_auth_settings * settings) = 0; }; class MockConfigBuilder: public IConfigBuilder @@ -27,6 +28,7 @@ public: MOCK_METHOD1(setServerKey, void (char const * key_path)); MOCK_METHOD1(setServerCert, void (char const * cert_path)); MOCK_METHOD1(setServerDocumentRoot, void (char const * document_root)); + MOCK_METHOD1(addAuthProvider, bool (wfd_auth_settings * settings)); struct wfd_config_builder getBuilder(); }; diff --git a/test/test_auth_factory.cc b/test/test_auth_factory.cc new file mode 100644 index 0000000..e3611dc --- /dev/null +++ b/test/test_auth_factory.cc @@ -0,0 +1,26 @@ +#include +#include "webfused/auth/factory.h" +#include "webfused/auth/authenticator.h" +#include "webfused/config/auth_settings.h" +#include "webfused/log/log.h" +#include "mock_logger.hpp" + +using ::testing::_; +using ::webfused_test::MockLogger; + + +TEST(auth_factory, fail_unknown_provider) +{ + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + wfd_auth_settings * auth_settings = wfd_auth_settings_create( + "unknown", NULL); + + wfd_authenticator authenticator; + bool result = wfd_authenticator_create(auth_settings, &authenticator); + ASSERT_FALSE(result); + + wfd_auth_settings_dispose(auth_settings); +} \ No newline at end of file diff --git a/test/test_auth_settings.cc b/test/test_auth_settings.cc new file mode 100644 index 0000000..2f786a9 --- /dev/null +++ b/test/test_auth_settings.cc @@ -0,0 +1,31 @@ +#include +#include "webfused/auth/settings.h" +#include "webfused/config/auth_settings.h" +#include + +TEST(auth_settings, auth_settings) +{ + char const settings_text[] = + "settings:\n" + "{\n" + " string_value = \"some.string\"\n" + " int_value = 42\n" + "}\n" + ; + config_t config; + config_init(&config); + int rc = config_read_string(&config, settings_text); + ASSERT_TRUE(CONFIG_TRUE == rc); + + config_setting_t * settings = config_lookup(&config, "settings"); + ASSERT_NE(nullptr, settings); + + wfd_auth_settings * auth_settings = wfd_auth_settings_create("test_provider", settings); + ASSERT_STREQ("test_provider", wfd_auth_settings_get_provider(auth_settings)); + ASSERT_STREQ("some.string", wfd_auth_settings_get(auth_settings, "string_value")); + ASSERT_EQ(nullptr, wfd_auth_settings_get(auth_settings, "int_value")); + ASSERT_EQ(nullptr, wfd_auth_settings_get(auth_settings, "invalid_value")); + + wfd_auth_settings_dispose(auth_settings); + config_destroy(&config); +} \ No newline at end of file diff --git a/test/test_config_factory.cc b/test/test_config_factory.cc index c0179b1..425d161 100644 --- a/test/test_config_factory.cc +++ b/test/test_config_factory.cc @@ -8,6 +8,7 @@ using ::testing::_; +using ::testing::Return; using ::testing::StrictMock; using ::testing::StrEq; using ::webfused_test::MockLogger; @@ -18,6 +19,7 @@ TEST(config, is_loadable) StrictMock builder; EXPECT_CALL(builder, setServerVhostname(StrEq("localhost"))).Times(1); EXPECT_CALL(builder, setServerPort(8080)).Times(1); + EXPECT_CALL(builder, addAuthProvider(_)).Times(1).WillOnce(Return(true)); bool result = wfd_config_load_file(builder.getBuilder(), "webfused.conf"); ASSERT_TRUE(result); @@ -50,6 +52,18 @@ TEST(config, invalid_config) ASSERT_FALSE(result); } +TEST(config, invalid_config_file) +{ + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + + bool result = wfd_config_load_file(builder.getBuilder(), "invalid.conf"); + ASSERT_FALSE(result); +} + TEST(config, invalid_major_version_too_low) { MockLogger logger; @@ -239,3 +253,83 @@ TEST(config, document_root) bool result = wfd_config_load_string(builder.getBuilder(), config_text); ASSERT_TRUE(result); } + +TEST(config, authentication) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, addAuthProvider(_)).Times(1).WillOnce(Return(true)); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "authentication:\n" + "{\n" + " provider = \"test\"\n" + " settings: { }\n" + "}\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_TRUE(result); +} + +TEST(config, failed_create_authenticator) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, addAuthProvider(_)).Times(1).WillOnce(Return(false)); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "authentication:\n" + "{\n" + " provider = \"test\"\n" + " settings: { }\n" + "}\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_FALSE(result); +} + +TEST(config, failed_missing_auth_provider) +{ + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "authentication:\n" + "{\n" + " settings: { }\n" + "}\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_FALSE(result); +} + +TEST(config, failed_missing_auth_settings) +{ + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "authentication:\n" + "{\n" + " provider = \"test\"\n" + "}\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_FALSE(result); +} From 0a19daa0ff445f6e74660d7e385c079c41eeb628 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Tue, 17 Mar 2020 10:18:25 +0100 Subject: [PATCH 22/36] fix: include uncovered files in coverage report --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b6af497..e181834 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -154,9 +154,10 @@ add_dependencies(memcheck alltests) add_custom_target(coverage mkdir -p coverage - COMMAND lcov --initial --capture --directory . --output-file coverage/lcov.info + COMMAND lcov --initial --capture --directory . --output-file coverage/lcov_base.info COMMAND ./alltests COMMAND lcov --capture --directory . --output-file coverage/lcov.info + COMMAND lcov -a coverage/lcov_base.info -a coverage/lcov.info --output-file coverage/lcov.info COMMAND lcov --remove coverage/lcov.info '/usr/*' --output-file coverage/lcov.info COMMAND lcov --remove coverage/lcov.info '*/test/*' --output-file coverage/lcov.info ) From 5dadb6240d896c306b77090a2c61af14ef3a5cc9 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Tue, 17 Mar 2020 13:08:42 +0100 Subject: [PATCH 23/36] report branch coverage --- CMakeLists.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e181834..29da226 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -154,17 +154,17 @@ add_dependencies(memcheck alltests) add_custom_target(coverage mkdir -p coverage - COMMAND lcov --initial --capture --directory . --output-file coverage/lcov_base.info + COMMAND lcov --initial --capture --directory . --output-file coverage/lcov_base.info --rc lcov_branch_coverage=1 COMMAND ./alltests - COMMAND lcov --capture --directory . --output-file coverage/lcov.info - COMMAND lcov -a coverage/lcov_base.info -a coverage/lcov.info --output-file coverage/lcov.info - COMMAND lcov --remove coverage/lcov.info '/usr/*' --output-file coverage/lcov.info - COMMAND lcov --remove coverage/lcov.info '*/test/*' --output-file coverage/lcov.info + COMMAND lcov --capture --directory . --output-file coverage/lcov.info --rc lcov_branch_coverage=1 + COMMAND lcov -a coverage/lcov_base.info -a coverage/lcov.info --output-file coverage/lcov.info --rc lcov_branch_coverage=1 + COMMAND lcov --remove coverage/lcov.info '/usr/*' --output-file coverage/lcov.info --rc lcov_branch_coverage=1 + COMMAND lcov --remove coverage/lcov.info '*/test/*' --output-file coverage/lcov.info --rc lcov_branch_coverage=1 ) add_dependencies(coverage alltests) add_custom_target(coverage-report - COMMAND genhtml -branch-coverage --highlight --legend coverage/lcov.info --output-directory coverage/report + COMMAND genhtml --branch-coverage --highlight --legend coverage/lcov.info --output-directory coverage/report ) add_dependencies(coverage-report coverage) From 5e90853ecfe52009ef30ea35c39bf00d9e190342 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Tue, 17 Mar 2020 13:17:33 +0100 Subject: [PATCH 24/36] added implementation of file_authenticator --- CMakeLists.txt | 7 + src/webfused/auth/authenticator.c | 10 ++ src/webfused/auth/authenticator.h | 4 + src/webfused/auth/file_authenticator.c | 70 +++++++- test/mock_credentials.cc | 64 ++++++++ test/mock_credentials.hpp | 29 ++++ test/test_file_authenticator.cc | 211 +++++++++++++++++++++++++ test/test_passwd.json | 14 ++ 8 files changed, 408 insertions(+), 1 deletion(-) create mode 100644 test/mock_credentials.cc create mode 100644 test/mock_credentials.hpp create mode 100644 test/test_file_authenticator.cc create mode 100644 test/test_passwd.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 29da226..47392c4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,10 +112,12 @@ pkg_check_modules(GMOCK gmock) add_executable(alltests test/mock_config_builder.cc test/mock_logger.cc + test/mock_credentials.cc test/test_config_factory.cc test/test_config.cc test/test_auth_settings.cc test/test_auth_factory.cc + test/test_file_authenticator.cc test/test_log.cc ) @@ -128,10 +130,14 @@ target_include_directories(alltests PRIVATE target_compile_options(alltests PRIVATE ${GMOCK_CFLAGS} ${GTEST_CFLAGS} "-pthread") target_link_libraries(alltests PRIVATE + -Wl,--wrap=wf_credentials_type + -Wl,--wrap=wf_credentials_get webfused-static + userdb ${LIBCONFIG_LIBRARIES} ${WEBFUSE_LIBRARIES} ${UUID_LIBRARIES} + ${OPENSSL_LIBRARIES} ${GMOCK_LIBRARIES} ${GTEST_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} @@ -140,6 +146,7 @@ target_link_libraries(alltests PRIVATE # copy test data configure_file(etc/webfused.conf webfused.conf COPYONLY) configure_file(test/invalid.conf invalid.conf COPYONLY) +configure_file(test/test_passwd.json test_passwd.json COPYONLY) enable_testing() gtest_discover_tests(alltests TEST_PREFIX alltests:) diff --git a/src/webfused/auth/authenticator.c b/src/webfused/auth/authenticator.c index 4e9342b..ff7732a 100644 --- a/src/webfused/auth/authenticator.c +++ b/src/webfused/auth/authenticator.c @@ -6,3 +6,13 @@ wfd_authenticator_dispose( { authenticator.vtable->dispose(authenticator.data); } + +extern bool +wfd_authenticator_authenticate( + struct wfd_authenticator authenticator, + struct wf_credentials * credentials) +{ + return authenticator.vtable->authenticate( + credentials, authenticator.data); +} + diff --git a/src/webfused/auth/authenticator.h b/src/webfused/auth/authenticator.h index 2300b9e..1665a03 100644 --- a/src/webfused/auth/authenticator.h +++ b/src/webfused/auth/authenticator.h @@ -28,6 +28,10 @@ extern void wfd_authenticator_dispose( struct wfd_authenticator authenticator); +extern bool +wfd_authenticator_authenticate( + struct wfd_authenticator authenticator, + struct wf_credentials * credentials); #ifdef __cplusplus } diff --git a/src/webfused/auth/file_authenticator.c b/src/webfused/auth/file_authenticator.c index 02ee81e..1a0bf49 100644 --- a/src/webfused/auth/file_authenticator.c +++ b/src/webfused/auth/file_authenticator.c @@ -1,9 +1,77 @@ #include "webfused/auth/file_authenticator.h" +#include "webfused/auth/settings.h" +#include "webfused/auth/authenticator.h" + +#include "webfuse/adapter/credentials.h" +#include "userdb/userdb.h" + +#include +#include + +struct wfd_file_authenticator +{ + char * filename; +}; + +static void +wfd_file_authenticator_dispose( + void * data) +{ + struct wfd_file_authenticator * authenticator = data; + + free(authenticator->filename); + free(authenticator); +} + +static bool +wfd_file_authenticator_authenticate( + struct wf_credentials * credentials, + void * user_data) +{ + bool result = false; + struct wfd_file_authenticator * authenticator = user_data; + + char const * username = wf_credentials_get(credentials, "username"); + char const * password = wf_credentials_get(credentials, "password"); + if ((NULL != username) && (NULL != password)) + { + struct userdb * db = userdb_create(""); + result = userdb_load(db, authenticator->filename); + if (result) + { + result = userdb_check(db, username, password); + } + + userdb_dispose(db); + } + + return result; +} + +static struct wfd_authenticator_vtable +wfd_file_authenticator_vtable = +{ + .dispose = &wfd_file_authenticator_dispose, + .authenticate = &wfd_file_authenticator_authenticate +}; bool wfd_file_authenticator_create( struct wfd_auth_settings * settings, struct wfd_authenticator * authenticator) { - return false; + bool result = false; + + char const * filename = wfd_auth_settings_get(settings, "file"); + if (NULL != filename) + { + struct wfd_file_authenticator * data = malloc(sizeof(struct wfd_file_authenticator)); + data->filename = strdup(filename); + + authenticator->vtable = &wfd_file_authenticator_vtable; + authenticator->data = data; + result = true; + } + + return result; } diff --git a/test/mock_credentials.cc b/test/mock_credentials.cc new file mode 100644 index 0000000..a6023b1 --- /dev/null +++ b/test/mock_credentials.cc @@ -0,0 +1,64 @@ +#include "mock_credentials.hpp" + + +extern "C" +{ +using webfused_test::ICredentials; + +static ICredentials * wfd_mock_credentials = nullptr; + +extern char const * +__real_wf_credentials_type( + struct wf_credentials const * credentials); + +char const * +__wrap_wf_credentials_type( + struct wf_credentials const * credentials) +{ + if (nullptr == wfd_mock_credentials) + { + return __real_wf_credentials_type(credentials); + } + else + { + return wfd_mock_credentials->type(); + } +} + +extern char const * __real_wf_credentials_get( + struct wf_credentials const * credentials, + char const * key); + + +char const * __wrap_wf_credentials_get( + struct wf_credentials const * credentials, + char const * key) +{ + if (nullptr == wfd_mock_credentials) + { + return __real_wf_credentials_get(credentials, key); + } + else + { + return wfd_mock_credentials->get(key); + } +} + + +} + + +namespace webfused_test +{ + +MockCredentials::MockCredentials() +{ + wfd_mock_credentials = this; +} + +MockCredentials::~MockCredentials() +{ + wfd_mock_credentials = nullptr; +} + +} diff --git a/test/mock_credentials.hpp b/test/mock_credentials.hpp new file mode 100644 index 0000000..02b88c9 --- /dev/null +++ b/test/mock_credentials.hpp @@ -0,0 +1,29 @@ +#ifndef WFD_MOCK_CREDENTIALS_HPP +#define WFD_MOCK_CREDENTIALS_HPP + +#include "gmock/gmock.h" +#include "webfuse/adapter/credentials.h" + +namespace webfused_test +{ + +class ICredentials +{ +public: + virtual ~ICredentials() = default; + virtual char const * type() = 0; + virtual char const * get(char const * key) = 0; +}; + +class MockCredentials: public ICredentials +{ +public: + MockCredentials(); + virtual ~MockCredentials(); + MOCK_METHOD0(type, char const*()); + MOCK_METHOD1(get, char const *(char const * key)); +}; + +} + +#endif diff --git a/test/test_file_authenticator.cc b/test/test_file_authenticator.cc new file mode 100644 index 0000000..a864afe --- /dev/null +++ b/test/test_file_authenticator.cc @@ -0,0 +1,211 @@ +#include "webfused/auth/file_authenticator.h" +#include "webfused/auth/authenticator.h" +#include "webfused/config/auth_settings.h" +#include "webfused/auth/factory.h" + +#include "mock_credentials.hpp" + +#include +#include + +using ::webfused_test::MockCredentials; +using ::testing::Return; +using ::testing::StrEq; + +TEST(file_authenticator, create) +{ + char const config_text[] = + "file = \"/tmp/webfuse_passwd.json\"\n" + ; + config_t config; + config_init(&config); + config_read_string(&config, config_text); + config_setting_t * settings = config_root_setting(&config); + + wfd_auth_settings * auth_settings = wfd_auth_settings_create("file", settings); + + wfd_authenticator authenticator; + bool success = wfd_file_authenticator_create(auth_settings, &authenticator); + ASSERT_TRUE(success); + + wfd_auth_settings_dispose(auth_settings); + wfd_authenticator_dispose(authenticator); + config_destroy(&config); +} + +TEST(file_authenticator, create_fail_missing_file) +{ + config_t config; + config_init(&config); + config_setting_t * settings = config_root_setting(&config); + + wfd_auth_settings * auth_settings = wfd_auth_settings_create("file", settings); + + wfd_authenticator authenticator; + bool success = wfd_file_authenticator_create(auth_settings, &authenticator); + ASSERT_FALSE(success); + + wfd_auth_settings_dispose(auth_settings); + config_destroy(&config); +} + +TEST(file_authenticator, create_via_factory) +{ + char const config_text[] = + "file = \"/tmp/webfuse_passwd.json\"\n" + ; + config_t config; + config_init(&config); + config_read_string(&config, config_text); + config_setting_t * settings = config_root_setting(&config); + + wfd_auth_settings * auth_settings = wfd_auth_settings_create("file", settings); + + wfd_authenticator authenticator; + bool success = wfd_authenticator_create(auth_settings, &authenticator); + ASSERT_TRUE(success); + + wfd_auth_settings_dispose(auth_settings); + wfd_authenticator_dispose(authenticator); + config_destroy(&config); +} + +TEST(file_authenticator, authenticate) +{ + char const config_text[] = + "file = \"test_passwd.json\"\n" + ; + config_t config; + config_init(&config); + config_read_string(&config, config_text); + config_setting_t * settings = config_root_setting(&config); + + wfd_auth_settings * auth_settings = wfd_auth_settings_create("file", settings); + + wfd_authenticator authenticator; + bool success = wfd_authenticator_create(auth_settings, &authenticator); + ASSERT_TRUE(success); + + MockCredentials creds; + EXPECT_CALL(creds, get(StrEq("username"))).Times(1).WillOnce(Return("bob")); + EXPECT_CALL(creds, get(StrEq("password"))).Times(1).WillOnce(Return("secret")); + + bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr); + ASSERT_TRUE(is_authenticated); + + wfd_auth_settings_dispose(auth_settings); + wfd_authenticator_dispose(authenticator); + config_destroy(&config); +} + +TEST(file_authenticator, authenticate_fail_wrong_passwd) +{ + char const config_text[] = + "file = \"test_passwd.json\"\n" + ; + config_t config; + config_init(&config); + config_read_string(&config, config_text); + config_setting_t * settings = config_root_setting(&config); + + wfd_auth_settings * auth_settings = wfd_auth_settings_create("file", settings); + + wfd_authenticator authenticator; + bool success = wfd_authenticator_create(auth_settings, &authenticator); + ASSERT_TRUE(success); + + MockCredentials creds; + EXPECT_CALL(creds, get(StrEq("username"))).Times(1).WillOnce(Return("bob")); + EXPECT_CALL(creds, get(StrEq("password"))).Times(1).WillOnce(Return("unkown")); + + bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr); + ASSERT_FALSE(is_authenticated); + + wfd_auth_settings_dispose(auth_settings); + wfd_authenticator_dispose(authenticator); + config_destroy(&config); +} + +TEST(file_authenticator, authenticate_fail_no_passwd_file) +{ + char const config_text[] = + "file = \"non_existing_passwd.json\"\n" + ; + config_t config; + config_init(&config); + config_read_string(&config, config_text); + config_setting_t * settings = config_root_setting(&config); + + wfd_auth_settings * auth_settings = wfd_auth_settings_create("file", settings); + + wfd_authenticator authenticator; + bool success = wfd_authenticator_create(auth_settings, &authenticator); + ASSERT_TRUE(success); + + MockCredentials creds; + EXPECT_CALL(creds, get(StrEq("username"))).Times(1).WillOnce(Return("bob")); + EXPECT_CALL(creds, get(StrEq("password"))).Times(1).WillOnce(Return("secred")); + + bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr); + ASSERT_FALSE(is_authenticated); + + wfd_auth_settings_dispose(auth_settings); + wfd_authenticator_dispose(authenticator); + config_destroy(&config); +} + +TEST(file_authenticator, authenticate_fail_missing_username) +{ + char const config_text[] = + "file = \"test_passwd.json\"\n" + ; + config_t config; + config_init(&config); + config_read_string(&config, config_text); + config_setting_t * settings = config_root_setting(&config); + + wfd_auth_settings * auth_settings = wfd_auth_settings_create("file", settings); + + wfd_authenticator authenticator; + bool success = wfd_authenticator_create(auth_settings, &authenticator); + ASSERT_TRUE(success); + + MockCredentials creds; + EXPECT_CALL(creds, get(StrEq("username"))).Times(1).WillOnce(Return(nullptr)); + EXPECT_CALL(creds, get(StrEq("password"))).Times(1).WillOnce(Return("unkown")); + + bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr); + ASSERT_FALSE(is_authenticated); + + wfd_auth_settings_dispose(auth_settings); + wfd_authenticator_dispose(authenticator); + config_destroy(&config); +} + +TEST(file_authenticator, authenticate_fail_missing_password) +{ + char const config_text[] = + "file = \"test_passwd.json\"\n" + ; + config_t config; + config_init(&config); + config_read_string(&config, config_text); + config_setting_t * settings = config_root_setting(&config); + + wfd_auth_settings * auth_settings = wfd_auth_settings_create("file", settings); + + wfd_authenticator authenticator; + bool success = wfd_authenticator_create(auth_settings, &authenticator); + ASSERT_TRUE(success); + + MockCredentials creds; + EXPECT_CALL(creds, get(StrEq("username"))).Times(1).WillOnce(Return("bob")); + EXPECT_CALL(creds, get(StrEq("password"))).Times(1).WillOnce(Return(nullptr)); + + bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr); + ASSERT_FALSE(is_authenticated); + + wfd_auth_settings_dispose(auth_settings); + wfd_authenticator_dispose(authenticator); + config_destroy(&config); +} \ No newline at end of file diff --git a/test/test_passwd.json b/test/test_passwd.json new file mode 100644 index 0000000..595c06d --- /dev/null +++ b/test/test_passwd.json @@ -0,0 +1,14 @@ +{ + "meta": { + "type": "wf-userdb", + "major": 1, + "minor": 0, + "hash_algorithm": "sha512" + }, + "users": { + "bob": { + "password_hash": "e51e27ce47054feead3d83068d47f2a07307d4877ac67da668ef43e0e466fe8c7b66651af14fdb8d48c51592ef5afa0c63f874d20861c6b9ef8e6513bfcaa330", + "salt": "b3be6979921edecfea88c50d0d1ec40b7f8c383831b2276c65969ead18e47c03" + } + } +} \ No newline at end of file From b5cd41d0fa17f342f67f4f0164fdad9826c633f5 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Tue, 17 Mar 2020 13:30:13 +0100 Subject: [PATCH 25/36] added test for default log --- test/test_log.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/test_log.cc b/test/test_log.cc index 91ceb10..86423bb 100644 --- a/test/test_log.cc +++ b/test/test_log.cc @@ -104,3 +104,8 @@ TEST(log, omit_onclose_if_nullptr) WFD_WARN("too bad"); wfd_logger_close(); } + +TEST(log, default_log) +{ + WFD_ERROR("trigger log"); +} \ No newline at end of file From d90afed1b2673a7ab5eac24dbeca8dad02d25711 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Tue, 17 Mar 2020 14:47:22 +0100 Subject: [PATCH 26/36] fixed include --- test/mock_credentials.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/mock_credentials.hpp b/test/mock_credentials.hpp index 02b88c9..6f0ca1e 100644 --- a/test/mock_credentials.hpp +++ b/test/mock_credentials.hpp @@ -1,7 +1,7 @@ #ifndef WFD_MOCK_CREDENTIALS_HPP #define WFD_MOCK_CREDENTIALS_HPP -#include "gmock/gmock.h" +#include #include "webfuse/adapter/credentials.h" namespace webfused_test From 7e7cbd5d428e1e2f82536f45d5a83ec188a341e1 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Tue, 17 Mar 2020 16:49:17 +0100 Subject: [PATCH 27/36] add authenticator to server config --- CMakeLists.txt | 3 + src/webfused/auth/authenticator.c | 6 ++ src/webfused/auth/authenticator.h | 9 ++ src/webfused/auth/file_authenticator.c | 11 +- src/webfused/config/config.c | 42 +++++++- test/mock_auth_settings.cc | 63 +++++++++++ test/mock_auth_settings.hpp | 31 ++++++ test/test_config.cc | 58 ++++++++++ test/test_file_authenticator.cc | 141 +++++++++---------------- 9 files changed, 268 insertions(+), 96 deletions(-) create mode 100644 test/mock_auth_settings.cc create mode 100644 test/mock_auth_settings.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 47392c4..ce13d3d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -113,6 +113,7 @@ add_executable(alltests test/mock_config_builder.cc test/mock_logger.cc test/mock_credentials.cc + test/mock_auth_settings.cc test/test_config_factory.cc test/test_config.cc test/test_auth_settings.cc @@ -132,6 +133,8 @@ target_compile_options(alltests PRIVATE ${GMOCK_CFLAGS} ${GTEST_CFLAGS} "-pthrea target_link_libraries(alltests PRIVATE -Wl,--wrap=wf_credentials_type -Wl,--wrap=wf_credentials_get + -Wl,--wrap=wfd_auth_settings_get_provider + -Wl,--wrap=wfd_auth_settings_get webfused-static userdb ${LIBCONFIG_LIBRARIES} diff --git a/src/webfused/auth/authenticator.c b/src/webfused/auth/authenticator.c index ff7732a..dc04cf5 100644 --- a/src/webfused/auth/authenticator.c +++ b/src/webfused/auth/authenticator.c @@ -16,3 +16,9 @@ wfd_authenticator_authenticate( credentials, authenticator.data); } +char const * +wfd_authenticator_get_type( + struct wfd_authenticator authenticator) +{ + return authenticator.vtable->get_type(authenticator.data); +} diff --git a/src/webfused/auth/authenticator.h b/src/webfused/auth/authenticator.h index 1665a03..ef97305 100644 --- a/src/webfused/auth/authenticator.h +++ b/src/webfused/auth/authenticator.h @@ -12,10 +12,15 @@ typedef void wfd_authenticator_dispose_fn( void * data); +typedef char const * +wfd_authenticator_get_type_fn( + void * data); + struct wfd_authenticator_vtable { wfd_authenticator_dispose_fn * dispose; wf_authenticate_fn * authenticate; + wfd_authenticator_get_type_fn * get_type; }; struct wfd_authenticator @@ -33,6 +38,10 @@ wfd_authenticator_authenticate( struct wfd_authenticator authenticator, struct wf_credentials * credentials); +extern char const * +wfd_authenticator_get_type( + struct wfd_authenticator authenticator); + #ifdef __cplusplus } #endif diff --git a/src/webfused/auth/file_authenticator.c b/src/webfused/auth/file_authenticator.c index 1a0bf49..d7cd2db 100644 --- a/src/webfused/auth/file_authenticator.c +++ b/src/webfused/auth/file_authenticator.c @@ -48,11 +48,20 @@ wfd_file_authenticator_authenticate( return result; } +static char const * +wfd_file_authenticator_get_type( + void * data) +{ + (void) data; + return "username"; +} + static struct wfd_authenticator_vtable wfd_file_authenticator_vtable = { .dispose = &wfd_file_authenticator_dispose, - .authenticate = &wfd_file_authenticator_authenticate + .authenticate = &wfd_file_authenticator_authenticate, + .get_type = &wfd_file_authenticator_get_type }; bool diff --git a/src/webfused/config/config.c b/src/webfused/config/config.c index 706e0ed..868bb5b 100644 --- a/src/webfused/config/config.c +++ b/src/webfused/config/config.c @@ -1,5 +1,7 @@ #include "webfused/config/config.h" #include "webfuse/adapter/server_config.h" +#include "webfused/auth/factory.h" +#include "webfused/auth/authenticator.h" #include @@ -9,6 +11,8 @@ struct wfd_config { struct wf_server_config * server; + bool has_authenticator; + struct wfd_authenticator authenticator; }; static void @@ -56,6 +60,33 @@ wfd_config_set_server_document_root( wf_server_config_set_documentroot(config->server, document_root); } +static bool +wfd_config_add_auth_provider( + void * data, + struct wfd_auth_settings * settings) +{ + bool result = false; + struct wfd_config * config = data; + + if (!config->has_authenticator) + { + result = wfd_authenticator_create(settings, &config->authenticator); + if (result) + { + wf_server_config_add_authenticator( + config->server, + wfd_authenticator_get_type(config->authenticator), + config->authenticator.vtable->authenticate, + config->authenticator.data); + + config->has_authenticator = true; + } + } + + return result; +} + + static const struct wfd_config_builder_vtable wfd_config_vtable_config_builder = { @@ -63,17 +94,21 @@ wfd_config_vtable_config_builder = .set_server_port = &wfd_config_set_server_port, .set_server_key = &wfd_config_set_server_key, .set_server_cert = &wfd_config_set_server_cert, - .set_server_document_root = &wfd_config_set_server_document_root + .set_server_document_root = &wfd_config_set_server_document_root, + .add_auth_provider = &wfd_config_add_auth_provider }; struct wfd_config * wfd_config_create(void) { struct wfd_config * config = malloc(sizeof(struct wfd_config)); + config->server = wf_server_config_create(); wf_server_config_set_vhostname(config->server, WFD_CONFIG_DEFAULT_VHOSTNAME); wf_server_config_set_port(config->server, WFD_CONFIG_DEFAULT_PORT); + config->has_authenticator = false; + return config; } @@ -82,6 +117,11 @@ wfd_config_dispose( struct wfd_config * config) { wf_server_config_dispose(config->server); + if (config->has_authenticator) + { + wfd_authenticator_dispose(config->authenticator); + } + free(config); } diff --git a/test/mock_auth_settings.cc b/test/mock_auth_settings.cc new file mode 100644 index 0000000..a40391e --- /dev/null +++ b/test/mock_auth_settings.cc @@ -0,0 +1,63 @@ +#include "mock_auth_settings.hpp" + +extern "C" +{ +using webfused_test::IAuthSettings; + +static IAuthSettings * wfd_mock_auth_settings = nullptr; + +extern char const * +__real_wfd_auth_settings_get_provider( + struct wfd_auth_settings * settings); + +extern char const * +__real_wfd_auth_settings_get( + struct wfd_auth_settings * settings, + char const * key); + +char const * +__wrap_wfd_auth_settings_get_provider( + struct wfd_auth_settings * settings) +{ + if (nullptr == wfd_mock_auth_settings) + { + return __real_wfd_auth_settings_get_provider(settings); + } + else + { + return wfd_mock_auth_settings->getProvider(); + } +} + +char const * +__wrap_wfd_auth_settings_get( + struct wfd_auth_settings * settings, + char const * key) +{ + if (nullptr == wfd_mock_auth_settings) + { + return __real_wfd_auth_settings_get(settings, key); + } + else + { + return wfd_mock_auth_settings->get(key); + } +} + + +} + +namespace webfused_test +{ + +MockAuthSettings::MockAuthSettings() +{ + wfd_mock_auth_settings = this; +} + +MockAuthSettings::~MockAuthSettings() +{ + wfd_mock_auth_settings = nullptr; +} + +} \ No newline at end of file diff --git a/test/mock_auth_settings.hpp b/test/mock_auth_settings.hpp new file mode 100644 index 0000000..0ba4c38 --- /dev/null +++ b/test/mock_auth_settings.hpp @@ -0,0 +1,31 @@ +#ifndef WFD_MOCK_AUTH_SETTINGS_HPP +#define WFD_MOCK_AUTH_SETTINGS_HPP + +#include +#include "webfused/auth/settings.h" + +namespace webfused_test +{ + +class IAuthSettings +{ +public: + virtual ~IAuthSettings() = default; + virtual char const * getProvider() = 0; + virtual char const * get(char const * key) = 0; +}; + +class MockAuthSettings: public IAuthSettings +{ +public: + MockAuthSettings(); + ~MockAuthSettings() override; + MOCK_METHOD0(getProvider, char const * ()); + MOCK_METHOD1(get, char const * (char const * key)); +}; + +} + + + +#endif diff --git a/test/test_config.cc b/test/test_config.cc index b43b8a0..d07abd9 100644 --- a/test/test_config.cc +++ b/test/test_config.cc @@ -1,5 +1,10 @@ #include #include "webfused/config/config.h" +#include "mock_auth_settings.hpp" + +using ::webfused_test::MockAuthSettings; +using ::testing::Return; +using ::testing::StrEq; TEST(config, server_config) { @@ -16,5 +21,58 @@ TEST(config, server_config) wf_server_config * server_config = wfd_config_get_server_config(config); ASSERT_NE(nullptr, server_config); + wfd_config_dispose(config); +} + +TEST(config, auth_config) +{ + wfd_config * config = wfd_config_create(); + ASSERT_NE(nullptr, config); + + wfd_config_builder builder = wfd_config_get_builder(config); + + MockAuthSettings settings; + EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("file")); + EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); + + bool success = wfd_config_builder_add_auth_provider(builder, nullptr); + ASSERT_TRUE(success); + + wfd_config_dispose(config); +} + +TEST(config, auth_config_failed_to_add_second_provider) +{ + wfd_config * config = wfd_config_create(); + ASSERT_NE(nullptr, config); + + wfd_config_builder builder = wfd_config_get_builder(config); + + MockAuthSettings settings; + EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("file")); + EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); + + bool success = wfd_config_builder_add_auth_provider(builder, nullptr); + ASSERT_TRUE(success); + + success = wfd_config_builder_add_auth_provider(builder, nullptr); + ASSERT_FALSE(success); + + wfd_config_dispose(config); +} + +TEST(config, auth_config_failed_to_add_unknown_provider) +{ + wfd_config * config = wfd_config_create(); + ASSERT_NE(nullptr, config); + + wfd_config_builder builder = wfd_config_get_builder(config); + + MockAuthSettings settings; + EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("unknown")); + + bool success = wfd_config_builder_add_auth_provider(builder, nullptr); + ASSERT_FALSE(success); + wfd_config_dispose(config); } \ No newline at end of file diff --git a/test/test_file_authenticator.cc b/test/test_file_authenticator.cc index a864afe..b7037a2 100644 --- a/test/test_file_authenticator.cc +++ b/test/test_file_authenticator.cc @@ -4,86 +4,59 @@ #include "webfused/auth/factory.h" #include "mock_credentials.hpp" +#include "mock_auth_settings.hpp" #include #include +using ::webfused_test::MockAuthSettings; using ::webfused_test::MockCredentials; using ::testing::Return; using ::testing::StrEq; TEST(file_authenticator, create) { - char const config_text[] = - "file = \"/tmp/webfuse_passwd.json\"\n" - ; - config_t config; - config_init(&config); - config_read_string(&config, config_text); - config_setting_t * settings = config_root_setting(&config); - - wfd_auth_settings * auth_settings = wfd_auth_settings_create("file", settings); + MockAuthSettings settings; + EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; - bool success = wfd_file_authenticator_create(auth_settings, &authenticator); + bool success = wfd_file_authenticator_create(nullptr, &authenticator); ASSERT_TRUE(success); - wfd_auth_settings_dispose(auth_settings); wfd_authenticator_dispose(authenticator); - config_destroy(&config); } TEST(file_authenticator, create_fail_missing_file) { - config_t config; - config_init(&config); - config_setting_t * settings = config_root_setting(&config); - - wfd_auth_settings * auth_settings = wfd_auth_settings_create("file", settings); + MockAuthSettings settings; + EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return(nullptr)); wfd_authenticator authenticator; - bool success = wfd_file_authenticator_create(auth_settings, &authenticator); + bool success = wfd_file_authenticator_create(nullptr, &authenticator); ASSERT_FALSE(success); - - wfd_auth_settings_dispose(auth_settings); - config_destroy(&config); } TEST(file_authenticator, create_via_factory) { - char const config_text[] = - "file = \"/tmp/webfuse_passwd.json\"\n" - ; - config_t config; - config_init(&config); - config_read_string(&config, config_text); - config_setting_t * settings = config_root_setting(&config); - - wfd_auth_settings * auth_settings = wfd_auth_settings_create("file", settings); + MockAuthSettings settings; + EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("file")); + EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; - bool success = wfd_authenticator_create(auth_settings, &authenticator); + bool success = wfd_authenticator_create(nullptr, &authenticator); ASSERT_TRUE(success); - wfd_auth_settings_dispose(auth_settings); wfd_authenticator_dispose(authenticator); - config_destroy(&config); } TEST(file_authenticator, authenticate) { - char const config_text[] = - "file = \"test_passwd.json\"\n" - ; - config_t config; - config_init(&config); - config_read_string(&config, config_text); - config_setting_t * settings = config_root_setting(&config); - - wfd_auth_settings * auth_settings = wfd_auth_settings_create("file", settings); + MockAuthSettings settings; + EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("file")); + EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; - bool success = wfd_authenticator_create(auth_settings, &authenticator); + bool success = wfd_authenticator_create(nullptr, &authenticator); ASSERT_TRUE(success); MockCredentials creds; @@ -93,25 +66,17 @@ TEST(file_authenticator, authenticate) bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr); ASSERT_TRUE(is_authenticated); - wfd_auth_settings_dispose(auth_settings); wfd_authenticator_dispose(authenticator); - config_destroy(&config); } TEST(file_authenticator, authenticate_fail_wrong_passwd) { - char const config_text[] = - "file = \"test_passwd.json\"\n" - ; - config_t config; - config_init(&config); - config_read_string(&config, config_text); - config_setting_t * settings = config_root_setting(&config); - - wfd_auth_settings * auth_settings = wfd_auth_settings_create("file", settings); + MockAuthSettings settings; + EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("file")); + EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; - bool success = wfd_authenticator_create(auth_settings, &authenticator); + bool success = wfd_authenticator_create(nullptr, &authenticator); ASSERT_TRUE(success); MockCredentials creds; @@ -121,25 +86,17 @@ TEST(file_authenticator, authenticate_fail_wrong_passwd) bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr); ASSERT_FALSE(is_authenticated); - wfd_auth_settings_dispose(auth_settings); wfd_authenticator_dispose(authenticator); - config_destroy(&config); } TEST(file_authenticator, authenticate_fail_no_passwd_file) { - char const config_text[] = - "file = \"non_existing_passwd.json\"\n" - ; - config_t config; - config_init(&config); - config_read_string(&config, config_text); - config_setting_t * settings = config_root_setting(&config); - - wfd_auth_settings * auth_settings = wfd_auth_settings_create("file", settings); + MockAuthSettings settings; + EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("file")); + EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("unknown_passwd.json")); wfd_authenticator authenticator; - bool success = wfd_authenticator_create(auth_settings, &authenticator); + bool success = wfd_authenticator_create(nullptr, &authenticator); ASSERT_TRUE(success); MockCredentials creds; @@ -149,25 +106,17 @@ TEST(file_authenticator, authenticate_fail_no_passwd_file) bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr); ASSERT_FALSE(is_authenticated); - wfd_auth_settings_dispose(auth_settings); wfd_authenticator_dispose(authenticator); - config_destroy(&config); } TEST(file_authenticator, authenticate_fail_missing_username) { - char const config_text[] = - "file = \"test_passwd.json\"\n" - ; - config_t config; - config_init(&config); - config_read_string(&config, config_text); - config_setting_t * settings = config_root_setting(&config); - - wfd_auth_settings * auth_settings = wfd_auth_settings_create("file", settings); + MockAuthSettings settings; + EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("file")); + EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; - bool success = wfd_authenticator_create(auth_settings, &authenticator); + bool success = wfd_authenticator_create(nullptr, &authenticator); ASSERT_TRUE(success); MockCredentials creds; @@ -177,25 +126,17 @@ TEST(file_authenticator, authenticate_fail_missing_username) bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr); ASSERT_FALSE(is_authenticated); - wfd_auth_settings_dispose(auth_settings); wfd_authenticator_dispose(authenticator); - config_destroy(&config); } TEST(file_authenticator, authenticate_fail_missing_password) { - char const config_text[] = - "file = \"test_passwd.json\"\n" - ; - config_t config; - config_init(&config); - config_read_string(&config, config_text); - config_setting_t * settings = config_root_setting(&config); - - wfd_auth_settings * auth_settings = wfd_auth_settings_create("file", settings); + MockAuthSettings settings; + EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("file")); + EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; - bool success = wfd_authenticator_create(auth_settings, &authenticator); + bool success = wfd_authenticator_create(nullptr, &authenticator); ASSERT_TRUE(success); MockCredentials creds; @@ -205,7 +146,19 @@ TEST(file_authenticator, authenticate_fail_missing_password) bool is_authenticated = wfd_authenticator_authenticate(authenticator, nullptr); ASSERT_FALSE(is_authenticated); - wfd_auth_settings_dispose(auth_settings); wfd_authenticator_dispose(authenticator); - config_destroy(&config); -} \ No newline at end of file +} + +TEST(file_authenticator, get_type) +{ + MockAuthSettings settings; + EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); + + wfd_authenticator authenticator; + bool success = wfd_file_authenticator_create(nullptr, &authenticator); + ASSERT_TRUE(success); + + ASSERT_STREQ("username", wfd_authenticator_get_type(authenticator)); + + wfd_authenticator_dispose(authenticator); +} From 16c5db6b2c4d31999c53fc662e60a4fd5e7c15cf Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Tue, 17 Mar 2020 16:59:54 +0100 Subject: [PATCH 28/36] ignore tests --- codecov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codecov.yml b/codecov.yml index 2efff1f..e233cf0 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,2 +1,2 @@ ignore: - - test + - "test/**/*" From b62e9fc67b252a843871ea2e4ee1fb2e47bdb1c8 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Tue, 17 Mar 2020 21:51:04 +0100 Subject: [PATCH 29/36] parse filesystem info --- CMakeLists.txt | 2 + src/webfused/config/builder.c | 9 ++ src/webfused/config/builder.h | 12 +++ src/webfused/config/config.c | 23 ++++- src/webfused/config/factory.c | 50 +++++++++++ src/webfused/mountpoint_factory.c | 145 ++++++++++++++++++++++++++++++ src/webfused/mountpoint_factory.h | 39 ++++++++ test/mock_config_builder.cc | 15 +++- test/mock_config_builder.hpp | 2 + test/test_config.cc | 19 ++++ test/test_config_factory.cc | 100 +++++++++++++++++++++ test/test_mountpoint_factory.cc | 135 ++++++++++++++++++++++++++++ 12 files changed, 546 insertions(+), 5 deletions(-) create mode 100644 src/webfused/mountpoint_factory.c create mode 100644 src/webfused/mountpoint_factory.h create mode 100644 test/test_mountpoint_factory.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index ce13d3d..cb57ec6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,7 @@ target_compile_options(userdb PUBLIC ${OPENSSL_CFLAGS_OTHER}) add_library(webfused-static STATIC src/webfused/daemon.c + src/webfused/mountpoint_factory.c src/webfused/config/config.c src/webfused/config/factory.c src/webfused/config/builder.c @@ -119,6 +120,7 @@ add_executable(alltests test/test_auth_settings.cc test/test_auth_factory.cc test/test_file_authenticator.cc + test/test_mountpoint_factory.cc test/test_log.cc ) diff --git a/src/webfused/config/builder.c b/src/webfused/config/builder.c index e59c9d5..af13c09 100644 --- a/src/webfused/config/builder.c +++ b/src/webfused/config/builder.c @@ -48,4 +48,13 @@ wfd_config_builder_add_auth_provider( return builder.vtable->add_auth_provider(builder.data, settings); } +bool +wfd_config_builder_add_filesystem( + struct wfd_config_builder builder, + char const * name, + char const * mount_point) +{ + return builder.vtable->add_filesystem(builder.data, name, mount_point); +} + diff --git a/src/webfused/config/builder.h b/src/webfused/config/builder.h index 0e75f2d..8e23fd1 100644 --- a/src/webfused/config/builder.h +++ b/src/webfused/config/builder.h @@ -42,6 +42,12 @@ wfd_config_builder_add_auth_provider_fn( void * data, struct wfd_auth_settings * settings); +typedef bool +wfd_config_builder_add_filesystem_fn( + void * data, + char const * name, + char const * mount_point); + struct wfd_config_builder_vtable { wfd_config_builder_set_server_vhostname_fn * set_server_vhostname; @@ -50,6 +56,7 @@ struct wfd_config_builder_vtable wfd_config_builder_set_server_cert_fn * set_server_cert; wfd_config_builder_set_server_document_root_fn * set_server_document_root; wfd_config_builder_add_auth_provider_fn * add_auth_provider; + wfd_config_builder_add_filesystem_fn * add_filesystem; }; struct wfd_config_builder @@ -88,6 +95,11 @@ wfd_config_builder_add_auth_provider( struct wfd_config_builder builder, struct wfd_auth_settings * settings); +extern bool +wfd_config_builder_add_filesystem( + struct wfd_config_builder builder, + char const * name, + char const * mount_point); #ifdef __cplusplus } diff --git a/src/webfused/config/config.c b/src/webfused/config/config.c index 868bb5b..6499f12 100644 --- a/src/webfused/config/config.c +++ b/src/webfused/config/config.c @@ -2,6 +2,7 @@ #include "webfuse/adapter/server_config.h" #include "webfused/auth/factory.h" #include "webfused/auth/authenticator.h" +#include "webfused/mountpoint_factory.h" #include @@ -13,6 +14,7 @@ struct wfd_config struct wf_server_config * server; bool has_authenticator; struct wfd_authenticator authenticator; + struct wfd_mountpoint_factory * mountpoint_factory; }; static void @@ -86,6 +88,16 @@ wfd_config_add_auth_provider( return result; } +static bool +wfd_config_add_filesystem( + void * data, + char const * name, + char const * mount_point) +{ + struct wfd_config * config = data; + return wfd_mountpoint_factory_add_filesystem( + config->mountpoint_factory, name, mount_point); +} static const struct wfd_config_builder_vtable wfd_config_vtable_config_builder = @@ -95,7 +107,8 @@ wfd_config_vtable_config_builder = .set_server_key = &wfd_config_set_server_key, .set_server_cert = &wfd_config_set_server_cert, .set_server_document_root = &wfd_config_set_server_document_root, - .add_auth_provider = &wfd_config_add_auth_provider + .add_auth_provider = &wfd_config_add_auth_provider, + .add_filesystem = &wfd_config_add_filesystem }; struct wfd_config * @@ -103,11 +116,14 @@ wfd_config_create(void) { struct wfd_config * config = malloc(sizeof(struct wfd_config)); + config->mountpoint_factory = wfd_mountpoint_factory_create(); + config->has_authenticator = false; config->server = wf_server_config_create(); wf_server_config_set_vhostname(config->server, WFD_CONFIG_DEFAULT_VHOSTNAME); wf_server_config_set_port(config->server, WFD_CONFIG_DEFAULT_PORT); - - config->has_authenticator = false; + wf_server_config_set_mountpoint_factory(config->server, + wfd_mountpoint_factory_create_mountpoint, + config->mountpoint_factory); return config; } @@ -121,6 +137,7 @@ wfd_config_dispose( { wfd_authenticator_dispose(config->authenticator); } + wfd_mountpoint_factory_dispose(config->mountpoint_factory); free(config); } diff --git a/src/webfused/config/factory.c b/src/webfused/config/factory.c index 6be06bf..9343b38 100644 --- a/src/webfused/config/factory.c +++ b/src/webfused/config/factory.c @@ -143,6 +143,55 @@ wfd_config_read_authentication( return result; } +static bool +wfd_config_read_filesystems( + config_t * config, + struct wfd_config_builder builder) +{ + bool result = true; + config_setting_t * filesystems = config_lookup(config, "filesystems"); + if (NULL != filesystems) + { + int length = config_setting_length(filesystems); + for (int i = 0; i < length; i++) + { + config_setting_t * fs = config_setting_get_elem(filesystems, i); + if (NULL == fs) + { + WFD_ERROR("failed to load config: invalid filesystem section"); + result = false; + break; + } + + char const * name; + int rc = config_setting_lookup_string(fs, "name", &name); + if (rc != CONFIG_TRUE) + { + WFD_ERROR("failed to load config: missing required filesystem property \'name\'"); + result = false; + break; + } + + char const * mount_point; + rc = config_setting_lookup_string(fs, "mount_point", &mount_point); + if (rc != CONFIG_TRUE) + { + WFD_ERROR("failed to load config: missing required filesystem property \'mount_point\'"); + result = false; + break; + } + + result = wfd_config_builder_add_filesystem(builder, name, mount_point); + if (!result) + { + break; + } + } + } + + return result; +} + static bool wfd_config_load( struct wfd_config_builder builder, @@ -152,6 +201,7 @@ wfd_config_load( bool result = wfd_config_check_version(config) && wfd_config_read_server(config, builder) && wfd_config_read_authentication(config, builder) + && wfd_config_read_filesystems(config, builder) ; return result; diff --git a/src/webfused/mountpoint_factory.c b/src/webfused/mountpoint_factory.c new file mode 100644 index 0000000..a327937 --- /dev/null +++ b/src/webfused/mountpoint_factory.c @@ -0,0 +1,145 @@ +#include "webfused/mountpoint_factory.h" +#include "webfused/log/log.h" + +#include + +#include +#include +#include + +#define WFD_FILESYSTEM_DEFAULT_CAPACITY 16 + +struct wfd_filesystem +{ + char * name; + char * mount_point; + bool in_use; +}; + +struct wfd_mountpoint_factory +{ + struct wfd_filesystem * filesystems; + size_t capacity; + size_t count; +}; + +static struct wfd_filesystem * +wfd_mountpoint_factory_find( + struct wfd_mountpoint_factory * factory, + char const * name) +{ + for (size_t i = 0; i < factory->count; i++) + { + struct wfd_filesystem * filesystem = &(factory->filesystems[i]); + if (0 == strcmp(name, filesystem->name)) + { + return filesystem; + } + } + + return NULL; +} + +static void +wfd_mountpoint_factory_release_mountpoint( + void * user_data) +{ + bool * in_use = user_data; + *in_use = false; +} + +struct wfd_mountpoint_factory * +wfd_mountpoint_factory_create(void) +{ + struct wfd_mountpoint_factory * factory = malloc(sizeof(struct wfd_mountpoint_factory)); + factory->filesystems = malloc(sizeof(struct wfd_filesystem) * WFD_FILESYSTEM_DEFAULT_CAPACITY); + factory->count = 0; + factory->capacity = WFD_FILESYSTEM_DEFAULT_CAPACITY; + + return factory; +} + +void +wfd_mountpoint_factory_dispose( + struct wfd_mountpoint_factory * factory) +{ + for(size_t i = 0; i < factory->count; i++) + { + struct wfd_filesystem * filesystem = &(factory->filesystems[i]); + free(filesystem->name); + free(filesystem->mount_point); + } + + free(factory->filesystems); + free(factory); +} + +bool +wfd_mountpoint_factory_add_filesystem( + struct wfd_mountpoint_factory * factory, + char const * name, + char const * mount_point) +{ + bool result = (NULL == wfd_mountpoint_factory_find(factory, name)); + if (!result) + { + WFD_ERROR("mount_point already defined: \'%s\'", mount_point); + } + + char * path = NULL; + if (result) + { + mkdir(mount_point, 0755); + path = realpath(mount_point, NULL); + if (NULL == path) + { + WFD_ERROR("invalid mount_point: \'%s\'", mount_point); + result = false; + } + } + + if (result) + { + if (factory->count >= factory->capacity) + { + factory->capacity *= 2; + factory->filesystems = realloc(factory->filesystems, + sizeof(struct wfd_filesystem) * factory->capacity); + } + + struct wfd_filesystem * actual = &(factory->filesystems[factory->count]); + actual->name = strdup(name); + actual->mount_point = path; + actual->in_use = false; + factory->count++; + } + + return result; +} + +extern struct wf_mountpoint * +wfd_mountpoint_factory_create_mountpoint( + char const * filesystem, + void * user_data) +{ + struct wfd_mountpoint_factory * factory = user_data; + struct wfd_filesystem * fs = wfd_mountpoint_factory_find(factory, filesystem); + if (NULL == fs) + { + WFD_INFO("failed to create mountpoint: filesystem \'%s\' not found", filesystem); + return NULL; + } + + if (fs->in_use) + { + WFD_INFO("failed to create mountpoint: filesystem \'%s\' already in use", filesystem); + return NULL; + } + + fs->in_use = true; + struct wf_mountpoint * result = wf_mountpoint_create(fs->mount_point); + wf_mountpoint_set_userdata(result, + &fs->in_use, &wfd_mountpoint_factory_release_mountpoint); + + return result; +} diff --git a/src/webfused/mountpoint_factory.h b/src/webfused/mountpoint_factory.h new file mode 100644 index 0000000..3459ad4 --- /dev/null +++ b/src/webfused/mountpoint_factory.h @@ -0,0 +1,39 @@ +#ifndef WFD_MOUNTPOINT_FACTORY_H +#define WFD_MOUNTPOINT_FACTORY_H + +#include "webfuse/adapter/mountpoint_factory.h" + +#ifndef __cplusplus +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wfd_mountpoint_factory; + +extern struct wfd_mountpoint_factory * +wfd_mountpoint_factory_create(void); + +extern void +wfd_mountpoint_factory_dispose( + struct wfd_mountpoint_factory * factory); + +extern bool +wfd_mountpoint_factory_add_filesystem( + struct wfd_mountpoint_factory * factory, + char const * name, + char const * mount_point); + +extern struct wf_mountpoint * +wfd_mountpoint_factory_create_mountpoint( + char const * filesystem, + void * user_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/mock_config_builder.cc b/test/mock_config_builder.cc index 0fb7f11..f872edf 100644 --- a/test/mock_config_builder.cc +++ b/test/mock_config_builder.cc @@ -55,7 +55,17 @@ wfd_MockConfigBuilder_add_auth_provider( struct wfd_auth_settings * settings) { auto * builder = reinterpret_cast(data); - builder->addAuthProvider(settings); + return builder->addAuthProvider(settings); +} + +static bool +wfd_MockConfigBuilder_add_filesystem( + void * data, + char const * name, + char const * mountpoint) +{ + auto * builder = reinterpret_cast(data); + return builder->addFilesystem(name, mountpoint); } @@ -66,7 +76,8 @@ static const wfd_config_builder_vtable wfd_MockConfigBuilder_vtable = &wfd_MockConfigBuilder_set_server_key, &wfd_MockConfigBuilder_set_server_cert, &wfd_MockConfigBuilder_set_server_document_root, - &wfd_MockConfigBuilder_add_auth_provider + &wfd_MockConfigBuilder_add_auth_provider, + &wfd_MockConfigBuilder_add_filesystem }; } diff --git a/test/mock_config_builder.hpp b/test/mock_config_builder.hpp index 7141c17..d37c47a 100644 --- a/test/mock_config_builder.hpp +++ b/test/mock_config_builder.hpp @@ -17,6 +17,7 @@ public: virtual void setServerCert(char const * cert_path) = 0; virtual void setServerDocumentRoot(char const * document_root) = 0; virtual bool addAuthProvider(wfd_auth_settings * settings) = 0; + virtual bool addFilesystem(char const * name, char const * mountpoint) = 0; }; class MockConfigBuilder: public IConfigBuilder @@ -29,6 +30,7 @@ public: MOCK_METHOD1(setServerCert, void (char const * cert_path)); MOCK_METHOD1(setServerDocumentRoot, void (char const * document_root)); MOCK_METHOD1(addAuthProvider, bool (wfd_auth_settings * settings)); + MOCK_METHOD2(addFilesystem, bool (char const * name, char const * mountpoint)); struct wfd_config_builder getBuilder(); }; diff --git a/test/test_config.cc b/test/test_config.cc index d07abd9..a86a777 100644 --- a/test/test_config.cc +++ b/test/test_config.cc @@ -2,6 +2,12 @@ #include "webfused/config/config.h" #include "mock_auth_settings.hpp" +#include "webfused/log/logger.h" +#include "webfused/log/log.h" +#include "mock_logger.hpp" +using ::webfused_test::MockLogger; +using ::testing::_; + using ::webfused_test::MockAuthSettings; using ::testing::Return; using ::testing::StrEq; @@ -74,5 +80,18 @@ TEST(config, auth_config_failed_to_add_unknown_provider) bool success = wfd_config_builder_add_auth_provider(builder, nullptr); ASSERT_FALSE(success); + wfd_config_dispose(config); +} + +TEST(config, add_filesystem) +{ + wfd_config * config = wfd_config_create(); + ASSERT_NE(nullptr, config); + + wfd_config_builder builder = wfd_config_get_builder(config); + + bool success = wfd_config_builder_add_filesystem(builder, "test", "/tmp/test"); + ASSERT_TRUE(success); + wfd_config_dispose(config); } \ No newline at end of file diff --git a/test/test_config_factory.cc b/test/test_config_factory.cc index 425d161..ba83165 100644 --- a/test/test_config_factory.cc +++ b/test/test_config_factory.cc @@ -20,6 +20,7 @@ TEST(config, is_loadable) EXPECT_CALL(builder, setServerVhostname(StrEq("localhost"))).Times(1); EXPECT_CALL(builder, setServerPort(8080)).Times(1); EXPECT_CALL(builder, addAuthProvider(_)).Times(1).WillOnce(Return(true)); + EXPECT_CALL(builder, addFilesystem(_,_)).Times(1).WillOnce(Return(true)); bool result = wfd_config_load_file(builder.getBuilder(), "webfused.conf"); ASSERT_TRUE(result); @@ -333,3 +334,102 @@ TEST(config, failed_missing_auth_settings) bool result = wfd_config_load_string(builder.getBuilder(), config_text); ASSERT_FALSE(result); } + +TEST(config, filesystems) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, addFilesystem(_, _)).Times(1).WillOnce(Return(true)); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "filesystems:\n" + "(\n" + " {name = \"foo\", mount_point = \"/tmp/test\" }\n" + ")\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_TRUE(result); +} + +TEST(config, filesystems_empty) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, addFilesystem(_, _)).Times(0); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "filesystems:\n" + "(\n" + ")\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_TRUE(result); +} + +TEST(config, filesystems_failed_add) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, addFilesystem(_, _)).Times(1).WillOnce(Return(false)); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "filesystems:\n" + "(\n" + " {name = \"foo\", mount_point = \"/tmp/test\" }\n" + ")\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_FALSE(result); +} + +TEST(config, filesystems_failed_missing_name) +{ + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, addFilesystem(_, _)).Times(0); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "filesystems:\n" + "(\n" + " {mount_point = \"/tmp/test\" }\n" + ")\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_FALSE(result); +} + +TEST(config, filesystems_failed_missing_mountpoint) +{ + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, addFilesystem(_, _)).Times(0); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "filesystems:\n" + "(\n" + " {name = \"foo\"}\n" + ")\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_FALSE(result); +} diff --git a/test/test_mountpoint_factory.cc b/test/test_mountpoint_factory.cc new file mode 100644 index 0000000..0509d0f --- /dev/null +++ b/test/test_mountpoint_factory.cc @@ -0,0 +1,135 @@ +#include +#include "webfused/mountpoint_factory.h" +#include + +#include + +TEST(mountpoint_factory, create) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + wfd_mountpoint_factory_dispose(factory); +} + +TEST(mountpiont_factory, add_filesystem) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + bool success = wfd_mountpoint_factory_add_filesystem(factory, "test", "/tmp/webfused_test"); + ASSERT_TRUE(success); + + wfd_mountpoint_factory_dispose(factory); +} + +TEST(mountpiont_factory, add_filesystem_fail_to_add_twice) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + bool success = wfd_mountpoint_factory_add_filesystem(factory, "test", "/tmp/webfused_test"); + ASSERT_TRUE(success); + + success = wfd_mountpoint_factory_add_filesystem(factory, "test", "/tmp/webfused_test"); + ASSERT_FALSE(success); + + wfd_mountpoint_factory_dispose(factory); +} + +TEST(mountpiont_factory, add_filesystem_multi) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + + for (size_t i = 0; i < 24; i++) + { + char name[10]; + snprintf(name, 10, "test_%zu", i); + bool success = wfd_mountpoint_factory_add_filesystem(factory, name, "/tmp/webfused_test"); + ASSERT_TRUE(success) << i; + } + + wfd_mountpoint_factory_dispose(factory); +} + +TEST(mountpiont_factory, add_filesystem_fail_invalid_path) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + bool success = wfd_mountpoint_factory_add_filesystem(factory, "test", "/do/not/allow/nested/paths"); + ASSERT_FALSE(success); + + wfd_mountpoint_factory_dispose(factory); +} + +TEST(mountpiont_factory, create_mountpoint) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + bool success = wfd_mountpoint_factory_add_filesystem(factory, "test", "/tmp/webfuse_test"); + ASSERT_TRUE(success); + + wf_mountpoint * mountpoint = wfd_mountpoint_factory_create_mountpoint("test", factory); + ASSERT_NE(nullptr, mountpoint); + ASSERT_STREQ("/tmp/webfuse_test", wf_mountpoint_get_path(mountpoint)); + + wf_mountpoint_dispose(mountpoint); + wfd_mountpoint_factory_dispose(factory); +} + +TEST(mountpiont_factory, create_mountpoint_fail_already_in_use) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + bool success = wfd_mountpoint_factory_add_filesystem(factory, "test", "/tmp/webfuse_test"); + ASSERT_TRUE(success); + + wf_mountpoint * mountpoint = wfd_mountpoint_factory_create_mountpoint("test", factory); + ASSERT_NE(nullptr, mountpoint); + ASSERT_STREQ("/tmp/webfuse_test", wf_mountpoint_get_path(mountpoint)); + + wf_mountpoint * mountpoint2 = wfd_mountpoint_factory_create_mountpoint("test", factory); + ASSERT_EQ(nullptr, mountpoint2); + + wf_mountpoint_dispose(mountpoint); + wfd_mountpoint_factory_dispose(factory); +} + +TEST(mountpiont_factory, create_mountpoint_fail_unknown_filesystem) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + bool success = wfd_mountpoint_factory_add_filesystem(factory, "test", "/tmp/webfuse_test"); + ASSERT_TRUE(success); + + wf_mountpoint * mountpoint = wfd_mountpoint_factory_create_mountpoint("unkown", factory); + ASSERT_EQ(nullptr, mountpoint); + + wfd_mountpoint_factory_dispose(factory); +} + +TEST(mountpiont_factory, create_mountpoint_multi) +{ + wfd_mountpoint_factory * factory = wfd_mountpoint_factory_create(); + ASSERT_NE(nullptr, factory); + + bool success = wfd_mountpoint_factory_add_filesystem(factory, "test", "/tmp/webfuse_test"); + ASSERT_TRUE(success); + + for(int i = 0; i < 5; i++) + { + wf_mountpoint * mountpoint = wfd_mountpoint_factory_create_mountpoint("test", factory); + ASSERT_NE(nullptr, mountpoint) << i; + ASSERT_STREQ("/tmp/webfuse_test", wf_mountpoint_get_path(mountpoint)) << i; + + wf_mountpoint_dispose(mountpoint); + } + + wfd_mountpoint_factory_dispose(factory); +} From 5a58025e4ac61b6122e548f0798cd74e53673be1 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Tue, 17 Mar 2020 22:53:38 +0100 Subject: [PATCH 30/36] switches daemon to config file --- CMakeLists.txt | 1 + src/webfused/auth/file_authenticator.c | 5 + src/webfused/daemon.c | 141 ++++++++----------------- src/webfused/log/stderr_logger.c | 40 +++++++ src/webfused/log/stderr_logger.h | 31 ++++++ src/webfused/mountpoint_factory.c | 5 + 6 files changed, 127 insertions(+), 96 deletions(-) create mode 100644 src/webfused/log/stderr_logger.c create mode 100644 src/webfused/log/stderr_logger.h diff --git a/CMakeLists.txt b/CMakeLists.txt index cb57ec6..6c16983 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,6 +59,7 @@ add_library(webfused-static STATIC src/webfused/auth/factory.c src/webfused/auth/file_authenticator.c src/webfused/log/logger.c + src/webfused/log/stderr_logger.c ) add_executable(webfused diff --git a/src/webfused/auth/file_authenticator.c b/src/webfused/auth/file_authenticator.c index d7cd2db..258badd 100644 --- a/src/webfused/auth/file_authenticator.c +++ b/src/webfused/auth/file_authenticator.c @@ -4,6 +4,7 @@ #include "webfuse/adapter/credentials.h" #include "userdb/userdb.h" +#include "webfused/log/log.h" #include #include @@ -45,6 +46,10 @@ wfd_file_authenticator_authenticate( userdb_dispose(db); } + WFD_INFO("authenticate user \'%s\': %s", + (NULL != username) ? username : "", + result ? "success" : "failure"); + return result; } diff --git a/src/webfused/daemon.c b/src/webfused/daemon.c index c338b29..c0b6de5 100644 --- a/src/webfused/daemon.c +++ b/src/webfused/daemon.c @@ -11,14 +11,17 @@ #include #include -#include +#include "webfused/config/config.h" +#include "webfused/config/factory.h" +#include "webfused/log/stderr_logger.h" +#include "webfused/log/log.h" -#define SERVICE_TIMEOUT (1 * 1000) +#define WFD_SERVICE_TIMEOUT (1 * 1000) +#define WFD_DEFAULT_CONFIG_FILE ("/etc/webfuse.conf") struct args { - struct wf_server_config * config; - char * passwd_path; + char * config_file; bool show_help; }; @@ -27,67 +30,35 @@ static bool shutdown_requested = false; static void show_help(void) { printf( - "webfused, Copyright (c) 2019, webfused authors \n" + "webfused, Copyright (c) 2019-2020, webfused authors \n" "Websocket file system daemon\n" "\n" - "Usage: webfused [m ] [-d ] [-p ]\n" - " [-c ] [-k ] [-P ]\n" + "Usage: webfused [-f ] | -h\n" "\n" "Options:\n" - "\t-m, --mount_point Path of mount point (required)\n" - "\t-d, --document_root Path of www directory (default: not set, www disabled)\n" - "\t-c, --server_cert_path Path of servers own certificate (default: not set, TLS disabled)\n" - "\t-k, --server_key_path Path of servers private key (default: not set, TLS disabled)\n" - "\t-n, --vhost_name Name of virtual host (default: \"localhost\")\n" - "\t-p, --port Number of servers port (default: 8080)\n" - "\t-P, --passwd_path Path to password file (default: not set, authentication disabled)\n" + "\t-f, --config-file Path to config file (default: /etc/webfuse.conf)\n" + "\t-h, --help Print this message and terminate\n" "\n"); } -static bool authenticate(struct wf_credentials * creds, void * user_data) -{ - bool result = false; - struct args * args = user_data; - - char const * username = wf_credentials_get(creds, "username"); - char const * password = wf_credentials_get(creds, "password"); - if ((NULL != username) && (NULL != password)) - { - struct userdb * db = userdb_create(""); - result = userdb_load(db, args->passwd_path); - if (result) - { - result = userdb_check(db, username, password); - } - - userdb_dispose(db); - } - - return result; -} - static int parse_arguments(int argc, char * argv[], struct args * args) { static struct option const options[] = { - {"mount_point", required_argument, NULL, 'm'}, - {"document_root", required_argument, NULL, 'd'}, - {"server_cert_path", required_argument, NULL, 'c'}, - {"server_key_path", required_argument, NULL, 'k'}, - {"vhost_name", required_argument, NULL, 'n'}, - {"port", required_argument, NULL, 'p'}, - {"passwd_path", required_argument, NULL, 'P'}, + {"config-file", required_argument, NULL, 'f'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0} }; + args->config_file = strdup(WFD_DEFAULT_CONFIG_FILE); + args->show_help = false; + bool result = EXIT_SUCCESS; bool finished = false; - bool has_mountpoint = false; while ((!finished) && (EXIT_SUCCESS == result)) { int option_index = 0; - int const c = getopt_long(argc, argv, "m:d:c:k:n:p:P:h", options, &option_index); + int const c = getopt_long(argc, argv, "f:h", options, &option_index); switch (c) { @@ -98,32 +69,9 @@ static int parse_arguments(int argc, char * argv[], struct args * args) args->show_help = true; finished = true; break; - case 'm': - wf_server_config_set_mountpoint(args->config, optarg); - has_mountpoint = true; - break; - case 'd': - wf_server_config_set_documentroot(args->config, optarg); - break; - case 'c': - wf_server_config_set_certpath(args->config, optarg); - break; - case 'k': - wf_server_config_set_keypath(args->config, optarg); - break; - case 'n': - wf_server_config_set_vhostname(args->config, optarg); - break; - case 'p': - wf_server_config_set_port(args->config, atoi(optarg)); - break; - case 'P': - free(args->passwd_path); - args->passwd_path = strdup(optarg); - wf_server_config_add_authenticator(args->config, - "username", - &authenticate, - args); + case 'f': + free(args->config_file); + args->config_file = strdup(optarg); break; default: fprintf(stderr, "error: unknown argument\n"); @@ -132,15 +80,6 @@ static int parse_arguments(int argc, char * argv[], struct args * args) } } - if ((EXIT_SUCCESS == result) && (!args->show_help)) - { - if (!has_mountpoint) - { - fprintf(stderr, "error: missing mount point\n"); - result = EXIT_FAILURE; - } - } - if (EXIT_SUCCESS != result) { args->show_help = true; @@ -158,41 +97,51 @@ static void on_interrupt(int signal_id) int wfd_daemon_run(int argc, char * argv[]) { - struct args args; - args.config = wf_server_config_create(); - wf_server_config_set_vhostname(args.config, "localhost"); - wf_server_config_set_port(args.config, 8080); - args.passwd_path = NULL; - args.show_help = false; + wfd_stderr_logger_init(WFD_LOGLEVEL_ALL); + struct args args; int result = parse_arguments(argc, argv, &args); if (!args.show_help) { signal(SIGINT, on_interrupt); - struct wf_server * server = wf_server_create(args.config); - if (NULL != server) + + struct wfd_config * config = wfd_config_create(); + struct wfd_config_builder builder = wfd_config_get_builder(config); + bool success = wfd_config_load_file(builder, args.config_file); + if (success) { - while (!shutdown_requested) + struct wf_server_config * server_config = wfd_config_get_server_config(config); + struct wf_server * server = wf_server_create(server_config); + if (NULL != server) { - wf_server_service(server, SERVICE_TIMEOUT); - } + while (!shutdown_requested) + { + wf_server_service(server, WFD_SERVICE_TIMEOUT); + } - wf_server_dispose(server); + wf_server_dispose(server); + } + else + { + fprintf(stderr, "fatal: unable start server\n"); + result = EXIT_FAILURE; + } } else { - fprintf(stderr, "fatal: unable start server\n"); + fprintf(stderr, "fatal: failed to load server config\n"); result = EXIT_FAILURE; - } + } + + wfd_config_dispose(config); } else { show_help(); } - free(args.passwd_path); - wf_server_config_dispose(args.config); + free(args.config_file); return result; } diff --git a/src/webfused/log/stderr_logger.c b/src/webfused/log/stderr_logger.c new file mode 100644 index 0000000..224f7f9 --- /dev/null +++ b/src/webfused/log/stderr_logger.c @@ -0,0 +1,40 @@ +#include "webfused/log/stderr_logger.h" +#include "webfused/log/logger.h" +#include "webfused/log/log.h" + +#include +#include + +static const char * +wfd_stderr_logger_level_str(int level) +{ + switch (level) + { + case WFD_LOGLEVEL_FATAL: return "fatal"; + case WFD_LOGLEVEL_ERROR: return "error"; + case WFD_LOGLEVEL_WARN: return "warn"; + case WFD_LOGLEVEL_INFO: return "info"; + case WFD_LOGLEVEL_DEBUG: return "debug"; + default: return "notice"; + } +} + +void +wfd_stderr_logger_log( + void * user_data, + int level, + char const * format, + va_list args) +{ + fprintf(stderr, "%s: ", wfd_stderr_logger_level_str(level)); + vfprintf(stderr, format, args); + fprintf(stderr, "\n"); +} + + +void +wfd_stderr_logger_init( + int level) +{ + wfd_logger_init(level, &wfd_stderr_logger_log, NULL, NULL); +} diff --git a/src/webfused/log/stderr_logger.h b/src/webfused/log/stderr_logger.h new file mode 100644 index 0000000..40385da --- /dev/null +++ b/src/webfused/log/stderr_logger.h @@ -0,0 +1,31 @@ +#ifndef WFD_LOG_STDERR_LOGGER_H +#define WFD_LOG_STDERR_LOGGER_H + +#ifndef __cplusplus +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern void +wfd_stderr_logger_log( + void * user_data, + int level, + char const * format, + va_list args); + + +extern void +wfd_stderr_logger_init( + int level); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/webfused/mountpoint_factory.c b/src/webfused/mountpoint_factory.c index a327937..3fc641e 100644 --- a/src/webfused/mountpoint_factory.c +++ b/src/webfused/mountpoint_factory.c @@ -141,5 +141,10 @@ wfd_mountpoint_factory_create_mountpoint( wf_mountpoint_set_userdata(result, &fs->in_use, &wfd_mountpoint_factory_release_mountpoint); + WFD_INFO("create mountpoint \'%s\' at path \'%s\': %s", + filesystem, + fs->mount_point, + result ? "success" : "failure"); + return result; } From 609fbee24f3c90a5db160338475d2be96f7f6cc7 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Wed, 18 Mar 2020 09:38:25 +0100 Subject: [PATCH 31/36] added syslog logger --- CMakeLists.txt | 1 + src/webfused/daemon.c | 4 ++- src/webfused/log/syslog_logger.c | 56 ++++++++++++++++++++++++++++++++ src/webfused/log/syslog_logger.h | 20 ++++++++++++ 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 src/webfused/log/syslog_logger.c create mode 100644 src/webfused/log/syslog_logger.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c16983..dcc89c2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,6 +60,7 @@ add_library(webfused-static STATIC src/webfused/auth/file_authenticator.c src/webfused/log/logger.c src/webfused/log/stderr_logger.c + src/webfused/log/syslog_logger.c ) add_executable(webfused diff --git a/src/webfused/daemon.c b/src/webfused/daemon.c index c0b6de5..457b1fe 100644 --- a/src/webfused/daemon.c +++ b/src/webfused/daemon.c @@ -13,8 +13,9 @@ #include #include "webfused/config/config.h" #include "webfused/config/factory.h" -#include "webfused/log/stderr_logger.h" #include "webfused/log/log.h" +#include "webfused/log/logger.h" +#include "webfused/log/stderr_logger.h" #define WFD_SERVICE_TIMEOUT (1 * 1000) #define WFD_DEFAULT_CONFIG_FILE ("/etc/webfuse.conf") @@ -141,6 +142,7 @@ int wfd_daemon_run(int argc, char * argv[]) show_help(); } + wfd_logger_close(); free(args.config_file); return result; } diff --git a/src/webfused/log/syslog_logger.c b/src/webfused/log/syslog_logger.c new file mode 100644 index 0000000..02bca99 --- /dev/null +++ b/src/webfused/log/syslog_logger.c @@ -0,0 +1,56 @@ +#include "webfused/log/syslog_logger.h" +#include "webfused/log/logger.h" +#include "webfused/log/log.h" + +#include +#include + +static int +wfd_syslog_logger_to_priority( + int level) +{ + switch (level) + { + case WFD_LOGLEVEL_FATAL: return LOG_CRIT; + case WFD_LOGLEVEL_ERROR: return LOG_ERR; + case WFD_LOGLEVEL_WARN: return LOG_WARNING; + case WFD_LOGLEVEL_INFO: return LOG_INFO; + case WFD_LOGLEVEL_DEBUG: return LOG_DEBUG; + default: return LOG_NOTICE; + } +} + +static void +wfd_syslog_logger_log( + void * user_data, + int level, + char const * format, + va_list args) +{ + (void) user_data; + + int prio = wfd_syslog_logger_to_priority(level); + vsyslog(prio, format, args); +} + +static void +wfd_syslog_logger_close( + void * user_data) +{ + closelog(); +} + +void +wfd_syslog_logger_init( + int level, + char const * ident, + int options, + int facility) +{ + wfd_logger_init(level, + &wfd_syslog_logger_log, + &wfd_syslog_logger_close, + NULL); + + openlog(ident, options, facility); +} \ No newline at end of file diff --git a/src/webfused/log/syslog_logger.h b/src/webfused/log/syslog_logger.h new file mode 100644 index 0000000..1466d1d --- /dev/null +++ b/src/webfused/log/syslog_logger.h @@ -0,0 +1,20 @@ +#ifndef WFD_LOG_SYSLOG_LOGGER_H +#define WFD_LOG_SYSLOG_LOGGER_H + +#ifdef __cplusplus +extern "C" + { +#endif + +extern void +wfd_syslog_logger_init( + int level, + char const * ident, + int options, + int facility); + +#ifdef __cplusplus + } +#endif + +#endif From 1625869696cf24b209e06a654f9e16683085b2a3 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Wed, 18 Mar 2020 10:17:17 +0100 Subject: [PATCH 32/36] refactor: generalize auth_settings --- CMakeLists.txt | 9 ++-- etc/webfused.conf | 14 +++++- src/webfused/auth/factory.c | 10 ++-- src/webfused/auth/factory.h | 5 +- src/webfused/auth/file_authenticator.c | 10 ++-- src/webfused/auth/file_authenticator.h | 4 +- src/webfused/auth/settings.h | 30 ------------ src/webfused/config/auth_settings.c | 51 --------------------- src/webfused/config/auth_settings.h | 25 ---------- src/webfused/config/builder.c | 5 +- src/webfused/config/builder.h | 8 ++-- src/webfused/config/config.c | 5 +- src/webfused/config/factory.c | 11 ++--- src/webfused/config/settings.c | 32 +++++++++++++ src/webfused/config/settings.h | 22 +++++++++ src/webfused/config/settings_intern.h | 30 ++++++++++++ test/mock_auth_settings.cc | 63 -------------------------- test/mock_auth_settings.hpp | 31 ------------- test/mock_config_builder.cc | 5 +- test/mock_config_builder.hpp | 4 +- test/mock_settings.cc | 45 ++++++++++++++++++ test/mock_settings.hpp | 29 ++++++++++++ test/test_auth_factory.cc | 8 +--- test/test_auth_settings.cc | 31 ------------- test/test_config.cc | 21 ++++----- test/test_config_factory.cc | 6 +-- test/test_file_authenticator.cc | 42 ++++++++--------- test/test_settings.cc | 31 +++++++++++++ 28 files changed, 272 insertions(+), 315 deletions(-) delete mode 100644 src/webfused/auth/settings.h delete mode 100644 src/webfused/config/auth_settings.c delete mode 100644 src/webfused/config/auth_settings.h create mode 100644 src/webfused/config/settings.c create mode 100644 src/webfused/config/settings.h create mode 100644 src/webfused/config/settings_intern.h delete mode 100644 test/mock_auth_settings.cc delete mode 100644 test/mock_auth_settings.hpp create mode 100644 test/mock_settings.cc create mode 100644 test/mock_settings.hpp delete mode 100644 test/test_auth_settings.cc create mode 100644 test/test_settings.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index dcc89c2..23e6a47 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,7 +54,7 @@ add_library(webfused-static STATIC src/webfused/config/config.c src/webfused/config/factory.c src/webfused/config/builder.c - src/webfused/config/auth_settings.c + src/webfused/config/settings.c src/webfused/auth/authenticator.c src/webfused/auth/factory.c src/webfused/auth/file_authenticator.c @@ -116,10 +116,10 @@ add_executable(alltests test/mock_config_builder.cc test/mock_logger.cc test/mock_credentials.cc - test/mock_auth_settings.cc + test/mock_settings.cc test/test_config_factory.cc test/test_config.cc - test/test_auth_settings.cc + test/test_settings.cc test/test_auth_factory.cc test/test_file_authenticator.cc test/test_mountpoint_factory.cc @@ -137,8 +137,7 @@ target_compile_options(alltests PRIVATE ${GMOCK_CFLAGS} ${GTEST_CFLAGS} "-pthrea target_link_libraries(alltests PRIVATE -Wl,--wrap=wf_credentials_type -Wl,--wrap=wf_credentials_get - -Wl,--wrap=wfd_auth_settings_get_provider - -Wl,--wrap=wfd_auth_settings_get + -Wl,--wrap=wfd_settings_get webfused-static userdb ${LIBCONFIG_LIBRARIES} diff --git a/etc/webfused.conf b/etc/webfused.conf index 99f2f10..3f28976 100644 --- a/etc/webfused.conf +++ b/etc/webfused.conf @@ -27,5 +27,17 @@ authentication: filesystems: ( - {name = "test", mount_point = "/tmp" } + {name = "test", mount_point = "/tmp/webfused" } ) + +log: +{ + provider: "syslog" + level: "warning" + settings: + { + ident = "webfused" + facility = "daemon" + log_pid = true + } +} diff --git a/src/webfused/auth/factory.c b/src/webfused/auth/factory.c index b2744e0..8bd9421 100644 --- a/src/webfused/auth/factory.c +++ b/src/webfused/auth/factory.c @@ -1,24 +1,24 @@ #include "webfused/auth/factory.h" -#include "webfused/auth/settings.h" #include "webfused/auth/file_authenticator.h" +#include "webfused/config/settings.h" #include "webfused/log/log.h" #include bool wfd_authenticator_create( - struct wfd_auth_settings * settings, + char const * provider, + struct wfd_settings * settings, struct wfd_authenticator * authenticator) { bool result = false; - char const * provider_name = wfd_auth_settings_get_provider(settings); - if (0 == strcmp("file", provider_name)) + if (0 == strcmp("file", provider)) { result = wfd_file_authenticator_create(settings, authenticator); } else { - WFD_ERROR("failed to create authenticator: unknown type \"%s\"", provider_name); + WFD_ERROR("failed to create authenticator: unknown type \"%s\"", provider); } return result; diff --git a/src/webfused/auth/factory.h b/src/webfused/auth/factory.h index 5121b78..44194af 100644 --- a/src/webfused/auth/factory.h +++ b/src/webfused/auth/factory.h @@ -11,11 +11,12 @@ extern "C" #endif struct wfd_authenticator; -struct wfd_auth_settings; +struct wfd_settings; extern bool wfd_authenticator_create( - struct wfd_auth_settings * settings, + char const * provider, + struct wfd_settings * settings, struct wfd_authenticator * authenticator); #ifdef __cplusplus diff --git a/src/webfused/auth/file_authenticator.c b/src/webfused/auth/file_authenticator.c index 258badd..afc64dd 100644 --- a/src/webfused/auth/file_authenticator.c +++ b/src/webfused/auth/file_authenticator.c @@ -1,11 +1,11 @@ #include "webfused/auth/file_authenticator.h" -#include "webfused/auth/settings.h" #include "webfused/auth/authenticator.h" - -#include "webfuse/adapter/credentials.h" +#include "webfused/config/settings.h" #include "userdb/userdb.h" #include "webfused/log/log.h" +#include + #include #include @@ -71,12 +71,12 @@ wfd_file_authenticator_vtable = bool wfd_file_authenticator_create( - struct wfd_auth_settings * settings, + struct wfd_settings * settings, struct wfd_authenticator * authenticator) { bool result = false; - char const * filename = wfd_auth_settings_get(settings, "file"); + char const * filename = wfd_settings_get(settings, "file"); if (NULL != filename) { struct wfd_file_authenticator * data = malloc(sizeof(struct wfd_file_authenticator)); diff --git a/src/webfused/auth/file_authenticator.h b/src/webfused/auth/file_authenticator.h index 1ece0e3..7b406a6 100644 --- a/src/webfused/auth/file_authenticator.h +++ b/src/webfused/auth/file_authenticator.h @@ -12,11 +12,11 @@ extern "C" #endif struct wfd_authenticator; -struct wfd_auth_settings; +struct wfd_settings; extern bool wfd_file_authenticator_create( - struct wfd_auth_settings * settings, + struct wfd_settings * settings, struct wfd_authenticator * authenticator); #ifdef __cplusplus diff --git a/src/webfused/auth/settings.h b/src/webfused/auth/settings.h deleted file mode 100644 index 5e214c8..0000000 --- a/src/webfused/auth/settings.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef WFD_AUTH_SETTINGS_H -#define WFD_AUTH_SETTINGS_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -struct wfd_auth_settings; - - -extern char const * -wfd_auth_settings_get_provider( - struct wfd_auth_settings * settings); - -extern char const * -wfd_auth_settings_get( - struct wfd_auth_settings * settings, - char const * key); - - - - - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/src/webfused/config/auth_settings.c b/src/webfused/config/auth_settings.c deleted file mode 100644 index de319d3..0000000 --- a/src/webfused/config/auth_settings.c +++ /dev/null @@ -1,51 +0,0 @@ -#include "webfused/auth/settings.h" -#include "webfused/config/auth_settings.h" - -#include -#include -#include - -struct wfd_auth_settings -{ - char * provider_name; - struct config_setting_t * settings; -}; - -struct wfd_auth_settings * -wfd_auth_settings_create( - char const * provider_name, - struct config_setting_t * settings) -{ - struct wfd_auth_settings * auth_settings = malloc(sizeof(struct wfd_auth_settings)); - auth_settings->provider_name = strdup(provider_name); - auth_settings->settings = settings; - - return auth_settings; -} - -void -wfd_auth_settings_dispose( - struct wfd_auth_settings * settings) -{ - free(settings->provider_name); - free(settings); -} - -char const * -wfd_auth_settings_get_provider( - struct wfd_auth_settings * settings) -{ - return settings->provider_name; -} - -char const * -wfd_auth_settings_get( - struct wfd_auth_settings * settings, - char const * key) -{ - char const * result; - int rc = config_setting_lookup_string(settings->settings, key, &result); - - return (CONFIG_TRUE == rc) ? result : NULL; -} - diff --git a/src/webfused/config/auth_settings.h b/src/webfused/config/auth_settings.h deleted file mode 100644 index dd2abfc..0000000 --- a/src/webfused/config/auth_settings.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef WFD_CONFIG_AUTH_SETTINGS_H -#define WFD_CONFIG_AUTH_SETTINGS_H - -#ifdef __cplusplus -extern "C" -{ -#endif - -struct wfd_auth_settings; -struct config_setting_t; - -extern struct wfd_auth_settings * -wfd_auth_settings_create( - char const * provider_name, - struct config_setting_t * settings); - -extern void -wfd_auth_settings_dispose( - struct wfd_auth_settings * settings); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/webfused/config/builder.c b/src/webfused/config/builder.c index af13c09..bbe7680 100644 --- a/src/webfused/config/builder.c +++ b/src/webfused/config/builder.c @@ -43,9 +43,10 @@ wfd_config_builder_set_server_document_root( bool wfd_config_builder_add_auth_provider( struct wfd_config_builder builder, - struct wfd_auth_settings * settings) + char const * provider, + struct wfd_settings * settings) { - return builder.vtable->add_auth_provider(builder.data, settings); + return builder.vtable->add_auth_provider(builder.data, provider, settings); } bool diff --git a/src/webfused/config/builder.h b/src/webfused/config/builder.h index 8e23fd1..ccb80ed 100644 --- a/src/webfused/config/builder.h +++ b/src/webfused/config/builder.h @@ -10,7 +10,7 @@ extern "C" { #endif -struct wfd_auth_settings; +struct wfd_settings; typedef void wfd_config_builder_set_server_vhostname_fn( @@ -40,7 +40,8 @@ wfd_config_builder_set_server_document_root_fn( typedef bool wfd_config_builder_add_auth_provider_fn( void * data, - struct wfd_auth_settings * settings); + char const * provider, + struct wfd_settings * settings); typedef bool wfd_config_builder_add_filesystem_fn( @@ -93,7 +94,8 @@ wfd_config_builder_set_server_document_root( extern bool wfd_config_builder_add_auth_provider( struct wfd_config_builder builder, - struct wfd_auth_settings * settings); + char const * provider, + struct wfd_settings * settings); extern bool wfd_config_builder_add_filesystem( diff --git a/src/webfused/config/config.c b/src/webfused/config/config.c index 6499f12..f8e45f1 100644 --- a/src/webfused/config/config.c +++ b/src/webfused/config/config.c @@ -65,14 +65,15 @@ wfd_config_set_server_document_root( static bool wfd_config_add_auth_provider( void * data, - struct wfd_auth_settings * settings) + char const * provider, + struct wfd_settings * settings) { bool result = false; struct wfd_config * config = data; if (!config->has_authenticator) { - result = wfd_authenticator_create(settings, &config->authenticator); + result = wfd_authenticator_create(provider, settings, &config->authenticator); if (result) { wf_server_config_add_authenticator( diff --git a/src/webfused/config/factory.c b/src/webfused/config/factory.c index 9343b38..2f3c36f 100644 --- a/src/webfused/config/factory.c +++ b/src/webfused/config/factory.c @@ -1,5 +1,5 @@ #include "webfused/config/factory.h" -#include "webfused/config/auth_settings.h" +#include "webfused/config/settings_intern.h" #include "webfused/log/log.h" #include @@ -131,13 +131,12 @@ wfd_config_read_authentication( if (result) { - struct wfd_auth_settings * auth_settings = wfd_auth_settings_create( - provider_name, settings); + struct wfd_settings auth_settings; + wfd_settings_init(&auth_settings, settings); - result = wfd_config_builder_add_auth_provider(builder, auth_settings); - wfd_auth_settings_dispose(auth_settings); + result = wfd_config_builder_add_auth_provider(builder, provider_name, &auth_settings); + wfd_settings_cleanup(&auth_settings); } - } return result; diff --git a/src/webfused/config/settings.c b/src/webfused/config/settings.c new file mode 100644 index 0000000..cafec21 --- /dev/null +++ b/src/webfused/config/settings.c @@ -0,0 +1,32 @@ +#include "webfused/config/settings.h" +#include "webfused/config/settings_intern.h" + +#include +#include + +void +wfd_settings_init( + struct wfd_settings * settings, + struct config_setting_t * setting) +{ + settings->setting = setting; +} + +void +wfd_settings_cleanup( + struct wfd_settings * settings) +{ + settings->setting = NULL; +} + +char const * +wfd_settings_get( + struct wfd_settings * settings, + char const * key) +{ + char const * result; + int rc = config_setting_lookup_string(settings->setting, key, &result); + + return (CONFIG_TRUE == rc) ? result : NULL; +} + diff --git a/src/webfused/config/settings.h b/src/webfused/config/settings.h new file mode 100644 index 0000000..f89b23b --- /dev/null +++ b/src/webfused/config/settings.h @@ -0,0 +1,22 @@ +#ifndef WFD_CONFIG_SETTINGS_H +#define WFD_CONFIG_SETTINGS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wfd_settings; + + +extern char const * +wfd_settings_get( + struct wfd_settings * settings, + char const * key); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/src/webfused/config/settings_intern.h b/src/webfused/config/settings_intern.h new file mode 100644 index 0000000..04bf395 --- /dev/null +++ b/src/webfused/config/settings_intern.h @@ -0,0 +1,30 @@ +#ifndef WFD_CONFIG_SETTINGS_INTERN_H +#define WFD_CONFIG_SETTINGS_INTERN_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct config_setting_t; + +struct wfd_settings +{ + struct config_setting_t * setting; +}; + + +extern void +wfd_settings_init( + struct wfd_settings * settings, + struct config_setting_t * setting); + +extern void +wfd_settings_cleanup( + struct wfd_settings * settings); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/mock_auth_settings.cc b/test/mock_auth_settings.cc deleted file mode 100644 index a40391e..0000000 --- a/test/mock_auth_settings.cc +++ /dev/null @@ -1,63 +0,0 @@ -#include "mock_auth_settings.hpp" - -extern "C" -{ -using webfused_test::IAuthSettings; - -static IAuthSettings * wfd_mock_auth_settings = nullptr; - -extern char const * -__real_wfd_auth_settings_get_provider( - struct wfd_auth_settings * settings); - -extern char const * -__real_wfd_auth_settings_get( - struct wfd_auth_settings * settings, - char const * key); - -char const * -__wrap_wfd_auth_settings_get_provider( - struct wfd_auth_settings * settings) -{ - if (nullptr == wfd_mock_auth_settings) - { - return __real_wfd_auth_settings_get_provider(settings); - } - else - { - return wfd_mock_auth_settings->getProvider(); - } -} - -char const * -__wrap_wfd_auth_settings_get( - struct wfd_auth_settings * settings, - char const * key) -{ - if (nullptr == wfd_mock_auth_settings) - { - return __real_wfd_auth_settings_get(settings, key); - } - else - { - return wfd_mock_auth_settings->get(key); - } -} - - -} - -namespace webfused_test -{ - -MockAuthSettings::MockAuthSettings() -{ - wfd_mock_auth_settings = this; -} - -MockAuthSettings::~MockAuthSettings() -{ - wfd_mock_auth_settings = nullptr; -} - -} \ No newline at end of file diff --git a/test/mock_auth_settings.hpp b/test/mock_auth_settings.hpp deleted file mode 100644 index 0ba4c38..0000000 --- a/test/mock_auth_settings.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef WFD_MOCK_AUTH_SETTINGS_HPP -#define WFD_MOCK_AUTH_SETTINGS_HPP - -#include -#include "webfused/auth/settings.h" - -namespace webfused_test -{ - -class IAuthSettings -{ -public: - virtual ~IAuthSettings() = default; - virtual char const * getProvider() = 0; - virtual char const * get(char const * key) = 0; -}; - -class MockAuthSettings: public IAuthSettings -{ -public: - MockAuthSettings(); - ~MockAuthSettings() override; - MOCK_METHOD0(getProvider, char const * ()); - MOCK_METHOD1(get, char const * (char const * key)); -}; - -} - - - -#endif diff --git a/test/mock_config_builder.cc b/test/mock_config_builder.cc index f872edf..c1ae9b8 100644 --- a/test/mock_config_builder.cc +++ b/test/mock_config_builder.cc @@ -52,10 +52,11 @@ wfd_MockConfigBuilder_set_server_document_root( static bool wfd_MockConfigBuilder_add_auth_provider( void * data, - struct wfd_auth_settings * settings) + char const * provider, + struct wfd_settings * settings) { auto * builder = reinterpret_cast(data); - return builder->addAuthProvider(settings); + return builder->addAuthProvider(provider, settings); } static bool diff --git a/test/mock_config_builder.hpp b/test/mock_config_builder.hpp index d37c47a..f0c04a6 100644 --- a/test/mock_config_builder.hpp +++ b/test/mock_config_builder.hpp @@ -16,7 +16,7 @@ public: virtual void setServerKey(char const * key_path) = 0; virtual void setServerCert(char const * cert_path) = 0; virtual void setServerDocumentRoot(char const * document_root) = 0; - virtual bool addAuthProvider(wfd_auth_settings * settings) = 0; + virtual bool addAuthProvider(char const * provider, wfd_settings * settings) = 0; virtual bool addFilesystem(char const * name, char const * mountpoint) = 0; }; @@ -29,7 +29,7 @@ public: MOCK_METHOD1(setServerKey, void (char const * key_path)); MOCK_METHOD1(setServerCert, void (char const * cert_path)); MOCK_METHOD1(setServerDocumentRoot, void (char const * document_root)); - MOCK_METHOD1(addAuthProvider, bool (wfd_auth_settings * settings)); + MOCK_METHOD2(addAuthProvider, bool (char const * provider, wfd_settings * settings)); MOCK_METHOD2(addFilesystem, bool (char const * name, char const * mountpoint)); struct wfd_config_builder getBuilder(); diff --git a/test/mock_settings.cc b/test/mock_settings.cc new file mode 100644 index 0000000..cc66555 --- /dev/null +++ b/test/mock_settings.cc @@ -0,0 +1,45 @@ +#include "mock_settings.hpp" + +extern "C" +{ +using webfused_test::ISettings; + +static ISettings * wfd_mock_settings = nullptr; + +extern char const * +__real_wfd_settings_get( + struct wfd_settings * settings, + char const * key); + +char const * +__wrap_wfd_settings_get( + struct wfd_settings * settings, + char const * key) +{ + if (nullptr == wfd_mock_settings) + { + return __real_wfd_settings_get(settings, key); + } + else + { + return wfd_mock_settings->get(key); + } +} + + +} + +namespace webfused_test +{ + +MockSettings::MockSettings() +{ + wfd_mock_settings = this; +} + +MockSettings::~MockSettings() +{ + wfd_mock_settings = nullptr; +} + +} \ No newline at end of file diff --git a/test/mock_settings.hpp b/test/mock_settings.hpp new file mode 100644 index 0000000..016a8f4 --- /dev/null +++ b/test/mock_settings.hpp @@ -0,0 +1,29 @@ +#ifndef WFD_MOCK_AUTH_SETTINGS_HPP +#define WFD_MOCK_AUTH_SETTINGS_HPP + +#include +#include "webfused/config/settings.h" + +namespace webfused_test +{ + +class ISettings +{ +public: + virtual ~ISettings() = default; + virtual char const * get(char const * key) = 0; +}; + +class MockSettings: public ISettings +{ +public: + MockSettings(); + ~MockSettings() override; + MOCK_METHOD1(get, char const * (char const * key)); +}; + +} + + + +#endif diff --git a/test/test_auth_factory.cc b/test/test_auth_factory.cc index e3611dc..2e26cca 100644 --- a/test/test_auth_factory.cc +++ b/test/test_auth_factory.cc @@ -1,7 +1,6 @@ #include #include "webfused/auth/factory.h" #include "webfused/auth/authenticator.h" -#include "webfused/config/auth_settings.h" #include "webfused/log/log.h" #include "mock_logger.hpp" @@ -15,12 +14,7 @@ TEST(auth_factory, fail_unknown_provider) EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); EXPECT_CALL(logger, onclose()).Times(1); - wfd_auth_settings * auth_settings = wfd_auth_settings_create( - "unknown", NULL); - wfd_authenticator authenticator; - bool result = wfd_authenticator_create(auth_settings, &authenticator); + bool result = wfd_authenticator_create("unknown", NULL, &authenticator); ASSERT_FALSE(result); - - wfd_auth_settings_dispose(auth_settings); } \ No newline at end of file diff --git a/test/test_auth_settings.cc b/test/test_auth_settings.cc deleted file mode 100644 index 2f786a9..0000000 --- a/test/test_auth_settings.cc +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include "webfused/auth/settings.h" -#include "webfused/config/auth_settings.h" -#include - -TEST(auth_settings, auth_settings) -{ - char const settings_text[] = - "settings:\n" - "{\n" - " string_value = \"some.string\"\n" - " int_value = 42\n" - "}\n" - ; - config_t config; - config_init(&config); - int rc = config_read_string(&config, settings_text); - ASSERT_TRUE(CONFIG_TRUE == rc); - - config_setting_t * settings = config_lookup(&config, "settings"); - ASSERT_NE(nullptr, settings); - - wfd_auth_settings * auth_settings = wfd_auth_settings_create("test_provider", settings); - ASSERT_STREQ("test_provider", wfd_auth_settings_get_provider(auth_settings)); - ASSERT_STREQ("some.string", wfd_auth_settings_get(auth_settings, "string_value")); - ASSERT_EQ(nullptr, wfd_auth_settings_get(auth_settings, "int_value")); - ASSERT_EQ(nullptr, wfd_auth_settings_get(auth_settings, "invalid_value")); - - wfd_auth_settings_dispose(auth_settings); - config_destroy(&config); -} \ No newline at end of file diff --git a/test/test_config.cc b/test/test_config.cc index a86a777..14df533 100644 --- a/test/test_config.cc +++ b/test/test_config.cc @@ -1,6 +1,6 @@ #include #include "webfused/config/config.h" -#include "mock_auth_settings.hpp" +#include "mock_settings.hpp" #include "webfused/log/logger.h" #include "webfused/log/log.h" @@ -8,7 +8,7 @@ using ::webfused_test::MockLogger; using ::testing::_; -using ::webfused_test::MockAuthSettings; +using ::webfused_test::MockSettings; using ::testing::Return; using ::testing::StrEq; @@ -37,11 +37,10 @@ TEST(config, auth_config) wfd_config_builder builder = wfd_config_get_builder(config); - MockAuthSettings settings; - EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("file")); + MockSettings settings; EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); - bool success = wfd_config_builder_add_auth_provider(builder, nullptr); + bool success = wfd_config_builder_add_auth_provider(builder, "file", nullptr); ASSERT_TRUE(success); wfd_config_dispose(config); @@ -54,14 +53,13 @@ TEST(config, auth_config_failed_to_add_second_provider) wfd_config_builder builder = wfd_config_get_builder(config); - MockAuthSettings settings; - EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("file")); + MockSettings settings; EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); - bool success = wfd_config_builder_add_auth_provider(builder, nullptr); + bool success = wfd_config_builder_add_auth_provider(builder, "file", nullptr); ASSERT_TRUE(success); - success = wfd_config_builder_add_auth_provider(builder, nullptr); + success = wfd_config_builder_add_auth_provider(builder, "file", nullptr); ASSERT_FALSE(success); wfd_config_dispose(config); @@ -74,10 +72,7 @@ TEST(config, auth_config_failed_to_add_unknown_provider) wfd_config_builder builder = wfd_config_get_builder(config); - MockAuthSettings settings; - EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("unknown")); - - bool success = wfd_config_builder_add_auth_provider(builder, nullptr); + bool success = wfd_config_builder_add_auth_provider(builder, "unknown", nullptr); ASSERT_FALSE(success); wfd_config_dispose(config); diff --git a/test/test_config_factory.cc b/test/test_config_factory.cc index ba83165..374af8c 100644 --- a/test/test_config_factory.cc +++ b/test/test_config_factory.cc @@ -19,7 +19,7 @@ TEST(config, is_loadable) StrictMock builder; EXPECT_CALL(builder, setServerVhostname(StrEq("localhost"))).Times(1); EXPECT_CALL(builder, setServerPort(8080)).Times(1); - EXPECT_CALL(builder, addAuthProvider(_)).Times(1).WillOnce(Return(true)); + EXPECT_CALL(builder, addAuthProvider(_, _)).Times(1).WillOnce(Return(true)); EXPECT_CALL(builder, addFilesystem(_,_)).Times(1).WillOnce(Return(true)); bool result = wfd_config_load_file(builder.getBuilder(), "webfused.conf"); @@ -262,7 +262,7 @@ TEST(config, authentication) EXPECT_CALL(logger, onclose()).Times(1); StrictMock builder; - EXPECT_CALL(builder, addAuthProvider(_)).Times(1).WillOnce(Return(true)); + EXPECT_CALL(builder, addAuthProvider(_, _)).Times(1).WillOnce(Return(true)); char const config_text[] = "version = { major = 1, minor = 0 }\n" @@ -283,7 +283,7 @@ TEST(config, failed_create_authenticator) EXPECT_CALL(logger, onclose()).Times(1); StrictMock builder; - EXPECT_CALL(builder, addAuthProvider(_)).Times(1).WillOnce(Return(false)); + EXPECT_CALL(builder, addAuthProvider(_, _)).Times(1).WillOnce(Return(false)); char const config_text[] = "version = { major = 1, minor = 0 }\n" diff --git a/test/test_file_authenticator.cc b/test/test_file_authenticator.cc index b7037a2..451b4fa 100644 --- a/test/test_file_authenticator.cc +++ b/test/test_file_authenticator.cc @@ -1,22 +1,22 @@ #include "webfused/auth/file_authenticator.h" #include "webfused/auth/authenticator.h" -#include "webfused/config/auth_settings.h" +#include "webfused/config/settings.h" #include "webfused/auth/factory.h" #include "mock_credentials.hpp" -#include "mock_auth_settings.hpp" +#include "mock_settings.hpp" #include #include -using ::webfused_test::MockAuthSettings; +using ::webfused_test::MockSettings; using ::webfused_test::MockCredentials; using ::testing::Return; using ::testing::StrEq; TEST(file_authenticator, create) { - MockAuthSettings settings; + MockSettings settings; EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; @@ -28,7 +28,7 @@ TEST(file_authenticator, create) TEST(file_authenticator, create_fail_missing_file) { - MockAuthSettings settings; + MockSettings settings; EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return(nullptr)); wfd_authenticator authenticator; @@ -38,12 +38,11 @@ TEST(file_authenticator, create_fail_missing_file) TEST(file_authenticator, create_via_factory) { - MockAuthSettings settings; - EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("file")); + MockSettings settings; EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; - bool success = wfd_authenticator_create(nullptr, &authenticator); + bool success = wfd_authenticator_create("file", nullptr, &authenticator); ASSERT_TRUE(success); wfd_authenticator_dispose(authenticator); @@ -51,12 +50,11 @@ TEST(file_authenticator, create_via_factory) TEST(file_authenticator, authenticate) { - MockAuthSettings settings; - EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("file")); + MockSettings settings; EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; - bool success = wfd_authenticator_create(nullptr, &authenticator); + bool success = wfd_file_authenticator_create(nullptr, &authenticator); ASSERT_TRUE(success); MockCredentials creds; @@ -71,12 +69,11 @@ TEST(file_authenticator, authenticate) TEST(file_authenticator, authenticate_fail_wrong_passwd) { - MockAuthSettings settings; - EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("file")); + MockSettings settings; EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; - bool success = wfd_authenticator_create(nullptr, &authenticator); + bool success = wfd_file_authenticator_create(nullptr, &authenticator); ASSERT_TRUE(success); MockCredentials creds; @@ -91,12 +88,11 @@ TEST(file_authenticator, authenticate_fail_wrong_passwd) TEST(file_authenticator, authenticate_fail_no_passwd_file) { - MockAuthSettings settings; - EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("file")); + MockSettings settings; EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("unknown_passwd.json")); wfd_authenticator authenticator; - bool success = wfd_authenticator_create(nullptr, &authenticator); + bool success = wfd_file_authenticator_create(nullptr, &authenticator); ASSERT_TRUE(success); MockCredentials creds; @@ -111,12 +107,11 @@ TEST(file_authenticator, authenticate_fail_no_passwd_file) TEST(file_authenticator, authenticate_fail_missing_username) { - MockAuthSettings settings; - EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("file")); + MockSettings settings; EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; - bool success = wfd_authenticator_create(nullptr, &authenticator); + bool success = wfd_file_authenticator_create(nullptr, &authenticator); ASSERT_TRUE(success); MockCredentials creds; @@ -131,12 +126,11 @@ TEST(file_authenticator, authenticate_fail_missing_username) TEST(file_authenticator, authenticate_fail_missing_password) { - MockAuthSettings settings; - EXPECT_CALL(settings, getProvider()).Times(1).WillOnce(Return("file")); + MockSettings settings; EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; - bool success = wfd_authenticator_create(nullptr, &authenticator); + bool success = wfd_file_authenticator_create(nullptr, &authenticator); ASSERT_TRUE(success); MockCredentials creds; @@ -151,7 +145,7 @@ TEST(file_authenticator, authenticate_fail_missing_password) TEST(file_authenticator, get_type) { - MockAuthSettings settings; + MockSettings settings; EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); wfd_authenticator authenticator; diff --git a/test/test_settings.cc b/test/test_settings.cc new file mode 100644 index 0000000..730a059 --- /dev/null +++ b/test/test_settings.cc @@ -0,0 +1,31 @@ +#include +#include "webfused/config/settings_intern.h" +#include "webfused/config/settings.h" +#include + +TEST(settings, settings) +{ + char const settings_text[] = + "settings:\n" + "{\n" + " string_value = \"some.string\"\n" + " int_value = 42\n" + "}\n" + ; + config_t config; + config_init(&config); + int rc = config_read_string(&config, settings_text); + ASSERT_TRUE(CONFIG_TRUE == rc); + + config_setting_t * setting = config_lookup(&config, "settings"); + ASSERT_NE(nullptr, setting); + + wfd_settings settings; + wfd_settings_init(&settings, setting); + ASSERT_STREQ("some.string", wfd_settings_get(&settings, "string_value")); + ASSERT_EQ(nullptr, wfd_settings_get(&settings, "int_value")); + ASSERT_EQ(nullptr, wfd_settings_get(&settings, "invalid_value")); + + wfd_settings_cleanup(&settings); + config_destroy(&config); +} \ No newline at end of file From adbfd459517c6fe2b065be31e22a51a89d88f4a3 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Wed, 18 Mar 2020 17:33:31 +0100 Subject: [PATCH 33/36] read log config from config file --- CMakeLists.txt | 9 ++- src/webfused/auth/file_authenticator.c | 2 +- src/webfused/config/builder.c | 11 +++ src/webfused/config/builder.h | 15 ++++ src/webfused/config/config.c | 15 +++- src/webfused/config/factory.c | 54 +++++++++++++ src/webfused/config/settings.c | 30 ++++++- src/webfused/config/settings.h | 17 +++- src/webfused/daemon.c | 2 +- src/webfused/log/log.c | 62 +++++++++++++++ src/webfused/log/log.h | 10 +++ src/webfused/log/manager.c | 30 +++++++ src/webfused/log/manager.h | 25 ++++++ src/webfused/log/stderr_logger.c | 27 ++----- src/webfused/log/stderr_logger.h | 17 ++-- src/webfused/log/syslog_logger.c | 84 +++++++++++++++++--- src/webfused/log/syslog_logger.h | 12 ++- test/mock_config_builder.cc | 14 +++- test/mock_config_builder.hpp | 2 + test/mock_settings.cc | 50 +++++++++++- test/mock_settings.hpp | 8 +- test/test_config.cc | 17 +++- test/test_config_factory.cc | 105 +++++++++++++++++++++++++ test/test_file_authenticator.cc | 18 ++--- test/test_log.cc | 59 ++++++++++++++ test/test_log_manager.cc | 10 +++ test/test_settings.cc | 67 +++++++++++++++- test/test_stderr_logger.cc | 27 +++++++ test/test_syslog_logger.cc | 45 +++++++++++ 29 files changed, 772 insertions(+), 72 deletions(-) create mode 100644 src/webfused/log/log.c create mode 100644 src/webfused/log/manager.c create mode 100644 src/webfused/log/manager.h create mode 100644 test/test_log_manager.cc create mode 100644 test/test_stderr_logger.cc create mode 100644 test/test_syslog_logger.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 23e6a47..c2bcbd4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,9 @@ add_library(webfused-static STATIC src/webfused/auth/authenticator.c src/webfused/auth/factory.c src/webfused/auth/file_authenticator.c + src/webfused/log/log.c src/webfused/log/logger.c + src/webfused/log/manager.c src/webfused/log/stderr_logger.c src/webfused/log/syslog_logger.c ) @@ -124,6 +126,9 @@ add_executable(alltests test/test_file_authenticator.cc test/test_mountpoint_factory.cc test/test_log.cc + test/test_log_manager.cc + test/test_stderr_logger.cc + test/test_syslog_logger.cc ) target_include_directories(alltests PRIVATE @@ -137,7 +142,9 @@ target_compile_options(alltests PRIVATE ${GMOCK_CFLAGS} ${GTEST_CFLAGS} "-pthrea target_link_libraries(alltests PRIVATE -Wl,--wrap=wf_credentials_type -Wl,--wrap=wf_credentials_get - -Wl,--wrap=wfd_settings_get + -Wl,--wrap=wfd_settings_get_string + -Wl,--wrap=wfd_settings_get_string_or_default + -Wl,--wrap=wfd_settings_get_bool webfused-static userdb ${LIBCONFIG_LIBRARIES} diff --git a/src/webfused/auth/file_authenticator.c b/src/webfused/auth/file_authenticator.c index afc64dd..61dae0a 100644 --- a/src/webfused/auth/file_authenticator.c +++ b/src/webfused/auth/file_authenticator.c @@ -76,7 +76,7 @@ wfd_file_authenticator_create( { bool result = false; - char const * filename = wfd_settings_get(settings, "file"); + char const * filename = wfd_settings_get_string(settings, "file"); if (NULL != filename) { struct wfd_file_authenticator * data = malloc(sizeof(struct wfd_file_authenticator)); diff --git a/src/webfused/config/builder.c b/src/webfused/config/builder.c index bbe7680..6d712f4 100644 --- a/src/webfused/config/builder.c +++ b/src/webfused/config/builder.c @@ -58,4 +58,15 @@ wfd_config_builder_add_filesystem( return builder.vtable->add_filesystem(builder.data, name, mount_point); } +bool +wfd_config_builder_set_logger( + struct wfd_config_builder builder, + char const * provider, + int level, + struct wfd_settings * settings) +{ + return builder.vtable->set_logger(builder.data, provider, level, settings); +} + + diff --git a/src/webfused/config/builder.h b/src/webfused/config/builder.h index ccb80ed..01348ea 100644 --- a/src/webfused/config/builder.h +++ b/src/webfused/config/builder.h @@ -49,6 +49,13 @@ wfd_config_builder_add_filesystem_fn( char const * name, char const * mount_point); +typedef bool +wfd_config_builder_set_logger_fn( + void * data, + char const * provider, + int level, + struct wfd_settings * settings); + struct wfd_config_builder_vtable { wfd_config_builder_set_server_vhostname_fn * set_server_vhostname; @@ -58,6 +65,7 @@ struct wfd_config_builder_vtable wfd_config_builder_set_server_document_root_fn * set_server_document_root; wfd_config_builder_add_auth_provider_fn * add_auth_provider; wfd_config_builder_add_filesystem_fn * add_filesystem; + wfd_config_builder_set_logger_fn * set_logger; }; struct wfd_config_builder @@ -103,6 +111,13 @@ wfd_config_builder_add_filesystem( char const * name, char const * mount_point); +extern bool +wfd_config_builder_set_logger( + struct wfd_config_builder builder, + char const * provider, + int level, + struct wfd_settings * settings); + #ifdef __cplusplus } #endif diff --git a/src/webfused/config/config.c b/src/webfused/config/config.c index f8e45f1..f74fed7 100644 --- a/src/webfused/config/config.c +++ b/src/webfused/config/config.c @@ -3,6 +3,7 @@ #include "webfused/auth/factory.h" #include "webfused/auth/authenticator.h" #include "webfused/mountpoint_factory.h" +#include "webfused/log/manager.h" #include @@ -100,6 +101,17 @@ wfd_config_add_filesystem( config->mountpoint_factory, name, mount_point); } +static bool +wfd_config_set_logger( + void * data, + char const * provider, + int level, + struct wfd_settings * settings) +{ + struct wfd_config * config = data; + return wfd_log_manager_set_logger(provider, level, settings); +} + static const struct wfd_config_builder_vtable wfd_config_vtable_config_builder = { @@ -109,7 +121,8 @@ wfd_config_vtable_config_builder = .set_server_cert = &wfd_config_set_server_cert, .set_server_document_root = &wfd_config_set_server_document_root, .add_auth_provider = &wfd_config_add_auth_provider, - .add_filesystem = &wfd_config_add_filesystem + .add_filesystem = &wfd_config_add_filesystem, + .set_logger = &wfd_config_set_logger }; struct wfd_config * diff --git a/src/webfused/config/factory.c b/src/webfused/config/factory.c index 2f3c36f..ddd4ff0 100644 --- a/src/webfused/config/factory.c +++ b/src/webfused/config/factory.c @@ -55,6 +55,59 @@ wfd_config_check_version( return true; } +static bool +wfd_config_read_logger( + config_t * config, + struct wfd_config_builder builder) +{ + bool result = true; + + bool hasLogger = (NULL != config_lookup(config, "log")); + if (hasLogger) + { + char const * provider; + int rc = config_lookup_string(config, "log.provider", &provider); + if (CONFIG_TRUE != rc) + { + WFD_ERROR("missing log provider"); + result = false; + } + + char const * level_str; + if (result) + { + rc = config_lookup_string(config, "log.level", &level_str); + if (CONFIG_TRUE != rc) + { + WFD_ERROR("missing log level"); + result = false; + } + } + + int level; + if (result) + { + bool success = wfd_log_level_parse(level_str, &level); + if (!success) + { + WFD_ERROR("failed to parse log level: unknown valuie \'%s\'", level_str); + result = false; + } + } + + if (result) + { + config_setting_t * setting = config_lookup(config, "log.settings"); + struct wfd_settings settings; + wfd_settings_init(&settings, setting); + result = wfd_config_builder_set_logger(builder, provider, level, &settings); + wfd_settings_cleanup(&settings); + } + } + + return result; +} + static bool wfd_config_read_server( config_t * config, @@ -198,6 +251,7 @@ wfd_config_load( { bool result = wfd_config_check_version(config) + && wfd_config_read_logger(config, builder) && wfd_config_read_server(config, builder) && wfd_config_read_authentication(config, builder) && wfd_config_read_filesystems(config, builder) diff --git a/src/webfused/config/settings.c b/src/webfused/config/settings.c index cafec21..0c7df95 100644 --- a/src/webfused/config/settings.c +++ b/src/webfused/config/settings.c @@ -20,13 +20,41 @@ wfd_settings_cleanup( } char const * -wfd_settings_get( +wfd_settings_get_string( struct wfd_settings * settings, char const * key) { + if (NULL == settings) {return NULL; } + char const * result; int rc = config_setting_lookup_string(settings->setting, key, &result); return (CONFIG_TRUE == rc) ? result : NULL; } +char const * +wfd_settings_get_string_or_default( + struct wfd_settings * settings, + char const * key, + char const * default_value) +{ + if (NULL == settings) {return default_value; } + + char const * result; + int rc = config_setting_lookup_string(settings->setting, key, &result); + + return (CONFIG_TRUE == rc) ? result : default_value; +} + +bool +wfd_settings_get_bool( + struct wfd_settings * settings, + char const * key) +{ + if (NULL == settings) {return false; } + + int result; + int rc = config_setting_lookup_bool(settings->setting, key, &result); + + return ((CONFIG_TRUE == rc) && (CONFIG_TRUE == result)); +} diff --git a/src/webfused/config/settings.h b/src/webfused/config/settings.h index f89b23b..9035367 100644 --- a/src/webfused/config/settings.h +++ b/src/webfused/config/settings.h @@ -1,6 +1,10 @@ #ifndef WFD_CONFIG_SETTINGS_H #define WFD_CONFIG_SETTINGS_H +#ifndef __cplusplus +#include +#endif + #ifdef __cplusplus extern "C" { @@ -10,7 +14,18 @@ struct wfd_settings; extern char const * -wfd_settings_get( +wfd_settings_get_string( + struct wfd_settings * settings, + char const * key); + +extern char const * +wfd_settings_get_string_or_default( + struct wfd_settings * settings, + char const * key, + char const * default_value); + +extern bool +wfd_settings_get_bool( struct wfd_settings * settings, char const * key); diff --git a/src/webfused/daemon.c b/src/webfused/daemon.c index 457b1fe..b7786cd 100644 --- a/src/webfused/daemon.c +++ b/src/webfused/daemon.c @@ -98,7 +98,7 @@ static void on_interrupt(int signal_id) int wfd_daemon_run(int argc, char * argv[]) { - wfd_stderr_logger_init(WFD_LOGLEVEL_ALL); + wfd_stderr_logger_init(WFD_LOGLEVEL_ALL, NULL); struct args args; int result = parse_arguments(argc, argv, &args); diff --git a/src/webfused/log/log.c b/src/webfused/log/log.c new file mode 100644 index 0000000..986fa5f --- /dev/null +++ b/src/webfused/log/log.c @@ -0,0 +1,62 @@ +#include "webfused/log/log.h" +#include + +char const * +wfd_log_level_tostring(int level) +{ + switch (level) + { + case WFD_LOGLEVEL_NONE: return "none"; + case WFD_LOGLEVEL_FATAL: return "fatal"; + case WFD_LOGLEVEL_ERROR: return "error"; + case WFD_LOGLEVEL_WARN: return "warn"; + case WFD_LOGLEVEL_INFO: return "info"; + case WFD_LOGLEVEL_DEBUG: return "debug"; + case WFD_LOGLEVEL_ALL: return "all"; + default: return ""; + } +} + +bool +wfd_log_level_parse( + char const * level, + int * result) +{ + bool success = true; + + if (0 == strcasecmp("all", level)) + { + *result = WFD_LOGLEVEL_ALL; + } + else if (0 == strcasecmp("none", level)) + { + *result = WFD_LOGLEVEL_NONE; + } + else if (0 == strcasecmp("fatal", level)) + { + *result = WFD_LOGLEVEL_FATAL; + } + else if (0 == strcasecmp("error", level)) + { + *result = WFD_LOGLEVEL_ERROR; + } + else if ((0 == strcasecmp("warn", level)) || + (0 == strcasecmp("warning", level))) + { + *result = WFD_LOGLEVEL_WARN; + } + else if (0 == strcasecmp("info", level)) + { + *result = WFD_LOGLEVEL_INFO; + } + else if (0 == strcasecmp("debug", level)) + { + *result = WFD_LOGLEVEL_DEBUG; + } + else + { + return false; + } + + return success; +} diff --git a/src/webfused/log/log.h b/src/webfused/log/log.h index 08a3b54..3a312c1 100644 --- a/src/webfused/log/log.h +++ b/src/webfused/log/log.h @@ -2,6 +2,7 @@ #define WFD_LOG_H #ifndef __cplusplus +#include #include #else #include @@ -16,6 +17,7 @@ extern "C" #define WFD_LOGLEVEL WFD_LOGLEVEL_ALL #endif +#define WFD_LOGLEVEL_NONE -1 #define WFD_LOGLEVEL_FATAL 1 #define WFD_LOGLEVEL_ERROR 3 #define WFD_LOGLEVEL_WARN 4 @@ -51,6 +53,14 @@ wfd_log( char const * format, ...); +extern char const * +wfd_log_level_tostring(int level); + +extern bool +wfd_log_level_parse( + char const * level, + int * result); + #ifdef __cplusplus } #endif diff --git a/src/webfused/log/manager.c b/src/webfused/log/manager.c new file mode 100644 index 0000000..c8f09b0 --- /dev/null +++ b/src/webfused/log/manager.c @@ -0,0 +1,30 @@ +#include "webfused/log/manager.h" +#include "webfused/log/log.h" +#include "webfused/log/stderr_logger.h" +#include "webfused/log/syslog_logger.h" + +#include + +bool +wfd_log_manager_set_logger( + char const * provider, + int level, + struct wfd_settings * settings) +{ + bool result = false; + + if (0 == strcmp("syslog", provider)) + { + result = wfd_syslog_logger_init(level, settings); + } + else if (0 == strcmp("stderr", provider)) + { + result = wfd_stderr_logger_init(level, settings); + } + else + { + WFD_ERROR("failed to init log: unknown provider \'%s\'", provider); + } + + return result; +} diff --git a/src/webfused/log/manager.h b/src/webfused/log/manager.h new file mode 100644 index 0000000..103418f --- /dev/null +++ b/src/webfused/log/manager.h @@ -0,0 +1,25 @@ +#ifndef WFD_LOG_MANAGER_H +#define WFD_LOG_MANAGER_H + +#ifndef __cplusplus +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wfd_settings; + +extern bool +wfd_log_manager_set_logger( + char const * provider, + int level, + struct wfd_settings * settings); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/webfused/log/stderr_logger.c b/src/webfused/log/stderr_logger.c index 224f7f9..34c3f5f 100644 --- a/src/webfused/log/stderr_logger.c +++ b/src/webfused/log/stderr_logger.c @@ -5,36 +5,25 @@ #include #include -static const char * -wfd_stderr_logger_level_str(int level) -{ - switch (level) - { - case WFD_LOGLEVEL_FATAL: return "fatal"; - case WFD_LOGLEVEL_ERROR: return "error"; - case WFD_LOGLEVEL_WARN: return "warn"; - case WFD_LOGLEVEL_INFO: return "info"; - case WFD_LOGLEVEL_DEBUG: return "debug"; - default: return "notice"; - } -} - -void +static void wfd_stderr_logger_log( void * user_data, int level, char const * format, va_list args) { - fprintf(stderr, "%s: ", wfd_stderr_logger_level_str(level)); + fprintf(stderr, "%s: ", wfd_log_level_tostring(level)); vfprintf(stderr, format, args); fprintf(stderr, "\n"); } - -void +bool wfd_stderr_logger_init( - int level) + int level, + struct wfd_settings * settings) { + (void) settings; + wfd_logger_init(level, &wfd_stderr_logger_log, NULL, NULL); + return true; } diff --git a/src/webfused/log/stderr_logger.h b/src/webfused/log/stderr_logger.h index 40385da..d1bb25e 100644 --- a/src/webfused/log/stderr_logger.h +++ b/src/webfused/log/stderr_logger.h @@ -2,9 +2,7 @@ #define WFD_LOG_STDERR_LOGGER_H #ifndef __cplusplus -#include -#else -#include +#include #endif #ifdef __cplusplus @@ -12,17 +10,12 @@ extern "C" { #endif -extern void -wfd_stderr_logger_log( - void * user_data, - int level, - char const * format, - va_list args); - +struct wfd_settings; -extern void +extern bool wfd_stderr_logger_init( - int level); + int level, + struct wfd_settings * settings); #ifdef __cplusplus } diff --git a/src/webfused/log/syslog_logger.c b/src/webfused/log/syslog_logger.c index 02bca99..0f66ad4 100644 --- a/src/webfused/log/syslog_logger.c +++ b/src/webfused/log/syslog_logger.c @@ -1,8 +1,11 @@ #include "webfused/log/syslog_logger.h" #include "webfused/log/logger.h" #include "webfused/log/log.h" +#include "webfused/config/settings.h" #include +#include + #include static int @@ -40,17 +43,80 @@ wfd_syslog_logger_close( closelog(); } -void +struct wfd_syslog_facility +{ + char const * name; + int value; +}; + +static bool +wfd_syslog_logger_parse_facility( + char const * facility, + int * result) +{ + static struct wfd_syslog_facility const facilities[] = + { + {"auth", LOG_AUTH}, + {"authpriv", LOG_AUTHPRIV}, + {"cron", LOG_CRON}, + {"daemon", LOG_DAEMON}, + {"fpt", LOG_FTP}, + {"kern", LOG_KERN}, + {"local0", LOG_LOCAL0}, + {"local1", LOG_LOCAL1}, + {"local2", LOG_LOCAL2}, + {"local3", LOG_LOCAL3}, + {"local4", LOG_LOCAL4}, + {"local5", LOG_LOCAL5}, + {"local6", LOG_LOCAL6}, + {"local7", LOG_LOCAL7}, + {"lpr", LOG_LPR}, + {"mail", LOG_MAIL}, + {"news", LOG_NEWS}, + {"syslog", LOG_SYSLOG}, + {"user", LOG_USER}, + {"uucp", LOG_UUCP} + }; + static size_t const facilites_count = sizeof(facilities) / sizeof(facilities[0]); + + for (size_t i = 0; i < facilites_count; i++) + { + if (0 == strcasecmp(facility, facilities[i].name)) + { + *result = facilities[i].value; + return true; + } + } + + return false; +} + + +bool wfd_syslog_logger_init( int level, - char const * ident, - int options, - int facility) + struct wfd_settings * settings) { - wfd_logger_init(level, - &wfd_syslog_logger_log, - &wfd_syslog_logger_close, - NULL); + char const * ident = wfd_settings_get_string_or_default(settings, "ident", "webfused"); + char const * facility_str = wfd_settings_get_string_or_default(settings, "facility", "daemon"); + bool log_pid = wfd_settings_get_bool(settings, "log_pid"); + + int facility; + bool result = wfd_syslog_logger_parse_facility(facility_str, &facility); + if (result) + { + int options = (log_pid) ? LOG_PID : 0; + wfd_logger_init(level, + &wfd_syslog_logger_log, + &wfd_syslog_logger_close, + NULL); + + openlog(ident, options, facility); + } + else + { + WFD_ERROR("failed to init syslog logger: invalid log facility: \'%s\'", facility_str); + } - openlog(ident, options, facility); + return result; } \ No newline at end of file diff --git a/src/webfused/log/syslog_logger.h b/src/webfused/log/syslog_logger.h index 1466d1d..6682715 100644 --- a/src/webfused/log/syslog_logger.h +++ b/src/webfused/log/syslog_logger.h @@ -1,17 +1,21 @@ #ifndef WFD_LOG_SYSLOG_LOGGER_H #define WFD_LOG_SYSLOG_LOGGER_H +#ifndef __cplusplus +#include +#endif + #ifdef __cplusplus extern "C" { #endif -extern void +struct wfd_settings; + +extern bool wfd_syslog_logger_init( int level, - char const * ident, - int options, - int facility); + struct wfd_settings * settings); #ifdef __cplusplus } diff --git a/test/mock_config_builder.cc b/test/mock_config_builder.cc index c1ae9b8..7967178 100644 --- a/test/mock_config_builder.cc +++ b/test/mock_config_builder.cc @@ -69,6 +69,17 @@ wfd_MockConfigBuilder_add_filesystem( return builder->addFilesystem(name, mountpoint); } +static bool +wfd_MockConfigBuilder_set_logger( + void * data, + char const * provider, + int level, + struct wfd_settings * settings) +{ + auto * builder = reinterpret_cast(data); + return builder->setLogger(provider, level, settings); +} + static const wfd_config_builder_vtable wfd_MockConfigBuilder_vtable = { @@ -78,7 +89,8 @@ static const wfd_config_builder_vtable wfd_MockConfigBuilder_vtable = &wfd_MockConfigBuilder_set_server_cert, &wfd_MockConfigBuilder_set_server_document_root, &wfd_MockConfigBuilder_add_auth_provider, - &wfd_MockConfigBuilder_add_filesystem + &wfd_MockConfigBuilder_add_filesystem, + &wfd_MockConfigBuilder_set_logger }; } diff --git a/test/mock_config_builder.hpp b/test/mock_config_builder.hpp index f0c04a6..a512a10 100644 --- a/test/mock_config_builder.hpp +++ b/test/mock_config_builder.hpp @@ -18,6 +18,7 @@ public: virtual void setServerDocumentRoot(char const * document_root) = 0; virtual bool addAuthProvider(char const * provider, wfd_settings * settings) = 0; virtual bool addFilesystem(char const * name, char const * mountpoint) = 0; + virtual bool setLogger(char const * provider, int level, wfd_settings * settings) = 0; }; class MockConfigBuilder: public IConfigBuilder @@ -31,6 +32,7 @@ public: MOCK_METHOD1(setServerDocumentRoot, void (char const * document_root)); MOCK_METHOD2(addAuthProvider, bool (char const * provider, wfd_settings * settings)); MOCK_METHOD2(addFilesystem, bool (char const * name, char const * mountpoint)); + MOCK_METHOD3(setLogger, bool (char const * provider, int level, wfd_settings * settings)); struct wfd_config_builder getBuilder(); }; diff --git a/test/mock_settings.cc b/test/mock_settings.cc index cc66555..3cc36ff 100644 --- a/test/mock_settings.cc +++ b/test/mock_settings.cc @@ -7,25 +7,67 @@ using webfused_test::ISettings; static ISettings * wfd_mock_settings = nullptr; extern char const * -__real_wfd_settings_get( +__real_wfd_settings_get_string( + struct wfd_settings * settings, + char const * key); + +extern char const * +__real_wfd_settings_get_string_or_default( + struct wfd_settings * settings, + char const * key, + char const * default_value); + +extern bool +__real_wfd_settings_get_bool( struct wfd_settings * settings, char const * key); char const * -__wrap_wfd_settings_get( +__wrap_wfd_settings_get_string( struct wfd_settings * settings, char const * key) { if (nullptr == wfd_mock_settings) { - return __real_wfd_settings_get(settings, key); + return __real_wfd_settings_get_string(settings, key); } else { - return wfd_mock_settings->get(key); + return wfd_mock_settings->getString(key); } } +char const * +__wrap_wfd_settings_get_string_or_default( + struct wfd_settings * settings, + char const * key, + char const * default_value) +{ + if (nullptr == wfd_mock_settings) + { + return __real_wfd_settings_get_string_or_default( + settings, key, default_value); + } + else + { + return wfd_mock_settings->getStringOrDefault(key, default_value); + } +} + +bool +__wrap_wfd_settings_get_bool( + struct wfd_settings * settings, + char const * key) +{ + if (nullptr == wfd_mock_settings) + { + return __real_wfd_settings_get_bool(settings, key); + } + else + { + return wfd_mock_settings->getBool(key); + } +} } diff --git a/test/mock_settings.hpp b/test/mock_settings.hpp index 016a8f4..f3d8692 100644 --- a/test/mock_settings.hpp +++ b/test/mock_settings.hpp @@ -11,7 +11,9 @@ class ISettings { public: virtual ~ISettings() = default; - virtual char const * get(char const * key) = 0; + virtual char const * getString(char const * key) = 0; + virtual char const * getStringOrDefault(char const * key, char const * default_value) = 0; + virtual bool getBool(char const * key) = 0; }; class MockSettings: public ISettings @@ -19,7 +21,9 @@ class MockSettings: public ISettings public: MockSettings(); ~MockSettings() override; - MOCK_METHOD1(get, char const * (char const * key)); + MOCK_METHOD1(getString, char const * (char const * key)); + MOCK_METHOD2(getStringOrDefault, char const * (char const * key, char const * default_value)); + MOCK_METHOD1(getBool, bool (char const * key)); }; } diff --git a/test/test_config.cc b/test/test_config.cc index 14df533..4fe66be 100644 --- a/test/test_config.cc +++ b/test/test_config.cc @@ -38,7 +38,7 @@ TEST(config, auth_config) wfd_config_builder builder = wfd_config_get_builder(config); MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); bool success = wfd_config_builder_add_auth_provider(builder, "file", nullptr); ASSERT_TRUE(success); @@ -54,7 +54,7 @@ TEST(config, auth_config_failed_to_add_second_provider) wfd_config_builder builder = wfd_config_get_builder(config); MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); bool success = wfd_config_builder_add_auth_provider(builder, "file", nullptr); ASSERT_TRUE(success); @@ -88,5 +88,18 @@ TEST(config, add_filesystem) bool success = wfd_config_builder_add_filesystem(builder, "test", "/tmp/test"); ASSERT_TRUE(success); + wfd_config_dispose(config); +} + +TEST(config, set_logger) +{ + wfd_config * config = wfd_config_create(); + ASSERT_NE(nullptr, config); + + wfd_config_builder builder = wfd_config_get_builder(config); + + bool success = wfd_config_builder_set_logger(builder, "stderr", WFD_LOGLEVEL_ALL, nullptr); + ASSERT_TRUE(success); + wfd_config_dispose(config); } \ No newline at end of file diff --git a/test/test_config_factory.cc b/test/test_config_factory.cc index 374af8c..58d2f7d 100644 --- a/test/test_config_factory.cc +++ b/test/test_config_factory.cc @@ -17,6 +17,7 @@ using ::webfused_test::MockConfigBuilder; TEST(config, is_loadable) { StrictMock builder; + EXPECT_CALL(builder, setLogger(_,_,_)).Times(1).WillOnce(Return(true)); EXPECT_CALL(builder, setServerVhostname(StrEq("localhost"))).Times(1); EXPECT_CALL(builder, setServerPort(8080)).Times(1); EXPECT_CALL(builder, addAuthProvider(_, _)).Times(1).WillOnce(Return(true)); @@ -433,3 +434,107 @@ TEST(config, filesystems_failed_missing_mountpoint) bool result = wfd_config_load_string(builder.getBuilder(), config_text); ASSERT_FALSE(result); } + +TEST(config, log) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, setLogger(_, _, _)).Times(1).WillOnce(Return(true)); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "log:\n" + "{\n" + " provider = \"stderr\"\n" + " level = \"all\"\n" + "}\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_TRUE(result); +} + +TEST(config, log_fail_set_logger) +{ + MockLogger logger; + EXPECT_CALL(logger, log(_, _, _)).Times(0); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, setLogger(_, _, _)).Times(1).WillOnce(Return(false)); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "log:\n" + "{\n" + " provider = \"stderr\"\n" + " level = \"all\"\n" + "}\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_FALSE(result); +} + +TEST(config, log_fail_missing_provider) +{ + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, setLogger(_, _, _)).Times(0); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "log:\n" + "{\n" + " level = \"all\"\n" + "}\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_FALSE(result); +} + +TEST(config, log_fail_missing_level) +{ + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, setLogger(_, _, _)).Times(0); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "log:\n" + "{\n" + " provider = \"stderr\"\n" + " level = \"fancy\"\n" + "}\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_FALSE(result); +} + +TEST(config, log_fail_invalid_level) +{ + MockLogger logger; + EXPECT_CALL(logger, log(WFD_LOGLEVEL_ERROR, _, _)).Times(1); + EXPECT_CALL(logger, onclose()).Times(1); + + StrictMock builder; + EXPECT_CALL(builder, setLogger(_, _, _)).Times(0); + + char const config_text[] = + "version = { major = 1, minor = 0 }\n" + "log:\n" + "{\n" + " provider = \"stderr\"\n" + "}\n" + ; + bool result = wfd_config_load_string(builder.getBuilder(), config_text); + ASSERT_FALSE(result); +} + diff --git a/test/test_file_authenticator.cc b/test/test_file_authenticator.cc index 451b4fa..ff3293e 100644 --- a/test/test_file_authenticator.cc +++ b/test/test_file_authenticator.cc @@ -17,7 +17,7 @@ using ::testing::StrEq; TEST(file_authenticator, create) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; bool success = wfd_file_authenticator_create(nullptr, &authenticator); @@ -29,7 +29,7 @@ TEST(file_authenticator, create) TEST(file_authenticator, create_fail_missing_file) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return(nullptr)); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return(nullptr)); wfd_authenticator authenticator; bool success = wfd_file_authenticator_create(nullptr, &authenticator); @@ -39,7 +39,7 @@ TEST(file_authenticator, create_fail_missing_file) TEST(file_authenticator, create_via_factory) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; bool success = wfd_authenticator_create("file", nullptr, &authenticator); @@ -51,7 +51,7 @@ TEST(file_authenticator, create_via_factory) TEST(file_authenticator, authenticate) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; bool success = wfd_file_authenticator_create(nullptr, &authenticator); @@ -70,7 +70,7 @@ TEST(file_authenticator, authenticate) TEST(file_authenticator, authenticate_fail_wrong_passwd) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; bool success = wfd_file_authenticator_create(nullptr, &authenticator); @@ -89,7 +89,7 @@ TEST(file_authenticator, authenticate_fail_wrong_passwd) TEST(file_authenticator, authenticate_fail_no_passwd_file) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("unknown_passwd.json")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("unknown_passwd.json")); wfd_authenticator authenticator; bool success = wfd_file_authenticator_create(nullptr, &authenticator); @@ -108,7 +108,7 @@ TEST(file_authenticator, authenticate_fail_no_passwd_file) TEST(file_authenticator, authenticate_fail_missing_username) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; bool success = wfd_file_authenticator_create(nullptr, &authenticator); @@ -127,7 +127,7 @@ TEST(file_authenticator, authenticate_fail_missing_username) TEST(file_authenticator, authenticate_fail_missing_password) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("test_passwd.json")); wfd_authenticator authenticator; bool success = wfd_file_authenticator_create(nullptr, &authenticator); @@ -146,7 +146,7 @@ TEST(file_authenticator, authenticate_fail_missing_password) TEST(file_authenticator, get_type) { MockSettings settings; - EXPECT_CALL(settings, get(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); + EXPECT_CALL(settings, getString(StrEq("file"))).Times(1).WillOnce(Return("/any/path")); wfd_authenticator authenticator; bool success = wfd_file_authenticator_create(nullptr, &authenticator); diff --git a/test/test_log.cc b/test/test_log.cc index 86423bb..331d0eb 100644 --- a/test/test_log.cc +++ b/test/test_log.cc @@ -108,4 +108,63 @@ TEST(log, omit_onclose_if_nullptr) TEST(log, default_log) { WFD_ERROR("trigger log"); +} + +TEST(log, loglevel_parse) +{ + int level; + + ASSERT_TRUE(wfd_log_level_parse("fatal", &level)); + ASSERT_EQ(WFD_LOGLEVEL_FATAL, level); + ASSERT_TRUE(wfd_log_level_parse("FATAL", &level)); + ASSERT_EQ(WFD_LOGLEVEL_FATAL, level); + + ASSERT_TRUE(wfd_log_level_parse("error", &level)); + ASSERT_EQ(WFD_LOGLEVEL_ERROR, level); + ASSERT_TRUE(wfd_log_level_parse("ERROR", &level)); + ASSERT_EQ(WFD_LOGLEVEL_ERROR, level); + + ASSERT_TRUE(wfd_log_level_parse("warn", &level)); + ASSERT_EQ(WFD_LOGLEVEL_WARN, level); + ASSERT_TRUE(wfd_log_level_parse("WARN", &level)); + ASSERT_EQ(WFD_LOGLEVEL_WARN, level); + ASSERT_TRUE(wfd_log_level_parse("warning", &level)); + ASSERT_EQ(WFD_LOGLEVEL_WARN, level); + ASSERT_TRUE(wfd_log_level_parse("WARNING", &level)); + ASSERT_EQ(WFD_LOGLEVEL_WARN, level); + + ASSERT_TRUE(wfd_log_level_parse("info", &level)); + ASSERT_EQ(WFD_LOGLEVEL_INFO, level); + ASSERT_TRUE(wfd_log_level_parse("INFO", &level)); + ASSERT_EQ(WFD_LOGLEVEL_INFO, level); + + ASSERT_TRUE(wfd_log_level_parse("debug", &level)); + ASSERT_EQ(WFD_LOGLEVEL_DEBUG, level); + ASSERT_TRUE(wfd_log_level_parse("DEBUG", &level)); + ASSERT_EQ(WFD_LOGLEVEL_DEBUG, level); + + ASSERT_FALSE(wfd_log_level_parse("", &level)); + + ASSERT_TRUE(wfd_log_level_parse("all", &level)); + ASSERT_EQ(WFD_LOGLEVEL_ALL, level); + ASSERT_TRUE(wfd_log_level_parse("ALL", &level)); + ASSERT_EQ(WFD_LOGLEVEL_ALL, level); + + ASSERT_TRUE(wfd_log_level_parse("none", &level)); + ASSERT_EQ(WFD_LOGLEVEL_NONE, level); + ASSERT_TRUE(wfd_log_level_parse("NONE", &level)); + ASSERT_EQ(WFD_LOGLEVEL_NONE, level); + +} + +TEST(log, log_level_tostring) +{ + ASSERT_STREQ("none", wfd_log_level_tostring(WFD_LOGLEVEL_NONE)); + ASSERT_STREQ("fatal", wfd_log_level_tostring(WFD_LOGLEVEL_FATAL)); + ASSERT_STREQ("error", wfd_log_level_tostring(WFD_LOGLEVEL_ERROR)); + ASSERT_STREQ("warn", wfd_log_level_tostring(WFD_LOGLEVEL_WARN)); + ASSERT_STREQ("info", wfd_log_level_tostring(WFD_LOGLEVEL_INFO)); + ASSERT_STREQ("debug", wfd_log_level_tostring(WFD_LOGLEVEL_DEBUG)); + ASSERT_STREQ("all", wfd_log_level_tostring(WFD_LOGLEVEL_ALL)); + ASSERT_STREQ("", wfd_log_level_tostring(42)); } \ No newline at end of file diff --git a/test/test_log_manager.cc b/test/test_log_manager.cc new file mode 100644 index 0000000..35ce8bb --- /dev/null +++ b/test/test_log_manager.cc @@ -0,0 +1,10 @@ +#include "webfused/log/manager.h" +#include "webfused/log/log.h" + +#include +#include + +TEST(log_manager, set_logger_fail_unknown_provider) +{ + ASSERT_FALSE(wfd_log_manager_set_logger("unknown", WFD_LOGLEVEL_ALL, NULL)); +} diff --git a/test/test_settings.cc b/test/test_settings.cc index 730a059..3f6b1a5 100644 --- a/test/test_settings.cc +++ b/test/test_settings.cc @@ -3,7 +3,7 @@ #include "webfused/config/settings.h" #include -TEST(settings, settings) +TEST(settings, get_string) { char const settings_text[] = "settings:\n" @@ -22,9 +22,68 @@ TEST(settings, settings) wfd_settings settings; wfd_settings_init(&settings, setting); - ASSERT_STREQ("some.string", wfd_settings_get(&settings, "string_value")); - ASSERT_EQ(nullptr, wfd_settings_get(&settings, "int_value")); - ASSERT_EQ(nullptr, wfd_settings_get(&settings, "invalid_value")); + ASSERT_STREQ("some.string", wfd_settings_get_string(&settings, "string_value")); + ASSERT_EQ(nullptr, wfd_settings_get_string(&settings, "int_value")); + ASSERT_EQ(nullptr, wfd_settings_get_string(&settings, "invalid_value")); + ASSERT_EQ(nullptr, wfd_settings_get_string(NULL, "invalid_value")); + + wfd_settings_cleanup(&settings); + config_destroy(&config); +} + +TEST(settings, get_string_or_default) +{ + char const settings_text[] = + "settings:\n" + "{\n" + " string_value = \"some.string\"\n" + " int_value = 42\n" + "}\n" + ; + config_t config; + config_init(&config); + int rc = config_read_string(&config, settings_text); + ASSERT_TRUE(CONFIG_TRUE == rc); + + config_setting_t * setting = config_lookup(&config, "settings"); + ASSERT_NE(nullptr, setting); + + wfd_settings settings; + wfd_settings_init(&settings, setting); + ASSERT_STREQ("some.string", wfd_settings_get_string_or_default(&settings, "string_value", "default")); + ASSERT_STREQ("default", wfd_settings_get_string_or_default(&settings, "int_value", "default")); + ASSERT_STREQ("default", wfd_settings_get_string_or_default(&settings, "invalid_value", "default")); + ASSERT_STREQ("default", wfd_settings_get_string_or_default(NULL, "invalid_value", "default")); + + wfd_settings_cleanup(&settings); + config_destroy(&config); +} + +TEST(settings, get_bool) +{ + char const settings_text[] = + "settings:\n" + "{\n" + " true_value = true\n" + " false_value = false\n" + " int_value = 42\n" + "}\n" + ; + config_t config; + config_init(&config); + int rc = config_read_string(&config, settings_text); + ASSERT_TRUE(CONFIG_TRUE == rc); + + config_setting_t * setting = config_lookup(&config, "settings"); + ASSERT_NE(nullptr, setting); + + wfd_settings settings; + wfd_settings_init(&settings, setting); + ASSERT_TRUE(wfd_settings_get_bool(&settings, "true_value")); + ASSERT_FALSE(wfd_settings_get_bool(&settings, "false_value")); + ASSERT_FALSE(wfd_settings_get_bool(&settings, "int_value")); + ASSERT_FALSE(wfd_settings_get_bool(&settings, "invalid_value")); + ASSERT_FALSE(wfd_settings_get_bool(NULL, "invalid_value")); wfd_settings_cleanup(&settings); config_destroy(&config); diff --git a/test/test_stderr_logger.cc b/test/test_stderr_logger.cc new file mode 100644 index 0000000..923bf59 --- /dev/null +++ b/test/test_stderr_logger.cc @@ -0,0 +1,27 @@ +#include "webfused/log/stderr_logger.h" +#include "webfused/log/manager.h" +#include "webfused/log/logger.h" +#include "webfused/log/log.h" + +#include +#include + +TEST(stderr_logger, init) +{ + ASSERT_TRUE(wfd_stderr_logger_init(WFD_LOGLEVEL_ALL, NULL)); + wfd_logger_close(); +} + +TEST(stderr_logger, init_via_manager) +{ + ASSERT_TRUE(wfd_log_manager_set_logger("stderr", WFD_LOGLEVEL_ALL, NULL)); + wfd_logger_close(); +} + +TEST(stderr_logger, log) +{ + ASSERT_TRUE(wfd_stderr_logger_init(WFD_LOGLEVEL_ALL, NULL)); + WFD_INFO("some information"); + + wfd_logger_close(); +} \ No newline at end of file diff --git a/test/test_syslog_logger.cc b/test/test_syslog_logger.cc new file mode 100644 index 0000000..1d04740 --- /dev/null +++ b/test/test_syslog_logger.cc @@ -0,0 +1,45 @@ +#include "webfused/log/syslog_logger.h" +#include "webfused/log/manager.h" +#include "webfused/log/logger.h" +#include "webfused/log/log.h" + +#include "mock_settings.hpp" + +#include +#include + +using ::webfused_test::MockSettings; +using ::testing::StrEq; +using ::testing::_; +using ::testing::Return; + +TEST(syslog_logger, init) +{ + ASSERT_TRUE(wfd_syslog_logger_init(WFD_LOGLEVEL_ALL, NULL)); + wfd_logger_close(); +} + +TEST(syslog_logger, init_fail_invalid_facility) +{ + MockSettings settings; + EXPECT_CALL(settings, getStringOrDefault(StrEq("ident"), _)).Times(1).WillOnce(Return("webfused_test")); + EXPECT_CALL(settings, getStringOrDefault(StrEq("facility"), _)).Times(1).WillOnce(Return("invalid")); + EXPECT_CALL(settings, getBool(StrEq("log_pid"))).Times(1).WillOnce(Return(false)); + + wfd_settings * fake_settings = reinterpret_cast(0xDEADBEEF); + ASSERT_FALSE(wfd_syslog_logger_init(WFD_LOGLEVEL_ALL, fake_settings)); +} + +TEST(syslog_logger, init_via_manager) +{ + ASSERT_TRUE(wfd_log_manager_set_logger("syslog", WFD_LOGLEVEL_ALL, NULL)); + wfd_logger_close(); +} + +TEST(syslog_logger, log) +{ + ASSERT_TRUE(wfd_syslog_logger_init(WFD_LOGLEVEL_ALL, NULL)); + WFD_INFO("some information"); + + wfd_logger_close(); +} \ No newline at end of file From 1cd1b1ddff51e94a768ffc70e3e76b8277c1a600 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Wed, 18 Mar 2020 18:00:53 +0100 Subject: [PATCH 34/36] added basic tests for daemon --- CMakeLists.txt | 2 ++ src/webfused/daemon.c | 2 ++ test/test_daemon.cc | 68 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 test/test_daemon.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index c2bcbd4..3b84d16 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,6 +129,7 @@ add_executable(alltests test/test_log_manager.cc test/test_stderr_logger.cc test/test_syslog_logger.cc + test/test_daemon.cc ) target_include_directories(alltests PRIVATE @@ -180,6 +181,7 @@ add_custom_target(coverage COMMAND lcov -a coverage/lcov_base.info -a coverage/lcov.info --output-file coverage/lcov.info --rc lcov_branch_coverage=1 COMMAND lcov --remove coverage/lcov.info '/usr/*' --output-file coverage/lcov.info --rc lcov_branch_coverage=1 COMMAND lcov --remove coverage/lcov.info '*/test/*' --output-file coverage/lcov.info --rc lcov_branch_coverage=1 + COMMAND lcov --remove coverage/lcov.info '*/main.c' --output-file coverage/lcov.info --rc lcov_branch_coverage=1 ) add_dependencies(coverage alltests) diff --git a/src/webfused/daemon.c b/src/webfused/daemon.c index b7786cd..8911777 100644 --- a/src/webfused/daemon.c +++ b/src/webfused/daemon.c @@ -56,6 +56,7 @@ static int parse_arguments(int argc, char * argv[], struct args * args) bool result = EXIT_SUCCESS; bool finished = false; + optind = 0; while ((!finished) && (EXIT_SUCCESS == result)) { int option_index = 0; @@ -144,6 +145,7 @@ int wfd_daemon_run(int argc, char * argv[]) wfd_logger_close(); free(args.config_file); + shutdown_requested = false; return result; } diff --git a/test/test_daemon.cc b/test/test_daemon.cc new file mode 100644 index 0000000..a0ed0c5 --- /dev/null +++ b/test/test_daemon.cc @@ -0,0 +1,68 @@ +#include "webfused/daemon.h" + +#include +#include +#include +#include + +TEST(daemon, print_usage) +{ + char argv0[] = "daemon"; + char argv1[] = "--help"; + char * argv[] = { argv0, argv1, NULL}; + + int exit_code = wfd_daemon_run(2, argv); + ASSERT_EQ(EXIT_SUCCESS, exit_code); +} + +TEST(daemon, print_usage_short) +{ + char argv0[] = "daemon"; + char argv1[] = "-h"; + char * argv[] = { argv0, argv1, NULL}; + + int exit_code = wfd_daemon_run(2, argv); + ASSERT_EQ(EXIT_SUCCESS, exit_code); +} + +TEST(daemon, fail_invalid_argument) +{ + char argv0[] = "daemon"; + char argv1[] = "-x"; + char * argv[] = { argv0, argv1, NULL}; + + int exit_code = wfd_daemon_run(2, argv); + ASSERT_EQ(EXIT_FAILURE, exit_code); +} + +TEST(daemon, fail_invalid_config_file) +{ + char argv0[] = "daemon"; + char argv1[] = "-f"; + char argv2[] = "invalid.conf"; + char * argv[] = { argv0, argv1, argv2, NULL}; + + int exit_code = wfd_daemon_run(3, argv); + ASSERT_EQ(EXIT_FAILURE, exit_code); +} + +void defered_raise() +{ + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + raise(SIGINT); +} + +TEST(daemon, run) +{ + char argv0[] = "daemon"; + char argv1[] = "-f"; + char argv2[] = "webfused.conf"; + char * argv[] = { argv0, argv1, argv2, NULL}; + + std::thread thread(defered_raise); + + int exit_code = wfd_daemon_run(3, argv); + ASSERT_EQ(EXIT_SUCCESS, exit_code); + + thread.join(); +} From b37e95f7249574deda89ec385e65e3fbf1dff763 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Wed, 18 Mar 2020 18:49:52 +0100 Subject: [PATCH 35/36] added config file documentation --- README.md | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 139 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3164b7a..f258f3d 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,145 @@ To install dependecies, see below. cd build cmake .. make - ./webfused -m test --port=4711 + ./webfused -f webfused.conf + +## Config file + +``` +version = { major = 1, minor = 0 } + +server: +{ + vhost_name = "localhost" + port = 8080 + + tls: + { + certificate = "/etc/webfused/cert.pem" + + key = "/etc/webfused/key.pem" + } + + document_root = "/var/www" +} + +authentication: +{ + # name of authenticaton provider + provider = "file" + + settings: + { + file = "/etc/webfused/passwd" + } +} + +filesystems: +( + {name = "test", mount_point = "/tmp/webfused" } +) + +log: +{ + provider: "syslog" + level: "warning" + settings: + { + ident = "webfused" + facility = "daemon" + log_pid = true + } +} +``` + +### Version + +The version sections specifies the schema version of the config file. +Currently, there is only one schema version defined: 1.0 + +### Server + +| Setting | Type | Default value | Description | +| ------------- | ------ | ------------- | ------------------------ | +| vhostname | string | localhost | Name of the virtual host | +| port | int | 8080 | Port number of server | +| document_root | string | *-empty-* | Path of HTTP files | +| tls | object | *-empty-* | see below | + +When *document_root* is omitted, no HTTP files are served. + +#### TLS + +| Setting | Type | Default value | Description | +| ----------- | ------ | ------------- | ------------------------------------------- | +| certificate | string | *-empty-* | Path to servers own certificate (.pem file) | +| key | string | *-empty-* | Path to servers own private key (.pem file) | + +TLS is only activated, when both, *certificate* and *key* are specified. +Otherwise, plain websockes without TLS are used. + +### Authentication + +| Setting | Type | Default value | Description | +| -------- | ------ | ------------- | ----------------------------------------------- | +| provider | string | *-required-* | Name of the authentication provider (see below) | +| settings | object | *-empty-* | Provider specific settings (see below) + +Currently, only one provider is specified: + +- *file*: file based authentication + +### File Authenticaton Provider + +Allows authentication against a file containing username and password. + +| Setting | Type | Default value | Description | +| -------- | ------ | ------------- | ------------------------------- | +| file | string | *-empty-* | Path to the authentication file | + +### Filesystems + +Contains a list of file systems that can be provided by webfuse providers. + +| Setting | Type | Default value | Description | +| ----------- | ------ | ------------- | ---------------------------------- | +| name | string | *-required-* | Name of the filesystem | +| mount_point | string | *-required-* | Local path to mount the filesystem | + +### Log + +| Setting | Type | Default value | Description | +| ----------- | ------ | ------------- | -------------------------------------- | +| provider | string | *-required-* | Name of log provider (see below) | +| level | string | *-required-* | Log level (see below) | +| settings | object | *-empty-* | Provider specific settings (see below) | + +The following log levels are supported: + +- *none*: diabled logging +- *fatal*: log only fatal errors +- *error*: log all kind of errors +- *warn*: log errors and warnings +- *info*: log info messages, warnings and errors +- *debug*: log debug and info messages as well as warnings and errors +- *all*: log all kind of messages + +Currently, the following providers are available: + +- *stderr*: logs to console error output +- *syslog*: logs to syslog + +#### Stderr Logger + +This logger does not provide any settings. + +#### Syslog Logger + +| Setting | Type | Default value | Description | +| ----------- | ------ | ------------- | ------------------------------------------ | +| ident | string | webfused | Syslog ident (see syslog documentation) | +| facility | string | daemon | Syslog facility (see syslog documentation) | +| log_pid | bool | false | Add process ID to log messages | ## Dependencies @@ -52,7 +190,6 @@ To install libfuse, meson is needed. Please refer to [meson quick guide](https:/ make sudo make install - #### jansson wget https://github.com/akheron/jansson/archive/v2.12.tar.gz -O jansson.tar.gz From 46ba61e97db812a512dcccfa00e6b40247ad5e02 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Wed, 18 Mar 2020 19:14:02 +0100 Subject: [PATCH 36/36] allow specification of multiple authenticators --- README.md | 14 +++---- etc/webfused.conf | 12 +++--- src/webfused/config/factory.c | 70 ++++++++++++++++++++++------------- test/test_config_factory.cc | 36 +++++++++++------- 4 files changed, 80 insertions(+), 52 deletions(-) diff --git a/README.md b/README.md index f258f3d..e5b8852 100644 --- a/README.md +++ b/README.md @@ -37,15 +37,15 @@ server: } authentication: -{ - # name of authenticaton provider - provider = "file" - - settings: +( { - file = "/etc/webfused/passwd" + provider = "file" + settings: + { + file = "/etc/webfused/passwd" + } } -} +) filesystems: ( diff --git a/etc/webfused.conf b/etc/webfused.conf index 3f28976..eb2df66 100644 --- a/etc/webfused.conf +++ b/etc/webfused.conf @@ -17,13 +17,15 @@ server: } authentication: -{ - provider = "file" - settings: +( { - file = "/etc/webfused/passwd" + provider = "file" + settings: + { + file = "/etc/webfused/passwd" + } } -} +) filesystems: ( diff --git a/src/webfused/config/factory.c b/src/webfused/config/factory.c index ddd4ff0..794b67c 100644 --- a/src/webfused/config/factory.c +++ b/src/webfused/config/factory.c @@ -152,43 +152,61 @@ wfd_config_read_server( } static bool -wfd_config_read_authentication( - config_t * config, +wfd_config_read_authenticator( + config_setting_t * authenticator, struct wfd_config_builder builder) { - bool result = true; + bool result = (NULL != authenticator); - bool hasAuthentication = (NULL != config_lookup(config, "authentication")); - if (hasAuthentication) + char const * provider_name = NULL; + if (result) { - char const * provider_name = NULL; + int rc = config_setting_lookup_string(authenticator, "provider", &provider_name); + if (CONFIG_TRUE != rc) { - int rc = config_lookup_string(config, "authentication.provider", &provider_name); - if (CONFIG_TRUE != rc) - { - WFD_ERROR("missing authentication provider"); - result = false; - } + WFD_ERROR("missing authentication provider"); + result = false; } + } - struct config_setting_t * settings = NULL; - if (result) + struct config_setting_t * settings = NULL; + if (result) + { + settings = config_setting_lookup(authenticator, "settings"); + if (NULL == settings) { - settings = config_lookup(config, "authentication.settings"); - if (NULL == settings) - { - WFD_ERROR("missing authentication settings"); - result = false; - } + WFD_ERROR("missing authentication settings"); + result = false; } + } - if (result) - { - struct wfd_settings auth_settings; - wfd_settings_init(&auth_settings, settings); + if (result) + { + struct wfd_settings auth_settings; + wfd_settings_init(&auth_settings, settings); + + result = wfd_config_builder_add_auth_provider(builder, provider_name, &auth_settings); + wfd_settings_cleanup(&auth_settings); + } - result = wfd_config_builder_add_auth_provider(builder, provider_name, &auth_settings); - wfd_settings_cleanup(&auth_settings); + return result; +} + +static bool +wfd_config_read_authentication( + config_t * config, + struct wfd_config_builder builder) +{ + bool result = true; + + config_setting_t * authentication = config_lookup(config, "authentication"); + if (NULL != authentication) + { + int length = config_setting_length(authentication); + for (int i = 0; (result) && (i < length); i++) + { + config_setting_t * authenticator = config_setting_get_elem(authentication, i); + result = wfd_config_read_authenticator(authenticator, builder); } } diff --git a/test/test_config_factory.cc b/test/test_config_factory.cc index 58d2f7d..48a6de8 100644 --- a/test/test_config_factory.cc +++ b/test/test_config_factory.cc @@ -268,10 +268,12 @@ TEST(config, authentication) char const config_text[] = "version = { major = 1, minor = 0 }\n" "authentication:\n" - "{\n" - " provider = \"test\"\n" - " settings: { }\n" - "}\n" + "(\n" + " {\n" + " provider = \"test\"\n" + " settings: { }\n" + " }\n" + ")\n" ; bool result = wfd_config_load_string(builder.getBuilder(), config_text); ASSERT_TRUE(result); @@ -289,10 +291,12 @@ TEST(config, failed_create_authenticator) char const config_text[] = "version = { major = 1, minor = 0 }\n" "authentication:\n" - "{\n" - " provider = \"test\"\n" - " settings: { }\n" - "}\n" + "(\n" + " {\n" + " provider = \"test\"\n" + " settings: { }\n" + " }\n" + ")\n" ; bool result = wfd_config_load_string(builder.getBuilder(), config_text); ASSERT_FALSE(result); @@ -309,9 +313,11 @@ TEST(config, failed_missing_auth_provider) char const config_text[] = "version = { major = 1, minor = 0 }\n" "authentication:\n" - "{\n" - " settings: { }\n" - "}\n" + "(\n" + " {\n" + " settings: { }\n" + " }\n" + ")\n" ; bool result = wfd_config_load_string(builder.getBuilder(), config_text); ASSERT_FALSE(result); @@ -328,9 +334,11 @@ TEST(config, failed_missing_auth_settings) char const config_text[] = "version = { major = 1, minor = 0 }\n" "authentication:\n" - "{\n" - " provider = \"test\"\n" - "}\n" + "(\n" + " {\n" + " provider = \"test\"\n" + " }\n" + ")\n" ; bool result = wfd_config_load_string(builder.getBuilder(), config_text); ASSERT_FALSE(result);