From 06a24e09da2724ea02b201e4afafb1096d42f38e Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Thu, 11 Jun 2020 18:07:42 +0200 Subject: [PATCH] added wf_client_tlsconfig --- include/webfuse/adapter/client_callback.h | 7 +- include/webfuse/adapter/client_tlsconfig.h | 32 +++++++++ include/webfuse/core/protocol_names.h | 12 ++++ include/webfuse_adapter.h | 1 + lib/webfuse/adapter/api.c | 26 +++++++ lib/webfuse/adapter/impl/client.c | 58 ++++++++++++++-- lib/webfuse/adapter/impl/client_protocol.c | 55 +++++++++++++++ lib/webfuse/adapter/impl/client_protocol.h | 51 ++++++++++++++ lib/webfuse/adapter/impl/client_tlsconfig.c | 55 +++++++++++++++ lib/webfuse/adapter/impl/client_tlsconfig.h | 52 ++++++++++++++ meson.build | 3 + .../tests/adapter/test_client_tlsconfig.cc | 69 +++++++++++++++++++ 12 files changed, 412 insertions(+), 9 deletions(-) create mode 100644 include/webfuse/adapter/client_tlsconfig.h create mode 100644 lib/webfuse/adapter/impl/client_protocol.c create mode 100644 lib/webfuse/adapter/impl/client_protocol.h create mode 100644 lib/webfuse/adapter/impl/client_tlsconfig.c create mode 100644 lib/webfuse/adapter/impl/client_tlsconfig.h create mode 100644 test/webfuse/tests/adapter/test_client_tlsconfig.cc diff --git a/include/webfuse/adapter/client_callback.h b/include/webfuse/adapter/client_callback.h index b603a1c..90aabab 100644 --- a/include/webfuse/adapter/client_callback.h +++ b/include/webfuse/adapter/client_callback.h @@ -7,8 +7,9 @@ extern "C" #endif -#define WF_CLIENT_CREATED 0x0001 -#define WF_CLIENT_DISPOSING 0x0002 +#define WF_CLIENT_INIT 0x0001 +#define WF_CLIENT_CLEANUP 0x0002 +#define WF_CLIENT_CREATED 0x0003 #define WF_CLIENT_CONNECTED 0x0011 #define WF_CLIENT_DISCONNECTED 0x0012 @@ -20,6 +21,8 @@ extern "C" #define WF_CLIENT_FILESYSTEM_ADDED 0x0031 #define WF_CLIENT_FILESYSTEM_ADD_FAILED 0x0032 +#define WF_CLIENT_GET_TLS_CONFIG 0x0041 + struct wf_client; typedef void wf_client_callback_fn( diff --git a/include/webfuse/adapter/client_tlsconfig.h b/include/webfuse/adapter/client_tlsconfig.h new file mode 100644 index 0000000..c2b5298 --- /dev/null +++ b/include/webfuse/adapter/client_tlsconfig.h @@ -0,0 +1,32 @@ +#ifndef WF_ADAPTER_CLIENT_TLSCONFIG_H +#define WF_ADAPTER_CLIENT_TLSCONFIG_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wf_client_tlsconfig; + +extern WF_API void +wf_client_tlsconfig_set_keypath( + struct wf_client_tlsconfig * config, + char const * key_path); + +extern WF_API void +wf_client_tlsconfig_set_certpath( + struct wf_client_tlsconfig * config, + char const * cert_path); + +extern WF_API void +wf_client_tlsconfig_set_cafilepath( + struct wf_client_tlsconfig * config, + char const * cafile_path); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/webfuse/core/protocol_names.h b/include/webfuse/core/protocol_names.h index 4de8c4a..aa9abfe 100644 --- a/include/webfuse/core/protocol_names.h +++ b/include/webfuse/core/protocol_names.h @@ -12,10 +12,22 @@ //------------------------------------------------------------------------------ #define WF_PROTOCOL_NAME_ADAPTER_SERVER ("webfuse-adapter-server") +//------------------------------------------------------------------------------ +/// \def WF_PROTOCOL_NAME_ADAPTER_CLIENT +/// \brief Name of the websocket protocol an adapter client is running. +//------------------------------------------------------------------------------ +#define WF_PROTOCOL_NAME_ADAPTER_CLIENT ("webfuse-adapter-client") + //------------------------------------------------------------------------------ /// \def WF_PROTOCOL_NAME_PROVIDER_CLIENT /// \brief Name of the websocket protocol an provider client is running. //------------------------------------------------------------------------------ #define WF_PROTOCOL_NAME_PROVIDER_CLIENT ("webfuse-provider-client") +//------------------------------------------------------------------------------ +/// \def WF_PROTOCOL_NAME_PROVIDER_SERVER +/// \brief Name of the websocket protocol an provider server is running. +//------------------------------------------------------------------------------ +#define WF_PROTOCOL_NAME_PROVIDER_SERVER ("webfuse-provider-server") + #endif diff --git a/include/webfuse_adapter.h b/include/webfuse_adapter.h index a198e8b..093fd06 100644 --- a/include/webfuse_adapter.h +++ b/include/webfuse_adapter.h @@ -19,6 +19,7 @@ #include #include +#include #endif diff --git a/lib/webfuse/adapter/api.c b/lib/webfuse/adapter/api.c index 382a6c4..cdef689 100644 --- a/lib/webfuse/adapter/api.c +++ b/lib/webfuse/adapter/api.c @@ -9,6 +9,7 @@ #include "webfuse/core/util.h" #include "webfuse/adapter/impl/client.h" +#include "webfuse/adapter/impl/client_tlsconfig.h" // server @@ -265,3 +266,28 @@ wf_client_add_filesystem( wf_impl_client_add_filesystem(client, local_path, name); } +// client_tlsconfig + +void +wf_client_tlsconfig_set_keypath( + struct wf_client_tlsconfig * config, + char const * key_path) +{ + wf_impl_client_tlsconfig_set_keypath(config, key_path); +} + +void +wf_client_tlsconfig_set_certpath( + struct wf_client_tlsconfig * config, + char const * cert_path) +{ + wf_impl_client_tlsconfig_set_certpath(config, cert_path); +} + +void +wf_client_tlsconfig_set_cafilepath( + struct wf_client_tlsconfig * config, + char const * cafile_path) +{ + wf_impl_client_tlsconfig_set_cafilepath(config, cafile_path); +} diff --git a/lib/webfuse/adapter/impl/client.c b/lib/webfuse/adapter/impl/client.c index cefe39c..58f00b5 100644 --- a/lib/webfuse/adapter/impl/client.c +++ b/lib/webfuse/adapter/impl/client.c @@ -1,10 +1,22 @@ #include "webfuse/adapter/impl/client.h" +#include "webfuse/adapter/impl/client_protocol.h" +#include "webfuse/adapter/impl/client_tlsconfig.h" +#include "webfuse/core/lws_log.h" + +#include #include +#include + +#define WF_CLIENT_PROTOCOL_COUNT 2 struct wf_client { - wf_client_callback_fn * callback; + struct wf_client_protocol protocol; + struct lws_context_creation_info info; + struct lws_protocols protocols[WF_CLIENT_PROTOCOL_COUNT]; + struct wf_client_tlsconfig tls; + struct lws_context * context; void * user_data; }; @@ -13,12 +25,42 @@ wf_impl_client_create( wf_client_callback_fn * callback, void * user_data) { + wf_lwslog_disable(); + struct wf_client * client = malloc(sizeof(struct wf_client)); - client->callback = callback; + wf_impl_client_tlsconfig_init(&client->tls); client->user_data = user_data; + wf_impl_client_protocol_init(&client->protocol, + (wf_client_callback_fn*) callback, (void*) client); + + memset(client->protocols, 0, sizeof(struct lws_protocols) * WF_CLIENT_PROTOCOL_COUNT); + wf_impl_client_protocol_init_lws(&client->protocol, &client->protocols[0]); + + memset(&client->info, 0, sizeof(struct lws_context_creation_info)); + client->info.port = CONTEXT_PORT_NO_LISTEN; + client->info.protocols = client->protocols; + client->info.uid = -1; + client->info.gid = -1; + + wf_impl_client_protocol_callback(&client->protocol, WF_CLIENT_GET_TLS_CONFIG, &client->tls); + if (wf_impl_client_tlsconfig_isset(&client->tls)) + { + client->info.options |= LWS_SERVER_OPTION_EXPLICIT_VHOSTS; + } + + client->context = lws_create_context(&client->info); - client->callback(client, WF_CLIENT_CREATED, NULL); + if (wf_impl_client_tlsconfig_isset(&client->tls)) + { + struct lws_vhost * vhost = lws_create_vhost(client->context, &client->info); + client->info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT; + client->info.client_ssl_cert_filepath = client->tls.cert_path; + client->info.client_ssl_private_key_filepath = client->tls.key_path; + client->info.client_ssl_ca_filepath = client->tls.cafile_path; + lws_init_vhost_client_ssl(&client->info, vhost); + } + wf_impl_client_protocol_callback(&client->protocol, WF_CLIENT_CREATED ,NULL); return client; } @@ -26,7 +68,9 @@ void wf_impl_client_dispose( struct wf_client * client) { - client->callback(client, WF_CLIENT_DISPOSING, NULL); + lws_context_destroy(client->context); + wf_impl_client_protocol_cleanup(&client->protocol); + wf_impl_client_tlsconfig_cleanup(&client->tls); free(client); } @@ -57,7 +101,7 @@ wf_impl_client_connect( char const * url) { (void) url; - client->callback(client, WF_CLIENT_DISCONNECTED, NULL); + wf_impl_client_protocol_callback(&client->protocol, WF_CLIENT_DISCONNECTED, NULL); } void @@ -71,7 +115,7 @@ void wf_impl_client_authenticate( struct wf_client * client) { - client->callback(client, WF_CLIENT_AUTHENTICATION_FAILED, NULL); + wf_impl_client_protocol_callback(&client->protocol, WF_CLIENT_AUTHENTICATION_FAILED, NULL); } void @@ -83,5 +127,5 @@ wf_impl_client_add_filesystem( (void) local_path; (void) name; - client->callback(client, WF_CLIENT_FILESYSTEM_ADD_FAILED, NULL); + wf_impl_client_protocol_callback(&client->protocol, WF_CLIENT_FILESYSTEM_ADD_FAILED, NULL); } diff --git a/lib/webfuse/adapter/impl/client_protocol.c b/lib/webfuse/adapter/impl/client_protocol.c new file mode 100644 index 0000000..d197ceb --- /dev/null +++ b/lib/webfuse/adapter/impl/client_protocol.c @@ -0,0 +1,55 @@ +#include "webfuse/adapter/impl/client_protocol.h" +#include "webfuse/adapter/client_callback.h" +#include "webfuse/core/protocol_names.h" +#include "webfuse/core/util.h" + +#include +#include + +static int wf_impl_client_protocol_lws_callback( + struct lws * WF_UNUSED_PARAM(wsi), + enum lws_callback_reasons WF_UNUSED_PARAM(reason), + void * WF_UNUSED_PARAM(user), + void * WF_UNUSED_PARAM(in), + size_t WF_UNUSED_PARAM(len)) +{ + return 0; +} + +void +wf_impl_client_protocol_init( + struct wf_client_protocol * protocol, + wf_client_callback_fn * callback, + void * user_data) +{ + protocol->callback = callback; + protocol->user_data = user_data; + protocol->callback(protocol->user_data, WF_CLIENT_INIT, NULL); +} + +void +wf_impl_client_protocol_cleanup( + struct wf_client_protocol * protocol) +{ + protocol->callback(protocol->user_data, WF_CLIENT_CLEANUP, NULL); +} + +void +wf_impl_client_protocol_callback( + struct wf_client_protocol * protocol, + int reason, + void * arg) +{ + protocol->callback(protocol->user_data, reason, arg); +} + +void +wf_impl_client_protocol_init_lws( + struct wf_client_protocol * protocol, + struct lws_protocols * lws_protocol) +{ + lws_protocol->name = WF_PROTOCOL_NAME_ADAPTER_CLIENT; + lws_protocol->callback = &wf_impl_client_protocol_lws_callback; + lws_protocol->per_session_data_size = 0; + lws_protocol->user = protocol; +} diff --git a/lib/webfuse/adapter/impl/client_protocol.h b/lib/webfuse/adapter/impl/client_protocol.h new file mode 100644 index 0000000..4f00bb5 --- /dev/null +++ b/lib/webfuse/adapter/impl/client_protocol.h @@ -0,0 +1,51 @@ +#ifndef WF_ADAPTER_IMPL_CLIENT_PROTOCOL_H +#define WF_ADAPTER_IMPL_CLIENT_PROTOCOL_H + +#include "webfuse/adapter/client_callback.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct lws_protocols; + +typedef void +wf_client_protocol_callback_fn( + void * user_data, + int reason, + void * arg); + +struct wf_client_protocol +{ + wf_client_callback_fn * callback; + void * user_data; +}; + +extern void +wf_impl_client_protocol_init( + struct wf_client_protocol * protocol, + wf_client_callback_fn * callback, + void * user_data); + +extern void +wf_impl_client_protocol_cleanup( + struct wf_client_protocol * protocol); + +extern void +wf_impl_client_protocol_callback( + struct wf_client_protocol * protocol, + int reason, + void * arg); + +extern void +wf_impl_client_protocol_init_lws( + struct wf_client_protocol * protocol, + struct lws_protocols * lws_protocol); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/lib/webfuse/adapter/impl/client_tlsconfig.c b/lib/webfuse/adapter/impl/client_tlsconfig.c new file mode 100644 index 0000000..0c1c419 --- /dev/null +++ b/lib/webfuse/adapter/impl/client_tlsconfig.c @@ -0,0 +1,55 @@ +#include "webfuse/adapter/impl/client_tlsconfig.h" +#include +#include + +void +wf_impl_client_tlsconfig_init( + struct wf_client_tlsconfig * config) +{ + config->key_path = NULL; + config->cert_path = NULL; + config->cafile_path = NULL; +} + +void +wf_impl_client_tlsconfig_cleanup( + struct wf_client_tlsconfig * config) +{ + free(config->key_path); + free(config->cert_path); + free(config->cafile_path); +} + +void +wf_impl_client_tlsconfig_set_keypath( + struct wf_client_tlsconfig * config, + char const * key_path) +{ + free(config->key_path); + config->key_path = strdup(key_path); +} + +void +wf_impl_client_tlsconfig_set_certpath( + struct wf_client_tlsconfig * config, + char const * cert_path) +{ + free(config->cert_path); + config->cert_path = strdup(cert_path); +} + +void +wf_impl_client_tlsconfig_set_cafilepath( + struct wf_client_tlsconfig * config, + char const * cafile_path) +{ + free(config->cafile_path); + config->cafile_path = strdup(cafile_path); +} + +bool +wf_impl_client_tlsconfig_isset( + struct wf_client_tlsconfig const * config) +{ + return (NULL != config->cert_path) && (NULL != config->key_path); +} diff --git a/lib/webfuse/adapter/impl/client_tlsconfig.h b/lib/webfuse/adapter/impl/client_tlsconfig.h new file mode 100644 index 0000000..1bbddeb --- /dev/null +++ b/lib/webfuse/adapter/impl/client_tlsconfig.h @@ -0,0 +1,52 @@ +#ifndef WF_ADAPTER_IMPL_CLIENT_TLSCONFIG_H +#define WF_ADAPTER_IMPL_CLIENT_TLSCONFIG_H + +#ifndef __cplusplus +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct wf_client_tlsconfig +{ + char * key_path; + char * cert_path; + char * cafile_path; +}; + +extern void +wf_impl_client_tlsconfig_init( + struct wf_client_tlsconfig * config); + +extern void +wf_impl_client_tlsconfig_cleanup( + struct wf_client_tlsconfig * config); + +extern void +wf_impl_client_tlsconfig_set_keypath( + struct wf_client_tlsconfig * config, + char const * key_path); + +extern void +wf_impl_client_tlsconfig_set_certpath( + struct wf_client_tlsconfig * config, + char const * cert_path); + +extern void +wf_impl_client_tlsconfig_set_cafilepath( + struct wf_client_tlsconfig * config, + char const * cafile_path); + +extern bool +wf_impl_client_tlsconfig_isset( + struct wf_client_tlsconfig const * config); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/meson.build b/meson.build index 4f58ab0..76ac684 100644 --- a/meson.build +++ b/meson.build @@ -133,6 +133,8 @@ webfuse_adapter_static = static_library('webfuse_adapter', 'lib/webfuse/adapter/impl/operation/close.c', 'lib/webfuse/adapter/impl/operation/read.c', 'lib/webfuse/adapter/impl/client.c', + 'lib/webfuse/adapter/impl/client_protocol.c', + 'lib/webfuse/adapter/impl/client_tlsconfig.c', c_args: ['-fvisibility=hidden'], include_directories: private_inc_dir, dependencies: [webfuse_core_dep, libfuse_dep]) @@ -252,6 +254,7 @@ alltests = executable('alltests', 'test/webfuse/tests/integration/server.cc', 'test/webfuse/tests/integration/provider.cc', 'test/webfuse/tests/adapter/test_client.cc', + 'test/webfuse/tests/adapter/test_client_tlsconfig.cc', link_args: [ '-Wl,--wrap=wf_timer_manager_create', '-Wl,--wrap=wf_timer_manager_dispose', diff --git a/test/webfuse/tests/adapter/test_client_tlsconfig.cc b/test/webfuse/tests/adapter/test_client_tlsconfig.cc new file mode 100644 index 0000000..788b906 --- /dev/null +++ b/test/webfuse/tests/adapter/test_client_tlsconfig.cc @@ -0,0 +1,69 @@ +#include +#include "webfuse/adapter/client_tlsconfig.h" +#include "webfuse/adapter/impl/client_tlsconfig.h" + +TEST(ClientTlsConfig, InitAndCleanup) +{ + wf_client_tlsconfig config; + + wf_impl_client_tlsconfig_init(&config); + wf_impl_client_tlsconfig_cleanup(&config); +} + +TEST(ClientTlsConfig, SetKeyPath) +{ + wf_client_tlsconfig config; + wf_impl_client_tlsconfig_init(&config); + + wf_client_tlsconfig_set_keypath(&config, "/path/to/key.pem"); + ASSERT_STREQ("/path/to/key.pem", config.key_path); + + wf_impl_client_tlsconfig_cleanup(&config); +} + +TEST(ClientTlsConfig, SetCertPath) +{ + wf_client_tlsconfig config; + wf_impl_client_tlsconfig_init(&config); + + wf_client_tlsconfig_set_certpath(&config, "/path/to/cert.pem"); + ASSERT_STREQ("/path/to/cert.pem", config.cert_path); + + wf_impl_client_tlsconfig_cleanup(&config); +} + +TEST(ClientTlsConfig, SetCafilePath) +{ + wf_client_tlsconfig config; + wf_impl_client_tlsconfig_init(&config); + + wf_client_tlsconfig_set_cafilepath(&config, "/path/to/cafile.pem"); + ASSERT_STREQ("/path/to/cafile.pem", config.cafile_path); + + wf_impl_client_tlsconfig_cleanup(&config); +} + +TEST(ClientTslConfig, IsSet) +{ + wf_client_tlsconfig config; + + wf_impl_client_tlsconfig_init(&config); + ASSERT_FALSE(wf_impl_client_tlsconfig_isset(&config)); + wf_impl_client_tlsconfig_cleanup(&config); + + wf_impl_client_tlsconfig_init(&config); + wf_client_tlsconfig_set_keypath(&config, "/path/to/key.pem"); + ASSERT_FALSE(wf_impl_client_tlsconfig_isset(&config)); + wf_impl_client_tlsconfig_cleanup(&config); + + wf_impl_client_tlsconfig_init(&config); + wf_client_tlsconfig_set_certpath(&config, "/path/to/cert.pem"); + ASSERT_FALSE(wf_impl_client_tlsconfig_isset(&config)); + wf_impl_client_tlsconfig_cleanup(&config); + + wf_impl_client_tlsconfig_init(&config); + wf_client_tlsconfig_set_keypath(&config, "/path/to/key.pem"); + wf_client_tlsconfig_set_certpath(&config, "/path/to/cert.pem"); + ASSERT_TRUE(wf_impl_client_tlsconfig_isset(&config)); + wf_impl_client_tlsconfig_cleanup(&config); +} \ No newline at end of file