Core/NetworkIO: Moved SMSG_AUTH_CHALLENGE and CMSG_AUTH_SESSION to packet claases, added SMSG_COMPRESSED_PACKET

This commit is contained in:
Shauren
2014-10-31 01:20:53 +01:00
parent 1823e2f9b8
commit 7de1356085
12 changed files with 123 additions and 81 deletions

View File

@@ -1317,7 +1317,7 @@ void Object::AddDynamicValue(uint16 index, uint32 value)
}
}
void Object::RemoveDynamicValue(uint16 index, uint32 value)
void Object::RemoveDynamicValue(uint16 index, uint32 /*value*/)
{
ASSERT(index < _dynamicValuesCount || PrintIndexError(index, false));
/// TODO: Research if this is actually needed

View File

@@ -181,7 +181,7 @@ public:
inline static ObjectGuid MapSpecific(HighGuid type, uint8 subType, uint16 mapId, uint32 serverId, uint32 entry, ObjectGuid::LowType counter)
{
return ObjectGuid(uint64((uint64(type) << 58) | (uint64(realmHandle.Index & 0x1FFF) << 42) | (uint64(mapId & 0x1FFF) << 29) | (uint64(entry & 0x7FFFFF) << 6)),
return ObjectGuid(uint64((uint64(type) << 58) | (uint64(realmHandle.Index & 0x1FFF) << 42) | (uint64(mapId & 0x1FFF) << 29) | (uint64(entry & 0x7FFFFF) << 6) | (uint64(subType) & 0x3F)),
uint64((uint64(serverId & 0xFFFFFF) << 40) | (counter & UI64LIT(0xFFFFFFFFFF))));
}
};

View File

@@ -770,7 +770,6 @@ bool Pet::CreateBaseAtCreatureInfo(CreatureTemplate const* cinfo, Unit* owner)
bool Pet::CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map, uint32 phaseMask)
{
TC_LOG_DEBUG("entities.pet", "Pet::CreateBaseForTamed");
uint32 petId = sObjectMgr->GeneratePetNumber();
if (!Create(sObjectMgr->GetGenerator<HighGuid::Pet>()->Generate(), map, phaseMask, cinfo->Entry))
return false;

View File

@@ -48,6 +48,14 @@ namespace WorldPackets
size_t GetSize() const { return _worldPacket.size(); }
void Reset() { _worldPacket.clear(); }
};
class ClientPacket : public Packet
{
public:
ClientPacket(WorldPacket&& packet) : Packet(std::move(packet)) { }
void Write() override final { ASSERT(!"Write not allowed for client packets."); }
};
}
#endif

View File

@@ -17,6 +17,37 @@
#include "AuthenticationPackets.h"
void WorldPackets::Auth::AuthChallenge::Write()
{
_worldPacket << uint32(Challenge);
_worldPacket.append(DosChallenge, sizeof(DosChallenge));
_worldPacket << uint8(DosZeroBits);
}
void WorldPackets::Auth::AuthSession::Read()
{
uint32 addonDataSize;
_worldPacket >> LoginServerID;
_worldPacket >> Build;
_worldPacket >> RegionID;
_worldPacket >> BattlegroupID;
_worldPacket >> RealmID;
_worldPacket >> LoginServerType;
_worldPacket >> BuildType;
_worldPacket >> LocalChallenge;
_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);
}
}
WorldPackets::Auth::AuthResponse::AuthResponse()
: ServerPacket(SMSG_AUTH_RESPONSE, 132)
{
@@ -104,4 +135,4 @@ void WorldPackets::Auth::AuthResponse::Write()
}
_worldPacket.FlushBits();
}
}

View File

@@ -19,11 +19,49 @@
#include "Packet.h"
#include "Util.h"
#include <SHA1.h>
namespace WorldPackets
{
namespace Auth
{
class AuthChallenge final : public ServerPacket
{
public:
AuthChallenge() : ServerPacket(SMSG_AUTH_CHALLENGE, 8 + 32 + 1), Challenge(0) { }
void Write() override;
uint32 Challenge;
uint32 DosChallenge[8]; ///< Encryption seeds
uint8 DosZeroBits;
};
class AuthSession final : public ClientPacket
{
public:
AuthSession(WorldPacket&& packet) : ClientPacket(std::move(packet))
{
memset(Digest, 0, SHA_DIGEST_LENGTH);
}
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;
uint32 RegionID = 0;
uint64 DosResponse = 0;
uint8 Digest[SHA_DIGEST_LENGTH];
std::string Account;
bool UseIPv6 = false;
ByteBuffer AddonInfo;
};
class AuthResponse final : public ServerPacket
{
public:

View File

@@ -31,7 +31,6 @@ enum OpcodeMisc : uint32
NUM_OPCODE_HANDLERS = (MAX_OPCODE + 1),
UNKNOWN_OPCODE = (0xFFFF + 1),
NULL_OPCODE = 0,
COMPRESSED_OPCODE_MASK = 0x8000
};
// CMSGs
@@ -69,7 +68,7 @@ enum OpcodeClient : uint32
CMSG_AUCTION_PLACE_BID = 0x0000,
CMSG_AUCTION_REMOVE_ITEM = 0x0000,
CMSG_AUCTION_SELL_ITEM = 0x0000,
CMSG_AUTH_SESSION = 0x1B05,
CMSG_AUTH_SESSION = 0x0487,
CMSG_AUTOBANK_ITEM = 0x0000,
CMSG_AUTOEQUIP_GROUND_ITEM = 0x0000,
CMSG_AUTOEQUIP_ITEM = 0x0000,
@@ -712,8 +711,8 @@ enum OpcodeServer : uint32
SMSG_AURA_POINTS_DEPLETED = 0x0000,
SMSG_AURA_UPDATE = 0x128B,
SMSG_AURA_UPDATE_ALL = 0x0000,
SMSG_AUTH_CHALLENGE = 0x10AA,
SMSG_AUTH_RESPONSE = 0x0564,
SMSG_AUTH_CHALLENGE = 0x1759,
SMSG_AUTH_RESPONSE = 0x0DA9,
SMSG_AVAILABLE_VOICE_CHANNEL = 0x0000,
SMSG_AVERAGE_ITEM_LEVEL_INFORM = 0x0000,
SMSG_BARBER_SHOP_RESULT = 0x0000,
@@ -809,6 +808,7 @@ enum OpcodeServer : uint32
SMSG_COMMENTATOR_STATE_CHANGED = 0x0000,
SMSG_COMPLAIN_RESULT = 0x0000,
SMSG_COMPRESSED_MOVES = 0x0000,
SMSG_COMPRESSED_PACKET = 0x07CA,
SMSG_COMSAT_CONNECT_FAIL = 0x0000,
SMSG_COMSAT_DISCONNECT = 0x0000,
SMSG_COMSAT_RECONNECT_TRY = 0x0000,
@@ -1512,11 +1512,7 @@ inline std::string GetOpcodeNameForLogging(T id)
if (static_cast<uint32>(id) < UNKNOWN_OPCODE)
{
if (OpcodeHandler const* handler = opcodeTable[T(opcode & 0x7FFF)])
{
ss << handler->Name;
if (opcode & COMPRESSED_OPCODE_MASK)
ss << "_COMPRESSED";
}
else
ss << "UNKNOWN OPCODE";
}

View File

@@ -23,13 +23,12 @@
void WorldPacket::Compress(z_stream* compressionStream)
{
OpcodeServer uncompressedOpcode = static_cast<OpcodeServer>(GetOpcode());
if (uncompressedOpcode & COMPRESSED_OPCODE_MASK)
if (uncompressedOpcode == SMSG_COMPRESSED_PACKET)
{
TC_LOG_ERROR("network", "Packet with opcode 0x%04X is already compressed!", uncompressedOpcode);
return;
}
OpcodeServer opcode = OpcodeServer(uncompressedOpcode | COMPRESSED_OPCODE_MASK);
uint32 size = wpos();
uint32 destsize = compressBound(size);
@@ -41,11 +40,12 @@ void WorldPacket::Compress(z_stream* compressionStream)
return;
clear();
reserve(destsize + sizeof(uint32));
reserve(destsize + sizeof(uint32) * 2);
*this << uint32(uncompressedOpcode);
*this << uint32(size);
append(&storage[0], destsize);
SetOpcode(opcode);
TC_LOG_INFO("network", "%s (len %u) successfully compressed to %04X (len %u)", GetOpcodeNameForLogging(uncompressedOpcode).c_str(), size, opcode, destsize);
SetOpcode(SMSG_COMPRESSED_PACKET);
TC_LOG_INFO("network", "%s (len %u) successfully compressed to len %u", GetOpcodeNameForLogging(uncompressedOpcode).c_str(), size, destsize);
}
//! Compresses another packet and stores it in self (source left intact)
@@ -54,30 +54,29 @@ void WorldPacket::Compress(z_stream* compressionStream, WorldPacket const* sourc
ASSERT(source != this);
OpcodeServer uncompressedOpcode = static_cast<OpcodeServer>(source->GetOpcode());
if (uncompressedOpcode & COMPRESSED_OPCODE_MASK)
if (uncompressedOpcode == SMSG_COMPRESSED_PACKET)
{
TC_LOG_ERROR("network", "Packet with opcode 0x%04X is already compressed!", uncompressedOpcode);
return;
}
OpcodeServer opcode = OpcodeServer(uncompressedOpcode | COMPRESSED_OPCODE_MASK);
uint32 size = source->size();
uint32 destsize = compressBound(size);
size_t sizePos = 0;
resize(destsize + sizeof(uint32));
resize(destsize + sizeof(uint32) * 2);
_compressionStream = compressionStream;
Compress(static_cast<void*>(&_storage[0] + sizeof(uint32)), &destsize, static_cast<const void*>(source->contents()), size);
Compress(static_cast<void*>(&_storage[0] + sizeof(uint32) * 2), &destsize, static_cast<const void*>(source->contents()), size);
if (destsize == 0)
return;
put<uint32>(sizePos, size);
put<uint32>(0, uncompressedOpcode);
put<uint32>(4, size);
resize(destsize + sizeof(uint32));
SetOpcode(opcode);
SetOpcode(SMSG_COMPRESSED_PACKET);
TC_LOG_INFO("network", "%s (len %u) successfully compressed to %04X (len %u)", GetOpcodeNameForLogging(uncompressedOpcode).c_str(), size, opcode, destsize);
TC_LOG_INFO("network", "%s (len %u) successfully compressed to len %u", GetOpcodeNameForLogging(uncompressedOpcode).c_str(), size, destsize);
}
void WorldPacket::Compress(void* dst, uint32 *dst_size, const void* src, int src_size)

View File

@@ -65,7 +65,7 @@ class WorldPacket : public ByteBuffer
uint32 GetOpcode() const { return m_opcode; }
void SetOpcode(uint32 opcode) { m_opcode = opcode; }
bool IsCompressed() const { return (m_opcode & COMPRESSED_OPCODE_MASK) != 0; }
bool IsCompressed() const { return m_opcode == SMSG_COMPRESSED_PACKET; }
void Compress(z_stream_s* compressionStream);
void Compress(z_stream_s* compressionStream, WorldPacket const* source);

View File

@@ -806,7 +806,7 @@ void WorldSession::SaveTutorialsData(SQLTransaction &trans)
m_TutorialsChanged = false;
}
void WorldSession::ReadAddonsInfo(WorldPacket &data)
void WorldSession::ReadAddonsInfo(ByteBuffer& data)
{
if (data.rpos() + 4 > data.size())
return;

View File

@@ -268,7 +268,7 @@ class WorldSession
bool PlayerLogoutWithSave() const { return m_playerLogout && m_playerSave; }
bool PlayerRecentlyLoggedOut() const { return m_playerRecentlyLogout; }
void ReadAddonsInfo(WorldPacket& data);
void ReadAddonsInfo(ByteBuffer& data);
void SendAddonsInfo();
bool IsAddonRegistered(const std::string& prefix) const;

View File

@@ -63,19 +63,20 @@ void WorldSocket::Start()
void WorldSocket::HandleSendAuthSession()
{
WorldPacket packet(SMSG_AUTH_CHALLENGE, 37);
packet << uint32(_authSeed);
BigNumber seed1;
seed1.SetRand(16 * 8);
packet.append(seed1.AsByteArray(16).get(), 16); // new encryption seeds
BigNumber seed2;
seed1.SetRand(16 * 8);
seed2.SetRand(16 * 8);
packet.append(seed2.AsByteArray(16).get(), 16); // new encryption seeds
packet << uint8(1);
SendPacket(packet);
WorldPackets::Auth::AuthChallenge challenge;
challenge.Challenge = _authSeed;
memcpy(&challenge.DosChallenge[0], seed1.AsByteArray(16).get(), 16);
memcpy(&challenge.DosChallenge[4], seed2.AsByteArray(16).get(), 16);
challenge.DosZeroBits = 1;
challenge.Write();
SendPacket(challenge.GetWorldPacket());
}
void WorldSocket::ReadHandler()
@@ -334,50 +335,21 @@ void WorldSocket::SendPacket(WorldPacket& packet)
void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
{
uint8 digest[SHA_DIGEST_LENGTH];
uint32 clientSeed;
WorldPackets::Auth::AuthSession authSession(std::move(recvPacket));
authSession.Read();
uint8 security;
uint16 clientBuild;
uint32 id;
uint32 addonSize;
LocaleConstant locale;
std::string account;
SHA1Hash sha;
BigNumber k;
bool wardenActive = sWorld->getBoolConfig(CONFIG_WARDEN_ENABLED);
WorldPacket addonsData;
uint8 loginServerType;
uint32 realmIndex;
recvPacket.read_skip<uint32>(); // Grunt - ServerId
recvPacket >> clientBuild;
recvPacket.read_skip<uint32>(); // Region
recvPacket.read_skip<uint32>(); // Battlegroup
recvPacket >> realmIndex;
recvPacket >> loginServerType; // could be swapped with other uint8 (both always 1)
recvPacket.read_skip<uint8>();
recvPacket >> clientSeed;
recvPacket.read_skip<uint64>(); // DosResponse
for (int i = 0; i < SHA_DIGEST_LENGTH; i++)
recvPacket >> digest[i];
uint32 accountNameLength = recvPacket.ReadBits(11);
account = recvPacket.ReadString(accountNameLength);
recvPacket.ReadBit(); // UseIPv6
recvPacket >> addonSize;
if (addonSize)
{
addonsData.resize(addonSize);
recvPacket.read((uint8*)addonsData.contents(), addonSize);
}
// Get the account information from the auth database
// 0 1 2 3 4 5 6 7 8
// SELECT id, sessionkey, last_ip, locked, expansion, mutetime, locale, recruiter, os FROM account WHERE username = ?
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME);
stmt->setString(0, account);
stmt->setString(0, authSession.Account);
PreparedQueryResult result = LoginDatabase.Query(stmt);
@@ -405,7 +377,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_ATTEMPT_IP);
stmt->setString(0, address);
stmt->setString(1, account);
stmt->setString(1, authSession.Account);
LoginDatabase.Execute(stmt);
// This also allows to check for possible "hack" attempts on account
@@ -428,7 +400,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
return;
}
if (realmIndex != realmHandle.Index)
if (authSession.RealmID != realmHandle.Index)
{
SendAuthResponseError(REALM_LIST_REALM_NOT_FOUND);
TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Sent Auth Response (bad realm).");
@@ -450,17 +422,17 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
// Check that Key and account name are the same on client and server
uint32 t = 0;
sha.UpdateData(account);
sha.UpdateData(authSession.Account);
sha.UpdateData((uint8*)&t, 4);
sha.UpdateData((uint8*)&clientSeed, 4);
sha.UpdateData((uint8*)&authSession.LocalChallenge, 4);
sha.UpdateData((uint8*)&_authSeed, 4);
sha.UpdateBigNumbers(&k, NULL);
sha.Finalize();
if (memcmp(sha.GetDigest(), digest, SHA_DIGEST_LENGTH) != 0)
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", id, account.c_str(), address.c_str());
TC_LOG_ERROR("network", "WorldSocket::HandleAuthSession: Authentication failed for account: %u ('%s') address: %s", id, authSession.Account.c_str(), address.c_str());
DelayedCloseSocket();
return;
}
@@ -500,7 +472,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
uint32 recruiter = fields[7].GetUInt32();
uint32 battlenetAccountId = 0;
if (loginServerType == 1)
if (authSession.LoginServerType == 1)
battlenetAccountId = Battlenet::AccountMgr::GetIdByGameAccount(id);
// Checks gmlevel per Realm
@@ -549,8 +521,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
}
TC_LOG_DEBUG("network", "WorldSocket::HandleAuthSession: Client '%s' authenticated successfully from %s.",
account.c_str(),
address.c_str());
authSession.Account.c_str(), address.c_str());
// Check if this user is by any chance a recruiter
stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_RECRUITER);
@@ -567,7 +538,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_LAST_IP);
stmt->setString(0, address);
stmt->setString(1, account);
stmt->setString(1, authSession.Account);
LoginDatabase.Execute(stmt);
@@ -577,7 +548,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
_worldSession = new WorldSession(id, battlenetAccountId, shared_from_this(), AccountTypes(security), expansion, mutetime, locale, recruiter, isRecruiter);
_worldSession->LoadGlobalAccountData();
_worldSession->LoadTutorialsData();
_worldSession->ReadAddonsInfo(addonsData);
_worldSession->ReadAddonsInfo(authSession.AddonInfo);
_worldSession->LoadPermissions();
// Initialize Warden system only if it is enabled by config