From aec9fdd08624196245c9cde66597adc1dc24c605 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 10 Mar 2019 00:06:13 +0100 Subject: [PATCH 01/18] makes wsfs_server_config opaque --- example/daemon/main.c | 45 +++++++---------- include/wsfs/adapter/server_config.h | 42 ++++++++++------ lib/wsfs/adapter/server.c | 2 +- lib/wsfs/adapter/server_config.c | 67 ++++++++++++++++++++++++- lib/wsfs/adapter/server_config_intern.h | 35 +++++++++++++ test/test_server.cc | 7 +-- 6 files changed, 150 insertions(+), 48 deletions(-) create mode 100644 lib/wsfs/adapter/server_config_intern.h diff --git a/example/daemon/main.c b/example/daemon/main.c index 0964674..387e231 100644 --- a/example/daemon/main.c +++ b/example/daemon/main.c @@ -12,7 +12,7 @@ struct args { - struct wsfs_server_config config; + struct wsfs_server_config * config; bool show_help; }; @@ -53,6 +53,7 @@ static int parse_arguments(int argc, char * argv[], struct args * args) bool result = EXIT_SUCCESS; bool finished = false; + bool has_mountpoint = false; while ((!finished) && (EXIT_SUCCESS == result)) { int option_index = 0; @@ -68,27 +69,23 @@ static int parse_arguments(int argc, char * argv[], struct args * args) finished = true; break; case 'm': - free(args->config.mount_point); - args->config.mount_point = strdup(optarg); + wsfs_server_config_set_mountpoint(args->config, optarg); + has_mountpoint = true; break; case 'd': - free(args->config.document_root); - args->config.document_root = strdup(optarg); + wsfs_server_config_set_documentroot(args->config, optarg); break; case 'c': - free(args->config.cert_path); - args->config.cert_path = strdup(optarg); + wsfs_server_config_set_certpath(args->config, optarg); break; case 'k': - free(args->config.key_path); - args->config.key_path = strdup(optarg); + wsfs_server_config_set_keypath(args->config, optarg); break; case 'n': - free(args->config.vhost_name); - args->config.vhost_name = strdup(optarg); + wsfs_server_config_set_vhostname(args->config, optarg); break; case 'p': - args->config.port = atoi(optarg); + wsfs_server_config_set_port(args->config, atoi(optarg)); break; default: fprintf(stderr, "error: unknown argument\n"); @@ -99,7 +96,7 @@ static int parse_arguments(int argc, char * argv[], struct args * args) if ((EXIT_SUCCESS == result) && (!args->show_help)) { - if (NULL == args->config.mount_point) + if (!has_mountpoint) { fprintf(stderr, "error: missing mount point\n"); result = EXIT_FAILURE; @@ -123,26 +120,18 @@ static void on_interrupt(int signal_id) int main(int argc, char * argv[]) { - struct args args = - { - .config = - { - .mount_point = NULL, - .document_root = NULL, - .cert_path = NULL, - .key_path = NULL, - .vhost_name = strdup("localhost"), - .port = 8080, - }, - .show_help = 0 - }; + struct args args; + args.config = wsfs_server_config_create(); + wsfs_server_config_set_vhostname(args.config, "localhost"); + wsfs_server_config_set_port(args.config, 8080); + args.show_help = false; int result = parse_arguments(argc, argv, &args); if (!args.show_help) { signal(SIGINT, on_interrupt); - server = wsfs_server_create(&args.config); + server = wsfs_server_create(args.config); if (NULL != server) { wsfs_server_run(server); @@ -159,7 +148,7 @@ int main(int argc, char * argv[]) show_help(); } - wsfs_server_config_cleanup(&args.config); + wsfs_server_config_dispose(args.config); return result; } diff --git a/include/wsfs/adapter/server_config.h b/include/wsfs/adapter/server_config.h index 27c3bbe..b6d9b7e 100644 --- a/include/wsfs/adapter/server_config.h +++ b/include/wsfs/adapter/server_config.h @@ -3,30 +3,42 @@ #include "wsfs/adapter/api.h" -struct wsfs_server_config -{ - char * mount_point; - char * document_root; - char * key_path; - char * cert_path; - char * vhost_name; - int port; -}; +struct wsfs_server_config; #ifdef __cplusplus extern "C" { #endif -extern WSFSA_API void wsfs_server_config_init( +extern WSFSA_API struct wsfs_server_config * wsfs_server_config_create(void); + +extern WSFSA_API void wsfs_server_config_dispose( struct wsfs_server_config * config); -extern WSFSA_API void wsfs_server_config_cleanup( - struct wsfs_server_config * config); -extern WSFSA_API void wsfs_server_config_clone( - struct wsfs_server_config * config, - struct wsfs_server_config * clone); +extern WSFSA_API void wsfs_server_config_set_mountpoint( + struct wsfs_server_config * config, + char const * mount_point); + +extern WSFSA_API void wsfs_server_config_set_documentroot( + struct wsfs_server_config * config, + char const * document_root); + +extern WSFSA_API void wsfs_server_config_set_keypath( + struct wsfs_server_config * config, + char const * key_path); + +extern WSFSA_API void wsfs_server_config_set_certpath( + struct wsfs_server_config * config, + char const * cert_path); + +extern WSFSA_API void wsfs_server_config_set_vhostname( + struct wsfs_server_config * config, + char const * vhost_name); + +extern WSFSA_API void wsfs_server_config_set_port( + struct wsfs_server_config * config, + int port); #ifdef __cplusplus } diff --git a/lib/wsfs/adapter/server.c b/lib/wsfs/adapter/server.c index 2590f0d..31da29d 100644 --- a/lib/wsfs/adapter/server.c +++ b/lib/wsfs/adapter/server.c @@ -4,7 +4,7 @@ #include #include -#include "wsfs/adapter/server_config.h" +#include "wsfs/adapter/server_config_intern.h" #include "wsfs/adapter/server_protocol_intern.h" #define WSFS_DISABLE_LWS_LOG 0 diff --git a/lib/wsfs/adapter/server_config.c b/lib/wsfs/adapter/server_config.c index 8f88a17..13e1f37 100644 --- a/lib/wsfs/adapter/server_config.c +++ b/lib/wsfs/adapter/server_config.c @@ -1,4 +1,4 @@ -#include "wsfs/adapter/server_config.h" +#include "wsfs/adapter/server_config_intern.h" #include #include @@ -43,3 +43,68 @@ void wsfs_server_config_clone( clone->vhost_name = wsfs_server_config_strdup(config->vhost_name); clone->port = config->port; } + +struct wsfs_server_config * wsfs_server_config_create(void) +{ + struct wsfs_server_config * config = malloc(sizeof(struct wsfs_server_config)); + if (NULL != config) + { + wsfs_server_config_init(config); + } + + return config; +} + +void wsfs_server_config_dispose( + struct wsfs_server_config * config) +{ + wsfs_server_config_cleanup(config); + free(config); +} + +void wsfs_server_config_set_mountpoint( + struct wsfs_server_config * config, + char const * mount_point) +{ + free(config->mount_point); + config->mount_point = strdup(mount_point); +} + +void wsfs_server_config_set_documentroot( + struct wsfs_server_config * config, + char const * document_root) +{ + free(config->document_root); + config->document_root = strdup(document_root); +} + +void wsfs_server_config_set_keypath( + struct wsfs_server_config * config, + char const * key_path) +{ + free(config->key_path); + config->key_path = strdup(key_path); +} + +void wsfs_server_config_set_certpath( + struct wsfs_server_config * config, + char const * cert_path) +{ + free(config->cert_path); + config->cert_path = strdup(cert_path); +} + +void wsfs_server_config_set_vhostname( + struct wsfs_server_config * config, + char const * vhost_name) +{ + free(config->vhost_name); + config->vhost_name = strdup(vhost_name); +} + +void wsfs_server_config_set_port( + struct wsfs_server_config * config, + int port) +{ + config->port = port; +} diff --git a/lib/wsfs/adapter/server_config_intern.h b/lib/wsfs/adapter/server_config_intern.h new file mode 100644 index 0000000..941ac8a --- /dev/null +++ b/lib/wsfs/adapter/server_config_intern.h @@ -0,0 +1,35 @@ +#ifndef WSFS_ADAPTER_SERVER_CONFIG_INTERN_H +#define WSFS_ADAPTER_SERVER_CONFIG_INTERN_H + +#include "wsfs/adapter/server_config.h" + +struct wsfs_server_config +{ + char * mount_point; + char * document_root; + char * key_path; + char * cert_path; + char * vhost_name; + int port; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern void wsfs_server_config_init( + struct wsfs_server_config * config); + +extern void wsfs_server_config_cleanup( + struct wsfs_server_config * config); + +extern void wsfs_server_config_clone( + struct wsfs_server_config * config, + struct wsfs_server_config * clone); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/test_server.cc b/test/test_server.cc index 965852e..a5625c5 100644 --- a/test/test_server.cc +++ b/test/test_server.cc @@ -13,12 +13,13 @@ TEST(server, create_dispose) { mkdir("test", 0700); - struct wsfs_server_config config = {strdup("test"), nullptr, nullptr, nullptr, nullptr, 0}; - struct wsfs_server * server = wsfs_server_create(&config); + struct wsfs_server_config * config = wsfs_server_config_create(); + wsfs_server_config_set_mountpoint(config, "test"); + struct wsfs_server * server = wsfs_server_create(config); ASSERT_NE(nullptr, server); wsfs_server_dispose(server); - wsfs_server_config_cleanup(&config); + wsfs_server_config_dispose(config); rmdir("test"); } \ No newline at end of file From bbcb974363ab8548351798a18f6502d4f13b332c Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Mon, 11 Mar 2019 23:21:49 +0100 Subject: [PATCH 02/18] feature: try to create mount point, if not present --- lib/wsfs/adapter/server.c | 57 +++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/lib/wsfs/adapter/server.c b/lib/wsfs/adapter/server.c index 31da29d..cb1beec 100644 --- a/lib/wsfs/adapter/server.c +++ b/lib/wsfs/adapter/server.c @@ -4,6 +4,10 @@ #include #include +#include +#include +#include + #include "wsfs/adapter/server_config_intern.h" #include "wsfs/adapter/server_protocol_intern.h" @@ -74,24 +78,49 @@ static struct lws_context * wsfs_server_context_create( } +static bool wsfs_server_check_mountpoint( + struct wsfs_server_config * config) +{ + bool result = false; + + if (NULL != config->mount_point) + { + struct stat info; + int const rc = stat(config->mount_point, &info); + bool const isDir = ((0 == rc) && (S_ISDIR(info.st_mode))); + + if (!isDir) + { + result = (0 == mkdir(config->mount_point, 0755)); + } + } + + return result; +} + struct wsfs_server * wsfs_server_create( struct wsfs_server_config * config) { - struct wsfs_server * server = malloc(sizeof(struct wsfs_server)); - if (NULL != server) - { - if (wsfs_server_protocol_init(&server->protocol, config->mount_point)) + struct wsfs_server * server = NULL; + + if (wsfs_server_check_mountpoint(config)) + { + server = malloc(sizeof(struct wsfs_server)); + if (NULL != server) { - server->shutdown_requested = false; - wsfs_server_config_clone(config, &server->config); - server->context = wsfs_server_context_create(server); - } - else - { - free(server); - server = NULL; - } - } + if (wsfs_server_protocol_init(&server->protocol, config->mount_point)) + { + server->shutdown_requested = false; + wsfs_server_config_clone(config, &server->config); + server->context = wsfs_server_context_create(server); + } + else + { + free(server); + server = NULL; + } + } + } return server; } From eeb67203102bf79eb9ca7b3b50d04d06a3f04319 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Tue, 12 Mar 2019 15:35:56 +0100 Subject: [PATCH 03/18] fixes server start failure due to existing mountpoint --- lib/wsfs/adapter/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/wsfs/adapter/server.c b/lib/wsfs/adapter/server.c index cb1beec..5f1631b 100644 --- a/lib/wsfs/adapter/server.c +++ b/lib/wsfs/adapter/server.c @@ -87,9 +87,9 @@ static bool wsfs_server_check_mountpoint( { struct stat info; int const rc = stat(config->mount_point, &info); - bool const isDir = ((0 == rc) && (S_ISDIR(info.st_mode))); + result = ((0 == rc) && (S_ISDIR(info.st_mode))); - if (!isDir) + if (!result) { result = (0 == mkdir(config->mount_point, 0755)); } From 60ab76aa8177120002e418e1ca8da3cda98297d8 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 17 Mar 2019 10:26:07 +0100 Subject: [PATCH 04/18] added basic authentication infrastructure --- CMakeLists.txt | 7 +- include/wsfs/adapter/authenticate.h | 15 ++++ include/wsfs/adapter/credentials.h | 25 ++++++ include/wsfs/adapter/server_config.h | 8 ++ include/wsfs_adapter.h | 2 + lib/wsfs/adapter/authenticator.c | 49 ++++++++++++ lib/wsfs/adapter/authenticator.h | 40 ++++++++++ lib/wsfs/adapter/authenticators.c | 101 ++++++++++++++++++++++++ lib/wsfs/adapter/authenticators.h | 38 +++++++++ lib/wsfs/adapter/credentials.c | 40 ++++++++++ lib/wsfs/adapter/credentials_intern.h | 30 +++++++ lib/wsfs/adapter/server_config.c | 16 ++++ lib/wsfs/adapter/server_config_intern.h | 2 + lib/wsfs/provider/operation/getattr.c | 2 +- 14 files changed, 372 insertions(+), 3 deletions(-) create mode 100644 include/wsfs/adapter/authenticate.h create mode 100644 include/wsfs/adapter/credentials.h create mode 100644 lib/wsfs/adapter/authenticator.c create mode 100644 lib/wsfs/adapter/authenticator.h create mode 100644 lib/wsfs/adapter/authenticators.c create mode 100644 lib/wsfs/adapter/authenticators.h create mode 100644 lib/wsfs/adapter/credentials.c create mode 100644 lib/wsfs/adapter/credentials_intern.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c017d3e..184d20e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,11 @@ install(FILES include/wsfs/status.h DESTINATION include/wsfs) set(WSFS_ADAPTER_SOURCES lib/wsfs/adapter/filesystem.c lib/wsfs/adapter/server.c + lib/wsfs/adapter/server_config.c + lib/wsfs/adapter/server_protocol.c + lib/wsfs/adapter/authenticator.c + lib/wsfs/adapter/authenticators.c + lib/wsfs/adapter/credentials.c lib/wsfs/adapter/time/timepoint.c lib/wsfs/adapter/time/timer.c lib/wsfs/adapter/time/timeout_manager.c @@ -65,8 +70,6 @@ set(WSFS_ADAPTER_SOURCES lib/wsfs/adapter/operation/open.c lib/wsfs/adapter/operation/close.c lib/wsfs/adapter/operation/read.c - lib/wsfs/adapter/server_config.c - lib/wsfs/adapter/server_protocol.c lib/wsfs/adapter/jsonrpc/server.c lib/wsfs/adapter/jsonrpc/method.c lib/wsfs/adapter/jsonrpc/request.c diff --git a/include/wsfs/adapter/authenticate.h b/include/wsfs/adapter/authenticate.h new file mode 100644 index 0000000..9e630ee --- /dev/null +++ b/include/wsfs/adapter/authenticate.h @@ -0,0 +1,15 @@ +#ifndef WSFS_ADAPTER_AUTHENTICATE_H +#define WSFS_ADAPTER_AUTHENTICATE_H + +#ifndef __cplusplus +#include +#endif + +struct wsfs_credentials; + +typedef bool wsfs_authenticate_fn( + struct wsfs_credentials * credentials, + void * user_data); + + +#endif diff --git a/include/wsfs/adapter/credentials.h b/include/wsfs/adapter/credentials.h new file mode 100644 index 0000000..747b107 --- /dev/null +++ b/include/wsfs/adapter/credentials.h @@ -0,0 +1,25 @@ +#ifndef WSFS_ADAPTER_CREDENTIALS_H +#define WSFS_ADAPTER_CREDENTIALS_H + +#include "wsfs/adapter/api.h" + +struct wsfs_credentials; + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern WSFSA_API char const * wsfs_credentials_type( + struct wsfs_credentials const * credentials); + +extern WSFSA_API char const * wsfs_credentials_get( + struct wsfs_credentials const * credentials, + char const * key); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/include/wsfs/adapter/server_config.h b/include/wsfs/adapter/server_config.h index b6d9b7e..df4966e 100644 --- a/include/wsfs/adapter/server_config.h +++ b/include/wsfs/adapter/server_config.h @@ -2,6 +2,7 @@ #define WSFS_ADAPTER_SERVER_CONFIG_H #include "wsfs/adapter/api.h" +#include "wsfs/adapter/authenticate.h" struct wsfs_server_config; @@ -40,6 +41,13 @@ extern WSFSA_API void wsfs_server_config_set_port( struct wsfs_server_config * config, int port); +extern WSFSA_API void wsfs_server_add_authenticator( + struct wsfs_server_config * config, + char const * type, + wsfs_authenticate_fn * authenticate, + void * user_data +); + #ifdef __cplusplus } #endif diff --git a/include/wsfs_adapter.h b/include/wsfs_adapter.h index 6a812a3..6900f13 100644 --- a/include/wsfs_adapter.h +++ b/include/wsfs_adapter.h @@ -7,5 +7,7 @@ #include #include #include +#include +#include #endif diff --git a/lib/wsfs/adapter/authenticator.c b/lib/wsfs/adapter/authenticator.c new file mode 100644 index 0000000..04f1c60 --- /dev/null +++ b/lib/wsfs/adapter/authenticator.c @@ -0,0 +1,49 @@ +#include "wsfs/adapter/authenticator.h" + +#include +#include + +#include "wsfs/adapter/credentials_intern.h" + +struct wsfs_authenticator * wsfs_authenticator_create( + char const * type, + wsfs_authenticate_fn * authenticate, + void * user_data) +{ + struct wsfs_authenticator * authenticator = malloc(sizeof(struct wsfs_authenticator)); + if (NULL != authenticator) + { + authenticator->type = strdup(type); + authenticator->authenticate = authenticate; + authenticator->user_data = user_data; + authenticator->next = NULL; + } + + return authenticator; +} + +void wsfs_authenticator_dispose( + struct wsfs_authenticator * authenticator) +{ + free(authenticator->type); + free(authenticator); +} + +bool wsfs_authenticator_autenticate( + struct wsfs_authenticator * authenticator, + struct wsfs_credentials * credentials) +{ + bool result; + + if (0 == strcmp(authenticator->type, credentials->type)) + { + result = authenticator->authenticate(credentials, authenticator->user_data); + } + else + { + result = false; + } + + + return result; +} \ No newline at end of file diff --git a/lib/wsfs/adapter/authenticator.h b/lib/wsfs/adapter/authenticator.h new file mode 100644 index 0000000..585cc24 --- /dev/null +++ b/lib/wsfs/adapter/authenticator.h @@ -0,0 +1,40 @@ +#ifndef WSFS_ADAPTER_AUTHENTICATOR_H +#define WSFS_ADAPTER_AUTHENTICATOR_H + +#ifndef __cplusplus +#include +#endif + +#include "wsfs/adapter/authenticate.h" + +struct wsfs_authenticator +{ + char * type; + wsfs_authenticate_fn * authenticate; + void * user_data; + struct wsfs_authenticator * next; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern struct wsfs_authenticator * wsfs_authenticator_create( + char const * type, + wsfs_authenticate_fn * authenticate, + void * user_data); + +extern void wsfs_authenticator_dispose( + struct wsfs_authenticator * authenticator); + +extern bool wsfs_authenticator_autenticate( + struct wsfs_authenticator * authenticator, + struct wsfs_credentials * credentials); + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/wsfs/adapter/authenticators.c b/lib/wsfs/adapter/authenticators.c new file mode 100644 index 0000000..aa59809 --- /dev/null +++ b/lib/wsfs/adapter/authenticators.c @@ -0,0 +1,101 @@ +#include "wsfs/adapter/authenticators.h" +#include +#include + +#include "wsfs/adapter/authenticator.h" +#include "wsfs/adapter/credentials_intern.h" + +static struct wsfs_authenticator * wsfs_authenticators_find( + struct wsfs_authenticators * authenticators, + char const * type) +{ + struct wsfs_authenticator * result = NULL; + + struct wsfs_authenticator * actual = authenticators->first; + while ((NULL == result) && (NULL != actual)) + { + struct wsfs_authenticator * next = actual->next; + if (0 == strcmp(type, actual->type)) + { + result = actual; + } + + actual = next; + } + + return result; +} + +void wsfs_authenticators_init( + struct wsfs_authenticators * authenticators) +{ + authenticators->first = NULL; +} + +void wsfs_authenticators_cleanup( + struct wsfs_authenticators * authenticators) +{ + struct wsfs_authenticator * actual = authenticators->first; + while (NULL != actual) + { + struct wsfs_authenticator * next = actual->next; + wsfs_authenticator_dispose(actual); + actual = next; + } + + authenticators->first = NULL; +} + +void wsfs_authenticators_clone( + struct wsfs_authenticators * authenticators, + struct wsfs_authenticators * other) +{ + wsfs_authenticators_init(other); + + struct wsfs_authenticator * actual = authenticators->first; + while (NULL != actual) + { + struct wsfs_authenticator * next = actual->next; + wsfs_authenticators_add(other, + actual->type, actual->authenticate, actual->user_data); + actual = next; + } + +} + +void wsfs_authenticators_add( + struct wsfs_authenticators * authenticators, + char const * type, + wsfs_authenticate_fn * authenticate, + void * user_data) +{ + struct wsfs_authenticator * authenticator = wsfs_authenticator_create(type, authenticate, user_data); + authenticator->next = authenticators->first; + authenticators->first = authenticator; +} + +bool wsfs_authenticators_authenticate( + struct wsfs_authenticators * authenticators, + struct wsfs_credentials * credentials) +{ + bool result; + + if (NULL != credentials) + { + struct wsfs_authenticator * authenticator = wsfs_authenticators_find(authenticators, credentials->type); + if (NULL != authenticator) + { + result = wsfs_authenticator_autenticate(authenticator, credentials); + } + else + { + result = false; + } + } + else + { + result = (NULL == authenticators->first); + } + + return result; +} \ No newline at end of file diff --git a/lib/wsfs/adapter/authenticators.h b/lib/wsfs/adapter/authenticators.h new file mode 100644 index 0000000..c7cadf6 --- /dev/null +++ b/lib/wsfs/adapter/authenticators.h @@ -0,0 +1,38 @@ +#ifndef WSFS_ADAPTER_AUTHENTICATORS_H +#define WSFS_ADAPTER_AUTHENTICATORS_H + +#ifndef __cplusplus +#include +#endif + +#include "wsfs/adapter/authenticate.h" + +struct wsfs_authenticator; +struct wsfs_credentials; + +struct wsfs_authenticators +{ + struct wsfs_authenticator * first; +}; + +extern void wsfs_authenticators_init( + struct wsfs_authenticators * authenticators); + +extern void wsfs_authenticators_cleanup( + struct wsfs_authenticators * authenticators); + +extern void wsfs_authenticators_clone( + struct wsfs_authenticators * authenticators, + struct wsfs_authenticators * other); + +extern void wsfs_authenticators_add( + struct wsfs_authenticators * authenticators, + char const * type, + wsfs_authenticate_fn * authenticate, + void * user_data); + +extern bool wsfs_authenticators_authenticate( + struct wsfs_authenticators * authenticators, + struct wsfs_credentials * credentials); + +#endif diff --git a/lib/wsfs/adapter/credentials.c b/lib/wsfs/adapter/credentials.c new file mode 100644 index 0000000..40df93f --- /dev/null +++ b/lib/wsfs/adapter/credentials.c @@ -0,0 +1,40 @@ +#include "wsfs/adapter/credentials_intern.h" +#include + +void wsfs_credentials_init( + struct wsfs_credentials * credentials, + char const * type, + json_t * data) +{ + credentials->type = strdup(type); + credentials->data = data; + json_incref(credentials->data); +} + +void wsfs_credentails_cleanup( + struct wsfs_credentials * credentials) +{ + free(credentials->type); + json_decref(credentials->data); +} + +char const * wsfs_credentials_type( + struct wsfs_credentials const * credentials) +{ + return credentials->type; +} + +char const * wsfs_credentials_get( + struct wsfs_credentials const * credentials, + char const * key) +{ + char const * result = NULL; + + json_t * value_holder = json_object_get(credentials->data, key); + if (json_is_string(value_holder)) + { + result = json_string_value(value_holder); + } + + return result; +} diff --git a/lib/wsfs/adapter/credentials_intern.h b/lib/wsfs/adapter/credentials_intern.h new file mode 100644 index 0000000..d0c6f44 --- /dev/null +++ b/lib/wsfs/adapter/credentials_intern.h @@ -0,0 +1,30 @@ +#ifndef WSFS_ADAPTER_CREDENTIALS_INTERN_H +#define WSFS_ADAPTER_CREDENTIALS_INTERN_H + +#include "wsfs/adapter/credentials.h" +#include + +struct wsfs_credentials +{ + char * type; + json_t * data; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern void wsfs_credentials_init( + struct wsfs_credentials * credentials, + char const * type, + json_t * data); + +extern void wsfs_credentails_cleanup( + struct wsfs_credentials * credentials); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/lib/wsfs/adapter/server_config.c b/lib/wsfs/adapter/server_config.c index 13e1f37..d4602bd 100644 --- a/lib/wsfs/adapter/server_config.c +++ b/lib/wsfs/adapter/server_config.c @@ -18,11 +18,15 @@ void wsfs_server_config_init( struct wsfs_server_config * config) { memset(config, 0, sizeof(struct wsfs_server_config)); + + wsfs_authenticators_init(&config->authenticators); } void wsfs_server_config_cleanup( struct wsfs_server_config * config) { + wsfs_authenticators_cleanup(&config->authenticators); + free(config->mount_point); free(config->document_root); free(config->key_path); @@ -42,6 +46,8 @@ void wsfs_server_config_clone( clone->cert_path = wsfs_server_config_strdup(config->cert_path); clone->vhost_name = wsfs_server_config_strdup(config->vhost_name); clone->port = config->port; + + wsfs_authenticators_clone(&config->authenticators, &clone->authenticators); } struct wsfs_server_config * wsfs_server_config_create(void) @@ -108,3 +114,13 @@ void wsfs_server_config_set_port( { config->port = port; } + +void wsfs_server_add_authenticator( + struct wsfs_server_config * config, + char const * type, + wsfs_authenticate_fn * authenticate, + void * user_data +) +{ + wsfs_authenticators_add(&config->authenticators, type, authenticate, user_data); +} \ No newline at end of file diff --git a/lib/wsfs/adapter/server_config_intern.h b/lib/wsfs/adapter/server_config_intern.h index 941ac8a..2ae0a2f 100644 --- a/lib/wsfs/adapter/server_config_intern.h +++ b/lib/wsfs/adapter/server_config_intern.h @@ -2,6 +2,7 @@ #define WSFS_ADAPTER_SERVER_CONFIG_INTERN_H #include "wsfs/adapter/server_config.h" +#include "wsfs/adapter/authenticators.h" struct wsfs_server_config { @@ -11,6 +12,7 @@ struct wsfs_server_config char * cert_path; char * vhost_name; int port; + struct wsfs_authenticators authenticators; }; #ifdef __cplusplus diff --git a/lib/wsfs/provider/operation/getattr.c b/lib/wsfs/provider/operation/getattr.c index c4be838..90aefa0 100644 --- a/lib/wsfs/provider/operation/getattr.c +++ b/lib/wsfs/provider/operation/getattr.c @@ -32,7 +32,7 @@ void wsfsp_getattr_default( ino_t WSFS_UNUSED_PARAM(inode), void * WSFS_UNUSED_PARAM(user_data)) { - wsfsp_respond_error(request, -1); + wsfsp_respond_error(request, WSFS_BAD_NOENTRY); } void wsfsp_respond_getattr( From 7dd38275555e475116c5330b7dcfec4b98a2d59d Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 10 Mar 2019 00:06:13 +0100 Subject: [PATCH 05/18] makes wsfs_server_config opaque --- example/daemon/main.c | 45 +++++++---------- include/wsfs/adapter/server_config.h | 42 ++++++++++------ lib/wsfs/adapter/server.c | 2 +- lib/wsfs/adapter/server_config.c | 67 ++++++++++++++++++++++++- lib/wsfs/adapter/server_config_intern.h | 35 +++++++++++++ test/test_server.cc | 7 +-- 6 files changed, 150 insertions(+), 48 deletions(-) create mode 100644 lib/wsfs/adapter/server_config_intern.h diff --git a/example/daemon/main.c b/example/daemon/main.c index 0964674..387e231 100644 --- a/example/daemon/main.c +++ b/example/daemon/main.c @@ -12,7 +12,7 @@ struct args { - struct wsfs_server_config config; + struct wsfs_server_config * config; bool show_help; }; @@ -53,6 +53,7 @@ static int parse_arguments(int argc, char * argv[], struct args * args) bool result = EXIT_SUCCESS; bool finished = false; + bool has_mountpoint = false; while ((!finished) && (EXIT_SUCCESS == result)) { int option_index = 0; @@ -68,27 +69,23 @@ static int parse_arguments(int argc, char * argv[], struct args * args) finished = true; break; case 'm': - free(args->config.mount_point); - args->config.mount_point = strdup(optarg); + wsfs_server_config_set_mountpoint(args->config, optarg); + has_mountpoint = true; break; case 'd': - free(args->config.document_root); - args->config.document_root = strdup(optarg); + wsfs_server_config_set_documentroot(args->config, optarg); break; case 'c': - free(args->config.cert_path); - args->config.cert_path = strdup(optarg); + wsfs_server_config_set_certpath(args->config, optarg); break; case 'k': - free(args->config.key_path); - args->config.key_path = strdup(optarg); + wsfs_server_config_set_keypath(args->config, optarg); break; case 'n': - free(args->config.vhost_name); - args->config.vhost_name = strdup(optarg); + wsfs_server_config_set_vhostname(args->config, optarg); break; case 'p': - args->config.port = atoi(optarg); + wsfs_server_config_set_port(args->config, atoi(optarg)); break; default: fprintf(stderr, "error: unknown argument\n"); @@ -99,7 +96,7 @@ static int parse_arguments(int argc, char * argv[], struct args * args) if ((EXIT_SUCCESS == result) && (!args->show_help)) { - if (NULL == args->config.mount_point) + if (!has_mountpoint) { fprintf(stderr, "error: missing mount point\n"); result = EXIT_FAILURE; @@ -123,26 +120,18 @@ static void on_interrupt(int signal_id) int main(int argc, char * argv[]) { - struct args args = - { - .config = - { - .mount_point = NULL, - .document_root = NULL, - .cert_path = NULL, - .key_path = NULL, - .vhost_name = strdup("localhost"), - .port = 8080, - }, - .show_help = 0 - }; + struct args args; + args.config = wsfs_server_config_create(); + wsfs_server_config_set_vhostname(args.config, "localhost"); + wsfs_server_config_set_port(args.config, 8080); + args.show_help = false; int result = parse_arguments(argc, argv, &args); if (!args.show_help) { signal(SIGINT, on_interrupt); - server = wsfs_server_create(&args.config); + server = wsfs_server_create(args.config); if (NULL != server) { wsfs_server_run(server); @@ -159,7 +148,7 @@ int main(int argc, char * argv[]) show_help(); } - wsfs_server_config_cleanup(&args.config); + wsfs_server_config_dispose(args.config); return result; } diff --git a/include/wsfs/adapter/server_config.h b/include/wsfs/adapter/server_config.h index 27c3bbe..b6d9b7e 100644 --- a/include/wsfs/adapter/server_config.h +++ b/include/wsfs/adapter/server_config.h @@ -3,30 +3,42 @@ #include "wsfs/adapter/api.h" -struct wsfs_server_config -{ - char * mount_point; - char * document_root; - char * key_path; - char * cert_path; - char * vhost_name; - int port; -}; +struct wsfs_server_config; #ifdef __cplusplus extern "C" { #endif -extern WSFSA_API void wsfs_server_config_init( +extern WSFSA_API struct wsfs_server_config * wsfs_server_config_create(void); + +extern WSFSA_API void wsfs_server_config_dispose( struct wsfs_server_config * config); -extern WSFSA_API void wsfs_server_config_cleanup( - struct wsfs_server_config * config); -extern WSFSA_API void wsfs_server_config_clone( - struct wsfs_server_config * config, - struct wsfs_server_config * clone); +extern WSFSA_API void wsfs_server_config_set_mountpoint( + struct wsfs_server_config * config, + char const * mount_point); + +extern WSFSA_API void wsfs_server_config_set_documentroot( + struct wsfs_server_config * config, + char const * document_root); + +extern WSFSA_API void wsfs_server_config_set_keypath( + struct wsfs_server_config * config, + char const * key_path); + +extern WSFSA_API void wsfs_server_config_set_certpath( + struct wsfs_server_config * config, + char const * cert_path); + +extern WSFSA_API void wsfs_server_config_set_vhostname( + struct wsfs_server_config * config, + char const * vhost_name); + +extern WSFSA_API void wsfs_server_config_set_port( + struct wsfs_server_config * config, + int port); #ifdef __cplusplus } diff --git a/lib/wsfs/adapter/server.c b/lib/wsfs/adapter/server.c index 2590f0d..31da29d 100644 --- a/lib/wsfs/adapter/server.c +++ b/lib/wsfs/adapter/server.c @@ -4,7 +4,7 @@ #include #include -#include "wsfs/adapter/server_config.h" +#include "wsfs/adapter/server_config_intern.h" #include "wsfs/adapter/server_protocol_intern.h" #define WSFS_DISABLE_LWS_LOG 0 diff --git a/lib/wsfs/adapter/server_config.c b/lib/wsfs/adapter/server_config.c index 8f88a17..13e1f37 100644 --- a/lib/wsfs/adapter/server_config.c +++ b/lib/wsfs/adapter/server_config.c @@ -1,4 +1,4 @@ -#include "wsfs/adapter/server_config.h" +#include "wsfs/adapter/server_config_intern.h" #include #include @@ -43,3 +43,68 @@ void wsfs_server_config_clone( clone->vhost_name = wsfs_server_config_strdup(config->vhost_name); clone->port = config->port; } + +struct wsfs_server_config * wsfs_server_config_create(void) +{ + struct wsfs_server_config * config = malloc(sizeof(struct wsfs_server_config)); + if (NULL != config) + { + wsfs_server_config_init(config); + } + + return config; +} + +void wsfs_server_config_dispose( + struct wsfs_server_config * config) +{ + wsfs_server_config_cleanup(config); + free(config); +} + +void wsfs_server_config_set_mountpoint( + struct wsfs_server_config * config, + char const * mount_point) +{ + free(config->mount_point); + config->mount_point = strdup(mount_point); +} + +void wsfs_server_config_set_documentroot( + struct wsfs_server_config * config, + char const * document_root) +{ + free(config->document_root); + config->document_root = strdup(document_root); +} + +void wsfs_server_config_set_keypath( + struct wsfs_server_config * config, + char const * key_path) +{ + free(config->key_path); + config->key_path = strdup(key_path); +} + +void wsfs_server_config_set_certpath( + struct wsfs_server_config * config, + char const * cert_path) +{ + free(config->cert_path); + config->cert_path = strdup(cert_path); +} + +void wsfs_server_config_set_vhostname( + struct wsfs_server_config * config, + char const * vhost_name) +{ + free(config->vhost_name); + config->vhost_name = strdup(vhost_name); +} + +void wsfs_server_config_set_port( + struct wsfs_server_config * config, + int port) +{ + config->port = port; +} diff --git a/lib/wsfs/adapter/server_config_intern.h b/lib/wsfs/adapter/server_config_intern.h new file mode 100644 index 0000000..941ac8a --- /dev/null +++ b/lib/wsfs/adapter/server_config_intern.h @@ -0,0 +1,35 @@ +#ifndef WSFS_ADAPTER_SERVER_CONFIG_INTERN_H +#define WSFS_ADAPTER_SERVER_CONFIG_INTERN_H + +#include "wsfs/adapter/server_config.h" + +struct wsfs_server_config +{ + char * mount_point; + char * document_root; + char * key_path; + char * cert_path; + char * vhost_name; + int port; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern void wsfs_server_config_init( + struct wsfs_server_config * config); + +extern void wsfs_server_config_cleanup( + struct wsfs_server_config * config); + +extern void wsfs_server_config_clone( + struct wsfs_server_config * config, + struct wsfs_server_config * clone); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/test/test_server.cc b/test/test_server.cc index 965852e..a5625c5 100644 --- a/test/test_server.cc +++ b/test/test_server.cc @@ -13,12 +13,13 @@ TEST(server, create_dispose) { mkdir("test", 0700); - struct wsfs_server_config config = {strdup("test"), nullptr, nullptr, nullptr, nullptr, 0}; - struct wsfs_server * server = wsfs_server_create(&config); + struct wsfs_server_config * config = wsfs_server_config_create(); + wsfs_server_config_set_mountpoint(config, "test"); + struct wsfs_server * server = wsfs_server_create(config); ASSERT_NE(nullptr, server); wsfs_server_dispose(server); - wsfs_server_config_cleanup(&config); + wsfs_server_config_dispose(config); rmdir("test"); } \ No newline at end of file From c5cebc7cf2df8bc7434502b851a4e14171452778 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Mon, 11 Mar 2019 23:21:49 +0100 Subject: [PATCH 06/18] feature: try to create mount point, if not present --- lib/wsfs/adapter/server.c | 57 +++++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/lib/wsfs/adapter/server.c b/lib/wsfs/adapter/server.c index 31da29d..cb1beec 100644 --- a/lib/wsfs/adapter/server.c +++ b/lib/wsfs/adapter/server.c @@ -4,6 +4,10 @@ #include #include +#include +#include +#include + #include "wsfs/adapter/server_config_intern.h" #include "wsfs/adapter/server_protocol_intern.h" @@ -74,24 +78,49 @@ static struct lws_context * wsfs_server_context_create( } +static bool wsfs_server_check_mountpoint( + struct wsfs_server_config * config) +{ + bool result = false; + + if (NULL != config->mount_point) + { + struct stat info; + int const rc = stat(config->mount_point, &info); + bool const isDir = ((0 == rc) && (S_ISDIR(info.st_mode))); + + if (!isDir) + { + result = (0 == mkdir(config->mount_point, 0755)); + } + } + + return result; +} + struct wsfs_server * wsfs_server_create( struct wsfs_server_config * config) { - struct wsfs_server * server = malloc(sizeof(struct wsfs_server)); - if (NULL != server) - { - if (wsfs_server_protocol_init(&server->protocol, config->mount_point)) + struct wsfs_server * server = NULL; + + if (wsfs_server_check_mountpoint(config)) + { + server = malloc(sizeof(struct wsfs_server)); + if (NULL != server) { - server->shutdown_requested = false; - wsfs_server_config_clone(config, &server->config); - server->context = wsfs_server_context_create(server); - } - else - { - free(server); - server = NULL; - } - } + if (wsfs_server_protocol_init(&server->protocol, config->mount_point)) + { + server->shutdown_requested = false; + wsfs_server_config_clone(config, &server->config); + server->context = wsfs_server_context_create(server); + } + else + { + free(server); + server = NULL; + } + } + } return server; } From 19e0834b0e3aef2e287743508baac2e1220ab461 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Tue, 12 Mar 2019 15:35:56 +0100 Subject: [PATCH 07/18] fixes server start failure due to existing mountpoint --- lib/wsfs/adapter/server.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/wsfs/adapter/server.c b/lib/wsfs/adapter/server.c index cb1beec..5f1631b 100644 --- a/lib/wsfs/adapter/server.c +++ b/lib/wsfs/adapter/server.c @@ -87,9 +87,9 @@ static bool wsfs_server_check_mountpoint( { struct stat info; int const rc = stat(config->mount_point, &info); - bool const isDir = ((0 == rc) && (S_ISDIR(info.st_mode))); + result = ((0 == rc) && (S_ISDIR(info.st_mode))); - if (!isDir) + if (!result) { result = (0 == mkdir(config->mount_point, 0755)); } From 78111e90555a73c2960b0632a7afe05510bb94fb Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 17 Mar 2019 10:26:07 +0100 Subject: [PATCH 08/18] added basic authentication infrastructure --- CMakeLists.txt | 7 +- include/wsfs/adapter/authenticate.h | 15 ++++ include/wsfs/adapter/credentials.h | 25 ++++++ include/wsfs/adapter/server_config.h | 8 ++ include/wsfs_adapter.h | 2 + lib/wsfs/adapter/authenticator.c | 49 ++++++++++++ lib/wsfs/adapter/authenticator.h | 40 ++++++++++ lib/wsfs/adapter/authenticators.c | 101 ++++++++++++++++++++++++ lib/wsfs/adapter/authenticators.h | 38 +++++++++ lib/wsfs/adapter/credentials.c | 40 ++++++++++ lib/wsfs/adapter/credentials_intern.h | 30 +++++++ lib/wsfs/adapter/server_config.c | 16 ++++ lib/wsfs/adapter/server_config_intern.h | 2 + lib/wsfs/provider/operation/getattr.c | 2 +- 14 files changed, 372 insertions(+), 3 deletions(-) create mode 100644 include/wsfs/adapter/authenticate.h create mode 100644 include/wsfs/adapter/credentials.h create mode 100644 lib/wsfs/adapter/authenticator.c create mode 100644 lib/wsfs/adapter/authenticator.h create mode 100644 lib/wsfs/adapter/authenticators.c create mode 100644 lib/wsfs/adapter/authenticators.h create mode 100644 lib/wsfs/adapter/credentials.c create mode 100644 lib/wsfs/adapter/credentials_intern.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c017d3e..184d20e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,6 +56,11 @@ install(FILES include/wsfs/status.h DESTINATION include/wsfs) set(WSFS_ADAPTER_SOURCES lib/wsfs/adapter/filesystem.c lib/wsfs/adapter/server.c + lib/wsfs/adapter/server_config.c + lib/wsfs/adapter/server_protocol.c + lib/wsfs/adapter/authenticator.c + lib/wsfs/adapter/authenticators.c + lib/wsfs/adapter/credentials.c lib/wsfs/adapter/time/timepoint.c lib/wsfs/adapter/time/timer.c lib/wsfs/adapter/time/timeout_manager.c @@ -65,8 +70,6 @@ set(WSFS_ADAPTER_SOURCES lib/wsfs/adapter/operation/open.c lib/wsfs/adapter/operation/close.c lib/wsfs/adapter/operation/read.c - lib/wsfs/adapter/server_config.c - lib/wsfs/adapter/server_protocol.c lib/wsfs/adapter/jsonrpc/server.c lib/wsfs/adapter/jsonrpc/method.c lib/wsfs/adapter/jsonrpc/request.c diff --git a/include/wsfs/adapter/authenticate.h b/include/wsfs/adapter/authenticate.h new file mode 100644 index 0000000..9e630ee --- /dev/null +++ b/include/wsfs/adapter/authenticate.h @@ -0,0 +1,15 @@ +#ifndef WSFS_ADAPTER_AUTHENTICATE_H +#define WSFS_ADAPTER_AUTHENTICATE_H + +#ifndef __cplusplus +#include +#endif + +struct wsfs_credentials; + +typedef bool wsfs_authenticate_fn( + struct wsfs_credentials * credentials, + void * user_data); + + +#endif diff --git a/include/wsfs/adapter/credentials.h b/include/wsfs/adapter/credentials.h new file mode 100644 index 0000000..747b107 --- /dev/null +++ b/include/wsfs/adapter/credentials.h @@ -0,0 +1,25 @@ +#ifndef WSFS_ADAPTER_CREDENTIALS_H +#define WSFS_ADAPTER_CREDENTIALS_H + +#include "wsfs/adapter/api.h" + +struct wsfs_credentials; + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern WSFSA_API char const * wsfs_credentials_type( + struct wsfs_credentials const * credentials); + +extern WSFSA_API char const * wsfs_credentials_get( + struct wsfs_credentials const * credentials, + char const * key); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/include/wsfs/adapter/server_config.h b/include/wsfs/adapter/server_config.h index b6d9b7e..df4966e 100644 --- a/include/wsfs/adapter/server_config.h +++ b/include/wsfs/adapter/server_config.h @@ -2,6 +2,7 @@ #define WSFS_ADAPTER_SERVER_CONFIG_H #include "wsfs/adapter/api.h" +#include "wsfs/adapter/authenticate.h" struct wsfs_server_config; @@ -40,6 +41,13 @@ extern WSFSA_API void wsfs_server_config_set_port( struct wsfs_server_config * config, int port); +extern WSFSA_API void wsfs_server_add_authenticator( + struct wsfs_server_config * config, + char const * type, + wsfs_authenticate_fn * authenticate, + void * user_data +); + #ifdef __cplusplus } #endif diff --git a/include/wsfs_adapter.h b/include/wsfs_adapter.h index 6a812a3..6900f13 100644 --- a/include/wsfs_adapter.h +++ b/include/wsfs_adapter.h @@ -7,5 +7,7 @@ #include #include #include +#include +#include #endif diff --git a/lib/wsfs/adapter/authenticator.c b/lib/wsfs/adapter/authenticator.c new file mode 100644 index 0000000..04f1c60 --- /dev/null +++ b/lib/wsfs/adapter/authenticator.c @@ -0,0 +1,49 @@ +#include "wsfs/adapter/authenticator.h" + +#include +#include + +#include "wsfs/adapter/credentials_intern.h" + +struct wsfs_authenticator * wsfs_authenticator_create( + char const * type, + wsfs_authenticate_fn * authenticate, + void * user_data) +{ + struct wsfs_authenticator * authenticator = malloc(sizeof(struct wsfs_authenticator)); + if (NULL != authenticator) + { + authenticator->type = strdup(type); + authenticator->authenticate = authenticate; + authenticator->user_data = user_data; + authenticator->next = NULL; + } + + return authenticator; +} + +void wsfs_authenticator_dispose( + struct wsfs_authenticator * authenticator) +{ + free(authenticator->type); + free(authenticator); +} + +bool wsfs_authenticator_autenticate( + struct wsfs_authenticator * authenticator, + struct wsfs_credentials * credentials) +{ + bool result; + + if (0 == strcmp(authenticator->type, credentials->type)) + { + result = authenticator->authenticate(credentials, authenticator->user_data); + } + else + { + result = false; + } + + + return result; +} \ No newline at end of file diff --git a/lib/wsfs/adapter/authenticator.h b/lib/wsfs/adapter/authenticator.h new file mode 100644 index 0000000..585cc24 --- /dev/null +++ b/lib/wsfs/adapter/authenticator.h @@ -0,0 +1,40 @@ +#ifndef WSFS_ADAPTER_AUTHENTICATOR_H +#define WSFS_ADAPTER_AUTHENTICATOR_H + +#ifndef __cplusplus +#include +#endif + +#include "wsfs/adapter/authenticate.h" + +struct wsfs_authenticator +{ + char * type; + wsfs_authenticate_fn * authenticate; + void * user_data; + struct wsfs_authenticator * next; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern struct wsfs_authenticator * wsfs_authenticator_create( + char const * type, + wsfs_authenticate_fn * authenticate, + void * user_data); + +extern void wsfs_authenticator_dispose( + struct wsfs_authenticator * authenticator); + +extern bool wsfs_authenticator_autenticate( + struct wsfs_authenticator * authenticator, + struct wsfs_credentials * credentials); + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/lib/wsfs/adapter/authenticators.c b/lib/wsfs/adapter/authenticators.c new file mode 100644 index 0000000..aa59809 --- /dev/null +++ b/lib/wsfs/adapter/authenticators.c @@ -0,0 +1,101 @@ +#include "wsfs/adapter/authenticators.h" +#include +#include + +#include "wsfs/adapter/authenticator.h" +#include "wsfs/adapter/credentials_intern.h" + +static struct wsfs_authenticator * wsfs_authenticators_find( + struct wsfs_authenticators * authenticators, + char const * type) +{ + struct wsfs_authenticator * result = NULL; + + struct wsfs_authenticator * actual = authenticators->first; + while ((NULL == result) && (NULL != actual)) + { + struct wsfs_authenticator * next = actual->next; + if (0 == strcmp(type, actual->type)) + { + result = actual; + } + + actual = next; + } + + return result; +} + +void wsfs_authenticators_init( + struct wsfs_authenticators * authenticators) +{ + authenticators->first = NULL; +} + +void wsfs_authenticators_cleanup( + struct wsfs_authenticators * authenticators) +{ + struct wsfs_authenticator * actual = authenticators->first; + while (NULL != actual) + { + struct wsfs_authenticator * next = actual->next; + wsfs_authenticator_dispose(actual); + actual = next; + } + + authenticators->first = NULL; +} + +void wsfs_authenticators_clone( + struct wsfs_authenticators * authenticators, + struct wsfs_authenticators * other) +{ + wsfs_authenticators_init(other); + + struct wsfs_authenticator * actual = authenticators->first; + while (NULL != actual) + { + struct wsfs_authenticator * next = actual->next; + wsfs_authenticators_add(other, + actual->type, actual->authenticate, actual->user_data); + actual = next; + } + +} + +void wsfs_authenticators_add( + struct wsfs_authenticators * authenticators, + char const * type, + wsfs_authenticate_fn * authenticate, + void * user_data) +{ + struct wsfs_authenticator * authenticator = wsfs_authenticator_create(type, authenticate, user_data); + authenticator->next = authenticators->first; + authenticators->first = authenticator; +} + +bool wsfs_authenticators_authenticate( + struct wsfs_authenticators * authenticators, + struct wsfs_credentials * credentials) +{ + bool result; + + if (NULL != credentials) + { + struct wsfs_authenticator * authenticator = wsfs_authenticators_find(authenticators, credentials->type); + if (NULL != authenticator) + { + result = wsfs_authenticator_autenticate(authenticator, credentials); + } + else + { + result = false; + } + } + else + { + result = (NULL == authenticators->first); + } + + return result; +} \ No newline at end of file diff --git a/lib/wsfs/adapter/authenticators.h b/lib/wsfs/adapter/authenticators.h new file mode 100644 index 0000000..c7cadf6 --- /dev/null +++ b/lib/wsfs/adapter/authenticators.h @@ -0,0 +1,38 @@ +#ifndef WSFS_ADAPTER_AUTHENTICATORS_H +#define WSFS_ADAPTER_AUTHENTICATORS_H + +#ifndef __cplusplus +#include +#endif + +#include "wsfs/adapter/authenticate.h" + +struct wsfs_authenticator; +struct wsfs_credentials; + +struct wsfs_authenticators +{ + struct wsfs_authenticator * first; +}; + +extern void wsfs_authenticators_init( + struct wsfs_authenticators * authenticators); + +extern void wsfs_authenticators_cleanup( + struct wsfs_authenticators * authenticators); + +extern void wsfs_authenticators_clone( + struct wsfs_authenticators * authenticators, + struct wsfs_authenticators * other); + +extern void wsfs_authenticators_add( + struct wsfs_authenticators * authenticators, + char const * type, + wsfs_authenticate_fn * authenticate, + void * user_data); + +extern bool wsfs_authenticators_authenticate( + struct wsfs_authenticators * authenticators, + struct wsfs_credentials * credentials); + +#endif diff --git a/lib/wsfs/adapter/credentials.c b/lib/wsfs/adapter/credentials.c new file mode 100644 index 0000000..40df93f --- /dev/null +++ b/lib/wsfs/adapter/credentials.c @@ -0,0 +1,40 @@ +#include "wsfs/adapter/credentials_intern.h" +#include + +void wsfs_credentials_init( + struct wsfs_credentials * credentials, + char const * type, + json_t * data) +{ + credentials->type = strdup(type); + credentials->data = data; + json_incref(credentials->data); +} + +void wsfs_credentails_cleanup( + struct wsfs_credentials * credentials) +{ + free(credentials->type); + json_decref(credentials->data); +} + +char const * wsfs_credentials_type( + struct wsfs_credentials const * credentials) +{ + return credentials->type; +} + +char const * wsfs_credentials_get( + struct wsfs_credentials const * credentials, + char const * key) +{ + char const * result = NULL; + + json_t * value_holder = json_object_get(credentials->data, key); + if (json_is_string(value_holder)) + { + result = json_string_value(value_holder); + } + + return result; +} diff --git a/lib/wsfs/adapter/credentials_intern.h b/lib/wsfs/adapter/credentials_intern.h new file mode 100644 index 0000000..d0c6f44 --- /dev/null +++ b/lib/wsfs/adapter/credentials_intern.h @@ -0,0 +1,30 @@ +#ifndef WSFS_ADAPTER_CREDENTIALS_INTERN_H +#define WSFS_ADAPTER_CREDENTIALS_INTERN_H + +#include "wsfs/adapter/credentials.h" +#include + +struct wsfs_credentials +{ + char * type; + json_t * data; +}; + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern void wsfs_credentials_init( + struct wsfs_credentials * credentials, + char const * type, + json_t * data); + +extern void wsfs_credentails_cleanup( + struct wsfs_credentials * credentials); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/lib/wsfs/adapter/server_config.c b/lib/wsfs/adapter/server_config.c index 13e1f37..d4602bd 100644 --- a/lib/wsfs/adapter/server_config.c +++ b/lib/wsfs/adapter/server_config.c @@ -18,11 +18,15 @@ void wsfs_server_config_init( struct wsfs_server_config * config) { memset(config, 0, sizeof(struct wsfs_server_config)); + + wsfs_authenticators_init(&config->authenticators); } void wsfs_server_config_cleanup( struct wsfs_server_config * config) { + wsfs_authenticators_cleanup(&config->authenticators); + free(config->mount_point); free(config->document_root); free(config->key_path); @@ -42,6 +46,8 @@ void wsfs_server_config_clone( clone->cert_path = wsfs_server_config_strdup(config->cert_path); clone->vhost_name = wsfs_server_config_strdup(config->vhost_name); clone->port = config->port; + + wsfs_authenticators_clone(&config->authenticators, &clone->authenticators); } struct wsfs_server_config * wsfs_server_config_create(void) @@ -108,3 +114,13 @@ void wsfs_server_config_set_port( { config->port = port; } + +void wsfs_server_add_authenticator( + struct wsfs_server_config * config, + char const * type, + wsfs_authenticate_fn * authenticate, + void * user_data +) +{ + wsfs_authenticators_add(&config->authenticators, type, authenticate, user_data); +} \ No newline at end of file diff --git a/lib/wsfs/adapter/server_config_intern.h b/lib/wsfs/adapter/server_config_intern.h index 941ac8a..2ae0a2f 100644 --- a/lib/wsfs/adapter/server_config_intern.h +++ b/lib/wsfs/adapter/server_config_intern.h @@ -2,6 +2,7 @@ #define WSFS_ADAPTER_SERVER_CONFIG_INTERN_H #include "wsfs/adapter/server_config.h" +#include "wsfs/adapter/authenticators.h" struct wsfs_server_config { @@ -11,6 +12,7 @@ struct wsfs_server_config char * cert_path; char * vhost_name; int port; + struct wsfs_authenticators authenticators; }; #ifdef __cplusplus diff --git a/lib/wsfs/provider/operation/getattr.c b/lib/wsfs/provider/operation/getattr.c index c4be838..90aefa0 100644 --- a/lib/wsfs/provider/operation/getattr.c +++ b/lib/wsfs/provider/operation/getattr.c @@ -32,7 +32,7 @@ void wsfsp_getattr_default( ino_t WSFS_UNUSED_PARAM(inode), void * WSFS_UNUSED_PARAM(user_data)) { - wsfsp_respond_error(request, -1); + wsfsp_respond_error(request, WSFS_BAD_NOENTRY); } void wsfsp_respond_getattr( From fca001113f2b2744cfa875ecfe2a8ffcb757aa8f Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 17 Mar 2019 14:14:10 +0100 Subject: [PATCH 09/18] added unit tests for credentials --- CMakeLists.txt | 1 + lib/wsfs/adapter/credentials.c | 2 +- lib/wsfs/adapter/credentials_intern.h | 2 +- test/test_credentials.cc | 70 +++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 test/test_credentials.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 184d20e..7218be6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -205,6 +205,7 @@ add_executable(alltests test/test_timepoint.cc test/test_timer.cc test/test_url.cc + test/test_credentials.cc ${WSFS_COMMON_SOURCES} ) diff --git a/lib/wsfs/adapter/credentials.c b/lib/wsfs/adapter/credentials.c index 40df93f..fa8b09e 100644 --- a/lib/wsfs/adapter/credentials.c +++ b/lib/wsfs/adapter/credentials.c @@ -11,7 +11,7 @@ void wsfs_credentials_init( json_incref(credentials->data); } -void wsfs_credentails_cleanup( +void wsfs_credentials_cleanup( struct wsfs_credentials * credentials) { free(credentials->type); diff --git a/lib/wsfs/adapter/credentials_intern.h b/lib/wsfs/adapter/credentials_intern.h index d0c6f44..026c515 100644 --- a/lib/wsfs/adapter/credentials_intern.h +++ b/lib/wsfs/adapter/credentials_intern.h @@ -20,7 +20,7 @@ extern void wsfs_credentials_init( char const * type, json_t * data); -extern void wsfs_credentails_cleanup( +extern void wsfs_credentials_cleanup( struct wsfs_credentials * credentials); #ifdef __cplusplus diff --git a/test/test_credentials.cc b/test/test_credentials.cc new file mode 100644 index 0000000..9862d78 --- /dev/null +++ b/test/test_credentials.cc @@ -0,0 +1,70 @@ +#include + +#include "wsfs/adapter/credentials_intern.h" +#include + +TEST(Credentials, Type) +{ + struct wsfs_credentials creds; + + wsfs_credentials_init(&creds, "test", nullptr); + ASSERT_STREQ("test", wsfs_credentials_type(&creds)); + wsfs_credentials_cleanup(&creds); +} + +TEST(Credentials, Get) +{ + struct wsfs_credentials creds; + json_t * data = json_object(); + json_object_set_new(data, "username", json_string("bob")); + json_object_set_new(data, "password", json_string("")); + + wsfs_credentials_init(&creds, "username", data); + ASSERT_STREQ("username", wsfs_credentials_type(&creds)); + ASSERT_STREQ("bob", wsfs_credentials_get(&creds, "username")); + ASSERT_STREQ("", wsfs_credentials_get(&creds, "password")); + + wsfs_credentials_cleanup(&creds); + json_decref(data); +} + +TEST(Credentials, FailedToGetNonexistingValue) +{ + struct wsfs_credentials creds; + json_t * data = json_object(); + + wsfs_credentials_init(&creds, "username", data); + ASSERT_STREQ("username", wsfs_credentials_type(&creds)); + ASSERT_STREQ(nullptr, wsfs_credentials_get(&creds, "username")); + ASSERT_STREQ(nullptr, wsfs_credentials_get(&creds, "password")); + + wsfs_credentials_cleanup(&creds); + json_decref(data); +} + +TEST(Credentials, FailedToGetWithoutData) +{ + struct wsfs_credentials creds; + + wsfs_credentials_init(&creds, "username", nullptr); + ASSERT_STREQ("username", wsfs_credentials_type(&creds)); + ASSERT_STREQ(nullptr, wsfs_credentials_get(&creds, "username")); + ASSERT_STREQ(nullptr, wsfs_credentials_get(&creds, "password")); + + wsfs_credentials_cleanup(&creds); +} + +TEST(Credentials, FailedToGetWrongDataType) +{ + struct wsfs_credentials creds; + json_t * data = json_string("invalid_creds"); + + wsfs_credentials_init(&creds, "username", data); + ASSERT_STREQ("username", wsfs_credentials_type(&creds)); + ASSERT_STREQ(nullptr, wsfs_credentials_get(&creds, "username")); + ASSERT_STREQ(nullptr, wsfs_credentials_get(&creds, "password")); + + wsfs_credentials_cleanup(&creds); + json_decref(data); +} + From ec74b4a8036e8a47d6f7c607329faa26fafea4cb Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 17 Mar 2019 15:31:26 +0100 Subject: [PATCH 10/18] added unit tests for authenticators --- CMakeLists.txt | 10 ++- lib/wsfs/adapter/authenticators.c | 10 +-- lib/wsfs/adapter/authenticators.h | 9 ++ test/mock_authenticator.cc | 42 ++++++++++ test/mock_authenticator.hpp | 34 ++++++++ test/test_authenticator.cc | 63 ++++++++++++++ test/test_authenticators.cc | 135 ++++++++++++++++++++++++++++++ 7 files changed, 291 insertions(+), 12 deletions(-) create mode 100644 test/mock_authenticator.cc create mode 100644 test/mock_authenticator.hpp create mode 100644 test/test_authenticator.cc create mode 100644 test/test_authenticators.cc diff --git a/CMakeLists.txt b/CMakeLists.txt index 7218be6..96b829d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -186,6 +186,7 @@ endif(NOT WITHOUT_EXAMPLE) if(NOT WITHOUT_TESTS) pkg_check_modules(GTEST gtest_main) +pkg_check_modules(GMOCK gmock) add_library(wsfs-adapter-static STATIC ${WSFS_ADAPTER_SOURCES}) set_target_properties(wsfs-adapter-static PROPERTIES OUTPUT_NAME wsfs-adapter) @@ -200,18 +201,21 @@ target_compile_options(wsfs-provider-static PUBLIC ${EXTRA_CFLAGS}) add_executable(alltests test/msleep.cc + test/mock_authenticator.cc test/test_response_parser.cc test/test_server.cc test/test_timepoint.cc test/test_timer.cc test/test_url.cc test/test_credentials.cc + test/test_authenticator.cc + test/test_authenticators.cc ${WSFS_COMMON_SOURCES} ) -target_link_libraries(alltests PUBLIC wsfs-adapter-static wsfs-provider-static ${EXTRA_LIBS} ${GTEST_LIBRARIES}) -target_include_directories(alltests PUBLIC lib ${EXTRA_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}) -target_compile_options(alltests PUBLIC ${EXTRA_CFLAGS} ${GTEST_CFLAGS}) +target_link_libraries(alltests PUBLIC wsfs-adapter-static wsfs-provider-static ${EXTRA_LIBS} ${GMOCK_LIBRARIES} ${GTEST_LIBRARIES}) +target_include_directories(alltests PUBLIC lib ${EXTRA_INCLUDE_DIRS} ${GMOCK_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS}) +target_compile_options(alltests PUBLIC ${EXTRA_CFLAGS} ${GMOCK_CFLAGS} ${GTEST_CFLAGS}) enable_testing() add_test(alltests alltests) diff --git a/lib/wsfs/adapter/authenticators.c b/lib/wsfs/adapter/authenticators.c index aa59809..58176bb 100644 --- a/lib/wsfs/adapter/authenticators.c +++ b/lib/wsfs/adapter/authenticators.c @@ -78,7 +78,7 @@ bool wsfs_authenticators_authenticate( struct wsfs_authenticators * authenticators, struct wsfs_credentials * credentials) { - bool result; + bool result = (NULL == authenticators->first); if (NULL != credentials) { @@ -87,14 +87,6 @@ bool wsfs_authenticators_authenticate( { result = wsfs_authenticator_autenticate(authenticator, credentials); } - else - { - result = false; - } - } - else - { - result = (NULL == authenticators->first); } return result; diff --git a/lib/wsfs/adapter/authenticators.h b/lib/wsfs/adapter/authenticators.h index c7cadf6..bbabf68 100644 --- a/lib/wsfs/adapter/authenticators.h +++ b/lib/wsfs/adapter/authenticators.h @@ -15,6 +15,11 @@ struct wsfs_authenticators struct wsfs_authenticator * first; }; +#ifdef __cplusplus +extern "C" +{ +#endif + extern void wsfs_authenticators_init( struct wsfs_authenticators * authenticators); @@ -35,4 +40,8 @@ extern bool wsfs_authenticators_authenticate( struct wsfs_authenticators * authenticators, struct wsfs_credentials * credentials); +#ifdef __cplusplus +} +#endif + #endif diff --git a/test/mock_authenticator.cc b/test/mock_authenticator.cc new file mode 100644 index 0000000..f455270 --- /dev/null +++ b/test/mock_authenticator.cc @@ -0,0 +1,42 @@ +#include "mock_authenticator.hpp" + +#define WSFS_AUTHENTICTOR_COUNT 3 + +namespace +{ + +wsfs_test::Authenticator * g_authenticators[WSFS_AUTHENTICTOR_COUNT]; + +} + + +namespace wsfs_test +{ + +void set_authenticator(Authenticator * authenticator) +{ + set_authenticator(0, authenticator); +} + +void set_authenticator(size_t i, Authenticator * authenticator) +{ + g_authenticators[i] = authenticator; +} + +bool authenticate(struct wsfs_credentials * creds, void * user_data) +{ + return g_authenticators[0]->authenticate(creds, user_data); +} + +bool authenticate_1(struct wsfs_credentials * creds, void * user_data) +{ + return g_authenticators[1]->authenticate(creds, user_data); +} + +bool authenticate_2(struct wsfs_credentials * creds, void * user_data) +{ + return g_authenticators[2]->authenticate(creds, user_data); +} + + +} \ No newline at end of file diff --git a/test/mock_authenticator.hpp b/test/mock_authenticator.hpp new file mode 100644 index 0000000..ef5d909 --- /dev/null +++ b/test/mock_authenticator.hpp @@ -0,0 +1,34 @@ +#ifndef MOCK_AUTHENTICATOR_H +#define MOCK_AUTHENTICATOR_H + +#include +#include "wsfs/adapter/authenticator.h" + +namespace wsfs_test +{ + +class Authenticator +{ +public: + virtual ~Authenticator() { } + virtual bool authenticate( + struct wsfs_credentials * credentials, + void * user_data) = 0; +}; + +class MockAuthenticator: public Authenticator +{ +public: + MOCK_METHOD2(authenticate, bool (struct wsfs_credentials * credentials, void * user_data)); +}; + +void set_authenticator(Authenticator * authenticator); +void set_authenticator(size_t index, Authenticator * authenticator); + +bool authenticate(struct wsfs_credentials * creds, void * user_data); +bool authenticate_1(struct wsfs_credentials * creds, void * user_data); +bool authenticate_2(struct wsfs_credentials * creds, void * user_data); + +} + +#endif diff --git a/test/test_authenticator.cc b/test/test_authenticator.cc new file mode 100644 index 0000000..71989f2 --- /dev/null +++ b/test/test_authenticator.cc @@ -0,0 +1,63 @@ +#include +#include + +#include "mock_authenticator.hpp" + +#include "wsfs/adapter/authenticator.h" +#include "wsfs/adapter/credentials_intern.h" + +using ::testing::Return; +using ::testing::_; +using ::wsfs_test::Authenticator; +using ::wsfs_test::MockAuthenticator; +using ::wsfs_test::set_authenticator; +using ::wsfs_test::authenticate; + + +TEST(Authenticator, Authenticate) +{ + MockAuthenticator mock; + set_authenticator(&mock); + + struct wsfs_credentials creds; + wsfs_credentials_init(&creds, "username", nullptr); + char dummy[] = "usr_data"; + void * user_data = reinterpret_cast(dummy); + + EXPECT_CALL(mock, authenticate(&creds, user_data)) + .Times(1) + .WillRepeatedly(Return(true)); + + struct wsfs_authenticator * authenticator = wsfs_authenticator_create( + "username", + &authenticate, + user_data); + + bool result = wsfs_authenticator_autenticate(authenticator, &creds); + ASSERT_TRUE(result); + + wsfs_authenticator_dispose(authenticator); + wsfs_credentials_cleanup(&creds); +} + +TEST(Authenticator, SkipAuthenticationWithWrongType) +{ + MockAuthenticator mock; + set_authenticator(&mock); + + struct wsfs_credentials creds; + wsfs_credentials_init(&creds, "username", nullptr); + EXPECT_CALL(mock, authenticate(_, _)) + .Times(0); + + struct wsfs_authenticator * authenticator = wsfs_authenticator_create( + "certificate", + &authenticate, + nullptr); + + bool result = wsfs_authenticator_autenticate(authenticator, &creds); + ASSERT_FALSE(result); + + wsfs_authenticator_dispose(authenticator); + wsfs_credentials_cleanup(&creds); +} \ No newline at end of file diff --git a/test/test_authenticators.cc b/test/test_authenticators.cc new file mode 100644 index 0000000..bcd2c5e --- /dev/null +++ b/test/test_authenticators.cc @@ -0,0 +1,135 @@ +#include +#include + +#include "wsfs/adapter/authenticators.h" +#include "wsfs/adapter/credentials_intern.h" +#include "mock_authenticator.hpp" + +using ::testing::_; +using ::testing::Return; +using ::wsfs_test::MockAuthenticator; +using ::wsfs_test::set_authenticator; +using ::wsfs_test::authenticate; +using ::wsfs_test::authenticate_1; +using ::wsfs_test::authenticate_2; + + +TEST(Authenticators, CloneEmpty) +{ + struct wsfs_authenticators authenticators; + struct wsfs_authenticators clone; + + wsfs_authenticators_init(&authenticators); + ASSERT_EQ(nullptr, authenticators.first); + + wsfs_authenticators_clone(&authenticators, &clone); + ASSERT_EQ(nullptr, clone.first); + + wsfs_authenticators_cleanup(&authenticators); + wsfs_authenticators_cleanup(&clone); +} + +TEST(Authenticators, Clone) +{ + struct wsfs_authenticators authenticators; + struct wsfs_authenticators clone; + + wsfs_authenticators_init(&authenticators); + wsfs_authenticators_add(&authenticators, "username", &authenticate, nullptr); + ASSERT_NE(nullptr, authenticators.first); + + wsfs_authenticators_clone(&authenticators, &clone); + ASSERT_NE(nullptr, clone.first); + ASSERT_NE(authenticators.first, clone.first); + + wsfs_authenticators_cleanup(&authenticators); + wsfs_authenticators_cleanup(&clone); +} + +TEST(Authenticators, AuthenticateWithoutAuthenticators) +{ + struct wsfs_credentials creds; + wsfs_credentials_init(&creds, "username", nullptr); + + struct wsfs_authenticators authenticators; + wsfs_authenticators_init(&authenticators); + + bool result = wsfs_authenticators_authenticate(&authenticators, &creds); + ASSERT_TRUE(result); + + result = wsfs_authenticators_authenticate(&authenticators, nullptr); + ASSERT_TRUE(result); + + wsfs_authenticators_cleanup(&authenticators); + wsfs_credentials_cleanup(&creds); +} + +TEST(Authenticators, FailToAuthenticateWithoutCredentials) +{ + MockAuthenticator mock; + set_authenticator(&mock); + + struct wsfs_authenticators authenticators; + wsfs_authenticators_init(&authenticators); + wsfs_authenticators_add(&authenticators, "username", &authenticate, nullptr); + + bool result = wsfs_authenticators_authenticate(&authenticators, nullptr); + ASSERT_FALSE(result); + + wsfs_authenticators_cleanup(&authenticators); +} + +TEST(Authenticators, AuthenticateWithMultipleCredentials) +{ + struct wsfs_credentials creds; + wsfs_credentials_init(&creds, "username", nullptr); + + MockAuthenticator username_mock; + set_authenticator(1, &username_mock); + EXPECT_CALL(username_mock, authenticate(&creds, nullptr)) + .Times(1) + .WillRepeatedly(Return(true)); + + MockAuthenticator certificate_mock; + set_authenticator(2, &certificate_mock); + EXPECT_CALL(certificate_mock, authenticate(_, _)) + .Times(0); + + struct wsfs_authenticators authenticators; + wsfs_authenticators_init(&authenticators); + wsfs_authenticators_add(&authenticators, "username", &authenticate_1, nullptr); + wsfs_authenticators_add(&authenticators, "certificate", &authenticate_2, nullptr); + + bool result = wsfs_authenticators_authenticate(&authenticators, &creds); + ASSERT_TRUE(result); + + wsfs_authenticators_cleanup(&authenticators); + wsfs_credentials_cleanup(&creds); +} + +TEST(Authenticators, FailedAuthenticateWithWrongType) +{ + struct wsfs_credentials creds; + wsfs_credentials_init(&creds, "token", nullptr); + + MockAuthenticator username_mock; + set_authenticator(1, &username_mock); + EXPECT_CALL(username_mock, authenticate(&creds, nullptr)) + .Times(0); + + MockAuthenticator certificate_mock; + set_authenticator(2, &certificate_mock); + EXPECT_CALL(certificate_mock, authenticate(_, _)) + .Times(0); + + struct wsfs_authenticators authenticators; + wsfs_authenticators_init(&authenticators); + wsfs_authenticators_add(&authenticators, "username", &authenticate_1, nullptr); + wsfs_authenticators_add(&authenticators, "certificate", &authenticate_2, nullptr); + + bool result = wsfs_authenticators_authenticate(&authenticators, &creds); + ASSERT_FALSE(result); + + wsfs_authenticators_cleanup(&authenticators); + wsfs_credentials_cleanup(&creds); +} \ No newline at end of file From 511d819241d01e177f6943b7a28225ce66726199 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 17 Mar 2019 19:05:51 +0100 Subject: [PATCH 11/18] propagates authenticators to server protocol --- include/wsfs/adapter/server_protocol.h | 9 ++++++++- lib/wsfs/adapter/authenticators.c | 8 ++++++++ lib/wsfs/adapter/authenticators.h | 4 ++++ lib/wsfs/adapter/server.c | 1 + lib/wsfs/adapter/server_protocol.c | 18 ++++++++++++++++-- lib/wsfs/adapter/server_protocol_intern.h | 5 ++++- test/test_authenticators.cc | 21 ++++++++++++++++++++- 7 files changed, 61 insertions(+), 5 deletions(-) diff --git a/include/wsfs/adapter/server_protocol.h b/include/wsfs/adapter/server_protocol.h index 1af4cc1..0579677 100644 --- a/include/wsfs/adapter/server_protocol.h +++ b/include/wsfs/adapter/server_protocol.h @@ -1,7 +1,8 @@ #ifndef WSFS_ADAPTER_SERVER_PROTOCOL_H #define WSFS_ADAPTER_SERVER_PROTOCOL_H -#include "wsfs/adapter/api.h" +#include +#include struct wsfs_server_protocol; struct lws_protocols; @@ -21,6 +22,12 @@ extern WSFSA_API void wsfs_server_protocol_init_lws( struct wsfs_server_protocol * protocol, struct lws_protocols * lws_protocol); +extern WSFSA_API void wsfs_server_protocol_add_authenticator( + struct wsfs_server_protocol * protocol, + char const * type, + wsfs_authenticate_fn * authenticate, + void * user_data); + #ifdef __cplusplus } #endif diff --git a/lib/wsfs/adapter/authenticators.c b/lib/wsfs/adapter/authenticators.c index 58176bb..856354d 100644 --- a/lib/wsfs/adapter/authenticators.c +++ b/lib/wsfs/adapter/authenticators.c @@ -63,6 +63,14 @@ void wsfs_authenticators_clone( } +extern void wsfs_authenticators_move( + struct wsfs_authenticators * authenticators, + struct wsfs_authenticators * other) +{ + other->first = authenticators->first; + authenticators->first = NULL; +} + void wsfs_authenticators_add( struct wsfs_authenticators * authenticators, char const * type, diff --git a/lib/wsfs/adapter/authenticators.h b/lib/wsfs/adapter/authenticators.h index bbabf68..48b8056 100644 --- a/lib/wsfs/adapter/authenticators.h +++ b/lib/wsfs/adapter/authenticators.h @@ -30,6 +30,10 @@ extern void wsfs_authenticators_clone( struct wsfs_authenticators * authenticators, struct wsfs_authenticators * other); +extern void wsfs_authenticators_move( + struct wsfs_authenticators * authenticators, + struct wsfs_authenticators * other); + extern void wsfs_authenticators_add( struct wsfs_authenticators * authenticators, char const * type, diff --git a/lib/wsfs/adapter/server.c b/lib/wsfs/adapter/server.c index 5f1631b..0ca0c74 100644 --- a/lib/wsfs/adapter/server.c +++ b/lib/wsfs/adapter/server.c @@ -112,6 +112,7 @@ struct wsfs_server * wsfs_server_create( { server->shutdown_requested = false; wsfs_server_config_clone(config, &server->config); + wsfs_authenticators_move(&server->config.authenticators, &server->protocol.authenticators); server->context = wsfs_server_context_create(server); } else diff --git a/lib/wsfs/adapter/server_protocol.c b/lib/wsfs/adapter/server_protocol.c index fa53e0d..843c2f1 100644 --- a/lib/wsfs/adapter/server_protocol.c +++ b/lib/wsfs/adapter/server_protocol.c @@ -36,12 +36,14 @@ static int wsfs_server_protocol_callback( if (NULL == protocol->wsi) { protocol->wsi = wsi; + protocol->is_authenticated = wsfs_authenticators_authenticate(&protocol->authenticators, NULL); } break; case LWS_CALLBACK_CLOSED: if (wsi == protocol->wsi) { protocol->wsi = NULL; + protocol->is_authenticated = false; wsfs_message_queue_cleanup(&protocol->queue); } break; @@ -78,7 +80,7 @@ static bool wsfs_server_protocol_invoke( bool result = false; struct wsfs_server_protocol * protocol = user_data; - if (NULL != protocol->wsi) + if ((protocol->is_authenticated) && (NULL != protocol->wsi)) { struct wsfs_message * message = wsfs_message_create(request); if (NULL != message) @@ -131,9 +133,10 @@ bool wsfs_server_protocol_init( char * mount_point) { protocol->wsi = NULL; + protocol->is_authenticated = false; wsfs_message_queue_init(&protocol->queue); - wsfs_timeout_manager_init(&protocol->timeout_manager); + wsfs_authenticators_init(&protocol->authenticators); wsfs_jsonrpc_server_init(&protocol->rpc, &protocol->timeout_manager); wsfs_jsonrpc_server_add(&protocol->rpc, "lookup", &wsfs_server_protocol_invoke, protocol); @@ -149,6 +152,7 @@ bool wsfs_server_protocol_init( if (!success) { wsfs_jsonrpc_server_cleanup(&protocol->rpc); + wsfs_authenticators_cleanup(&protocol->authenticators); wsfs_timeout_manager_cleanup(&protocol->timeout_manager); wsfs_message_queue_cleanup(&protocol->queue); } @@ -163,5 +167,15 @@ void wsfs_server_protocol_cleanup( wsfs_jsonrpc_server_cleanup(&protocol->rpc); wsfs_timeout_manager_cleanup(&protocol->timeout_manager); wsfs_message_queue_cleanup(&protocol->queue); + wsfs_authenticators_cleanup(&protocol->authenticators); protocol->wsi = NULL; } + +void wsfs_server_protocol_add_authenticator( + struct wsfs_server_protocol * protocol, + char const * type, + wsfs_authenticate_fn * authenticate, + void * user_data) +{ + wsfs_authenticators_add(&protocol->authenticators, type, authenticate, user_data); +} diff --git a/lib/wsfs/adapter/server_protocol_intern.h b/lib/wsfs/adapter/server_protocol_intern.h index ecdb0e9..2add201 100644 --- a/lib/wsfs/adapter/server_protocol_intern.h +++ b/lib/wsfs/adapter/server_protocol_intern.h @@ -7,6 +7,7 @@ #include "wsfs/adapter/filesystem.h" #include "wsfs/adapter/jsonrpc/server.h" #include "wsfs/adapter/time/timeout_manager.h" +#include "wsfs/adapter/authenticators.h" struct wsfs_server_protocol { @@ -14,7 +15,9 @@ struct wsfs_server_protocol struct wsfs_filesystem filesystem; struct wsfs_jsonrpc_server rpc; struct wsfs_message_queue queue; - struct lws * wsi; + struct wsfs_authenticators authenticators; + struct lws * wsi; + bool is_authenticated; }; extern bool wsfs_server_protocol_init( diff --git a/test/test_authenticators.cc b/test/test_authenticators.cc index bcd2c5e..6c7c021 100644 --- a/test/test_authenticators.cc +++ b/test/test_authenticators.cc @@ -40,6 +40,25 @@ TEST(Authenticators, Clone) wsfs_authenticators_clone(&authenticators, &clone); ASSERT_NE(nullptr, clone.first); + ASSERT_NE(nullptr, authenticators.first); + ASSERT_NE(authenticators.first, clone.first); + + wsfs_authenticators_cleanup(&authenticators); + wsfs_authenticators_cleanup(&clone); +} + +TEST(Authenticators, Move) +{ + struct wsfs_authenticators authenticators; + struct wsfs_authenticators clone; + + wsfs_authenticators_init(&authenticators); + wsfs_authenticators_add(&authenticators, "username", &authenticate, nullptr); + ASSERT_NE(nullptr, authenticators.first); + + wsfs_authenticators_move(&authenticators, &clone); + ASSERT_NE(nullptr, clone.first); + ASSERT_EQ(nullptr, authenticators.first); ASSERT_NE(authenticators.first, clone.first); wsfs_authenticators_cleanup(&authenticators); @@ -132,4 +151,4 @@ TEST(Authenticators, FailedAuthenticateWithWrongType) wsfs_authenticators_cleanup(&authenticators); wsfs_credentials_cleanup(&creds); -} \ No newline at end of file +} From b6935d753ecc0ae2e423f1e828609737e9dd0221 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 17 Mar 2019 19:32:26 +0100 Subject: [PATCH 12/18] enabled username authentication in daemon example --- example/daemon/main.c | 48 ++++++++++++++++++++++++++-- include/wsfs/adapter/server_config.h | 2 +- lib/wsfs/adapter/server_config.c | 2 +- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/example/daemon/main.c b/example/daemon/main.c index 387e231..0614970 100644 --- a/example/daemon/main.c +++ b/example/daemon/main.c @@ -7,12 +7,15 @@ #include #include +#include #include + struct args { struct wsfs_server_config * config; + char * passwd_path; bool show_help; }; @@ -25,7 +28,7 @@ static void show_help(void) "Websocket file system daemon\n" "\n" "Usage: wsfsd [m ] [-d ] [-p ]\n" - " [-c -k] []\n" + " [-c ] [-k ] [-P ]\n" "\n" "Options:\n" "\t-m, --mount_point Path of mount point (required)\n" @@ -34,9 +37,39 @@ static void show_help(void) "\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" "\n"); } +static bool authenticate(struct wsfs_credentials * creds, void * user_data) +{ + bool result = false; + struct args * args = user_data; + + char const * username = wsfs_credentials_get(creds, "username"); + char const * password = wsfs_credentials_get(creds, "password"); + if ((NULL != username) && (NULL != password)) + { + json_t * passwd = json_load_file(args->passwd_path, 0, NULL); + if (NULL != passwd) + { + json_t * user = json_object_get(passwd, username); + if (json_is_object(user)) + { + json_t * password_holder = json_object_get(user, "password"); + if (json_is_string(password_holder)) + { + result = (0 == strcmp(password, json_string_value(password_holder))); + } + } + + json_decref(passwd); + } + } + + return result; +} + static int parse_arguments(int argc, char * argv[], struct args * args) { static struct option const options[] = @@ -47,6 +80,7 @@ static int parse_arguments(int argc, char * argv[], struct args * args) {"server_key_path", required_argument, NULL, 'k'}, {"vhost_name", required_argument, NULL, 'n'}, {"port", required_argument, NULL, 'p'}, + {"passwd_path", required_argument, NULL, 'P'}, {"help", no_argument, NULL, 'h'}, {NULL, 0, NULL, 0} }; @@ -57,7 +91,7 @@ static int parse_arguments(int argc, char * argv[], struct args * args) while ((!finished) && (EXIT_SUCCESS == result)) { int option_index = 0; - int const c = getopt_long(argc, argv, "m:d:c:k:n:p:h", options, &option_index); + int const c = getopt_long(argc, argv, "m:d:c:k:n:p:P:h", options, &option_index); switch (c) { @@ -87,6 +121,14 @@ static int parse_arguments(int argc, char * argv[], struct args * args) case 'p': wsfs_server_config_set_port(args->config, atoi(optarg)); break; + case 'P': + free(args->passwd_path); + args->passwd_path = strdup(optarg); + wsfs_server_config_add_authenticator(args->config, + "username", + &authenticate, + args); + break; default: fprintf(stderr, "error: unknown argument\n"); result = EXIT_FAILURE; @@ -124,6 +166,7 @@ int main(int argc, char * argv[]) args.config = wsfs_server_config_create(); wsfs_server_config_set_vhostname(args.config, "localhost"); wsfs_server_config_set_port(args.config, 8080); + args.passwd_path = NULL; args.show_help = false; int result = parse_arguments(argc, argv, &args); @@ -148,6 +191,7 @@ int main(int argc, char * argv[]) show_help(); } + free(args.passwd_path); wsfs_server_config_dispose(args.config); return result; } diff --git a/include/wsfs/adapter/server_config.h b/include/wsfs/adapter/server_config.h index df4966e..639e1c1 100644 --- a/include/wsfs/adapter/server_config.h +++ b/include/wsfs/adapter/server_config.h @@ -41,7 +41,7 @@ extern WSFSA_API void wsfs_server_config_set_port( struct wsfs_server_config * config, int port); -extern WSFSA_API void wsfs_server_add_authenticator( +extern WSFSA_API void wsfs_server_config_add_authenticator( struct wsfs_server_config * config, char const * type, wsfs_authenticate_fn * authenticate, diff --git a/lib/wsfs/adapter/server_config.c b/lib/wsfs/adapter/server_config.c index d4602bd..61796d2 100644 --- a/lib/wsfs/adapter/server_config.c +++ b/lib/wsfs/adapter/server_config.c @@ -115,7 +115,7 @@ void wsfs_server_config_set_port( config->port = port; } -void wsfs_server_add_authenticator( +void wsfs_server_config_add_authenticator( struct wsfs_server_config * config, char const * type, wsfs_authenticate_fn * authenticate, From 39d0cf7987ce04f28d10c824d2ea24fc4588988d Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 17 Mar 2019 21:12:11 +0100 Subject: [PATCH 13/18] adds example to compute password hash --- CMakeLists.txt | 24 +++++++++++ example/passwd/main.c | 98 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 example/passwd/main.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 96b829d..b32c031 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -179,6 +179,30 @@ target_link_libraries(wsfs-provider-app PUBLIC wsfs-provider ${EXTRA_LIBS}) target_include_directories(wsfs-provider-app PUBLIC ${EXTRA_INCLUDE_DIRS}) target_compile_options(wsfs-provider-app PUBLIC ${EXTRA_CFLAGS}) +# wsfs-passwd + +pkg_check_modules(OPENSSL REQUIRED openssl) + + +add_executable(wsfs-passwd + example/passwd/main.c +) + +target_link_libraries(wsfs-passwd PUBLIC + ${OPENSSL_LIBRARIES} +) + +target_include_directories(wsfs-passwd PUBLIC + example/passwd + ${OPENSSL_INCLUDE_DIRS} +) + +target_compile_options(wsfs-passwd PUBLIC + ${C_WARNINGS} + ${OPENSSL_CFLAGS_OTHER} +) + + endif(NOT WITHOUT_EXAMPLE) # tests diff --git a/example/passwd/main.c b/example/passwd/main.c new file mode 100644 index 0000000..0f8f971 --- /dev/null +++ b/example/passwd/main.c @@ -0,0 +1,98 @@ +#include +#include +#include + +#include +#include + +#define HASH_ALGORITHM "sha512" + +static char hex_char(unsigned char value) +{ + switch (value) + { + case 0x00: return '0'; + case 0x01: return '1'; + case 0x02: return '2'; + case 0x03: return '3'; + case 0x04: return '4'; + case 0x05: return '5'; + case 0x06: return '6'; + case 0x07: return '7'; + case 0x08: return '8'; + case 0x09: return '9'; + case 0x0a: return 'a'; + case 0x0b: return 'b'; + case 0x0c: return 'c'; + case 0x0d: return 'd'; + case 0x0e: return 'e'; + case 0x0f: return 'f'; + default: return '?'; + } +} + +static char * to_hex(unsigned char const * value, size_t length) +{ + char * result = malloc((2 * length) + 1); + if (NULL != result) + { + for (size_t i = 0, j = 0; i < length; i++, j+=2) + { + unsigned char high = (value[i] >> 4) & 0x0f; + unsigned char low = value[i] & 0x0f; + + result[j ] = hex_char(high); + result[j + 1] = hex_char(low); + } + + result[2 * length] = '\0'; + } + + return result; +} + +static char * get_password_hash( + char const * password, + char const * salt, + char * pepper) +{ + EVP_MD const * digest = EVP_get_digestbyname(HASH_ALGORITHM); + if (NULL == digest) + { + fprintf(stderr, "error: hash algorithm %s not supported\n", HASH_ALGORITHM); + exit(EXIT_FAILURE); + } + + char * result = NULL; + unsigned int hash_size = digest->md_size; + unsigned char * hash = malloc(hash_size); + + if (NULL != hash) + { + EVP_MD_CTX context; + EVP_MD_CTX_init(&context); + EVP_DigestInit_ex(&context, digest, NULL); + EVP_DigestUpdate(&context, password, strlen(password)); + EVP_DigestUpdate(&context, salt, strlen(salt)); + EVP_DigestUpdate(&context, pepper, strlen(pepper)); + EVP_DigestFinal_ex(&context, hash, &hash_size); + EVP_MD_CTX_cleanup(&context); + + result = to_hex(hash, hash_size); + free(hash); + } + + return result; +} + +int main(int argc, char * argv[]) +{ + OPENSSL_init(); + OPENSSL_add_all_algorithms_conf(); + + char * test = get_password_hash("secret", "123\n", ""); + puts(test); + free(test); + + return EXIT_SUCCESS; +} \ No newline at end of file From c0a905d65bfbc08da370351d26dca50b7387f445 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Mon, 18 Mar 2019 21:49:26 +0100 Subject: [PATCH 14/18] adds infrastructure to execute commands --- CMakeLists.txt | 3 + example/passwd/main.c | 270 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 269 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b32c031..a945e17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -190,16 +190,19 @@ add_executable(wsfs-passwd target_link_libraries(wsfs-passwd PUBLIC ${OPENSSL_LIBRARIES} + ${JANSSON_LIBRARIES} ) target_include_directories(wsfs-passwd PUBLIC example/passwd ${OPENSSL_INCLUDE_DIRS} + ${JANSSON_INCLUDE_DIRS} ) target_compile_options(wsfs-passwd PUBLIC ${C_WARNINGS} ${OPENSSL_CFLAGS_OTHER} + ${JANSSON_CFLAGS_OTHER} ) diff --git a/example/passwd/main.c b/example/passwd/main.c index 0f8f971..3650c6f 100644 --- a/example/passwd/main.c +++ b/example/passwd/main.c @@ -1,11 +1,250 @@ #include #include #include +#include +#include +#include + +#include #include +#include #include +#include #define HASH_ALGORITHM "sha512" +#define PASSWD_FORMAT_MAJOR 1 +#define PASSWD_FORMAT_MINOR 0 + +struct args +{ + char * file; + char * command; + char * username; + char * password; + char * pepper; + bool show_help; +}; + +typedef int command_invoke_fn( + struct args * args); + +struct command +{ + char const * name; + command_invoke_fn * invoke; +}; + +static void print_usage(void) +{ + printf( + "wsfs-passwd, Copyright (c) 2019 authors \n" + "Manage wsfs passwd file\n" + "\n" + "Usage: wsfs-passwd -f -c [-u ] [-p ] [-P ]\n" + "\n" + "Options:\n" + "\t-f, --file Path of wsfs passwd file\n" + "\t-c, --command Command to execute\n" + "\t-u, --username Name of user\n" + "\t-p, --password Password of user\n" + "\t-P, --pepper pepper\n" + "\t-h, --help Shows this message\n" + "\n" + "Commands:\n" + "\tcreate Creates an empty passwd file (or cleans an existing)\n" + "\t Example: wsfs-passwd -f passwd.json -c create\n" + "\tadd Adds or replaces a user\n" + "\t Example: wsfs-passwd -f passwd.json -c add -u bob -p secret\n" + "\tremove Removes a user\n" + "\t Example: wsfs-passwd -f passwd.json -c remove -u bob\n" + "\tcheck Checks password of a user\n" + "\t Example: wsfs-passwd -f passwd.json -c check -u bob -p secret\n" + "\n" + ); +} + +static int parse_args(struct args * args, int argc, char * argv[]) +{ + static struct option const options[] = + { + {"file", required_argument, NULL, 'f'}, + {"command", required_argument, NULL, 'c'}, + {"username", required_argument, NULL, 'u'}, + {"password", required_argument, NULL, 'p'}, + {"Pepper", required_argument, NULL, 'P'}, + {"help", required_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} + }; + + int result = EXIT_SUCCESS; + bool finished = false; + while ((!finished) && (EXIT_SUCCESS == result)) + { + int option_index = 0; + int const c = getopt_long(argc, argv, "f:c:u:p:P:h", options, &option_index); + + switch (c) + { + case -1: + finished = true; + break; + case 'h': + args->show_help = true; + finished = true; + break; + case 'f': + free(args->file); + args->file = strdup(optarg); + break; + case 'c': + free(args->command); + args->command = strdup(optarg); + break; + case 'u': + free(args->username); + args->username = strdup(optarg); + break; + case 'p': + free(args->password); + args->password = strdup(optarg); + break; + case 'P': + free(args->pepper); + args->pepper = strdup(optarg); + break; + default: + fprintf(stderr, "error: unknown argument\n"); + result = EXIT_FAILURE; + break; + } + } + + if ((result == EXIT_SUCCESS) && (!args->show_help)) + { + if (NULL == args->file) + { + fprintf(stderr, "error: missing file\n"); + args->show_help = true; + result = EXIT_FAILURE; + } + else if (NULL == args->command) + { + fprintf(stderr, "error: missing command\n"); + args->show_help = true; + result = EXIT_FAILURE; + } + } + + return result; +} + +static void args_init(struct args * args) +{ + args->file = NULL; + args->command = NULL; + args->username = NULL; + args->password = NULL; + args->pepper = strdup(""); + args->show_help = false; +} + +static int create_passwd(struct args * args) +{ + json_t * db = json_object(); + + json_t * meta = json_object(); + json_object_set_new(meta, "type", json_string("wsfs-passwd")); + json_object_set_new(meta, "major", json_integer(PASSWD_FORMAT_MAJOR)); + json_object_set_new(meta, "minor", json_integer(PASSWD_FORMAT_MINOR)); + json_object_set_new(meta, "hash_alorithm", json_string(HASH_ALGORITHM)); + json_object_set_new(db, "meta", meta); + + json_t * users = json_object(); + json_object_set_new(db, "users", users); + + int result = json_dump_file(db, args->file, JSON_INDENT(2)); + json_decref(db); + + return (0 == result) ? EXIT_SUCCESS : EXIT_FAILURE; +} + +static int add_user(struct args * args) +{ + if (NULL == args->username) + { + fprintf(stderr, "error: missing username"); + args->show_help = true; + return EXIT_FAILURE; + } + + if (NULL == args->password) + { + fprintf(stderr, "error: missing password"); + args->show_help = true; + return EXIT_FAILURE; + } + + + + puts("add"); + return EXIT_FAILURE; +} + +static int remove_user(struct args * args) +{ + puts("remove"); + return EXIT_FAILURE; +} + +static int check_password(struct args * args) +{ + puts("check"); + return EXIT_FAILURE; +} + +static int invoke_invalid_command(struct args * args) +{ + fprintf(stderr, "error: unknown command\n"); + return EXIT_FAILURE; +} + +static struct command const commands[] = +{ + {"create", &create_passwd}, + {"add", &add_user}, + {"remove", &remove_user}, + {"check", &check_password}, + {NULL, NULL} +}; + +static struct command const invalid_command = +{ + "", + &invoke_invalid_command +}; + +static struct command const * get_command(char const * name) +{ + for(size_t i = 0; NULL != commands[i].name; i++) + { + if (0 == strcmp(name, commands[i].name)) + { + return &commands[i]; + } + } + + return &invalid_command; +} + +static void args_cleanup(struct args * args) +{ + free(args->file); + free(args->command); + free(args->username); + free(args->password); + free(args->pepper); +} static char hex_char(unsigned char value) { @@ -85,14 +324,37 @@ static char * get_password_hash( return result; } +static void openssl_cleanup(void) +{ + FIPS_mode_set(0); + ENGINE_cleanup(); + CONF_modules_unload(1); + EVP_cleanup(); + CRYPTO_cleanup_all_ex_data(); + ERR_remove_state(0); + ERR_free_strings(); +} + int main(int argc, char * argv[]) { OPENSSL_init(); OPENSSL_add_all_algorithms_conf(); - char * test = get_password_hash("secret", "123\n", ""); - puts(test); - free(test); + struct args args; + args_init(&args); + int result = parse_args(&args, argc, argv); + if ((EXIT_SUCCESS == result) && (!args.show_help)) + { + struct command const * command = get_command(args.command); + result = command->invoke(&args); + } - return EXIT_SUCCESS; + if (args.show_help) + { + print_usage(); + } + + args_cleanup(&args); + openssl_cleanup(); + return result; } \ No newline at end of file From 44b0fad541f08c09245f40e5dd16222fb1662aa8 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Wed, 20 Mar 2019 21:46:36 +0100 Subject: [PATCH 15/18] added userdb to encapsulate authentication stuff --- CMakeLists.txt | 20 ++ example/lib/userdb/include/userdb.h | 46 +++++ example/lib/userdb/src/userdb.c | 278 ++++++++++++++++++++++++++++ example/passwd/main.c | 149 +++++---------- 4 files changed, 390 insertions(+), 103 deletions(-) create mode 100644 example/lib/userdb/include/userdb.h create mode 100644 example/lib/userdb/src/userdb.c diff --git a/CMakeLists.txt b/CMakeLists.txt index a945e17..f818608 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -157,6 +157,24 @@ install(FILES "${PROJECT_BINARY_DIR}/libwsfs-provider.pc" DESTINATION lib${LIB_S if(NOT WITHOUT_EXAMPLE) +# libuserdb + +add_library(userdb STATIC + example/lib/userdb/src/userdb.c +) + +target_include_directories(userdb PUBLIC + example/lib/userdb/include + ${OPENSSL_INCLUDE_DIRS} + ${JANSSON_INCLUDE_DIRS} +) + +target_compile_options(userdb PUBLIC + ${C_WARNINGS} + ${OPENSSL_CFLAGS_OTHER} + ${JANSSON_CFLAGS_OTHER} +) + # daemon add_executable(wsfsd @@ -189,12 +207,14 @@ add_executable(wsfs-passwd ) target_link_libraries(wsfs-passwd PUBLIC + userdb ${OPENSSL_LIBRARIES} ${JANSSON_LIBRARIES} ) target_include_directories(wsfs-passwd PUBLIC example/passwd + example/lib/userdb/include ${OPENSSL_INCLUDE_DIRS} ${JANSSON_INCLUDE_DIRS} ) diff --git a/example/lib/userdb/include/userdb.h b/example/lib/userdb/include/userdb.h new file mode 100644 index 0000000..cf133d0 --- /dev/null +++ b/example/lib/userdb/include/userdb.h @@ -0,0 +1,46 @@ +#ifndef USERDB_H +#define USERDB_H + +#ifndef __cplusplus +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct userdb; + +extern struct userdb * userdb_create( + char const * pepper); + +extern void userdb_dispose(struct userdb * db); + +extern bool userdb_save( + struct userdb * db, + char const * filename); + +extern bool userdb_load( + struct userdb * db, + char const * filename); + +extern void userdb_add( + struct userdb * db, + char const * username, + char const * password); + +extern void userdb_remove( + struct userdb * db, + char const * user); + +extern bool userdb_check( + struct userdb * db, + char const * username, + char const * password); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/example/lib/userdb/src/userdb.c b/example/lib/userdb/src/userdb.c new file mode 100644 index 0000000..e8493e0 --- /dev/null +++ b/example/lib/userdb/src/userdb.c @@ -0,0 +1,278 @@ +#include "userdb.h" + +#include +#include +#include +#include + +#include +#include + +#define USERDB_HASH_ALGORITHM "sha512" +#define USERDB_MAJOR 1 +#define USERDB_MINOR 0 + +#define USERDB_SALT_SIZE 32 + +struct userdb +{ + json_t * users; + char * pepper; + char * hash_algorithm; +}; + +static bool is_compatible(json_t * meta) +{ + bool result = false; + if (json_is_object(meta)) + { + json_t * type = json_object_get(meta, "type"); + json_t * major = json_object_get(meta, "major"); + json_t * minor = json_object_get(meta, "minor"); + json_t * hash_algorithm = json_object_get(meta, "hash_algorithm"); + + result = ( + json_is_string(type) && + (0 == strcmp(json_string_value(type), "wsfs-userdb")) && + json_is_integer(major) && + (USERDB_MAJOR == json_integer_value(major)) && + json_is_integer(minor) && + json_is_string(hash_algorithm) + ); + + if (result) + { + char const * algorithm = json_string_value(hash_algorithm); + result = (NULL != EVP_get_digestbyname(algorithm)); + } + + } + return result; +} + +static char hex_char(unsigned char value) +{ + switch (value) + { + case 0x00: return '0'; + case 0x01: return '1'; + case 0x02: return '2'; + case 0x03: return '3'; + case 0x04: return '4'; + case 0x05: return '5'; + case 0x06: return '6'; + case 0x07: return '7'; + case 0x08: return '8'; + case 0x09: return '9'; + case 0x0a: return 'a'; + case 0x0b: return 'b'; + case 0x0c: return 'c'; + case 0x0d: return 'd'; + case 0x0e: return 'e'; + case 0x0f: return 'f'; + default: return '?'; + } +} + +static char * to_hex(unsigned char const * value, size_t length) +{ + char * result = malloc((2 * length) + 1); + if (NULL != result) + { + for (size_t i = 0, j = 0; i < length; i++, j+=2) + { + unsigned char high = (value[i] >> 4) & 0x0f; + unsigned char low = value[i] & 0x0f; + + result[j ] = hex_char(high); + result[j + 1] = hex_char(low); + } + + result[2 * length] = '\0'; + } + + return result; +} + +static char * generate_salt(void) +{ + unsigned char buffer[USERDB_SALT_SIZE]; + int rc = RAND_bytes(buffer, USERDB_SALT_SIZE); + if (1 != rc) + { + fprintf(stderr, "fatal: failed to generate salt (OpenSSL RAND_bytes failed)\n"); + exit(EXIT_FAILURE); + } + + return to_hex(buffer, USERDB_SALT_SIZE); +} + +static char * compute_hash( + struct userdb * db, + char const * password, + char const * salt) +{ + EVP_MD const * digest = EVP_get_digestbyname(db->hash_algorithm); + if (NULL == digest) + { + fprintf(stderr, "error: hash algorithm %s not supported\n", db->hash_algorithm); + return NULL; + } + + char * result = NULL; + unsigned int hash_size = digest->md_size; + unsigned char * hash = malloc(hash_size); + + if (NULL != hash) + { + EVP_MD_CTX context; + EVP_MD_CTX_init(&context); + EVP_DigestInit_ex(&context, digest, NULL); + EVP_DigestUpdate(&context, password, strlen(password)); + EVP_DigestUpdate(&context, salt, strlen(salt)); + EVP_DigestUpdate(&context, db->pepper, strlen(db->pepper)); + EVP_DigestFinal_ex(&context, hash, &hash_size); + EVP_MD_CTX_cleanup(&context); + + result = to_hex(hash, hash_size); + free(hash); + } + + return result; +} + +struct userdb * userdb_create( + char const * pepper) +{ + struct userdb * db = malloc(sizeof(struct userdb)); + if (NULL != db) + { + db->users = json_object(); + db->pepper = strdup(pepper); + db->hash_algorithm = strdup(USERDB_HASH_ALGORITHM); + } + + return db; +} + +void userdb_dispose( + struct userdb * db) +{ + json_decref(db->users); + free(db->pepper); + free(db->hash_algorithm); + free(db); +} + +bool userdb_save( + struct userdb * db, + char const * filename) +{ + json_t * container = json_object(); + + json_t * meta = json_object(); + json_object_set_new(meta, "type", json_string("wsfs-userdb")); + json_object_set_new(meta, "major", json_integer(USERDB_MAJOR)); + json_object_set_new(meta, "minor", json_integer(USERDB_MINOR)); + json_object_set_new(meta, "hash_algorithm", json_string(db->hash_algorithm)); + json_object_set_new(container, "meta", meta); + + json_object_set(container, "users", db->users); + + int result = json_dump_file(container, filename, JSON_INDENT(2)); + json_decref(container); + + return (0 == result); +} + + +bool userdb_load( + struct userdb * db, + char const * filename) +{ + bool result = false; + json_t * container = json_load_file(filename, 0, NULL); + if (NULL != container) + { + json_t * meta = json_object_get(container, "meta"); + json_t * users = json_object_get(container, "users"); + + if ((is_compatible(meta)) && (json_is_object(users))) { + json_t * hash_algorithm = json_object_get(meta, "hash_algorithm"); + free(db->hash_algorithm); + db->hash_algorithm = strdup(json_string_value(hash_algorithm)); + + json_decref(db->users); + json_incref(users); + db->users = users; + + result = true; + } + + json_decref(container); + } + + return result; +} + +void userdb_add( + struct userdb * db, + char const * username, + char const * password) +{ + char * salt = generate_salt(); + char * hash = compute_hash(db, password, salt); + + json_t * user = json_object(); + json_object_set_new(user, "password_hash", json_string(hash)); + json_object_set_new(user, "salt", json_string(salt)); + + json_object_set_new(db->users, username, user); + + free(salt); + free(hash); +} + +void userdb_remove( + struct userdb * db, + char const * user) +{ + json_object_del(db->users, user); +} + +static char const * json_object_get_string( + json_t * object, + char const * key) +{ + char const * result = NULL; + + json_t * string_holder = json_object_get(object, key); + if (json_is_string(string_holder)) + { + result = json_string_value(string_holder); + } + + return result; +} + +bool userdb_check( + struct userdb * db, + char const * username, + char const * password) +{ + bool result = false; + + json_t * user = json_object_get(db->users, username); + if (json_is_object(user)) + { + char const * salt = json_object_get_string(user, "salt"); + char const * hash = json_object_get_string(user, "password_hash"); + + char * computed_hash = compute_hash(db, password, salt); + + result = (0 == strcmp(computed_hash, hash)); + free(computed_hash); + } + + return result; +} \ No newline at end of file diff --git a/example/passwd/main.c b/example/passwd/main.c index 3650c6f..c662000 100644 --- a/example/passwd/main.c +++ b/example/passwd/main.c @@ -11,10 +11,8 @@ #include #include #include +#include -#define HASH_ALGORITHM "sha512" -#define PASSWD_FORMAT_MAJOR 1 -#define PASSWD_FORMAT_MINOR 0 struct args { @@ -151,22 +149,11 @@ static void args_init(struct args * args) static int create_passwd(struct args * args) { - json_t * db = json_object(); + struct userdb * db = userdb_create(args->pepper); + bool result = userdb_save(db, args->file); + userdb_dispose(db); - json_t * meta = json_object(); - json_object_set_new(meta, "type", json_string("wsfs-passwd")); - json_object_set_new(meta, "major", json_integer(PASSWD_FORMAT_MAJOR)); - json_object_set_new(meta, "minor", json_integer(PASSWD_FORMAT_MINOR)); - json_object_set_new(meta, "hash_alorithm", json_string(HASH_ALGORITHM)); - json_object_set_new(db, "meta", meta); - - json_t * users = json_object(); - json_object_set_new(db, "users", users); - - int result = json_dump_file(db, args->file, JSON_INDENT(2)); - json_decref(db); - - return (0 == result) ? EXIT_SUCCESS : EXIT_FAILURE; + return (result) ? EXIT_SUCCESS : EXIT_FAILURE; } static int add_user(struct args * args) @@ -185,22 +172,56 @@ static int add_user(struct args * args) return EXIT_FAILURE; } - + struct userdb * db = userdb_create(args->pepper); + userdb_load(db, args->file); + userdb_add(db, args->username, args->password); + bool result = userdb_save(db, args->file); + userdb_dispose(db); - puts("add"); - return EXIT_FAILURE; + return (result) ? EXIT_SUCCESS : EXIT_FAILURE; } static int remove_user(struct args * args) { - puts("remove"); - return EXIT_FAILURE; + if (NULL == args->username) + { + fprintf(stderr, "error: missing username"); + args->show_help = true; + return EXIT_FAILURE; + } + + struct userdb * db = userdb_create(args->pepper); + userdb_load(db, args->file); + userdb_remove(db, args->username); + bool result = userdb_save(db, args->file); + userdb_dispose(db); + + return (result) ? EXIT_SUCCESS : EXIT_FAILURE; } static int check_password(struct args * args) { - puts("check"); - return EXIT_FAILURE; + if (NULL == args->username) + { + fprintf(stderr, "error: missing username"); + args->show_help = true; + return EXIT_FAILURE; + } + + if (NULL == args->password) + { + fprintf(stderr, "error: missing password"); + args->show_help = true; + return EXIT_FAILURE; + } + + struct userdb * db = userdb_create(args->pepper); + userdb_load(db, args->file); + bool result = userdb_check(db, args->username, args->password); + userdb_dispose(db); + + printf("%s\n", (result) ? "OK" : "FAILURE"); + return (result) ? EXIT_SUCCESS : EXIT_FAILURE; } static int invoke_invalid_command(struct args * args) @@ -246,84 +267,6 @@ static void args_cleanup(struct args * args) free(args->pepper); } -static char hex_char(unsigned char value) -{ - switch (value) - { - case 0x00: return '0'; - case 0x01: return '1'; - case 0x02: return '2'; - case 0x03: return '3'; - case 0x04: return '4'; - case 0x05: return '5'; - case 0x06: return '6'; - case 0x07: return '7'; - case 0x08: return '8'; - case 0x09: return '9'; - case 0x0a: return 'a'; - case 0x0b: return 'b'; - case 0x0c: return 'c'; - case 0x0d: return 'd'; - case 0x0e: return 'e'; - case 0x0f: return 'f'; - default: return '?'; - } -} - -static char * to_hex(unsigned char const * value, size_t length) -{ - char * result = malloc((2 * length) + 1); - if (NULL != result) - { - for (size_t i = 0, j = 0; i < length; i++, j+=2) - { - unsigned char high = (value[i] >> 4) & 0x0f; - unsigned char low = value[i] & 0x0f; - - result[j ] = hex_char(high); - result[j + 1] = hex_char(low); - } - - result[2 * length] = '\0'; - } - - return result; -} - -static char * get_password_hash( - char const * password, - char const * salt, - char * pepper) -{ - EVP_MD const * digest = EVP_get_digestbyname(HASH_ALGORITHM); - if (NULL == digest) - { - fprintf(stderr, "error: hash algorithm %s not supported\n", HASH_ALGORITHM); - exit(EXIT_FAILURE); - } - - char * result = NULL; - unsigned int hash_size = digest->md_size; - unsigned char * hash = malloc(hash_size); - - if (NULL != hash) - { - EVP_MD_CTX context; - EVP_MD_CTX_init(&context); - EVP_DigestInit_ex(&context, digest, NULL); - EVP_DigestUpdate(&context, password, strlen(password)); - EVP_DigestUpdate(&context, salt, strlen(salt)); - EVP_DigestUpdate(&context, pepper, strlen(pepper)); - EVP_DigestFinal_ex(&context, hash, &hash_size); - EVP_MD_CTX_cleanup(&context); - - result = to_hex(hash, hash_size); - free(hash); - } - - return result; -} - static void openssl_cleanup(void) { FIPS_mode_set(0); From d6479d49e1e8b5cc03fc8cab8b594ae37260e62e Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Fri, 22 Mar 2019 21:20:35 +0100 Subject: [PATCH 16/18] adds session and session_manager --- CMakeLists.txt | 2 + lib/wsfs/adapter/server_protocol.c | 33 ++++++-------- lib/wsfs/adapter/server_protocol_intern.h | 7 +-- lib/wsfs/adapter/session.c | 20 +++++++++ lib/wsfs/adapter/session.h | 37 ++++++++++++++++ lib/wsfs/adapter/session_manager.c | 52 +++++++++++++++++++++++ lib/wsfs/adapter/session_manager.h | 45 ++++++++++++++++++++ 7 files changed, 172 insertions(+), 24 deletions(-) create mode 100644 lib/wsfs/adapter/session.c create mode 100644 lib/wsfs/adapter/session.h create mode 100644 lib/wsfs/adapter/session_manager.c create mode 100644 lib/wsfs/adapter/session_manager.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f818608..796859c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,6 +58,8 @@ set(WSFS_ADAPTER_SOURCES lib/wsfs/adapter/server.c lib/wsfs/adapter/server_config.c lib/wsfs/adapter/server_protocol.c + lib/wsfs/adapter/session.c + lib/wsfs/adapter/session_manager.c lib/wsfs/adapter/authenticator.c lib/wsfs/adapter/authenticators.c lib/wsfs/adapter/credentials.c diff --git a/lib/wsfs/adapter/server_protocol.c b/lib/wsfs/adapter/server_protocol.c index 843c2f1..9f8c503 100644 --- a/lib/wsfs/adapter/server_protocol.c +++ b/lib/wsfs/adapter/server_protocol.c @@ -19,6 +19,7 @@ static int wsfs_server_protocol_callback( struct wsfs_server_protocol * protocol = ws_protocol->user; wsfs_timeout_manager_check(&protocol->timeout_manager); + struct wsfs_session * session = wsfs_session_manager_get(&protocol->session_manager, wsi); switch (reason) { @@ -33,28 +34,24 @@ static int wsfs_server_protocol_callback( } break; case LWS_CALLBACK_ESTABLISHED: - if (NULL == protocol->wsi) { - protocol->wsi = wsi; - protocol->is_authenticated = wsfs_authenticators_authenticate(&protocol->authenticators, NULL); + bool is_authenticated = wsfs_authenticators_authenticate(&protocol->authenticators, NULL); + wsfs_session_manager_add(&protocol->session_manager, wsi, is_authenticated); } break; case LWS_CALLBACK_CLOSED: - if (wsi == protocol->wsi) { - protocol->wsi = NULL; - protocol->is_authenticated = false; - wsfs_message_queue_cleanup(&protocol->queue); + wsfs_session_manager_remove(&protocol->session_manager, wsi); } break; case LWS_CALLBACK_SERVER_WRITEABLE: - if ((wsi == protocol->wsi) && (!wsfs_message_queue_empty(&protocol->queue))) + if ((NULL != session) && (!wsfs_message_queue_empty(&session->queue))) { - struct wsfs_message * message = wsfs_message_queue_pop(&protocol->queue); + struct wsfs_message * message = wsfs_message_queue_pop(&session->queue); lws_write(wsi, (unsigned char*) message->data, message->length, LWS_WRITE_TEXT); wsfs_message_dispose(message); - if (!wsfs_message_queue_empty(&protocol->queue)) + if (!wsfs_message_queue_empty(&session->queue)) { lws_callback_on_writable(wsi); } @@ -79,14 +76,15 @@ static bool wsfs_server_protocol_invoke( { bool result = false; struct wsfs_server_protocol * protocol = user_data; + struct wsfs_session * session = &protocol->session_manager.session; - if ((protocol->is_authenticated) && (NULL != protocol->wsi)) + if ((session->is_authenticated) && (NULL != session->wsi)) { struct wsfs_message * message = wsfs_message_create(request); if (NULL != message) { - wsfs_message_queue_push(&protocol->queue, message); - lws_callback_on_writable(protocol->wsi); + wsfs_message_queue_push(&session->queue, message); + lws_callback_on_writable(session->wsi); result = true; } @@ -132,10 +130,8 @@ bool wsfs_server_protocol_init( struct wsfs_server_protocol * protocol, char * mount_point) { - protocol->wsi = NULL; - protocol->is_authenticated = false; - wsfs_message_queue_init(&protocol->queue); wsfs_timeout_manager_init(&protocol->timeout_manager); + wsfs_session_manager_init(&protocol->session_manager); wsfs_authenticators_init(&protocol->authenticators); wsfs_jsonrpc_server_init(&protocol->rpc, &protocol->timeout_manager); @@ -154,7 +150,7 @@ bool wsfs_server_protocol_init( wsfs_jsonrpc_server_cleanup(&protocol->rpc); wsfs_authenticators_cleanup(&protocol->authenticators); wsfs_timeout_manager_cleanup(&protocol->timeout_manager); - wsfs_message_queue_cleanup(&protocol->queue); + wsfs_session_manager_cleanup(&protocol->session_manager); } return success; @@ -166,9 +162,8 @@ void wsfs_server_protocol_cleanup( wsfs_filesystem_cleanup(&protocol->filesystem); wsfs_jsonrpc_server_cleanup(&protocol->rpc); wsfs_timeout_manager_cleanup(&protocol->timeout_manager); - wsfs_message_queue_cleanup(&protocol->queue); wsfs_authenticators_cleanup(&protocol->authenticators); - protocol->wsi = NULL; + wsfs_session_manager_cleanup(&protocol->session_manager); } void wsfs_server_protocol_add_authenticator( diff --git a/lib/wsfs/adapter/server_protocol_intern.h b/lib/wsfs/adapter/server_protocol_intern.h index 2add201..7304934 100644 --- a/lib/wsfs/adapter/server_protocol_intern.h +++ b/lib/wsfs/adapter/server_protocol_intern.h @@ -1,23 +1,20 @@ #ifndef WSFS_ADAPTER_SERVER_PROTOCOL_INTERN_H #define WSFS_ADAPTER_SERVER_PROTOCOL_INTERN_H -#include "wsfs/message_queue.h" - #include "wsfs/adapter/server_protocol.h" #include "wsfs/adapter/filesystem.h" #include "wsfs/adapter/jsonrpc/server.h" #include "wsfs/adapter/time/timeout_manager.h" #include "wsfs/adapter/authenticators.h" +#include "wsfs/adapter/session_manager.h" struct wsfs_server_protocol { struct wsfs_timeout_manager timeout_manager; struct wsfs_filesystem filesystem; struct wsfs_jsonrpc_server rpc; - struct wsfs_message_queue queue; struct wsfs_authenticators authenticators; - struct lws * wsi; - bool is_authenticated; + struct wsfs_session_manager session_manager; }; extern bool wsfs_server_protocol_init( diff --git a/lib/wsfs/adapter/session.c b/lib/wsfs/adapter/session.c new file mode 100644 index 0000000..4ad8606 --- /dev/null +++ b/lib/wsfs/adapter/session.c @@ -0,0 +1,20 @@ +#include "wsfs/adapter/session.h" +#include + +void wsfs_session_init( + struct wsfs_session * session, + struct lws * wsi, + bool is_authenticated) + { + session->wsi = wsi; + session->is_authenticated = is_authenticated; + wsfs_message_queue_init(&session->queue); + } + +void wsfs_session_cleanup( + struct wsfs_session * session) +{ + wsfs_message_queue_cleanup(&session->queue); + session->is_authenticated = false; + session->wsi = NULL; +} \ No newline at end of file diff --git a/lib/wsfs/adapter/session.h b/lib/wsfs/adapter/session.h new file mode 100644 index 0000000..3c45341 --- /dev/null +++ b/lib/wsfs/adapter/session.h @@ -0,0 +1,37 @@ +#ifndef WSFS_ADAPTER_SESSION_H +#define WSFS_ADAPTER_SESSION_H + +#ifndef __cplusplus +#include +#endif + +#include "wsfs/message_queue.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct lws; + +struct wsfs_session +{ + struct lws * wsi; + bool is_authenticated; + struct wsfs_message_queue queue; +}; + +extern void wsfs_session_init( + struct wsfs_session * session, + struct lws * wsi, + bool is_authenticated); + +extern void wsfs_session_cleanup( + struct wsfs_session * session); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/lib/wsfs/adapter/session_manager.c b/lib/wsfs/adapter/session_manager.c new file mode 100644 index 0000000..73e332e --- /dev/null +++ b/lib/wsfs/adapter/session_manager.c @@ -0,0 +1,52 @@ +#include "wsfs/adapter/session_manager.h" +#include + +void wsfs_session_manager_init( + struct wsfs_session_manager * manager) +{ + wsfs_session_init(&manager->session, NULL, false); +} + +void wsfs_session_manager_cleanup( + struct wsfs_session_manager * manager) +{ + wsfs_session_cleanup(&manager->session); +} + +bool wsfs_session_manager_add( + struct wsfs_session_manager * manager, + struct lws * wsi, + bool is_authenticated) +{ + bool const result = (NULL == manager->session.wsi); + if (result) + { + wsfs_session_init(&manager->session, wsi, is_authenticated); + } + + return result; +} + +struct wsfs_session * wsfs_session_manager_get( + struct wsfs_session_manager * manager, + struct lws * wsi) +{ + struct wsfs_session * session = NULL; + if (wsi == manager->session.wsi) + { + session = &manager->session; + } + + return session; +} + +void wsfs_session_manager_remove( + struct wsfs_session_manager * manager, + struct lws * wsi) +{ + if (wsi == manager->session.wsi) + { + wsfs_session_cleanup(&manager->session); + manager->session.wsi = NULL; + } +} diff --git a/lib/wsfs/adapter/session_manager.h b/lib/wsfs/adapter/session_manager.h new file mode 100644 index 0000000..b21eeab --- /dev/null +++ b/lib/wsfs/adapter/session_manager.h @@ -0,0 +1,45 @@ +#ifndef WSFS_ADAPTER_SESSION_MANAGER_H +#define WSFS_ADAPTER_SESSION_MANAGER_H + +#ifndef __cplusplus +#include +#endif + +#include "wsfs/adapter/session.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct lws; + +struct wsfs_session_manager +{ + struct wsfs_session session; +}; + +extern void wsfs_session_manager_init( + struct wsfs_session_manager * manager); + +extern void wsfs_session_manager_cleanup( + struct wsfs_session_manager * manager); + +extern bool wsfs_session_manager_add( + struct wsfs_session_manager * manager, + struct lws * wsi, + bool is_authenticated); + +extern struct wsfs_session * wsfs_session_manager_get( + struct wsfs_session_manager * manager, + struct lws * wsi); + +extern void wsfs_session_manager_remove( + struct wsfs_session_manager * manager, + struct lws * wsi); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file From eea13654b65de21398550a7b50d3b9b016dbe592 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sat, 23 Mar 2019 11:33:03 +0100 Subject: [PATCH 17/18] fixes warning about unused param --- example/passwd/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/example/passwd/main.c b/example/passwd/main.c index c662000..a0b50be 100644 --- a/example/passwd/main.c +++ b/example/passwd/main.c @@ -226,6 +226,8 @@ static int check_password(struct args * args) static int invoke_invalid_command(struct args * args) { + (void) args; + fprintf(stderr, "error: unknown command\n"); return EXIT_FAILURE; } From 54e16bfd3dc14e60e55b1da7ddb91597bab6f66f Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sat, 23 Mar 2019 11:33:42 +0100 Subject: [PATCH 18/18] moves some logic from server_protocol to session --- lib/wsfs/adapter/server_protocol.c | 48 ++++++++------------ lib/wsfs/adapter/session.c | 72 ++++++++++++++++++++++++++++-- lib/wsfs/adapter/session.h | 29 +++++++++++- lib/wsfs/adapter/session_manager.c | 16 ++++--- lib/wsfs/adapter/session_manager.h | 5 ++- 5 files changed, 127 insertions(+), 43 deletions(-) diff --git a/lib/wsfs/adapter/server_protocol.c b/lib/wsfs/adapter/server_protocol.c index 9f8c503..2d037c4 100644 --- a/lib/wsfs/adapter/server_protocol.c +++ b/lib/wsfs/adapter/server_protocol.c @@ -34,31 +34,31 @@ static int wsfs_server_protocol_callback( } break; case LWS_CALLBACK_ESTABLISHED: - { - bool is_authenticated = wsfs_authenticators_authenticate(&protocol->authenticators, NULL); - wsfs_session_manager_add(&protocol->session_manager, wsi, is_authenticated); - } + session = wsfs_session_manager_add( + &protocol->session_manager, + wsi, + &protocol->authenticators, + &protocol->rpc); + + if (NULL != session) + { + wsfs_session_authenticate(session, NULL); + } break; case LWS_CALLBACK_CLOSED: - { - wsfs_session_manager_remove(&protocol->session_manager, wsi); - } + wsfs_session_manager_remove(&protocol->session_manager, wsi); break; case LWS_CALLBACK_SERVER_WRITEABLE: - if ((NULL != session) && (!wsfs_message_queue_empty(&session->queue))) + if (NULL != session) { - struct wsfs_message * message = wsfs_message_queue_pop(&session->queue); - lws_write(wsi, (unsigned char*) message->data, message->length, LWS_WRITE_TEXT); - wsfs_message_dispose(message); - - if (!wsfs_message_queue_empty(&session->queue)) - { - lws_callback_on_writable(wsi); - } + wsfs_session_onwritable(session); } break; case LWS_CALLBACK_RECEIVE: - wsfs_jsonrpc_server_onresult(&protocol->rpc, in, len); + if (NULL != session) + { + wsfs_session_receive(session, in, len); + } break; case LWS_CALLBACK_RAW_RX_FILE: wsfs_filesystem_process_request(&protocol->filesystem); @@ -74,21 +74,11 @@ static bool wsfs_server_protocol_invoke( void * user_data, json_t const * request) { - bool result = false; struct wsfs_server_protocol * protocol = user_data; struct wsfs_session * session = &protocol->session_manager.session; + struct wsfs_message * message = wsfs_message_create(request); - if ((session->is_authenticated) && (NULL != session->wsi)) - { - struct wsfs_message * message = wsfs_message_create(request); - if (NULL != message) - { - wsfs_message_queue_push(&session->queue, message); - lws_callback_on_writable(session->wsi); - - result = true; - } - } + bool const result = wsfs_session_send(session, message); return result; } diff --git a/lib/wsfs/adapter/session.c b/lib/wsfs/adapter/session.c index 4ad8606..1112e64 100644 --- a/lib/wsfs/adapter/session.c +++ b/lib/wsfs/adapter/session.c @@ -1,14 +1,23 @@ #include "wsfs/adapter/session.h" +#include "wsfs/adapter/authenticators.h" +#include "wsfs/message_queue.h" +#include "wsfs/message.h" +#include "wsfs/adapter/jsonrpc/server.h" + +#include #include void wsfs_session_init( struct wsfs_session * session, struct lws * wsi, - bool is_authenticated) + struct wsfs_authenticators * authenticators, + struct wsfs_jsonrpc_server * rpc) { - session->wsi = wsi; - session->is_authenticated = is_authenticated; - wsfs_message_queue_init(&session->queue); + session->wsi = wsi; + session->is_authenticated = false; + session->authenticators = authenticators; + session->rpc = rpc; + wsfs_message_queue_init(&session->queue); } void wsfs_session_cleanup( @@ -17,4 +26,59 @@ void wsfs_session_cleanup( wsfs_message_queue_cleanup(&session->queue); session->is_authenticated = false; session->wsi = NULL; + session->authenticators = NULL; + session->rpc = NULL; +} + +void wsfs_session_authenticate( + struct wsfs_session * session, + struct wsfs_credentials * creds) +{ + session->is_authenticated = wsfs_authenticators_authenticate(session->authenticators, creds); +} + +bool wsfs_session_send( + struct wsfs_session * session, + struct wsfs_message * message) +{ + bool result = (session->is_authenticated) && (NULL != session->wsi); + + if (result) + { + wsfs_message_queue_push(&session->queue, message); + lws_callback_on_writable(session->wsi); + + result = true; + } + else + { + wsfs_message_dispose(message); + } + + return result; +} + +void wsfs_session_onwritable( + struct wsfs_session * session) +{ + if (!wsfs_message_queue_empty(&session->queue)) + { + struct wsfs_message * message = wsfs_message_queue_pop(&session->queue); + lws_write(session->wsi, (unsigned char*) message->data, message->length, LWS_WRITE_TEXT); + wsfs_message_dispose(message); + + if (!wsfs_message_queue_empty(&session->queue)) + { + lws_callback_on_writable(session->wsi); + } + } +} + + +void wsfs_session_receive( + struct wsfs_session * session, + char const * data, + size_t length) +{ + wsfs_jsonrpc_server_onresult(session->rpc, data, length); } \ No newline at end of file diff --git a/lib/wsfs/adapter/session.h b/lib/wsfs/adapter/session.h index 3c45341..86d41d8 100644 --- a/lib/wsfs/adapter/session.h +++ b/lib/wsfs/adapter/session.h @@ -3,6 +3,10 @@ #ifndef __cplusplus #include +#include +#else +#include +using std::size_t; #endif #include "wsfs/message_queue.h" @@ -13,18 +17,41 @@ extern "C" #endif struct lws; +struct wsfs_message; +struct wsfs_credentials; +struct wsfs_authenticators; +struct wsfs_jsonrpc_server; struct wsfs_session { struct lws * wsi; bool is_authenticated; struct wsfs_message_queue queue; + struct wsfs_authenticators * authenticators; + struct wsfs_jsonrpc_server * rpc; }; extern void wsfs_session_init( struct wsfs_session * session, struct lws * wsi, - bool is_authenticated); + struct wsfs_authenticators * authenticators, + struct wsfs_jsonrpc_server * rpc); + +extern void wsfs_session_authenticate( + struct wsfs_session * session, + struct wsfs_credentials * creds); + +extern bool wsfs_session_send( + struct wsfs_session * session, + struct wsfs_message * message); + +extern void wsfs_session_receive( + struct wsfs_session * session, + char const * data, + size_t length); + +extern void wsfs_session_onwritable( + struct wsfs_session * session); extern void wsfs_session_cleanup( struct wsfs_session * session); diff --git a/lib/wsfs/adapter/session_manager.c b/lib/wsfs/adapter/session_manager.c index 73e332e..290398e 100644 --- a/lib/wsfs/adapter/session_manager.c +++ b/lib/wsfs/adapter/session_manager.c @@ -4,7 +4,7 @@ void wsfs_session_manager_init( struct wsfs_session_manager * manager) { - wsfs_session_init(&manager->session, NULL, false); + wsfs_session_init(&manager->session, NULL, NULL, NULL); } void wsfs_session_manager_cleanup( @@ -13,18 +13,20 @@ void wsfs_session_manager_cleanup( wsfs_session_cleanup(&manager->session); } -bool wsfs_session_manager_add( +struct wsfs_session * wsfs_session_manager_add( struct wsfs_session_manager * manager, struct lws * wsi, - bool is_authenticated) + struct wsfs_authenticators * authenticators, + struct wsfs_jsonrpc_server * rpc) { - bool const result = (NULL == manager->session.wsi); - if (result) + struct wsfs_session * session = NULL; + if (NULL == manager->session.wsi) { - wsfs_session_init(&manager->session, wsi, is_authenticated); + session = &manager->session; + wsfs_session_init(&manager->session, wsi, authenticators, rpc); } - return result; + return session; } struct wsfs_session * wsfs_session_manager_get( diff --git a/lib/wsfs/adapter/session_manager.h b/lib/wsfs/adapter/session_manager.h index b21eeab..d047aef 100644 --- a/lib/wsfs/adapter/session_manager.h +++ b/lib/wsfs/adapter/session_manager.h @@ -25,10 +25,11 @@ extern void wsfs_session_manager_init( extern void wsfs_session_manager_cleanup( struct wsfs_session_manager * manager); -extern bool wsfs_session_manager_add( +extern struct wsfs_session * wsfs_session_manager_add( struct wsfs_session_manager * manager, struct lws * wsi, - bool is_authenticated); + struct wsfs_authenticators * authenticators, + struct wsfs_jsonrpc_server * rpc); extern struct wsfs_session * wsfs_session_manager_get( struct wsfs_session_manager * manager,