1
0
mirror of https://github.com/falk-werner/webfuse synced 2024-10-27 20:34:10 +00:00

use tls configuration in server and provider

This commit is contained in:
Falk Werner 2023-01-14 23:58:22 +01:00
parent 412c1f9a51
commit f12f461154
12 changed files with 156 additions and 23 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
/build/
/.vscode/
*.pem

View File

@ -34,6 +34,7 @@ add_library(webfuse_static STATIC
src/webfuse/ws/client.cpp
src/webfuse/ws/messagewriter.cpp
src/webfuse/ws/messagereader.cpp
src/webfuse/ws/url.cpp
)
target_include_directories(webfuse_static PUBLIC src)

7
script/create_cert.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
openssl req -x509 -newkey rsa:4096 \
-keyout server-key.pem \
-out server-cert.pem \
-days 365 -nodes -batch \
-subj /CN=localhost

View File

@ -33,6 +33,7 @@ public:
{
{"path" , required_argument, nullptr, 'p'},
{"url" , required_argument, nullptr, 'u'},
{"ca-path", required_argument, nullptr, 'a'},
{"version", no_argument , nullptr, 'v'},
{"help" , no_argument , nullptr, 'h'},
{nullptr , 0 , nullptr, 0 }
@ -44,7 +45,7 @@ public:
while (!finished)
{
int option_index = 0;
const int c = getopt_long(argc, argv, "p:u:vh", long_options, &option_index);
const int c = getopt_long(argc, argv, "p:u:a:vh", long_options, &option_index);
switch (c)
{
case -1:
@ -56,6 +57,9 @@ public:
case 'u':
url = optarg;
break;
case 'a':
ca_path = optarg;
break;
case 'h':
cmd = command::show_help;
break;
@ -81,6 +85,7 @@ public:
std::string base_path;
std::string url;
std::string ca_path;
command cmd;
int exit_code;
};
@ -91,11 +96,12 @@ void print_usage()
expose a local directory via webfuse2
Usage:
webfuse-provider -u <url> [-p <path>]
webfuse-provider -u <url> [-p <path>] [-a <ca_path>]
Options:
--url, -u set url of webfuse2 service
--path, -p set path of directory to expose (default: .)
--ca-path, -a set path of ca file (default: not set)
--version, -v print version and quit
--help, -h print this message and quit
@ -439,7 +445,7 @@ int main(int argc, char* argv[])
signal(SIGTERM, &on_signal);
filesystem fs(ctx.base_path);
webfuse::provider provider(fs);
webfuse::provider provider(fs, ctx.ca_path);
provider.set_connection_listener([](bool connected) {
if (!connected)
{

View File

@ -13,9 +13,9 @@ namespace webfuse
class provider::detail
{
public:
detail(filesystem_i & fs)
detail(filesystem_i & fs, std::string const & ca_path)
: fs_(fs)
, client([this](auto& reader) { return this->on_message(reader); })
, client(ca_path, [this](auto& reader) { return this->on_message(reader); })
{
}
@ -375,8 +375,8 @@ private:
ws_client client;
};
provider::provider(filesystem_i & fs)
: d(new detail(fs))
provider::provider(filesystem_i & fs, std::string const & ca_path)
: d(new detail(fs, ca_path))
{
}

View File

@ -13,7 +13,7 @@ class provider
provider(provider const &) = delete;
provider& operator=(provider const &) = delete;
public:
provider(filesystem_i & fs);
provider(filesystem_i & fs, std::string const & ca_path);
~provider();
provider(provider && other);
provider& operator=(provider && other);

View File

@ -1,4 +1,6 @@
#include "webfuse/ws/client.hpp"
#include "webfuse/ws/url.hpp"
#include <libwebsockets.h>
#include <cstring>
#include <iostream>
@ -106,8 +108,10 @@ class ws_client::detail
detail(detail &&) = delete;
detail& operator=(detail &&) = delete;
public:
detail(ws_client_handler handler)
detail(std::string const & ca_path, ws_client_handler handler)
{
lws_set_log_level(0, nullptr);
memset(reinterpret_cast<void*>(protocols), 0, sizeof(lws_protocols) * 2);
protocols[0].callback = &webfuse_client_callback;
protocols[0].name = "webfuse2-client";
@ -119,12 +123,22 @@ public:
info.protocols = protocols;
info.uid = -1;
info.gid = -1;
info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS;
data.handler = handler;
data.connection_listener = [](bool){ };
data.connection = nullptr;
context = lws_create_context(&info);
struct lws_vhost * vhost = lws_create_vhost(context, &info);
info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
if (!ca_path.empty())
{
info.client_ssl_ca_filepath = ca_path.c_str();
}
lws_init_vhost_client_ssl(&info, vhost);
}
~detail()
@ -134,15 +148,17 @@ public:
void connect(std::string const & url)
{
ws_url parsed_url(url);
lws_client_connect_info info;
memset(reinterpret_cast<void*>(&info), 0, sizeof(lws_client_connect_info));
info.context = context;
info.port = 8081; //NOLINT(readability-magic-numbers)
info.address = "localhost";
info.host = "localhost";
info.path = "/";
info.origin = "localhost";
info.ssl_connection = 0;
info.port = parsed_url.port;
info.address = parsed_url.hostname.c_str();
info.host = info.address;
info.path = parsed_url.path.c_str();
info.origin = info.address;
info.ssl_connection = (parsed_url.use_tls) ? LCCSCF_USE_SSL : 0;
info.protocol = "webfuse2";
info.local_protocol_name = "webfuse2-client";
info.pwsi = &data.connection;
@ -172,8 +188,8 @@ private:
user_data data;
};
ws_client::ws_client(ws_client_handler handler)
: d(new detail(handler))
ws_client::ws_client(std::string const & ca_path, ws_client_handler handler)
: d(new detail(ca_path, handler))
{
}

View File

@ -16,7 +16,7 @@ class ws_client
ws_client(ws_client const &) = delete;
ws_client& operator=(ws_client const &) = delete;
public:
ws_client(ws_client_handler handler);
ws_client(std::string const & ca_path, ws_client_handler handler);
~ws_client();
ws_client(ws_client && other);
ws_client& operator=(ws_client && other);

View File

@ -164,6 +164,8 @@ public:
detail(ws_config const & config)
: shutdown_requested(false)
{
lws_set_log_level(0, nullptr);
memset(reinterpret_cast<void*>(protocols), 0, sizeof(protocols));
protocols[0].name = "webfuse2";
protocols[0].callback = &ws_server_callback;
@ -173,15 +175,21 @@ public:
memset(reinterpret_cast<void*>(&info), 0, sizeof(info));
info.port = config.port;
info.protocols = protocols;
info.vhost_name = "localhost";
info.vhost_name = config.vhost_name.c_str();
info.options = LWS_SERVER_OPTION_HTTP_HEADERS_SECURITY_BEST_PRACTICES_ENFORCE | LWS_SERVER_OPTION_EXPLICIT_VHOSTS;
if (config.use_tls)
{
info.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
info.ssl_cert_filepath = config.cert_path.c_str();
info.ssl_private_key_filepath = config.key_path.c_str();
}
context = lws_create_context(&info);
lws_create_vhost(context, &info);
// lws_vhost * const vhost = lws_create_vhost(context, &info);
// port = lws_get_vhost_port(vhost);
// int port = lws_get_vhost_port(vhost);
thread = std::thread([this]() {
while (!shutdown_requested)

70
src/webfuse/ws/url.cpp Normal file
View File

@ -0,0 +1,70 @@
#include "webfuse/ws/url.hpp"
#include <cstring>
#include <stdexcept>
namespace
{
bool starts_with(std::string const & value, std::string const & prefix)
{
return (0 == value.find(prefix));
}
std::string parse_protocol(std::string const &url, bool &use_tls)
{
if (starts_with(url, "ws://"))
{
use_tls = false;
return url.substr(strlen("ws://"));
}
if (starts_with(url, "wss://"))
{
use_tls = true;
return url.substr(strlen("wss://"));
}
throw std::runtime_error("unknown protocol");
}
}
namespace webfuse
{
constexpr uint16_t const ws_port = 80;
constexpr uint16_t const wss_port = 443;
ws_url::ws_url(std::string const & url)
{
auto remainder = parse_protocol(url, use_tls);
auto const path_start = remainder.find('/');
if (path_start != std::string::npos)
{
path = remainder.substr(path_start);
remainder = remainder.substr(0, path_start);
}
else
{
path = "/";
}
auto const port_start = remainder.find(':');
if (port_start != std::string::npos)
{
auto const port_str = remainder.substr(port_start + 1);
port = static_cast<uint16_t>(std::stoi(port_str));
hostname = remainder.substr(0, port_start);
}
else
{
port = (use_tls) ? wss_port : ws_port;
hostname = remainder;
}
}
}

24
src/webfuse/ws/url.hpp Normal file
View File

@ -0,0 +1,24 @@
#ifndef WEBFUSE_URL_HPP
#define WEBFUSE_URL_HPP
#include <cinttypes>
#include <string>
namespace webfuse
{
class ws_url
{
public:
ws_url(std::string const & url);
~ws_url() = default;
bool use_tls;
std::string hostname;
uint16_t port;
std::string path;
};
}
#endif

View File

@ -10,7 +10,7 @@ namespace webfuse
fixture::fixture(filesystem_i & fs)
: shutdown_requested(false)
, provider_running(false)
, fs_provider(fs)
, fs_provider(fs, "")
, app(working_dir.name())
{
fs_provider.set_connection_listener([this](bool is_connected) {