aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2016-03-25 21:33:55 +0100
committerShauren <shauren.trinity@gmail.com>2016-03-25 21:33:55 +0100
commit9ad79934d3f1e33488dde2959dfad6fa80094e1d (patch)
tree141f8ccdf3ec765ac9c5dcb4f5e91fa19788ab0f
parent45c857a6bf78f7913ad4032524c84df41b7efc5f (diff)
Core/PacketIO: Updated packet structures to 6.2.4.21355
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.cpp8
-rw-r--r--src/server/database/Database/Implementation/LoginDatabase.cpp2
-rw-r--r--src/server/game/Server/Packets/AuthenticationPackets.cpp295
-rw-r--r--src/server/game/Server/Packets/AuthenticationPackets.h33
-rw-r--r--src/server/game/Server/Packets/CharacterPackets.cpp8
-rw-r--r--src/server/game/Server/Packets/CharacterPackets.h3
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp6
-rw-r--r--src/server/game/Server/WorldSocket.cpp127
-rw-r--r--src/server/game/Server/WorldSocket.h6
9 files changed, 133 insertions, 355 deletions
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp
index babf39ec3e5..8b7baf385ce 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp
@@ -45,21 +45,21 @@ void CharacterDatabaseConnection::DoPrepareStatements()
"subject, deliver_time, expire_time, money, has_items FROM mail WHERE receiver = ? ", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_MAIL_LIST_ITEMS, "SELECT itemEntry,count FROM item_instance WHERE guid = ?", CONNECTION_SYNCH);
PrepareStatement(CHAR_SEL_ENUM, "SELECT c.guid, c.name, c.race, c.class, c.gender, c.skin, c.face, c.hairStyle, c.hairColor, c.facialStyle, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, "
- "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid, c.slot "
+ "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid, c.slot, c.logout_time "
"FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? LEFT JOIN guild_member AS gm ON c.guid = gm.guid "
"LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_ENUM_DECLINED_NAME, "SELECT c.guid, c.name, c.race, c.class, c.gender, c.skin, c.face, c.hairStyle, c.hairColor, c.facialStyle, c.level, c.zone, c.map, "
"c.position_x, c.position_y, c.position_z, gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, "
- "cb.guid, c.slot, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? "
+ "cb.guid, c.slot, c.logout_time, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? "
"LEFT JOIN character_declinedname AS cd ON c.guid = cd.guid LEFT JOIN guild_member AS gm ON c.guid = gm.guid "
"LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.account = ? AND c.deleteInfos_Name IS NULL", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_UNDELETE_ENUM, "SELECT c.guid, c.deleteInfos_Name, c.race, c.class, c.gender, c.skin, c.face, c.hairStyle, c.hairColor, c.facialStyle, c.level, c.zone, c.map, c.position_x, c.position_y, c.position_z, "
- "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid, c.slot "
+ "gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, cb.guid, c.slot, c.logout_time "
"FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? LEFT JOIN guild_member AS gm ON c.guid = gm.guid "
"LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.deleteInfos_Account = ? AND c.deleteInfos_Name IS NOT NULL", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_UNDELETE_ENUM_DECLINED_NAME, "SELECT c.guid, c.deleteInfos_Name, c.race, c.class, c.gender, c.skin, c.face, c.hairStyle, c.hairColor, c.facialStyle, c.level, c.zone, c.map, "
"c.position_x, c.position_y, c.position_z, gm.guildid, c.playerFlags, c.at_login, cp.entry, cp.modelid, cp.level, c.equipmentCache, "
- "cb.guid, c.slot, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? "
+ "cb.guid, c.slot, c.logout_time, cd.genitive FROM characters AS c LEFT JOIN character_pet AS cp ON c.guid = cp.owner AND cp.slot = ? "
"LEFT JOIN character_declinedname AS cd ON c.guid = cd.guid LEFT JOIN guild_member AS gm ON c.guid = gm.guid "
"LEFT JOIN character_banned AS cb ON c.guid = cb.guid AND cb.active = 1 WHERE c.deleteInfos_Account = ? AND c.deleteInfos_Name IS NOT NULL", CONNECTION_ASYNC);
PrepareStatement(CHAR_SEL_FREE_NAME, "SELECT name, at_login FROM characters WHERE guid = ? AND NOT EXISTS (SELECT NULL FROM characters WHERE name = ?)", CONNECTION_ASYNC);
diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp
index 964748a2682..2ca59c05ecc 100644
--- a/src/server/database/Database/Implementation/LoginDatabase.cpp
+++ b/src/server/database/Database/Implementation/LoginDatabase.cpp
@@ -39,7 +39,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_SEL_LOGON_COUNTRY, "SELECT country FROM ip2nation WHERE ip < ? ORDER BY ip DESC LIMIT 0,1", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_LIST_BY_NAME, "SELECT id, username FROM account WHERE username = ?", CONNECTION_SYNCH);
- PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME, "SELECT a.id, a.sessionkey, ba.last_ip, ba.locked, ba.lock_country, a.expansion, a.mutetime, ba.locale, a.recruiter, ba.os, ba.id, aa.gmLevel, "
+ PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME, "SELECT a.id, a.sessionkey, ba.last_ip, ba.locked, ba.lock_country, a.expansion, a.mutetime, ba.locale, a.recruiter, a.os, ba.id, aa.gmLevel, "
"bab.unbandate > UNIX_TIMESTAMP() OR bab.unbandate = bab.bandate, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, r.id "
"FROM account a LEFT JOIN account r ON a.id = r.recruiter LEFT JOIN battlenet_accounts ba ON a.battlenet_account = ba.id "
"LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID IN (-1, ?) LEFT JOIN battlenet_account_bans bab ON ba.id = bab.id LEFT JOIN account_banned ab ON a.id = ab.id AND ab.active = 1 "
diff --git a/src/server/game/Server/Packets/AuthenticationPackets.cpp b/src/server/game/Server/Packets/AuthenticationPackets.cpp
index 6a76f8ee3b8..648d03ec4ef 100644
--- a/src/server/game/Server/Packets/AuthenticationPackets.cpp
+++ b/src/server/game/Server/Packets/AuthenticationPackets.cpp
@@ -20,34 +20,39 @@
WorldPacket const* WorldPackets::Auth::AuthChallenge::Write()
{
- _worldPacket << uint32(Challenge);
_worldPacket.append(DosChallenge, 8);
+ _worldPacket.append(Challenge.data(), Challenge.size());
_worldPacket << uint8(DosZeroBits);
return &_worldPacket;
}
void WorldPackets::Auth::AuthSession::Read()
{
- uint32 addonDataSize;
+ uint32 addonDataSize, realmJoinTicketSize;
- _worldPacket >> LoginServerID;
_worldPacket >> Build;
+ _worldPacket >> BuildType;
_worldPacket >> RegionID;
_worldPacket >> BattlegroupID;
_worldPacket >> RealmID;
- _worldPacket >> LoginServerType;
- _worldPacket >> BuildType;
- _worldPacket >> LocalChallenge;
+ _worldPacket.read(LocalChallenge.data(), LocalChallenge.size());
+ _worldPacket.read(Digest.data(), Digest.size());
_worldPacket >> DosResponse;
- _worldPacket.read(Digest, SHA_DIGEST_LENGTH);
- Account = _worldPacket.ReadString(_worldPacket.ReadBits(11));
- UseIPv6 = _worldPacket.ReadBit(); // UseIPv6
_worldPacket >> addonDataSize;
if (addonDataSize)
{
- AddonInfo.resize(addonDataSize);
- _worldPacket.read(AddonInfo.contents(), addonDataSize);
+ AddonInfo.resize(std::min(addonDataSize, uint32(_worldPacket.size() - _worldPacket.rpos())));
+ _worldPacket.read(AddonInfo.contents(), AddonInfo.size());
+ }
+
+ _worldPacket >> realmJoinTicketSize;
+ if (realmJoinTicketSize)
+ {
+ RealmJoinTicket.resize(std::min(realmJoinTicketSize, uint32(_worldPacket.size() - _worldPacket.rpos())));
+ _worldPacket.read(reinterpret_cast<uint8*>(&RealmJoinTicket[0]), RealmJoinTicket.size());
}
+
+ UseIPv6 = _worldPacket.ReadBit(); // UseIPv6
}
WorldPackets::Auth::AuthResponse::AuthResponse()
@@ -57,7 +62,7 @@ WorldPackets::Auth::AuthResponse::AuthResponse()
WorldPacket const* WorldPackets::Auth::AuthResponse::Write()
{
- _worldPacket << uint8(Result);
+ _worldPacket << uint32(Result);
_worldPacket.WriteBit(SuccessInfo.is_initialized());
_worldPacket.WriteBit(WaitInfo.is_initialized());
_worldPacket.FlushBits();
@@ -294,7 +299,7 @@ WorldPacket const* WorldPackets::Auth::ConnectTo::Write()
ByteBuffer payload;
uint16 port = Payload.Where.port();
uint8 address[16] = { 0 };
- uint32 addressType = 3;
+ uint8 addressType = 3;
if (Payload.Where.address().is_v4())
{
memcpy(address, Payload.Where.address().to_v4().to_bytes().data(), 4);
@@ -308,7 +313,7 @@ WorldPacket const* WorldPackets::Auth::ConnectTo::Write()
HmacSha1 hmacHash(64, WherePacketHmac);
hmacHash.UpdateData(address, 16);
- hmacHash.UpdateData((uint8* const)&addressType, 4);
+ hmacHash.UpdateData(&addressType, 1);
hmacHash.UpdateData((uint8* const)&port, 2);
hmacHash.UpdateData((uint8* const)Haiku.c_str(), 71);
hmacHash.UpdateData(Payload.PanamaKey, 32);
@@ -316,260 +321,15 @@ WorldPacket const* WorldPackets::Auth::ConnectTo::Write()
hmacHash.UpdateData(&Payload.XorMagic, 1);
hmacHash.Finalize();
- uint8* hmac = hmacHash.GetDigest();
-
- payload << uint8(Haiku[53]);
- payload << uint8(PiDigits[12]);
- payload << uint8(Haiku[27]);
- payload << uint8(PiDigits[65]);
- payload << uint8(PiDigits[96]);
- payload << uint8(Haiku[29]);
- payload << uint8(Payload.PanamaKey[12]);
- payload << uint8(hmac[3]);
- payload << uint8(PiDigits[10]);
- payload << uint8(Payload.PanamaKey[20]);
- payload << uint8(PiDigits[14]);
- payload << uint8(hmac[17]);
- payload << uint8(Haiku[3]);
- payload << uint8(PiDigits[26]);
- payload << uint8(PiDigits[94]);
- payload << uint8(PiDigits[7]);
- payload << uint8(PiDigits[93]);
- payload << uint8(Payload.PanamaKey[8]);
- payload << uint8(PiDigits[40]);
- payload << uint8(PiDigits[52]);
- payload << uint8(Haiku[44]);
- payload << uint8(address[13]);
- payload << uint8(Haiku[57]);
- payload << uint8(PiDigits[59]);
- payload << uint8(PiDigits[97]);
- payload << uint8(PiDigits[42]);
- payload << uint8(Haiku[70]);
- payload << uint8(Haiku[42]);
- payload << uint8(PiDigits[50]);
- payload << uint8(address[3]);
- payload << uint8(PiDigits[60]);
- payload << uint8(address[12]);
- payload << uint8(PiDigits[86]);
- payload << uint8(Haiku[56]);
- payload << uint8(PiDigits[70]);
- payload << uint8(Haiku[26]);
- payload << uint8(PiDigits[74]);
- payload << uint8(PiDigits[49]);
- payload << uint8(Payload.PanamaKey[28]);
- payload << uint8(Haiku[69]);
- payload << uint8(hmac[9]);
- payload << uint8(Haiku[15]);
- payload << uint8(Payload.PanamaKey[0]);
- payload << uint8(Payload.PanamaKey[6]);
- payload << uint8(Haiku[17]);
- payload << uint8((port >> 8) & 0xFF);
- payload << uint8(PiDigits[20]);
- payload << uint8(PiDigits[99]);
- payload << uint8(PiDigits[95]);
- payload << uint8(PiDigits[100]);
- payload << uint8(PiDigits[105]);
- payload << uint8(hmac[13]);
- payload << uint8(Payload.PanamaKey[9]);
- payload << uint8(PiDigits[41]);
- payload << uint8(PiDigits[35]);
- payload << uint8(Haiku[10]);
- payload << uint8(Haiku[20]);
- payload << uint8(Haiku[14]);
- payload << uint8(Haiku[47]);
- payload << uint8(Payload.PanamaKey[10]);
- payload << uint8(PiDigits[54]);
- payload << uint8(PiDigits[67]);
- payload << uint8(PiDigits[79]);
- payload << uint8(Payload.PanamaKey[3]);
- payload << uint8(PiDigits[84]);
- payload << uint8(Haiku[33]);
- payload << uint8(Haiku[23]);
- payload << uint8(Haiku[48]);
- payload << uint8(PiDigits[64]);
- payload << uint8(PiDigits[85]);
- payload << uint8(Payload.PanamaKey[24]);
- payload << uint8(hmac[8]);
- payload << uint8(PiDigits[101]);
- payload << uint8(addressType);
- payload << uint8(PiDigits[53]);
- payload << uint8(Haiku[39]);
- payload << uint8(hmac[19]);
- payload << uint8(Payload.PanamaKey[31]);
- payload << uint8(Payload.PanamaKey[18]);
- payload << uint8(hmac[4]);
- payload << uint8(Haiku[54]);
- payload << uint8(PiDigits[76]);
- payload << uint8(address[9]);
- payload << uint8(hmac[7]);
- payload << uint8(PiDigits[80]);
- payload << uint8(hmac[2]);
- payload << uint8(Haiku[13]);
- payload << uint8(Haiku[11]);
- payload << uint8(Payload.PanamaKey[7]);
- payload << uint8(Haiku[64]);
- payload << uint8(Haiku[62]);
- payload << uint8(Haiku[9]);
- payload << uint8(Payload.PanamaKey[26]);
- payload << uint8(hmac[1]);
- payload << uint8(hmac[15]);
- payload << uint8(PiDigits[25]);
- payload << uint8(hmac[14]);
- payload << uint8(Haiku[35]);
- payload << uint8(Haiku[43]);
- payload << uint8(PiDigits[58]);
- payload << uint8(Payload.PanamaKey[1]);
- payload << uint8(PiDigits[45]);
- payload << uint8(Payload.PanamaKey[25]);
- payload << uint8(PiDigits[69]);
- payload << uint8(PiDigits[27]);
- payload << uint8(address[4]);
- payload << uint8(PiDigits[11]);
- payload << uint8(Payload.PanamaKey[16]);
- payload << uint8(PiDigits[38]);
- payload << uint8(PiDigits[82]);
- payload << uint8(PiDigits[1]);
- payload << uint8(PiDigits[103]);
- payload << uint8(address[10]);
- payload << uint8(Haiku[18]);
- payload << uint8(PiDigits[91]);
- payload << uint8(PiDigits[75]);
- payload << uint8(PiDigits[34]);
- payload << uint8(Payload.PanamaKey[27]);
- payload << uint8(PiDigits[106]);
- payload << uint8(PiDigits[28]);
- payload << uint8(Haiku[8]);
- payload << uint8(PiDigits[5]);
- payload << uint8(Haiku[68]);
- payload << uint8(Payload.PanamaKey[15]);
- payload << uint8(address[2]);
- payload << uint8(PiDigits[48]);
- payload << uint8(PiDigits[107]);
- payload << uint8(Payload.PanamaKey[17]);
- payload << uint8(PiDigits[15]);
payload << uint32(Payload.Adler32);
- payload << uint8(PiDigits[36]);
- payload << uint8(address[5]);
- payload << uint8(PiDigits[71]);
- payload << uint8(address[15]);
- payload << uint8(address[0]);
- payload << uint8(hmac[5]);
- payload << uint8(PiDigits[83]);
- payload << uint8(Payload.PanamaKey[14]);
- payload << uint8(PiDigits[55]);
- payload << uint8(PiDigits[31]);
- payload << uint8(Haiku[52]);
- payload << uint8(PiDigits[22]);
- payload << uint8(PiDigits[8]);
- payload << uint8(PiDigits[6]);
- payload << uint8(Payload.PanamaKey[21]);
- payload << uint8(port & 0xFF);
- payload << uint8(PiDigits[51]);
- payload << uint8(Haiku[31]);
- payload << uint8(Haiku[59]);
- payload << uint8(PiDigits[17]);
- payload << uint8(PiDigits[88]);
- payload << uint8(PiDigits[32]);
- payload << uint8(address[6]);
- payload << uint8(Haiku[49]);
- payload << uint8(PiDigits[21]);
- payload << uint8(Payload.PanamaKey[13]);
- payload << uint8(address[1]);
- payload << uint8(Haiku[19]);
- payload << uint8(Haiku[63]);
- payload << uint8(PiDigits[4]);
- payload << uint8(Haiku[65]);
- payload << uint8(PiDigits[39]);
- payload << uint8(Haiku[21]);
- payload << uint8(Haiku[32]);
- payload << uint8(Haiku[25]);
- payload << uint8(Haiku[1]);
- payload << uint8(PiDigits[9]);
- payload << uint8(Haiku[2]);
- payload << uint8(Payload.PanamaKey[22]);
- payload << uint8(PiDigits[78]);
- payload << uint8(Haiku[4]);
- payload << uint8(Haiku[50]);
- payload << uint8(Payload.PanamaKey[29]);
- payload << uint8(hmac[12]);
- payload << uint8(PiDigits[56]);
- payload << uint8(address[11]);
- payload << uint8(PiDigits[102]);
- payload << uint8(Payload.PanamaKey[19]);
- payload << uint8(PiDigits[33]);
- payload << uint8(Haiku[30]);
- payload << uint8(Payload.PanamaKey[5]);
- payload << uint8(PiDigits[46]);
- payload << uint8(PiDigits[30]);
- payload << uint8(PiDigits[98]);
- payload << uint8(Haiku[66]);
- payload << uint8(PiDigits[77]);
- payload << uint8(PiDigits[63]);
- payload << uint8(Payload.PanamaKey[11]);
- payload << uint8(PiDigits[2]);
- payload << uint8(Haiku[61]);
- payload << uint8(address[7]);
- payload << uint8(PiDigits[3]);
- payload << uint8(Haiku[12]);
- payload << uint8(Haiku[40]);
- payload << uint8(PiDigits[57]);
- payload << uint8(Haiku[28]);
- payload << uint8(PiDigits[29]);
- payload << uint8(Haiku[46]);
- payload << uint8(PiDigits[44]);
- payload << uint8(address[14]);
- payload << uint8(PiDigits[16]);
- payload << uint8(PiDigits[87]);
- payload << uint8(PiDigits[81]);
- payload << uint8(hmac[18]);
- payload << uint8(address[8]);
- payload << uint8(Haiku[6]);
- payload << uint8(hmac[16]);
- payload << uint8(PiDigits[62]);
- payload << uint8(PiDigits[72]);
- payload << uint8(PiDigits[18]);
- payload << uint8(PiDigits[43]);
- payload << uint8(Haiku[7]);
- payload << uint8(Haiku[37]);
+ payload << uint8(addressType);
+ payload.append(address, 16);
+ payload << uint16(port);
+ payload.append(Haiku.data(), 71);
+ payload.append(Payload.PanamaKey, 32);
+ payload.append(PiDigits, 108);
payload << uint8(Payload.XorMagic);
- payload << uint8(Payload.PanamaKey[2]);
- payload << uint8(PiDigits[92]);
- payload << uint8(PiDigits[47]);
- payload << uint8(PiDigits[13]);
- payload << uint8(PiDigits[66]);
- payload << uint8(Haiku[55]);
- payload << uint8(PiDigits[73]);
- payload << uint8(Haiku[5]);
- payload << uint8(PiDigits[0]);
- payload << uint8(Haiku[16]);
- payload << uint8(Haiku[34]);
- payload << uint8(hmac[10]);
- payload << uint8(PiDigits[89]);
- payload << uint8(Haiku[38]);
- payload << uint8(Haiku[22]);
- payload << uint8(hmac[11]);
- payload << uint8(PiDigits[61]);
- payload << uint8(Haiku[0]);
- payload << uint8(hmac[0]);
- payload << uint8(Haiku[24]);
- payload << uint8(PiDigits[37]);
- payload << uint8(hmac[6]);
- payload << uint8(Haiku[41]);
- payload << uint8(Haiku[60]);
- payload << uint8(PiDigits[90]);
- payload << uint8(Haiku[67]);
- payload << uint8(Haiku[51]);
- payload << uint8(PiDigits[24]);
- payload << uint8(PiDigits[23]);
- payload << uint8(Haiku[58]);
- payload << uint8(Haiku[45]);
- payload << uint8(PiDigits[104]);
- payload << uint8(PiDigits[68]);
- payload << uint8(Payload.PanamaKey[30]);
- payload << uint8(Payload.PanamaKey[23]);
- payload << uint8(Payload.PanamaKey[4]);
- payload << uint8(Haiku[36]);
- payload << uint8(PiDigits[19]);
+ payload.append(hmacHash.GetDigest(), hmacHash.GetLength());
BigNumber bnData;
bnData.SetBinary(payload.contents(), payload.size());
@@ -594,7 +354,8 @@ void WorldPackets::Auth::AuthContinuedSession::Read()
{
_worldPacket >> DosResponse;
_worldPacket >> Key;
- _worldPacket.read(Digest, SHA_DIGEST_LENGTH);
+ _worldPacket.read(LocalChallenge.data(), LocalChallenge.size());
+ _worldPacket.read(Digest.data(), Digest.size());
}
void WorldPackets::Auth::ConnectToFailed::Read()
diff --git a/src/server/game/Server/Packets/AuthenticationPackets.h b/src/server/game/Server/Packets/AuthenticationPackets.h
index 123d4a24f10..5bd433ebb57 100644
--- a/src/server/game/Server/Packets/AuthenticationPackets.h
+++ b/src/server/game/Server/Packets/AuthenticationPackets.h
@@ -38,7 +38,7 @@ namespace WorldPackets
WorldPacket const* Write() override;
- uint32 Challenge = 0;
+ std::array<uint8, 16> Challenge;
uint32 DosChallenge[8]; ///< Encryption seeds
uint8 DosZeroBits = 0;
};
@@ -46,26 +46,27 @@ namespace WorldPackets
class AuthSession final : public ClientPacket
{
public:
+ static uint32 const DigestLength = 24;
+
AuthSession(WorldPacket&& packet) : ClientPacket(CMSG_AUTH_SESSION, std::move(packet))
{
- memset(Digest, 0, SHA_DIGEST_LENGTH);
+ LocalChallenge.fill(0);
+ Digest.fill(0);
}
void Read() override;
- uint32 BattlegroupID = 0;
- int8 LoginServerType = 0; ///< Auth type used - 0 GRUNT, 1 battle.net
- int8 BuildType = 0;
- uint32 RealmID = 0;
uint16 Build = 0;
- uint32 LocalChallenge = 0;
- int32 LoginServerID = 0;
+ int8 BuildType = 0;
uint32 RegionID = 0;
+ uint32 BattlegroupID = 0;
+ uint32 RealmID = 0;
+ std::array<uint8, 16> LocalChallenge;
+ std::array<uint8, DigestLength> Digest;
uint64 DosResponse = 0;
- uint8 Digest[SHA_DIGEST_LENGTH];
- std::string Account;
- bool UseIPv6 = false;
ByteBuffer AddonInfo;
+ std::string RealmJoinTicket;
+ bool UseIPv6 = false;
};
class AuthResponse final : public ServerPacket
@@ -121,7 +122,7 @@ namespace WorldPackets
Optional<AuthSuccessInfo> SuccessInfo; ///< contains the packet data in case that it has account information (It is never set when WaitInfo is set), otherwise its contents are undefined.
Optional<AuthWaitInfo> WaitInfo; ///< contains the queue wait information in case the account is in the login queue.
- uint8 Result = 0; ///< the result of the authentication process, it is AUTH_OK if it succeeded and the account is ready to log in. It can also be AUTH_WAIT_QUEUE if the account entered the login queue (Queued, QueuePos), possible values are @ref ResponseCodes
+ uint32 Result = 0; ///< the result of the authentication process, it is AUTH_OK if it succeeded and the account is ready to log in. It can also be AUTH_WAIT_QUEUE if the account entered the login queue (Queued, QueuePos), possible values are @ref ResponseCodes
};
enum class ConnectToSerial : uint32
@@ -169,16 +170,20 @@ namespace WorldPackets
class AuthContinuedSession final : public ClientPacket
{
public:
+ static uint32 const DigestLength = 24;
+
AuthContinuedSession(WorldPacket&& packet) : ClientPacket(CMSG_AUTH_CONTINUED_SESSION, std::move(packet))
{
- memset(Digest, 0, SHA_DIGEST_LENGTH);
+ LocalChallenge.fill(0);
+ Digest.fill(0);
}
void Read() override;
uint64 DosResponse = 0;
uint64 Key = 0;
- uint8 Digest[SHA_DIGEST_LENGTH];
+ std::array<uint8, 16> LocalChallenge;
+ std::array<uint8, DigestLength> Digest;
};
class ResumeComms final : public ServerPacket
diff --git a/src/server/game/Server/Packets/CharacterPackets.cpp b/src/server/game/Server/Packets/CharacterPackets.cpp
index d54402d40c7..d30779d49c2 100644
--- a/src/server/game/Server/Packets/CharacterPackets.cpp
+++ b/src/server/game/Server/Packets/CharacterPackets.cpp
@@ -28,8 +28,8 @@ WorldPackets::Character::EnumCharactersResult::CharacterInfo::CharacterInfo(Fiel
// "characters.hairColor, characters.facialStyle, characters.level, characters.zone, characters.map, characters.position_x, characters.position_y, characters.position_z, "
// 16 17 18 19 20 21 22
// "guild_member.guildid, characters.playerFlags, characters.at_login, character_pet.entry, character_pet.modelid, character_pet.level, characters.equipmentCache, "
- // 23 24 25
- // "character_banned.guid, characters.slot, character_declinedname.genitive"
+ // 23 24 25 26
+ // "character_banned.guid, characters.slot, characters.logout_time, character_declinedname.genitive"
Guid = ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64());
Name = fields[1].GetString();
@@ -72,7 +72,7 @@ WorldPackets::Character::EnumCharactersResult::CharacterInfo::CharacterInfo(Fiel
if (fields[23].GetUInt64())
Flags |= CHARACTER_FLAG_LOCKED_BY_BILLING;
- if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED) && !fields[25].GetString().empty())
+ if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED) && !fields[26].GetString().empty())
Flags |= CHARACTER_FLAG_DECLINED;
if (atLoginFlags & AT_LOGIN_CUSTOMIZE)
@@ -102,6 +102,7 @@ WorldPackets::Character::EnumCharactersResult::CharacterInfo::CharacterInfo(Fiel
Tokenizer equipment(fields[22].GetString(), ' ');
ListPosition = fields[24].GetUInt8();
+ LastPlayedTime = fields[25].GetUInt32();
for (uint8 slot = 0; slot < INVENTORY_SLOT_BAG_END; ++slot)
{
@@ -155,6 +156,7 @@ WorldPacket const* WorldPackets::Character::EnumCharactersResult::Write()
_worldPacket << uint8(charInfo.VisualItems[slot].InventoryType);
}
+ _worldPacket << uint32(charInfo.LastPlayedTime);
_worldPacket.WriteBits(charInfo.Name.length(), 6);
_worldPacket.WriteBit(charInfo.FirstLogin);
_worldPacket.WriteBit(charInfo.BoostInProgress);
diff --git a/src/server/game/Server/Packets/CharacterPackets.h b/src/server/game/Server/Packets/CharacterPackets.h
index bb163b075cc..017dddd1d06 100644
--- a/src/server/game/Server/Packets/CharacterPackets.h
+++ b/src/server/game/Server/Packets/CharacterPackets.h
@@ -133,6 +133,7 @@ namespace WorldPackets
uint32 Flags3 = 0; ///< Character flags 3 @todo research
bool FirstLogin = false;
uint8 unkWod61x = 0;
+ uint32 LastPlayedTime = 0;
struct PetInfo
{
@@ -721,7 +722,7 @@ namespace WorldPackets
{
public:
SetPlayerDeclinedNames(WorldPacket&& packet) : ClientPacket(CMSG_SET_PLAYER_DECLINED_NAMES, std::move(packet)) { }
-
+
void Read() override;
ObjectGuid Player;
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index fe60f15a3f7..19aff2468a9 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -846,8 +846,8 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUCTION_WON_NOTIFICATION, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_AURA_POINTS_DEPLETED, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_AURA_UPDATE, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUTH_CHALLENGE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUTH_RESPONSE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUTH_CHALLENGE, STATUS_NEVER, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_AUTH_RESPONSE, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_AVAILABLE_VOICE_CHANNEL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BAN_REASON, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_BARBER_SHOP_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
@@ -1048,7 +1048,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ENCHANTMENT_LOG, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ENCOUNTER_END, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ENCOUNTER_START, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_ENUM_CHARACTERS_RESULT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_ENUM_CHARACTERS_RESULT, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_ENVIRONMENTAL_DAMAGE_LOG, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_EQUIPMENT_SET_ID, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_EXPECTED_SPAM_RECORDS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index 8cf122f77d8..84561dbd37e 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -20,10 +20,12 @@
#include "AuthenticationPackets.h"
#include "BigNumber.h"
#include "CharacterPackets.h"
+#include "HmacHash.h"
#include "Opcodes.h"
-#include "ScriptMgr.h"
-#include "SHA1.h"
#include "PacketLog.h"
+#include "ScriptMgr.h"
+#include "SessionKeyGeneration.h"
+#include "SHA256.h"
#include "World.h"
#include <zlib.h>
@@ -61,10 +63,15 @@ uint32 const WorldSocket::MinSizeForCompression = 0x400;
uint32 const SizeOfClientHeader[2] = { sizeof(uint16) + sizeof(uint16), sizeof(uint32) + sizeof(uint16) };
uint32 const SizeOfServerHeader[2] = { sizeof(uint16) + sizeof(uint16), sizeof(uint32) + sizeof(uint16) };
+uint8 const WorldSocket::AuthCheckSeed[16] = { 0xC5, 0xC6, 0x98, 0x95, 0x76, 0x3F, 0x1D, 0xCD, 0xB6, 0xA1, 0x37, 0x28, 0xB3, 0x12, 0xFF, 0x8A };
+uint8 const WorldSocket::SessionKeySeed[16] = { 0x58, 0xCB, 0xCF, 0x40, 0xFE, 0x2E, 0xCE, 0xA6, 0x5A, 0x90, 0xB8, 0x01, 0x68, 0x6C, 0x28, 0x0B };
+uint8 const WorldSocket::ContinuedSessionSeed[16] = { 0x16, 0xAD, 0x0C, 0xD4, 0x46, 0xF9, 0x4F, 0xB2, 0xEF, 0x7D, 0xEA, 0x2A, 0x17, 0x66, 0x4D, 0x2F };
+
WorldSocket::WorldSocket(tcp::socket&& socket) : Socket(std::move(socket)),
- _type(CONNECTION_TYPE_REALM), _authSeed(rand32()), _OverSpeedPings(0),
+ _type(CONNECTION_TYPE_REALM), _OverSpeedPings(0),
_worldSession(nullptr), _authed(false), _compressionStream(nullptr)
{
+ _serverChallenge.SetRand(8 * 16);
_headerBuffer.Resize(SizeOfClientHeader[0]);
}
@@ -244,7 +251,7 @@ void WorldSocket::HandleSendAuthSession()
_decryptSeed.SetRand(16 * 8);
WorldPackets::Auth::AuthChallenge challenge;
- challenge.Challenge = _authSeed;
+ memcpy(challenge.Challenge.data(), _serverChallenge.AsByteArray(16).get(), 16);
memcpy(&challenge.DosChallenge[0], _encryptSeed.AsByteArray(16).get(), 16);
memcpy(&challenge.DosChallenge[4], _decryptSeed.AsByteArray(16).get(), 16);
challenge.DosZeroBits = 1;
@@ -399,10 +406,9 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
}
std::shared_ptr<WorldPackets::Auth::AuthSession> authSession = std::make_shared<WorldPackets::Auth::AuthSession>(std::move(packet));
- //authSession->Read();
- //HandleAuthSession(authSession);
- //return ReadDataHandlerResult::WaitingForQuery;
- return ReadDataHandlerResult::Error;
+ authSession->Read();
+ HandleAuthSession(authSession);
+ return ReadDataHandlerResult::WaitingForQuery;
}
case CMSG_AUTH_CONTINUED_SESSION:
{
@@ -416,10 +422,9 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
}
std::shared_ptr<WorldPackets::Auth::AuthContinuedSession> authSession = std::make_shared<WorldPackets::Auth::AuthContinuedSession>(std::move(packet));
- //authSession->Read();
- //HandleAuthContinuedSession(authSession);
- //return ReadDataHandlerResult::WaitingForQuery;
- return ReadDataHandlerResult::Error;
+ authSession->Read();
+ HandleAuthContinuedSession(authSession);
+ return ReadDataHandlerResult::WaitingForQuery;
}
case CMSG_KEEP_ALIVE:
LogOpcodeText(opcode, sessionGuard);
@@ -594,7 +599,6 @@ struct AccountInfo
std::string LastIP;
std::string LockCountry;
LocaleConstant Locale;
- std::string OS;
bool IsBanned;
} BattleNet;
@@ -606,6 +610,7 @@ struct AccountInfo
uint8 Expansion;
int64 MuteTime;
uint32 Recruiter;
+ std::string OS;
bool IsRectuiter;
AccountTypes Security;
bool IsBanned;
@@ -615,8 +620,8 @@ struct AccountInfo
explicit AccountInfo(Field* fields)
{
- // 0 1 2 3 4 5 6 7 8 9 10 11
- // SELECT a.id, a.sessionkey, ba.last_ip, ba.locked, ba.lock_country, a.expansion, a.mutetime, ba.locale, a.recruiter, ba.os, ba.id, aa.gmLevel,
+ // 0 1 2 3 4 5 6 7 8 9 10 11
+ // SELECT a.id, a.sessionkey, ba.last_ip, ba.locked, ba.lock_country, a.expansion, a.mutetime, ba.locale, a.recruiter, a.os, ba.id, aa.gmLevel,
// 12 13 14
// bab.unbandate > UNIX_TIMESTAMP() OR bab.unbandate = bab.bandate, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, r.id
// FROM account a LEFT JOIN battlenet_accounts ba ON a.battlenet_account = ba.id LEFT JOIN account_access aa ON a.id = aa.id AND aa.RealmID IN (-1, ?)
@@ -631,7 +636,7 @@ struct AccountInfo
Game.MuteTime = fields[6].GetInt64();
BattleNet.Locale = LocaleConstant(fields[7].GetUInt8());
Game.Recruiter = fields[8].GetUInt32();
- BattleNet.OS = fields[9].GetString();
+ Game.OS = fields[9].GetString();
BattleNet.Id = fields[10].GetUInt32();
Game.Security = AccountTypes(fields[11].GetUInt8());
BattleNet.IsBanned = fields[12].GetUInt64() != 0;
@@ -655,7 +660,7 @@ void WorldSocket::HandleAuthSession(std::shared_ptr<WorldPackets::Auth::AuthSess
// Get the account information from the auth database
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME);
stmt->setInt32(0, int32(realm.Id.Realm));
- stmt->setString(1, authSession->Account);
+ stmt->setString(1, authSession->RealmJoinTicket);
_queryCallback = std::bind(&WorldSocket::HandleAuthSessionCallback, this, authSession, std::placeholders::_1);
_queryFuture = LoginDatabase.AsyncQuery(stmt);
@@ -667,7 +672,6 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth::
if (!result)
{
// We can not log here, as we do not know the account. Thus, no accountId.
- SendAuthResponseError(AUTH_UNKNOWN_ACCOUNT);
TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Sent Auth Response (unknown account).");
DelayedCloseSocket();
return;
@@ -678,16 +682,43 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth::
// For hook purposes, we get Remoteaddress at this point.
std::string address = GetRemoteIpAddress().to_string();
+ HmacSha256 hmac(SHA256_DIGEST_LENGTH, account.Game.SessionKey.AsByteArray(SHA256_DIGEST_LENGTH).get());
+ hmac.UpdateData(authSession->LocalChallenge.data(), authSession->LocalChallenge.size());
+ hmac.UpdateData(_serverChallenge.AsByteArray(16).get(), 16);
+ hmac.UpdateData(AuthCheckSeed, 16);
+ hmac.Finalize();
+
+ if (memcmp(hmac.GetDigest(), authSession->Digest.data(), authSession->Digest.size()) != 0)
+ {
+ TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", account.Game.Id, authSession->RealmJoinTicket.c_str(), address.c_str());
+ DelayedCloseSocket();
+ return;
+ }
+
+ HmacSha256 sessionKeyHmac(SHA256_DIGEST_LENGTH, account.Game.SessionKey.AsByteArray(SHA256_DIGEST_LENGTH).get());
+ sessionKeyHmac.UpdateData(_serverChallenge.AsByteArray(16).get(), 16);
+ sessionKeyHmac.UpdateData(authSession->LocalChallenge.data(), authSession->LocalChallenge.size());
+ sessionKeyHmac.UpdateData(SessionKeySeed, 16);
+ sessionKeyHmac.Finalize();
+
+ uint8 sessionKey[40];
+ SessionKeyGenerator<SHA256Hash> sessionKeyGenerator(sessionKeyHmac.GetDigest(), sessionKeyHmac.GetLength());
+ sessionKeyGenerator.Generate(sessionKey, 40);
+
+ BigNumber K;
+ K.SetBinary(sessionKey, 40);
+
+ // Check that Key and account name are the same on client and server
+ // only do this after verifying credentials - no error message is better than bad encryption making the client crash
+ _authCrypt.Init(&K);
+
// As we don't know if attempted login process by ip works, we update last_attempt_ip right away
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_ATTEMPT_IP);
stmt->setString(0, address);
- stmt->setString(1, authSession->Account);
+ stmt->setString(1, authSession->RealmJoinTicket);
LoginDatabase.Execute(stmt);
// This also allows to check for possible "hack" attempts on account
- // even if auth credentials are bad, try using the session key we have - client cannot read auth response error without it
- _authCrypt.Init(&account.Game.SessionKey);
-
// First reject the connection if packet contains invalid data or realm state doesn't allow logging in
if (sWorld->IsClosed())
{
@@ -708,37 +739,10 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth::
// Must be done before WorldSession is created
bool wardenActive = sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED);
- if (wardenActive && account.BattleNet.OS != "Win" && account.BattleNet.OS != "Wn64" && account.BattleNet.OS != "Mc64")
- {
- SendAuthResponseError(AUTH_REJECT);
- TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Client %s attempted to log in using invalid client OS (%s).", address.c_str(), account.BattleNet.OS.c_str());
- DelayedCloseSocket();
- return;
- }
-
- if (!account.BattleNet.Id || authSession->LoginServerType != 1)
+ if (wardenActive && account.Game.OS != "Win" && account.Game.OS != "Wn64" && account.Game.OS != "Mc64")
{
SendAuthResponseError(AUTH_REJECT);
- TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Client %s (%s) attempted to log in using deprecated login method (GRUNT).", authSession->Account.c_str(), address.c_str());
- DelayedCloseSocket();
- return;
- }
-
- // Check that Key and account name are the same on client and server
- uint32 t = 0;
-
- SHA1Hash sha;
- sha.UpdateData(authSession->Account);
- sha.UpdateData((uint8*)&t, 4);
- sha.UpdateData((uint8*)&authSession->LocalChallenge, 4);
- sha.UpdateData((uint8*)&_authSeed, 4);
- sha.UpdateBigNumbers(&account.Game.SessionKey, NULL);
- sha.Finalize();
-
- if (memcmp(sha.GetDigest(), authSession->Digest, SHA_DIGEST_LENGTH) != 0)
- {
- SendAuthResponseError(AUTH_FAILED);
- TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", account.Game.Id, authSession->Account.c_str(), address.c_str());
+ TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Client %s attempted to log in using invalid client OS (%s).", address.c_str(), account.Game.OS.c_str());
DelayedCloseSocket();
return;
}
@@ -802,13 +806,13 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth::
return;
}
- TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", authSession->Account.c_str(), address.c_str());
+ TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.", authSession->RealmJoinTicket.c_str(), address.c_str());
// Update the last_ip in the database as it was successful for login
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_IP);
stmt->setString(0, address);
- stmt->setString(1, authSession->Account);
+ stmt->setString(1, authSession->RealmJoinTicket);
LoginDatabase.Execute(stmt);
@@ -816,13 +820,13 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth::
sScriptMgr->OnAccountLogin(account.Game.Id);
_authed = true;
- _worldSession = new WorldSession(account.Game.Id, std::move(authSession->Account), account.BattleNet.Id, shared_from_this(), account.Game.Security,
+ _worldSession = new WorldSession(account.Game.Id, std::move(authSession->RealmJoinTicket), account.BattleNet.Id, shared_from_this(), account.Game.Security,
account.Game.Expansion, mutetime, account.BattleNet.Locale, account.Game.Recruiter, account.Game.IsRectuiter);
_worldSession->ReadAddonsInfo(authSession->AddonInfo);
// Initialize Warden system only if it is enabled by config
if (wardenActive)
- _worldSession->InitWarden(&account.Game.SessionKey, account.BattleNet.OS);
+ _worldSession->InitWarden(&account.Game.SessionKey, account.Game.OS);
_queryCallback = std::bind(&WorldSocket::LoadSessionPermissionsCallback, this, std::placeholders::_1);
_queryFuture = _worldSession->LoadPermissionsAsync();
@@ -881,13 +885,14 @@ void WorldSocket::HandleAuthContinuedSessionCallback(std::shared_ptr<WorldPacket
_authCrypt.Init(&k, _encryptSeed.AsByteArray().get(), _decryptSeed.AsByteArray().get());
- SHA1Hash sha;
- sha.UpdateData(login);
- sha.UpdateBigNumbers(&k, NULL);
- sha.UpdateData((uint8*)&_authSeed, 4);
- sha.Finalize();
+ HmacSha256 hmac(40, k.AsByteArray(40).get());
+ hmac.UpdateData(reinterpret_cast<uint8 const*>(&authSession->Key), sizeof(authSession->Key));
+ hmac.UpdateData(authSession->LocalChallenge.data(), authSession->LocalChallenge.size());
+ hmac.UpdateData(_serverChallenge.AsByteArray(16).get(), 16);
+ hmac.UpdateData(ContinuedSessionSeed, 16);
+ hmac.Finalize();
- if (memcmp(sha.GetDigest(), authSession->Digest, sha.GetLength()))
+ if (memcmp(hmac.GetDigest(), authSession->Digest.data(), authSession->Digest.size()))
{
SendAuthResponseError(AUTH_UNKNOWN_ACCOUNT);
TC_LOG_ERROR("network", "WorldSocket::HandleAuthContinuedSession: Authentication failed for account: %u ('%s') address: %s", accountId, login.c_str(), GetRemoteIpAddress().to_string().c_str());
diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h
index a77ce0d55a1..a5593e83521 100644
--- a/src/server/game/Server/WorldSocket.h
+++ b/src/server/game/Server/WorldSocket.h
@@ -74,6 +74,10 @@ class TC_GAME_API WorldSocket : public Socket<WorldSocket>
static std::string const ClientConnectionInitialize;
static uint32 const MinSizeForCompression;
+ static uint8 const AuthCheckSeed[16];
+ static uint8 const SessionKeySeed[16];
+ static uint8 const ContinuedSessionSeed[16];
+
typedef Socket<WorldSocket> BaseSocket;
public:
@@ -132,7 +136,7 @@ private:
ConnectionType _type;
- uint32 _authSeed;
+ BigNumber _serverChallenge;
WorldPacketCrypt _authCrypt;
BigNumber _encryptSeed;
BigNumber _decryptSeed;