diff options
author | Shauren <shauren.trinity@gmail.com> | 2024-01-18 00:31:57 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2024-01-18 00:31:57 +0100 |
commit | 5cc1b97fc1430f07d8942ae9f87fd5ad9708db59 (patch) | |
tree | ff17b7c7d6b0b8b43a030e246db185c0d1d048d1 /src/server/bnetserver | |
parent | ac7e718511e1aea7d7e8fa44537a757db079f98d (diff) |
Core/Bnet: Added SRP http endpoints10.2.0.52808
Diffstat (limited to 'src/server/bnetserver')
-rw-r--r-- | src/server/bnetserver/REST/LoginRESTService.cpp | 114 | ||||
-rw-r--r-- | src/server/bnetserver/REST/LoginRESTService.h | 1 |
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, |