diff options
Diffstat (limited to 'contrib/epee')
25 files changed, 199 insertions, 108 deletions
diff --git a/contrib/epee/CMakeLists.txt b/contrib/epee/CMakeLists.txt index 035b24b36..a2c636304 100644 --- a/contrib/epee/CMakeLists.txt +++ b/contrib/epee/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2018, The Monero Project +# Copyright (c) 2014-2019, The Monero Project # # All rights reserved. # diff --git a/contrib/epee/include/hex.h b/contrib/epee/include/hex.h index 901c666a9..6e720f128 100644 --- a/contrib/epee/include/hex.h +++ b/contrib/epee/include/hex.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // @@ -32,6 +32,7 @@ #include <cstdint> #include <iosfwd> #include <string> +#include <boost/utility/string_ref.hpp> #include "wipeable_string.h" #include "span.h" @@ -68,4 +69,10 @@ namespace epee //! Write `src` bytes as hex to `out`. `out` must be twice the length static void buffer_unchecked(char* out, const span<const std::uint8_t> src) noexcept; }; + + struct from_hex + { + //! \return An std::vector of unsigned integers from the `src` + static std::vector<uint8_t> vector(boost::string_ref src); + }; } diff --git a/contrib/epee/include/int-util.h b/contrib/epee/include/int-util.h index 3bcc085e2..0ed6505ff 100644 --- a/contrib/epee/include/int-util.h +++ b/contrib/epee/include/int-util.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/include/memwipe.h b/contrib/epee/include/memwipe.h index 0d8f491b7..d586608cb 100644 --- a/contrib/epee/include/memwipe.h +++ b/contrib/epee/include/memwipe.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h index 76773192e..ec08c0f4b 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<std::string, t_connection_type> 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<std::string, std::string> &private_key_and_certificate_path = std::make_pair(std::string(), std::string()), const std::list<std::string> &allowed_certificates = {}, 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<std::string, std::string> &private_key_and_certificate_path = std::make_pair(std::string(), std::string()), const std::list<std::string> &allowed_certificates = {}, 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<std::string, std::string> &private_key_and_certificate_path = std::make_pair(std::string(), std::string()), const std::list<std::string> &allowed_certificates = {}, const std::vector<std::vector<uint8_t>> &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<std::string, std::string> &private_key_and_certificate_path = std::make_pair(std::string(), std::string()), const std::list<std::string> &allowed_certificates = {}, const std::vector<std::vector<uint8_t>> &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()); diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index 39d6911e3..7adb44c88 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -58,6 +58,12 @@ #define DEFAULT_TIMEOUT_MS_REMOTE 300000 // 5 minutes #define TIMEOUT_EXTRA_MS_PER_BYTE 0.2 +#if BOOST_VERSION >= 107000 +#define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context()) +#else +#define GET_IO_SERVICE(s) ((s).get_io_service()) +#endif + PRAGMA_WARNING_PUSH namespace epee { @@ -99,7 +105,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) m_connection_type( connection_type ), m_throttle_speed_in("speed_in", "throttle_speed_in"), m_throttle_speed_out("speed_out", "throttle_speed_out"), - m_timer(socket_.get_io_service()), + m_timer(GET_IO_SERVICE(socket_)), m_local(false), m_ready_to_close(false) { @@ -243,7 +249,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) template<class t_protocol_handler> boost::asio::io_service& connection<t_protocol_handler>::get_io_service() { - return socket().get_io_service(); + return GET_IO_SERVICE(socket()); } //--------------------------------------------------------------------------------- template<class t_protocol_handler> @@ -487,7 +493,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) if(!m_is_multithreaded) { //single thread model, we can wait in blocked call - size_t cnt = socket().get_io_service().run_one(); + size_t cnt = GET_IO_SERVICE(socket()).run_one(); if(!cnt)//service is going to quit return false; }else @@ -497,7 +503,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) //if no handlers were called //TODO: Maybe we need to have have critical section + event + callback to upper protocol to //ask it inside(!) critical region if we still able to go in event wait... - size_t cnt = socket().get_io_service().poll_one(); + size_t cnt = GET_IO_SERVICE(socket()).poll_one(); if(!cnt) misc_utils::sleep_no_w(1); } @@ -900,7 +906,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) m_thread_index(0), m_connection_type( connection_type ), new_connection_(), - m_ssl_context({boost::asio::ssl::context(boost::asio::ssl::context::sslv23), {}}) + m_ssl_context({boost::asio::ssl::context(boost::asio::ssl::context::tlsv12), {}}) { create_server_type_map(); m_thread_name_prefix = "NET"; @@ -939,14 +945,14 @@ PRAGMA_WARNING_DISABLE_VS(4355) } //--------------------------------------------------------------------------------- template<class t_protocol_handler> - bool boosted_tcp_server<t_protocol_handler>::init_server(uint32_t port, const std::string address, epee::net_utils::ssl_support_t ssl_support, const std::pair<std::string, std::string> &private_key_and_certificate_path, const std::list<std::string> &allowed_certificates, bool allow_any_cert) + bool boosted_tcp_server<t_protocol_handler>::init_server(uint32_t port, const std::string address, epee::net_utils::ssl_support_t ssl_support, const std::pair<std::string, std::string> &private_key_and_certificate_path, const std::list<std::string> &allowed_certificates, const std::vector<std::vector<uint8_t>> &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, allow_any_cert); + m_ssl_context = create_ssl_context(private_key_and_certificate_path, allowed_certificates, 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<std::string>(port), boost::asio::ip::tcp::resolver::query::canonical_name); @@ -980,7 +986,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) PUSH_WARNINGS DISABLE_GCC_WARNING(maybe-uninitialized) template<class t_protocol_handler> - bool boosted_tcp_server<t_protocol_handler>::init_server(const std::string port, const std::string& address, epee::net_utils::ssl_support_t ssl_support, const std::pair<std::string, std::string> &private_key_and_certificate_path, const std::list<std::string> &allowed_certificates, bool allow_any_cert) + bool boosted_tcp_server<t_protocol_handler>::init_server(const std::string port, const std::string& address, epee::net_utils::ssl_support_t ssl_support, const std::pair<std::string, std::string> &private_key_and_certificate_path, const std::list<std::string> &allowed_certificates, const std::vector<std::vector<uint8_t>> &allowed_fingerprints, bool allow_any_cert) { uint32_t p = 0; @@ -988,7 +994,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, allow_any_cert); + return this->init_server(p, address, ssl_support, private_key_and_certificate_path, allowed_certificates, allowed_fingerprints, allow_any_cert); } POP_WARNINGS //--------------------------------------------------------------------------------- @@ -1207,7 +1213,7 @@ POP_WARNINGS template<class t_protocol_handler> bool boosted_tcp_server<t_protocol_handler>::add_connection(t_connection_context& out, boost::asio::ip::tcp::socket&& sock, network_address real_remote, epee::net_utils::ssl_support_t ssl_support) { - if(std::addressof(get_io_service()) == std::addressof(sock.get_io_service())) + if(std::addressof(get_io_service()) == std::addressof(GET_IO_SERVICE(sock))) { connection_ptr conn(new connection<t_protocol_handler>(std::move(sock), m_state, m_connection_type, ssl_support, m_ssl_context)); if(conn->start(false, 1 < m_threads_count, std::move(real_remote))) diff --git a/contrib/epee/include/net/connection_basic.hpp b/contrib/epee/include/net/connection_basic.hpp index 328f9afbf..feedc6895 100644 --- a/contrib/epee/include/net/connection_basic.hpp +++ b/contrib/epee/include/net/connection_basic.hpp @@ -8,7 +8,7 @@ // ! (how ever if in some wonderful juristdictions that is not the case, then why not make another sub-class withat that members and licence it as epee part) // ! Working on above premise, IF this is valid in your juristdictions, then consider this code as released as: -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/include/net/http_auth.h b/contrib/epee/include/net/http_auth.h index 4324c41fd..00b9750b7 100644 --- a/contrib/epee/include/net/http_auth.h +++ b/contrib/epee/include/net/http_auth.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h index 34b3ac06c..58a8e6888 100644 --- a/contrib/epee/include/net/http_client.h +++ b/contrib/epee/include/net/http_client.h @@ -278,6 +278,7 @@ namespace net_utils epee::net_utils::ssl_support_t m_ssl_support; std::pair<std::string, std::string> m_ssl_private_key_and_certificate_path; std::list<std::string> m_ssl_allowed_certificates; + std::vector<std::vector<uint8_t>> m_ssl_allowed_fingerprints; bool m_ssl_allow_any_cert; public: @@ -302,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<login> user, epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair<std::string, std::string> &private_key_and_certificate_path = {}, const std::list<std::string> &allowed_ssl_certificates = {}, bool allow_any_cert = false) + bool set_server(const std::string& address, boost::optional<login> user, epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair<std::string, std::string> &private_key_and_certificate_path = {}, const std::list<std::string> &allowed_ssl_certificates = {}, const std::vector<std::vector<uint8_t>> &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, allow_any_cert); + 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); return true; } - void set_server(std::string host, std::string port, boost::optional<login> user, epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair<std::string, std::string> &private_key_and_certificate_path = {}, const std::list<std::string> &allowed_ssl_certificates = {}, bool allow_any_cert = false) + void set_server(std::string host, std::string port, boost::optional<login> user, epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair<std::string, std::string> &private_key_and_certificate_path = {}, const std::list<std::string> &allowed_ssl_certificates = {}, const std::vector<std::vector<uint8_t>> &allowed_ssl_fingerprints = {}, bool allow_any_cert = false) { CRITICAL_REGION_LOCAL(m_lock); disconnect(); @@ -321,8 +322,9 @@ namespace net_utils 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_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_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); } bool connect(std::chrono::milliseconds timeout) diff --git a/contrib/epee/include/net/http_server_impl_base.h b/contrib/epee/include/net/http_server_impl_base.h index 236067580..0922f21f2 100644 --- a/contrib/epee/include/net/http_server_impl_base.h +++ b/contrib/epee/include/net/http_server_impl_base.h @@ -61,7 +61,9 @@ namespace epee boost::optional<net_utils::http::login> user = boost::none, epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect, const std::pair<std::string, std::string> &private_key_and_certificate_path = {}, - const std::list<std::string> &allowed_certificates = std::list<std::string>(), bool allow_any_cert = false) + std::list<std::string> allowed_certificates = {}, + std::vector<std::vector<uint8_t>> allowed_fingerprints = {}, + bool allow_any_cert = false) { //set self as callback handler @@ -78,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, allowed_certificates, allow_any_cert); + 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); 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 5d9bb61cf..742cf916e 100644 --- a/contrib/epee/include/net/net_helper.h +++ b/contrib/epee/include/net/net_helper.h @@ -93,7 +93,7 @@ namespace net_utils m_deadline(m_io_service), m_shutdowned(0), m_ssl_support(epee::net_utils::ssl_support_t::e_ssl_support_autodetect), - m_ctx({boost::asio::ssl::context(boost::asio::ssl::context::sslv23), {}}), + m_ctx({boost::asio::ssl::context(boost::asio::ssl::context::tlsv12), {}}), m_ssl_socket(new boost::asio::ssl::stream<boost::asio::ip::tcp::socket>(m_io_service,m_ctx.context)) { @@ -118,12 +118,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<std::string, std::string> &private_key_and_certificate_path = {}, const std::list<std::string> &allowed_certificates = std::list<std::string>(), 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<std::string, std::string> &private_key_and_certificate_path = {}, std::list<std::string> allowed_certificates = {}, std::vector<std::vector<uint8_t>> 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::sslv23), {}}; + m_ctx = {boost::asio::ssl::context(boost::asio::ssl::context::tlsv12), {}, {}}; else - m_ctx = create_ssl_context(private_key_and_certificate_path, allowed_certificates, allow_any_cert); + m_ctx = create_ssl_context(private_key_and_certificate_path, std::move(allowed_certificates), std::move(allowed_fingerprints), allow_any_cert); m_ssl_support = ssl_support; } diff --git a/contrib/epee/include/net/net_ssl.h b/contrib/epee/include/net/net_ssl.h index 9ae1883af..f7b102164 100644 --- a/contrib/epee/include/net/net_ssl.h +++ b/contrib/epee/include/net/net_ssl.h @@ -50,16 +50,16 @@ namespace net_utils { boost::asio::ssl::context context; std::list<std::string> allowed_certificates; + std::vector<std::vector<uint8_t>> allowed_fingerprints; bool allow_any_cert; }; // 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<std::string, std::string> &private_key_and_certificate_path, std::list<std::string> allowed_certificates, bool allow_any_cert); + ssl_context_t create_ssl_context(const std::pair<std::string, std::string> &private_key_and_certificate_path, std::list<std::string> allowed_certificates, std::vector<std::vector<uint8_t>> allowed_fingerprints, bool allow_any_cert); void use_ssl_certificate(ssl_context_t &ssl_context, const std::pair<std::string, std::string> &private_key_and_certificate_path); - bool create_ssl_certificate(std::string &pkey_buffer, std::string &cert_buffer); - bool is_certificate_allowed(boost::asio::ssl::verify_context &ctx, const std::list<std::string> &allowed_certificates); + bool is_certificate_allowed(boost::asio::ssl::verify_context &ctx, const ssl_context_t &ssl_context); bool ssl_handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &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); } diff --git a/contrib/epee/include/net/network_throttle-detail.hpp b/contrib/epee/include/net/network_throttle-detail.hpp index 9d12291f4..d7f2cc37a 100644 --- a/contrib/epee/include/net/network_throttle-detail.hpp +++ b/contrib/epee/include/net/network_throttle-detail.hpp @@ -2,7 +2,7 @@ /// @author rfree (current maintainer in monero.cc project) /// @brief implementaion for throttling of connection (count and rate-limit speed etc) -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/include/net/network_throttle.hpp b/contrib/epee/include/net/network_throttle.hpp index 7df79a908..5092241a4 100644 --- a/contrib/epee/include/net/network_throttle.hpp +++ b/contrib/epee/include/net/network_throttle.hpp @@ -2,7 +2,7 @@ /// @author rfree (current maintainer in monero.cc project) /// @brief interface for throttling of connection (count and rate-limit speed etc) -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/include/span.h b/contrib/epee/include/span.h index cfb5b1a17..19720ea8b 100644 --- a/contrib/epee/include/span.h +++ b/contrib/epee/include/span.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/include/wipeable_string.h b/contrib/epee/include/wipeable_string.h index 31854fe2e..f0e526b92 100644 --- a/contrib/epee/include/wipeable_string.h +++ b/contrib/epee/include/wipeable_string.h @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt index e913211ea..0787a9d08 100644 --- a/contrib/epee/src/CMakeLists.txt +++ b/contrib/epee/src/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2018, The Monero Project +# Copyright (c) 2014-2019, The Monero Project # # All rights reserved. # diff --git a/contrib/epee/src/connection_basic.cpp b/contrib/epee/src/connection_basic.cpp index 377fb3452..6354082aa 100644 --- a/contrib/epee/src/connection_basic.cpp +++ b/contrib/epee/src/connection_basic.cpp @@ -2,7 +2,7 @@ /// @author rfree (current maintainer in monero.cc project) /// @brief base for connection, contains e.g. the ratelimit hooks -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // @@ -47,6 +47,12 @@ // TODO: #include "net/network_throttle-detail.hpp" +#if BOOST_VERSION >= 107000 +#define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context()) +#else +#define GET_IO_SERVICE(s) ((s).get_io_service()) +#endif + #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "net.conn" @@ -117,8 +123,8 @@ connection_basic::connection_basic(boost::asio::ip::tcp::socket&& sock, boost::s : m_stats(std::move(stats)), mI( new connection_basic_pimpl("peer") ), - strand_(sock.get_io_service()), - socket_(sock.get_io_service(), ssl_context.context), + strand_(GET_IO_SERVICE(sock)), + socket_(GET_IO_SERVICE(sock), ssl_context.context), m_want_close_connection(false), m_was_shutdown(false), m_ssl_support(ssl_support), diff --git a/contrib/epee/src/hex.cpp b/contrib/epee/src/hex.cpp index 5c8acc8be..558983f7e 100644 --- a/contrib/epee/src/hex.cpp +++ b/contrib/epee/src/hex.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // @@ -83,4 +83,67 @@ namespace epee { return write_hex(out, src); } + + std::vector<uint8_t> from_hex::vector(boost::string_ref src) + { + // should we include a specific character + auto include = [](char input) { + // we ignore spaces and colons + return !std::isspace(input) && input != ':'; + }; + + // the number of relevant characters to decode + auto count = std::count_if(src.begin(), src.end(), include); + + // this must be a multiple of two, otherwise we have a truncated input + if (count % 2) { + throw std::length_error{ "Invalid hexadecimal input length" }; + } + + std::vector<uint8_t> result; + result.reserve(count / 2); + + // the data to work with (std::string is always null-terminated) + auto data = src.data(); + + // convert a single hex character to an unsigned integer + auto char_to_int = [](const char *input) { + switch (std::tolower(*input)) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'a': return 10; + case 'b': return 11; + case 'c': return 12; + case 'd': return 13; + case 'e': return 14; + case 'f': return 15; + default: throw std::range_error{ "Invalid hexadecimal input" }; + } + }; + + // keep going until we reach the end + while (data[0] != '\0') { + // skip unwanted characters + if (!include(data[0])) { + ++data; + continue; + } + + // convert two matching characters to int + auto high = char_to_int(data++); + auto low = char_to_int(data++); + + result.push_back(high << 4 | low); + } + + return result; + } } diff --git a/contrib/epee/src/http_auth.cpp b/contrib/epee/src/http_auth.cpp index dc968d971..289069daa 100644 --- a/contrib/epee/src/http_auth.cpp +++ b/contrib/epee/src/http_auth.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/src/memwipe.c b/contrib/epee/src/memwipe.c index c2a26c392..ad1ef510d 100644 --- a/contrib/epee/src/memwipe.c +++ b/contrib/epee/src/memwipe.c @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/src/net_ssl.cpp b/contrib/epee/src/net_ssl.cpp index 941799078..eb0b0ad65 100644 --- a/contrib/epee/src/net_ssl.cpp +++ b/contrib/epee/src/net_ssl.cpp @@ -74,22 +74,23 @@ bool create_ssl_certificate(EVP_PKEY *&pkey, X509 *&cert) { MGINFO("Generating SSL certificate"); pkey = EVP_PKEY_new(); - openssl_pkey pkey_deleter{pkey}; if (!pkey) { MERROR("Failed to create new private key"); return false; } + + openssl_pkey pkey_deleter{pkey}; RSA *rsa = RSA_generate_key(4096, RSA_F4, NULL, NULL); if (!rsa) { MERROR("Error generating RSA private key"); return false; } - if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) + if (EVP_PKEY_assign_RSA(pkey, rsa) <= 0) // The RSA will be automatically freed when the EVP_PKEY structure is freed. { - RSA_free(rsa); MERROR("Error assigning RSA private key"); + RSA_free(rsa); return false; } @@ -117,50 +118,23 @@ bool create_ssl_certificate(EVP_PKEY *&pkey, X509 *&cert) X509_free(cert); return false; } + (void)pkey_deleter.release(); return true; } -bool create_ssl_certificate(std::string &pkey_buffer, std::string &cert_buffer) +ssl_context_t create_ssl_context(const std::pair<std::string, std::string> &private_key_and_certificate_path, std::list<std::string> allowed_certificates, std::vector<std::vector<uint8_t>> allowed_fingerprints, bool allow_any_cert) { - EVP_PKEY *pkey; - X509 *cert; - if (!create_ssl_certificate(pkey, cert)) - return false; - BIO *bio_pkey = BIO_new(BIO_s_mem()), *bio_cert = BIO_new(BIO_s_mem()); - openssl_bio bio_pkey_deleter{bio_pkey}; - bool success = PEM_write_bio_PrivateKey(bio_pkey, pkey, NULL, NULL, 0, NULL, NULL) && PEM_write_bio_X509(bio_cert, cert); - X509_free(cert); - if (!success) - { - MERROR("Failed to write cert and/or pkey: " << ERR_get_error()); - return false; - } - BUF_MEM *buf = NULL; - BIO_get_mem_ptr(bio_pkey, &buf); - if (!buf || !buf->data || !buf->length) - { - MERROR("Failed to write pkey: " << ERR_get_error()); - return false; - } - pkey_buffer = std::string(buf->data, buf->length); - buf = NULL; - BIO_get_mem_ptr(bio_cert, &buf); - if (!buf || !buf->data || !buf->length) - { - MERROR("Failed to write cert: " << ERR_get_error()); - return false; - } - cert_buffer = std::string(buf->data, buf->length); - return success; -} + ssl_context_t ssl_context{boost::asio::ssl::context(boost::asio::ssl::context::tlsv12), std::move(allowed_certificates), std::move(allowed_fingerprints)}; -ssl_context_t create_ssl_context(const std::pair<std::string, std::string> &private_key_and_certificate_path, std::list<std::string> allowed_certificates, bool allow_any_cert) -{ - ssl_context_t ssl_context({boost::asio::ssl::context(boost::asio::ssl::context::sslv23), std::move(allowed_certificates)}); + // only allow tls v1.2 and up + ssl_context.context.set_options(boost::asio::ssl::context::default_workarounds); + ssl_context.context.set_options(boost::asio::ssl::context::no_sslv2); + ssl_context.context.set_options(boost::asio::ssl::context::no_sslv3); + ssl_context.context.set_options(boost::asio::ssl::context::no_tlsv1); + ssl_context.context.set_options(boost::asio::ssl::context::no_tlsv1_1); - // disable sslv2 - ssl_context.context.set_options(boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2); - ssl_context.context.set_default_verify_paths(); + // only allow a select handful of tls v1.3 and v1.2 ciphers to be used + SSL_CTX_set_cipher_list(ssl_context.context.native_handle(), "ECDHE-ECDSA-CHACHA20-POLY1305-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-CHACHA20-POLY1305"); // set options on the SSL context for added security SSL_CTX *ctx = ssl_context.context.native_handle(); @@ -179,15 +153,18 @@ ssl_context_t create_ssl_context(const std::pair<std::string, std::string> &priv #ifdef SSL_OP_NO_COMPRESSION SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION); #endif - SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1); // https://github.com/ssllabs/research/wiki/SSL-and-TLS-Deployment-Best-Practices + ssl_context.context.set_default_verify_paths(); CHECK_AND_ASSERT_THROW_MES(private_key_and_certificate_path.first.empty() == private_key_and_certificate_path.second.empty(), "private key and certificate must be either both given or both empty"); if (private_key_and_certificate_path.second.empty()) { - std::string pkey, cert; + EVP_PKEY *pkey; + X509 *cert; CHECK_AND_ASSERT_THROW_MES(create_ssl_certificate(pkey, cert), "Failed to create certificate"); - ssl_context.context.use_private_key(boost::asio::buffer(pkey), boost::asio::ssl::context::pem); - ssl_context.context.use_certificate(boost::asio::buffer(cert), boost::asio::ssl::context::pem); + CHECK_AND_ASSERT_THROW_MES(SSL_CTX_use_certificate(ctx, cert), "Failed to use generated certificate"); + // don't free the cert, the CTX owns it now + CHECK_AND_ASSERT_THROW_MES(SSL_CTX_use_PrivateKey(ctx, pkey), "Failed to use generated private key"); + EVP_PKEY_free(pkey); } else { @@ -225,7 +202,7 @@ bool is_ssl(const unsigned char *data, size_t len) return false; } -bool is_certificate_allowed(boost::asio::ssl::verify_context &ctx, const std::list<std::string> &allowed_certificates) +bool is_certificate_allowed(boost::asio::ssl::verify_context &ctx, const ssl_context_t &ssl_context) { X509_STORE_CTX *sctx = ctx.native_handle(); if (!sctx) @@ -240,23 +217,51 @@ bool is_certificate_allowed(boost::asio::ssl::verify_context &ctx, const std::li return false; } - BIO *bio_cert = BIO_new(BIO_s_mem()); - openssl_bio bio_cert_deleter{bio_cert}; - bool success = PEM_write_bio_X509(bio_cert, cert); - if (!success) - { - MERROR("Failed to print certificate"); - return false; + // can we check the certificate against a list of fingerprints? + if (!ssl_context.allowed_fingerprints.empty()) { + // buffer for the certificate digest and the size of the result + std::vector<uint8_t> digest(EVP_MAX_MD_SIZE); + unsigned int size{ 0 }; + + // create the digest from the certificate + if (!X509_digest(cert, EVP_sha1(), digest.data(), &size)) { + MERROR("Failed to create certificate fingerprint"); + return false; + } + + // strip unnecessary bytes from the digest + digest.resize(size); + + // is the certificate fingerprint inside the list of allowed fingerprints? + if (std::find(ssl_context.allowed_fingerprints.begin(), ssl_context.allowed_fingerprints.end(), digest) != ssl_context.allowed_fingerprints.end()) + return true; } - BUF_MEM *buf = NULL; - BIO_get_mem_ptr(bio_cert, &buf); - if (!buf || !buf->data || !buf->length) - { - MERROR("Failed to write certificate: " << ERR_get_error()); - return false; + + if (!ssl_context.allowed_certificates.empty()) { + BIO *bio_cert = BIO_new(BIO_s_mem()); + bool success = PEM_write_bio_X509(bio_cert, cert); + if (!success) + { + BIO_free(bio_cert); + MERROR("Failed to print certificate"); + return false; + } + BUF_MEM *buf = NULL; + BIO_get_mem_ptr(bio_cert, &buf); + if (!buf || !buf->data || !buf->length) + { + BIO_free(bio_cert); + MERROR("Failed to write certificate: " << ERR_get_error()); + return false; + } + std::string certificate(std::string(buf->data, buf->length)); + BIO_free(bio_cert); + if (std::find(ssl_context.allowed_certificates.begin(), ssl_context.allowed_certificates.end(), certificate) != ssl_context.allowed_certificates.end()) + return true; } - std::string certificate(std::string(buf->data, buf->length)); - return std::find(allowed_certificates.begin(), allowed_certificates.end(), certificate) != allowed_certificates.end(); + + // if either checklist is non-empty we must have failed it + return ssl_context.allowed_fingerprints.empty() && ssl_context.allowed_certificates.empty(); } bool ssl_handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket, boost::asio::ssl::stream_base::handshake_type type, const epee::net_utils::ssl_context_t &ssl_context) @@ -276,7 +281,7 @@ bool ssl_handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socke return false; } } - if (!ssl_context.allow_any_cert && !ssl_context.allowed_certificates.empty() && !is_certificate_allowed(ctx, ssl_context.allowed_certificates)) + if (!ssl_context.allow_any_cert && !is_certificate_allowed(ctx, ssl_context)) { MERROR("Certificate is not in the allowed list, connection droppped"); return false; @@ -289,7 +294,7 @@ bool ssl_handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socke socket.handshake(type, ec); if (ec) { - MERROR("handshake failed, connection dropped"); + MERROR("handshake failed, connection dropped: " << ec.message()); return false; } if (!ssl_context.allow_any_cert && !verified) diff --git a/contrib/epee/src/network_throttle-detail.cpp b/contrib/epee/src/network_throttle-detail.cpp index 0b42402bd..f89e7aec0 100644 --- a/contrib/epee/src/network_throttle-detail.cpp +++ b/contrib/epee/src/network_throttle-detail.cpp @@ -2,7 +2,7 @@ /// @author rfree (current maintainer in monero.cc project) /// @brief implementaion for throttling of connection (count and rate-limit speed etc) -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/src/network_throttle.cpp b/contrib/epee/src/network_throttle.cpp index 167738855..f4f0b2c46 100644 --- a/contrib/epee/src/network_throttle.cpp +++ b/contrib/epee/src/network_throttle.cpp @@ -26,7 +26,7 @@ Throttling work by: */ -// Copyright (c) 2014-2018, The Monero Project +// Copyright (c) 2014-2019, The Monero Project // // All rights reserved. // diff --git a/contrib/epee/src/wipeable_string.cpp b/contrib/epee/src/wipeable_string.cpp index 69f92e106..3a6ee5dac 100644 --- a/contrib/epee/src/wipeable_string.cpp +++ b/contrib/epee/src/wipeable_string.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2018, The Monero Project +// Copyright (c) 2017-2019, The Monero Project // // All rights reserved. // |