Remove tls rpc

This commit is contained in:
Piotr Wójcik 2024-05-25 12:39:09 +02:00
commit f02cee1da8
19 changed files with 8 additions and 590 deletions

View file

@ -1,6 +1,5 @@
#include <nano/lib/jsonconfig.hpp>
#include <nano/lib/rpcconfig.hpp>
#include <nano/lib/tlsconfig.hpp>
#include <nano/lib/tomlconfig.hpp>
#include <nano/node/daemonconfig.hpp>
#include <nano/secure/utility.hpp>
@ -943,64 +942,6 @@ TEST (toml, daemon_read_config)
}
}
/** Deserialize an tls config with non-default values */
TEST (toml, tls_config_deserialize_no_defaults)
{
std::stringstream ss;
// A config file with values that differs from devnet defaults
ss << R"toml(
enable_https=true
enable_wss=true
verbose_logging=true
server_cert_path="xyz.cert.pem"
server_key_path="xyz.key.pem"
server_key_passphrase="xyz"
server_dh_path="xyz.pem"
)toml";
nano::tomlconfig toml;
toml.read (ss);
nano::tls_config conf;
nano::tls_config defaults;
conf.deserialize_toml (toml);
ASSERT_FALSE (toml.get_error ()) << toml.get_error ().get_message ();
ASSERT_NE (conf.enable_https, defaults.enable_https);
ASSERT_NE (conf.enable_wss, defaults.enable_wss);
ASSERT_NE (conf.verbose_logging, defaults.verbose_logging);
ASSERT_NE (conf.server_cert_path, defaults.server_cert_path);
ASSERT_NE (conf.server_key_path, defaults.server_key_path);
ASSERT_NE (conf.server_key_passphrase, defaults.server_key_passphrase);
ASSERT_NE (conf.server_dh_path, defaults.server_dh_path);
}
/** Empty tls config file should match a default config object, and there should be no required values. */
TEST (toml, tls_config_defaults)
{
std::stringstream ss;
// A config with no values
ss << R"toml()toml";
nano::tomlconfig toml;
toml.read (ss);
nano::tls_config conf;
nano::tls_config defaults;
conf.deserialize_toml (toml);
ASSERT_FALSE (toml.get_error ()) << toml.get_error ().get_message ();
ASSERT_EQ (conf.enable_https, defaults.enable_wss);
ASSERT_EQ (conf.enable_wss, defaults.enable_wss);
ASSERT_EQ (conf.verbose_logging, defaults.verbose_logging);
ASSERT_EQ (conf.server_cert_path, defaults.server_cert_path);
ASSERT_EQ (conf.server_key_path, defaults.server_key_path);
ASSERT_EQ (conf.server_key_passphrase, defaults.server_key_passphrase);
ASSERT_EQ (conf.server_dh_path, defaults.server_dh_path);
}
TEST (toml, log_config_defaults)
{
std::stringstream ss;

View file

@ -99,8 +99,6 @@ add_library(
threading.cpp
timer.hpp
timer.cpp
tlsconfig.hpp
tlsconfig.cpp
tomlconfig.hpp
tomlconfig.cpp
uniquer.hpp

View file

@ -5,30 +5,6 @@
#include <boost/dll/runtime_symbol_info.hpp>
nano::error nano::rpc_secure_config::serialize_toml (nano::tomlconfig & toml) const
{
toml.put ("enable", enable, "Enable or disable TLS support.\ntype:bool");
toml.put ("verbose_logging", verbose_logging, "Enable or disable verbose logging.\ntype:bool");
toml.put ("server_key_passphrase", server_key_passphrase, "Server key passphrase.\ntype:string");
toml.put ("server_cert_path", server_cert_path, "Directory containing certificates.\ntype:string,path");
toml.put ("server_key_path", server_key_path, "Path to server key PEM file.\ntype:string,path");
toml.put ("server_dh_path", server_dh_path, "Path to Diffie-Hellman params file.\ntype:string,path");
toml.put ("client_certs_path", client_certs_path, "Directory containing client certificates.\ntype:string");
return toml.get_error ();
}
nano::error nano::rpc_secure_config::deserialize_toml (nano::tomlconfig & toml)
{
toml.get<bool> ("enable", enable);
toml.get<bool> ("verbose_logging", verbose_logging);
toml.get<std::string> ("server_key_passphrase", server_key_passphrase);
toml.get<std::string> ("server_cert_path", server_cert_path);
toml.get<std::string> ("server_key_path", server_key_path);
toml.get<std::string> ("server_dh_path", server_dh_path);
toml.get<std::string> ("client_certs_path", client_certs_path);
return toml.get_error ();
}
nano::rpc_config::rpc_config (nano::network_constants & network_constants) :
rpc_process{ network_constants },
address{ boost::asio::ip::address_v6::loopback ().to_string () }
@ -68,12 +44,6 @@ nano::error nano::rpc_config::deserialize_toml (nano::tomlconfig & toml)
{
if (!toml.empty ())
{
auto rpc_secure_l (toml.get_optional_child ("secure"));
if (rpc_secure_l)
{
return nano::error ("The RPC secure configuration has moved to config-tls.toml. Please update the configuration.");
}
boost::asio::ip::address_v6 address_l;
toml.get_optional<boost::asio::ip::address_v6> ("address", address_l, boost::asio::ip::address_v6::loopback ());
address = address_l.to_string ();

View file

@ -13,34 +13,6 @@
namespace nano
{
class tomlconfig;
class tls_config;
/**
* Configuration options for RPC TLS.
* @note This is deprecated, but kept for a few versions in order to yield a config error message on startup if it's used.
*/
class rpc_secure_config final
{
public:
nano::error serialize_toml (nano::tomlconfig &) const;
nano::error deserialize_toml (nano::tomlconfig &);
private:
/** If true, enable TLS */
bool enable{ false };
/** If true, log certificate verification details */
bool verbose_logging{ false };
/** Must be set if the private key PEM is password protected */
std::string server_key_passphrase;
/** Path to certificate- or chain file. Must be PEM formatted. */
std::string server_cert_path;
/** Path to private key file. Must be PEM formatted.*/
std::string server_key_path;
/** Path to dhparam file */
std::string server_dh_path;
/** Optional path to directory containing client certificates */
std::string client_certs_path;
};
class rpc_process_config final
{
@ -72,12 +44,9 @@ public:
std::string address;
uint16_t port{ rpc_process.network_constants.default_rpc_port };
bool enable_control{ false };
rpc_secure_config secure;
uint8_t max_json_depth{ 20 };
uint64_t max_request_size{ 32 * 1024 * 1024 };
nano::rpc_logging_config rpc_logging;
/** Optional TLS config */
std::shared_ptr<nano::tls_config> tls_config;
};
nano::error read_rpc_config_toml (std::filesystem::path const & data_path_a, nano::rpc_config & config_a, std::vector<std::string> const & config_overrides = std::vector<std::string> ());

View file

@ -1,186 +0,0 @@
#include <nano/lib/config.hpp>
#include <nano/lib/logging.hpp>
#include <nano/lib/tlsconfig.hpp>
#include <nano/lib/tomlconfig.hpp>
#include <boost/format.hpp>
#include <iostream>
namespace nano
{
nano::error nano::tls_config::serialize_toml (nano::tomlconfig & toml) const
{
toml.put ("enable_https", enable_https, "Enable or disable https:// support.\ntype:bool");
toml.put ("enable_wss", enable_wss, "Enable or disable wss:// support.\ntype:bool");
toml.put ("verbose_logging", verbose_logging, "Enable or disable verbose TLS logging.\ntype:bool");
toml.put ("server_key_passphrase", server_key_passphrase, "Server key passphrase.\ntype:string");
toml.put ("server_cert_path", server_cert_path, "Directory containing certificates.\ntype:string,path");
toml.put ("server_key_path", server_key_path, "Path to server key PEM file.\ntype:string,path");
toml.put ("server_dh_path", server_dh_path, "Path to Diffie-Hellman params file.\ntype:string,path");
toml.put ("client_certs_path", client_certs_path, "Directory containing optional client certificates.\ntype:string,path");
return toml.get_error ();
}
nano::error nano::tls_config::deserialize_toml (nano::tomlconfig & toml)
{
toml.get<bool> ("enable_https", enable_https);
toml.get<bool> ("enable_wss", enable_wss);
toml.get<bool> ("verbose_logging", verbose_logging);
toml.get<std::string> ("server_key_passphrase", server_key_passphrase);
toml.get<std::string> ("server_cert_path", server_cert_path);
toml.get<std::string> ("server_key_path", server_key_path);
toml.get<std::string> ("server_dh_path", server_dh_path);
toml.get<std::string> ("client_certs_path", client_certs_path);
return toml.get_error ();
}
#ifdef NANO_SECURE_RPC
namespace
{
bool on_verify_certificate (bool preverified, boost::asio::ssl::verify_context & ctx, nano::tls_config & config_a, nano::logger_mt & logger_a)
{
X509_STORE_CTX * cts = ctx.native_handle ();
auto error (X509_STORE_CTX_get_error (cts));
switch (error)
{
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
logger_a.always_log ("TLS: Unable to get issuer");
break;
case X509_V_ERR_CERT_NOT_YET_VALID:
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
logger_a.always_log ("TLS: Certificate not yet valid");
break;
case X509_V_ERR_CERT_HAS_EXPIRED:
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
logger_a.always_log ("TLS: Certificate expired");
break;
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
if (config_a.verbose_logging)
{
logger_a.always_log ("TLS: Self-signed certificate in chain");
}
// Allow self-signed certificates
preverified = true;
break;
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
logger_a.always_log ("TLS: Self-signed certificate not in the list of trusted certs (forgot to subject-hash certificate filename?)");
break;
default:
break;
}
if (config_a.verbose_logging)
{
if (error != 0)
{
logger_a.always_log ("TLS: Error: ", X509_verify_cert_error_string (error));
logger_a.always_log ("TLS: Error chain depth : ", X509_STORE_CTX_get_error_depth (cts));
}
X509 * cert = X509_STORE_CTX_get_current_cert (cts);
char subject_name[512];
X509_NAME_oneline (X509_get_subject_name (cert), subject_name, sizeof (subject_name) - 1);
logger_a.always_log ("TLS: Verifying: ", subject_name);
logger_a.always_log ("TLS: Verification: ", preverified);
}
else if (!preverified)
{
logger_a.always_log ("TLS: Pre-verification failed. Turn on verbose logging for more information.");
}
return preverified;
}
void load_certs (nano::tls_config & config_a, nano::logger_mt & logger_a)
{
try
{
// This is called if the key is password protected
config_a.ssl_context.set_password_callback (
[&config_a] (std::size_t,
boost::asio::ssl::context_base::password_purpose) {
return config_a.server_key_passphrase;
});
// The following two options disables the session cache and enables stateless session resumption.
// This is necessary because of the way the RPC server abruptly terminate connections.
SSL_CTX_set_session_cache_mode (config_a.ssl_context.native_handle (), SSL_SESS_CACHE_OFF);
SSL_CTX_set_options (config_a.ssl_context.native_handle (), SSL_OP_NO_TICKET);
config_a.ssl_context.set_options (
boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::no_sslv3 | boost::asio::ssl::context::single_dh_use);
config_a.ssl_context.use_certificate_chain_file (config_a.server_cert_path);
config_a.ssl_context.use_private_key_file (config_a.server_key_path, boost::asio::ssl::context::pem);
config_a.ssl_context.use_tmp_dh_file (config_a.server_dh_path);
// Verify client certificates?
if (!config_a.client_certs_path.empty ())
{
config_a.ssl_context.set_verify_mode (boost::asio::ssl::verify_fail_if_no_peer_cert | boost::asio::ssl::verify_peer);
config_a.ssl_context.add_verify_path (config_a.client_certs_path);
config_a.ssl_context.set_verify_callback ([&config_a, &logger_a] (auto preverified, auto & ctx) {
return on_verify_certificate (preverified, ctx, config_a, logger_a);
});
}
logger_a.always_log ("TLS: successfully configured");
}
catch (boost::system::system_error const & err)
{
auto error (boost::str (boost::format ("Could not load certificate information: %1%. Make sure the paths and the passphrase in config-tls.toml are correct.") % err.what ()));
std::cerr << error << std::endl;
logger_a.always_log (error);
}
}
}
#endif
nano::error read_tls_config_toml (std::filesystem::path const & data_path_a, nano::tls_config & config_a, nano::logger & logger, std::vector<std::string> const & config_overrides)
{
nano::error error;
auto toml_config_path = nano::get_tls_toml_config_path (data_path_a);
// Parse and deserialize
nano::tomlconfig toml;
std::stringstream config_overrides_stream;
for (auto const & entry : config_overrides)
{
config_overrides_stream << entry << std::endl;
}
config_overrides_stream << std::endl;
// Make sure we don't create an empty toml file if it doesn't exist. Running without a tls toml file is the default.
if (!error)
{
if (std::filesystem::exists (toml_config_path))
{
error = toml.read (config_overrides_stream, toml_config_path);
}
else
{
error = toml.read (config_overrides_stream);
}
}
if (!error)
{
error = config_a.deserialize_toml (toml);
}
if (!error && (config_a.enable_https || config_a.enable_wss))
{
#ifdef NANO_SECURE_RPC
load_certs (config_a, logger_a);
#else
logger.critical (nano::log::type::tls, "HTTPS or WSS is enabled in the TLS configuration, but the node is not built with NANO_SECURE_RPC");
std::exit (1);
#endif
}
return error;
}
}

View file

@ -1,58 +0,0 @@
#pragma once
#include <nano/lib/config.hpp>
#include <nano/lib/errors.hpp>
#include <string>
#include <thread>
#include <vector>
#ifdef NANO_SECURE_RPC
#include <boost/asio/ssl/context.hpp>
#endif
namespace nano
{
class logger;
class jsonconfig;
class tomlconfig;
/** Configuration options for secure RPC and WebSocket connections */
class tls_config final
{
public:
nano::error serialize_toml (nano::tomlconfig &) const;
nano::error deserialize_toml (nano::tomlconfig &);
/** If true, enable TLS for RPC (only allow https, otherwise only allow http) */
bool enable_https{ false };
/** If true, enable TLS for WebSocket (only allow wss, otherwise only allow ws) */
bool enable_wss{ false };
/** If true, log certificate verification details */
bool verbose_logging{ false };
/** Must be set if the private key PEM is password protected */
std::string server_key_passphrase;
/** Path to certificate- or chain file. Must be PEM formatted. */
std::string server_cert_path;
/** Path to private key file. Must be PEM formatted.*/
std::string server_key_path;
/** Path to dhparam file */
std::string server_dh_path;
/** Optional path to directory containing client certificates */
std::string client_certs_path;
#ifdef NANO_SECURE_RPC
/** The context needs to be shared between sessions to make resumption work */
boost::asio::ssl::context ssl_context{ boost::asio::ssl::context::tlsv12_server };
#endif
};
nano::error read_tls_config_toml (std::filesystem::path const & data_path_a, nano::tls_config & config_a, nano::logger &, std::vector<std::string> const & config_overrides = std::vector<std::string> ());
}

View file

@ -3,7 +3,6 @@
#include <nano/lib/stacktrace.hpp>
#include <nano/lib/thread_runner.hpp>
#include <nano/lib/threading.hpp>
#include <nano/lib/tlsconfig.hpp>
#include <nano/lib/utility.hpp>
#include <nano/nano_node/daemon.hpp>
#include <nano/node/cli.hpp>
@ -85,18 +84,6 @@ void nano::daemon::run (std::filesystem::path const & data_path, nano::node_flag
}
if (!error)
{
auto tls_config (std::make_shared<nano::tls_config> ());
error = nano::read_tls_config_toml (data_path, *tls_config, logger);
if (error)
{
std::cerr << error.get_message () << std::endl;
std::exit (1);
}
else
{
config.node.websocket_config.tls_config = tls_config;
}
std::shared_ptr<boost::asio::io_context> io_ctx = std::make_shared<boost::asio::io_context> ();
auto opencl = nano::opencl_work::create (config.opencl_enable, config.opencl, logger, config.node.network_params.work);
@ -176,7 +163,6 @@ void nano::daemon::run (std::filesystem::path const & data_path, nano::node_flag
std::exit (1);
}
rpc_config.tls_config = tls_config;
rpc_handler = std::make_unique<nano::inprocess_rpc_handler> (*node, *ipc_server, config.rpc, stop_callback);
rpc = nano::get_rpc (io_ctx, rpc_config, *rpc_handler);
rpc->start ();

View file

@ -4,7 +4,6 @@
#include <nano/lib/signal_manager.hpp>
#include <nano/lib/thread_runner.hpp>
#include <nano/lib/threading.hpp>
#include <nano/lib/tlsconfig.hpp>
#include <nano/lib/utility.hpp>
#include <nano/node/cli.hpp>
#include <nano/node/ipc/ipc_server.hpp>
@ -37,18 +36,6 @@ void run (std::filesystem::path const & data_path, std::vector<std::string> cons
auto error = nano::read_rpc_config_toml (data_path, rpc_config, config_overrides);
if (!error)
{
auto tls_config (std::make_shared<nano::tls_config> ());
error = nano::read_tls_config_toml (data_path, *tls_config, logger);
if (error)
{
logger.critical (nano::log::type::daemon_rpc, "Error reading RPC TLS config: {}", error.get_message ());
std::exit (1);
}
else
{
rpc_config.tls_config = tls_config;
}
std::shared_ptr<boost::asio::io_context> io_ctx = std::make_shared<boost::asio::io_context> ();
runner = std::make_unique<nano::thread_runner> (io_ctx, logger, rpc_config.rpc_process.io_threads, nano::thread_role::name::io_daemon);

View file

@ -5,7 +5,6 @@
#include <nano/lib/logging.hpp>
#include <nano/lib/rpcconfig.hpp>
#include <nano/lib/thread_runner.hpp>
#include <nano/lib/tlsconfig.hpp>
#include <nano/lib/tomlconfig.hpp>
#include <nano/lib/utility.hpp>
#include <nano/lib/walletconfig.hpp>
@ -109,19 +108,6 @@ int run_wallet (QApplication & application, int argc, char * const * argv, std::
{
nano::set_use_memory_pools (config.node.use_memory_pools);
auto tls_config (std::make_shared<nano::tls_config> ());
error = nano::read_tls_config_toml (data_path, *tls_config, logger);
if (error)
{
splash->hide ();
show_error (error.get_message ());
std::exit (1);
}
else
{
config.node.websocket_config.tls_config = tls_config;
}
std::shared_ptr<boost::asio::io_context> io_ctx = std::make_shared<boost::asio::io_context> ();
nano::thread_runner runner (io_ctx, logger, config.node.io_threads, nano::thread_role::name::io_daemon);
@ -190,7 +176,6 @@ int run_wallet (QApplication & application, int argc, char * const * argv, std::
show_error (error.get_message ());
std::exit (1);
}
rpc_config.tls_config = tls_config;
rpc_handler = std::make_unique<nano::inprocess_rpc_handler> (*node, ipc, config.rpc);
rpc = nano::get_rpc (io_ctx, rpc_config, *rpc_handler);
rpc->start ();

View file

@ -1,6 +1,5 @@
#include <nano/lib/blocks.hpp>
#include <nano/lib/cli.hpp>
#include <nano/lib/tlsconfig.hpp>
#include <nano/lib/tomlconfig.hpp>
#include <nano/node/cli.hpp>
#include <nano/node/common.hpp>
@ -700,12 +699,6 @@ std::error_code nano::handle_node_options (boost::program_options::variables_map
nano::log_config config = nano::log_config::sample_config ();
config.serialize_toml (toml);
}
else if (type == "tls")
{
valid_type = true;
nano::tls_config config;
config.serialize_toml (toml);
}
else
{
std::cerr << "Invalid configuration type " << type << ". Must be node or rpc." << std::endl;

View file

@ -3,7 +3,6 @@
#include <nano/boost/asio/strand.hpp>
#include <nano/lib/blocks.hpp>
#include <nano/lib/logging.hpp>
#include <nano/lib/tlsconfig.hpp>
#include <nano/lib/work.hpp>
#include <nano/node/election_status.hpp>
#include <nano/node/node_observers.hpp>
@ -578,8 +577,7 @@ void nano::websocket::listener::stop ()
sessions.clear ();
}
nano::websocket::listener::listener (std::shared_ptr<nano::tls_config> const & tls_config_a, nano::logger & logger_a, nano::wallets & wallets_a, boost::asio::io_context & io_ctx_a, boost::asio::ip::tcp::endpoint endpoint_a) :
tls_config (tls_config_a),
nano::websocket::listener::listener (nano::logger & logger_a, nano::wallets & wallets_a, boost::asio::io_context & io_ctx_a, boost::asio::ip::tcp::endpoint endpoint_a) :
logger (logger_a),
wallets (wallets_a),
acceptor (io_ctx_a),
@ -629,22 +627,15 @@ void nano::websocket::listener::on_accept (boost::system::error_code ec)
{
// Create the session and initiate websocket handshake
std::shared_ptr<nano::websocket::session> session;
if (tls_config && tls_config->enable_wss)
{
#ifdef NANO_SECURE_RPC
session = std::make_shared<nano::websocket::session> (*this, std::move (socket), tls_config->ssl_context);
#endif
}
else
{
session = std::make_shared<nano::websocket::session> (*this, std::move (socket), logger);
}
session = std::make_shared<nano::websocket::session> (*this, std::move (socket), logger);
// TODO: Why is this locking and unlocking mutex manually??
sessions_mutex.lock ();
sessions.push_back (session);
// Clean up expired sessions
sessions.erase (std::remove_if (sessions.begin (), sessions.end (), [] (auto & elem) { return elem.expired (); }), sessions.end ());
sessions_mutex.unlock ();
session->handshake ();
}
@ -1003,7 +994,7 @@ nano::websocket_server::websocket_server (nano::websocket::config & config_a, na
}
auto endpoint = nano::tcp_endpoint{ boost::asio::ip::make_address_v6 (config.address), config.port };
server = std::make_shared<nano::websocket::listener> (config.tls_config, logger, wallets, io_ctx, endpoint);
server = std::make_shared<nano::websocket::listener> (logger, wallets, io_ctx, endpoint);
observers.blocks.add ([this] (nano::election_status const & status_a, std::vector<nano::vote_with_weight_info> const & votes_a, nano::account const & account_a, nano::amount const & amount_a, bool is_state_send_a, bool is_state_epoch_a) {
debug_assert (status_a.type != nano::election_status_type::ongoing);

View file

@ -26,7 +26,6 @@ class ledger;
class logger;
class node_observers;
class telemetry_data;
class tls_config;
class vote;
enum class vote_code;
class wallets;
@ -303,7 +302,7 @@ namespace websocket
class listener final : public std::enable_shared_from_this<listener>
{
public:
listener (std::shared_ptr<nano::tls_config> const & tls_config_a, nano::logger &, nano::wallets & wallets_a, boost::asio::io_context & io_ctx_a, boost::asio::ip::tcp::endpoint endpoint_a);
listener (nano::logger &, nano::wallets & wallets_a, boost::asio::io_context & io_ctx_a, boost::asio::ip::tcp::endpoint endpoint_a);
/** Start accepting connections */
void run ();
@ -352,7 +351,6 @@ namespace websocket
/** Removes from subscription count of a specific topic*/
void decrease_subscriber_count (nano::websocket::topic const & topic_a);
std::shared_ptr<nano::tls_config> tls_config;
nano::logger & logger;
nano::wallets & wallets;
boost::asio::ip::tcp::acceptor acceptor;

View file

@ -8,7 +8,6 @@
namespace nano
{
class tomlconfig;
class tls_config;
namespace websocket
{
/** websocket configuration */
@ -22,8 +21,6 @@ namespace websocket
bool enabled{ false };
uint16_t port;
std::string address;
/** Optional TLS config */
std::shared_ptr<nano::tls_config> tls_config;
};
}
}

View file

@ -1,11 +1,5 @@
if(NANO_SECURE_RPC OR RAIBLOCKS_SECURE_RPC)
set(secure_rpc_sources rpc_secure.hpp rpc_secure.cpp
rpc_connection_secure.hpp rpc_connection_secure.cpp)
endif()
add_library(
rpc
${secure_rpc_sources}
rpc.hpp
rpc.cpp
rpc_connection.hpp
@ -15,4 +9,4 @@ add_library(
rpc_request_processor.hpp
rpc_request_processor.cpp)
target_link_libraries(rpc nano_lib Boost::beast ${OPENSSL_LIBRARIES})
target_link_libraries(rpc nano_lib Boost::beast)

View file

@ -1,6 +1,5 @@
#include <nano/boost/asio/bind_executor.hpp>
#include <nano/lib/rpc_handler_interface.hpp>
#include <nano/lib/tlsconfig.hpp>
#include <nano/rpc/rpc.hpp>
#include <nano/rpc/rpc_connection.hpp>
@ -8,10 +7,6 @@
#include <iostream>
#ifdef NANO_SECURE_RPC
#include <nano/rpc/rpc_secure.hpp>
#endif
nano::rpc::rpc (std::shared_ptr<boost::asio::io_context> io_ctx_a, nano::rpc_config config_a, nano::rpc_handler_interface & rpc_handler_interface_a) :
config (std::move (config_a)),
io_ctx_shared (io_ctx_a),
@ -88,15 +83,5 @@ void nano::rpc::stop ()
std::shared_ptr<nano::rpc> nano::get_rpc (std::shared_ptr<boost::asio::io_context> io_ctx_a, nano::rpc_config const & config_a, nano::rpc_handler_interface & rpc_handler_interface_a)
{
if (config_a.tls_config && config_a.tls_config->enable_https)
{
#ifdef NANO_SECURE_RPC
return std::make_shared<nano::rpc_secure> (io_ctx_a, config_a, rpc_handler_interface_a);
#endif
}
else
{
return std::make_shared<nano::rpc> (io_ctx_a, config_a, rpc_handler_interface_a);
}
return nullptr;
return std::make_shared<nano::rpc> (io_ctx_a, config_a, rpc_handler_interface_a);
}

View file

@ -1,47 +0,0 @@
#include <nano/boost/asio/bind_executor.hpp>
#include <nano/rpc/rpc_connection_secure.hpp>
#include <nano/rpc/rpc_secure.hpp>
#include <boost/polymorphic_pointer_cast.hpp>
nano::rpc_connection_secure::rpc_connection_secure (nano::rpc_config const & rpc_config, boost::asio::io_context & io_ctx, nano::logger_mt & logger, nano::rpc_handler_interface & rpc_handler_interface, boost::asio::ssl::context & ssl_context) :
nano::rpc_connection (rpc_config, io_ctx, logger, rpc_handler_interface),
stream (socket, ssl_context)
{
}
void nano::rpc_connection_secure::parse_connection ()
{
// Perform the SSL handshake
auto this_l = std::static_pointer_cast<nano::rpc_connection_secure> (shared_from_this ());
stream.async_handshake (boost::asio::ssl::stream_base::server,
boost::asio::bind_executor (this_l->strand, [this_l] (auto & ec) {
this_l->handle_handshake (ec);
}));
}
void nano::rpc_connection_secure::on_shutdown (boost::system::error_code const & error)
{
// No-op. We initiate the shutdown (since the RPC server kills the connection after each request)
// and we'll thus get an expected EOF error. If the client disconnects, a short-read error will be expected.
}
void nano::rpc_connection_secure::handle_handshake (boost::system::error_code const & error)
{
if (!error)
{
read (stream);
}
else
{
logger.always_log ("TLS: Handshake error: ", error.message ());
}
}
void nano::rpc_connection_secure::write_completion_handler (std::shared_ptr<nano::rpc_connection> const & rpc)
{
auto rpc_connection_secure = boost::polymorphic_pointer_downcast<nano::rpc_connection_secure> (rpc);
rpc_connection_secure->stream.async_shutdown (boost::asio::bind_executor (rpc->strand, [rpc_connection_secure] (auto const & ec_shutdown) {
rpc_connection_secure->on_shutdown (ec_shutdown);
}));
}

View file

@ -1,27 +0,0 @@
#pragma once
#include <nano/rpc/rpc_connection.hpp>
#include <boost/asio/ssl/stream.hpp>
namespace nano
{
/**
* Specialization of nano::rpc_connection for establishing TLS connections.
* Handshakes with client certificates are supported.
*/
class rpc_connection_secure : public rpc_connection
{
public:
rpc_connection_secure (nano::rpc_config const & rpc_config, boost::asio::io_context & io_ctx, nano::logger_mt & logger, nano::rpc_handler_interface & rpc_handler_interface_a, boost::asio::ssl::context & ssl_context);
void parse_connection () override;
void write_completion_handler (std::shared_ptr<nano::rpc_connection> const & rpc) override;
/** The TLS handshake callback */
void handle_handshake (boost::system::error_code const & error);
/** The TLS async shutdown callback */
void on_shutdown (boost::system::error_code const & error);
private:
boost::asio::ssl::stream<socket_type &> stream;
};
}

View file

@ -1,33 +0,0 @@
#include <nano/boost/asio/bind_executor.hpp>
#include <nano/lib/tlsconfig.hpp>
#include <nano/rpc/rpc_connection_secure.hpp>
#include <nano/rpc/rpc_secure.hpp>
#include <boost/format.hpp>
#include <boost/polymorphic_pointer_cast.hpp>
#include <iostream>
nano::rpc_secure::rpc_secure (boost::asio::io_context & context_a, nano::rpc_config const & config_a, nano::rpc_handler_interface & rpc_handler_interface_a) :
rpc (context_a, config_a, rpc_handler_interface_a)
{
}
void nano::rpc_secure::accept ()
{
auto connection (std::make_shared<nano::rpc_connection_secure> (config, io_ctx, logger, rpc_handler_interface, config.tls_config->ssl_context));
acceptor.async_accept (connection->socket, boost::asio::bind_executor (connection->strand, [this, connection] (boost::system::error_code const & ec) {
if (ec != boost::asio::error::operation_aborted && acceptor.is_open ())
{
accept ();
}
if (!ec)
{
connection->parse_connection ();
}
else
{
logger.error (nano::log::type::rpc, "Error accepting RPC connection: {}", ec.message ());
}
}));
}

View file

@ -1,25 +0,0 @@
#pragma once
#include <nano/rpc/rpc.hpp>
namespace boost
{
namespace asio
{
class io_context;
}
}
namespace nano
{
/**
* Specialization of nano::rpc with TLS support
*/
class rpc_secure : public rpc
{
public:
rpc_secure (boost::asio::io_context & context_a, nano::rpc_config const & config_a, nano::rpc_handler_interface & rpc_handler_interface_a);
/** Starts accepting connections */
void accept () override;
};
}