mirror of
https://github.com/falk-werner/webfuse
synced 2024-10-27 20:34:10 +00:00
Feature/authentication (#14)
* makes wsfs_server_config opaque * feature: try to create mount point, if not present * fixes server start failure due to existing mountpoint * added basic authentication infrastructure * makes wsfs_server_config opaque * feature: try to create mount point, if not present * fixes server start failure due to existing mountpoint * added basic authentication infrastructure * added unit tests for credentials * added unit tests for authenticators * propagates authenticators to server protocol * enabled username authentication in daemon example * adds example to compute password hash * adds infrastructure to execute commands * added userdb to encapsulate authentication stuff * adds session and session_manager * fixes warning about unused param * moves some logic from server_protocol to session * makes wsfs_server_config opaque * feature: try to create mount point, if not present * fixes server start failure due to existing mountpoint * added basic authentication infrastructure * makes wsfs_server_config opaque * added unit tests for credentials * added unit tests for authenticators * propagates authenticators to server protocol * enabled username authentication in daemon example * adds example to compute password hash * adds infrastructure to execute commands * added userdb to encapsulate authentication stuff * adds session and session_manager * fixes warning about unused param * moves some logic from server_protocol to session * updates libcrypto to version 1.1.0
This commit is contained in:
parent
de9095a978
commit
48185776b6
@ -58,6 +58,13 @@ install(FILES include/wsfs/status.h DESTINATION include/wsfs)
|
|||||||
set(WSFS_ADAPTER_SOURCES
|
set(WSFS_ADAPTER_SOURCES
|
||||||
lib/wsfs/adapter/filesystem.c
|
lib/wsfs/adapter/filesystem.c
|
||||||
lib/wsfs/adapter/server.c
|
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
|
||||||
lib/wsfs/adapter/time/timepoint.c
|
lib/wsfs/adapter/time/timepoint.c
|
||||||
lib/wsfs/adapter/time/timer.c
|
lib/wsfs/adapter/time/timer.c
|
||||||
lib/wsfs/adapter/time/timeout_manager.c
|
lib/wsfs/adapter/time/timeout_manager.c
|
||||||
@ -67,8 +74,6 @@ set(WSFS_ADAPTER_SOURCES
|
|||||||
lib/wsfs/adapter/operation/open.c
|
lib/wsfs/adapter/operation/open.c
|
||||||
lib/wsfs/adapter/operation/close.c
|
lib/wsfs/adapter/operation/close.c
|
||||||
lib/wsfs/adapter/operation/read.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/server.c
|
||||||
lib/wsfs/adapter/jsonrpc/method.c
|
lib/wsfs/adapter/jsonrpc/method.c
|
||||||
lib/wsfs/adapter/jsonrpc/request.c
|
lib/wsfs/adapter/jsonrpc/request.c
|
||||||
@ -156,6 +161,24 @@ install(FILES "${PROJECT_BINARY_DIR}/libwsfs-provider.pc" DESTINATION lib${LIB_S
|
|||||||
|
|
||||||
if(NOT WITHOUT_EXAMPLE)
|
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
|
# daemon
|
||||||
|
|
||||||
add_executable(wsfsd
|
add_executable(wsfsd
|
||||||
@ -178,6 +201,35 @@ target_link_libraries(wsfs-provider-app PUBLIC wsfs-provider ${EXTRA_LIBS})
|
|||||||
target_include_directories(wsfs-provider-app PUBLIC ${EXTRA_INCLUDE_DIRS})
|
target_include_directories(wsfs-provider-app PUBLIC ${EXTRA_INCLUDE_DIRS})
|
||||||
target_compile_options(wsfs-provider-app PUBLIC ${EXTRA_CFLAGS})
|
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
|
||||||
|
userdb
|
||||||
|
${OPENSSL_LIBRARIES}
|
||||||
|
${JANSSON_LIBRARIES}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(wsfs-passwd PUBLIC
|
||||||
|
example/passwd
|
||||||
|
example/lib/userdb/include
|
||||||
|
${OPENSSL_INCLUDE_DIRS}
|
||||||
|
${JANSSON_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_compile_options(wsfs-passwd PUBLIC
|
||||||
|
${C_WARNINGS}
|
||||||
|
${OPENSSL_CFLAGS_OTHER}
|
||||||
|
${JANSSON_CFLAGS_OTHER}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
endif(NOT WITHOUT_EXAMPLE)
|
endif(NOT WITHOUT_EXAMPLE)
|
||||||
|
|
||||||
# tests
|
# tests
|
||||||
@ -188,6 +240,7 @@ include (CTest)
|
|||||||
|
|
||||||
pkg_check_modules(GTEST gtest_main)
|
pkg_check_modules(GTEST gtest_main)
|
||||||
include(GoogleTest)
|
include(GoogleTest)
|
||||||
|
pkg_check_modules(GMOCK gmock)
|
||||||
|
|
||||||
add_library(wsfs-adapter-static STATIC ${WSFS_ADAPTER_SOURCES})
|
add_library(wsfs-adapter-static STATIC ${WSFS_ADAPTER_SOURCES})
|
||||||
set_target_properties(wsfs-adapter-static PROPERTIES OUTPUT_NAME wsfs-adapter)
|
set_target_properties(wsfs-adapter-static PROPERTIES OUTPUT_NAME wsfs-adapter)
|
||||||
@ -202,17 +255,21 @@ target_compile_options(wsfs-provider-static PUBLIC ${EXTRA_CFLAGS})
|
|||||||
|
|
||||||
add_executable(alltests
|
add_executable(alltests
|
||||||
test/msleep.cc
|
test/msleep.cc
|
||||||
|
test/mock_authenticator.cc
|
||||||
test/test_response_parser.cc
|
test/test_response_parser.cc
|
||||||
test/test_server.cc
|
test/test_server.cc
|
||||||
test/test_timepoint.cc
|
test/test_timepoint.cc
|
||||||
test/test_timer.cc
|
test/test_timer.cc
|
||||||
test/test_url.cc
|
test/test_url.cc
|
||||||
|
test/test_credentials.cc
|
||||||
|
test/test_authenticator.cc
|
||||||
|
test/test_authenticators.cc
|
||||||
${WSFS_COMMON_SOURCES}
|
${WSFS_COMMON_SOURCES}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(alltests PUBLIC wsfs-adapter-static wsfs-provider-static ${EXTRA_LIBS} ${GTEST_LIBRARIES})
|
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} ${GTEST_INCLUDE_DIRS})
|
target_include_directories(alltests PUBLIC lib ${EXTRA_INCLUDE_DIRS} ${GMOCK_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS})
|
||||||
target_compile_options(alltests PUBLIC ${EXTRA_CFLAGS} ${GTEST_CFLAGS})
|
target_compile_options(alltests PUBLIC ${EXTRA_CFLAGS} ${GMOCK_CFLAGS} ${GTEST_CFLAGS})
|
||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
gtest_discover_tests(alltests TEST_PREFIX alltests:)
|
gtest_discover_tests(alltests TEST_PREFIX alltests:)
|
||||||
|
@ -7,12 +7,15 @@
|
|||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#include <jansson.h>
|
||||||
|
|
||||||
#include <wsfs_adapter.h>
|
#include <wsfs_adapter.h>
|
||||||
|
|
||||||
|
|
||||||
struct args
|
struct args
|
||||||
{
|
{
|
||||||
struct wsfs_server_config config;
|
struct wsfs_server_config * config;
|
||||||
|
char * passwd_path;
|
||||||
bool show_help;
|
bool show_help;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -25,7 +28,7 @@ static void show_help(void)
|
|||||||
"Websocket file system daemon\n"
|
"Websocket file system daemon\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Usage: wsfsd [m <mount_point>] [-d <document_root] [-n <vhost_name>] [-p <port>]\n"
|
"Usage: wsfsd [m <mount_point>] [-d <document_root] [-n <vhost_name>] [-p <port>]\n"
|
||||||
" [-c <server_cert_path> -k] [<server_key_path>]\n"
|
" [-c <server_cert_path>] [-k <server_key_path>] [-P <passwd_path>]\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Options:\n"
|
"Options:\n"
|
||||||
"\t-m, --mount_point Path of mount point (required)\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-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-n, --vhost_name Name of virtual host (default: \"localhost\")\n"
|
||||||
"\t-p, --port Number of servers port (default: 8080)\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");
|
"\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 int parse_arguments(int argc, char * argv[], struct args * args)
|
||||||
{
|
{
|
||||||
static struct option const options[] =
|
static struct option const options[] =
|
||||||
@ -47,16 +80,18 @@ static int parse_arguments(int argc, char * argv[], struct args * args)
|
|||||||
{"server_key_path", required_argument, NULL, 'k'},
|
{"server_key_path", required_argument, NULL, 'k'},
|
||||||
{"vhost_name", required_argument, NULL, 'n'},
|
{"vhost_name", required_argument, NULL, 'n'},
|
||||||
{"port", required_argument, NULL, 'p'},
|
{"port", required_argument, NULL, 'p'},
|
||||||
|
{"passwd_path", required_argument, NULL, 'P'},
|
||||||
{"help", no_argument, NULL, 'h'},
|
{"help", no_argument, NULL, 'h'},
|
||||||
{NULL, 0, NULL, 0}
|
{NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool result = EXIT_SUCCESS;
|
bool result = EXIT_SUCCESS;
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
|
bool has_mountpoint = false;
|
||||||
while ((!finished) && (EXIT_SUCCESS == result))
|
while ((!finished) && (EXIT_SUCCESS == result))
|
||||||
{
|
{
|
||||||
int option_index = 0;
|
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)
|
switch (c)
|
||||||
{
|
{
|
||||||
@ -68,27 +103,31 @@ static int parse_arguments(int argc, char * argv[], struct args * args)
|
|||||||
finished = true;
|
finished = true;
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
free(args->config.mount_point);
|
wsfs_server_config_set_mountpoint(args->config, optarg);
|
||||||
args->config.mount_point = strdup(optarg);
|
has_mountpoint = true;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
free(args->config.document_root);
|
wsfs_server_config_set_documentroot(args->config, optarg);
|
||||||
args->config.document_root = strdup(optarg);
|
|
||||||
break;
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
free(args->config.cert_path);
|
wsfs_server_config_set_certpath(args->config, optarg);
|
||||||
args->config.cert_path = strdup(optarg);
|
|
||||||
break;
|
break;
|
||||||
case 'k':
|
case 'k':
|
||||||
free(args->config.key_path);
|
wsfs_server_config_set_keypath(args->config, optarg);
|
||||||
args->config.key_path = strdup(optarg);
|
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
free(args->config.vhost_name);
|
wsfs_server_config_set_vhostname(args->config, optarg);
|
||||||
args->config.vhost_name = strdup(optarg);
|
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
args->config.port = atoi(optarg);
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "error: unknown argument\n");
|
fprintf(stderr, "error: unknown argument\n");
|
||||||
@ -99,7 +138,7 @@ static int parse_arguments(int argc, char * argv[], struct args * args)
|
|||||||
|
|
||||||
if ((EXIT_SUCCESS == result) && (!args->show_help))
|
if ((EXIT_SUCCESS == result) && (!args->show_help))
|
||||||
{
|
{
|
||||||
if (NULL == args->config.mount_point)
|
if (!has_mountpoint)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "error: missing mount point\n");
|
fprintf(stderr, "error: missing mount point\n");
|
||||||
result = EXIT_FAILURE;
|
result = EXIT_FAILURE;
|
||||||
@ -123,26 +162,19 @@ static void on_interrupt(int signal_id)
|
|||||||
|
|
||||||
int main(int argc, char * argv[])
|
int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
struct args args =
|
struct args args;
|
||||||
{
|
args.config = wsfs_server_config_create();
|
||||||
.config =
|
wsfs_server_config_set_vhostname(args.config, "localhost");
|
||||||
{
|
wsfs_server_config_set_port(args.config, 8080);
|
||||||
.mount_point = NULL,
|
args.passwd_path = NULL;
|
||||||
.document_root = NULL,
|
args.show_help = false;
|
||||||
.cert_path = NULL,
|
|
||||||
.key_path = NULL,
|
|
||||||
.vhost_name = strdup("localhost"),
|
|
||||||
.port = 8080,
|
|
||||||
},
|
|
||||||
.show_help = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
int result = parse_arguments(argc, argv, &args);
|
int result = parse_arguments(argc, argv, &args);
|
||||||
|
|
||||||
if (!args.show_help)
|
if (!args.show_help)
|
||||||
{
|
{
|
||||||
signal(SIGINT, on_interrupt);
|
signal(SIGINT, on_interrupt);
|
||||||
server = wsfs_server_create(&args.config);
|
server = wsfs_server_create(args.config);
|
||||||
if (NULL != server)
|
if (NULL != server)
|
||||||
{
|
{
|
||||||
wsfs_server_run(server);
|
wsfs_server_run(server);
|
||||||
@ -159,7 +191,8 @@ int main(int argc, char * argv[])
|
|||||||
show_help();
|
show_help();
|
||||||
}
|
}
|
||||||
|
|
||||||
wsfs_server_config_cleanup(&args.config);
|
free(args.passwd_path);
|
||||||
|
wsfs_server_config_dispose(args.config);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
46
example/lib/userdb/include/userdb.h
Normal file
46
example/lib/userdb/include/userdb.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#ifndef USERDB_H
|
||||||
|
#define USERDB_H
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#include <stdbool.h>
|
||||||
|
#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
|
277
example/lib/userdb/src/userdb.c
Normal file
277
example/lib/userdb/src/userdb.c
Normal file
@ -0,0 +1,277 @@
|
|||||||
|
#include "userdb.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <jansson.h>
|
||||||
|
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
|
#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 = EVP_MD_size(digest);
|
||||||
|
unsigned char * hash = malloc(hash_size);
|
||||||
|
|
||||||
|
if (NULL != hash)
|
||||||
|
{
|
||||||
|
EVP_MD_CTX * context = EVP_MD_CTX_new();
|
||||||
|
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_free(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;
|
||||||
|
}
|
304
example/passwd/main.c
Normal file
304
example/passwd/main.c
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
#include <openssl/conf.h>
|
||||||
|
#include <openssl/opensslv.h>
|
||||||
|
#include <openssl/engine.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <jansson.h>
|
||||||
|
#include <userdb.h>
|
||||||
|
|
||||||
|
|
||||||
|
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 <https://github.com/falk-werner/fuse-wsfs>\n"
|
||||||
|
"Manage wsfs passwd file\n"
|
||||||
|
"\n"
|
||||||
|
"Usage: wsfs-passwd -f <file> -c <command> [-u <username>] [-p <password>] [-P <pepper>]\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)
|
||||||
|
{
|
||||||
|
struct userdb * db = userdb_create(args->pepper);
|
||||||
|
bool result = userdb_save(db, args->file);
|
||||||
|
userdb_dispose(db);
|
||||||
|
|
||||||
|
return (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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
return (result) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int remove_user(struct args * args)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
(void) 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 =
|
||||||
|
{
|
||||||
|
"<invalid>",
|
||||||
|
&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 void openssl_cleanup(void)
|
||||||
|
{
|
||||||
|
FIPS_mode_set(0);
|
||||||
|
ENGINE_cleanup();
|
||||||
|
CONF_modules_unload(1);
|
||||||
|
EVP_cleanup();
|
||||||
|
CRYPTO_cleanup_all_ex_data();
|
||||||
|
ERR_free_strings();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char * argv[])
|
||||||
|
{
|
||||||
|
OPENSSL_init();
|
||||||
|
OPENSSL_add_all_algorithms_conf();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.show_help)
|
||||||
|
{
|
||||||
|
print_usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
args_cleanup(&args);
|
||||||
|
openssl_cleanup();
|
||||||
|
return result;
|
||||||
|
}
|
15
include/wsfs/adapter/authenticate.h
Normal file
15
include/wsfs/adapter/authenticate.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#ifndef WSFS_ADAPTER_AUTHENTICATE_H
|
||||||
|
#define WSFS_ADAPTER_AUTHENTICATE_H
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#include <stdbool.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct wsfs_credentials;
|
||||||
|
|
||||||
|
typedef bool wsfs_authenticate_fn(
|
||||||
|
struct wsfs_credentials * credentials,
|
||||||
|
void * user_data);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
25
include/wsfs/adapter/credentials.h
Normal file
25
include/wsfs/adapter/credentials.h
Normal file
@ -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
|
@ -2,31 +2,51 @@
|
|||||||
#define WSFS_ADAPTER_SERVER_CONFIG_H
|
#define WSFS_ADAPTER_SERVER_CONFIG_H
|
||||||
|
|
||||||
#include "wsfs/adapter/api.h"
|
#include "wsfs/adapter/api.h"
|
||||||
|
#include "wsfs/adapter/authenticate.h"
|
||||||
|
|
||||||
struct wsfs_server_config
|
struct wsfs_server_config;
|
||||||
{
|
|
||||||
char * mount_point;
|
|
||||||
char * document_root;
|
|
||||||
char * key_path;
|
|
||||||
char * cert_path;
|
|
||||||
char * vhost_name;
|
|
||||||
int port;
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
#endif
|
#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);
|
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(
|
extern WSFSA_API void wsfs_server_config_set_mountpoint(
|
||||||
struct wsfs_server_config * config,
|
struct wsfs_server_config * config,
|
||||||
struct wsfs_server_config * clone);
|
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);
|
||||||
|
|
||||||
|
extern WSFSA_API void wsfs_server_config_add_authenticator(
|
||||||
|
struct wsfs_server_config * config,
|
||||||
|
char const * type,
|
||||||
|
wsfs_authenticate_fn * authenticate,
|
||||||
|
void * user_data
|
||||||
|
);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#ifndef WSFS_ADAPTER_SERVER_PROTOCOL_H
|
#ifndef WSFS_ADAPTER_SERVER_PROTOCOL_H
|
||||||
#define WSFS_ADAPTER_SERVER_PROTOCOL_H
|
#define WSFS_ADAPTER_SERVER_PROTOCOL_H
|
||||||
|
|
||||||
#include "wsfs/adapter/api.h"
|
#include <wsfs/adapter/api.h>
|
||||||
|
#include <wsfs/adapter/authenticate.h>
|
||||||
|
|
||||||
struct wsfs_server_protocol;
|
struct wsfs_server_protocol;
|
||||||
struct lws_protocols;
|
struct lws_protocols;
|
||||||
@ -21,6 +22,12 @@ extern WSFSA_API void wsfs_server_protocol_init_lws(
|
|||||||
struct wsfs_server_protocol * protocol,
|
struct wsfs_server_protocol * protocol,
|
||||||
struct lws_protocols * lws_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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,5 +7,7 @@
|
|||||||
#include <wsfs/adapter/server.h>
|
#include <wsfs/adapter/server.h>
|
||||||
#include <wsfs/adapter/server_config.h>
|
#include <wsfs/adapter/server_config.h>
|
||||||
#include <wsfs/adapter/server_protocol.h>
|
#include <wsfs/adapter/server_protocol.h>
|
||||||
|
#include <wsfs/adapter/authenticate.h>
|
||||||
|
#include <wsfs/adapter/credentials.h>
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
49
lib/wsfs/adapter/authenticator.c
Normal file
49
lib/wsfs/adapter/authenticator.c
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#include "wsfs/adapter/authenticator.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
40
lib/wsfs/adapter/authenticator.h
Normal file
40
lib/wsfs/adapter/authenticator.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#ifndef WSFS_ADAPTER_AUTHENTICATOR_H
|
||||||
|
#define WSFS_ADAPTER_AUTHENTICATOR_H
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#include <stdbool.h>
|
||||||
|
#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
|
101
lib/wsfs/adapter/authenticators.c
Normal file
101
lib/wsfs/adapter/authenticators.c
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
#include "wsfs/adapter/authenticators.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
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 = (NULL == authenticators->first);
|
||||||
|
|
||||||
|
if (NULL != credentials)
|
||||||
|
{
|
||||||
|
struct wsfs_authenticator * authenticator = wsfs_authenticators_find(authenticators, credentials->type);
|
||||||
|
if (NULL != authenticator)
|
||||||
|
{
|
||||||
|
result = wsfs_authenticator_autenticate(authenticator, credentials);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
51
lib/wsfs/adapter/authenticators.h
Normal file
51
lib/wsfs/adapter/authenticators.h
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#ifndef WSFS_ADAPTER_AUTHENTICATORS_H
|
||||||
|
#define WSFS_ADAPTER_AUTHENTICATORS_H
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#include <stdbool.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "wsfs/adapter/authenticate.h"
|
||||||
|
|
||||||
|
struct wsfs_authenticator;
|
||||||
|
struct wsfs_credentials;
|
||||||
|
|
||||||
|
struct wsfs_authenticators
|
||||||
|
{
|
||||||
|
struct wsfs_authenticator * first;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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_move(
|
||||||
|
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);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
40
lib/wsfs/adapter/credentials.c
Normal file
40
lib/wsfs/adapter/credentials.c
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#include "wsfs/adapter/credentials_intern.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
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_credentials_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;
|
||||||
|
}
|
30
lib/wsfs/adapter/credentials_intern.h
Normal file
30
lib/wsfs/adapter/credentials_intern.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef WSFS_ADAPTER_CREDENTIALS_INTERN_H
|
||||||
|
#define WSFS_ADAPTER_CREDENTIALS_INTERN_H
|
||||||
|
|
||||||
|
#include "wsfs/adapter/credentials.h"
|
||||||
|
#include <jansson.h>
|
||||||
|
|
||||||
|
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_credentials_cleanup(
|
||||||
|
struct wsfs_credentials * credentials);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -4,7 +4,11 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <libwebsockets.h>
|
#include <libwebsockets.h>
|
||||||
|
|
||||||
#include "wsfs/adapter/server_config.h"
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "wsfs/adapter/server_config_intern.h"
|
||||||
#include "wsfs/adapter/server_protocol_intern.h"
|
#include "wsfs/adapter/server_protocol_intern.h"
|
||||||
|
|
||||||
#define WSFS_DISABLE_LWS_LOG 0
|
#define WSFS_DISABLE_LWS_LOG 0
|
||||||
@ -74,16 +78,41 @@ 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);
|
||||||
|
result = ((0 == rc) && (S_ISDIR(info.st_mode)));
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
result = (0 == mkdir(config->mount_point, 0755));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
struct wsfs_server * wsfs_server_create(
|
struct wsfs_server * wsfs_server_create(
|
||||||
struct wsfs_server_config * config)
|
struct wsfs_server_config * config)
|
||||||
{
|
{
|
||||||
struct wsfs_server * server = malloc(sizeof(struct wsfs_server));
|
struct wsfs_server * server = NULL;
|
||||||
|
|
||||||
|
if (wsfs_server_check_mountpoint(config))
|
||||||
|
{
|
||||||
|
server = malloc(sizeof(struct wsfs_server));
|
||||||
if (NULL != server)
|
if (NULL != server)
|
||||||
{
|
{
|
||||||
if (wsfs_server_protocol_init(&server->protocol, config->mount_point))
|
if (wsfs_server_protocol_init(&server->protocol, config->mount_point))
|
||||||
{
|
{
|
||||||
server->shutdown_requested = false;
|
server->shutdown_requested = false;
|
||||||
wsfs_server_config_clone(config, &server->config);
|
wsfs_server_config_clone(config, &server->config);
|
||||||
|
wsfs_authenticators_move(&server->config.authenticators, &server->protocol.authenticators);
|
||||||
server->context = wsfs_server_context_create(server);
|
server->context = wsfs_server_context_create(server);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -92,6 +121,7 @@ struct wsfs_server * wsfs_server_create(
|
|||||||
server = NULL;
|
server = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "wsfs/adapter/server_config.h"
|
#include "wsfs/adapter/server_config_intern.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -18,11 +18,15 @@ void wsfs_server_config_init(
|
|||||||
struct wsfs_server_config * config)
|
struct wsfs_server_config * config)
|
||||||
{
|
{
|
||||||
memset(config, 0, sizeof(struct wsfs_server_config));
|
memset(config, 0, sizeof(struct wsfs_server_config));
|
||||||
|
|
||||||
|
wsfs_authenticators_init(&config->authenticators);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wsfs_server_config_cleanup(
|
void wsfs_server_config_cleanup(
|
||||||
struct wsfs_server_config * config)
|
struct wsfs_server_config * config)
|
||||||
{
|
{
|
||||||
|
wsfs_authenticators_cleanup(&config->authenticators);
|
||||||
|
|
||||||
free(config->mount_point);
|
free(config->mount_point);
|
||||||
free(config->document_root);
|
free(config->document_root);
|
||||||
free(config->key_path);
|
free(config->key_path);
|
||||||
@ -42,4 +46,82 @@ void wsfs_server_config_clone(
|
|||||||
clone->cert_path = wsfs_server_config_strdup(config->cert_path);
|
clone->cert_path = wsfs_server_config_strdup(config->cert_path);
|
||||||
clone->vhost_name = wsfs_server_config_strdup(config->vhost_name);
|
clone->vhost_name = wsfs_server_config_strdup(config->vhost_name);
|
||||||
clone->port = config->port;
|
clone->port = config->port;
|
||||||
|
|
||||||
|
wsfs_authenticators_clone(&config->authenticators, &clone->authenticators);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wsfs_server_config_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
37
lib/wsfs/adapter/server_config_intern.h
Normal file
37
lib/wsfs/adapter/server_config_intern.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef WSFS_ADAPTER_SERVER_CONFIG_INTERN_H
|
||||||
|
#define WSFS_ADAPTER_SERVER_CONFIG_INTERN_H
|
||||||
|
|
||||||
|
#include "wsfs/adapter/server_config.h"
|
||||||
|
#include "wsfs/adapter/authenticators.h"
|
||||||
|
|
||||||
|
struct wsfs_server_config
|
||||||
|
{
|
||||||
|
char * mount_point;
|
||||||
|
char * document_root;
|
||||||
|
char * key_path;
|
||||||
|
char * cert_path;
|
||||||
|
char * vhost_name;
|
||||||
|
int port;
|
||||||
|
struct wsfs_authenticators authenticators;
|
||||||
|
};
|
||||||
|
|
||||||
|
#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
|
@ -19,6 +19,7 @@ static int wsfs_server_protocol_callback(
|
|||||||
struct wsfs_server_protocol * protocol = ws_protocol->user;
|
struct wsfs_server_protocol * protocol = ws_protocol->user;
|
||||||
|
|
||||||
wsfs_timeout_manager_check(&protocol->timeout_manager);
|
wsfs_timeout_manager_check(&protocol->timeout_manager);
|
||||||
|
struct wsfs_session * session = wsfs_session_manager_get(&protocol->session_manager, wsi);
|
||||||
|
|
||||||
switch (reason)
|
switch (reason)
|
||||||
{
|
{
|
||||||
@ -33,33 +34,31 @@ static int wsfs_server_protocol_callback(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LWS_CALLBACK_ESTABLISHED:
|
case LWS_CALLBACK_ESTABLISHED:
|
||||||
if (NULL == protocol->wsi)
|
session = wsfs_session_manager_add(
|
||||||
|
&protocol->session_manager,
|
||||||
|
wsi,
|
||||||
|
&protocol->authenticators,
|
||||||
|
&protocol->rpc);
|
||||||
|
|
||||||
|
if (NULL != session)
|
||||||
{
|
{
|
||||||
protocol->wsi = wsi;
|
wsfs_session_authenticate(session, NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LWS_CALLBACK_CLOSED:
|
case LWS_CALLBACK_CLOSED:
|
||||||
if (wsi == protocol->wsi)
|
wsfs_session_manager_remove(&protocol->session_manager, wsi);
|
||||||
{
|
|
||||||
protocol->wsi = NULL;
|
|
||||||
wsfs_message_queue_cleanup(&protocol->queue);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case LWS_CALLBACK_SERVER_WRITEABLE:
|
case LWS_CALLBACK_SERVER_WRITEABLE:
|
||||||
if ((wsi == protocol->wsi) && (!wsfs_message_queue_empty(&protocol->queue)))
|
if (NULL != session)
|
||||||
{
|
{
|
||||||
struct wsfs_message * message = wsfs_message_queue_pop(&protocol->queue);
|
wsfs_session_onwritable(session);
|
||||||
lws_write(wsi, (unsigned char*) message->data, message->length, LWS_WRITE_TEXT);
|
|
||||||
wsfs_message_dispose(message);
|
|
||||||
|
|
||||||
if (!wsfs_message_queue_empty(&protocol->queue))
|
|
||||||
{
|
|
||||||
lws_callback_on_writable(wsi);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case LWS_CALLBACK_RECEIVE:
|
case LWS_CALLBACK_RECEIVE:
|
||||||
wsfs_jsonrpc_server_onresult(&protocol->rpc, in, len);
|
if (NULL != session)
|
||||||
|
{
|
||||||
|
wsfs_session_receive(session, in, len);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case LWS_CALLBACK_RAW_RX_FILE:
|
case LWS_CALLBACK_RAW_RX_FILE:
|
||||||
wsfs_filesystem_process_request(&protocol->filesystem);
|
wsfs_filesystem_process_request(&protocol->filesystem);
|
||||||
@ -75,20 +74,11 @@ static bool wsfs_server_protocol_invoke(
|
|||||||
void * user_data,
|
void * user_data,
|
||||||
json_t const * request)
|
json_t const * request)
|
||||||
{
|
{
|
||||||
bool result = false;
|
|
||||||
struct wsfs_server_protocol * protocol = user_data;
|
struct wsfs_server_protocol * protocol = user_data;
|
||||||
|
struct wsfs_session * session = &protocol->session_manager.session;
|
||||||
if (NULL != protocol->wsi)
|
|
||||||
{
|
|
||||||
struct wsfs_message * message = wsfs_message_create(request);
|
struct wsfs_message * message = wsfs_message_create(request);
|
||||||
if (NULL != message)
|
|
||||||
{
|
|
||||||
wsfs_message_queue_push(&protocol->queue, message);
|
|
||||||
lws_callback_on_writable(protocol->wsi);
|
|
||||||
|
|
||||||
result = true;
|
bool const result = wsfs_session_send(session, message);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -130,10 +120,9 @@ bool wsfs_server_protocol_init(
|
|||||||
struct wsfs_server_protocol * protocol,
|
struct wsfs_server_protocol * protocol,
|
||||||
char * mount_point)
|
char * mount_point)
|
||||||
{
|
{
|
||||||
protocol->wsi = NULL;
|
|
||||||
wsfs_message_queue_init(&protocol->queue);
|
|
||||||
|
|
||||||
wsfs_timeout_manager_init(&protocol->timeout_manager);
|
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);
|
wsfs_jsonrpc_server_init(&protocol->rpc, &protocol->timeout_manager);
|
||||||
wsfs_jsonrpc_server_add(&protocol->rpc, "lookup", &wsfs_server_protocol_invoke, protocol);
|
wsfs_jsonrpc_server_add(&protocol->rpc, "lookup", &wsfs_server_protocol_invoke, protocol);
|
||||||
@ -149,8 +138,9 @@ bool wsfs_server_protocol_init(
|
|||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
wsfs_jsonrpc_server_cleanup(&protocol->rpc);
|
wsfs_jsonrpc_server_cleanup(&protocol->rpc);
|
||||||
|
wsfs_authenticators_cleanup(&protocol->authenticators);
|
||||||
wsfs_timeout_manager_cleanup(&protocol->timeout_manager);
|
wsfs_timeout_manager_cleanup(&protocol->timeout_manager);
|
||||||
wsfs_message_queue_cleanup(&protocol->queue);
|
wsfs_session_manager_cleanup(&protocol->session_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
@ -162,6 +152,15 @@ void wsfs_server_protocol_cleanup(
|
|||||||
wsfs_filesystem_cleanup(&protocol->filesystem);
|
wsfs_filesystem_cleanup(&protocol->filesystem);
|
||||||
wsfs_jsonrpc_server_cleanup(&protocol->rpc);
|
wsfs_jsonrpc_server_cleanup(&protocol->rpc);
|
||||||
wsfs_timeout_manager_cleanup(&protocol->timeout_manager);
|
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(
|
||||||
|
struct wsfs_server_protocol * protocol,
|
||||||
|
char const * type,
|
||||||
|
wsfs_authenticate_fn * authenticate,
|
||||||
|
void * user_data)
|
||||||
|
{
|
||||||
|
wsfs_authenticators_add(&protocol->authenticators, type, authenticate, user_data);
|
||||||
}
|
}
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
#ifndef WSFS_ADAPTER_SERVER_PROTOCOL_INTERN_H
|
#ifndef WSFS_ADAPTER_SERVER_PROTOCOL_INTERN_H
|
||||||
#define 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/server_protocol.h"
|
||||||
#include "wsfs/adapter/filesystem.h"
|
#include "wsfs/adapter/filesystem.h"
|
||||||
#include "wsfs/adapter/jsonrpc/server.h"
|
#include "wsfs/adapter/jsonrpc/server.h"
|
||||||
#include "wsfs/adapter/time/timeout_manager.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_server_protocol
|
||||||
{
|
{
|
||||||
struct wsfs_timeout_manager timeout_manager;
|
struct wsfs_timeout_manager timeout_manager;
|
||||||
struct wsfs_filesystem filesystem;
|
struct wsfs_filesystem filesystem;
|
||||||
struct wsfs_jsonrpc_server rpc;
|
struct wsfs_jsonrpc_server rpc;
|
||||||
struct wsfs_message_queue queue;
|
struct wsfs_authenticators authenticators;
|
||||||
struct lws * wsi;
|
struct wsfs_session_manager session_manager;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool wsfs_server_protocol_init(
|
extern bool wsfs_server_protocol_init(
|
||||||
|
84
lib/wsfs/adapter/session.c
Normal file
84
lib/wsfs/adapter/session.c
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
#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 <libwebsockets.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
void wsfs_session_init(
|
||||||
|
struct wsfs_session * session,
|
||||||
|
struct lws * wsi,
|
||||||
|
struct wsfs_authenticators * authenticators,
|
||||||
|
struct wsfs_jsonrpc_server * rpc)
|
||||||
|
{
|
||||||
|
session->wsi = wsi;
|
||||||
|
session->is_authenticated = false;
|
||||||
|
session->authenticators = authenticators;
|
||||||
|
session->rpc = rpc;
|
||||||
|
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;
|
||||||
|
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);
|
||||||
|
}
|
64
lib/wsfs/adapter/session.h
Normal file
64
lib/wsfs/adapter/session.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#ifndef WSFS_ADAPTER_SESSION_H
|
||||||
|
#define WSFS_ADAPTER_SESSION_H
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#else
|
||||||
|
#include <cstddef>
|
||||||
|
using std::size_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "wsfs/message_queue.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
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,
|
||||||
|
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);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
54
lib/wsfs/adapter/session_manager.c
Normal file
54
lib/wsfs/adapter/session_manager.c
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include "wsfs/adapter/session_manager.h"
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
void wsfs_session_manager_init(
|
||||||
|
struct wsfs_session_manager * manager)
|
||||||
|
{
|
||||||
|
wsfs_session_init(&manager->session, NULL, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wsfs_session_manager_cleanup(
|
||||||
|
struct wsfs_session_manager * manager)
|
||||||
|
{
|
||||||
|
wsfs_session_cleanup(&manager->session);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wsfs_session * wsfs_session_manager_add(
|
||||||
|
struct wsfs_session_manager * manager,
|
||||||
|
struct lws * wsi,
|
||||||
|
struct wsfs_authenticators * authenticators,
|
||||||
|
struct wsfs_jsonrpc_server * rpc)
|
||||||
|
{
|
||||||
|
struct wsfs_session * session = NULL;
|
||||||
|
if (NULL == manager->session.wsi)
|
||||||
|
{
|
||||||
|
session = &manager->session;
|
||||||
|
wsfs_session_init(&manager->session, wsi, authenticators, rpc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
46
lib/wsfs/adapter/session_manager.h
Normal file
46
lib/wsfs/adapter/session_manager.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#ifndef WSFS_ADAPTER_SESSION_MANAGER_H
|
||||||
|
#define WSFS_ADAPTER_SESSION_MANAGER_H
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#include <stdbool.h>
|
||||||
|
#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 struct wsfs_session * wsfs_session_manager_add(
|
||||||
|
struct wsfs_session_manager * manager,
|
||||||
|
struct lws * wsi,
|
||||||
|
struct wsfs_authenticators * authenticators,
|
||||||
|
struct wsfs_jsonrpc_server * rpc);
|
||||||
|
|
||||||
|
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
|
@ -32,7 +32,7 @@ void wsfsp_getattr_default(
|
|||||||
ino_t WSFS_UNUSED_PARAM(inode),
|
ino_t WSFS_UNUSED_PARAM(inode),
|
||||||
void * WSFS_UNUSED_PARAM(user_data))
|
void * WSFS_UNUSED_PARAM(user_data))
|
||||||
{
|
{
|
||||||
wsfsp_respond_error(request, -1);
|
wsfsp_respond_error(request, WSFS_BAD_NOENTRY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wsfsp_respond_getattr(
|
void wsfsp_respond_getattr(
|
||||||
|
42
test/mock_authenticator.cc
Normal file
42
test/mock_authenticator.cc
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
34
test/mock_authenticator.hpp
Normal file
34
test/mock_authenticator.hpp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef MOCK_AUTHENTICATOR_H
|
||||||
|
#define MOCK_AUTHENTICATOR_H
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#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
|
63
test/test_authenticator.cc
Normal file
63
test/test_authenticator.cc
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
#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<void*>(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);
|
||||||
|
}
|
154
test/test_authenticators.cc
Normal file
154
test/test_authenticators.cc
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
|
#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(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);
|
||||||
|
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);
|
||||||
|
}
|
70
test/test_credentials.cc
Normal file
70
test/test_credentials.cc
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "wsfs/adapter/credentials_intern.h"
|
||||||
|
#include <jansson.h>
|
||||||
|
|
||||||
|
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("<secret>"));
|
||||||
|
|
||||||
|
wsfs_credentials_init(&creds, "username", data);
|
||||||
|
ASSERT_STREQ("username", wsfs_credentials_type(&creds));
|
||||||
|
ASSERT_STREQ("bob", wsfs_credentials_get(&creds, "username"));
|
||||||
|
ASSERT_STREQ("<secret>", 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);
|
||||||
|
}
|
||||||
|
|
@ -13,12 +13,13 @@ TEST(server, create_dispose)
|
|||||||
{
|
{
|
||||||
mkdir("test", 0700);
|
mkdir("test", 0700);
|
||||||
|
|
||||||
struct wsfs_server_config config = {strdup("test"), nullptr, nullptr, nullptr, nullptr, 0};
|
struct wsfs_server_config * config = wsfs_server_config_create();
|
||||||
struct wsfs_server * server = wsfs_server_create(&config);
|
wsfs_server_config_set_mountpoint(config, "test");
|
||||||
|
struct wsfs_server * server = wsfs_server_create(config);
|
||||||
ASSERT_NE(nullptr, server);
|
ASSERT_NE(nullptr, server);
|
||||||
|
|
||||||
wsfs_server_dispose(server);
|
wsfs_server_dispose(server);
|
||||||
wsfs_server_config_cleanup(&config);
|
wsfs_server_config_dispose(config);
|
||||||
|
|
||||||
rmdir("test");
|
rmdir("test");
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user