diff options
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | config.cpp | 2 | ||||
-rw-r--r-- | config.h | 2 | ||||
-rw-r--r-- | http.cpp | 36 | ||||
-rw-r--r-- | https.cpp | 66 | ||||
-rw-r--r-- | https.h | 2 | ||||
-rw-r--r-- | server.h | 2 |
7 files changed, 80 insertions, 33 deletions
@@ -2,3 +2,6 @@ Certbot: https://certbot.eff.org/lets-encrypt/debianbuster-other Webbox Debian 10 alternative hosts www, lists, ... + +drop privileges: www-data,www-data, ...? +Speed up DocRoot, use string_view @@ -182,7 +182,7 @@ void Config::dump() const std::cout << "=============================================" << std::endl; } -std::string Config::DocRoot(const Socket& socket, const std::string& requested_host, const std::string& requested_path) +std::string Config::DocRoot(const Socket& socket, const std::string& requested_host, const std::string& requested_path) const { // TODO: speed this up std::string host{requested_host}; @@ -71,7 +71,7 @@ class Config const std::vector<Socket>& Sockets() const; /// param[in] requested_host e.g. www.domain.com:8080 or www.domain.com - std::string DocRoot(const Socket& socket, const std::string& requested_host, const std::string& requested_path); + std::string DocRoot(const Socket& socket, const std::string& requested_host, const std::string& requested_path) const; void dump() const; }; @@ -97,7 +97,8 @@ template< class Send> void handle_request( - beast::string_view doc_root, + const Config& config, + const Socket& socket, http::request<Body, http::basic_fields<Allocator>>&& req, Send&& send) { @@ -152,8 +153,9 @@ handle_request( return send(bad_request("Illegal request-target")); // Build the path to the requested file - std::string path = path_cat(doc_root, req.target()); - std::cout << "DEBUG: " << req["host"] << "|" << req.target() << std::endl; + std::string host{req["host"]}; // TODO: just use string_view + std::string target{req.target()}; + std::string path = path_cat(config.DocRoot(socket, host, target), req.target()); if(req.target().back() == '/') path.append("index.html"); @@ -247,7 +249,8 @@ class session : public std::enable_shared_from_this<session> beast::tcp_stream stream_; beast::flat_buffer buffer_; - std::shared_ptr<std::string const> doc_root_; + const Config& m_config; + const Socket& m_socket; http::request<http::string_body> req_; std::shared_ptr<void> res_; send_lambda lambda_; @@ -256,9 +259,11 @@ public: // Take ownership of the stream session( tcp::socket&& socket, - std::shared_ptr<std::string const> const& doc_root) + const Config& config, + const Socket& config_socket) : stream_(std::move(socket)) - , doc_root_(doc_root) + , m_config(config) + , m_socket(config_socket) , lambda_(*this) { } @@ -309,7 +314,7 @@ public: return fail(ec, "read"); // Send the response - handle_request(*doc_root_, std::move(req_), lambda_); + handle_request(m_config, m_socket , std::move(req_), lambda_); } void @@ -355,16 +360,19 @@ class listener : public std::enable_shared_from_this<listener> { net::io_context& ioc_; tcp::acceptor acceptor_; - std::shared_ptr<std::string const> doc_root_; + const Config& m_config; + const Socket& m_socket; public: listener( net::io_context& ioc, tcp::endpoint endpoint, - std::shared_ptr<std::string const> const& doc_root) + const Config& config, + const Socket& socket) : ioc_(ioc) , acceptor_(net::make_strand(ioc)) - , doc_root_(doc_root) + , m_config(config) + , m_socket(socket) { beast::error_code ec; @@ -433,7 +441,8 @@ private: // Create the session and run it std::make_shared<session>( std::move(socket), - doc_root_)->run(); + m_config, + m_socket)->run(); } // Accept another connection @@ -457,16 +466,15 @@ namespace HTTP { int Server::start() { - // TODO: Config auto const address = net::ip::make_address(m_socket.address); auto const port = static_cast<unsigned short>(std::atoi(m_socket.port.data())); - auto const doc_root = std::make_shared<std::string>(m_config.Sites()[0].paths[0].params.at("target")); // Create and launch a listening port std::make_shared<listener>( m_ioc, tcp::endpoint{address, port}, - doc_root)->run(); + m_config, + m_socket)->run(); return EXIT_SUCCESS; } @@ -8,6 +8,7 @@ #include "server_certificate.h" +#include <openssl/ssl.h> #include <boost/beast/core.hpp> #include <boost/beast/http.hpp> #include <boost/beast/version.hpp> @@ -104,7 +105,8 @@ template< class Send> void handle_request( - beast::string_view doc_root, + const Config& config, + const Socket& socket, http::request<Body, http::basic_fields<Allocator>>&& req, Send&& send) { @@ -159,7 +161,9 @@ handle_request( return send(bad_request("Illegal request-target")); // Build the path to the requested file - std::string path = path_cat(doc_root, req.target()); + std::string host{req["host"]}; // TODO: just use string_view + std::string target{req.target()}; + std::string path = path_cat(config.DocRoot(socket, host, target), req.target()); if(req.target().back() == '/') path.append("index.html"); @@ -273,7 +277,8 @@ class session : public std::enable_shared_from_this<session> beast::ssl_stream<beast::tcp_stream> stream_; beast::flat_buffer buffer_; - std::shared_ptr<std::string const> doc_root_; + const Config& m_config; + const Socket& m_socket; http::request<http::string_body> req_; std::shared_ptr<void> res_; send_lambda lambda_; @@ -284,9 +289,11 @@ public: session( tcp::socket&& socket, ssl::context& ctx, - std::shared_ptr<std::string const> const& doc_root) + const Config& config, + const Socket& config_socket) : stream_(std::move(socket), ctx) - , doc_root_(doc_root) + , m_config(config) + , m_socket(config_socket) , lambda_(*this) { } @@ -296,9 +303,7 @@ public: run() { // We need to be executing within a strand to perform async operations - // on the I/O objects in this session. Although not strictly necessary - // for single-threaded contexts, this example code is written to be - // thread-safe by default. + // on the I/O objects in this session. net::dispatch( stream_.get_executor(), beast::bind_front_handler( @@ -362,7 +367,7 @@ public: return fail(ec, "read"); // Send the response - handle_request(*doc_root_, std::move(req_), lambda_); + handle_request(m_config, m_socket, std::move(req_), lambda_); } void @@ -421,18 +426,21 @@ class listener : public std::enable_shared_from_this<listener> net::io_context& ioc_; ssl::context& ctx_; tcp::acceptor acceptor_; - std::shared_ptr<std::string const> doc_root_; + const Config& m_config; + const Socket& m_socket; public: listener( net::io_context& ioc, ssl::context& ctx, tcp::endpoint endpoint, - std::shared_ptr<std::string const> const& doc_root) + const Config& config, + const Socket& socket) : ioc_(ioc) , ctx_(ctx) , acceptor_(ioc) - , doc_root_(doc_root) + , m_config(config) + , m_socket(socket) { beast::error_code ec; @@ -502,7 +510,8 @@ private: std::make_shared<session>( std::move(socket), ctx_, - doc_root_)->run(); + m_config, + m_socket)->run(); } // Accept another connection @@ -515,10 +524,34 @@ private: namespace HTTPS { +int servername_callback(SSL *s, int *al, void *arg) +{ + int type {SSL_get_servername_type(s)}; + std::string server_name {SSL_get_servername(s, type)}; + + Server* server = (Server*)arg; + if (server_name == "lists.antcom.de"s) { + SSL_set_SSL_CTX(s, server->m_ctx.native_handle()); + } else { + SSL_set_SSL_CTX(s, server->m_ctx2.native_handle()); + } + return SSL_TLSEXT_ERR_OK; +} + Server::Server(Config& config, boost::asio::io_context& ioc, const Socket& socket): ::Server(config, ioc), m_socket(socket) { - // This holds the self-signed certificate used by the server + for (const auto& site: socket.serve_sites) { + std::cout << "Creating SSL context/cert for site " << site << std::endl; + } + load_server_certificate(m_ctx, m_socket.cert_path, m_socket.key_path); + load_server_certificate(m_ctx2, "/home/ernie/code/webserver/cert.pem", "/home/ernie/code/webserver/key.pem"); + + SSL_CTX_set_tlsext_servername_callback(m_ctx.native_handle(), servername_callback); + SSL_CTX_set_tlsext_servername_arg(m_ctx.native_handle(), this); + + SSL_CTX_set_tlsext_servername_callback(m_ctx2.native_handle(), servername_callback); + SSL_CTX_set_tlsext_servername_arg(m_ctx2.native_handle(), this); } Server::~Server() @@ -527,17 +560,16 @@ Server::~Server() int Server::start() { - // TODO: Config auto const address = net::ip::make_address(m_socket.address); auto const port = static_cast<unsigned short>(std::atoi(m_socket.port.data())); - auto const doc_root = std::make_shared<std::string>(m_config.Sites()[0].paths[0].params.at("target")); // Create and launch a listening port std::make_shared<listener>( m_ioc, m_ctx, tcp::endpoint{address, port}, - doc_root)->run(); + m_config, + m_socket)->run(); return EXIT_SUCCESS; } @@ -15,7 +15,9 @@ namespace HTTPS { class Server: public ::Server { // The SSL context is required, and holds certificates +public: ssl::context m_ctx{ssl::context::tlsv13}; + ssl::context m_ctx2{ssl::context::tlsv13}; const Socket& m_socket; public: @@ -1,5 +1,7 @@ #pragma once +#include <boost/asio/io_context.hpp> + #include "config.h" using namespace std::string_literals; |