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); +}