22#include <boost/filesystem/operations.hpp>
23#include <boost/filesystem/path.hpp>
24#include <openssl/store.h>
25#include <openssl/ui.h>
29auto CreatePasswordUiMethodFromPemCallback(::pem_password_cb* callback)
34auto OpenOpenSSLStore(boost::filesystem::path
const& storePath, UI_METHOD
const* passwordCallback,
void* passwordCallbackData)
37 uri.reserve(6 + storePath.size());
40 std::string genericPath = storePath.generic_string();
41 if (!genericPath.empty() && !genericPath.starts_with(
'/'))
49boost::system::error_code GetLastOpenSSLError()
51 auto ossl_error = ::ERR_get_error();
52#if OPENSSL_VERSION_NUMBER >= 0x30000000L
53 if (ERR_SYSTEM_ERROR(ossl_error))
54 return boost::system::error_code(
static_cast<int>(::ERR_GET_REASON(ossl_error)), boost::asio::error::get_system_category());
57 return boost::system::error_code(
static_cast<int>(ossl_error), boost::asio::error::get_ssl_category());
63 boost::system::error_code err;
64#define LOAD_CHECK(fn) do { fn; \
67 TC_LOG_ERROR("server.ssl", #fn " failed: {}", err.message()); \
71 std::string certificateChainFile =
sConfigMgr->GetStringDefault(
"CertificatesFile",
"./bnetserver.cert.pem");
73 auto passwordCallback = [](std::size_t , boost::asio::ssl::context::password_purpose ) -> std::string
75 return sConfigMgr->GetStringDefault(
"PrivateKeyPassword",
"");
80 SSL_CTX* nativeContext =
instance().native_handle();
81 auto password_ui_method = CreatePasswordUiMethodFromPemCallback(SSL_CTX_get_default_passwd_cb(nativeContext));
83 auto store = OpenOpenSSLStore(boost::filesystem::absolute(certificateChainFile),
84 password_ui_method.get(), SSL_CTX_get_default_passwd_cb_userdata(nativeContext));
88 err = GetLastOpenSSLError();
89 TC_LOG_ERROR(
"server.ssl",
"OSSL_STORE_open failed: {}", err.message());
93 EVP_PKEY* key =
nullptr;
94 STACK_OF(X509)* certs = sk_X509_new_null();
95 while (!OSSL_STORE_eof(store.get()))
97 OSSL_STORE_INFO* info = OSSL_STORE_load(store.get());
101 switch (OSSL_STORE_INFO_get_type(info))
103 case OSSL_STORE_INFO_PKEY:
104 key = OSSL_STORE_INFO_get1_PKEY(info);
106 case OSSL_STORE_INFO_CERT:
107 sk_X509_push(certs, OSSL_STORE_INFO_get1_CERT(info));
114 if (sk_X509_num(certs) > 0)
116 X509* cert = sk_X509_shift(certs);
117 SSL_CTX_use_cert_and_key(nativeContext, cert, key, certs, 1);
124 std::string privateKeyFile =
sConfigMgr->GetStringDefault(
"PrivateKeyFile",
"./bnetserver.key.pem");
125 LOAD_CHECK(
instance().use_private_key_file(privateKeyFile, boost::asio::ssl::context::pem, err));
135 static boost::asio::ssl::context context(boost::asio::ssl::context::tls);
#define TC_LOG_ERROR(filterType__,...)
static boost::asio::ssl::context & instance()
auto make_unique_ptr_with_deleter(T ptr, Del &&deleter)