mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-15 23:20:36 +01:00
Core/PacketIO: Increase max allowed incoming packet size for CMSG_HOTFIX_REQUEST
This commit is contained in:
@@ -63,3 +63,25 @@ bool Trinity::Crypto::AES::Process(IV const& iv, uint8* data, size_t length, Tag
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Trinity::Crypto::AES::ProcessNoIntegrityCheck(IV const& iv, uint8* data, size_t partialLength)
|
||||
{
|
||||
ASSERT(!_encrypting, "Partial encryption is not allowed");
|
||||
ASSERT(partialLength <= std::numeric_limits<int>::max());
|
||||
int len = static_cast<int>(partialLength);
|
||||
if (!EVP_CipherInit_ex(_ctx, nullptr, nullptr, nullptr, iv.data(), -1))
|
||||
return false;
|
||||
|
||||
int outLen;
|
||||
if (!EVP_CipherUpdate(_ctx, data, &outLen, data, len))
|
||||
return false;
|
||||
|
||||
len -= outLen;
|
||||
|
||||
if (!EVP_CipherFinal_ex(_ctx, data + outLen, &outLen))
|
||||
return false;
|
||||
|
||||
ASSERT(len == outLen);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ namespace Crypto
|
||||
void Init(Key const& key);
|
||||
|
||||
bool Process(IV const& iv, uint8* data, size_t length, Tag& tag);
|
||||
bool ProcessNoIntegrityCheck(IV const& iv, uint8* data, size_t partialLength);
|
||||
|
||||
private:
|
||||
EVP_CIPHER_CTX* _ctx;
|
||||
|
||||
@@ -41,6 +41,18 @@ struct WorldPacketCryptIV
|
||||
std::array<uint8, 12> Value;
|
||||
};
|
||||
|
||||
bool WorldPacketCrypt::PeekDecryptRecv(uint8* data, size_t length)
|
||||
{
|
||||
if (_initialized)
|
||||
{
|
||||
WorldPacketCryptIV iv{ _clientCounter, 0x544E4C43 };
|
||||
if (!_clientDecrypt.ProcessNoIntegrityCheck(iv.Value, data, length))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WorldPacketCrypt::DecryptRecv(uint8* data, size_t length, Trinity::Crypto::AES::Tag& tag)
|
||||
{
|
||||
if (_initialized)
|
||||
|
||||
@@ -27,6 +27,7 @@ public:
|
||||
WorldPacketCrypt();
|
||||
|
||||
void Init(Trinity::Crypto::AES::Key const& key);
|
||||
bool PeekDecryptRecv(uint8* data, size_t length);
|
||||
bool DecryptRecv(uint8* data, size_t length, Trinity::Crypto::AES::Tag& tag);
|
||||
bool EncryptSend(uint8* data, size_t length, Trinity::Crypto::AES::Tag& tag);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user