aboutsummaryrefslogtreecommitdiff
path: root/contrib/epee/src
diff options
context:
space:
mode:
authorJeffrey Ryan <jeffreyryan@tutanota.com>2022-05-19 15:27:30 -0500
committerjeffro256 <jeffro256@tutanota.com>2023-07-02 19:38:51 -0500
commit70bbd2536b0eb005458f7dee419eef503ff9e0cb (patch)
treebd821c083bc992dbb457670cff6ac3d5a93b1947 /contrib/epee/src
parentMerge pull request #8842 (diff)
downloadmonero-70bbd2536b0eb005458f7dee419eef503ff9e0cb.tar.xz
core_rpc_server: new file: rpc_ssl.fingerprint
Diffstat (limited to 'contrib/epee/src')
-rw-r--r--contrib/epee/src/net_ssl.cpp73
1 files changed, 73 insertions, 0 deletions
diff --git a/contrib/epee/src/net_ssl.cpp b/contrib/epee/src/net_ssl.cpp
index ff9c48c34..3822eb16d 100644
--- a/contrib/epee/src/net_ssl.cpp
+++ b/contrib/epee/src/net_ssl.cpp
@@ -641,6 +641,56 @@ bool ssl_options_t::handshake(
return true;
}
+std::string get_hr_ssl_fingerprint(const X509 *cert, const EVP_MD *fdig)
+{
+ unsigned int j;
+ unsigned int n;
+ unsigned char md[EVP_MAX_MD_SIZE];
+ std::string fingerprint;
+
+ CHECK_AND_ASSERT_THROW_MES(cert && fdig, "Pointer args to get_hr_ssl_fingerprint cannot be null");
+
+ if (!X509_digest(cert, fdig, md, &n))
+ {
+ const unsigned long ssl_err_val = static_cast<int>(ERR_get_error());
+ const boost::system::error_code ssl_err_code = boost::asio::error::ssl_errors(static_cast<int>(ssl_err_val));
+ MERROR("Failed to create SSL fingerprint: " << ERR_reason_error_string(ssl_err_val));
+ throw boost::system::system_error(ssl_err_code, ERR_reason_error_string(ssl_err_val));
+ }
+ fingerprint.resize(n * 3 - 1);
+ char *out = &fingerprint[0];
+ for (j = 0; j < n; ++j)
+ {
+ snprintf(out, 3 + (j + 1 < n), "%02X%s", md[j], (j + 1 == n) ? "" : ":");
+ out += 3;
+ }
+ return fingerprint;
+}
+
+std::string get_hr_ssl_fingerprint_from_file(const std::string& cert_path, const EVP_MD *fdig) {
+ // Open file for reading
+ FILE* fp = fopen(cert_path.c_str(), "r");
+ if (!fp)
+ {
+ const boost::system::error_code err_code(errno, boost::system::system_category());
+ throw boost::system::system_error(err_code, "Failed to open certificate file '" + cert_path + "'");
+ }
+ std::unique_ptr<FILE, decltype(&fclose)> file(fp, &fclose);
+
+ // Extract certificate structure from file
+ X509* ssl_cert_handle = PEM_read_X509(file.get(), NULL, NULL, NULL);
+ if (!ssl_cert_handle) {
+ const unsigned long ssl_err_val = static_cast<int>(ERR_get_error());
+ const boost::system::error_code ssl_err_code = boost::asio::error::ssl_errors(static_cast<int>(ssl_err_val));
+ MERROR("OpenSSL error occurred while loading certificate at '" + cert_path + "'");
+ throw boost::system::system_error(ssl_err_code, ERR_reason_error_string(ssl_err_val));
+ }
+ std::unique_ptr<X509, decltype(&X509_free)> ssl_cert(ssl_cert_handle, &X509_free);
+
+ // Get the fingerprint from X509 structure
+ return get_hr_ssl_fingerprint(ssl_cert.get(), fdig);
+}
+
bool ssl_support_from_string(ssl_support_t &ssl, boost::string_ref s)
{
if (s == "enabled")
@@ -705,6 +755,29 @@ boost::system::error_code store_ssl_keys(boost::asio::ssl::context& ssl, const b
return boost::asio::error::ssl_errors(ERR_get_error());
if (std::fclose(file.release()) != 0)
return {errno, boost::system::system_category()};
+
+ // write SHA-256 fingerprint file
+ const boost::filesystem::path fp_file{base.string() + ".fingerprint"};
+ file.reset(std::fopen(fp_file.string().c_str(), "w"));
+ if (!file)
+ return {errno, boost::system::system_category()};
+ const auto fp_perms = (boost::filesystem::owner_read | boost::filesystem::group_read | boost::filesystem::others_read);
+ boost::filesystem::permissions(fp_file, fp_perms, error);
+ if (error)
+ return error;
+ try
+ {
+ const std::string fingerprint = get_hr_ssl_fingerprint(ssl_cert);
+ if (fingerprint.length() != fwrite(fingerprint.c_str(), sizeof(char), fingerprint.length(), file.get()))
+ return {errno, boost::system::system_category()};
+ }
+ catch (const boost::system::system_error& fperr)
+ {
+ return fperr.code();
+ }
+ if (std::fclose(file.release()) != 0)
+ return {errno, boost::system::system_category()};
+
return error;
}