Core/Battle.net: Implemented reconnects
This commit is contained in:
@@ -176,6 +176,7 @@ CREATE TABLE `battlenet_accounts` (
|
||||
`sha_pass_hash` varchar(64) NOT NULL DEFAULT '',
|
||||
`v` varchar(256) NOT NULL DEFAULT '',
|
||||
`s` varchar(64) NOT NULL DEFAULT '',
|
||||
`sessionKey` varchar(128) NOT NULL DEFAULT '',
|
||||
`joindate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`last_ip` varchar(15) NOT NULL DEFAULT '127.0.0.1',
|
||||
`failed_logins` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
@@ -272,7 +273,11 @@ INSERT INTO `battlenet_modules` VALUES
|
||||
('b37136b39add83cfdbafa81857de3dd8f15b34e0135ec6cd9c3131d3a578d8c2','Thumbprint','auth','Mc64','E716F4F0A01EB9C032A6C1393356A4F766F067949D71023C0CFC0613718966EF814E65CC6EE70C432A7F8AFD8A062B52603A2697E851D231D72C0277614181D713369B1E8E4BEEAB72045A9AAD45F319DB918ECDDB83C8EF8B7510600D391D45E7FEC0BEEAE904A5F9FA620F1CCDAD699D84A4739CE669B5A551831E396214E13B4C88F573F5CDC784CD01530C086B674C03BEB66403A0F87ED17ABBB403DE54CF31BE828A20C566C22E4D4263AA77220B0644D99245345BCAC276EA06925EB984D664725C3CB757140AFE12E27CB996F17159B1057E9B58B78BBB5A139C9FF6215A0D250B75FC9DD435655DDEADCD6CFD84800792C146B3633188ECEB53D2038C185E0BD51A9E6C70FD38ADF530F8DF50FB62053C5E894897AB7DD65C7AC80665F18E7989BE6E30F15E939751123D6D8A44F033175301D15AAAD2AEA06FAC60BA4065846AE938F32B1CB15F16DC0E76792A7332346896048065D17C059899E1D2300E402BD0EA74265DA6A42B1C854E2470D7B21AE4A2DAE90E602A759B2CA0EE610B50D5389DB89335D5451FE76DD85B09FD5297D6F9EFB6C34CE885007F7DF20D6A524E0C3E772FA04B3DD2E014D3A337A790943DAD523CBB5453F4FDF8E74DFE361BD5F25AB31952B478148B570DF5762643F32B994FEC99A747E4A265A66EE84A53509EC285C84679606049314FC526C61B537AC8061C788F8B86F52208'),
|
||||
('c0f38d05aa1b83065e839c9bd96c831e9f7e42477085138752657a6a9bb9c520','RiskFingerprint','auth','Mac',NULL),
|
||||
('c3a1ac0694979e709c3b5486927e558af1e2be02ca96e5615c5a65aacc829226','Thumbprint','auth','Wn64','E716F4F0A01EB9C032A6C1393356A4F766F067949D71023C0CFC0613718966EF814E65CC6EE70C432A7F8AFD8A062B52603A2697E851D231D72C0277614181D713369B1E8E4BEEAB72045A9AAD45F319DB918ECDDB83C8EF8B7510600D391D45E7FEC0BEEAE904A5F9FA620F1CCDAD699D84A4739CE669B5A551831E396214E13B4C88F573F5CDC784CD01530C086B674C03BEB66403A0F87ED17ABBB403DE54CF31BE828A20C566C22E4D4263AA77220B0644D99245345BCAC276EA06925EB984D664725C3CB757140AFE12E27CB996F17159B1057E9B58B78BBB5A139C9FF6215A0D250B75FC9DD435655DDEADCD6CFD84800792C146B3633188ECEB53D2038C185E0BD51A9E6C70FD38ADF530F8DF50FB62053C5E894897AB7DD65C7AC80665F18E7989BE6E30F15E939751123D6D8A44F033175301D15AAAD2AEA06FAC60BA4065846AE938F32B1CB15F16DC0E76792A7332346896048065D17C059899E1D2300E402BD0EA74265DA6A42B1C854E2470D7B21AE4A2DAE90E602A759B2CA0EE610B50D5389DB89335D5451FE76DD85B09FD5297D6F9EFB6C34CE885007F7DF20D6A524E0C3E772FA04B3DD2E014D3A337A790943DAD523CBB5453F4FDF8E74DFE361BD5F25AB31952B478148B570DF5762643F32B994FEC99A747E4A265A66EE84A53509EC285C84679606049314FC526C61B537AC8061C788F8B86F52208'),
|
||||
('fbe675a99fb5f4b7fb3eb5e5a22add91a4cabf83e3c5930c6659ad13c457ba18','Token','auth','Win',NULL);
|
||||
('fbe675a99fb5f4b7fb3eb5e5a22add91a4cabf83e3c5930c6659ad13c457ba18','Token','auth','Win',NULL),
|
||||
('bfe4ceb47700aa872e815e007e27df955d4cd4bc1fe731039ee6498ce209f368','Resume','auth','Win',NULL),
|
||||
('00ffd88a437afbb88d7d4b74be2e3b43601605ee229151aa9f4bebb29ef66280','Resume','auth','Mac',NULL),
|
||||
('898166926805f897804bdbbf40662c9d768590a51a0b26c40dbcdf332ba11974','Resume','auth','Wn64',NULL),
|
||||
('304627d437c38500c0b5ca0c6220eeade91390e52a2b005ff3f7754afa1f93cd','Resume','auth','Mc64',NULL);
|
||||
/*!40000 ALTER TABLE `battlenet_modules` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
ALTER TABLE `battlenet_accounts` ADD `sessionKey` VARCHAR(128) NOT NULL DEFAULT '' AFTER `s`;
|
||||
|
||||
DELETE FROM `battlenet_modules` WHERE `Name`='Resume';
|
||||
INSERT INTO `battlenet_modules` VALUES
|
||||
('bfe4ceb47700aa872e815e007e27df955d4cd4bc1fe731039ee6498ce209f368','Resume','auth','Win',NULL),
|
||||
('00ffd88a437afbb88d7d4b74be2e3b43601605ee229151aa9f4bebb29ef66280','Resume','auth','Mac',NULL),
|
||||
('898166926805f897804bdbbf40662c9d768590a51a0b26c40dbcdf332ba11974','Resume','auth','Wn64',NULL),
|
||||
('304627d437c38500c0b5ca0c6220eeade91390e52a2b005ff3f7754afa1f93cd','Resume','auth','Mc64',NULL);
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user