From e234229ae80da0fa9967b797f7b5f4f381cba4b4 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sun, 5 Apr 2020 14:22:31 +0200 Subject: All certificates configurable per site --- https.cpp | 177 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 154 insertions(+), 23 deletions(-) (limited to 'https.cpp') diff --git a/https.cpp b/https.cpp index 9d0784e..0e45272 100644 --- a/https.cpp +++ b/https.cpp @@ -1,22 +1,27 @@ #include "https.h" +#include "config.h" +#include "file.h" #include "server.h" #include #if BOOST_VERSION == 107100 -#include "server_certificate.h" - #include + +#include #include #include #include #include #include +#include #include #include + #include +#include #include #include #include @@ -519,39 +524,161 @@ private: } }; -} // anonymous namespace -//------------------------------------------------------------------------------ +/* Load a signed certificate into the ssl context, and configure + the context for use with a server. -namespace HTTPS { + For this to work with the browser or operating system, it is + necessary to import the "Beast Test CA" certificate into + the local certificate store, browser, or operating system + depending on your environment Please see the documentation + accompanying the Beast certificate for more details. +*/ +void load_server_certificate(boost::asio::ssl::context& ctx, fs::path cert_path, fs::path key_path) +{ + /* + The certificate was generated from CMD.EXE on Windows 10 using: + + winpty openssl dhparam -out dh.pem 2048 + winpty openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 10000 -out cert.pem -subj "//C=US\ST=CA\L=Los Angeles\O=Beast\CN=www.example.com" + */ + + std::string const dh = + "-----BEGIN DH PARAMETERS-----\n" + "MIIBCAKCAQEArzQc5mpm0Fs8yahDeySj31JZlwEphUdZ9StM2D8+Fo7TMduGtSi+\n" + "/HRWVwHcTFAgrxVdm+dl474mOUqqaz4MpzIb6+6OVfWHbQJmXPepZKyu4LgUPvY/\n" + "4q3/iDMjIS0fLOu/bLuObwU5ccZmDgfhmz1GanRlTQOiYRty3FiOATWZBRh6uv4u\n" + "tff4A9Bm3V9tLx9S6djq31w31Gl7OQhryodW28kc16t9TvO1BzcV3HjRPwpe701X\n" + "oEEZdnZWANkkpR/m/pfgdmGPU66S2sXMHgsliViQWpDCYeehrvFRHEdR9NV+XJfC\n" + "QMUk26jPTIVTLfXmmwU0u8vUkpR7LQKkwwIBAg==\n" + "-----END DH PARAMETERS-----\n"; + + ctx.set_password_callback( + [](std::size_t, + boost::asio::ssl::context_base::password_purpose) + { + return "test"; + }); + + ctx.set_options( + boost::asio::ssl::context::default_workarounds | + boost::asio::ssl::context::no_sslv2 | + boost::asio::ssl::context::single_dh_use); + + std::string cert; + if (cert_path == "") { + cert = + "-----BEGIN CERTIFICATE-----\n" + "MIIDnTCCAoWgAwIBAgIULkYtO+2Ddeg+qLZ+aDQpmA5b4L0wDQYJKoZIhvcNAQEL\n" + "BQAwXjELMAkGA1UEBhMCREUxEDAOBgNVBAgMB0JhdmFyaWExDzANBgNVBAcMBk11\n" + "bmljaDEVMBMGA1UECgwMUmVpY2h3ZWluIElUMRUwEwYDVQQDDAxyZWljaHdlaW4u\n" + "aXQwHhcNMjAwNDA1MDgwNzIyWhcNNDcwODIyMDgwNzIyWjBeMQswCQYDVQQGEwJE\n" + "RTEQMA4GA1UECAwHQmF2YXJpYTEPMA0GA1UEBwwGTXVuaWNoMRUwEwYDVQQKDAxS\n" + "ZWljaHdlaW4gSVQxFTATBgNVBAMMDHJlaWNod2Vpbi5pdDCCASIwDQYJKoZIhvcN\n" + "AQEBBQADggEPADCCAQoCggEBALJNb0WLbz+xP+YITMMk+eeK/SIOCRFs/9aZIAyK\n" + "ParGauxa+8d25mlfJTAo6/G0h3sA240JHyNpOzVOogPU+v4dRWyGO0w5vHVD0caB\n" + "rDb1eEfmLtqfKLLUL9iPDReUh6WAE7qoNDtfoT551uSMIae1cpPUduVTnSkEgw8k\n" + "NjJSHYT800jSB2R+e7tJG3ErXDM63R3B8RbitZPoWACjpBxDT+Qrj0fBFS4AWw6b\n" + "z09uitv0RrgI6CW7xRh3UAdRwEBGHiU6HTIthX6LNgez1UL0sfu1iZ22wNmYZP/S\n" + "sL3b20WtSH9LN2PRJ4q3AGt6RMbmSGr65ljha9xkTFna0Y8CAwEAAaNTMFEwHQYD\n" + "VR0OBBYEFKd5/MGFZUAUV502vJ/Kcswax8WVMB8GA1UdIwQYMBaAFKd5/MGFZUAU\n" + "V502vJ/Kcswax8WVMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB\n" + "AIBS4AfM7wiunQ2UZQQ5A0Un99+BLax9e+h11h/jGeJ+/9maY/E9MK6UG9LXoOv2\n" + "z32Q7Ta2xKeRu6GC/qupwYJ0Xt3LENOfogsaNCAgxKlAN48LGlRyCTvzWsEMh28j\n" + "RaelWonh2qQoiryKLVnRwrg8g1Bu4v+V437cIBmeZPxf0spEL9EVqlN+iS8plmel\n" + "7/F4ULdybKGq39tgicuS7JhnY21ZzOFoq0bWnKBbAeTndmuROdb3pEppxW6pwu0q\n" + "TFdMrSJE38kiQh2O9IchPQbTZ+Rdj0HE9NxStlrNr5bu6rjikRm50/G3JoXpzYdp\n" + "AN4ZI2QZ6R6Y+TzDixKecNk=\n" + "-----END CERTIFICATE-----\n" + ; + } else { + cert = File::getFile(cert_path); + } + + ctx.use_certificate_chain( + boost::asio::buffer(cert.data(), cert.size())); + + std::string key; + if (key_path == "") { + key = + "-----BEGIN PRIVATE KEY-----\n" + "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCyTW9Fi28/sT/m\n" + "CEzDJPnniv0iDgkRbP/WmSAMij2qxmrsWvvHduZpXyUwKOvxtId7ANuNCR8jaTs1\n" + "TqID1Pr+HUVshjtMObx1Q9HGgaw29XhH5i7anyiy1C/Yjw0XlIelgBO6qDQ7X6E+\n" + "edbkjCGntXKT1HblU50pBIMPJDYyUh2E/NNI0gdkfnu7SRtxK1wzOt0dwfEW4rWT\n" + "6FgAo6QcQ0/kK49HwRUuAFsOm89Pborb9Ea4COglu8UYd1AHUcBARh4lOh0yLYV+\n" + "izYHs9VC9LH7tYmdtsDZmGT/0rC929tFrUh/Szdj0SeKtwBrekTG5khq+uZY4Wvc\n" + "ZExZ2tGPAgMBAAECggEBAK9bJKIa3dCgPB257/TEOtsTgJyrfROcRYkCk9iBZOC9\n" + "v46wdIrZTwY2wtY4iMPwLoY0c7ijTfJ/nfFxYjmujyK4Gvz+jvcKmWQizP8TrRFo\n" + "HWFo6o+slFQ8BspO9itIspd7/OtIXgY+qNBO959Sig7sjsEA5eXoc9pRS6vqizq0\n" + "j4G/UO5Amr/l3ciEJiqMJgZsIVLDKaGlqFTymydSqkB8UHQYWK1kunQxhK4Ldycu\n" + "hTooQE7tXM0zvoFVV6v1fldV5OFsZk2kPMNtvMO6ZEpOM4rNMlg+vJy8kB1fb3Gs\n" + "iFE/DCUpZsMSserQMU9/hfrYlndgsFD5Sr1EVGEebhECgYEA1gc9qx+ugdhYTY5j\n" + "tJDXjOsnw8KY/l/1y+mQ8XNJ9MVdBGy1WB+uWB4teiyJchV49gn2XlKUK2rcCBvZ\n" + "vC5CwPmFi2t70JezQgnXtDlbR0bARPlRd741i4rBpD7hEiZNCTOd2HFBpUg/CGWN\n" + "E4n1ksazBm6jvv3Jo6WAa07Z390CgYEA1USrFqmc/fKGQpTCdH0qYZv3hQtrb1TQ\n" + "9YnrbhtaC0haPpintZKjvhU3tCd1fPuIDXtMAgaaKSyoGiE2aMvLxt1/eV08BkMi\n" + "kGIss9poYNi5+6ZD9QAHmHJhzZtVGj8U5L8379XmwxAByiBRVVE8CW1X/e6+iJpz\n" + "+CLgN+zEVlsCgYEAsuOAdtxXJm4meERwL8b0cvNF3Eh1Sf/42MPTAwzCntSrh3w5\n" + "InvwY/RtPHWnN/ScksEG7BWHhLafTCPDHJdp8hNcvIhNB68UBDln0loyYePP5pag\n" + "sj4IUSbb7SUlR989elhrMTKQlM5K6QDAJrmjyVdM4S5urL9A3wgAyzAvyP0CgYAO\n" + "paGuc8WxdzebWQYl4/bGL2UHgSpGwid7xZYiwMQlZDm2dNuHz+NpCaICwHcEN243\n" + "ptEojnWGAGgnK0LGXcDIDqxTlICr2W6FRgjV7Vkf1aKoUtn1+KOM58YpzdJBdDWm\n" + "JC/eS+2GVhIZZLDRUDv0VcsmSIBTd3AhiZumm588YwKBgBZfNqfmHAwIP2pM1wml\n" + "Ck3vaLLvonghj3iQW9CFJ/SqLOnfT4KJkFObR6oGbxY0RtXsCrmSqidIKgDd0Kkq\n" + "L6QbHp2j3+16GBdmLNUJlfjBTNPJp69IDKztjeCX7/8JZs79p/LAv+I9Sh4lVw4O\n" + "IrDprlB0yzP5zigcsAZeViYJ\n" + "-----END PRIVATE KEY-----\n" + ; + } else { + key = File::getFile(key_path); + } + ctx.use_private_key( + boost::asio::buffer(key.data(), key.size()), + boost::asio::ssl::context::file_format::pem); + + ctx.use_tmp_dh( + boost::asio::buffer(dh.data(), dh.size())); +} 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()); - } + HTTPS::Server::ctx_type* ctx_map = (HTTPS::Server::ctx_type*)arg; + + ssl::context& ctx = *(ctx_map->at(server_name)); + + SSL_set_SSL_CTX(s, ctx.native_handle()); + return SSL_TLSEXT_ERR_OK; } +} // anonymous namespace +//------------------------------------------------------------------------------ + +namespace HTTPS { + Server::Server(Config& config, boost::asio::io_context& ioc, const Socket& socket): ::Server(config, ioc), m_socket(socket) { - for (const auto& site: socket.serve_sites) { - std::cout << "Creating SSL context/cert for site " << site << std::endl; - } + for (const auto& serve_site: socket.serve_sites) { + for (const auto& site: config.Sites()) { + if (site.name == serve_site) { + std::shared_ptr ctx {std::make_shared(tls_method)}; - 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); + std::cout << "Creating SSL context/cert for site " << serve_site << std::endl; + + load_server_certificate(*ctx, site.cert_path, site.key_path); + SSL_CTX_set_tlsext_servername_callback(ctx->native_handle(), servername_callback); + SSL_CTX_set_tlsext_servername_arg(ctx->native_handle(), &m_ctx); + + for (const auto& host: site.hosts) { + std::cout << " Adding Host " << host << std::endl; + m_ctx.emplace(host, ctx); + } + } + } + } } Server::~Server() @@ -563,10 +690,14 @@ int Server::start() auto const address = net::ip::make_address(m_socket.address); auto const port = static_cast(std::atoi(m_socket.port.data())); + load_server_certificate(m_ctx_dummy, "", ""); // initial dummy, before we can add specific ctx w/ certificate + SSL_CTX_set_tlsext_servername_callback(m_ctx_dummy.native_handle(), servername_callback); + SSL_CTX_set_tlsext_servername_arg(m_ctx_dummy.native_handle(), &m_ctx); + // Create and launch a listening port std::make_shared( m_ioc, - m_ctx, + m_ctx_dummy, tcp::endpoint{address, port}, m_config, m_socket)->run(); -- cgit v1.2.3