void Battlenet::Session::HandleResumeRequest(Authentication::ResumeRequest const& resumeRequest) { if (_queryCallback) { Authentication::ResumeResponse* logonResponse = new Authentication::ResumeResponse(); logonResponse->SetAuthResult(AUTH_LOGON_TOO_FAST); AsyncWrite(logonResponse); TC_LOG_DEBUG("session", "[Battlenet::ResumeRequest] %s attempted to log too quick after previous attempt!", GetClientInfo().c_str()); return; } std::string login = resumeRequest.Login; _locale = resumeRequest.Locale; _os = resumeRequest.Platform; auto baseComponent = std::find_if(resumeRequest.Components.begin(), resumeRequest.Components.end(), [](Component const& c) { return c.Program == "base"; }); if (baseComponent != resumeRequest.Components.end()) _build = baseComponent->Build; Utf8ToUpperOnlyLatin(login); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_RECONNECT_INFO); stmt->setString(0, login); stmt->setString(1, resumeRequest.GameAccountName); _queryCallback = std::bind(&Battlenet::Session::HandleResumeRequestCallback, this, std::placeholders::_1); _queryFuture = LoginDatabase.AsyncQuery(stmt); }
void Battlenet::Session::HandleResumeRequest(Authentication::ResumeRequest const& resumeRequest) { _accountName = resumeRequest.Login; _locale = resumeRequest.Locale; _os = resumeRequest.Platform; auto baseComponent = std::find_if(resumeRequest.Components.begin(), resumeRequest.Components.end(), [](Component const& c) { return c.Program == "base"; }); if (baseComponent != resumeRequest.Components.end()) _build = baseComponent->Build; Utf8ToUpperOnlyLatin(_accountName); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_RECONNECT_INFO); stmt->setString(0, _accountName); stmt->setString(1, resumeRequest.GameAccountName); PreparedQueryResult result = LoginDatabase.Query(stmt); if (!result) { Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse(); resumeResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); AsyncWrite(resumeResponse); return; } Field* fields = result->Fetch(); _accountId = fields[0].GetUInt32(); K.SetHexStr(fields[1].GetString().c_str()); _gameAccountId = fields[2].GetUInt32(); _gameAccountName = resumeRequest.GameAccountName; ModuleInfo* thumbprint = sModuleMgr->CreateModule(_os, "Thumbprint"); ModuleInfo* resume = sModuleMgr->CreateModule(_os, "Resume"); BitStream resumeData; uint8 state = 0; _reconnectProof.SetRand(16 * 8); resumeData.WriteBytes(&state, 1); resumeData.WriteBytes(_reconnectProof.AsByteArray().get(), 16); resume->DataSize = resumeData.GetSize(); resume->Data = new uint8[resume->DataSize]; memcpy(resume->Data, resumeData.GetBuffer(), resume->DataSize); _modulesWaitingForData.push(MODULE_RESUME); Authentication::ProofRequest* proofRequest = new Authentication::ProofRequest(); proofRequest->Modules.push_back(thumbprint); proofRequest->Modules.push_back(resume); AsyncWrite(proofRequest); }
void Battlenet::Session::HandleResumeRequestCallback(PreparedQueryResult result) { if (!result) { Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse(); resumeResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); AsyncWrite(resumeResponse); return; } Field* fields = result->Fetch(); _accountInfo->LoadResult(fields); K.SetHexStr(fields[8].GetString().c_str()); _gameAccounts.resize(1); _gameAccountInfo = &_gameAccounts[0]; _gameAccountInfo->LoadResult(fields + 9); ModuleInfo* thumbprint = sModuleMgr->CreateModule(_os, "Thumbprint"); ModuleInfo* resume = sModuleMgr->CreateModule(_os, "Resume"); BitStream resumeData; uint8 state = 0; _reconnectProof.SetRand(16 * 8); resumeData.WriteBytes(&state, 1); resumeData.WriteBytes(_reconnectProof.AsByteArray().get(), 16); resume->DataSize = resumeData.GetSize(); resume->Data = new uint8[resume->DataSize]; memcpy(resume->Data, resumeData.GetBuffer(), resume->DataSize); _modulesWaitingForData.push(MODULE_RESUME); Authentication::ProofRequest* proofRequest = new Authentication::ProofRequest(); proofRequest->Modules.push_back(thumbprint); proofRequest->Modules.push_back(resume); AsyncWrite(proofRequest); }
bool Battlenet::Session::HandleResumeModule(BitStream* dataStream, ServerPacket** response) { if (dataStream->Read<uint8>(8) != 1) { Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse(); resumeResponse->SetAuthResult(AUTH_CORRUPTED_MODULE); ReplaceResponse(response, resumeResponse); return false; } static uint8 const ResumeClient = 0; static uint8 const ResumeServer = 1; std::unique_ptr<uint8[]> clientChallenge = dataStream->ReadBytes(16); std::unique_ptr<uint8[]> clientProof = dataStream->ReadBytes(32); std::unique_ptr<uint8[]> serverChallenge = _reconnectProof.AsByteArray(16); std::unique_ptr<uint8[]> sessionKey = K.AsByteArray(64); HmacSha256 clientPart(64, sessionKey.get()); clientPart.UpdateData(&ResumeClient, 1); clientPart.UpdateData(clientChallenge.get(), 16); clientPart.UpdateData(serverChallenge.get(), 16); clientPart.Finalize(); HmacSha256 serverPart(64, sessionKey.get()); serverPart.UpdateData(&ResumeServer, 1); serverPart.UpdateData(serverChallenge.get(), 16); serverPart.UpdateData(clientChallenge.get(), 16); serverPart.Finalize(); uint8 newSessionKey[64]; memcpy(&newSessionKey[0], clientPart.GetDigest(), clientPart.GetLength()); memcpy(&newSessionKey[32], serverPart.GetDigest(), serverPart.GetLength()); K.SetBinary(newSessionKey, 64); HmacSha256 proof(64, newSessionKey); proof.UpdateData(&ResumeClient, 1); proof.UpdateData(clientChallenge.get(), 16); proof.UpdateData(serverChallenge.get(), 16); proof.Finalize(); if (memcmp(proof.GetDigest(), clientProof.get(), serverPart.GetLength())) { PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_FAILED_LOGINS); stmt->setString(0, _accountInfo->Login); LoginDatabase.Execute(stmt); TC_LOG_DEBUG("session", "[Battlenet::Resume] %s attempted to reconnect with invalid password!", GetClientInfo().c_str()); Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse(); resumeResponse->SetAuthResult(AUTH_UNKNOWN_ACCOUNT); ReplaceResponse(response, resumeResponse); return false; } PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_SESSION_KEY); stmt->setString(0, K.AsHexStr()); stmt->setBool(1, true); stmt->setUInt32(2, _accountInfo->Id); LoginDatabase.Execute(stmt); HmacSha256 serverProof(64, newSessionKey); serverProof.UpdateData(&ResumeServer, 1); serverProof.UpdateData(serverChallenge.get(), 16); serverProof.UpdateData(clientChallenge.get(), 16); serverProof.Finalize(); ModuleInfo* resume = sModuleMgr->CreateModule(_os, "Resume"); BitStream resumeData; uint8 state = 2; resumeData.WriteBytes(&state, 1); resumeData.WriteBytes(serverProof.GetDigest(), serverProof.GetLength()); resume->DataSize = resumeData.GetSize(); resume->Data = new uint8[resume->DataSize]; memcpy(resume->Data, resumeData.GetBuffer(), resume->DataSize); Authentication::ResumeResponse* resumeResponse = new Authentication::ResumeResponse(); resumeResponse->Modules.push_back(resume); ReplaceResponse(response, resumeResponse); _authed = true; sSessionMgr.AddSession(this); return true; }