diff options
-rw-r--r-- | src/server/game/Entities/Object/Object.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Object/ObjectGuid.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Entities/Pet/Pet.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Server/Packet.h | 8 | ||||
-rw-r--r-- | src/server/game/Server/Packets/AuthenticationPackets.cpp | 33 | ||||
-rw-r--r-- | src/server/game/Server/Packets/AuthenticationPackets.h | 38 | ||||
-rw-r--r-- | src/server/game/Server/Protocol/Opcodes.h | 12 | ||||
-rw-r--r-- | src/server/game/Server/WorldPacket.cpp | 25 | ||||
-rw-r--r-- | src/server/game/Server/WorldPacket.h | 2 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Server/WorldSession.h | 2 | ||||
-rw-r--r-- | src/server/game/Server/WorldSocket.cpp | 77 |
12 files changed, 123 insertions, 81 deletions
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index 6fc422c65cf..fa9634add80 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -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 diff --git a/src/server/game/Entities/Object/ObjectGuid.cpp b/src/server/game/Entities/Object/ObjectGuid.cpp index b51493bcd23..126916c4364 100644 --- a/src/server/game/Entities/Object/ObjectGuid.cpp +++ b/src/server/game/Entities/Object/ObjectGuid.cpp @@ -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)))); } }; diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 083d08cc41a..e9799a3c648 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -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; diff --git a/src/server/game/Server/Packet.h b/src/server/game/Server/Packet.h index ebfa5c302a9..bda0166098d 100644 --- a/src/server/game/Server/Packet.h +++ b/src/server/game/Server/Packet.h @@ -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 diff --git a/src/server/game/Server/Packets/AuthenticationPackets.cpp b/src/server/game/Server/Packets/AuthenticationPackets.cpp index 1d20c582b0b..c64ef37d320 100644 --- a/src/server/game/Server/Packets/AuthenticationPackets.cpp +++ b/src/server/game/Server/Packets/AuthenticationPackets.cpp @@ -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(); -}
\ No newline at end of file +} diff --git a/src/server/game/Server/Packets/AuthenticationPackets.h b/src/server/game/Server/Packets/AuthenticationPackets.h index dd5fea06e10..41b3d7cb257 100644 --- a/src/server/game/Server/Packets/AuthenticationPackets.h +++ b/src/server/game/Server/Packets/AuthenticationPackets.h @@ -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: diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h index bd56173ba38..5c995664dbb 100644 --- a/src/server/game/Server/Protocol/Opcodes.h +++ b/src/server/game/Server/Protocol/Opcodes.h @@ -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"; } diff --git a/src/server/game/Server/WorldPacket.cpp b/src/server/game/Server/WorldPacket.cpp index a1a9b15f20b..ab2c0b089e2 100644 --- a/src/server/game/Server/WorldPacket.cpp +++ b/src/server/game/Server/WorldPacket.cpp @@ -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) diff --git a/src/server/game/Server/WorldPacket.h b/src/server/game/Server/WorldPacket.h index 7c36f8f2321..9e29026ba05 100644 --- a/src/server/game/Server/WorldPacket.h +++ b/src/server/game/Server/WorldPacket.h @@ -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); diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp index 2332829e69a..9e22e294a0a 100644 --- a/src/server/game/Server/WorldSession.cpp +++ b/src/server/game/Server/WorldSession.cpp @@ -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; diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h index 254532bcf4c..ef29f0da7e6 100644 --- a/src/server/game/Server/WorldSession.h +++ b/src/server/game/Server/WorldSession.h @@ -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; diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index e9200eae84c..25ed950a37c 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -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 |