aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet_rpc_server.cpp
diff options
context:
space:
mode:
authorRiccardo Spagni <ric@spagni.net>2019-04-11 12:39:56 +0200
committerRiccardo Spagni <ric@spagni.net>2019-04-11 12:39:56 +0200
commit7c85f3b28e9f0528ff27284e98424c4e40205301 (patch)
tree103d97e9da3ceb4c6b2311dac3b41cb9e7085026 /src/wallet/wallet_rpc_server.cpp
parentMerge pull request #5364 (diff)
parentEnabling daemon-rpc SSL now requires non-system CA verification (diff)
downloadmonero-7c85f3b28e9f0528ff27284e98424c4e40205301.tar.xz
Merge pull request #5320
2e578b82 Enabling daemon-rpc SSL now requires non-system CA verification (Lee Clagett) d58f3682 Require manual override for user chain certificates. (Lee Clagett) 97cd1fa9 Only check top-level certificate against fingerprint list. (Lee Clagett) 7c388fb3 Call `use_certificate_chain_file` instead of `use_certificate_file` (Lee Clagett) eca0fea4 Perform RFC 2818 hostname verification in client SSL handshakes (Lee Clagett) 0416764c Require server verification when SSL is enabled. (Lee Clagett) 96d602ac Add `verify_fail_if_no_cert` option for proper client authentication (Lee Clagett) 21eb1b07 Pass SSL arguments via one class and use shared_ptr instead of reference (Lee Clagett) 1f5ed328 Change default SSL to "enabled" if user specifies fingerprint/certificate (Lee Clagett) f18a069f Do not require client certificate unless server has some whitelisted. (Lee Clagett) a3b02848 Change SSL certificate file list to OpenSSL builtin load_verify_location (Lee Clagett)
Diffstat (limited to 'src/wallet/wallet_rpc_server.cpp')
-rw-r--r--src/wallet/wallet_rpc_server.cpp76
1 files changed, 50 insertions, 26 deletions
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 92265d954..d456797a9 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -68,7 +68,7 @@ namespace
const command_line::arg_descriptor<std::string> arg_rpc_ssl = {"rpc-ssl", tools::wallet2::tr("Enable SSL on wallet RPC connections: enabled|disabled|autodetect"), "autodetect"};
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::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::string> arg_rpc_ssl_ca_certificates = {"rpc-ssl-ca-certificates", tools::wallet2::tr("Path to file containing concatenated PEM format certificate(s) to replace system CA(s).")};
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";
@@ -247,28 +247,34 @@ namespace tools
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_allowed_certificates = command_line::get_arg(vm, arg_rpc_ssl_allowed_certificates);
+ auto rpc_ssl_ca_file = command_line::get_arg(vm, arg_rpc_ssl_ca_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);
- epee::net_utils::ssl_support_t rpc_ssl_support;
- if (!epee::net_utils::ssl_support_from_string(rpc_ssl_support, rpc_ssl))
+ epee::net_utils::ssl_options_t rpc_ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_enabled;
+
+ if (!rpc_ssl_ca_file.empty() || !rpc_ssl_allowed_fingerprints.empty())
{
- MERROR("Invalid argument for " << std::string(arg_rpc_ssl.name));
- return false;
+ 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);
+
+ rpc_ssl_options = epee::net_utils::ssl_options_t{
+ std::move(allowed_fingerprints), std::move(rpc_ssl_ca_file)
+ };
}
- std::list<std::string> allowed_certificates;
- for (const std::string &path: rpc_ssl_allowed_certificates)
+
+ // user specified CA file or fingeprints implies enabled SSL by default
+ if (rpc_ssl_options.verification != epee::net_utils::ssl_verification_t::user_certificates || !command_line::is_arg_defaulted(vm, arg_rpc_ssl))
{
- allowed_certificates.push_back({});
- if (!epee::file_io_utils::load_file_to_string(path, allowed_certificates.back()))
- {
- MERROR("Failed to load certificate: " << path);
- allowed_certificates.back() = std::string();
- }
+ if (!epee::net_utils::ssl_support_from_string(rpc_ssl_options.support, rpc_ssl))
+ {
+ MERROR("Invalid argument for " << std::string(arg_rpc_ssl.name));
+ return false;
+ }
}
- 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);
+ rpc_ssl_options.auth = epee::net_utils::ssl_authentication_t{
+ std::move(rpc_ssl_private_key), std::move(rpc_ssl_certificate)
+ };
m_auto_refresh_period = DEFAULT_AUTO_REFRESH_PERIOD;
m_last_auto_refresh_time = boost::posix_time::min_date_time;
@@ -277,7 +283,7 @@ namespace tools
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(
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), std::move(allowed_certificates), std::move(allowed_fingerprints)
+ std::move(rpc_ssl_options)
);
}
//------------------------------------------------------------------------------------------------------------------------------
@@ -4054,13 +4060,7 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
- epee::net_utils::ssl_support_t ssl_support;
- if (!epee::net_utils::ssl_support_from_string(ssl_support, req.ssl_support))
- {
- er.code = WALLET_RPC_ERROR_CODE_NO_DAEMON_CONNECTION;
- er.message = std::string("Invalid ssl support mode");
- return false;
- }
+
std::vector<std::vector<uint8_t>> ssl_allowed_fingerprints;
ssl_allowed_fingerprints.reserve(req.ssl_allowed_fingerprints.size());
for (const std::string &fp: req.ssl_allowed_fingerprints)
@@ -4070,7 +4070,31 @@ namespace tools
for (auto c: fp)
v.push_back(c);
}
- if (!m_wallet->set_daemon(req.address, boost::none, req.trusted, ssl_support, std::make_pair(req.ssl_private_key_path, req.ssl_certificate_path), req.ssl_allowed_certificates, ssl_allowed_fingerprints, req.ssl_allow_any_cert))
+
+ epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_enabled;
+ if (req.ssl_allow_any_cert)
+ ssl_options.verification = epee::net_utils::ssl_verification_t::none;
+ else if (!ssl_allowed_fingerprints.empty() || !req.ssl_ca_file.empty())
+ ssl_options = epee::net_utils::ssl_options_t{std::move(ssl_allowed_fingerprints), std::move(req.ssl_ca_file)};
+
+ if (!epee::net_utils::ssl_support_from_string(ssl_options.support, req.ssl_support))
+ {
+ er.code = WALLET_RPC_ERROR_CODE_NO_DAEMON_CONNECTION;
+ er.message = std::string("Invalid ssl support mode");
+ return false;
+ }
+
+ ssl_options.auth = epee::net_utils::ssl_authentication_t{
+ std::move(req.ssl_private_key_path), std::move(req.ssl_certificate_path)
+ };
+
+ if (ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_enabled && !ssl_options.has_strong_verification(boost::string_ref{}))
+ {
+ er.code = WALLET_RPC_ERROR_CODE_NO_DAEMON_CONNECTION;
+ er.message = "SSL is enabled but no user certificate or fingerprints were provided";
+ }
+
+ if (!m_wallet->set_daemon(req.address, boost::none, req.trusted, std::move(ssl_options)))
{
er.code = WALLET_RPC_ERROR_CODE_NO_DAEMON_CONNECTION;
er.message = std::string("Unable to set daemon");
@@ -4278,7 +4302,7 @@ int main(int argc, char** argv) {
command_line::add_arg(desc_params, arg_rpc_ssl);
command_line::add_arg(desc_params, arg_rpc_ssl_private_key);
command_line::add_arg(desc_params, arg_rpc_ssl_certificate);
- command_line::add_arg(desc_params, arg_rpc_ssl_allowed_certificates);
+ command_line::add_arg(desc_params, arg_rpc_ssl_ca_certificates);
command_line::add_arg(desc_params, arg_rpc_ssl_allowed_fingerprints);
daemonizer::init_options(hidden_options, desc_params);