aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2014-06-01 13:56:36 +0200
committerShauren <shauren.trinity@gmail.com>2014-06-01 13:56:36 +0200
commitbdd6e9aa8aeeda439a2a3a8f23bc21bb04699133 (patch)
tree0ea7adf7f6418ac57a3a3551108235930fa4196d /src
parentdc5c5ef6361f3f4dbb5fc9b5a755951c83f954fa (diff)
Core/Battle.net: Implemented reconnects
Diffstat (limited to 'src')
-rw-r--r--src/server/authserver/Server/BattlenetPackets.cpp149
-rw-r--r--src/server/authserver/Server/BattlenetPackets.h54
-rw-r--r--src/server/authserver/Server/BattlenetSocket.cpp173
-rw-r--r--src/server/authserver/Server/BattlenetSocket.h7
-rw-r--r--src/server/shared/Database/Implementation/LoginDatabase.cpp2
-rw-r--r--src/server/shared/Database/Implementation/LoginDatabase.h2
6 files changed, 361 insertions, 26 deletions
diff --git a/src/server/authserver/Server/BattlenetPackets.cpp b/src/server/authserver/Server/BattlenetPackets.cpp
index 99e3fa10b14..471a6128c4c 100644
--- a/src/server/authserver/Server/BattlenetPackets.cpp
+++ b/src/server/authserver/Server/BattlenetPackets.cpp
@@ -57,9 +57,6 @@ void Battlenet::AuthChallenge::Read()
if (_stream.Read<uint32>(1))
Login = _stream.ReadString(9, 3);
-
- if (GetHeader().Opcode == CMSG_AUTH_CHALLENGE_NEW)
- _stream.FinishReading();
}
std::string Battlenet::AuthChallenge::ToString() const
@@ -75,6 +72,40 @@ std::string Battlenet::AuthChallenge::ToString() const
return stream.str();
}
+void Battlenet::AuthResumeInfo::Read()
+{
+ Program = _stream.ReadFourCC();
+ Platform = _stream.ReadFourCC();
+ Locale = _stream.ReadFourCC();
+
+ Components.resize(_stream.Read<uint32>(6));
+ for (size_t i = 0; i < Components.size(); ++i)
+ {
+ Component& component = Components[i];
+ component.Program = _stream.ReadFourCC();
+ component.Platform = _stream.ReadFourCC();
+ component.Build = _stream.Read<uint32>(32);
+ }
+
+ Login = _stream.ReadString(9, 3);
+ Region = _stream.Read<uint8>(8);
+ GameAccountName = _stream.ReadString(5, 1);
+}
+
+std::string Battlenet::AuthResumeInfo::ToString() const
+{
+ std::ostringstream stream;
+ stream << "Battlenet::AuthReconnect Program: " << Program << ", Platform: " << Platform << ", Locale: " << Locale;
+ for (Component const& component : Components)
+ stream << std::endl << "Battlenet::Component Program: " << component.Program << ", Platform: " << component.Platform << ", Build: " << component.Build;
+
+ stream << std::endl << "Battlenet::AuthReconnect Login: " << Login;
+ stream << std::endl << "Battlenet::AuthReconnect Region: " << uint32(Region);
+ stream << std::endl << "Battlenet::AuthReconnect GameAccountName: " << GameAccountName;
+
+ return stream.str();
+}
+
Battlenet::ProofRequest::~ProofRequest()
{
for (size_t i = 0; i < Modules.size(); ++i)
@@ -134,6 +165,12 @@ std::string Battlenet::ProofResponse::ToString() const
return stream.str();
}
+Battlenet::AuthComplete::~AuthComplete()
+{
+ for (ModuleInfo* m : Modules)
+ delete m;
+}
+
void Battlenet::AuthComplete::Write()
{
_stream.Write(Result != 0, 1);
@@ -142,12 +179,12 @@ void Battlenet::AuthComplete::Write()
_stream.Write(Modules.size(), 3);
for (size_t i = 0; i < Modules.size(); ++i)
{
- ModuleInfo& info = Modules[i];
- _stream.WriteBytes(info.Type.c_str(), 4);
- _stream.WriteFourCC(info.Region);
- _stream.WriteBytes(info.ModuleId, 32);
- _stream.Write(info.DataSize, 10);
- _stream.WriteBytes(info.Data, info.DataSize);
+ ModuleInfo* info = Modules[i];
+ _stream.WriteBytes(info->Type.c_str(), 4);
+ _stream.WriteFourCC(info->Region);
+ _stream.WriteBytes(info->ModuleId, 32);
+ _stream.Write(info->DataSize, 10);
+ _stream.WriteBytes(info->Data, info->DataSize);
}
_stream.Write(PingTimeout + std::numeric_limits<int32>::min(), 32);
@@ -168,10 +205,10 @@ void Battlenet::AuthComplete::Write()
_stream.Write(GameAccountId, 32);
_stream.Write(2, 8);
_stream.Write(0, 64);
- _stream.Write(2, 8);
+ _stream.Write(2, 8);
_stream.WriteString(GameAccountName, 5, -1);
- _stream.Write(AccountFlags, 64);
+ _stream.Write(GameAccountFlags, 64);
_stream.Write(0, 32);
}
@@ -180,12 +217,10 @@ void Battlenet::AuthComplete::Write()
_stream.Write(!Modules.empty(), 1);
if (!Modules.empty())
{
- ModuleInfo& info = Modules[0];
- _stream.WriteBytes(info.Type.c_str(), 4);
- _stream.WriteFourCC(info.Region);
- _stream.WriteBytes(info.ModuleId, 32);
- _stream.Write(info.DataSize, 10);
- _stream.WriteBytes(info.Data, info.DataSize);
+ ModuleInfo* info = Modules[0];
+ _stream.WriteBytes(info->Type.c_str(), 4);
+ _stream.WriteFourCC(info->Region);
+ _stream.WriteBytes(info->ModuleId, 32);
}
_stream.Write(ErrorType, 2);
@@ -199,7 +234,15 @@ void Battlenet::AuthComplete::Write()
std::string Battlenet::AuthComplete::ToString() const
{
- return "Battlenet::AuthComplete";
+ std::ostringstream stream;
+ stream << "Battlenet::AuthComplete AuthResult " << Result << " PingTimeout " << PingTimeout << " Threshold " << Threshold << " Rate " << Rate
+ << " FirstName " << FirstName << " LastName " << LastName << " GameAccountId " << GameAccountId << " GameAccountName " << GameAccountName
+ << " GameAccountFlags " << GameAccountFlags << " Modules " << Modules.size();
+
+ for (ModuleInfo const* module : Modules)
+ stream << std::endl << "Battlenet::ModuleInfo Locale " << module->Region.c_str() << ", ModuleId " << ByteArrayToHexStr(module->ModuleId, 32) << ", DataSize " << module->DataSize << ", Data " << ByteArrayToHexStr(module->Data, module->DataSize);
+
+ return stream.str();
}
void Battlenet::AuthComplete::SetAuthResult(AuthResult result)
@@ -208,6 +251,76 @@ void Battlenet::AuthComplete::SetAuthResult(AuthResult result)
Result = result;
}
+Battlenet::AuthResume::~AuthResume()
+{
+ for (ModuleInfo* m : Modules)
+ delete m;
+}
+
+void Battlenet::AuthResume::Write()
+{
+ _stream.Write(Result != 0, 1);
+ if (Result == 0)
+ {
+ _stream.Write(Modules.size(), 3);
+ for (size_t i = 0; i < Modules.size(); ++i)
+ {
+ ModuleInfo* info = Modules[i];
+ _stream.WriteBytes(info->Type.c_str(), 4);
+ _stream.WriteFourCC(info->Region);
+ _stream.WriteBytes(info->ModuleId, 32);
+ _stream.Write(info->DataSize, 10);
+ _stream.WriteBytes(info->Data, info->DataSize);
+ }
+
+ _stream.Write(PingTimeout + std::numeric_limits<int32>::min(), 32);
+ _stream.Write(1, 1);
+ // if written == 1
+ {
+ _stream.Write(1, 1);
+ // if written == 1
+ {
+ _stream.Write(Threshold, 32);
+ _stream.Write(Rate, 32);
+ }
+ }
+ }
+ else
+ {
+ _stream.Write(!Modules.empty(), 1);
+ if (!Modules.empty())
+ {
+ ModuleInfo* info = Modules[0];
+ _stream.WriteBytes(info->Type.c_str(), 4);
+ _stream.WriteFourCC(info->Region);
+ _stream.WriteBytes(info->ModuleId, 32);
+ }
+
+ _stream.Write(ErrorType, 2);
+ if (ErrorType == 1)
+ {
+ _stream.Write(Result, 16);
+ _stream.Write(0x80000000, 32);
+ }
+ }
+}
+
+std::string Battlenet::AuthResume::ToString() const
+{
+ std::ostringstream stream;
+ stream << "Battlenet::AuthResume AuthResult " << Result << " PingTimeout " << PingTimeout << " Threshold " << Threshold << " Rate " << Rate << " Modules " << Modules.size();
+ for (ModuleInfo const* module : Modules)
+ stream << std::endl << "Battlenet::ModuleInfo Locale " << module->Region.c_str() << ", ModuleId " << ByteArrayToHexStr(module->ModuleId, 32) << ", DataSize " << module->DataSize << ", Data " << ByteArrayToHexStr(module->Data, module->DataSize);
+
+ return stream.str();
+}
+
+void Battlenet::AuthResume::SetAuthResult(AuthResult result)
+{
+ ErrorType = result != AUTH_OK ? 1 : 0;
+ Result = result;
+}
+
Battlenet::RealmCharacterCounts::~RealmCharacterCounts()
{
for (ServerPacket* realmData : RealmData)
diff --git a/src/server/authserver/Server/BattlenetPackets.h b/src/server/authserver/Server/BattlenetPackets.h
index 9acc707bd10..d790760ea24 100644
--- a/src/server/authserver/Server/BattlenetPackets.h
+++ b/src/server/authserver/Server/BattlenetPackets.h
@@ -41,9 +41,9 @@ namespace Battlenet
CMSG_AUTH_CHALLENGE = 0x0,
CMSG_AUTH_RECONNECT = 0x1,
CMSG_AUTH_PROOF_RESPONSE = 0x2,
- CMSG_AUTH_CHALLENGE_NEW = 0x9, // MoP
SMSG_AUTH_COMPLETE = 0x0,
+ SMSG_AUTH_RESUME = 0x1,
SMSG_AUTH_PROOF_REQUEST = 0x2
};
@@ -51,6 +51,7 @@ namespace Battlenet
{
CMSG_PING = 0x0,
CMSG_ENABLE_ENCRYPTION = 0x5,
+ CMSG_DISCONNECT = 0x6,
CMSG_INVALID_PACKET = 0x9,
SMSG_PONG = 0x0
@@ -141,7 +142,7 @@ namespace Battlenet
public:
AuthChallenge(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
{
- ASSERT(header.Channel == AUTHENTICATION && (header.Opcode == CMSG_AUTH_CHALLENGE || header.Opcode == CMSG_AUTH_CHALLENGE_NEW) && "Invalid packet header for AuthChallenge");
+ ASSERT(header == PacketHeader(CMSG_AUTH_CHALLENGE, AUTHENTICATION) && "Invalid packet header for AuthChallenge");
}
void Read() override;
@@ -154,6 +155,26 @@ namespace Battlenet
std::string Login;
};
+ class AuthResumeInfo final : public ClientPacket
+ {
+ public:
+ AuthResumeInfo(PacketHeader const& header, BitStream& stream) : ClientPacket(header, stream)
+ {
+ ASSERT(header == PacketHeader(CMSG_AUTH_RECONNECT, AUTHENTICATION) && "Invalid packet header for AuthResumeInfo");
+ }
+
+ void Read() override;
+ std::string ToString() const override;
+
+ std::string Program;
+ std::string Platform;
+ std::string Locale;
+ std::vector<Component> Components;
+ std::string Login;
+ uint8 Region;
+ std::string GameAccountName;
+ };
+
class ProofRequest final : public ServerPacket
{
public:
@@ -191,10 +212,12 @@ namespace Battlenet
{
}
+ ~AuthComplete();
+
void Write() override;
std::string ToString() const override;
- std::vector<ModuleInfo> Modules;
+ std::vector<ModuleInfo*> Modules;
void SetAuthResult(AuthResult result);
AuthResult Result;
uint32 ErrorType;
@@ -206,7 +229,30 @@ namespace Battlenet
std::string LastName;
uint32 GameAccountId;
std::string GameAccountName;
- uint64 AccountFlags;
+ uint64 GameAccountFlags;
+ };
+
+ class AuthResume final : public ServerPacket
+ {
+ public:
+ AuthResume() : ServerPacket(PacketHeader(SMSG_AUTH_RESUME, AUTHENTICATION)),
+ Result(AUTH_OK), ErrorType(0), PingTimeout(120000), Threshold(25000000), Rate(1000)
+ {
+ }
+
+ ~AuthResume();
+
+ void Write() override;
+ std::string ToString() const override;
+
+ std::vector<ModuleInfo*> Modules;
+ void SetAuthResult(AuthResult result);
+ AuthResult Result;
+ uint32 ErrorType;
+
+ int32 PingTimeout;
+ uint32 Threshold;
+ uint32 Rate;
};
class Pong final : public ServerPacket
diff --git a/src/server/authserver/Server/BattlenetSocket.cpp b/src/server/authserver/Server/BattlenetSocket.cpp
index 258ae371075..119fccd9abb 100644
--- a/src/server/authserver/Server/BattlenetSocket.cpp
+++ b/src/server/authserver/Server/BattlenetSocket.cpp
@@ -33,11 +33,12 @@ std::map<Battlenet::PacketHeader, Battlenet::Socket::PacketHandler> InitHandlers
std::map<Battlenet::PacketHeader, Battlenet::Socket::PacketHandler> handlers;
handlers[Battlenet::PacketHeader(Battlenet::CMSG_AUTH_CHALLENGE, Battlenet::AUTHENTICATION)] = &Battlenet::Socket::HandleAuthChallenge;
- handlers[Battlenet::PacketHeader(Battlenet::CMSG_AUTH_CHALLENGE_NEW, Battlenet::AUTHENTICATION)] = &Battlenet::Socket::HandleAuthChallenge;
+ handlers[Battlenet::PacketHeader(Battlenet::CMSG_AUTH_RECONNECT, Battlenet::AUTHENTICATION)] = &Battlenet::Socket::HandleAuthReconnect;
handlers[Battlenet::PacketHeader(Battlenet::CMSG_AUTH_PROOF_RESPONSE, Battlenet::AUTHENTICATION)] = &Battlenet::Socket::HandleAuthProofResponse;
handlers[Battlenet::PacketHeader(Battlenet::CMSG_PING, Battlenet::CREEP)] = &Battlenet::Socket::HandlePing;
handlers[Battlenet::PacketHeader(Battlenet::CMSG_ENABLE_ENCRYPTION, Battlenet::CREEP)] = &Battlenet::Socket::HandleEnableEncryption;
+ handlers[Battlenet::PacketHeader(Battlenet::CMSG_DISCONNECT, Battlenet::CREEP)] = &Battlenet::Socket::HandleDisconnect;
handlers[Battlenet::PacketHeader(Battlenet::CMSG_REALM_UPDATE_SUBSCRIBE, Battlenet::WOW)] = &Battlenet::Socket::HandleRealmUpdateSubscribe;
handlers[Battlenet::PacketHeader(Battlenet::CMSG_JOIN_REQUEST, Battlenet::WOW)] = &Battlenet::Socket::HandleRealmJoinRequest;
@@ -54,10 +55,12 @@ Battlenet::Socket::ModuleHandler const Battlenet::Socket::ModuleHandlers[MODULE_
&Battlenet::Socket::UnhandledModule,
&Battlenet::Socket::HandleSelectGameAccountModule,
&Battlenet::Socket::HandleRiskFingerprintModule,
+ &Battlenet::Socket::HandleResumeModule,
};
Battlenet::Socket::Socket(RealmSocket& socket) : _socket(socket), _accountId(0), _accountName(), _locale(),
- _os(), _build(0), _gameAccountId(0), _accountSecurityLevel(SEC_PLAYER)
+ _os(), _build(0), _gameAccountId(0), _accountSecurityLevel(SEC_PLAYER), I(), s(), v(), b(), B(), K(),
+ _reconnectProof(), _crypt(), _authed(false)
{
static uint8 const N_Bytes[] =
{
@@ -304,6 +307,61 @@ bool Battlenet::Socket::HandleAuthChallenge(PacketHeader& header, BitStream& pac
return true;
}
+bool Battlenet::Socket::HandleAuthReconnect(PacketHeader& header, BitStream& packet)
+{
+ AuthResumeInfo reconnect(header, packet);
+ reconnect.Read();
+
+ TC_LOG_DEBUG("server.battlenet", "%s", reconnect.ToString().c_str());
+
+ _accountName = reconnect.Login;
+ _locale = reconnect.Locale;
+ _os = reconnect.Platform;
+ auto baseComponent = std::find_if(reconnect.Components.begin(), reconnect.Components.end(), [](Component const& c) { return c.Program == "base"; });
+ if (baseComponent != reconnect.Components.end())
+ _build = baseComponent->Build;
+
+ Utf8ToUpperOnlyLatin(_accountName);
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_RECONNECT_INFO);
+ stmt->setString(0, _accountName);
+ stmt->setString(1, reconnect.GameAccountName.c_str());
+ PreparedQueryResult result = LoginDatabase.Query(stmt);
+ if (!result)
+ {
+ AuthResume resume;
+ resume.SetAuthResult(AUTH_UNKNOWN_ACCOUNT);
+ Send(resume);
+ return false;
+ }
+
+ Field* fields = result->Fetch();
+
+ _accountId = fields[0].GetUInt32();
+ K.SetHexStr(fields[1].GetString().c_str());
+ _gameAccountId = fields[2].GetUInt32();
+
+ ModuleInfo* thumbprint = sBattlenetMgr->CreateModule(_os, "Thumbprint");
+ ModuleInfo* resume = sBattlenetMgr->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);
+
+ ProofRequest request;
+ request.Modules.push_back(thumbprint);
+ request.Modules.push_back(resume);
+ Send(request);
+ return true;
+}
+
bool Battlenet::Socket::HandleAuthProofResponse(PacketHeader& header, BitStream& packet)
{
ProofResponse proof(header, packet);
@@ -350,6 +408,15 @@ bool Battlenet::Socket::HandleEnableEncryption(PacketHeader& /*header*/, BitStre
return true;
}
+bool Battlenet::Socket::HandleDisconnect(PacketHeader& /*header*/, BitStream& /*packet*/)
+{
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_SESSION_KEY);
+ stmt->setString(0, "");
+ stmt->setUInt32(1, _accountId);
+ LoginDatabase.Execute(stmt);
+ return true;
+}
+
bool Battlenet::Socket::HandleRealmUpdateSubscribe(PacketHeader& /*header*/, BitStream& /*packet*/)
{
sRealmList->UpdateIfNeed();
@@ -484,6 +551,13 @@ void Battlenet::Socket::OnRead()
if (packet.Read<bool>(1))
header.Channel = packet.Read<int32>(4);
+ if (header.Channel != AUTHENTICATION && !_authed)
+ {
+ TC_LOG_DEBUG("server.battlenet", "Battlenet::Socket::OnRead Received not allowed packet %s", header.ToString().c_str());
+ _socket.shutdown();
+ return;
+ }
+
TC_LOG_TRACE("server.battlenet", "Battlenet::Socket::OnRead %s", header.ToString().c_str());
std::map<PacketHeader, PacketHandler>::const_iterator itr = Handlers.find(header);
if (itr != Handlers.end())
@@ -796,14 +870,25 @@ bool Battlenet::Socket::HandleRiskFingerprintModule(BitStream* dataStream, Serve
complete->GameAccountId = _gameAccountId;
complete->GameAccountName = str.str();
- complete->AccountFlags = 0x800000; // 0x1 IsGMAccount, 0x8 IsTrialAccount, 0x800000 IsProPassAccount
+ complete->GameAccountFlags = 1;
+
+ SQLTransaction trans = LoginDatabase.BeginTransaction();
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_LAST_LOGIN_INFO);
stmt->setString(0, _socket.getRemoteAddress());
stmt->setUInt8(1, GetLocaleByName(_locale));
stmt->setString(2, _os);
stmt->setUInt32(3, _accountId);
- LoginDatabase.Execute(stmt);
+ trans->Append(stmt);
+
+ stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_SESSION_KEY);
+ stmt->setString(0, K.AsHexStr());
+ stmt->setUInt32(1, _accountId);
+ trans->Append(stmt);
+
+ LoginDatabase.CommitTransaction(trans);
+
+ _authed = true;
}
else
complete->SetAuthResult(AUTH_BAD_VERSION_HASH);
@@ -812,6 +897,86 @@ bool Battlenet::Socket::HandleRiskFingerprintModule(BitStream* dataStream, Serve
return true;
}
+bool Battlenet::Socket::HandleResumeModule(BitStream* dataStream, ServerPacket** response)
+{
+ if (dataStream->Read<uint8>(8) != 1)
+ {
+ AuthResume* complete = new AuthResume();
+ complete->SetAuthResult(AUTH_CORRUPTED_MODULE);
+ ReplaceResponse(response, complete);
+ return false;
+ }
+
+ static uint8 const ResumeClient = 0;
+ static uint8 const ResumeServer = 1;
+
+ ACE_Auto_Array_Ptr<uint8>&& clientChallenge = dataStream->ReadBytes(16);
+ ACE_Auto_Array_Ptr<uint8>&& clientProof = dataStream->ReadBytes(32);
+ ACE_Auto_Array_Ptr<uint8>&& serverChallenge = _reconnectProof.AsByteArray();
+ ACE_Auto_Array_Ptr<uint8>&& sessionKey = K.AsByteArray();
+
+ HmacHash clientPart(64, sessionKey.get(), EVP_sha256(), SHA256_DIGEST_LENGTH);
+ clientPart.UpdateData(&ResumeClient, 1);
+ clientPart.UpdateData(clientChallenge.get(), 16);
+ clientPart.UpdateData(serverChallenge.get(), 16);
+ clientPart.Finalize();
+
+ HmacHash serverPart(64, sessionKey.get(), EVP_sha256(), SHA256_DIGEST_LENGTH);
+ 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);
+
+ HmacHash proof(64, newSessionKey, EVP_sha256(), SHA256_DIGEST_LENGTH);
+ proof.UpdateData(&ResumeClient, 1);
+ proof.UpdateData(clientChallenge.get(), 16);
+ proof.UpdateData(serverChallenge.get(), 16);
+ proof.Finalize();
+
+ if (memcmp(proof.GetDigest(), clientProof.get(), serverPart.GetLength()))
+ {
+ TC_LOG_DEBUG("server.battlenet", "[Battlenet::Resume] Invalid proof!");
+ AuthResume* result = new AuthResume();
+ result->SetAuthResult(AUTH_UNKNOWN_ACCOUNT);
+ ReplaceResponse(response, result);
+ return false;
+ }
+
+ PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_SESSION_KEY);
+ stmt->setString(0, K.AsHexStr());
+ stmt->setUInt32(1, _accountId);
+ LoginDatabase.Execute(stmt);
+
+ HmacHash serverProof(64, newSessionKey, EVP_sha256(), SHA256_DIGEST_LENGTH);
+ serverProof.UpdateData(&ResumeServer, 1);
+ serverProof.UpdateData(serverChallenge.get(), 16);
+ serverProof.UpdateData(clientChallenge.get(), 16);
+ serverProof.Finalize();
+
+ ModuleInfo* resume = sBattlenetMgr->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);
+
+ AuthResume* result = new AuthResume();
+ result->Modules.push_back(resume);
+ ReplaceResponse(response, result);
+ _authed = true;
+ return true;
+}
+
bool Battlenet::Socket::UnhandledModule(BitStream* /*dataStream*/, ServerPacket** response)
{
AuthComplete* complete = new AuthComplete();
diff --git a/src/server/authserver/Server/BattlenetSocket.h b/src/server/authserver/Server/BattlenetSocket.h
index ff441b19cdd..c634a81b517 100644
--- a/src/server/authserver/Server/BattlenetSocket.h
+++ b/src/server/authserver/Server/BattlenetSocket.h
@@ -37,6 +37,7 @@ namespace Battlenet
MODULE_THUMBPRINT,
MODULE_SELECT_GAME_ACCOUNT,
MODULE_RISK_FINGERPRINT,
+ MODULE_RESUME,
MODULE_COUNT
};
@@ -53,11 +54,13 @@ namespace Battlenet
// Auth
bool HandleAuthChallenge(PacketHeader& header, BitStream& packet);
+ bool HandleAuthReconnect(PacketHeader& header, BitStream& packet);
bool HandleAuthProofResponse(PacketHeader& header, BitStream& packet);
// Creep
bool HandlePing(PacketHeader& header, BitStream& packet);
bool HandleEnableEncryption(PacketHeader& header, BitStream& packet);
+ bool HandleDisconnect(PacketHeader& header, BitStream& packet);
// WoW
bool HandleRealmUpdateSubscribe(PacketHeader& header, BitStream& packet);
@@ -78,6 +81,7 @@ namespace Battlenet
bool HandlePasswordModule(BitStream* dataStream, ServerPacket** response);
bool HandleSelectGameAccountModule(BitStream* dataStream, ServerPacket** response);
bool HandleRiskFingerprintModule(BitStream* dataStream, ServerPacket** response);
+ bool HandleResumeModule(BitStream* dataStream, ServerPacket** response);
bool UnhandledModule(BitStream* dataStream, ServerPacket** response);
RealmSocket& _socket;
@@ -102,9 +106,12 @@ namespace Battlenet
BigNumber B;
BigNumber K; // session key
+ BigNumber _reconnectProof;
+
std::queue<ModuleType> _modulesWaitingForData;
PacketCrypt _crypt;
+ bool _authed;
};
}
diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/shared/Database/Implementation/LoginDatabase.cpp
index a54557310e1..abe733e55e2 100644
--- a/src/server/shared/Database/Implementation/LoginDatabase.cpp
+++ b/src/server/shared/Database/Implementation/LoginDatabase.cpp
@@ -107,6 +107,8 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_DEL_BNET_EXPIRED_BANS, "UPDATE battlenet_account_bans SET active = 0 WHERE active = 1 AND unbandate <> bandate AND unbandate <= UNIX_TIMESTAMP()", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_BNET_ACTIVE_ACCOUNT_BAN, "SELECT bandate, unbandate FROM battlenet_account_bans WHERE id = ? AND active = 1", CONNECTION_SYNCH);
PrepareStatement(LOGIN_UPD_BNET_VS_FIELDS, "UPDATE battlenet_accounts SET v = ?, s = ? WHERE email = ?", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_UPD_BNET_SESSION_KEY, "UPDATE battlenet_accounts SET sessionKey = ? WHERE id = ?", CONNECTION_ASYNC);
+ PrepareStatement(LOGIN_SEL_BNET_RECONNECT_INFO, "SELECT ba.id, ba.sessionKey, a.id FROM battlenet_accounts ba LEFT JOIN account a ON ba.id = a.battlenet_account WHERE ba.email = ? AND a.id = SUBSTRING_INDEX(?, '#', 1)", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_BNET_GAME_ACCOUNTS, "SELECT a.username, a.id, ab.bandate, ab.unbandate, ab.active FROM account a LEFT JOIN account_banned ab ON a.id = ab.id WHERE battlenet_account = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_BNET_GAME_ACCOUNT, "SELECT a.id, ab.bandate, ab.unbandate, ab.active FROM account a LEFT JOIN account_banned ab ON a.id = ab.id WHERE username = ? AND battlenet_account = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_UPD_BNET_LAST_LOGIN_INFO, "UPDATE battlenet_accounts SET last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE id = ?", CONNECTION_ASYNC);
diff --git a/src/server/shared/Database/Implementation/LoginDatabase.h b/src/server/shared/Database/Implementation/LoginDatabase.h
index fff7a36766c..64264984e29 100644
--- a/src/server/shared/Database/Implementation/LoginDatabase.h
+++ b/src/server/shared/Database/Implementation/LoginDatabase.h
@@ -126,6 +126,8 @@ enum LoginDatabaseStatements
LOGIN_DEL_BNET_EXPIRED_BANS,
LOGIN_SEL_BNET_ACTIVE_ACCOUNT_BAN,
LOGIN_UPD_BNET_VS_FIELDS,
+ LOGIN_UPD_BNET_SESSION_KEY,
+ LOGIN_SEL_BNET_RECONNECT_INFO,
LOGIN_SEL_BNET_GAME_ACCOUNTS,
LOGIN_SEL_BNET_GAME_ACCOUNT,
LOGIN_UPD_BNET_LAST_LOGIN_INFO,