commit
5bbbe3902b
|
@ -32,6 +32,7 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <boost/utility/string_ref.hpp>
|
||||||
|
|
||||||
#include "wipeable_string.h"
|
#include "wipeable_string.h"
|
||||||
#include "span.h"
|
#include "span.h"
|
||||||
|
@ -68,4 +69,10 @@ namespace epee
|
||||||
//! Write `src` bytes as hex to `out`. `out` must be twice the length
|
//! 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;
|
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);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,8 +228,8 @@ namespace net_utils
|
||||||
std::map<std::string, t_connection_type> server_type_map;
|
std::map<std::string, t_connection_type> server_type_map;
|
||||||
void create_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(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 = {}, 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.
|
/// 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());
|
bool run_server(size_t threads_count, bool wait = true, const boost::thread::attributes& attrs = boost::thread::attributes());
|
||||||
|
|
|
@ -900,7 +900,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
|
||||||
m_thread_index(0),
|
m_thread_index(0),
|
||||||
m_connection_type( connection_type ),
|
m_connection_type( connection_type ),
|
||||||
new_connection_(),
|
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();
|
create_server_type_map();
|
||||||
m_thread_name_prefix = "NET";
|
m_thread_name_prefix = "NET";
|
||||||
|
@ -939,14 +939,14 @@ PRAGMA_WARNING_DISABLE_VS(4355)
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
template<class t_protocol_handler>
|
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();
|
TRY_ENTRY();
|
||||||
m_stop_signal_sent = false;
|
m_stop_signal_sent = false;
|
||||||
m_port = port;
|
m_port = port;
|
||||||
m_address = address;
|
m_address = address;
|
||||||
if (ssl_support != epee::net_utils::ssl_support_t::e_ssl_support_disabled)
|
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).
|
// 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 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);
|
boost::asio::ip::tcp::resolver::query query(address, boost::lexical_cast<std::string>(port), boost::asio::ip::tcp::resolver::query::canonical_name);
|
||||||
|
@ -980,7 +980,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
|
||||||
PUSH_WARNINGS
|
PUSH_WARNINGS
|
||||||
DISABLE_GCC_WARNING(maybe-uninitialized)
|
DISABLE_GCC_WARNING(maybe-uninitialized)
|
||||||
template<class t_protocol_handler>
|
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;
|
uint32_t p = 0;
|
||||||
|
|
||||||
|
@ -988,7 +988,7 @@ DISABLE_GCC_WARNING(maybe-uninitialized)
|
||||||
MERROR("Failed to convert port no = " << port);
|
MERROR("Failed to convert port no = " << port);
|
||||||
return false;
|
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
|
POP_WARNINGS
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
|
|
|
@ -278,6 +278,7 @@ namespace net_utils
|
||||||
epee::net_utils::ssl_support_t m_ssl_support;
|
epee::net_utils::ssl_support_t m_ssl_support;
|
||||||
std::pair<std::string, std::string> m_ssl_private_key_and_certificate_path;
|
std::pair<std::string, std::string> m_ssl_private_key_and_certificate_path;
|
||||||
std::list<std::string> m_ssl_allowed_certificates;
|
std::list<std::string> m_ssl_allowed_certificates;
|
||||||
|
std::vector<std::vector<uint8_t>> m_ssl_allowed_fingerprints;
|
||||||
bool m_ssl_allow_any_cert;
|
bool m_ssl_allow_any_cert;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -302,16 +303,16 @@ namespace net_utils
|
||||||
const std::string &get_host() const { return m_host_buff; };
|
const std::string &get_host() const { return m_host_buff; };
|
||||||
const std::string &get_port() const { return m_port; };
|
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{};
|
http::url_content parsed{};
|
||||||
const bool r = parse_url(address, parsed);
|
const bool r = parse_url(address, parsed);
|
||||||
CHECK_AND_ASSERT_MES(r, false, "failed to parse url: " << address);
|
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;
|
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);
|
CRITICAL_REGION_LOCAL(m_lock);
|
||||||
disconnect();
|
disconnect();
|
||||||
|
@ -321,8 +322,9 @@ namespace net_utils
|
||||||
m_ssl_support = ssl_support;
|
m_ssl_support = ssl_support;
|
||||||
m_ssl_private_key_and_certificate_path = private_key_and_certificate_path;
|
m_ssl_private_key_and_certificate_path = private_key_and_certificate_path;
|
||||||
m_ssl_allowed_certificates = allowed_ssl_certificates;
|
m_ssl_allowed_certificates = allowed_ssl_certificates;
|
||||||
|
m_ssl_allowed_fingerprints = allowed_ssl_fingerprints;
|
||||||
m_ssl_allow_any_cert = allow_any_cert;
|
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)
|
bool connect(std::chrono::milliseconds timeout)
|
||||||
|
|
|
@ -61,7 +61,9 @@ namespace epee
|
||||||
boost::optional<net_utils::http::login> user = boost::none,
|
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,
|
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::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
|
//set self as callback handler
|
||||||
|
@ -78,7 +80,7 @@ namespace epee
|
||||||
m_net_server.get_config_object().m_user = std::move(user);
|
m_net_server.get_config_object().m_user = std::move(user);
|
||||||
|
|
||||||
MGINFO("Binding on " << bind_ip << ":" << bind_port);
|
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)
|
if(!res)
|
||||||
{
|
{
|
||||||
LOG_ERROR("Failed to bind server");
|
LOG_ERROR("Failed to bind server");
|
||||||
|
|
|
@ -93,7 +93,7 @@ namespace net_utils
|
||||||
m_deadline(m_io_service),
|
m_deadline(m_io_service),
|
||||||
m_shutdowned(0),
|
m_shutdowned(0),
|
||||||
m_ssl_support(epee::net_utils::ssl_support_t::e_ssl_support_autodetect),
|
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))
|
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 */ }
|
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)
|
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
|
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;
|
m_ssl_support = ssl_support;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,16 +50,17 @@ namespace net_utils
|
||||||
{
|
{
|
||||||
boost::asio::ssl::context context;
|
boost::asio::ssl::context context;
|
||||||
std::list<std::string> allowed_certificates;
|
std::list<std::string> allowed_certificates;
|
||||||
|
std::vector<std::vector<uint8_t>> allowed_fingerprints;
|
||||||
bool allow_any_cert;
|
bool allow_any_cert;
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://security.stackexchange.com/questions/34780/checking-client-hello-for-https-classification
|
// https://security.stackexchange.com/questions/34780/checking-client-hello-for-https-classification
|
||||||
constexpr size_t get_ssl_magic_size() { return 9; }
|
constexpr size_t get_ssl_magic_size() { return 9; }
|
||||||
bool is_ssl(const unsigned char *data, size_t len);
|
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);
|
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 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_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);
|
bool ssl_support_from_string(ssl_support_t &ssl, boost::string_ref s);
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,4 +83,67 @@ namespace epee
|
||||||
{
|
{
|
||||||
return write_hex(out, src);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -154,13 +154,19 @@ bool create_ssl_certificate(std::string &pkey_buffer, std::string &cert_buffer)
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
ssl_context_t ssl_context({boost::asio::ssl::context(boost::asio::ssl::context::sslv23), std::move(allowed_certificates)});
|
ssl_context_t ssl_context{boost::asio::ssl::context(boost::asio::ssl::context::tlsv12), std::move(allowed_certificates), std::move(allowed_fingerprints)};
|
||||||
|
|
||||||
// disable sslv2
|
// only allow tls v1.2 and up
|
||||||
ssl_context.context.set_options(boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2);
|
ssl_context.context.set_options(boost::asio::ssl::context::default_workarounds);
|
||||||
ssl_context.context.set_default_verify_paths();
|
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);
|
||||||
|
|
||||||
|
// 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
|
// set options on the SSL context for added security
|
||||||
SSL_CTX *ctx = ssl_context.context.native_handle();
|
SSL_CTX *ctx = ssl_context.context.native_handle();
|
||||||
|
@ -179,7 +185,7 @@ ssl_context_t create_ssl_context(const std::pair<std::string, std::string> &priv
|
||||||
#ifdef SSL_OP_NO_COMPRESSION
|
#ifdef SSL_OP_NO_COMPRESSION
|
||||||
SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
|
SSL_CTX_set_options(ctx, SSL_OP_NO_COMPRESSION);
|
||||||
#endif
|
#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");
|
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())
|
if (private_key_and_certificate_path.second.empty())
|
||||||
|
@ -225,7 +231,7 @@ bool is_ssl(const unsigned char *data, size_t len)
|
||||||
return false;
|
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();
|
X509_STORE_CTX *sctx = ctx.native_handle();
|
||||||
if (!sctx)
|
if (!sctx)
|
||||||
|
@ -240,11 +246,32 @@ bool is_certificate_allowed(boost::asio::ssl::verify_context &ctx, const std::li
|
||||||
return false;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ssl_context.allowed_certificates.empty()) {
|
||||||
BIO *bio_cert = BIO_new(BIO_s_mem());
|
BIO *bio_cert = BIO_new(BIO_s_mem());
|
||||||
openssl_bio bio_cert_deleter{bio_cert};
|
|
||||||
bool success = PEM_write_bio_X509(bio_cert, cert);
|
bool success = PEM_write_bio_X509(bio_cert, cert);
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
|
BIO_free(bio_cert);
|
||||||
MERROR("Failed to print certificate");
|
MERROR("Failed to print certificate");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -252,11 +279,18 @@ bool is_certificate_allowed(boost::asio::ssl::verify_context &ctx, const std::li
|
||||||
BIO_get_mem_ptr(bio_cert, &buf);
|
BIO_get_mem_ptr(bio_cert, &buf);
|
||||||
if (!buf || !buf->data || !buf->length)
|
if (!buf || !buf->data || !buf->length)
|
||||||
{
|
{
|
||||||
|
BIO_free(bio_cert);
|
||||||
MERROR("Failed to write certificate: " << ERR_get_error());
|
MERROR("Failed to write certificate: " << ERR_get_error());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::string certificate(std::string(buf->data, buf->length));
|
std::string certificate(std::string(buf->data, buf->length));
|
||||||
return std::find(allowed_certificates.begin(), allowed_certificates.end(), certificate) != allowed_certificates.end();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
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 +310,7 @@ bool ssl_handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socke
|
||||||
return false;
|
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");
|
MERROR("Certificate is not in the allowed list, connection droppped");
|
||||||
return false;
|
return false;
|
||||||
|
@ -289,7 +323,7 @@ bool ssl_handshake(boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socke
|
||||||
socket.handshake(type, ec);
|
socket.handshake(type, ec);
|
||||||
if (ec)
|
if (ec)
|
||||||
{
|
{
|
||||||
MERROR("handshake failed, connection dropped");
|
MERROR("handshake failed, connection dropped: " << ec.message());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!ssl_context.allow_any_cert && !verified)
|
if (!ssl_context.allow_any_cert && !verified)
|
||||||
|
|
|
@ -80,6 +80,7 @@ namespace cryptonote
|
||||||
command_line::add_arg(desc, arg_rpc_ssl_private_key);
|
command_line::add_arg(desc, arg_rpc_ssl_private_key);
|
||||||
command_line::add_arg(desc, arg_rpc_ssl_certificate);
|
command_line::add_arg(desc, arg_rpc_ssl_certificate);
|
||||||
command_line::add_arg(desc, arg_rpc_ssl_allowed_certificates);
|
command_line::add_arg(desc, arg_rpc_ssl_allowed_certificates);
|
||||||
|
command_line::add_arg(desc, arg_rpc_ssl_allowed_fingerprints);
|
||||||
command_line::add_arg(desc, arg_rpc_ssl_allow_any_cert);
|
command_line::add_arg(desc, arg_rpc_ssl_allow_any_cert);
|
||||||
command_line::add_arg(desc, arg_bootstrap_daemon_address);
|
command_line::add_arg(desc, arg_bootstrap_daemon_address);
|
||||||
command_line::add_arg(desc, arg_bootstrap_daemon_login);
|
command_line::add_arg(desc, arg_bootstrap_daemon_login);
|
||||||
|
@ -156,12 +157,16 @@ namespace cryptonote
|
||||||
ssl_allowed_certificates.back() = std::string();
|
ssl_allowed_certificates.back() = std::string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<std::string> ssl_allowed_fingerprint_strings = command_line::get_arg(vm, arg_rpc_ssl_allowed_fingerprints);
|
||||||
|
std::vector<std::vector<uint8_t>> ssl_allowed_fingerprints{ ssl_allowed_fingerprint_strings.size() };
|
||||||
|
std::transform(ssl_allowed_fingerprint_strings.begin(), ssl_allowed_fingerprint_strings.end(), ssl_allowed_fingerprints.begin(), epee::from_hex::vector);
|
||||||
const bool ssl_allow_any_cert = command_line::get_arg(vm, arg_rpc_ssl_allow_any_cert);
|
const bool ssl_allow_any_cert = command_line::get_arg(vm, arg_rpc_ssl_allow_any_cert);
|
||||||
|
|
||||||
auto rng = [](size_t len, uint8_t *ptr){ return crypto::rand(len, ptr); };
|
auto rng = [](size_t len, uint8_t *ptr){ return crypto::rand(len, ptr); };
|
||||||
return epee::http_server_impl_base<core_rpc_server, connection_context>::init(
|
return epee::http_server_impl_base<core_rpc_server, connection_context>::init(
|
||||||
rng, std::move(port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login),
|
rng, std::move(port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login),
|
||||||
ssl_support, std::make_pair(ssl_private_key, ssl_certificate), ssl_allowed_certificates, ssl_allow_any_cert
|
ssl_support, std::make_pair(ssl_private_key, ssl_certificate), std::move(ssl_allowed_certificates), std::move(ssl_allowed_fingerprints), ssl_allow_any_cert
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -2369,6 +2374,11 @@ namespace cryptonote
|
||||||
, "List of paths to PEM format certificates of allowed peers (all allowed if empty)"
|
, "List of paths to PEM format certificates of allowed peers (all allowed if empty)"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const command_line::arg_descriptor<std::vector<std::string>> core_rpc_server::arg_rpc_ssl_allowed_fingerprints = {
|
||||||
|
"rpc-ssl-allowed-fingerprints"
|
||||||
|
, "List of certificate fingerprints to allow"
|
||||||
|
};
|
||||||
|
|
||||||
const command_line::arg_descriptor<bool> core_rpc_server::arg_rpc_ssl_allow_any_cert = {
|
const command_line::arg_descriptor<bool> core_rpc_server::arg_rpc_ssl_allow_any_cert = {
|
||||||
"rpc-ssl-allow-any-cert"
|
"rpc-ssl-allow-any-cert"
|
||||||
, "Allow any peer certificate, rather than just those on the allowed list"
|
, "Allow any peer certificate, rather than just those on the allowed list"
|
||||||
|
|
|
@ -60,6 +60,7 @@ namespace cryptonote
|
||||||
static const command_line::arg_descriptor<std::string> arg_rpc_ssl_private_key;
|
static const command_line::arg_descriptor<std::string> arg_rpc_ssl_private_key;
|
||||||
static const command_line::arg_descriptor<std::string> arg_rpc_ssl_certificate;
|
static const command_line::arg_descriptor<std::string> arg_rpc_ssl_certificate;
|
||||||
static const command_line::arg_descriptor<std::vector<std::string>> arg_rpc_ssl_allowed_certificates;
|
static const command_line::arg_descriptor<std::vector<std::string>> arg_rpc_ssl_allowed_certificates;
|
||||||
|
static const command_line::arg_descriptor<std::vector<std::string>> arg_rpc_ssl_allowed_fingerprints;
|
||||||
static const command_line::arg_descriptor<bool> arg_rpc_ssl_allow_any_cert;
|
static const command_line::arg_descriptor<bool> arg_rpc_ssl_allow_any_cert;
|
||||||
static const command_line::arg_descriptor<std::string> arg_bootstrap_daemon_address;
|
static const command_line::arg_descriptor<std::string> arg_bootstrap_daemon_address;
|
||||||
static const command_line::arg_descriptor<std::string> arg_bootstrap_daemon_login;
|
static const command_line::arg_descriptor<std::string> arg_bootstrap_daemon_login;
|
||||||
|
|
|
@ -241,6 +241,7 @@ struct options {
|
||||||
const command_line::arg_descriptor<std::string> daemon_ssl_private_key = {"daemon-ssl-private-key", tools::wallet2::tr("Path to a PEM format private key"), ""};
|
const command_line::arg_descriptor<std::string> daemon_ssl_private_key = {"daemon-ssl-private-key", tools::wallet2::tr("Path to a PEM format private key"), ""};
|
||||||
const command_line::arg_descriptor<std::string> daemon_ssl_certificate = {"daemon-ssl-certificate", tools::wallet2::tr("Path to a PEM format certificate"), ""};
|
const command_line::arg_descriptor<std::string> daemon_ssl_certificate = {"daemon-ssl-certificate", tools::wallet2::tr("Path to a PEM format certificate"), ""};
|
||||||
const command_line::arg_descriptor<std::vector<std::string>> daemon_ssl_allowed_certificates = {"daemon-ssl-allowed-certificates", tools::wallet2::tr("List of paths to PEM format certificates of allowed RPC servers")};
|
const command_line::arg_descriptor<std::vector<std::string>> daemon_ssl_allowed_certificates = {"daemon-ssl-allowed-certificates", tools::wallet2::tr("List of paths to PEM format certificates of allowed RPC servers")};
|
||||||
|
const command_line::arg_descriptor<std::vector<std::string>> daemon_ssl_allowed_fingerprints = {"daemon-ssl-allowed-fingerprints", tools::wallet2::tr("List of valid fingerprints of allowed RPC servers")};
|
||||||
const command_line::arg_descriptor<bool> daemon_ssl_allow_any_cert = {"daemon-ssl-allow-any-cert", tools::wallet2::tr("Allow any SSL certificate from the daemon"), false};
|
const command_line::arg_descriptor<bool> daemon_ssl_allow_any_cert = {"daemon-ssl-allow-any-cert", tools::wallet2::tr("Allow any SSL certificate from the daemon"), false};
|
||||||
const command_line::arg_descriptor<bool> testnet = {"testnet", tools::wallet2::tr("For testnet. Daemon must also be launched with --testnet flag"), false};
|
const command_line::arg_descriptor<bool> testnet = {"testnet", tools::wallet2::tr("For testnet. Daemon must also be launched with --testnet flag"), false};
|
||||||
const command_line::arg_descriptor<bool> stagenet = {"stagenet", tools::wallet2::tr("For stagenet. Daemon must also be launched with --stagenet flag"), false};
|
const command_line::arg_descriptor<bool> stagenet = {"stagenet", tools::wallet2::tr("For stagenet. Daemon must also be launched with --stagenet flag"), false};
|
||||||
|
@ -316,6 +317,7 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
|
||||||
auto daemon_ssl_private_key = command_line::get_arg(vm, opts.daemon_ssl_private_key);
|
auto daemon_ssl_private_key = command_line::get_arg(vm, opts.daemon_ssl_private_key);
|
||||||
auto daemon_ssl_certificate = command_line::get_arg(vm, opts.daemon_ssl_certificate);
|
auto daemon_ssl_certificate = command_line::get_arg(vm, opts.daemon_ssl_certificate);
|
||||||
auto daemon_ssl_allowed_certificates = command_line::get_arg(vm, opts.daemon_ssl_allowed_certificates);
|
auto daemon_ssl_allowed_certificates = command_line::get_arg(vm, opts.daemon_ssl_allowed_certificates);
|
||||||
|
auto daemon_ssl_allowed_fingerprints = command_line::get_arg(vm, opts.daemon_ssl_allowed_fingerprints);
|
||||||
auto daemon_ssl_allow_any_cert = command_line::get_arg(vm, opts.daemon_ssl_allow_any_cert);
|
auto daemon_ssl_allow_any_cert = command_line::get_arg(vm, opts.daemon_ssl_allow_any_cert);
|
||||||
auto daemon_ssl = command_line::get_arg(vm, opts.daemon_ssl);
|
auto daemon_ssl = command_line::get_arg(vm, opts.daemon_ssl);
|
||||||
epee::net_utils::ssl_support_t ssl_support;
|
epee::net_utils::ssl_support_t ssl_support;
|
||||||
|
@ -382,8 +384,11 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::vector<uint8_t>> ssl_allowed_fingerprints{ daemon_ssl_allowed_fingerprints.size() };
|
||||||
|
std::transform(daemon_ssl_allowed_fingerprints.begin(), daemon_ssl_allowed_fingerprints.end(), ssl_allowed_fingerprints.begin(), epee::from_hex::vector);
|
||||||
|
|
||||||
std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(nettype, kdf_rounds, unattended));
|
std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(nettype, kdf_rounds, unattended));
|
||||||
wallet->init(std::move(daemon_address), std::move(login), 0, *trusted_daemon, ssl_support, std::make_pair(daemon_ssl_private_key, daemon_ssl_certificate), ssl_allowed_certificates, daemon_ssl_allow_any_cert);
|
wallet->init(std::move(daemon_address), std::move(login), 0, *trusted_daemon, ssl_support, std::make_pair(daemon_ssl_private_key, daemon_ssl_certificate), ssl_allowed_certificates, ssl_allowed_fingerprints, daemon_ssl_allow_any_cert);
|
||||||
|
|
||||||
boost::filesystem::path ringdb_path = command_line::get_arg(vm, opts.shared_ringdb_dir);
|
boost::filesystem::path ringdb_path = command_line::get_arg(vm, opts.shared_ringdb_dir);
|
||||||
wallet->set_ring_database(ringdb_path.string());
|
wallet->set_ring_database(ringdb_path.string());
|
||||||
|
@ -1044,6 +1049,7 @@ void wallet2::init_options(boost::program_options::options_description& desc_par
|
||||||
command_line::add_arg(desc_params, opts.daemon_ssl_private_key);
|
command_line::add_arg(desc_params, opts.daemon_ssl_private_key);
|
||||||
command_line::add_arg(desc_params, opts.daemon_ssl_certificate);
|
command_line::add_arg(desc_params, opts.daemon_ssl_certificate);
|
||||||
command_line::add_arg(desc_params, opts.daemon_ssl_allowed_certificates);
|
command_line::add_arg(desc_params, opts.daemon_ssl_allowed_certificates);
|
||||||
|
command_line::add_arg(desc_params, opts.daemon_ssl_allowed_fingerprints);
|
||||||
command_line::add_arg(desc_params, opts.daemon_ssl_allow_any_cert);
|
command_line::add_arg(desc_params, opts.daemon_ssl_allow_any_cert);
|
||||||
command_line::add_arg(desc_params, opts.testnet);
|
command_line::add_arg(desc_params, opts.testnet);
|
||||||
command_line::add_arg(desc_params, opts.stagenet);
|
command_line::add_arg(desc_params, opts.stagenet);
|
||||||
|
@ -1096,7 +1102,7 @@ std::unique_ptr<wallet2> wallet2::make_dummy(const boost::program_options::varia
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
bool wallet2::init(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, uint64_t upper_transaction_weight_limit, bool trusted_daemon, 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 wallet2::init(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, uint64_t upper_transaction_weight_limit, bool trusted_daemon, 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)
|
||||||
{
|
{
|
||||||
m_checkpoints.init_default_checkpoints(m_nettype);
|
m_checkpoints.init_default_checkpoints(m_nettype);
|
||||||
if(m_http_client.is_connected())
|
if(m_http_client.is_connected())
|
||||||
|
@ -1106,7 +1112,7 @@ bool wallet2::init(std::string daemon_address, boost::optional<epee::net_utils::
|
||||||
m_daemon_address = std::move(daemon_address);
|
m_daemon_address = std::move(daemon_address);
|
||||||
m_daemon_login = std::move(daemon_login);
|
m_daemon_login = std::move(daemon_login);
|
||||||
m_trusted_daemon = trusted_daemon;
|
m_trusted_daemon = trusted_daemon;
|
||||||
return m_http_client.set_server(get_daemon_address(), get_daemon_login(), ssl_support, private_key_and_certificate_path, allowed_certificates, allow_any_cert);
|
return m_http_client.set_server(get_daemon_address(), get_daemon_login(), ssl_support, private_key_and_certificate_path, allowed_certificates, allowed_fingerprints, allow_any_cert);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
bool wallet2::is_deterministic() const
|
bool wallet2::is_deterministic() const
|
||||||
|
|
|
@ -680,7 +680,8 @@ namespace tools
|
||||||
bool trusted_daemon = true,
|
bool trusted_daemon = true,
|
||||||
epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect,
|
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::pair<std::string, std::string> &private_key_and_certificate_path = {},
|
||||||
const std::list<std::string> &allowed_certificates = {}, bool allow_any_cert = false);
|
const std::list<std::string> &allowed_certificates = {}, const std::vector<std::vector<uint8_t>> &allowed_fingerprints = {},
|
||||||
|
bool allow_any_cert = false);
|
||||||
|
|
||||||
void stop() { m_run.store(false, std::memory_order_relaxed); m_message_store.stop(); }
|
void stop() { m_run.store(false, std::memory_order_relaxed); m_message_store.stop(); }
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@ namespace
|
||||||
const command_line::arg_descriptor<std::string> arg_rpc_ssl_private_key = {"rpc-ssl-private-key", tools::wallet2::tr("Path to a PEM format private key"), ""};
|
const command_line::arg_descriptor<std::string> arg_rpc_ssl_private_key = {"rpc-ssl-private-key", tools::wallet2::tr("Path to a PEM format private key"), ""};
|
||||||
const command_line::arg_descriptor<std::string> arg_rpc_ssl_certificate = {"rpc-ssl-certificate", tools::wallet2::tr("Path to a PEM format certificate"), ""};
|
const command_line::arg_descriptor<std::string> arg_rpc_ssl_certificate = {"rpc-ssl-certificate", tools::wallet2::tr("Path to a PEM format certificate"), ""};
|
||||||
const command_line::arg_descriptor<std::vector<std::string>> arg_rpc_ssl_allowed_certificates = {"rpc-ssl-allowed-certificates", tools::wallet2::tr("List of paths to PEM format certificates of allowed RPC servers (all allowed if empty)")};
|
const command_line::arg_descriptor<std::vector<std::string>> arg_rpc_ssl_allowed_certificates = {"rpc-ssl-allowed-certificates", tools::wallet2::tr("List of paths to PEM format certificates of allowed RPC servers (all allowed if empty)")};
|
||||||
|
const command_line::arg_descriptor<std::vector<std::string>> arg_rpc_ssl_allowed_fingerprints = {"rpc-ssl-allowed-fingerprints", tools::wallet2::tr("List of certificate fingerprints to allow")};
|
||||||
|
|
||||||
constexpr const char default_rpc_username[] = "monero";
|
constexpr const char default_rpc_username[] = "monero";
|
||||||
|
|
||||||
|
@ -240,6 +241,7 @@ namespace tools
|
||||||
auto rpc_ssl_private_key = command_line::get_arg(vm, arg_rpc_ssl_private_key);
|
auto rpc_ssl_private_key = command_line::get_arg(vm, arg_rpc_ssl_private_key);
|
||||||
auto rpc_ssl_certificate = command_line::get_arg(vm, arg_rpc_ssl_certificate);
|
auto rpc_ssl_certificate = command_line::get_arg(vm, arg_rpc_ssl_certificate);
|
||||||
auto rpc_ssl_allowed_certificates = command_line::get_arg(vm, arg_rpc_ssl_allowed_certificates);
|
auto rpc_ssl_allowed_certificates = command_line::get_arg(vm, arg_rpc_ssl_allowed_certificates);
|
||||||
|
auto rpc_ssl_allowed_fingerprints = command_line::get_arg(vm, arg_rpc_ssl_allowed_fingerprints);
|
||||||
auto rpc_ssl = command_line::get_arg(vm, arg_rpc_ssl);
|
auto rpc_ssl = command_line::get_arg(vm, arg_rpc_ssl);
|
||||||
epee::net_utils::ssl_support_t rpc_ssl_support;
|
epee::net_utils::ssl_support_t rpc_ssl_support;
|
||||||
if (!epee::net_utils::ssl_support_from_string(rpc_ssl_support, rpc_ssl))
|
if (!epee::net_utils::ssl_support_from_string(rpc_ssl_support, rpc_ssl))
|
||||||
|
@ -258,11 +260,14 @@ namespace tools
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::vector<uint8_t>> allowed_fingerprints{ rpc_ssl_allowed_fingerprints.size() };
|
||||||
|
std::transform(rpc_ssl_allowed_fingerprints.begin(), rpc_ssl_allowed_fingerprints.end(), allowed_fingerprints.begin(), epee::from_hex::vector);
|
||||||
|
|
||||||
m_net_server.set_threads_prefix("RPC");
|
m_net_server.set_threads_prefix("RPC");
|
||||||
auto rng = [](size_t len, uint8_t *ptr) { return crypto::rand(len, ptr); };
|
auto rng = [](size_t len, uint8_t *ptr) { return crypto::rand(len, ptr); };
|
||||||
return epee::http_server_impl_base<wallet_rpc_server, connection_context>::init(
|
return epee::http_server_impl_base<wallet_rpc_server, connection_context>::init(
|
||||||
rng, std::move(bind_port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login),
|
rng, std::move(bind_port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login),
|
||||||
rpc_ssl_support, std::make_pair(rpc_ssl_private_key, rpc_ssl_certificate), allowed_certificates
|
rpc_ssl_support, std::make_pair(rpc_ssl_private_key, rpc_ssl_certificate), std::move(allowed_certificates), std::move(allowed_fingerprints)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -389,6 +389,25 @@ TEST(ToHex, String)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(FromHex, String)
|
||||||
|
{
|
||||||
|
// the source data to encode and decode
|
||||||
|
std::vector<uint8_t> source{{ 0x00, 0xFF, 0x0F, 0xF0 }};
|
||||||
|
|
||||||
|
// encode and decode the data
|
||||||
|
auto hex = epee::to_hex::string({ source.data(), source.size() });
|
||||||
|
auto decoded = epee::from_hex::vector(hex);
|
||||||
|
|
||||||
|
// encoded should be twice the size and should decode to the exact same data
|
||||||
|
EXPECT_EQ(source.size() * 2, hex.size());
|
||||||
|
EXPECT_EQ(source, decoded);
|
||||||
|
|
||||||
|
// we will now create a padded hex string, we want to explicitly allow
|
||||||
|
// decoding it this way also, ignoring spaces and colons between the numbers
|
||||||
|
hex.assign("00:ff 0f:f0");
|
||||||
|
EXPECT_EQ(source, epee::from_hex::vector(hex));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ToHex, Array)
|
TEST(ToHex, Array)
|
||||||
{
|
{
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
|
|
Loading…
Reference in New Issue