From 7856b5a99d158803c8f07ffd7d92462124e025f1 Mon Sep 17 00:00:00 2001 From: Falk Werner Date: Sun, 1 Mar 2020 13:42:46 +0100 Subject: [PATCH] feature: enabled authentication --- lib/jsonrpc/include/jsonrpc/proxy.h | 15 ++++- lib/jsonrpc/src/jsonrpc/impl/proxy.c | 6 ++ lib/webfuse/provider/impl/client_protocol.c | 65 +++++++++++++++++-- lib/webfuse/provider/impl/credentials.c | 12 ++++ lib/webfuse/provider/impl/credentials.h | 5 ++ lib/webfuse/provider/impl/provider.c | 9 ++- lib/webfuse/provider/impl/provider.h | 8 +++ .../tests/provider/test_client_protocol.cc | 2 +- 8 files changed, 115 insertions(+), 7 deletions(-) diff --git a/lib/jsonrpc/include/jsonrpc/proxy.h b/lib/jsonrpc/include/jsonrpc/proxy.h index 3f2dca5..a7573fa 100644 --- a/lib/jsonrpc/include/jsonrpc/proxy.h +++ b/lib/jsonrpc/include/jsonrpc/proxy.h @@ -33,7 +33,20 @@ jsonrpc_proxy_create( extern JSONRPC_API void jsonrpc_proxy_dispose( struct jsonrpc_proxy * proxy); - +//------------------------------------------------------------------------------ +/// \brief Invokes a method. +/// +/// Creates a method an sends it using the send function. +/// Proxy keeps track of method invokation. If no response is returned within +/// timeout, an error is propagated. +/// +/// \param proxy pointer to proxy instance +/// \param finished function which is called exactly once, either on success or +/// on failure. +/// \param method_name name of the method to invoke +/// \param param_info types of the param (s = string, i = integer, j = json) +/// \param ... params +//------------------------------------------------------------------------------ extern JSONRPC_API void jsonrpc_proxy_invoke( struct jsonrpc_proxy * proxy, jsonrpc_proxy_finished_fn * finished, diff --git a/lib/jsonrpc/src/jsonrpc/impl/proxy.c b/lib/jsonrpc/src/jsonrpc/impl/proxy.c index caea4a4..976da05 100644 --- a/lib/jsonrpc/src/jsonrpc/impl/proxy.c +++ b/lib/jsonrpc/src/jsonrpc/impl/proxy.c @@ -77,6 +77,12 @@ static json_t * jsonrpc_impl_request_create( json_array_append_new(params, json_integer(value)); } break; + case 'j': + { + json_t * const value = va_arg(args, json_t *); + json_array_append_new(params, value); + } + break; default: fprintf(stderr, "fatal: unknown param_type '%c'\n", *param_type); json_decref(params); diff --git a/lib/webfuse/provider/impl/client_protocol.c b/lib/webfuse/provider/impl/client_protocol.c index fdbcaf1..1b434fc 100644 --- a/lib/webfuse/provider/impl/client_protocol.c +++ b/lib/webfuse/provider/impl/client_protocol.c @@ -8,6 +8,7 @@ #include "webfuse/provider/impl/client_config.h" #include "webfuse/provider/impl/provider.h" +#include "webfuse/provider/impl/credentials.h" #include "webfuse/core/util.h" #include "webfuse/core/message.h" #include "webfuse/core/message_queue.h" @@ -67,14 +68,14 @@ static void wfp_impl_client_protocol_process( } static void -wfp_impl_client_protocol_on_authenticate_finished( +wfp_impl_client_protocol_on_add_filesystem_finished( void * user_data, json_t const * result, json_t const * WF_UNUSED_PARAM(error)) { struct wfp_client_protocol * protocol = user_data; if (NULL == protocol->wsi) { return; } - + if (NULL != result) { protocol->is_connected = true; @@ -92,13 +93,69 @@ static void wfp_impl_client_protocol_add_filesystem( { jsonrpc_proxy_invoke( protocol->proxy, - &wfp_impl_client_protocol_on_authenticate_finished, + &wfp_impl_client_protocol_on_add_filesystem_finished, protocol, "add_filesystem", "s", "cprovider"); } +static void +wfp_impl_client_protocol_on_authenticate_finished( + void * user_data, + json_t const * result, + json_t const * WF_UNUSED_PARAM(error)) +{ + struct wfp_client_protocol * protocol = user_data; + if (NULL == protocol->wsi) { return; } + + if (NULL != result) + { + wfp_impl_client_protocol_add_filesystem(protocol); + } + else + { + protocol->is_shutdown_requested = true; + lws_callback_on_writable(protocol->wsi); + } +} + +static void wfp_impl_client_protocol_authenticate( + struct wfp_client_protocol * protocol) +{ + struct wfp_credentials credentials; + wfp_impl_credentials_init(&credentials); + + protocol->provider.get_credentials(&credentials, protocol->user_data); + + char const * cred_type = wfp_impl_credentials_get_type(&credentials); + json_t * creds = wfp_impl_credentials_get(&credentials); + json_incref(creds); + + jsonrpc_proxy_invoke( + protocol->proxy, + &wfp_impl_client_protocol_on_authenticate_finished, + protocol, + "authenticate", + "sj", + cred_type, creds); + + wfp_impl_credentials_cleanup(&credentials); +} + +static void wfp_impl_client_protocol_handshake( + struct wfp_client_protocol * protocol) +{ + if (wfp_impl_provider_is_authentication_enabled(&protocol->provider)) + { + wfp_impl_client_protocol_authenticate(protocol); + } + else + { + wfp_impl_client_protocol_add_filesystem(protocol); + } +} + static int wfp_impl_client_protocol_callback( struct lws * wsi, enum lws_callback_reasons reason, @@ -117,7 +174,7 @@ static int wfp_impl_client_protocol_callback( switch (reason) { case LWS_CALLBACK_CLIENT_ESTABLISHED: - wfp_impl_client_protocol_add_filesystem(protocol); + wfp_impl_client_protocol_handshake(protocol); break; case LWS_CALLBACK_CLIENT_CONNECTION_ERROR: protocol->is_connected = false; diff --git a/lib/webfuse/provider/impl/credentials.c b/lib/webfuse/provider/impl/credentials.c index 8e788ca..f2d254f 100644 --- a/lib/webfuse/provider/impl/credentials.c +++ b/lib/webfuse/provider/impl/credentials.c @@ -32,3 +32,15 @@ void wfp_impl_credentials_add( { json_object_set_new(credentials->contents, key, json_string(value)); } + +char const * wfp_impl_credentials_get_type( + struct wfp_credentials * credentials) +{ + return credentials->type; +} + +json_t * wfp_impl_credentials_get( + struct wfp_credentials * credentials) +{ + return credentials->contents; +} diff --git a/lib/webfuse/provider/impl/credentials.h b/lib/webfuse/provider/impl/credentials.h index 6da40b9..304b067 100644 --- a/lib/webfuse/provider/impl/credentials.h +++ b/lib/webfuse/provider/impl/credentials.h @@ -30,6 +30,11 @@ extern void wfp_impl_credentials_add( char const * key, char const * value); +extern char const * wfp_impl_credentials_get_type( + struct wfp_credentials * credentials); + +extern json_t * wfp_impl_credentials_get( + struct wfp_credentials * credentials); #ifdef __cplusplus } diff --git a/lib/webfuse/provider/impl/provider.c b/lib/webfuse/provider/impl/provider.c index d3ba96c..14282d2 100644 --- a/lib/webfuse/provider/impl/provider.c +++ b/lib/webfuse/provider/impl/provider.c @@ -126,4 +126,11 @@ void wfp_impl_ontimer_default( (void) user_data; // empty -} \ No newline at end of file +} + + bool wfp_impl_provider_is_authentication_enabled( + struct wfp_provider * provider) +{ + return (NULL != provider->get_credentials); +} + diff --git a/lib/webfuse/provider/impl/provider.h b/lib/webfuse/provider/impl/provider.h index 8f6d115..a9b814d 100644 --- a/lib/webfuse/provider/impl/provider.h +++ b/lib/webfuse/provider/impl/provider.h @@ -1,9 +1,14 @@ #ifndef WF_PROVIDER_IMPL_PROVIDER_H #define WF_PROVIDER_IMPL_PROVIDER_H +#ifndef __cplusplus +#include +#endif + #include #include "webfuse/provider/client_config.h" + #ifdef __cplusplus extern "C" { @@ -42,6 +47,9 @@ extern void wfp_impl_provider_invoke( struct wfp_impl_invokation_context * context, json_t * request); +extern bool wfp_impl_provider_is_authentication_enabled( + struct wfp_provider * provider); + extern void wfp_impl_connected_default( void * user_data); diff --git a/test/webfuse/tests/provider/test_client_protocol.cc b/test/webfuse/tests/provider/test_client_protocol.cc index 53529c7..3563949 100644 --- a/test/webfuse/tests/provider/test_client_protocol.cc +++ b/test/webfuse/tests/provider/test_client_protocol.cc @@ -173,7 +173,7 @@ TEST(client_protocol, connect_with_username_authentication) EXPECT_CALL(provider, OnConnected()).Times(AtMost(1)); EXPECT_CALL(provider, OnDisconnected()).Times(1); - EXPECT_CALL(provider, GetCredentials(_)).WillOnce(Invoke(GetCredentials)).Times(1); + EXPECT_CALL(provider, GetCredentials(_)).Times(1).WillOnce(Invoke(GetCredentials)); fixture.Connect(); if (HasFatalFailure()) { return; }