From cb979d96e75a026e2fdb8a9cc7c44e38cd9d9b2d Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Wed, 13 Mar 2019 12:05:57 -0700 Subject: [PATCH] ircd::net::acceptor: Add callback stack framework for dynamic server name identification. --- include/ircd/net/acceptor.h | 2 + ircd/net.cc | 88 +++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/include/ircd/net/acceptor.h b/include/ircd/net/acceptor.h index 8eb04ffac..3983369fb 100644 --- a/include/ircd/net/acceptor.h +++ b/include/ircd/net/acceptor.h @@ -24,6 +24,7 @@ struct ircd::net::acceptor using proffer = listener::proffer; IRCD_EXCEPTION(listener::error, error) + IRCD_EXCEPTION(error, sni_warning) static log::log log; static conf::item timeout; @@ -48,6 +49,7 @@ struct ircd::net::acceptor void configure(const json::object &opts); // Handshake stack + bool handle_sni(SSL &, int &ad); void check_handshake_error(const error_code &ec, socket &); void handshake(const error_code &ec, std::shared_ptr, std::weak_ptr) noexcept; diff --git a/ircd/net.cc b/ircd/net.cc index 9f55db957..6c30e2e50 100644 --- a/ircd/net.cc +++ b/ircd/net.cc @@ -1530,6 +1530,91 @@ ircd::net::acceptor::check_handshake_error(const error_code &ec, throw_system_error(ec); } +bool +ircd::net::acceptor::handle_sni(SSL &ssl, + int &ad) +try +{ + const string_view &name + { + openssl::server_name(ssl) + }; + + log::debug + { + log, "%s offered SNI '%s'", + string(logheadbuf, *this), + name + }; + + if(!name) + return false; + + return true; +} +catch(const sni_warning &e) +{ + log::warning + { + log, "%s during SNI :%s", + string(logheadbuf, *this), + e.what() + }; + + throw; +} +catch(const std::exception &e) +{ + log::error + { + log, "%s during SNI :%s", + string(logheadbuf, *this), + e.what() + }; + + throw; +} + +static int +ircd_net_acceptor_handle_sni(SSL *const s, + int *const i, + void *const a) +noexcept try +{ + if(unlikely(!s || !i || !a)) + throw ircd::panic + { + "Missing arguments to callback s:%p i:%p a:%p", s, i, a + }; + + auto &acceptor + { + *reinterpret_cast(a) + }; + + return acceptor.handle_sni(*s, *i)? + SSL_TLSEXT_ERR_OK: + SSL_TLSEXT_ERR_NOACK; +} +catch(const ircd::net::acceptor::sni_warning &) +{ + return SSL_TLSEXT_ERR_ALERT_WARNING; +} +catch(const std::exception &) +{ + return SSL_TLSEXT_ERR_ALERT_FATAL; +} +catch(...) +{ + ircd::log::critical + { + ircd::net::acceptor::log, + "Acceptor SNI callback unhandled." + }; + + throw; +} + void ircd::net::acceptor::configure(const json::object &opts) { @@ -1742,6 +1827,9 @@ ircd::net::acceptor::configure(const json::object &opts) assert(0); return "foobar"; }); + + SSL_CTX_set_tlsext_servername_callback(ssl.native_handle(), ircd_net_acceptor_handle_sni); + SSL_CTX_set_tlsext_servername_arg(ssl.native_handle(), this); } //