aboutsummaryrefslogtreecommitdiff
path: root/src/server/bnetserver
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2024-01-18 00:31:57 +0100
committerShauren <shauren.trinity@gmail.com>2024-01-18 00:31:57 +0100
commit5cc1b97fc1430f07d8942ae9f87fd5ad9708db59 (patch)
treeff17b7c7d6b0b8b43a030e246db185c0d1d048d1 /src/server/bnetserver
parentac7e718511e1aea7d7e8fa44537a757db079f98d (diff)
Core/Bnet: Added SRP http endpoints10.2.0.52808
Diffstat (limited to 'src/server/bnetserver')
-rw-r--r--src/server/bnetserver/REST/LoginRESTService.cpp114
-rw-r--r--src/server/bnetserver/REST/LoginRESTService.h1
2 files changed, 112 insertions, 3 deletions
diff --git a/src/server/bnetserver/REST/LoginRESTService.cpp b/src/server/bnetserver/REST/LoginRESTService.cpp
index 9ec759d98a5..7587510bafc 100644
--- a/src/server/bnetserver/REST/LoginRESTService.cpp
+++ b/src/server/bnetserver/REST/LoginRESTService.cpp
@@ -63,6 +63,11 @@ bool LoginRESTService::StartNetwork(Trinity::Asio::IoContext& ioContext, std::st
return HandlePostLogin(std::move(session), context);
}, RequestHandlerFlag::DoNotLogRequestContent);
+ RegisterHandler(boost::beast::http::verb::post, "/bnetserver/login/srp/", [](std::shared_ptr<LoginHttpSession> 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)
{
return HandlePostRefreshLoginTicket(std::move(session), context);
@@ -160,10 +165,13 @@ 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<LoginHttpSession> session, HttpRequestContext& context) const
{
+ JSON::Login::FormInputs form = _formInputs;
+ form.set_srp_url(Trinity::StringFormat("https://{}:{}/bnetserver/login/srp/", GetHostnameForClient(session->GetRemoteIpAddress()), _port));
+
context.response.set(boost::beast::http::field::content_type, "application/json;charset=utf-8");
- context.response.body() = ::JSON::Serialize(_formInputs);
+ context.response.body() = ::JSON::Serialize(form);
return RequestHandlerResult::Handled;
}
@@ -271,6 +279,7 @@ LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostLogin(std::sh
std::string login(getInputValue(loginForm.get(), "account_name"));
Utf8ToUpperOnlyLatin(login);
bool passwordCorrect = false;
+ Optional<std::string> serverM2;
Field* fields = result->Fetch();
uint32 accountId = fields[0].GetUInt32();
@@ -288,6 +297,16 @@ LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostLogin(std::sh
passwordCorrect = session->GetSessionState()->Srp->CheckCredentials(srpUsername, password);
}
+ else
+ {
+ BigNumber A(getInputValue(loginForm.get(), "public_A"));
+ BigNumber M1(getInputValue(loginForm.get(), "client_evidence_M1"));
+ if (Optional<BigNumber> sessionKey = session->GetSessionState()->Srp->VerifyClientEvidence(A, M1))
+ {
+ passwordCorrect = true;
+ serverM2 = session->GetSessionState()->Srp->CalculateServerEvidence(A, M1, *sessionKey).AsHexStr();
+ }
+ }
uint32 failedLogins = fields[4].GetUInt32();
std::string loginTicket = fields[5].GetString();
@@ -359,11 +378,13 @@ LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostLogin(std::sh
stmt->setString(0, loginTicket);
stmt->setUInt32(1, time(nullptr) + _loginTicketDuration);
stmt->setUInt32(2, accountId);
- callback.WithPreparedCallback([session, context = std::move(context), loginTicket = std::move(loginTicket)](PreparedQueryResult) mutable
+ callback.WithPreparedCallback([session, context = std::move(context), loginTicket = std::move(loginTicket), serverM2 = std::move(serverM2)](PreparedQueryResult) mutable
{
JSON::Login::LoginResult loginResult;
loginResult.set_authentication_state(JSON::Login::DONE);
loginResult.set_login_ticket(loginTicket);
+ if (serverM2)
+ loginResult.set_server_evidence_m2(*serverM2);
context.response.set(boost::beast::http::field::content_type, "application/json;charset=utf-8");
context.response.body() = ::JSON::Serialize(loginResult);
@@ -374,6 +395,93 @@ LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostLogin(std::sh
return RequestHandlerResult::Async;
}
+LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostLoginSrpChallenge(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context)
+{
+ JSON::Login::LoginForm loginForm;
+ if (!::JSON::Deserialize(context.request.body(), &loginForm))
+ {
+ JSON::Login::LoginResult loginResult;
+ loginResult.set_authentication_state(JSON::Login::LOGIN);
+ loginResult.set_error_code("UNABLE_TO_DECODE");
+ loginResult.set_error_message("There was an internal error while connecting to Battle.net. Please try again later.");
+
+ context.response.result(boost::beast::http::status::bad_request);
+ context.response.set(boost::beast::http::field::content_type, "application/json;charset=utf-8");
+ context.response.body() = ::JSON::Serialize(loginResult);
+ session->SendResponse(context);
+
+ return RequestHandlerResult::Handled;
+ }
+
+ std::string login;
+
+ for (int32 i = 0; i < loginForm.inputs_size(); ++i)
+ if (loginForm.inputs(i).input_id() == "account_name")
+ login = loginForm.inputs(i).value();
+
+ Utf8ToUpperOnlyLatin(login);
+
+ LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHECK_PASSWORD_BY_EMAIL);
+ stmt->setString(0, login);
+
+ session->QueueQuery(LoginDatabase.AsyncQuery(stmt)
+ .WithPreparedCallback([session, context = std::move(context), login = std::move(login)](PreparedQueryResult result) mutable
+ {
+ if (!result)
+ {
+ JSON::Login::LoginResult loginResult;
+ loginResult.set_authentication_state(JSON::Login::DONE);
+ context.response.set(boost::beast::http::field::content_type, "application/json;charset=utf-8");
+ context.response.body() = ::JSON::Serialize(loginResult);
+ session->SendResponse(context);
+ return;
+ }
+
+ Field* fields = result->Fetch();
+ SrpVersion version = SrpVersion(fields[0].GetInt8());
+ SrpHashFunction hashFunction = SrpHashFunction::Sha256;
+ std::string srpUsername = ByteArrayToHexStr(Trinity::Crypto::SHA256::GetDigestOf(login));
+ Trinity::Crypto::SRP::Salt s = fields[1].GetBinary<Trinity::Crypto::SRP::SALT_LENGTH>();
+ Trinity::Crypto::SRP::Verifier v = fields[2].GetBinary();
+
+ session->GetSessionState()->Srp = CreateSrpImplementation(version, hashFunction, srpUsername, s, v);
+ if (!session->GetSessionState()->Srp)
+ {
+ context.response.result(boost::beast::http::status::internal_server_error);
+ session->SendResponse(context);
+ return;
+ }
+
+ JSON::Login::SrpLoginChallenge challenge;
+ challenge.set_version(session->GetSessionState()->Srp->GetVersion());
+ challenge.set_iterations(session->GetSessionState()->Srp->GetXIterations());
+ challenge.set_modulus(session->GetSessionState()->Srp->GetN().AsHexStr());
+ challenge.set_generator(session->GetSessionState()->Srp->Getg().AsHexStr());
+ challenge.set_hash_function([=]
+ {
+ switch (hashFunction)
+ {
+ case SrpHashFunction::Sha256:
+ return "SHA-256";
+ case SrpHashFunction::Sha512:
+ return "SHA-512";
+ default:
+ break;
+ }
+ return "";
+ }());
+ challenge.set_username(srpUsername);
+ challenge.set_salt(ByteArrayToHexStr(session->GetSessionState()->Srp->s));
+ challenge.set_public_b(session->GetSessionState()->Srp->B.AsHexStr());
+
+ context.response.set(boost::beast::http::field::content_type, "application/json;charset=utf-8");
+ context.response.body() = ::JSON::Serialize(challenge);
+ session->SendResponse(context);
+ }));
+
+ return RequestHandlerResult::Async;
+}
+
LoginRESTService::RequestHandlerResult LoginRESTService::HandlePostRefreshLoginTicket(std::shared_ptr<LoginHttpSession> session, HttpRequestContext& context) const
{
std::string ticket = ExtractAuthorization(context.request);
diff --git a/src/server/bnetserver/REST/LoginRESTService.h b/src/server/bnetserver/REST/LoginRESTService.h
index 9d48f1d2710..5683c262590 100644
--- a/src/server/bnetserver/REST/LoginRESTService.h
+++ b/src/server/bnetserver/REST/LoginRESTService.h
@@ -72,6 +72,7 @@ private:
RequestHandlerResult HandleGetPortal(std::shared_ptr<LoginHttpSession> 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;
static std::unique_ptr<Trinity::Crypto::SRP::BnetSRP6Base> CreateSrpImplementation(SrpVersion version, SrpHashFunction hashFunction,