diff options
| author | funjoker <funjoker109@gmail.com> | 2024-03-28 20:18:59 +0100 |
|---|---|---|
| committer | funjoker <funjoker109@gmail.com> | 2024-03-28 20:20:04 +0100 |
| commit | e769af1044f524ee9ef469a3d1bfb728ee5ef4d0 (patch) | |
| tree | 8da8700300f27e6070a12356e97f459a7841b081 /src/server/bnetserver | |
| parent | cdaf8ffc068ef00a3427af2b95a46e360d63e1fc (diff) | |
Core: port sneaky fixes from "Core: Updated to 10.2.6.53840"
Diffstat (limited to 'src/server/bnetserver')
| -rw-r--r-- | src/server/bnetserver/REST/LoginHttpSession.cpp | 62 | ||||
| -rw-r--r-- | src/server/bnetserver/REST/LoginHttpSession.h | 49 | ||||
| -rw-r--r-- | src/server/bnetserver/REST/LoginRESTService.cpp | 28 | ||||
| -rw-r--r-- | src/server/bnetserver/REST/LoginRESTService.h | 14 | ||||
| -rw-r--r-- | src/server/bnetserver/Server/Session.cpp | 3 | ||||
| -rw-r--r-- | src/server/bnetserver/Server/SslContext.cpp | 33 | ||||
| -rw-r--r-- | src/server/bnetserver/Server/SslContext.h | 5 |
7 files changed, 148 insertions, 46 deletions
diff --git a/src/server/bnetserver/REST/LoginHttpSession.cpp b/src/server/bnetserver/REST/LoginHttpSession.cpp index 95112cb8836..aff579de7f9 100644 --- a/src/server/bnetserver/REST/LoginHttpSession.cpp +++ b/src/server/bnetserver/REST/LoginHttpSession.cpp @@ -23,17 +23,20 @@ namespace Battlenet { -LoginHttpSession::LoginHttpSession(boost::asio::ip::tcp::socket&& socket) - : SslSocket(std::move(socket), SslContext::instance()) +template<template<typename> typename SocketImpl> +LoginHttpSession<SocketImpl>::LoginHttpSession(boost::asio::ip::tcp::socket&& socket, LoginHttpSessionWrapper& owner) + : BaseSocket(std::move(socket), SslContext::instance()), _owner(owner) { } -LoginHttpSession::~LoginHttpSession() = default; +template<template<typename> typename SocketImpl> +LoginHttpSession<SocketImpl>::~LoginHttpSession() = default; -void LoginHttpSession::Start() +template<template<typename> typename SocketImpl> +void LoginHttpSession<SocketImpl>::Start() { - std::string ip_address = GetRemoteIpAddress().to_string(); - TC_LOG_TRACE("server.http.session", "{} Accepted connection", GetClientInfo()); + std::string ip_address = this->GetRemoteIpAddress().to_string(); + TC_LOG_TRACE("server.http.session", "{} Accepted connection", this->GetClientInfo()); // Verify that this IP is not in the ip_banned table LoginDatabase.Execute(LoginDatabase.GetPreparedStatement(LOGIN_DEL_EXPIRED_IP_BANS)); @@ -41,11 +44,12 @@ void LoginHttpSession::Start() LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_IP_INFO); stmt->setString(0, ip_address); - _queryProcessor.AddCallback(LoginDatabase.AsyncQuery(stmt) - .WithPreparedCallback([sess = shared_from_this()](PreparedQueryResult result) { sess->CheckIpCallback(std::move(result)); })); + this->_queryProcessor.AddCallback(LoginDatabase.AsyncQuery(stmt) + .WithPreparedCallback([sess = this->shared_from_this()](PreparedQueryResult result) { sess->CheckIpCallback(std::move(result)); })); } -void LoginHttpSession::CheckIpCallback(PreparedQueryResult result) +template<template<typename> typename SocketImpl> +void LoginHttpSession<SocketImpl>::CheckIpCallback(PreparedQueryResult result) { if (result) { @@ -60,21 +64,30 @@ void LoginHttpSession::CheckIpCallback(PreparedQueryResult result) if (banned) { - TC_LOG_DEBUG("server.http.session", "{} tries to log in using banned IP!", GetClientInfo()); - CloseSocket(); + TC_LOG_DEBUG("server.http.session", "{} tries to log in using banned IP!", this->GetClientInfo()); + this->CloseSocket(); return; } } - AsyncHandshake(); + if constexpr (std::is_same_v<BaseSocket, Trinity::Net::Http::SslSocket<LoginHttpSession<Trinity::Net::Http::SslSocket>>>) + { + this->AsyncHandshake(); + } + else + { + this->ResetHttpParser(); + this->AsyncRead(); + } } -Trinity::Net::Http::RequestHandlerResult LoginHttpSession::RequestHandler(Trinity::Net::Http::RequestContext& context) +template<template<typename> typename SocketImpl> +Trinity::Net::Http::RequestHandlerResult LoginHttpSession<SocketImpl>::RequestHandler(Trinity::Net::Http::RequestContext& context) { - return sLoginService.HandleRequest(shared_from_this(), context); + return sLoginService.HandleRequest(_owner.shared_from_this(), context); } -std::shared_ptr<Trinity::Net::Http::SessionState> LoginHttpSession::ObtainSessionState(Trinity::Net::Http::RequestContext& context) const +std::shared_ptr<Trinity::Net::Http::SessionState> ObtainSessionState(Trinity::Net::Http::RequestContext& context, boost::asio::ip::address const& remoteAddress) { using namespace std::string_literals; @@ -92,27 +105,38 @@ std::shared_ptr<Trinity::Net::Http::SessionState> LoginHttpSession::ObtainSessio if (eq != std::string_view::npos) name = cookie.substr(0, eq); - return name == SESSION_ID_COOKIE; + return name == LoginHttpSessionWrapper::SESSION_ID_COOKIE; }); if (sessionIdItr != cookies.end()) { std::string_view value = sessionIdItr->substr(eq + 1); - state = sLoginService.FindAndRefreshSessionState(value, GetRemoteIpAddress()); + state = sLoginService.FindAndRefreshSessionState(value, remoteAddress); } } if (!state) { - state = sLoginService.CreateNewSessionState(GetRemoteIpAddress()); + state = sLoginService.CreateNewSessionState(remoteAddress); std::string_view host = Trinity::Net::Http::ToStdStringView(context.request[boost::beast::http::field::host]); if (std::size_t port = host.find(':'); port != std::string_view::npos) host.remove_suffix(host.length() - port); context.response.insert(boost::beast::http::field::set_cookie, Trinity::StringFormat("{}={}; Path=/bnetserver; Domain={}; Secure; HttpOnly; SameSite=None", - SESSION_ID_COOKIE, boost::uuids::to_string(state->Id), host)); + LoginHttpSessionWrapper::SESSION_ID_COOKIE, boost::uuids::to_string(state->Id), host)); } return state; } + +template class LoginHttpSession<Trinity::Net::Http::SslSocket>; +template class LoginHttpSession<Trinity::Net::Http::Socket>; + +LoginHttpSessionWrapper::LoginHttpSessionWrapper(boost::asio::ip::tcp::socket&& socket) +{ + if (!SslContext::UsesDevWildcardCertificate()) + _socket = std::make_shared<LoginHttpSession<Trinity::Net::Http::SslSocket>>(std::move(socket), *this); + else + _socket = std::make_shared<LoginHttpSession<Trinity::Net::Http::Socket>>(std::move(socket), *this); +} } diff --git a/src/server/bnetserver/REST/LoginHttpSession.h b/src/server/bnetserver/REST/LoginHttpSession.h index 2ee70d5afa5..6bd1ec113d0 100644 --- a/src/server/bnetserver/REST/LoginHttpSession.h +++ b/src/server/bnetserver/REST/LoginHttpSession.h @@ -18,8 +18,10 @@ #ifndef TRINITYCORE_LOGIN_HTTP_SESSION_H #define TRINITYCORE_LOGIN_HTTP_SESSION_H +#include "HttpSocket.h" #include "HttpSslSocket.h" #include "SRP6.h" +#include <variant> namespace Battlenet { @@ -28,12 +30,16 @@ struct LoginSessionState : public Trinity::Net::Http::SessionState std::unique_ptr<Trinity::Crypto::SRP::BnetSRP6Base> Srp; }; -class LoginHttpSession : public Trinity::Net::Http::SslSocket<LoginHttpSession> +class LoginHttpSessionWrapper; +std::shared_ptr<Trinity::Net::Http::SessionState> ObtainSessionState(Trinity::Net::Http::RequestContext& context, boost::asio::ip::address const& remoteAddress); + +template<template<typename> typename SocketImpl> +class LoginHttpSession : public SocketImpl<LoginHttpSession<SocketImpl>> { -public: - static constexpr std::string_view SESSION_ID_COOKIE = "JSESSIONID"; + using BaseSocket = SocketImpl<LoginHttpSession<SocketImpl>>; - explicit LoginHttpSession(boost::asio::ip::tcp::socket&& socket); +public: + explicit LoginHttpSession(boost::asio::ip::tcp::socket&& socket, LoginHttpSessionWrapper& owner); ~LoginHttpSession(); void Start() override; @@ -42,10 +48,41 @@ public: Trinity::Net::Http::RequestHandlerResult RequestHandler(Trinity::Net::Http::RequestContext& context) override; - LoginSessionState* GetSessionState() const { return static_cast<LoginSessionState*>(_state.get()); } + LoginSessionState* GetSessionState() const { return static_cast<LoginSessionState*>(this->_state.get()); } protected: - std::shared_ptr<Trinity::Net::Http::SessionState> ObtainSessionState(Trinity::Net::Http::RequestContext& context) const override; + std::shared_ptr<Trinity::Net::Http::SessionState> ObtainSessionState(Trinity::Net::Http::RequestContext& context) const override + { + return Battlenet::ObtainSessionState(context, this->GetRemoteIpAddress()); + } + + LoginHttpSessionWrapper& _owner; +}; + +class LoginHttpSessionWrapper : public Trinity::Net::Http::AbstractSocket, public std::enable_shared_from_this<LoginHttpSessionWrapper> +{ +public: + static constexpr std::string_view SESSION_ID_COOKIE = "JSESSIONID"; + + explicit LoginHttpSessionWrapper(boost::asio::ip::tcp::socket&& socket); + + void Start() { return std::visit([&](auto&& socket) { return socket->Start(); }, _socket); } + bool Update() { return std::visit([&](auto&& socket) { return socket->Update(); }, _socket); } + boost::asio::ip::address GetRemoteIpAddress() const { return std::visit([&](auto&& socket) { return socket->GetRemoteIpAddress(); }, _socket); } + bool IsOpen() const { return std::visit([&](auto&& socket) { return socket->IsOpen(); }, _socket); } + void CloseSocket() { return std::visit([&](auto&& socket) { return socket->CloseSocket(); }, _socket); } + + void SendResponse(Trinity::Net::Http::RequestContext& context) override { return std::visit([&](auto&& socket) { return socket->SendResponse(context); }, _socket); } + void QueueQuery(QueryCallback&& queryCallback) override { return std::visit([&](auto&& socket) { return socket->QueueQuery(std::move(queryCallback)); }, _socket); } + std::string GetClientInfo() const override { return std::visit([&](auto&& socket) { return socket->GetClientInfo(); }, _socket); } + Optional<boost::uuids::uuid> GetSessionId() const override { return std::visit([&](auto&& socket) { return socket->GetSessionId(); }, _socket); } + LoginSessionState* GetSessionState() const { return std::visit([&](auto&& socket) { return socket->GetSessionState(); }, _socket); } + +private: + std::variant< + std::shared_ptr<LoginHttpSession<Trinity::Net::Http::SslSocket>>, + std::shared_ptr<LoginHttpSession<Trinity::Net::Http::Socket>> + > _socket; }; } #endif // TRINITYCORE_LOGIN_HTTP_SESSION_H diff --git a/src/server/bnetserver/REST/LoginRESTService.cpp b/src/server/bnetserver/REST/LoginRESTService.cpp index 7587510bafc..c9aabb248a3 100644 --- a/src/server/bnetserver/REST/LoginRESTService.cpp +++ b/src/server/bnetserver/REST/LoginRESTService.cpp @@ -25,6 +25,7 @@ #include "IteratorPair.h" #include "ProtobufJSON.h" #include "Resolver.h" +#include "SslContext.h" #include "Timer.h" #include "Util.h" @@ -43,32 +44,32 @@ bool LoginRESTService::StartNetwork(Trinity::Asio::IoContext& ioContext, std::st using Trinity::Net::Http::RequestHandlerFlag; - RegisterHandler(boost::beast::http::verb::get, "/bnetserver/login/", [this](std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) + RegisterHandler(boost::beast::http::verb::get, "/bnetserver/login/", [this](std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) { return HandleGetForm(std::move(session), context); }); - RegisterHandler(boost::beast::http::verb::get, "/bnetserver/gameAccounts/", [](std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) + RegisterHandler(boost::beast::http::verb::get, "/bnetserver/gameAccounts/", [](std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) { return HandleGetGameAccounts(std::move(session), context); }); - RegisterHandler(boost::beast::http::verb::get, "/bnetserver/portal/", [this](std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) + RegisterHandler(boost::beast::http::verb::get, "/bnetserver/portal/", [this](std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) { return HandleGetPortal(std::move(session), context); }); - RegisterHandler(boost::beast::http::verb::post, "/bnetserver/login/", [this](std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) + RegisterHandler(boost::beast::http::verb::post, "/bnetserver/login/", [this](std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) { return HandlePostLogin(std::move(session), context); }, RequestHandlerFlag::DoNotLogRequestContent); - RegisterHandler(boost::beast::http::verb::post, "/bnetserver/login/srp/", [](std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) + RegisterHandler(boost::beast::http::verb::post, "/bnetserver/login/srp/", [](std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) { return HandlePostLoginSrpChallenge(std::move(session), context); }); - RegisterHandler(boost::beast::http::verb::post, "/bnetserver/refreshLoginTicket/", [this](std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) + RegisterHandler(boost::beast::http::verb::post, "/bnetserver/refreshLoginTicket/", [this](std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) { return HandlePostRefreshLoginTicket(std::move(session), context); }); @@ -165,17 +166,18 @@ std::string LoginRESTService::ExtractAuthorization(HttpRequest const& request) return ticket; } -LoginRESTService::RequestHandlerResult LoginRESTService::HandleGetForm(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) const +LoginRESTService::RequestHandlerResult LoginRESTService::HandleGetForm(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) const { JSON::Login::FormInputs form = _formInputs; - form.set_srp_url(Trinity::StringFormat("https://{}:{}/bnetserver/login/srp/", GetHostnameForClient(session->GetRemoteIpAddress()), _port)); + form.set_srp_url(Trinity::StringFormat("http{}://{}:{}/bnetserver/login/srp/", !SslContext::UsesDevWildcardCertificate() ? "s" : "", + GetHostnameForClient(session->GetRemoteIpAddress()), _port)); context.response.set(boost::beast::http::field::content_type, "application/json;charset=utf-8"); context.response.body() = ::JSON::Serialize(form); return RequestHandlerResult::Handled; } -LoginRESTService::RequestHandlerResult LoginRESTService::HandleGetGameAccounts(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) +LoginRESTService::RequestHandlerResult LoginRESTService::HandleGetGameAccounts(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) { std::string ticket = ExtractAuthorization(context.request); if (ticket.empty()) @@ -224,14 +226,14 @@ LoginRESTService::RequestHandlerResult LoginRESTService::HandleGetGameAccounts(s return RequestHandlerResult::Async; } -LoginRESTService::RequestHandlerResult LoginRESTService::HandleGetPortal(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) const +LoginRESTService::RequestHandlerResult LoginRESTService::HandleGetPortal(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) const { context.response.set(boost::beast::http::field::content_type, "text/plain"); context.response.body() = Trinity::StringFormat("{}:{}", GetHostnameForClient(session->GetRemoteIpAddress()), sConfigMgr->GetIntDefault("BattlenetPort", 1119)); return RequestHandlerResult::Handled; } -LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostLogin(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) const +LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostLogin(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) const { std::shared_ptr<JSON::Login::LoginForm> loginForm = std::make_shared<JSON::Login::LoginForm>(); if (!::JSON::Deserialize(context.request.body(), loginForm.get())) @@ -395,7 +397,7 @@ LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostLogin(std::sh return RequestHandlerResult::Async; } -LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostLoginSrpChallenge(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) +LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostLoginSrpChallenge(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) { JSON::Login::LoginForm loginForm; if (!::JSON::Deserialize(context.request.body(), &loginForm)) @@ -482,7 +484,7 @@ LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostLoginSrpChall return RequestHandlerResult::Async; } -LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostRefreshLoginTicket(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) const +LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostRefreshLoginTicket(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) const { std::string ticket = ExtractAuthorization(context.request); if (ticket.empty()) diff --git a/src/server/bnetserver/REST/LoginRESTService.h b/src/server/bnetserver/REST/LoginRESTService.h index 5683c262590..bcc99808505 100644 --- a/src/server/bnetserver/REST/LoginRESTService.h +++ b/src/server/bnetserver/REST/LoginRESTService.h @@ -42,7 +42,7 @@ enum class BanMode BAN_ACCOUNT = 1 }; -class LoginRESTService : public Trinity::Net::Http::HttpService<LoginHttpSession> +class LoginRESTService : public Trinity::Net::Http::HttpService<LoginHttpSessionWrapper> { public: using RequestHandlerResult = Trinity::Net::Http::RequestHandlerResult; @@ -67,13 +67,13 @@ private: static std::string ExtractAuthorization(HttpRequest const& request); - RequestHandlerResult HandleGetForm(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) const; - static RequestHandlerResult HandleGetGameAccounts(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context); - RequestHandlerResult HandleGetPortal(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) const; + RequestHandlerResult HandleGetForm(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) const; + static RequestHandlerResult HandleGetGameAccounts(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context); + RequestHandlerResult HandleGetPortal(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) const; - RequestHandlerResult HandlePostLogin(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) const; - static RequestHandlerResult HandlePostLoginSrpChallenge(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context); - RequestHandlerResult HandlePostRefreshLoginTicket(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) const; + RequestHandlerResult HandlePostLogin(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) const; + static RequestHandlerResult HandlePostLoginSrpChallenge(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context); + RequestHandlerResult HandlePostRefreshLoginTicket(std::shared_ptr<LoginHttpSessionWrapper> session, HttpRequestContext& context) const; static std::unique_ptr<Trinity::Crypto::SRP::BnetSRP6Base> CreateSrpImplementation(SrpVersion version, SrpHashFunction hashFunction, std::string const& username, Trinity::Crypto::SRP::Salt const& salt, Trinity::Crypto::SRP::Verifier const& verifier); diff --git a/src/server/bnetserver/Server/Session.cpp b/src/server/bnetserver/Server/Session.cpp index b450df14e1d..c94ee6e3e56 100644 --- a/src/server/bnetserver/Server/Session.cpp +++ b/src/server/bnetserver/Server/Session.cpp @@ -260,7 +260,8 @@ uint32 Battlenet::Session::HandleLogon(authentication::v1::LogonRequest const* l challenge::v1::ChallengeExternalRequest externalChallenge; externalChallenge.set_payload_type("web_auth_url"); - externalChallenge.set_payload(Trinity::StringFormat("https://{}:{}/bnetserver/login/", sLoginService.GetHostnameForClient(GetRemoteIpAddress()), sLoginService.GetPort())); + externalChallenge.set_payload(Trinity::StringFormat("http{}://{}:{}/bnetserver/login/", !SslContext::UsesDevWildcardCertificate() ? "s" : "", + sLoginService.GetHostnameForClient(GetRemoteIpAddress()), sLoginService.GetPort())); Service<challenge::v1::ChallengeListener>(this).OnExternalChallenge(&externalChallenge); return ERROR_OK; } diff --git a/src/server/bnetserver/Server/SslContext.cpp b/src/server/bnetserver/Server/SslContext.cpp index 92d95f24cc5..52daff1645d 100644 --- a/src/server/bnetserver/Server/SslContext.cpp +++ b/src/server/bnetserver/Server/SslContext.cpp @@ -24,6 +24,8 @@ #include <openssl/store.h> #include <openssl/ui.h> +bool Battlenet::SslContext::_usesDevWildcardCertificate = false; + namespace { auto CreatePasswordUiMethodFromPemCallback(::pem_password_cb* callback) @@ -114,6 +116,37 @@ bool Battlenet::SslContext::Initialize() if (sk_X509_num(certs) > 0) { X509* cert = sk_X509_shift(certs); + + _usesDevWildcardCertificate = [&] + { + X509_NAME const* nm = X509_get_subject_name(cert); + int32 lastpos = -1; + while (true) + { + lastpos = X509_NAME_get_index_by_NID(nm, NID_commonName, lastpos); + if (lastpos == -1) + break; + + X509_NAME_ENTRY* e = X509_NAME_get_entry(nm, lastpos); + if (!e) + continue; + + ASN1_STRING* text = X509_NAME_ENTRY_get_data(e); + if (!text) + continue; + + unsigned char* utf8TextRaw = nullptr; + if (int utf8Length = ASN1_STRING_to_UTF8(&utf8TextRaw, text); utf8Length >= 0) + { + auto utf8Text = Trinity::make_unique_ptr_with_deleter(utf8TextRaw, [](unsigned char* ptr) { ::OPENSSL_free(ptr); }); + if (std::string_view(reinterpret_cast<char const*>(utf8Text.get()), utf8Length) == "*.*") + return true; + } + } + + return false; + }(); + SSL_CTX_use_cert_and_key(nativeContext, cert, key, certs, 1); } diff --git a/src/server/bnetserver/Server/SslContext.h b/src/server/bnetserver/Server/SslContext.h index 470deffd97e..330c0db221b 100644 --- a/src/server/bnetserver/Server/SslContext.h +++ b/src/server/bnetserver/Server/SslContext.h @@ -28,6 +28,11 @@ namespace Battlenet static bool Initialize(); static boost::asio::ssl::context& instance(); + + static bool UsesDevWildcardCertificate() { return _usesDevWildcardCertificate; } + + private: + static bool _usesDevWildcardCertificate; }; } |
