diff options
Diffstat (limited to 'contrib/epee')
-rw-r--r-- | contrib/epee/include/math_helper.h | 2 | ||||
-rw-r--r-- | contrib/epee/include/net/abstract_tcp_server2.h | 2 | ||||
-rw-r--r-- | contrib/epee/include/net/abstract_tcp_server2.inl | 9 | ||||
-rw-r--r-- | contrib/epee/include/net/levin_protocol_handler_async.h | 2 | ||||
-rw-r--r-- | contrib/epee/include/net/net_fwd.h | 38 | ||||
-rw-r--r-- | contrib/epee/include/net/net_helper.h | 11 | ||||
-rw-r--r-- | contrib/epee/include/net/net_ssl.h | 5 | ||||
-rw-r--r-- | contrib/epee/include/net/net_utils_base.h | 54 | ||||
-rw-r--r-- | contrib/epee/include/rolling_median.h | 236 | ||||
-rw-r--r-- | contrib/epee/include/serialization/keyvalue_serialization.h | 3 | ||||
-rw-r--r-- | contrib/epee/include/serialization/keyvalue_serialization_overloads.h | 3 | ||||
-rw-r--r-- | contrib/epee/include/storages/portable_storage_from_bin.h | 1 | ||||
-rw-r--r-- | contrib/epee/src/buffer.cpp | 3 | ||||
-rw-r--r-- | contrib/epee/src/mlog.cpp | 2 | ||||
-rw-r--r-- | contrib/epee/src/net_ssl.cpp | 133 | ||||
-rw-r--r-- | contrib/epee/src/net_utils_base.cpp | 18 | ||||
-rw-r--r-- | contrib/epee/src/wipeable_string.cpp | 17 |
17 files changed, 512 insertions, 27 deletions
diff --git a/contrib/epee/include/math_helper.h b/contrib/epee/include/math_helper.h index 35b649972..ddc1f7f4b 100644 --- a/contrib/epee/include/math_helper.h +++ b/contrib/epee/include/math_helper.h @@ -32,7 +32,7 @@ #include <list> #include <numeric> -#include <boost/timer.hpp> +#include <boost/timer/timer.hpp> #include <boost/uuid/uuid.hpp> #include <boost/uuid/random_generator.hpp> diff --git a/contrib/epee/include/net/abstract_tcp_server2.h b/contrib/epee/include/net/abstract_tcp_server2.h index 374a28a2e..c1aa0fe5f 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.h +++ b/contrib/epee/include/net/abstract_tcp_server2.h @@ -70,7 +70,7 @@ namespace net_utils struct i_connection_filter { - virtual bool is_remote_host_allowed(const epee::net_utils::network_address &address)=0; + virtual bool is_remote_host_allowed(const epee::net_utils::network_address &address, time_t *t = NULL)=0; protected: virtual ~i_connection_filter(){} }; diff --git a/contrib/epee/include/net/abstract_tcp_server2.inl b/contrib/epee/include/net/abstract_tcp_server2.inl index 821594355..fa5858b9f 100644 --- a/contrib/epee/include/net/abstract_tcp_server2.inl +++ b/contrib/epee/include/net/abstract_tcp_server2.inl @@ -54,6 +54,9 @@ #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "net" +#define AGGRESSIVE_TIMEOUT_THRESHOLD 120 // sockets +#define NEW_CONNECTION_TIMEOUT_LOCAL 1200000 // 2 minutes +#define NEW_CONNECTION_TIMEOUT_REMOTE 10000 // 10 seconds #define DEFAULT_TIMEOUT_MS_LOCAL 1800000 // 30 minutes #define DEFAULT_TIMEOUT_MS_REMOTE 300000 // 5 minutes #define TIMEOUT_EXTRA_MS_PER_BYTE 0.2 @@ -189,7 +192,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) m_protocol_handler.after_init_connection(); - reset_timer(get_default_timeout(), false); + reset_timer(boost::posix_time::milliseconds(m_local ? NEW_CONNECTION_TIMEOUT_LOCAL : NEW_CONNECTION_TIMEOUT_REMOTE), false); // first read on the raw socket to detect SSL for the server buffer_ssl_init_fill = 0; @@ -691,7 +694,7 @@ PRAGMA_WARNING_DISABLE_VS(4355) { unsigned count; try { count = host_count(m_host); } catch (...) { count = 0; } - const unsigned shift = std::min(std::max(count, 1u) - 1, 8u); + const unsigned shift = get_state().sock_count > AGGRESSIVE_TIMEOUT_THRESHOLD ? std::min(std::max(count, 1u) - 1, 8u) : 0; boost::posix_time::milliseconds timeout(0); if (m_local) timeout = boost::posix_time::milliseconds(DEFAULT_TIMEOUT_MS_LOCAL >> shift); @@ -730,8 +733,6 @@ PRAGMA_WARNING_DISABLE_VS(4355) template<class t_protocol_handler> void connection<t_protocol_handler>::reset_timer(boost::posix_time::milliseconds ms, bool add) { - if (m_connection_type != e_connection_type_RPC) - return; MTRACE("Setting " << ms << " expiry"); auto self = safe_shared_from_this(); if(!self) diff --git a/contrib/epee/include/net/levin_protocol_handler_async.h b/contrib/epee/include/net/levin_protocol_handler_async.h index a1ea3e680..116b3ace1 100644 --- a/contrib/epee/include/net/levin_protocol_handler_async.h +++ b/contrib/epee/include/net/levin_protocol_handler_async.h @@ -266,7 +266,7 @@ public: m_pservice_endpoint(psnd_hndlr), m_config(config), m_connection_context(conn_context), - m_cache_in_buffer(256 * 1024), + m_cache_in_buffer(4 * 1024), m_state(stream_state_head) { m_close_called = 0; diff --git a/contrib/epee/include/net/net_fwd.h b/contrib/epee/include/net/net_fwd.h new file mode 100644 index 000000000..ba4fe6259 --- /dev/null +++ b/contrib/epee/include/net/net_fwd.h @@ -0,0 +1,38 @@ +// Copyright (c) 2019, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#pragma once + +namespace epee +{ + namespace net_utils + { + struct ssl_authentication_t; + class ssl_options_t; + } +} diff --git a/contrib/epee/include/net/net_helper.h b/contrib/epee/include/net/net_helper.h index 89cef8134..e315555fc 100644 --- a/contrib/epee/include/net/net_helper.h +++ b/contrib/epee/include/net/net_helper.h @@ -193,7 +193,6 @@ namespace net_utils return CONNECT_FAILURE; } } - m_ssl_options.support = ssl_support_t::e_ssl_support_enabled; } return CONNECT_SUCCESS; }else @@ -223,7 +222,6 @@ namespace net_utils return false; if (m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect) { - 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"); @@ -396,7 +394,7 @@ namespace net_utils if (!m_connected || !m_ssl_socket->next_layer().is_open()) return false; if (ssl) - *ssl = m_ssl_options.support == ssl_support_t::e_ssl_support_enabled; + *ssl = m_ssl_options.support != ssl_support_t::e_ssl_support_disabled; return true; } @@ -448,6 +446,7 @@ namespace net_utils { MTRACE("Connection err_code eof."); //connection closed there, empty + buff.clear(); return true; } @@ -650,7 +649,7 @@ namespace net_utils bool write(const void* data, size_t sz, boost::system::error_code& ec) { bool success; - if(m_ssl_options.support == ssl_support_t::e_ssl_support_enabled) + if(m_ssl_options.support != ssl_support_t::e_ssl_support_disabled) 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); @@ -659,7 +658,7 @@ namespace net_utils void async_write(const void* data, size_t sz, boost::system::error_code& ec) { - if(m_ssl_options.support == ssl_support_t::e_ssl_support_enabled) + if(m_ssl_options.support != ssl_support_t::e_ssl_support_disabled) 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); @@ -667,7 +666,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_options.support != ssl_support_t::e_ssl_support_enabled) + if(m_ssl_options.support == ssl_support_t::e_ssl_support_disabled) 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); diff --git a/contrib/epee/include/net/net_ssl.h b/contrib/epee/include/net/net_ssl.h index 957903ff8..3a97dfdaf 100644 --- a/contrib/epee/include/net/net_ssl.h +++ b/contrib/epee/include/net/net_ssl.h @@ -37,6 +37,8 @@ #include <boost/asio/ssl.hpp> #include <boost/system/error_code.hpp> +#define SSL_FINGERPRINT_SIZE 32 + namespace epee { namespace net_utils @@ -133,6 +135,9 @@ namespace net_utils constexpr size_t get_ssl_magic_size() { return 9; } bool is_ssl(const unsigned char *data, size_t len); bool ssl_support_from_string(ssl_support_t &ssl, boost::string_ref s); + + bool create_ec_ssl_certificate(EVP_PKEY *&pkey, X509 *&cert); + bool create_rsa_ssl_certificate(EVP_PKEY *&pkey, X509 *&cert); } } diff --git a/contrib/epee/include/net/net_utils_base.h b/contrib/epee/include/net/net_utils_base.h index 50536f63b..62618537f 100644 --- a/contrib/epee/include/net/net_utils_base.h +++ b/contrib/epee/include/net/net_utils_base.h @@ -41,7 +41,7 @@ #define MONERO_DEFAULT_LOG_CATEGORY "net" #ifndef MAKE_IP -#define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(a4<<24)) +#define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(((uint32_t)a4)<<24)) #endif #if BOOST_VERSION >= 107000 @@ -107,6 +107,53 @@ namespace net_utils inline bool operator>=(const ipv4_network_address& lhs, const ipv4_network_address& rhs) noexcept { return !lhs.less(rhs); } + class ipv4_network_subnet + { + uint32_t m_ip; + uint8_t m_mask; + + public: + constexpr ipv4_network_subnet() noexcept + : ipv4_network_subnet(0, 0) + {} + + constexpr ipv4_network_subnet(uint32_t ip, uint8_t mask) noexcept + : m_ip(ip), m_mask(mask) {} + + bool equal(const ipv4_network_subnet& other) const noexcept; + bool less(const ipv4_network_subnet& other) const noexcept; + constexpr bool is_same_host(const ipv4_network_subnet& other) const noexcept + { return subnet() == other.subnet(); } + bool matches(const ipv4_network_address &address) const; + + constexpr uint32_t subnet() const noexcept { return m_ip & ~(0xffffffffull << m_mask); } + std::string str() const; + std::string host_str() const; + bool is_loopback() const; + bool is_local() const; + static constexpr address_type get_type_id() noexcept { return address_type::invalid; } + static constexpr zone get_zone() noexcept { return zone::public_; } + static constexpr bool is_blockable() noexcept { return true; } + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(m_ip) + KV_SERIALIZE(m_mask) + END_KV_SERIALIZE_MAP() + }; + + inline bool operator==(const ipv4_network_subnet& lhs, const ipv4_network_subnet& rhs) noexcept + { return lhs.equal(rhs); } + inline bool operator!=(const ipv4_network_subnet& lhs, const ipv4_network_subnet& rhs) noexcept + { return !lhs.equal(rhs); } + inline bool operator<(const ipv4_network_subnet& lhs, const ipv4_network_subnet& rhs) noexcept + { return lhs.less(rhs); } + inline bool operator<=(const ipv4_network_subnet& lhs, const ipv4_network_subnet& rhs) noexcept + { return !rhs.less(lhs); } + inline bool operator>(const ipv4_network_subnet& lhs, const ipv4_network_subnet& rhs) noexcept + { return rhs.less(lhs); } + inline bool operator>=(const ipv4_network_subnet& lhs, const ipv4_network_subnet& rhs) noexcept + { return !lhs.less(rhs); } + class network_address { struct interface @@ -294,6 +341,11 @@ namespace net_utils m_max_speed_up(0) {} + connection_context_base(const connection_context_base& a): connection_context_base() + { + set_details(a.m_connection_id, a.m_remote_address, a.m_is_income, a.m_ssl); + } + connection_context_base& operator=(const connection_context_base& a) { set_details(a.m_connection_id, a.m_remote_address, a.m_is_income, a.m_ssl); diff --git a/contrib/epee/include/rolling_median.h b/contrib/epee/include/rolling_median.h new file mode 100644 index 000000000..8b5a82a84 --- /dev/null +++ b/contrib/epee/include/rolling_median.h @@ -0,0 +1,236 @@ +// Copyright (c) 2019, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Adapted from source by AShelly: +// Copyright (c) 2011 ashelly.myopenid.com, licenced under the MIT licence +// https://stackoverflow.com/questions/5527437/rolling-median-in-c-turlach-implementation +// https://stackoverflow.com/questions/1309263/rolling-median-algorithm-in-c +// https://ideone.com/XPbl6 + +#pragma once + +#include <stdlib.h> +#include <stdint.h> + +namespace epee +{ +namespace misc_utils +{ + +template<typename Item> +struct rolling_median_t +{ +private: + Item* data; //circular queue of values + int* pos; //index into `heap` for each value + int* heap; //max/median/min heap holding indexes into `data`. + int N; //allocated size. + int idx; //position in circular queue + int minCt; //count of items in min heap + int maxCt; //count of items in max heap + int sz; //count of items in heap + +private: + + //returns true if heap[i] < heap[j] + bool mmless(int i, int j) const + { + return data[heap[i]] < data[heap[j]]; + } + + //swaps items i&j in heap, maintains indexes + bool mmexchange(int i, int j) + { + const int t = heap[i]; + heap[i] = heap[j]; + heap[j] = t; + pos[heap[i]] = i; + pos[heap[j]] = j; + return 1; + } + + //swaps items i&j if i<j; returns true if swapped + bool mmCmpExch(int i, int j) + { + return mmless(i, j) && mmexchange(i, j); + } + + //maintains minheap property for all items below i. + void minSortDown(int i) + { + for (i *= 2; i <= minCt; i *= 2) + { + if (i < minCt && mmless(i + 1, i)) + ++i; + if (!mmCmpExch(i, i / 2)) + break; + } + } + + //maintains maxheap property for all items below i. (negative indexes) + void maxSortDown(int i) + { + for (i *= 2; i >= -maxCt; i *= 2) + { + if (i > -maxCt && mmless(i, i - 1)) + --i; + if (!mmCmpExch(i / 2, i)) + break; + } + } + + //maintains minheap property for all items above i, including median + //returns true if median changed + bool minSortUp(int i) + { + while (i > 0 && mmCmpExch(i, i / 2)) + i /= 2; + return i == 0; + } + + //maintains maxheap property for all items above i, including median + //returns true if median changed + bool maxSortUp(int i) + { + while (i < 0 && mmCmpExch(i / 2, i)) + i /= 2; + return i == 0; + } + +protected: + rolling_median_t &operator=(const rolling_median_t&) = delete; + rolling_median_t(const rolling_median_t&) = delete; + +public: + //creates new rolling_median_t: to calculate `nItems` running median. + rolling_median_t(size_t N): N(N) + { + int size = N * (sizeof(Item) + sizeof(int) * 2); + data = (Item*)malloc(size); + pos = (int*) (data + N); + heap = pos + N + (N / 2); //points to middle of storage. + clear(); + } + + rolling_median_t(rolling_median_t &&m) + { + free(data); + memcpy(this, &m, sizeof(rolling_median_t)); + m.data = NULL; + } + rolling_median_t &operator=(rolling_median_t &&m) + { + free(data); + memcpy(this, &m, sizeof(rolling_median_t)); + m.data = NULL; + return *this; + } + + ~rolling_median_t() + { + free(data); + } + + void clear() + { + idx = 0; + minCt = 0; + maxCt = 0; + sz = 0; + int nItems = N; + while (nItems--) //set up initial heap fill pattern: median,max,min,max,... + { + pos[nItems] = ((nItems + 1) / 2) * ((nItems & 1) ? -1 : 1); + heap[pos[nItems]] = nItems; + } + } + + int size() const + { + return sz; + } + + //Inserts item, maintains median in O(lg nItems) + void insert(Item v) + { + int p = pos[idx]; + Item old = data[idx]; + data[idx] = v; + idx = (idx + 1) % N; + sz = std::min<int>(sz + 1, N); + if (p > 0) //new item is in minHeap + { + if (minCt < (N - 1) / 2) + { + ++minCt; + } + else if (v > old) + { + minSortDown(p); + return; + } + if (minSortUp(p) && mmCmpExch(0, -1)) + maxSortDown(-1); + } + else if (p < 0) //new item is in maxheap + { + if (maxCt < N / 2) + { + ++maxCt; + } + else if (v < old) + { + maxSortDown(p); + return; + } + if (maxSortUp(p) && minCt && mmCmpExch(1, 0)) + minSortDown(1); + } + else //new item is at median + { + if (maxCt && maxSortUp(-1)) + maxSortDown(-1); + if (minCt && minSortUp(1)) + minSortDown(1); + } + } + + //returns median item (or average of 2 when item count is even) + Item median() const + { + Item v = data[heap[0]]; + if (minCt < maxCt) + { + v = (v + data[heap[-1]]) / 2; + } + return v; + } +}; + +} +} diff --git a/contrib/epee/include/serialization/keyvalue_serialization.h b/contrib/epee/include/serialization/keyvalue_serialization.h index fc5a21851..5459c8409 100644 --- a/contrib/epee/include/serialization/keyvalue_serialization.h +++ b/contrib/epee/include/serialization/keyvalue_serialization.h @@ -32,6 +32,9 @@ #include "enableable.h" #include "keyvalue_serialization_overloads.h" +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "serialization" + namespace epee { /************************************************************************/ diff --git a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h index 15c95f07a..fc8b90a2c 100644 --- a/contrib/epee/include/serialization/keyvalue_serialization_overloads.h +++ b/contrib/epee/include/serialization/keyvalue_serialization_overloads.h @@ -33,6 +33,9 @@ #include <boost/mpl/vector.hpp> #include <boost/mpl/contains_fwd.hpp> +#undef MONERO_DEFAULT_LOG_CATEGORY +#define MONERO_DEFAULT_LOG_CATEGORY "serialization" + namespace epee { namespace diff --git a/contrib/epee/include/storages/portable_storage_from_bin.h b/contrib/epee/include/storages/portable_storage_from_bin.h index 2884f8c5e..e0a32b3ca 100644 --- a/contrib/epee/include/storages/portable_storage_from_bin.h +++ b/contrib/epee/include/storages/portable_storage_from_bin.h @@ -136,6 +136,7 @@ namespace epee //for pod types array_entry_t<type_name> sa; size_t size = read_varint(); + CHECK_AND_ASSERT_THROW_MES(size <= m_count, "Size sanity check failed"); sa.reserve(size); //TODO: add some optimization here later while(size--) diff --git a/contrib/epee/src/buffer.cpp b/contrib/epee/src/buffer.cpp index d637b905e..10ea6de56 100644 --- a/contrib/epee/src/buffer.cpp +++ b/contrib/epee/src/buffer.cpp @@ -64,7 +64,8 @@ void buffer::append(const void *data, size_t sz) size_t reserve = (((size() + sz) * 3 / 2) + 4095) & ~4095; new_storage.reserve(reserve); new_storage.resize(size()); - memcpy(new_storage.data(), storage.data() + offset, storage.size() - offset); + if (size() > 0) + memcpy(new_storage.data(), storage.data() + offset, storage.size() - offset); offset = 0; std::swap(storage, new_storage); } diff --git a/contrib/epee/src/mlog.cpp b/contrib/epee/src/mlog.cpp index 9b6b832d1..4c6ad5516 100644 --- a/contrib/epee/src/mlog.cpp +++ b/contrib/epee/src/mlog.cpp @@ -100,7 +100,7 @@ static const char *get_default_categories(int level) switch (level) { case 0: - categories = "*:WARNING,net:FATAL,net.http:FATAL,net.p2p:FATAL,net.cn:FATAL,global:INFO,verify:FATAL,stacktrace:INFO,logging:INFO,msgwriter:INFO"; + categories = "*:WARNING,net:FATAL,net.http:FATAL,net.ssl:FATAL,net.p2p:FATAL,net.cn:FATAL,global:INFO,verify:FATAL,serialization:FATAL,stacktrace:INFO,logging:INFO,msgwriter:INFO"; break; case 1: categories = "*:INFO,global:INFO,stacktrace:INFO,logging:INFO,msgwriter:INFO,perf.*:DEBUG"; diff --git a/contrib/epee/src/net_ssl.cpp b/contrib/epee/src/net_ssl.cpp index 7bedb18ac..7d48d2a64 100644 --- a/contrib/epee/src/net_ssl.cpp +++ b/contrib/epee/src/net_ssl.cpp @@ -78,6 +78,24 @@ namespace }; using openssl_bignum = std::unique_ptr<BIGNUM, openssl_bignum_free>; + struct openssl_ec_key_free + { + void operator()(EC_KEY* ptr) const noexcept + { + EC_KEY_free(ptr); + } + }; + using openssl_ec_key = std::unique_ptr<EC_KEY, openssl_ec_key_free>; + + struct openssl_group_free + { + void operator()(EC_GROUP* ptr) const noexcept + { + EC_GROUP_free(ptr); + } + }; + using openssl_group = std::unique_ptr<EC_GROUP, openssl_group_free>; + boost::system::error_code load_ca_file(boost::asio::ssl::context& ctx, const std::string& path) { SSL_CTX* const ssl_ctx = ctx.native_handle(); // could be moved from context @@ -101,7 +119,7 @@ namespace net_utils // https://stackoverflow.com/questions/256405/programmatically-create-x509-certificate-using-openssl -bool create_ssl_certificate(EVP_PKEY *&pkey, X509 *&cert) +bool create_rsa_ssl_certificate(EVP_PKEY *&pkey, X509 *&cert) { MGINFO("Generating SSL certificate"); pkey = EVP_PKEY_new(); @@ -171,6 +189,87 @@ bool create_ssl_certificate(EVP_PKEY *&pkey, X509 *&cert) return true; } +bool create_ec_ssl_certificate(EVP_PKEY *&pkey, X509 *&cert, int type) +{ + MGINFO("Generating SSL certificate"); + pkey = EVP_PKEY_new(); + if (!pkey) + { + MERROR("Failed to create new private key"); + return false; + } + + openssl_pkey pkey_deleter{pkey}; + openssl_ec_key ec_key{EC_KEY_new()}; + if (!ec_key) + { + MERROR("Error allocating EC private key"); + return false; + } + + EC_GROUP *group = EC_GROUP_new_by_curve_name(type); + if (!group) + { + MERROR("Error getting EC group " << type); + return false; + } + openssl_group group_deleter{group}; + + EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); + EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED); + + if (!EC_GROUP_check(group, NULL)) + { + MERROR("Group failed check: " << ERR_reason_error_string(ERR_get_error())); + return false; + } + if (EC_KEY_set_group(ec_key.get(), group) != 1) + { + MERROR("Error setting EC group"); + return false; + } + if (EC_KEY_generate_key(ec_key.get()) != 1) + { + MERROR("Error generating EC private key"); + return false; + } + if (EVP_PKEY_assign_EC_KEY(pkey, ec_key.get()) <= 0) + { + MERROR("Error assigning EC private key"); + return false; + } + + // the key is now managed by the EVP_PKEY structure + (void)ec_key.release(); + + cert = X509_new(); + if (!cert) + { + MERROR("Failed to create new X509 certificate"); + return false; + } + ASN1_INTEGER_set(X509_get_serialNumber(cert), 1); + X509_gmtime_adj(X509_get_notBefore(cert), 0); + X509_gmtime_adj(X509_get_notAfter(cert), 3600 * 24 * 182); // half a year + if (!X509_set_pubkey(cert, pkey)) + { + MERROR("Error setting pubkey on certificate"); + X509_free(cert); + return false; + } + X509_NAME *name = X509_get_subject_name(cert); + X509_set_issuer_name(cert, name); + + if (X509_sign(cert, pkey, EVP_sha256()) == 0) + { + MERROR("Error signing certificate"); + X509_free(cert); + return false; + } + (void)pkey_deleter.release(); + return true; +} + ssl_options_t::ssl_options_t(std::vector<std::vector<std::uint8_t>> fingerprints, std::string ca_path) : fingerprints_(std::move(fingerprints)), ca_path(std::move(ca_path)), @@ -195,7 +294,7 @@ boost::asio::ssl::context ssl_options_t::create_context() const ssl_context.set_options(boost::asio::ssl::context::no_tlsv1_1); // only allow a select handful of tls v1.3 and v1.2 ciphers to be used - SSL_CTX_set_cipher_list(ssl_context.native_handle(), "ECDHE-ECDSA-CHACHA20-POLY1305-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-CHACHA20-POLY1305"); + SSL_CTX_set_cipher_list(ssl_context.native_handle(), "ECDHE-ECDSA-CHACHA20-POLY1305-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256"); // set options on the SSL context for added security SSL_CTX *ctx = ssl_context.native_handle(); @@ -214,6 +313,10 @@ boost::asio::ssl::context ssl_options_t::create_context() const #ifdef SSL_OP_NO_COMPRESSION SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION); #endif +#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE + SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); +#endif + SSL_CTX_set_ecdh_auto(ctx, 1); switch (verification) { @@ -240,11 +343,29 @@ boost::asio::ssl::context ssl_options_t::create_context() const { EVP_PKEY *pkey; X509 *cert; - CHECK_AND_ASSERT_THROW_MES(create_ssl_certificate(pkey, cert), "Failed to create certificate"); + bool ok = false; + +#ifdef USE_EXTRA_EC_CERT + CHECK_AND_ASSERT_THROW_MES(create_ec_ssl_certificate(pkey, cert, NID_secp256k1), "Failed to create certificate"); + CHECK_AND_ASSERT_THROW_MES(SSL_CTX_use_certificate(ctx, cert), "Failed to use generated certificate"); + if (!SSL_CTX_use_PrivateKey(ctx, pkey)) + MERROR("Failed to use generated EC private key for " << NID_secp256k1); + else + ok = true; + X509_free(cert); + EVP_PKEY_free(pkey); +#endif + + CHECK_AND_ASSERT_THROW_MES(create_rsa_ssl_certificate(pkey, cert), "Failed to create certificate"); 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"); + if (!SSL_CTX_use_PrivateKey(ctx, pkey)) + MERROR("Failed to use generated RSA private key for RSA"); + else + ok = true; + X509_free(cert); EVP_PKEY_free(pkey); + + CHECK_AND_ASSERT_THROW_MES(ok, "Failed to use any generated certificate"); } else auth.use_ssl_certificate(ssl_context); @@ -321,7 +442,7 @@ bool ssl_options_t::has_fingerprint(boost::asio::ssl::verify_context &ctx) const unsigned int size{ 0 }; // create the digest from the certificate - if (!X509_digest(cert, EVP_sha1(), digest.data(), &size)) { + if (!X509_digest(cert, EVP_sha256(), digest.data(), &size)) { MERROR("Failed to create certificate fingerprint"); return false; } diff --git a/contrib/epee/src/net_utils_base.cpp b/contrib/epee/src/net_utils_base.cpp index 9b781027e..b7f07a23b 100644 --- a/contrib/epee/src/net_utils_base.cpp +++ b/contrib/epee/src/net_utils_base.cpp @@ -22,6 +22,24 @@ namespace epee { namespace net_utils bool ipv4_network_address::is_local() const { return net_utils::is_ip_local(ip()); } + bool ipv4_network_subnet::equal(const ipv4_network_subnet& other) const noexcept + { return is_same_host(other) && m_mask == other.m_mask; } + + bool ipv4_network_subnet::less(const ipv4_network_subnet& other) const noexcept + { return subnet() < other.subnet() ? true : (other.subnet() < subnet() ? false : (m_mask < other.m_mask)); } + + std::string ipv4_network_subnet::str() const + { return string_tools::get_ip_string_from_int32(subnet()) + "/" + std::to_string(m_mask); } + + std::string ipv4_network_subnet::host_str() const { return string_tools::get_ip_string_from_int32(subnet()) + "/" + std::to_string(m_mask); } + bool ipv4_network_subnet::is_loopback() const { return net_utils::is_ip_loopback(subnet()); } + bool ipv4_network_subnet::is_local() const { return net_utils::is_ip_local(subnet()); } + bool ipv4_network_subnet::matches(const ipv4_network_address &address) const + { + return (address.ip() & ~(0xffffffffull << m_mask)) == subnet(); + } + + bool network_address::equal(const network_address& other) const { // clang typeid workaround diff --git a/contrib/epee/src/wipeable_string.cpp b/contrib/epee/src/wipeable_string.cpp index 3a6ee5dac..4209b71bf 100644 --- a/contrib/epee/src/wipeable_string.cpp +++ b/contrib/epee/src/wipeable_string.cpp @@ -62,13 +62,15 @@ wipeable_string::wipeable_string(wipeable_string &&other) wipeable_string::wipeable_string(const std::string &other) { grow(other.size()); - memcpy(buffer.data(), other.c_str(), size()); + if (size() > 0) + memcpy(buffer.data(), other.c_str(), size()); } wipeable_string::wipeable_string(std::string &&other) { grow(other.size()); - memcpy(buffer.data(), other.c_str(), size()); + if (size() > 0) + memcpy(buffer.data(), other.c_str(), size()); if (!other.empty()) { memwipe(&other[0], other.size()); // we're kinda left with this again aren't we @@ -79,7 +81,8 @@ wipeable_string::wipeable_string(std::string &&other) wipeable_string::wipeable_string(const char *s) { grow(strlen(s)); - memcpy(buffer.data(), s, size()); + if (size() > 0) + memcpy(buffer.data(), s, size()); } wipeable_string::wipeable_string(const char *s, size_t len) @@ -112,14 +115,18 @@ void wipeable_string::grow(size_t sz, size_t reserved) } size_t old_sz = buffer.size(); std::unique_ptr<char[]> tmp{new char[old_sz]}; - memcpy(tmp.get(), buffer.data(), old_sz * sizeof(char)); if (old_sz > 0) + { + memcpy(tmp.get(), buffer.data(), old_sz * sizeof(char)); memwipe(buffer.data(), old_sz * sizeof(char)); + } buffer.reserve(reserved); buffer.resize(sz); - memcpy(buffer.data(), tmp.get(), old_sz * sizeof(char)); if (old_sz > 0) + { + memcpy(buffer.data(), tmp.get(), old_sz * sizeof(char)); memwipe(tmp.get(), old_sz * sizeof(char)); + } } void wipeable_string::push_back(char c) |