diff options
author | Roland Reichwein <mail@reichwein.it> | 2020-04-11 15:58:01 +0200 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2020-04-11 15:58:01 +0200 |
commit | 1374fac8de85fe1ac877096f18b60a1561dfc96f (patch) | |
tree | bc9c2f3bd4ac82fab786824e8903a400b6170d7c /https.cpp | |
parent | 6081819802972c716745a44e3521ccb3b3cf7b1a (diff) |
Replace SSL_CTX_set_tlsext_servername_callback with SSL_client_hello_get0_ext
Diffstat (limited to 'https.cpp')
-rw-r--r-- | https.cpp | 62 |
1 files changed, 48 insertions, 14 deletions
@@ -6,6 +6,7 @@ #include "response.h" #include <openssl/ssl.h> +#include <openssl/crypto.h> #include <boost/asio/buffer.hpp> #include <boost/beast/core.hpp> @@ -566,25 +567,62 @@ void load_server_certificate(boost::asio::ssl::context& ctx, fs::path cert_path, boost::asio::buffer(dh.data(), dh.size())); } +int ServerNameError(SSL *s, HTTPS::Server::ctx_type& ctx_map) +{ + std::shared_ptr<ssl::context> ctx{ctx_map.at("")}; + SSL_set_SSL_CTX(s, ctx->native_handle()); + return SSL_CLIENT_HELLO_SUCCESS; // OK for now +} + 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)}; + HTTPS::Server::ctx_type& ctx_map = *(HTTPS::Server::ctx_type*)arg; + + if (0) { // not really necessary + int* numbers; + size_t numbers_size; + if (SSL_client_hello_get1_extensions_present(s, &numbers, &numbers_size) != 1) { + std::cout << "Error on SSL_client_hello_get1_extensions_present" << std::endl; + return ServerNameError(s, ctx_map); + } + bool server_name_available {false}; + for (size_t i = 0; i < numbers_size; i++) + if (numbers[i] == 0) + server_name_available = true; + + OPENSSL_free(numbers); + + if (!server_name_available) { + std::cout << "Error: No server_name available at SSL_client_hello_get1_extensions_present" << std::endl; + return ServerNameError(s, ctx_map); + } + } + + const unsigned char* data; + size_t data_size; + // 0 is server_name + if (SSL_client_hello_get0_ext(s, 0, &data, &data_size) != 1) { + std::cout << "Warning: Error on SSL_client_hello_get0_ext: servername not available. Using dummy ctx." << std::endl; + return ServerNameError(s, ctx_map); + } - HTTPS::Server::ctx_type* ctx_map = (HTTPS::Server::ctx_type*)arg; + // SNI Server Name, See https://tools.ietf.org/html/rfc6066 (TODO: why are there 5 bytes header?) + std::string server_name {std::string((const char*)data, (size_t)data_size)}; + if (server_name.size() >= 5 && server_name[0] == '\0') + server_name = server_name.substr(5); - auto it {ctx_map->find(server_name)}; + auto it {ctx_map.find(server_name)}; std::shared_ptr<ssl::context> ctx{}; - if (it != ctx_map->end()) { + if (it != ctx_map.end()) { ctx = it->second; } else { - std::cout << "Warning: server_name " << server_name << " not found in list of prepared contexts. Using dummy ctx." << std::endl; - ctx = ctx_map->at(""); + std::cout << "Warning: server_name " << server_name << " (" << server_name.size() << ") not found in list of prepared contexts. Using dummy ctx." << std::endl; + return ServerNameError(s, ctx_map); } SSL_set_SSL_CTX(s, ctx->native_handle()); - return SSL_TLSEXT_ERR_OK; + return SSL_CLIENT_HELLO_SUCCESS; } } // anonymous namespace @@ -598,9 +636,7 @@ Server::Server(Config& config, boost::asio::io_context& ioc, const Socket& socke // initial dummy, before we can add specific ctx w/ certificate std::shared_ptr<ssl::context> ctx_dummy{std::make_shared<ssl::context>(tls_method)}; load_server_certificate(*ctx_dummy, "", ""); - //SSL_CTX_set_client_hello_cb(ctx_dummy->native_handle(), servername_callback, &m_ctx); - SSL_CTX_set_tlsext_servername_callback(ctx_dummy->native_handle(), servername_callback); - SSL_CTX_set_tlsext_servername_arg(ctx_dummy->native_handle(), &m_ctx); + SSL_CTX_set_client_hello_cb(ctx_dummy->native_handle(), servername_callback, &m_ctx); m_ctx.emplace("", ctx_dummy); // import the real certificates @@ -612,9 +648,7 @@ Server::Server(Config& config, boost::asio::io_context& ioc, const Socket& socke std::cout << "Creating SSL context/cert for site " << serve_site << " on port " << socket.port << std::endl; load_server_certificate(*ctx, site.cert_path, site.key_path); - //SSL_CTX_set_client_hello_cb(ctx->native_handle(), servername_callback, &m_ctx); - SSL_CTX_set_tlsext_servername_callback(ctx->native_handle(), servername_callback); - SSL_CTX_set_tlsext_servername_arg(ctx->native_handle(), &m_ctx); + SSL_CTX_set_client_hello_cb(ctx->native_handle(), servername_callback, &m_ctx); for (const auto& host: site.hosts) { std::cout << " Adding Host " << host << std::endl; |