Core/PacketIO: Increase max allowed incoming packet size for CMSG_HOTFIX_REQUEST

This commit is contained in:
Shauren
2021-03-02 01:06:28 +01:00
parent e381745664
commit 55eef73c48
6 changed files with 61 additions and 8 deletions

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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)

View File

@@ -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);

View File

@@ -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();

View File

@@ -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;