diff options
author | Lee Clagett <code@leeclagett.com> | 2019-05-22 00:09:11 -0400 |
---|---|---|
committer | Lee Clagett <code@leeclagett.com> | 2019-05-22 00:09:11 -0400 |
commit | 3544596f9fd0a260c3a1a9b75432234f93f78cb7 (patch) | |
tree | 1e961af0bae06e17e45b80b23352d836944ba3a4 /src/rpc | |
parent | Fix configuration bug; wallet2 --daemon-ssl-allow-any-cert now works. (diff) | |
download | monero-3544596f9fd0a260c3a1a9b75432234f93f78cb7.tar.xz |
Add ssl_options support to monerod's rpc mode.
Diffstat (limited to 'src/rpc')
-rw-r--r-- | src/rpc/core_rpc_server.cpp | 83 | ||||
-rw-r--r-- | src/rpc/rpc_args.cpp | 82 | ||||
-rw-r--r-- | src/rpc/rpc_args.h | 18 |
3 files changed, 99 insertions, 84 deletions
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 5777370fc..5ca5f3fe7 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -90,15 +90,9 @@ namespace cryptonote command_line::add_arg(desc, arg_rpc_bind_port); command_line::add_arg(desc, arg_rpc_restricted_bind_port); command_line::add_arg(desc, arg_restricted_rpc); - command_line::add_arg(desc, arg_rpc_ssl); - 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_ca_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_bootstrap_daemon_address); command_line::add_arg(desc, arg_bootstrap_daemon_login); - cryptonote::rpc_args::init_options(desc); + cryptonote::rpc_args::init_options(desc, true); } //------------------------------------------------------------------------------------------------------------------------------ core_rpc_server::core_rpc_server( @@ -118,7 +112,7 @@ namespace cryptonote m_restricted = restricted; m_net_server.set_threads_prefix("RPC"); - auto rpc_config = cryptonote::rpc_args::process(vm); + auto rpc_config = cryptonote::rpc_args::process(vm, true); if (!rpc_config) return false; @@ -151,46 +145,9 @@ namespace cryptonote if (rpc_config->login) http_login.emplace(std::move(rpc_config->login->username), std::move(rpc_config->login->password).password()); - epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_autodetect; - if (command_line::get_arg(vm, arg_rpc_ssl_allow_any_cert)) - ssl_options.verification = epee::net_utils::ssl_verification_t::none; - else - { - std::string ssl_ca_path = command_line::get_arg(vm, arg_rpc_ssl_ca_certificates); - 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); - for (const auto &fpr: ssl_allowed_fingerprints) - { - if (fpr.size() != SSL_FINGERPRINT_SIZE) - { - MERROR("SHA-256 fingerprint should be " BOOST_PP_STRINGIZE(SSL_FINGERPRINT_SIZE) " bytes long."); - return false; - } - } - - if (!ssl_ca_path.empty() || !ssl_allowed_fingerprints.empty()) - ssl_options = epee::net_utils::ssl_options_t{std::move(ssl_allowed_fingerprints), std::move(ssl_ca_path)}; - } - - ssl_options.auth = epee::net_utils::ssl_authentication_t{ - command_line::get_arg(vm, arg_rpc_ssl_private_key), command_line::get_arg(vm, arg_rpc_ssl_certificate) - }; - - // user specified CA file or fingeprints implies enabled SSL by default - if (ssl_options.verification != epee::net_utils::ssl_verification_t::user_certificates || !command_line::is_arg_defaulted(vm, arg_rpc_ssl)) - { - const std::string ssl = command_line::get_arg(vm, arg_rpc_ssl); - if (!epee::net_utils::ssl_support_from_string(ssl_options.support, ssl)) - { - MFATAL("Invalid RPC SSL support: " << ssl); - return false; - } - } - 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( - rng, std::move(port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login), std::move(ssl_options) + rng, std::move(port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login), std::move(rpc_config->ssl_options) ); } //------------------------------------------------------------------------------------------------------------------------------ @@ -2439,40 +2396,6 @@ namespace cryptonote , false }; - const command_line::arg_descriptor<std::string> core_rpc_server::arg_rpc_ssl = { - "rpc-ssl" - , "Enable SSL on RPC connections: enabled|disabled|autodetect" - , "autodetect" - }; - - const command_line::arg_descriptor<std::string> core_rpc_server::arg_rpc_ssl_private_key = { - "rpc-ssl-private-key" - , "Path to a PEM format private key" - , "" - }; - - const command_line::arg_descriptor<std::string> core_rpc_server::arg_rpc_ssl_certificate = { - "rpc-ssl-certificate" - , "Path to a PEM format certificate" - , "" - }; - - const command_line::arg_descriptor<std::string> core_rpc_server::arg_rpc_ssl_ca_certificates = { - "rpc-ssl-ca-certificates" - , "Path to file containing concatenated PEM format certificate(s) to replace system CA(s)." - }; - - 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 = { - "rpc-ssl-allow-any-cert" - , "Allow any peer certificate" - , false - }; - const command_line::arg_descriptor<std::string> core_rpc_server::arg_bootstrap_daemon_address = { "bootstrap-daemon-address" , "URL of a 'bootstrap' remote daemon that the connected wallets can use while this daemon is still not fully synced" diff --git a/src/rpc/rpc_args.cpp b/src/rpc/rpc_args.cpp index f2be94f51..4479bd1f1 100644 --- a/src/rpc/rpc_args.cpp +++ b/src/rpc/rpc_args.cpp @@ -33,28 +33,95 @@ #include <boost/bind.hpp> #include "common/command_line.h" #include "common/i18n.h" +#include "hex.h" namespace cryptonote { + namespace + { + boost::optional<epee::net_utils::ssl_options_t> do_process_ssl(const boost::program_options::variables_map& vm, const rpc_args::descriptors& arg, const bool any_cert_option) + { + bool ssl_required = false; + epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_enabled; + if (any_cert_option && command_line::get_arg(vm, arg.rpc_ssl_allow_any_cert)) + ssl_options.verification = epee::net_utils::ssl_verification_t::none; + else + { + std::string ssl_ca_file = command_line::get_arg(vm, arg.rpc_ssl_ca_certificates); + const std::vector<std::string> ssl_allowed_fingerprints = command_line::get_arg(vm, arg.rpc_ssl_allowed_fingerprints); + + std::vector<std::vector<uint8_t>> allowed_fingerprints{ ssl_allowed_fingerprints.size() }; + std::transform(ssl_allowed_fingerprints.begin(), ssl_allowed_fingerprints.end(), allowed_fingerprints.begin(), epee::from_hex::vector); + for (const auto &fpr: allowed_fingerprints) + { + if (fpr.size() != SSL_FINGERPRINT_SIZE) + { + MERROR("SHA-256 fingerprint should be " BOOST_PP_STRINGIZE(SSL_FINGERPRINT_SIZE) " bytes long."); + return boost::none; + } + } + + if (!allowed_fingerprints.empty() || !ssl_ca_file.empty()) + { + ssl_required = true; + ssl_options = epee::net_utils::ssl_options_t{ + std::move(allowed_fingerprints), std::move(ssl_ca_file) + }; + + if (command_line::get_arg(vm, arg.rpc_ssl_allow_chained)) + ssl_options.verification = epee::net_utils::ssl_verification_t::user_ca; + } + } + + // user specified CA file or fingeprints implies enabled SSL by default + if (!ssl_required && !epee::net_utils::ssl_support_from_string(ssl_options.support, command_line::get_arg(vm, arg.rpc_ssl))) + { + MERROR("Invalid argument for " << std::string(arg.rpc_ssl.name)); + return boost::none; + } + + ssl_options.auth = epee::net_utils::ssl_authentication_t{ + command_line::get_arg(vm, arg.rpc_ssl_private_key), command_line::get_arg(vm, arg.rpc_ssl_certificate) + }; + + return {std::move(ssl_options)}; + } + } // anonymous + rpc_args::descriptors::descriptors() : rpc_bind_ip({"rpc-bind-ip", rpc_args::tr("Specify IP to bind RPC server"), "127.0.0.1"}) , rpc_login({"rpc-login", rpc_args::tr("Specify username[:password] required for RPC server"), "", true}) , confirm_external_bind({"confirm-external-bind", rpc_args::tr("Confirm rpc-bind-ip value is NOT a loopback (local) IP")}) , rpc_access_control_origins({"rpc-access-control-origins", rpc_args::tr("Specify a comma separated list of origins to allow cross origin resource sharing"), ""}) + , rpc_ssl({"rpc-ssl", rpc_args::tr("Enable SSL on RPC connections: enabled|disabled|autodetect"), "autodetect"}) + , rpc_ssl_private_key({"rpc-ssl-private-key", rpc_args::tr("Path to a PEM format private key"), ""}) + , rpc_ssl_certificate({"rpc-ssl-certificate", rpc_args::tr("Path to a PEM format certificate"), ""}) + , rpc_ssl_ca_certificates({"rpc-ssl-ca-certificates", rpc_args::tr("Path to file containing concatenated PEM format certificate(s) to replace system CA(s)."), ""}) + , rpc_ssl_allowed_fingerprints({"rpc-ssl-allowed-fingerprints", rpc_args::tr("List of certificate fingerprints to allow")}) + , rpc_ssl_allow_chained({"rpc-ssl-allow-chained", rpc_args::tr("Allow user (via --rpc-ssl-certificates) chain certificates"), false}) + , rpc_ssl_allow_any_cert({"rpc-ssl-allow-any-cert", rpc_args::tr("Allow any peer certificate"), false}) {} const char* rpc_args::tr(const char* str) { return i18n_translate(str, "cryptonote::rpc_args"); } - void rpc_args::init_options(boost::program_options::options_description& desc) + void rpc_args::init_options(boost::program_options::options_description& desc, const bool any_cert_option) { const descriptors arg{}; command_line::add_arg(desc, arg.rpc_bind_ip); command_line::add_arg(desc, arg.rpc_login); command_line::add_arg(desc, arg.confirm_external_bind); command_line::add_arg(desc, arg.rpc_access_control_origins); + command_line::add_arg(desc, arg.rpc_ssl); + 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_ca_certificates); + command_line::add_arg(desc, arg.rpc_ssl_allowed_fingerprints); + command_line::add_arg(desc, arg.rpc_ssl_allow_chained); + if (any_cert_option) + command_line::add_arg(desc, arg.rpc_ssl_allow_any_cert); } - boost::optional<rpc_args> rpc_args::process(const boost::program_options::variables_map& vm) + boost::optional<rpc_args> rpc_args::process(const boost::program_options::variables_map& vm, const bool any_cert_option) { const descriptors arg{}; rpc_args config{}; @@ -118,6 +185,17 @@ namespace cryptonote config.access_control_origins = std::move(access_control_origins); } + auto ssl_options = do_process_ssl(vm, arg, any_cert_option); + if (!ssl_options) + return boost::none; + config.ssl_options = std::move(*ssl_options); + return {std::move(config)}; } + + boost::optional<epee::net_utils::ssl_options_t> rpc_args::process_ssl(const boost::program_options::variables_map& vm, const bool any_cert_option) + { + const descriptors arg{}; + return do_process_ssl(vm, arg, any_cert_option); + } } diff --git a/src/rpc/rpc_args.h b/src/rpc/rpc_args.h index 216ba3712..619f02b42 100644 --- a/src/rpc/rpc_args.h +++ b/src/rpc/rpc_args.h @@ -35,6 +35,7 @@ #include "common/command_line.h" #include "common/password.h" +#include "net/net_ssl.h" namespace cryptonote { @@ -54,16 +55,29 @@ namespace cryptonote const command_line::arg_descriptor<std::string> rpc_login; const command_line::arg_descriptor<bool> confirm_external_bind; const command_line::arg_descriptor<std::string> rpc_access_control_origins; + const command_line::arg_descriptor<std::string> rpc_ssl; + const command_line::arg_descriptor<std::string> rpc_ssl_private_key; + const command_line::arg_descriptor<std::string> rpc_ssl_certificate; + const command_line::arg_descriptor<std::string> rpc_ssl_ca_certificates; + const command_line::arg_descriptor<std::vector<std::string>> rpc_ssl_allowed_fingerprints; + const command_line::arg_descriptor<bool> rpc_ssl_allow_chained; + const command_line::arg_descriptor<bool> rpc_ssl_allow_any_cert; }; + // `allow_any_cert` bool toggles `--rpc-ssl-allow-any-cert` configuration + static const char* tr(const char* str); - static void init_options(boost::program_options::options_description& desc); + static void init_options(boost::program_options::options_description& desc, const bool any_cert_option = false); //! \return Arguments specified by user, or `boost::none` if error - static boost::optional<rpc_args> process(const boost::program_options::variables_map& vm); + static boost::optional<rpc_args> process(const boost::program_options::variables_map& vm, const bool any_cert_option = false); + + //! \return SSL arguments specified by user, or `boost::none` if error + static boost::optional<epee::net_utils::ssl_options_t> process_ssl(const boost::program_options::variables_map& vm, const bool any_cert_option = false); std::string bind_ip; std::vector<std::string> access_control_origins; boost::optional<tools::login> login; // currently `boost::none` if unspecified by user + epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_enabled; }; } |