summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2020-04-05 12:03:52 +0200
committerRoland Reichwein <mail@reichwein.it>2020-04-05 12:03:52 +0200
commit918685c1c09de1e3cd14c41bb8cc8b89a177ccd2 (patch)
treef803517e6a34be0216f00249dd62525eadce0d05
parentcbfc28a946ded64e9402e1e6d32511150339ec72 (diff)
Different certificates for different hosts
-rw-r--r--TODO3
-rw-r--r--config.cpp2
-rw-r--r--config.h2
-rw-r--r--http.cpp36
-rw-r--r--https.cpp66
-rw-r--r--https.h2
-rw-r--r--server.h2
7 files changed, 80 insertions, 33 deletions
diff --git a/TODO b/TODO
index 1d083ca..5ec5b0e 100644
--- a/TODO
+++ b/TODO
@@ -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
diff --git a/config.cpp b/config.cpp
index 4e33dfc..6050768 100644
--- a/config.cpp
+++ b/config.cpp
@@ -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};
diff --git a/config.h b/config.h
index 0f5ec78..1c938c0 100644
--- a/config.h
+++ b/config.h
@@ -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;
};
diff --git a/http.cpp b/http.cpp
index eb4dc8c..2203ffe 100644
--- a/http.cpp
+++ b/http.cpp
@@ -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;
}
diff --git a/https.cpp b/https.cpp
index b4e77f9..9d0784e 100644
--- a/https.cpp
+++ b/https.cpp
@@ -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;
}
diff --git a/https.h b/https.h
index e137463..13a67a7 100644
--- a/https.h
+++ b/https.h
@@ -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:
diff --git a/server.h b/server.h
index 0dcf3dd..5e5343f 100644
--- a/server.h
+++ b/server.h
@@ -1,5 +1,7 @@
#pragma once
+#include <boost/asio/io_context.hpp>
+
#include "config.h"
using namespace std::string_literals;