1
0
mirror of https://github.com/falk-werner/webfuse synced 2025-06-13 12:54:15 +00:00
falk-werner_webfuse/lib/webfuse/adapter/impl/server_protocol.c
Falk Werner 3a7c064af7 feat(webfuse): add multiclient support (#23)
* fixes verbosity option when set through command line

* adds support for build type and allows to run gdb in container

* adds missing toolchain headers to project

* renames container macros

* adds gdbserver

* fixes verbosity option when set through command line

* adds support for build type and allows to run gdb in container

* adds missing toolchain headers to project

* renames container macros

* adds gdbserver

* removes language settings, which contains alternating values

* adds wrapper script to launch gdbserver

* fix docker command in wrapper script

* fixes run in dind setup

* replaces docker's init through dump-init

* moves filesystem to session

* fixes verbosity option when set through command line

* adds support for build type and allows to run gdb in container

* renames container macros

* adds gdbserver

* fixes verbosity option when set through command line

* adds support for build type and allows to run gdb in container

* renames container macros

* adds gdbserver

* adds wrapper script to launch gdbserver

* fix docker command in wrapper script

* fixes run in dind setup

* replaces docker's init through dump-init

* moves filesystem to session

* adds container_of

* added dlist

* allows multiple clients to connect

* removes directory when session is closed

* adds dependecy to uuid-dev

* allow clients to register filesystems

* updates documentation

* moves mountpoint handling into filesystem: mountpoints are removed during session cleanup

* adds filesystem name/id to request parameters

* fixes security issue: add_filesystem did not check name

* removes default link, if it is broken

* recreates symlink "default", if filesystem is gone

* updates documentation

* fixes memory leak

* makes authentication work .. again

* updates provider to support changed protocol

* removes execute right of hello.txt

* fixes style issues

* fixes javascript style issues

* fixes flase positive from Flawfinder

* fixes some javascript style issues

* removes use of PATH_MAX

* removes use of GNU extensions in container_of implementation

* ignores findings of flawfinder

* replaces dlist by slist

* removes duplicate implementation of slist (message_queue)
2019-04-17 22:51:16 +02:00

232 lines
6.4 KiB
C

#include "webfuse/adapter/impl/server_protocol.h"
#include <stdlib.h>
#include <ctype.h>
#include <libwebsockets.h>
#include "webfuse/core/message.h"
#include "webfuse/core/util.h"
#include "webfuse/adapter/impl/credentials.h"
#include "webfuse/adapter/impl/jsonrpc/request.h"
static int wf_impl_server_protocol_callback(
struct lws * wsi,
enum lws_callback_reasons reason,
void * WF_UNUSED_PARAM(user),
void * in,
size_t len)
{
struct lws_protocols const * ws_protocol = lws_get_protocol(wsi);
struct wf_server_protocol * protocol = ws_protocol->user;
wf_impl_timeout_manager_check(&protocol->timeout_manager);
struct wf_impl_session * session = wf_impl_session_manager_get(&protocol->session_manager, wsi);
switch (reason)
{
case LWS_CALLBACK_ESTABLISHED:
session = wf_impl_session_manager_add(
&protocol->session_manager,
wsi,
&protocol->authenticators,
&protocol->timeout_manager,
&protocol->server,
protocol->mount_point);
if (NULL != session)
{
wf_impl_session_authenticate(session, NULL);
}
break;
case LWS_CALLBACK_CLOSED:
wf_impl_session_manager_remove(&protocol->session_manager, wsi);
break;
case LWS_CALLBACK_SERVER_WRITEABLE:
if (NULL != session)
{
wf_impl_session_onwritable(session);
}
break;
case LWS_CALLBACK_RECEIVE:
if (NULL != session)
{
wf_impl_session_receive(session, in, len);
}
break;
case LWS_CALLBACK_RAW_RX_FILE:
if (NULL != session)
{
wf_impl_session_process_filesystem_request(session, wsi);
}
break;
default:
break;
}
return 0;
}
struct wf_server_protocol * wf_impl_server_protocol_create(
char * mount_point)
{
struct wf_server_protocol * protocol = malloc(sizeof(struct wf_server_protocol));
if (NULL != protocol)
{
wf_impl_server_protocol_init(protocol, mount_point);
}
return protocol;
}
void wf_impl_server_protocol_dispose(
struct wf_server_protocol * protocol)
{
wf_impl_server_protocol_cleanup(protocol);
free(protocol);
}
void wf_impl_server_protocol_init_lws(
struct wf_server_protocol * protocol,
struct lws_protocols * lws_protocol)
{
lws_protocol->callback = &wf_impl_server_protocol_callback;
lws_protocol->per_session_data_size = 0;
lws_protocol->user = protocol;
}
static void wf_impl_server_protocol_authenticate(
struct wf_impl_jsonrpc_request * request,
char const * WF_UNUSED_PARAM(method_name),
json_t * params,
void * WF_UNUSED_PARAM(user_data))
{
bool result = false;
json_t * type_holder = json_array_get(params, 0);
json_t * creds_holder = json_array_get(params, 1);
if (json_is_string(type_holder) && json_is_object(creds_holder))
{
char const * type = json_string_value(type_holder);
struct wf_credentials creds;
wf_impl_credentials_init(&creds, type, creds_holder);
struct wf_impl_session * session = wf_impl_jsonrpc_request_get_userdata(request);
result = wf_impl_session_authenticate(session, &creds);
wf_impl_credentials_cleanup(&creds);
}
if (result)
{
json_t * result = json_object();
wf_impl_jsonrpc_respond(request, result);
}
else
{
wf_impl_jsonrpc_respond_error(request, WF_BAD_ACCESS_DENIED);
}
}
static bool wf_impl_server_protocol_check_name(char const * value)
{
while ('\0' != *value)
{
char const c = * value;
if (!isalpha(c) && !isdigit(c) && ('_' != c))
{
return false;
}
value++;
}
return true;
}
static void wf_impl_server_protocol_add_filesystem(
struct wf_impl_jsonrpc_request * request,
char const * WF_UNUSED_PARAM(method_name),
json_t * params,
void * WF_UNUSED_PARAM(user_data))
{
struct wf_impl_session * session = wf_impl_jsonrpc_request_get_userdata(request);
wf_status status = (session->is_authenticated) ? WF_GOOD : WF_BAD_ACCESS_DENIED;
char const * name = NULL;
if (WF_GOOD == status)
{
json_t * name_holder = json_array_get(params, 0);
if (json_is_string(name_holder))
{
name = json_string_value(name_holder);
if (wf_impl_server_protocol_check_name(name))
{
bool const success = wf_impl_session_add_filesystem(session, name);
if (!success)
{
status = WF_BAD;
}
}
else
{
status = WF_BAD_FORMAT;
}
}
else
{
status = WF_BAD_FORMAT;
}
}
if (WF_GOOD == status)
{
json_t * result = json_object();
json_object_set_new(result, "id", json_string(name));
wf_impl_jsonrpc_respond(request, result);
}
else
{
wf_impl_jsonrpc_respond_error(request, status);
}
}
void wf_impl_server_protocol_init(
struct wf_server_protocol * protocol,
char * mount_point)
{
protocol->mount_point = strdup(mount_point);
wf_impl_timeout_manager_init(&protocol->timeout_manager);
wf_impl_session_manager_init(&protocol->session_manager);
wf_impl_authenticators_init(&protocol->authenticators);
wf_impl_jsonrpc_server_init(&protocol->server);
wf_impl_jsonrpc_server_add(&protocol->server, "authenticate", &wf_impl_server_protocol_authenticate, protocol);
wf_impl_jsonrpc_server_add(&protocol->server, "add_filesystem", &wf_impl_server_protocol_add_filesystem, protocol);
}
void wf_impl_server_protocol_cleanup(
struct wf_server_protocol * protocol)
{
free(protocol->mount_point);
wf_impl_jsonrpc_server_cleanup(&protocol->server);
wf_impl_timeout_manager_cleanup(&protocol->timeout_manager);
wf_impl_authenticators_cleanup(&protocol->authenticators);
wf_impl_session_manager_cleanup(&protocol->session_manager);
}
void wf_impl_server_protocol_add_authenticator(
struct wf_server_protocol * protocol,
char const * type,
wf_authenticate_fn * authenticate,
void * user_data)
{
wf_impl_authenticators_add(&protocol->authenticators, type, authenticate, user_data);
}