diff options
| author | Roland Reichwein <mail@reichwein.it> | 2020-04-05 12:03:52 +0200 | 
|---|---|---|
| committer | Roland Reichwein <mail@reichwein.it> | 2020-04-05 12:03:52 +0200 | 
| commit | 918685c1c09de1e3cd14c41bb8cc8b89a177ccd2 (patch) | |
| tree | f803517e6a34be0216f00249dd62525eadce0d05 | |
| parent | cbfc28a946ded64e9402e1e6d32511150339ec72 (diff) | |
Different certificates for different hosts
| -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;  | 
