From a3b0284837c9ea10865e6ddeb7f1244d621ae5c0 Mon Sep 17 00:00:00 2001 From: Lee Clagett Date: Mon, 11 Mar 2019 22:01:03 -0400 Subject: Change SSL certificate file list to OpenSSL builtin load_verify_location Specifying SSL certificates for peer verification does an exact match, making it a not-so-obvious alias for the fingerprints option. This changes the checks to OpenSSL which loads concatenated certificate(s) from a single file and does a certificate-authority (chain of trust) check instead. There is no drop in security - a compromised exact match fingerprint has the same worse case failure. There is increased security in allowing separate long-term CA key and short-term SSL server keys. This also removes loading of the system-default CA files if a custom CA file or certificate fingerprint is specified. --- contrib/epee/include/net/abstract_tcp_server2.h | 6 ++---- contrib/epee/include/net/abstract_tcp_server2.inl | 8 ++++---- contrib/epee/include/net/http_client.h | 12 ++++++------ contrib/epee/include/net/http_server_impl_base.h | 4 ++-- contrib/epee/include/net/net_helper.h | 6 ++---- contrib/epee/include/net/net_ssl.h | 7 ++++--- 6 files changed, 20 insertions(+), 23 deletions(-) (limited to 'contrib/epee/include/net') diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h index ec08c0f4b..f28b1fb7d 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.h +++ b/contrib/epee/include/net/abstract_tcp_server2.h @@ -228,8 +228,8 @@ namespace net_utils std::map server_type_map; void create_server_type_map(); - bool init_server(uint32_t port, const std::string address = "0.0.0.0", epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair &private_key_and_certificate_path = std::make_pair(std::string(), std::string()), const std::list &allowed_certificates = {}, const std::vector> &allowed_fingerprints = {}, bool allow_any_cert = false); - bool init_server(const std::string port, const std::string& address = "0.0.0.0", epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair &private_key_and_certificate_path = std::make_pair(std::string(), std::string()), const std::list &allowed_certificates = {}, const std::vector> &allowed_fingerprints = {}, bool allow_any_cert = false); + bool init_server(uint32_t port, const std::string address = "0.0.0.0", epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair &private_key_and_certificate_path = std::make_pair(std::string(), std::string()), const std::string &ca_file = {}, const std::vector> &allowed_fingerprints = {}, bool allow_any_cert = false); + bool init_server(const std::string port, const std::string& address = "0.0.0.0", epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair &private_key_and_certificate_path = std::make_pair(std::string(), std::string()), const std::string &ca_file = {}, const std::vector> &allowed_fingerprints = {}, bool allow_any_cert = false); /// Run the server's io_service loop. bool run_server(size_t threads_count, bool wait = true, const boost::thread::attributes& attrs = boost::thread::attributes()); @@ -382,8 +382,6 @@ namespace net_utils std::set connections_; ssl_context_t m_ssl_context; - std::list m_allowed_certificates; - }; // class <>boosted_tcp_server diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index 67c63cca5..e8b5b6c1e 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -941,14 +941,14 @@ PRAGMA_WARNING_DISABLE_VS(4355) } //--------------------------------------------------------------------------------- template - bool boosted_tcp_server::init_server(uint32_t port, const std::string address, epee::net_utils::ssl_support_t ssl_support, const std::pair &private_key_and_certificate_path, const std::list &allowed_certificates, const std::vector> &allowed_fingerprints, bool allow_any_cert) + bool boosted_tcp_server::init_server(uint32_t port, const std::string address, epee::net_utils::ssl_support_t ssl_support, const std::pair &private_key_and_certificate_path, const std::string &ca_file, const std::vector> &allowed_fingerprints, bool allow_any_cert) { TRY_ENTRY(); m_stop_signal_sent = false; m_port = port; m_address = address; if (ssl_support != epee::net_utils::ssl_support_t::e_ssl_support_disabled) - m_ssl_context = create_ssl_context(private_key_and_certificate_path, allowed_certificates, allowed_fingerprints, allow_any_cert); + m_ssl_context = create_ssl_context(private_key_and_certificate_path, ca_file, allowed_fingerprints, allow_any_cert); // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). boost::asio::ip::tcp::resolver resolver(io_service_); boost::asio::ip::tcp::resolver::query query(address, boost::lexical_cast(port), boost::asio::ip::tcp::resolver::query::canonical_name); @@ -982,7 +982,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) PUSH_WARNINGS DISABLE_GCC_WARNING(maybe-uninitialized) template - bool boosted_tcp_server::init_server(const std::string port, const std::string& address, epee::net_utils::ssl_support_t ssl_support, const std::pair &private_key_and_certificate_path, const std::list &allowed_certificates, const std::vector> &allowed_fingerprints, bool allow_any_cert) + bool boosted_tcp_server::init_server(const std::string port, const std::string& address, epee::net_utils::ssl_support_t ssl_support, const std::pair &private_key_and_certificate_path, const std::string &ca_file, const std::vector> &allowed_fingerprints, bool allow_any_cert) { uint32_t p = 0; @@ -990,7 +990,7 @@ DISABLE_GCC_WARNING(maybe-uninitialized) MERROR("Failed to convert port no = " << port); return false; } - return this->init_server(p, address, ssl_support, private_key_and_certificate_path, allowed_certificates, allowed_fingerprints, allow_any_cert); + return this->init_server(p, address, ssl_support, private_key_and_certificate_path, ca_file, allowed_fingerprints, allow_any_cert); } POP_WARNINGS //--------------------------------------------------------------------------------- diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h index 1864c77ad..36158b99f 100644 --- a/contrib/epee/include/net/http_client.h +++ b/contrib/epee/include/net/http_client.h @@ -277,7 +277,7 @@ namespace net_utils critical_section m_lock; epee::net_utils::ssl_support_t m_ssl_support; std::pair m_ssl_private_key_and_certificate_path; - std::list m_ssl_allowed_certificates; + std::string m_ssl_ca_file; std::vector> m_ssl_allowed_fingerprints; bool m_ssl_allow_any_cert; @@ -303,16 +303,16 @@ namespace net_utils const std::string &get_host() const { return m_host_buff; }; const std::string &get_port() const { return m_port; }; - bool set_server(const std::string& address, boost::optional user, epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair &private_key_and_certificate_path = {}, const std::list &allowed_ssl_certificates = {}, const std::vector> &allowed_ssl_fingerprints = {}, bool allow_any_cert = false) + bool set_server(const std::string& address, boost::optional user, epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair &private_key_and_certificate_path = {}, std::string ca_file = {}, const std::vector> &allowed_ssl_fingerprints = {}, bool allow_any_cert = false) { http::url_content parsed{}; const bool r = parse_url(address, parsed); CHECK_AND_ASSERT_MES(r, false, "failed to parse url: " << address); - set_server(std::move(parsed.host), std::to_string(parsed.port), std::move(user), ssl_support, private_key_and_certificate_path, allowed_ssl_certificates, allowed_ssl_fingerprints, allow_any_cert); + set_server(std::move(parsed.host), std::to_string(parsed.port), std::move(user), ssl_support, private_key_and_certificate_path, std::move(ca_file), allowed_ssl_fingerprints, allow_any_cert); return true; } - void set_server(std::string host, std::string port, boost::optional user, epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair &private_key_and_certificate_path = {}, const std::list &allowed_ssl_certificates = {}, const std::vector> &allowed_ssl_fingerprints = {}, bool allow_any_cert = false) + void set_server(std::string host, std::string port, boost::optional user, epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair &private_key_and_certificate_path = {}, std::string ca_file = {}, const std::vector> &allowed_ssl_fingerprints = {}, bool allow_any_cert = false) { CRITICAL_REGION_LOCAL(m_lock); disconnect(); @@ -321,10 +321,10 @@ namespace net_utils m_auth = user ? http_client_auth{std::move(*user)} : http_client_auth{}; m_ssl_support = ssl_support; m_ssl_private_key_and_certificate_path = private_key_and_certificate_path; - m_ssl_allowed_certificates = allowed_ssl_certificates; + m_ssl_ca_file = std::move(ca_file); m_ssl_allowed_fingerprints = allowed_ssl_fingerprints; m_ssl_allow_any_cert = allow_any_cert; - m_net_client.set_ssl(m_ssl_support, m_ssl_private_key_and_certificate_path, m_ssl_allowed_certificates, m_ssl_allowed_fingerprints, m_ssl_allow_any_cert); + m_net_client.set_ssl(m_ssl_support, m_ssl_private_key_and_certificate_path, m_ssl_ca_file, m_ssl_allowed_fingerprints, m_ssl_allow_any_cert); } template diff --git a/contrib/epee/include/net/http_server_impl_base.h b/contrib/epee/include/net/http_server_impl_base.h index 0922f21f2..8a6b32943 100644 --- a/contrib/epee/include/net/http_server_impl_base.h +++ b/contrib/epee/include/net/http_server_impl_base.h @@ -61,7 +61,7 @@ namespace epee boost::optional user = boost::none, epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair &private_key_and_certificate_path = {}, - std::list allowed_certificates = {}, + const std::string &ca_path = {}, std::vector> allowed_fingerprints = {}, bool allow_any_cert = false) { @@ -80,7 +80,7 @@ namespace epee m_net_server.get_config_object().m_user = std::move(user); MGINFO("Binding on " << bind_ip << ":" << bind_port); - bool res = m_net_server.init_server(bind_port, bind_ip, ssl_support, private_key_and_certificate_path, std::move(allowed_certificates), std::move(allowed_fingerprints), allow_any_cert); + bool res = m_net_server.init_server(bind_port, bind_ip, ssl_support, private_key_and_certificate_path, ca_path, std::move(allowed_fingerprints), allow_any_cert); if(!res) { LOG_ERROR("Failed to bind server"); diff --git a/contrib/epee/include/net/net_helper.h b/contrib/epee/include/net/net_helper.h index aa3df7160..2b220bb0f 100644 --- a/contrib/epee/include/net/net_helper.h +++ b/contrib/epee/include/net/net_helper.h @@ -136,12 +136,12 @@ namespace net_utils catch(...) { /* ignore */ } } - inline void set_ssl(epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair &private_key_and_certificate_path = {}, std::list allowed_certificates = {}, std::vector> allowed_fingerprints = {}, bool allow_any_cert = false) + inline void set_ssl(epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair &private_key_and_certificate_path = {}, const std::string &ca_path = {}, std::vector> allowed_fingerprints = {}, bool allow_any_cert = false) { if (ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_disabled) m_ctx = {boost::asio::ssl::context(boost::asio::ssl::context::tlsv12), {}, {}}; else - m_ctx = create_ssl_context(private_key_and_certificate_path, std::move(allowed_certificates), std::move(allowed_fingerprints), allow_any_cert); + m_ctx = create_ssl_context(private_key_and_certificate_path, ca_path, std::move(allowed_fingerprints), allow_any_cert); m_ssl_support = ssl_support; } @@ -212,8 +212,6 @@ namespace net_utils // Set SSL options // disable sslv2 - m_ctx.context.set_options(boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2); - m_ctx.context.set_default_verify_paths(); m_ssl_socket.reset(new boost::asio::ssl::stream(m_io_service, m_ctx.context)); // Get a list of endpoints corresponding to the server name. diff --git a/contrib/epee/include/net/net_ssl.h b/contrib/epee/include/net/net_ssl.h index f7b102164..1b90a948d 100644 --- a/contrib/epee/include/net/net_ssl.h +++ b/contrib/epee/include/net/net_ssl.h @@ -31,10 +31,11 @@ #include #include -#include +#include #include #include #include +#include namespace epee { @@ -49,7 +50,7 @@ namespace net_utils struct ssl_context_t { boost::asio::ssl::context context; - std::list allowed_certificates; + std::string ca_path; std::vector> allowed_fingerprints; bool allow_any_cert; }; @@ -57,7 +58,7 @@ namespace net_utils // https://security.stackexchange.com/questions/34780/checking-client-hello-for-https-classification constexpr size_t get_ssl_magic_size() { return 9; } bool is_ssl(const unsigned char *data, size_t len); - ssl_context_t create_ssl_context(const std::pair &private_key_and_certificate_path, std::list allowed_certificates, std::vector> allowed_fingerprints, bool allow_any_cert); + ssl_context_t create_ssl_context(const std::pair &private_key_and_certificate_path, const std::string &ca_path, std::vector> allowed_fingerprints, bool allow_any_cert); void use_ssl_certificate(ssl_context_t &ssl_context, const std::pair &private_key_and_certificate_path); bool is_certificate_allowed(boost::asio::ssl::verify_context &ctx, const ssl_context_t &ssl_context); bool ssl_handshake(boost::asio::ssl::stream &socket, boost::asio::ssl::stream_base::handshake_type type, const epee::net_utils::ssl_context_t &ssl_context); -- cgit v1.2.3 From 21eb1b0725717ad013d3e2b00fbfc3b84ad04699 Mon Sep 17 00:00:00 2001 From: Lee Clagett Date: Fri, 15 Mar 2019 00:03:32 -0400 Subject: Pass SSL arguments via one class and use shared_ptr instead of reference --- contrib/epee/include/net/abstract_tcp_server2.h | 16 ++--- contrib/epee/include/net/abstract_tcp_server2.inl | 44 ++++++-------- contrib/epee/include/net/connection_basic.hpp | 54 +++++++++++------ contrib/epee/include/net/http_client.h | 19 ++---- contrib/epee/include/net/http_server_impl_base.h | 8 +-- contrib/epee/include/net/net_helper.h | 48 +++++++-------- contrib/epee/include/net/net_ssl.h | 74 +++++++++++++++++++---- 7 files changed, 152 insertions(+), 111 deletions(-) (limited to 'contrib/epee/include/net') diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h index f28b1fb7d..d0eabbba5 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.h +++ b/contrib/epee/include/net/abstract_tcp_server2.h @@ -90,10 +90,10 @@ namespace net_utils public: typedef typename t_protocol_handler::connection_context t_connection_context; - struct shared_state : socket_stats + struct shared_state : connection_basic_shared_state { shared_state() - : socket_stats(), pfilter(nullptr), config() + : connection_basic_shared_state(), pfilter(nullptr), config() {} i_connection_filter* pfilter; @@ -104,14 +104,12 @@ namespace net_utils explicit connection( boost::asio::io_service& io_service, boost::shared_ptr state, t_connection_type connection_type, - epee::net_utils::ssl_support_t ssl_support, - ssl_context_t &ssl_context); + epee::net_utils::ssl_support_t ssl_support); explicit connection( boost::asio::ip::tcp::socket&& sock, boost::shared_ptr state, t_connection_type connection_type, - epee::net_utils::ssl_support_t ssl_support, - ssl_context_t &ssl_context); + epee::net_utils::ssl_support_t ssl_support); @@ -228,8 +226,8 @@ namespace net_utils std::map server_type_map; void create_server_type_map(); - bool init_server(uint32_t port, const std::string address = "0.0.0.0", epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair &private_key_and_certificate_path = std::make_pair(std::string(), std::string()), const std::string &ca_file = {}, const std::vector> &allowed_fingerprints = {}, bool allow_any_cert = false); - bool init_server(const std::string port, const std::string& address = "0.0.0.0", epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair &private_key_and_certificate_path = std::make_pair(std::string(), std::string()), const std::string &ca_file = {}, const std::vector> &allowed_fingerprints = {}, bool allow_any_cert = false); + bool init_server(uint32_t port, const std::string address = "0.0.0.0", ssl_options_t ssl_options = ssl_support_t::e_ssl_support_autodetect); + bool init_server(const std::string port, const std::string& address = "0.0.0.0", ssl_options_t ssl_options = ssl_support_t::e_ssl_support_autodetect); /// Run the server's io_service loop. bool run_server(size_t threads_count, bool wait = true, const boost::thread::attributes& attrs = boost::thread::attributes()); @@ -380,8 +378,6 @@ namespace net_utils boost::mutex connections_mutex; std::set connections_; - - ssl_context_t m_ssl_context; }; // class <>boosted_tcp_server diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index e8b5b6c1e..58f899a73 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -80,10 +80,9 @@ PRAGMA_WARNING_DISABLE_VS(4355) connection::connection( boost::asio::io_service& io_service, boost::shared_ptr state, t_connection_type connection_type, - epee::net_utils::ssl_support_t ssl_support, - ssl_context_t &ssl_context + ssl_support_t ssl_support ) - : connection(boost::asio::ip::tcp::socket{io_service}, std::move(state), connection_type, ssl_support, ssl_context) + : connection(boost::asio::ip::tcp::socket{io_service}, std::move(state), connection_type, ssl_support) { } @@ -91,11 +90,10 @@ PRAGMA_WARNING_DISABLE_VS(4355) connection::connection( boost::asio::ip::tcp::socket&& sock, boost::shared_ptr state, t_connection_type connection_type, - epee::net_utils::ssl_support_t ssl_support, - ssl_context_t &ssl_context + ssl_support_t ssl_support ) : - connection_basic(std::move(sock), state, ssl_support, ssl_context), + connection_basic(std::move(sock), state, ssl_support), m_protocol_handler(this, check_and_get(state).config, context), m_connection_type( connection_type ), m_throttle_speed_in("speed_in", "throttle_speed_in"), @@ -176,9 +174,9 @@ PRAGMA_WARNING_DISABLE_VS(4355) _dbg3("[sock " << socket_.native_handle() << "] new connection from " << print_connection_context_short(context) << " to " << local_ep.address().to_string() << ':' << local_ep.port() << - ", total sockets objects " << get_stats().sock_count); + ", total sockets objects " << get_state().sock_count); - if(static_cast(get_stats()).pfilter && !static_cast(get_stats()).pfilter->is_remote_host_allowed(context.m_remote_address)) + if(static_cast(get_state()).pfilter && !static_cast(get_state()).pfilter->is_remote_host_allowed(context.m_remote_address)) { _dbg2("[sock " << socket().native_handle() << "] host denied " << context.m_remote_address.host_str() << ", shutdowning connection"); close(); @@ -901,8 +899,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) m_threads_count(0), m_thread_index(0), m_connection_type( connection_type ), - new_connection_(), - m_ssl_context({boost::asio::ssl::context(boost::asio::ssl::context::tlsv12), {}}) + new_connection_() { create_server_type_map(); m_thread_name_prefix = "NET"; @@ -918,8 +915,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) m_threads_count(0), m_thread_index(0), m_connection_type(connection_type), - new_connection_(), - m_ssl_context({boost::asio::ssl::context(boost::asio::ssl::context::sslv23), {}}) + new_connection_() { create_server_type_map(); m_thread_name_prefix = "NET"; @@ -941,14 +937,14 @@ PRAGMA_WARNING_DISABLE_VS(4355) } //--------------------------------------------------------------------------------- template - bool boosted_tcp_server::init_server(uint32_t port, const std::string address, epee::net_utils::ssl_support_t ssl_support, const std::pair &private_key_and_certificate_path, const std::string &ca_file, const std::vector> &allowed_fingerprints, bool allow_any_cert) + bool boosted_tcp_server::init_server(uint32_t port, const std::string address, ssl_options_t ssl_options) { TRY_ENTRY(); m_stop_signal_sent = false; m_port = port; m_address = address; - if (ssl_support != epee::net_utils::ssl_support_t::e_ssl_support_disabled) - m_ssl_context = create_ssl_context(private_key_and_certificate_path, ca_file, allowed_fingerprints, allow_any_cert); + if (ssl_options) + m_state->configure_ssl(std::move(ssl_options)); // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). boost::asio::ip::tcp::resolver resolver(io_service_); boost::asio::ip::tcp::resolver::query query(address, boost::lexical_cast(port), boost::asio::ip::tcp::resolver::query::canonical_name); @@ -960,7 +956,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) boost::asio::ip::tcp::endpoint binded_endpoint = acceptor_.local_endpoint(); m_port = binded_endpoint.port(); MDEBUG("start accept"); - new_connection_.reset(new connection(io_service_, m_state, m_connection_type, ssl_support, m_ssl_context)); + new_connection_.reset(new connection(io_service_, m_state, m_connection_type, m_state->ssl_options().support)); acceptor_.async_accept(new_connection_->socket(), boost::bind(&boosted_tcp_server::handle_accept, this, boost::asio::placeholders::error)); @@ -982,7 +978,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) PUSH_WARNINGS DISABLE_GCC_WARNING(maybe-uninitialized) template - bool boosted_tcp_server::init_server(const std::string port, const std::string& address, epee::net_utils::ssl_support_t ssl_support, const std::pair &private_key_and_certificate_path, const std::string &ca_file, const std::vector> &allowed_fingerprints, bool allow_any_cert) + bool boosted_tcp_server::init_server(const std::string port, const std::string& address, ssl_options_t ssl_options) { uint32_t p = 0; @@ -990,7 +986,7 @@ DISABLE_GCC_WARNING(maybe-uninitialized) MERROR("Failed to convert port no = " << port); return false; } - return this->init_server(p, address, ssl_support, private_key_and_certificate_path, ca_file, allowed_fingerprints, allow_any_cert); + return this->init_server(p, address, std::move(ssl_options)); } POP_WARNINGS //--------------------------------------------------------------------------------- @@ -1165,7 +1161,7 @@ POP_WARNINGS new_connection_->setRpcStation(); // hopefully this is not needed actually } connection_ptr conn(std::move(new_connection_)); - new_connection_.reset(new connection(io_service_, m_state, m_connection_type, conn->get_ssl_support(), m_ssl_context)); + new_connection_.reset(new connection(io_service_, m_state, m_connection_type, conn->get_ssl_support())); acceptor_.async_accept(new_connection_->socket(), boost::bind(&boosted_tcp_server::handle_accept, this, boost::asio::placeholders::error)); @@ -1200,7 +1196,7 @@ POP_WARNINGS assert(m_state != nullptr); // always set in constructor _erro("Some problems at accept: " << e.message() << ", connections_count = " << m_state->sock_count); misc_utils::sleep_no_w(100); - new_connection_.reset(new connection(io_service_, m_state, m_connection_type, new_connection_->get_ssl_support(), m_ssl_context)); + new_connection_.reset(new connection(io_service_, m_state, m_connection_type, new_connection_->get_ssl_support())); acceptor_.async_accept(new_connection_->socket(), boost::bind(&boosted_tcp_server::handle_accept, this, boost::asio::placeholders::error)); @@ -1211,7 +1207,7 @@ POP_WARNINGS { if(std::addressof(get_io_service()) == std::addressof(GET_IO_SERVICE(sock))) { - connection_ptr conn(new connection(std::move(sock), m_state, m_connection_type, ssl_support, m_ssl_context)); + connection_ptr conn(new connection(std::move(sock), m_state, m_connection_type, ssl_support)); if(conn->start(false, 1 < m_threads_count, std::move(real_remote))) { conn->get_context(out); @@ -1298,7 +1294,7 @@ POP_WARNINGS _dbg3("Connected success to " << adr << ':' << port); - const epee::net_utils::ssl_support_t ssl_support = new_connection_l->get_ssl_support(); + const ssl_support_t ssl_support = new_connection_l->get_ssl_support(); if (ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_enabled || ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect) { // Handshake @@ -1329,7 +1325,7 @@ POP_WARNINGS { TRY_ENTRY(); - connection_ptr new_connection_l(new connection(io_service_, m_state, m_connection_type, ssl_support, m_ssl_context) ); + connection_ptr new_connection_l(new connection(io_service_, m_state, m_connection_type, ssl_support) ); connections_mutex.lock(); connections_.insert(new_connection_l); MDEBUG("connections_ size now " << connections_.size()); @@ -1393,7 +1389,7 @@ POP_WARNINGS bool boosted_tcp_server::connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeout, const t_callback &cb, const std::string& bind_ip, epee::net_utils::ssl_support_t ssl_support) { TRY_ENTRY(); - connection_ptr new_connection_l(new connection(io_service_, m_state, m_connection_type, ssl_support, m_ssl_context) ); + connection_ptr new_connection_l(new connection(io_service_, m_state, m_connection_type, ssl_support) ); connections_mutex.lock(); connections_.insert(new_connection_l); MDEBUG("connections_ size now " << connections_.size()); diff --git a/contrib/epee/include/net/connection_basic.hpp b/contrib/epee/include/net/connection_basic.hpp index feedc6895..d3f5f4f24 100644 --- a/contrib/epee/include/net/connection_basic.hpp +++ b/contrib/epee/include/net/connection_basic.hpp @@ -57,15 +57,30 @@ namespace epee { namespace net_utils { - struct socket_stats - { - socket_stats() - : sock_count(0), sock_number(0) - {} - - std::atomic sock_count; - std::atomic sock_number; - }; + + class connection_basic_shared_state + { + ssl_options_t ssl_options_; + public: + boost::asio::ssl::context ssl_context; + std::atomic sock_count; + std::atomic sock_number; + + connection_basic_shared_state() + : ssl_options_(ssl_support_t::e_ssl_support_disabled), + ssl_context(boost::asio::ssl::context::tlsv12), + sock_count(0), + sock_number(0) + {} + + void configure_ssl(ssl_options_t src) + { + ssl_options_ = std::move(src); + ssl_context = ssl_options_.create_context(); + } + + const ssl_options_t& ssl_options() const noexcept { return ssl_options_; } + }; /************************************************************************/ /* */ @@ -83,9 +98,10 @@ class connection_basic_pimpl; // PIMPL for this class std::string to_string(t_connection_type type); class connection_basic { // not-templated base class for rapid developmet of some code parts - // beware of removing const, net_utils::connection is sketchily doing a cast to prevent storing ptr twice - const boost::shared_ptr m_stats; + // beware of removing const, net_utils::connection is sketchily doing a cast to prevent storing ptr twice + const boost::shared_ptr m_state; public: + std::unique_ptr< connection_basic_pimpl > mI; // my Implementation // moved here from orginal connecton<> - common member variables that do not depend on template in connection<> @@ -97,20 +113,19 @@ class connection_basic { // not-templated base class for rapid developmet of som /// Strand to ensure the connection's handlers are not called concurrently. boost::asio::io_service::strand strand_; /// Socket for the connection. - ssl_context_t &m_ssl_context; - ssl_support_t m_ssl_support; boost::asio::ssl::stream socket_; + ssl_support_t m_ssl_support; public: // first counter is the ++/-- count of current sockets, the other socket_number is only-increasing ++ number generator - connection_basic(boost::asio::ip::tcp::socket&& socket, boost::shared_ptr stats, ssl_support_t ssl_support, ssl_context_t &ssl_context); - connection_basic(boost::asio::io_service &io_service, boost::shared_ptr stats, ssl_support_t ssl_support, ssl_context_t &ssl_context); + connection_basic(boost::asio::ip::tcp::socket&& socket, boost::shared_ptr state, ssl_support_t ssl_support); + connection_basic(boost::asio::io_service &io_service, boost::shared_ptr state, ssl_support_t ssl_support); virtual ~connection_basic() noexcept(false); - //! \return `socket_stats` object passed in construction (ptr never changes). - socket_stats& get_stats() noexcept { return *m_stats; /* verified in constructor */ } - connection_basic(boost::asio::io_service& io_service, std::atomic &ref_sock_count, std::atomic &sock_number, ssl_support_t ssl, ssl_context_t &ssl_context); + //! \return `shared_state` object passed in construction (ptr never changes). + connection_basic_shared_state& get_state() noexcept { return *m_state; /* verified in constructor */ } + connection_basic(boost::asio::io_service& io_service, std::atomic &ref_sock_count, std::atomic &sock_number, ssl_support_t ssl); boost::asio::ip::tcp::socket& socket() { return socket_.next_layer(); } ssl_support_t get_ssl_support() const { return m_ssl_support; } @@ -118,7 +133,8 @@ class connection_basic { // not-templated base class for rapid developmet of som bool handshake(boost::asio::ssl::stream_base::handshake_type type) { - return ssl_handshake(socket_, type, m_ssl_context); + //m_state != nullptr verified in constructor + return m_state->ssl_options().handshake(socket_, type); } template diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h index 36158b99f..a18a1d30a 100644 --- a/contrib/epee/include/net/http_client.h +++ b/contrib/epee/include/net/http_client.h @@ -275,11 +275,6 @@ namespace net_utils chunked_state m_chunked_state; std::string m_chunked_cache; critical_section m_lock; - epee::net_utils::ssl_support_t m_ssl_support; - std::pair m_ssl_private_key_and_certificate_path; - std::string m_ssl_ca_file; - std::vector> m_ssl_allowed_fingerprints; - bool m_ssl_allow_any_cert; public: explicit http_simple_client_template() @@ -297,34 +292,28 @@ namespace net_utils , m_chunked_state() , m_chunked_cache() , m_lock() - , m_ssl_support(epee::net_utils::ssl_support_t::e_ssl_support_autodetect) {} const std::string &get_host() const { return m_host_buff; }; const std::string &get_port() const { return m_port; }; - bool set_server(const std::string& address, boost::optional user, epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair &private_key_and_certificate_path = {}, std::string ca_file = {}, const std::vector> &allowed_ssl_fingerprints = {}, bool allow_any_cert = false) + bool set_server(const std::string& address, boost::optional user, ssl_options_t ssl_options = ssl_support_t::e_ssl_support_autodetect) { http::url_content parsed{}; const bool r = parse_url(address, parsed); CHECK_AND_ASSERT_MES(r, false, "failed to parse url: " << address); - set_server(std::move(parsed.host), std::to_string(parsed.port), std::move(user), ssl_support, private_key_and_certificate_path, std::move(ca_file), allowed_ssl_fingerprints, allow_any_cert); + set_server(std::move(parsed.host), std::to_string(parsed.port), std::move(user), std::move(ssl_options)); return true; } - void set_server(std::string host, std::string port, boost::optional user, epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair &private_key_and_certificate_path = {}, std::string ca_file = {}, const std::vector> &allowed_ssl_fingerprints = {}, bool allow_any_cert = false) + void set_server(std::string host, std::string port, boost::optional user, ssl_options_t ssl_options = ssl_support_t::e_ssl_support_autodetect) { CRITICAL_REGION_LOCAL(m_lock); disconnect(); m_host_buff = std::move(host); m_port = std::move(port); m_auth = user ? http_client_auth{std::move(*user)} : http_client_auth{}; - m_ssl_support = ssl_support; - m_ssl_private_key_and_certificate_path = private_key_and_certificate_path; - m_ssl_ca_file = std::move(ca_file); - m_ssl_allowed_fingerprints = allowed_ssl_fingerprints; - m_ssl_allow_any_cert = allow_any_cert; - m_net_client.set_ssl(m_ssl_support, m_ssl_private_key_and_certificate_path, m_ssl_ca_file, m_ssl_allowed_fingerprints, m_ssl_allow_any_cert); + m_net_client.set_ssl(std::move(ssl_options)); } template diff --git a/contrib/epee/include/net/http_server_impl_base.h b/contrib/epee/include/net/http_server_impl_base.h index 8a6b32943..fc2dcbf67 100644 --- a/contrib/epee/include/net/http_server_impl_base.h +++ b/contrib/epee/include/net/http_server_impl_base.h @@ -59,11 +59,7 @@ namespace epee bool init(std::function rng, const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0", std::vector access_control_origins = std::vector(), boost::optional user = boost::none, - epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, - const std::pair &private_key_and_certificate_path = {}, - const std::string &ca_path = {}, - std::vector> allowed_fingerprints = {}, - bool allow_any_cert = false) + net_utils::ssl_options_t ssl_options = net_utils::ssl_support_t::e_ssl_support_autodetect) { //set self as callback handler @@ -80,7 +76,7 @@ namespace epee m_net_server.get_config_object().m_user = std::move(user); MGINFO("Binding on " << bind_ip << ":" << bind_port); - bool res = m_net_server.init_server(bind_port, bind_ip, ssl_support, private_key_and_certificate_path, ca_path, std::move(allowed_fingerprints), allow_any_cert); + bool res = m_net_server.init_server(bind_port, bind_ip, std::move(ssl_options)); if(!res) { LOG_ERROR("Failed to bind server"); diff --git a/contrib/epee/include/net/net_helper.h b/contrib/epee/include/net/net_helper.h index 2b220bb0f..a9bfd6baa 100644 --- a/contrib/epee/include/net/net_helper.h +++ b/contrib/epee/include/net/net_helper.h @@ -101,10 +101,10 @@ namespace net_utils inline blocked_mode_client() : m_io_service(), - m_ctx({boost::asio::ssl::context(boost::asio::ssl::context::tlsv12), {}}), + m_ctx(boost::asio::ssl::context::tlsv12), m_connector(direct_connect{}), - m_ssl_socket(new boost::asio::ssl::stream(m_io_service, m_ctx.context)), - m_ssl_support(epee::net_utils::ssl_support_t::e_ssl_support_autodetect), + m_ssl_socket(new boost::asio::ssl::stream(m_io_service, m_ctx)), + m_ssl_options(epee::net_utils::ssl_support_t::e_ssl_support_autodetect), m_initialized(true), m_connected(false), m_deadline(m_io_service), @@ -136,13 +136,13 @@ namespace net_utils catch(...) { /* ignore */ } } - inline void set_ssl(epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair &private_key_and_certificate_path = {}, const std::string &ca_path = {}, std::vector> allowed_fingerprints = {}, bool allow_any_cert = false) + inline void set_ssl(ssl_options_t ssl_options) { - if (ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_disabled) - m_ctx = {boost::asio::ssl::context(boost::asio::ssl::context::tlsv12), {}, {}}; + if (ssl_options) + m_ctx = ssl_options.create_context(); else - m_ctx = create_ssl_context(private_key_and_certificate_path, ca_path, std::move(allowed_fingerprints), allow_any_cert); - m_ssl_support = ssl_support; + m_ctx = boost::asio::ssl::context(boost::asio::ssl::context::tlsv12); + m_ssl_options = std::move(ssl_options); } inline @@ -174,7 +174,7 @@ namespace net_utils // SSL Options if (ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_enabled || ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect) { - if (!ssl_handshake(*m_ssl_socket, boost::asio::ssl::stream_base::client, m_ctx)) + if (!m_ssl_options.handshake(*m_ssl_socket, boost::asio::ssl::stream_base::client)) { if (ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect) { @@ -191,7 +191,7 @@ namespace net_utils return CONNECT_FAILURE; } } - m_ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_enabled; + m_ssl_options.support = ssl_support_t::e_ssl_support_enabled; } return CONNECT_SUCCESS; }else @@ -212,21 +212,21 @@ namespace net_utils // Set SSL options // disable sslv2 - m_ssl_socket.reset(new boost::asio::ssl::stream(m_io_service, m_ctx.context)); + m_ssl_socket.reset(new boost::asio::ssl::stream(m_io_service, m_ctx)); // Get a list of endpoints corresponding to the server name. - try_connect_result_t try_connect_result = try_connect(addr, port, timeout, m_ssl_support); + try_connect_result_t try_connect_result = try_connect(addr, port, timeout, m_ssl_options.support); if (try_connect_result == CONNECT_FAILURE) return false; - if (m_ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect) + if (m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect) { - m_ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_enabled; + m_ssl_options.support = epee::net_utils::ssl_support_t::e_ssl_support_enabled; if (try_connect_result == CONNECT_NO_SSL) { MERROR("SSL handshake failed on an autodetect connection, reconnecting without SSL"); - m_ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_disabled; - if (try_connect(addr, port, timeout, m_ssl_support) != CONNECT_SUCCESS) + m_ssl_options.support = epee::net_utils::ssl_support_t::e_ssl_support_disabled; + if (try_connect(addr, port, timeout, m_ssl_options.support) != CONNECT_SUCCESS) return false; } } @@ -258,7 +258,7 @@ namespace net_utils if(m_connected) { m_connected = false; - if(m_ssl_support != epee::net_utils::ssl_support_t::e_ssl_support_disabled) + if(m_ssl_options) shutdown_ssl(); m_ssl_socket->next_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_both); } @@ -392,7 +392,7 @@ namespace net_utils if (!m_connected || !m_ssl_socket->next_layer().is_open()) return false; if (ssl) - *ssl = m_ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_enabled; + *ssl = m_ssl_options.support == ssl_support_t::e_ssl_support_enabled; return true; } @@ -556,7 +556,7 @@ namespace net_utils { m_deadline.cancel(); boost::system::error_code ec; - if(m_ssl_support != epee::net_utils::ssl_support_t::e_ssl_support_disabled) + if(m_ssl_options.support != ssl_support_t::e_ssl_support_disabled) shutdown_ssl(); m_ssl_socket->next_layer().cancel(ec); if(ec) @@ -633,7 +633,7 @@ namespace net_utils bool write(const void* data, size_t sz, boost::system::error_code& ec) { bool success; - if(m_ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_enabled) + if(m_ssl_options.support == ssl_support_t::e_ssl_support_enabled) success = boost::asio::write(*m_ssl_socket, boost::asio::buffer(data, sz), ec); else success = boost::asio::write(m_ssl_socket->next_layer(), boost::asio::buffer(data, sz), ec); @@ -642,7 +642,7 @@ namespace net_utils void async_write(const void* data, size_t sz, boost::system::error_code& ec) { - if(m_ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_enabled) + if(m_ssl_options.support == ssl_support_t::e_ssl_support_enabled) boost::asio::async_write(*m_ssl_socket, boost::asio::buffer(data, sz), boost::lambda::var(ec) = boost::lambda::_1); else boost::asio::async_write(m_ssl_socket->next_layer(), boost::asio::buffer(data, sz), boost::lambda::var(ec) = boost::lambda::_1); @@ -650,7 +650,7 @@ namespace net_utils void async_read(char* buff, size_t sz, boost::asio::detail::transfer_at_least_t transfer_at_least, handler_obj& hndlr) { - if(m_ssl_support != epee::net_utils::ssl_support_t::e_ssl_support_enabled) + if(m_ssl_options.support != ssl_support_t::e_ssl_support_enabled) boost::asio::async_read(m_ssl_socket->next_layer(), boost::asio::buffer(buff, sz), transfer_at_least, hndlr); else boost::asio::async_read(*m_ssl_socket, boost::asio::buffer(buff, sz), transfer_at_least, hndlr); @@ -659,10 +659,10 @@ namespace net_utils protected: boost::asio::io_service m_io_service; - epee::net_utils::ssl_context_t m_ctx; + boost::asio::ssl::context m_ctx; std::shared_ptr> m_ssl_socket; std::function m_connector; - epee::net_utils::ssl_support_t m_ssl_support; + ssl_options_t m_ssl_options; bool m_initialized; bool m_connected; boost::asio::steady_timer m_deadline; diff --git a/contrib/epee/include/net/net_ssl.h b/contrib/epee/include/net/net_ssl.h index 1b90a948d..5107f4db6 100644 --- a/contrib/epee/include/net/net_ssl.h +++ b/contrib/epee/include/net/net_ssl.h @@ -46,23 +46,71 @@ namespace net_utils e_ssl_support_enabled, e_ssl_support_autodetect, }; - - struct ssl_context_t - { - boost::asio::ssl::context context; - std::string ca_path; - std::vector> allowed_fingerprints; - bool allow_any_cert; - }; + + enum class ssl_verification_t : uint8_t + { + none = 0, //!< Do not verify peer. + system_ca, //!< Verify peer via system ca only (do not inspect user certificates) + user_certificates //!< Verify peer via user certificate(s) only. + }; + + struct ssl_authentication_t + { + std::string private_key_path; //!< Private key used for authentication + std::string certificate_path; //!< Certificate used for authentication to peer. + + //! Load `private_key_path` and `certificate_path` into `ssl_context`. + void use_ssl_certificate(boost::asio::ssl::context &ssl_context) const; + }; + + /*! + \note `verification != disabled && support == disabled` is currently + "allowed" via public interface but obviously invalid configuation. + */ + class ssl_options_t + { + // force sorted behavior in private + std::vector> fingerprints_; + + public: + std::string ca_path; + ssl_authentication_t auth; + ssl_support_t support; + ssl_verification_t verification; + + //! Verification is set to system ca unless SSL is disabled. + ssl_options_t(ssl_support_t support) + : fingerprints_(), + ca_path(), + auth(), + support(support), + verification(support == ssl_support_t::e_ssl_support_disabled ? ssl_verification_t::none : ssl_verification_t::system_ca) + {} + + //! Provide user fingerprints and/or ca path. Enables SSL and user_certificate verification + ssl_options_t(std::vector> fingerprints, std::string ca_path); + + ssl_options_t(const ssl_options_t&) = default; + ssl_options_t(ssl_options_t&&) = default; + + ssl_options_t& operator=(const ssl_options_t&) = default; + ssl_options_t& operator=(ssl_options_t&&) = default; + + //! \return False iff ssl is disabled, otherwise true. + explicit operator bool() const noexcept { return support != ssl_support_t::e_ssl_support_disabled; } + + //! Search against internal fingerprints. Always false if `behavior() != user_certificate_check`. + bool has_fingerprint(boost::asio::ssl::verify_context &ctx) const; + + boost::asio::ssl::context create_context() const; + + bool handshake(boost::asio::ssl::stream &socket, boost::asio::ssl::stream_base::handshake_type type) const; + }; // https://security.stackexchange.com/questions/34780/checking-client-hello-for-https-classification constexpr size_t get_ssl_magic_size() { return 9; } bool is_ssl(const unsigned char *data, size_t len); - ssl_context_t create_ssl_context(const std::pair &private_key_and_certificate_path, const std::string &ca_path, std::vector> allowed_fingerprints, bool allow_any_cert); - void use_ssl_certificate(ssl_context_t &ssl_context, const std::pair &private_key_and_certificate_path); - bool is_certificate_allowed(boost::asio::ssl::verify_context &ctx, const ssl_context_t &ssl_context); - bool ssl_handshake(boost::asio::ssl::stream &socket, boost::asio::ssl::stream_base::handshake_type type, const epee::net_utils::ssl_context_t &ssl_context); - bool ssl_support_from_string(ssl_support_t &ssl, boost::string_ref s); + bool ssl_support_from_string(ssl_support_t &ssl, boost::string_ref s); } } -- cgit v1.2.3 From 0416764caec5b2d504c820e71d74a4934c3e2c3e Mon Sep 17 00:00:00 2001 From: Lee Clagett Date: Sun, 17 Mar 2019 22:06:36 -0400 Subject: Require server verification when SSL is enabled. If SSL is "enabled" via command line without specifying a fingerprint or certificate, the system CA list is checked for server verification and _now_ fails the handshake if that check fails. This change was made to remain consistent with standard SSL/TLS client behavior. This can still be overridden by using the allow any certificate flag. If the SSL behavior is autodetect, the system CA list is still checked but a warning is logged if this fails. The stream is not rejected because a re-connect will be attempted - its better to have an unverified encrypted stream than an unverified + unencrypted stream. --- contrib/epee/include/net/net_ssl.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'contrib/epee/include/net') diff --git a/contrib/epee/include/net/net_ssl.h b/contrib/epee/include/net/net_ssl.h index 5107f4db6..f36755013 100644 --- a/contrib/epee/include/net/net_ssl.h +++ b/contrib/epee/include/net/net_ssl.h @@ -104,6 +104,12 @@ namespace net_utils boost::asio::ssl::context create_context() const; + /*! \note If `this->support == autodetect && this->verification != none`, + then the handshake will not fail when peer verification fails. The + assumption is that a re-connect will be attempted, so a warning is + logged instead of failure. + \return True if the SSL handshake completes with peer verification + settings. */ bool handshake(boost::asio::ssl::stream &socket, boost::asio::ssl::stream_base::handshake_type type) const; }; -- cgit v1.2.3 From eca0fea45a1fe2eb359c6fff5f5701e0b2fcdc5a Mon Sep 17 00:00:00 2001 From: Lee Clagett Date: Tue, 19 Mar 2019 16:04:32 -0400 Subject: Perform RFC 2818 hostname verification in client SSL handshakes If the verification mode is `system_ca`, clients will now do hostname verification. Thus, only certificates from expected hostnames are allowed when SSL is enabled. This can be overridden by forcible setting the SSL mode to autodetect. Clients will also send the hostname even when `system_ca` is not being performed. This leaks possible metadata, but allows servers providing multiple hostnames to respond with the correct certificate. One example is cloudflare, which getmonero.org is currently using. --- contrib/epee/include/net/net_helper.h | 2 +- contrib/epee/include/net/net_ssl.h | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'contrib/epee/include/net') diff --git a/contrib/epee/include/net/net_helper.h b/contrib/epee/include/net/net_helper.h index a9bfd6baa..66a307c97 100644 --- a/contrib/epee/include/net/net_helper.h +++ b/contrib/epee/include/net/net_helper.h @@ -174,7 +174,7 @@ namespace net_utils // SSL Options if (ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_enabled || ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect) { - if (!m_ssl_options.handshake(*m_ssl_socket, boost::asio::ssl::stream_base::client)) + if (!m_ssl_options.handshake(*m_ssl_socket, boost::asio::ssl::stream_base::client, addr)) { if (ssl_support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect) { diff --git a/contrib/epee/include/net/net_ssl.h b/contrib/epee/include/net/net_ssl.h index f36755013..ba6e2ee6d 100644 --- a/contrib/epee/include/net/net_ssl.h +++ b/contrib/epee/include/net/net_ssl.h @@ -108,9 +108,21 @@ namespace net_utils then the handshake will not fail when peer verification fails. The assumption is that a re-connect will be attempted, so a warning is logged instead of failure. + + \note It is strongly encouraged that clients using `system_ca` + verification provide a non-empty `host` for rfc2818 verification. + + \param socket Used in SSL handshake and verification + \param type Client or server + \param host This parameter is only used when + `type == client && !host.empty()`. The value is sent to the server for + situations where multiple hostnames are being handled by a server. If + `verification == system_ca` the client also does a rfc2818 check to + ensure that the server certificate is to the provided hostname. + \return True if the SSL handshake completes with peer verification settings. */ - bool handshake(boost::asio::ssl::stream &socket, boost::asio::ssl::stream_base::handshake_type type) const; + bool handshake(boost::asio::ssl::stream &socket, boost::asio::ssl::stream_base::handshake_type type, const std::string& host = {}) const; }; // https://security.stackexchange.com/questions/34780/checking-client-hello-for-https-classification -- cgit v1.2.3 From d58f368289709e0869c9b7927778339670cb85a7 Mon Sep 17 00:00:00 2001 From: Lee Clagett Date: Thu, 4 Apr 2019 13:35:33 -0400 Subject: Require manual override for user chain certificates. An override for the wallet to daemon connection is provided, but not for other SSL contexts. The intent is to prevent users from supplying a system CA as the "user" whitelisted certificate, which is less secure since the key is controlled by a third party. --- contrib/epee/include/net/net_ssl.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'contrib/epee/include/net') diff --git a/contrib/epee/include/net/net_ssl.h b/contrib/epee/include/net/net_ssl.h index ba6e2ee6d..726dcb61a 100644 --- a/contrib/epee/include/net/net_ssl.h +++ b/contrib/epee/include/net/net_ssl.h @@ -51,7 +51,8 @@ namespace net_utils { none = 0, //!< Do not verify peer. system_ca, //!< Verify peer via system ca only (do not inspect user certificates) - user_certificates //!< Verify peer via user certificate(s) only. + user_certificates,//!< Verify peer via specific (non-chain) certificate(s) only. + user_ca //!< Verify peer via specific (possibly chain) certificate(s) only. }; struct ssl_authentication_t -- cgit v1.2.3 From 2e578b8214b8b47d7ddefceb1cbf2d8129e85a5a Mon Sep 17 00:00:00 2001 From: Lee Clagett Date: Sat, 6 Apr 2019 21:28:37 -0400 Subject: Enabling daemon-rpc SSL now requires non-system CA verification If `--daemon-ssl enabled` is set in the wallet, then a user certificate, fingerprint, or onion/i2p address must be provided. --- contrib/epee/include/net/net_ssl.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'contrib/epee/include/net') diff --git a/contrib/epee/include/net/net_ssl.h b/contrib/epee/include/net/net_ssl.h index 726dcb61a..957903ff8 100644 --- a/contrib/epee/include/net/net_ssl.h +++ b/contrib/epee/include/net/net_ssl.h @@ -100,6 +100,9 @@ namespace net_utils //! \return False iff ssl is disabled, otherwise true. explicit operator bool() const noexcept { return support != ssl_support_t::e_ssl_support_disabled; } + //! \retrurn True if `host` can be verified using `this` configuration WITHOUT system "root" CAs. + bool has_strong_verification(boost::string_ref host) const noexcept; + //! Search against internal fingerprints. Always false if `behavior() != user_certificate_check`. bool has_fingerprint(boost::asio::ssl::verify_context &ctx) const; -- cgit v1.2.3