diff options
Diffstat (limited to 'src/server')
| -rw-r--r-- | src/server/game/Server/WorldSocket.cpp | 25 | ||||
| -rw-r--r-- | src/server/game/Server/WorldSocket.h | 8 |
2 files changed, 25 insertions, 8 deletions
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp index 0b0eeda6b86..3e22c91e2a1 100644 --- a/src/server/game/Server/WorldSocket.cpp +++ b/src/server/game/Server/WorldSocket.cpp @@ -71,11 +71,11 @@ uint8 const WorldSocket::EncryptionKeySeed[16] = { 0xE9, 0x75, 0x3C, 0x50, 0x90, WorldSocket::WorldSocket(tcp::socket&& socket) : Socket(std::move(socket)), _type(CONNECTION_TYPE_REALM), _key(0), _OverSpeedPings(0), - _worldSession(nullptr), _authed(false), _sendBufferSize(4096), _compressionStream(nullptr) + _worldSession(nullptr), _authed(false), _canRequestHotfixes(true), _sendBufferSize(4096), _compressionStream(nullptr) { Trinity::Crypto::GetRandomBytes(_serverChallenge); _encryptKey.fill(0); - _headerBuffer.Resize(sizeof(PacketHeader)); + _headerBuffer.Resize(sizeof(IncomingPacketHeader)); } WorldSocket::~WorldSocket() @@ -324,18 +324,26 @@ void WorldSocket::SetWorldSession(WorldSession* session) bool WorldSocket::ReadHeaderHandler() { - ASSERT(_headerBuffer.GetActiveSize() == sizeof(PacketHeader), "Header size " SZFMTD " different than expected " SZFMTD, _headerBuffer.GetActiveSize(), sizeof(PacketHeader)); + ASSERT(_headerBuffer.GetActiveSize() == sizeof(IncomingPacketHeader), "Header size " SZFMTD " different than expected " SZFMTD, _headerBuffer.GetActiveSize(), sizeof(IncomingPacketHeader)); - PacketHeader* header = reinterpret_cast<PacketHeader*>(_headerBuffer.GetReadPointer()); + IncomingPacketHeader* header = reinterpret_cast<IncomingPacketHeader*>(_headerBuffer.GetReadPointer()); + uint16 encryptedOpcode = header->EncryptedOpcode; if (!header->IsValidSize()) { - TC_LOG_ERROR("network", "WorldSocket::ReadHeaderHandler(): client %s sent malformed packet (size: %u)", - GetRemoteIpAddress().to_string().c_str(), header->Size); - return false; + _authCrypt.PeekDecryptRecv(reinterpret_cast<uint8*>(&header->EncryptedOpcode), sizeof(encryptedOpcode)); + + // CMSG_HOTFIX_REQUEST can be much larger than normal packets, allow receiving it once per session + if (header->EncryptedOpcode != CMSG_HOTFIX_REQUEST || header->Size > 0x100000 || !_canRequestHotfixes) + { + TC_LOG_ERROR("network", "WorldSocket::ReadHeaderHandler(): client %s sent malformed packet (size: %u, opcode %u)", + GetRemoteIpAddress().to_string().c_str(), header->Size, uint32(header->EncryptedOpcode)); + return false; + } } _packetBuffer.Resize(header->Size); + _packetBuffer.Write(&encryptedOpcode, sizeof(encryptedOpcode)); return true; } @@ -453,6 +461,9 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler() LogOpcodeText(opcode, sessionGuard); HandleEnterEncryptedModeAck(); break; + case CMSG_HOTFIX_REQUEST: + _canRequestHotfixes = false; + /* fallthrough */ default: { sessionGuard.lock(); diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h index da7890d4b07..5327db10ed6 100644 --- a/src/server/game/Server/WorldSocket.h +++ b/src/server/game/Server/WorldSocket.h @@ -57,7 +57,12 @@ struct PacketHeader uint32 Size; uint8 Tag[12]; - bool IsValidSize() { return Size < 0x40000; } + bool IsValidSize() { return Size < 0x10000; } +}; + +struct IncomingPacketHeader : PacketHeader +{ + uint16 EncryptedOpcode; }; #pragma pack(pop) @@ -142,6 +147,7 @@ private: std::mutex _worldSessionLock; WorldSession* _worldSession; bool _authed; + bool _canRequestHotfixes; MessageBuffer _headerBuffer; MessageBuffer _packetBuffer; |
