Skip to content

Commit

Permalink
Give better error messages when missing SSL files
Browse files Browse the repository at this point in the history
While copying my data dir to another drive, I missed copying the rpc_ssl.key file b/c of the file permissions.
This change will give a much more clear, descriptive error in that scenario.
  • Loading branch information
Jeffrey Ryan committed May 6, 2022
1 parent 67e5ca9 commit 1ddb1ee
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 6 deletions.
25 changes: 24 additions & 1 deletion contrib/epee/src/net_ssl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "misc_log_ex.h"
#include "net/net_helper.h"
#include "net/net_ssl.h"
#include "file_io_utils.h" // to validate .crt and .key paths

#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net.ssl"
Expand Down Expand Up @@ -356,6 +357,15 @@ boost::asio::ssl::context ssl_options_t::create_context() const
}

CHECK_AND_ASSERT_THROW_MES(auth.private_key_path.empty() == auth.certificate_path.empty(), "private key and certificate must be either both given or both empty");

const bool private_key_exists = epee::file_io_utils::is_file_exist(auth.private_key_path);
const bool certificate_exists = epee::file_io_utils::is_file_exist(auth.certificate_path);
if (private_key_exists && !certificate_exists) {
ASSERT_MES_AND_THROW("private key is present, but certificate file '" << auth.certificate_path << "' is missing");
} else if (!private_key_exists && certificate_exists) {
ASSERT_MES_AND_THROW("certificate is present, but private key file '" << auth.private_key_path << "' is missing");
}

if (auth.private_key_path.empty())
{
EVP_PKEY *pkey;
Expand Down Expand Up @@ -392,7 +402,12 @@ boost::asio::ssl::context ssl_options_t::create_context() const

void ssl_authentication_t::use_ssl_certificate(boost::asio::ssl::context &ssl_context) const
{
ssl_context.use_private_key_file(private_key_path, boost::asio::ssl::context::pem);
try {
ssl_context.use_private_key_file(private_key_path, boost::asio::ssl::context::pem);
} catch (const boost::system::system_error&) {
MERROR("Failed to load private key file '" << private_key_path << "' into SSL context");
throw;
}
ssl_context.use_certificate_chain_file(certificate_path);
}

Expand Down Expand Up @@ -590,7 +605,15 @@ boost::system::error_code store_ssl_keys(boost::asio::ssl::context& ssl, const b
const boost::filesystem::path key_file{base.string() + ".key"};
file.reset(std::fopen(key_file.string().c_str(), "wb"));
if (!file)
{
if (epee::file_io_utils::is_file_exist(key_file.string())) {
MERROR("Permission denied to overwrite SSL private key file: '" << key_file.string() << "'");
} else {
MERROR("Could not open SSL private key file for writing: '" << key_file.string() << "'");
}

return {errno, boost::system::system_category()};
}
boost::filesystem::permissions(key_file, boost::filesystem::owner_read, error);
if (error)
return error;
Expand Down
21 changes: 16 additions & 5 deletions src/rpc/core_rpc_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,12 +350,23 @@ namespace cryptonote

bool store_ssl_key = !restricted && rpc_config->ssl_options && rpc_config->ssl_options.auth.certificate_path.empty();
const auto ssl_base_path = (boost::filesystem::path{data_dir} / "rpc_ssl").string();
if (store_ssl_key && boost::filesystem::exists(ssl_base_path + ".crt"))
const bool ssl_cert_file_exists = boost::filesystem::exists(ssl_base_path + ".crt");
const bool ssl_pkey_file_exists = boost::filesystem::exists(ssl_base_path + ".key");
if (store_ssl_key)
{
// load key from previous run, password prompted by OpenSSL
store_ssl_key = false;
rpc_config->ssl_options.auth =
epee::net_utils::ssl_authentication_t{ssl_base_path + ".key", ssl_base_path + ".crt"};
// .key files are often given different read permissions as their corresponding .crt files.
// Consequently, sometimes the .key file wont't get copied, while the .crt file will.
if (ssl_cert_file_exists != ssl_pkey_file_exists)
{
MFATAL("Certificate (.crt) and private key (.key) files must both exist or both not exist at path: " << ssl_base_path);
return false;
}
else if (ssl_cert_file_exists) { // and ssl_pkey_file_exists
// load key from previous run, password prompted by OpenSSL
store_ssl_key = false;
rpc_config->ssl_options.auth =
epee::net_utils::ssl_authentication_t{ssl_base_path + ".key", ssl_base_path + ".crt"};
}
}

auto rng = [](size_t len, uint8_t *ptr){ return crypto::rand(len, ptr); };
Expand Down

0 comments on commit 1ddb1ee

Please sign in to comment.