aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/bnetserver/Packets/WoWRealmPackets.cpp7
-rw-r--r--src/server/game/Server/Protocol/ServerPktHeader.h40
-rw-r--r--src/server/game/Server/WorldSocket.cpp82
-rw-r--r--src/server/game/Server/WorldSocket.h25
-rw-r--r--src/server/shared/Cryptography/Authentication/WorldPacketCrypt.cpp4
5 files changed, 94 insertions, 64 deletions
diff --git a/src/server/bnetserver/Packets/WoWRealmPackets.cpp b/src/server/bnetserver/Packets/WoWRealmPackets.cpp
index 714c43b8eb4..4ea34a7e173 100644
--- a/src/server/bnetserver/Packets/WoWRealmPackets.cpp
+++ b/src/server/bnetserver/Packets/WoWRealmPackets.cpp
@@ -42,10 +42,12 @@ void Battlenet::WoWRealm::ListUnsubscribe::CallHandler(Session* session)
void Battlenet::WoWRealm::JoinRequestV2::Read()
{
+ ClientSeed = _stream.Read<uint32>(32);
+ _stream.Read<uint32>(20);
+ Realm.Region = _stream.Read<uint8>(8);
+ _stream.Read<uint16>(12);
Realm.Battlegroup = _stream.Read<uint8>(8);
Realm.Index = _stream.Read<uint32>(32);
- Realm.Region = _stream.Read<uint8>(8);
- ClientSeed = _stream.Read<uint32>(32);
}
std::string Battlenet::WoWRealm::JoinRequestV2::ToString() const
@@ -194,7 +196,6 @@ std::string Battlenet::WoWRealm::ToonReady::ToString() const
void Battlenet::WoWRealm::JoinResponseV2::Write()
{
- _stream.Write(0, 27);
_stream.Write(Response, 1);
if (Response == SUCCESS)
{
diff --git a/src/server/game/Server/Protocol/ServerPktHeader.h b/src/server/game/Server/Protocol/ServerPktHeader.h
index fcb24cfa80d..edd0057d8d1 100644
--- a/src/server/game/Server/Protocol/ServerPktHeader.h
+++ b/src/server/game/Server/Protocol/ServerPktHeader.h
@@ -19,43 +19,23 @@
#ifndef __SERVERPKTHDR_H__
#define __SERVERPKTHDR_H__
-#include "Log.h"
-
#pragma pack(push, 1)
-struct ServerPktHeader
+union ServerPktHeader
{
- /**
- * size is the length of the payload _plus_ the length of the opcode
- */
- ServerPktHeader(uint32 size, uint16 cmd) : size(size)
- {
- uint8 headerIndex=0;
- if (isLargePacket())
- {
- TC_LOG_DEBUG("network", "initializing large server to client packet. Size: %u, cmd: %u", size, cmd);
- header[headerIndex++] = 0x80 | (0xFF & (size >> 16));
- }
- header[headerIndex++] = 0xFF &(size >> 8);
- header[headerIndex++] = 0xFF & size;
+ static uint32 const SizeOf[2];
- header[headerIndex++] = 0xFF & cmd;
- header[headerIndex++] = 0xFF & (cmd >> 8);
- }
-
- uint8 getHeaderLength()
+ struct
{
- // cmd = 2 bytes, size= 2||3bytes
- return 2 + (isLargePacket() ? 3 : 2);
- }
+ uint16 Size;
+ uint32 Command;
+ } Setup;
- bool isLargePacket() const
+ struct
{
- return size > 0x7FFF;
- }
-
- const uint32 size;
- uint8 header[5];
+ uint32 Command : 13;
+ uint32 Size : 19;
+ } Normal;
};
#pragma pack(pop)
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index 639f2234973..c26da27fc80 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -32,11 +32,18 @@ std::string const WorldSocket::ServerConnectionInitialize("WORLD OF WARCRAFT CON
std::string const WorldSocket::ClientConnectionInitialize("WORLD OF WARCRAFT CONNECTION - CLIENT TO SERVER");
+uint32 const ClientPktHeader::SizeOf[2][2] =
+{
+ { 2, 0 },
+ { 6, 4 }
+};
+
+uint32 const ServerPktHeader::SizeOf[2] = { sizeof(uint16) + sizeof(uint32), sizeof(uint32) };
WorldSocket::WorldSocket(tcp::socket&& socket)
: Socket(std::move(socket)), _authSeed(rand32()), _OverSpeedPings(0), _worldSession(nullptr), _initialized(false)
{
- _headerBuffer.Resize(2);
+ _headerBuffer.Resize(ClientPktHeader::SizeOf[0][0]);
}
void WorldSocket::Start()
@@ -44,8 +51,9 @@ void WorldSocket::Start()
AsyncRead();
MessageBuffer initializer;
- ServerPktHeader header(ServerConnectionInitialize.size(), 0);
- initializer.Write(header.header, header.getHeaderLength() - 2);
+ ServerPktHeader header;
+ header.Setup.Size = ServerConnectionInitialize.size();
+ initializer.Write(&header, sizeof(header.Setup.Size));
initializer.Write(ServerConnectionInitialize.c_str(), ServerConnectionInitialize.length());
std::unique_lock<std::mutex> dummy(_writeLock, std::defer_lock);
@@ -122,38 +130,51 @@ void WorldSocket::ReadHandler()
AsyncRead();
}
+void WorldSocket::ExtractOpcodeAndSize(ClientPktHeader const* header, uint32& opcode, uint32& size) const
+{
+ if (_authCrypt.IsInitialized())
+ {
+ opcode = header->Normal.Command;
+ size = header->Normal.Size;
+ }
+ else
+ {
+ opcode = header->Setup.Command;
+ size = header->Setup.Size;
+ if (_initialized)
+ size -= 4;
+ }
+}
+
bool WorldSocket::ReadHeaderHandler()
{
- ASSERT(_headerBuffer.GetActiveSize() == (_initialized ? sizeof(ClientPktHeader) : 2));
+ ASSERT(_headerBuffer.GetActiveSize() == ClientPktHeader::SizeOf[_initialized][_authCrypt.IsInitialized()], "Header size %u different than expected %u", _headerBuffer.GetActiveSize(), ClientPktHeader::SizeOf[_initialized][_authCrypt.IsInitialized()]);
_authCrypt.DecryptRecv(_headerBuffer.GetReadPointer(), _headerBuffer.GetActiveSize());
ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(_headerBuffer.GetReadPointer());
- EndianConvertReverse(header->size);
+ uint32 opcode;
+ uint32 size;
- if (_initialized)
- EndianConvert(header->cmd);
+ ExtractOpcodeAndSize(header, opcode, size);
- if (!header->IsValidSize() || (_initialized && !header->IsValidOpcode()))
+ if (!ClientPktHeader::IsValidSize(size) || (_initialized && !ClientPktHeader::IsValidOpcode(opcode)))
{
if (_worldSession)
{
Player* player = _worldSession->GetPlayer();
TC_LOG_ERROR("network", "WorldSocket::ReadHeaderHandler(): client (account: %u, char [GUID: %u, name: %s]) sent malformed packet (size: %hu, cmd: %u)",
- _worldSession->GetAccountId(), player ? player->GetGUIDLow() : 0, player ? player->GetName().c_str() : "<none>", header->size, header->cmd);
+ _worldSession->GetAccountId(), player ? player->GetGUIDLow() : 0, player ? player->GetName().c_str() : "<none>", size, opcode);
}
else
TC_LOG_ERROR("network", "WorldSocket::ReadHeaderHandler(): client %s sent malformed packet (size: %hu, cmd: %u)",
- GetRemoteIpAddress().to_string().c_str(), header->size, header->cmd);
+ GetRemoteIpAddress().to_string().c_str(), size, opcode);
CloseSocket();
return false;
}
- if (_initialized)
- header->size -= sizeof(header->cmd);
-
- _packetBuffer.Resize(header->size);
+ _packetBuffer.Resize(size);
return true;
}
@@ -162,8 +183,12 @@ bool WorldSocket::ReadDataHandler()
if (_initialized)
{
ClientPktHeader* header = reinterpret_cast<ClientPktHeader*>(_headerBuffer.GetReadPointer());
+ uint32 cmd;
+ uint32 size;
- Opcodes opcode = Opcodes(header->cmd);
+ ExtractOpcodeAndSize(header, cmd, size);
+
+ Opcodes opcode = Opcodes(cmd);
std::string opcodeName = GetOpcodeNameForLogging(opcode);
@@ -250,7 +275,7 @@ bool WorldSocket::ReadDataHandler()
}
_initialized = true;
- _headerBuffer.Resize(sizeof(ClientPktHeader));
+ _headerBuffer.Resize(ClientPktHeader::SizeOf[1][0]);
_packetBuffer.Reset();
HandleSendAuthSession();
}
@@ -271,24 +296,34 @@ void WorldSocket::SendPacket(WorldPacket& packet)
TC_LOG_TRACE("network.opcode", "S->C: %s %s", (_worldSession ? _worldSession->GetPlayerInfo() : GetRemoteIpAddress().to_string()).c_str(), GetOpcodeNameForLogging(packet.GetOpcode()).c_str());
- ServerPktHeader header(packet.size() + 2, packet.GetOpcode());
-
std::unique_lock<std::mutex> guard(_writeLock);
- _authCrypt.EncryptSend(header.header, header.getHeaderLength());
+ ServerPktHeader header;
+ uint32 sizeOfHeader = ServerPktHeader::SizeOf[_authCrypt.IsInitialized()];
+ if (_authCrypt.IsInitialized())
+ {
+ header.Normal.Size = packet.size();
+ header.Normal.Command = packet.GetOpcode();
+ _authCrypt.EncryptSend((uint8*)&header, sizeOfHeader);
+ }
+ else
+ {
+ header.Setup.Size = packet.size() + 4;
+ header.Setup.Command = packet.GetOpcode();
+ }
#ifndef TC_SOCKET_USE_IOCP
- if (_writeQueue.empty() && _writeBuffer.GetRemainingSpace() >= header.getHeaderLength() + packet.size())
+ if (_writeQueue.empty() && _writeBuffer.GetRemainingSpace() >= sizeOfHeader + packet.size())
{
- _writeBuffer.Write(header.header, header.getHeaderLength());
+ _writeBuffer.Write((uint8*)&header, sizeOfHeader);
if (!packet.empty())
_writeBuffer.Write(packet.contents(), packet.size());
}
else
#endif
{
- MessageBuffer buffer(header.getHeaderLength() + packet.size());
- buffer.Write(header.header, header.getHeaderLength());
+ MessageBuffer buffer(sizeOfHeader + packet.size());
+ buffer.Write((uint8*)&header, sizeOfHeader);
if (!packet.empty())
buffer.Write(packet.contents(), packet.size());
@@ -381,6 +416,7 @@ void WorldSocket::HandleAuthSession(WorldPacket& recvPacket)
// even if auth credentials are bad, try using the session key we have - client cannot read auth response error without it
_authCrypt.Init(&k);
+ _headerBuffer.Resize(ClientPktHeader::SizeOf[1][1]);
// First reject the connection if packet contains invalid data or realm state doesn't allow logging in
if (sWorld->IsClosed())
diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h
index 46614afd3bd..9928e0d5afa 100644
--- a/src/server/game/Server/WorldSocket.h
+++ b/src/server/game/Server/WorldSocket.h
@@ -34,13 +34,24 @@ using boost::asio::ip::tcp;
#pragma pack(push, 1)
-struct ClientPktHeader
+union ClientPktHeader
{
- uint16 size;
- uint32 cmd;
-
- bool IsValidSize() const { return size >= 4 && size < 10240; }
- bool IsValidOpcode() const { return cmd < NUM_OPCODE_HANDLERS; }
+ static uint32 const SizeOf[2][2];
+
+ struct
+ {
+ uint16 Size;
+ uint32 Command;
+ } Setup;
+
+ struct
+ {
+ uint32 Command : 13;
+ uint32 Size : 19;
+ } Normal;
+
+ static bool IsValidSize(uint32 size) { return size < 10240; }
+ static bool IsValidOpcode(uint32 opcode) { return opcode < NUM_OPCODE_HANDLERS; }
};
#pragma pack(pop)
@@ -73,6 +84,8 @@ private:
void HandlePing(WorldPacket& recvPacket);
+ void ExtractOpcodeAndSize(ClientPktHeader const* header, uint32& opcode, uint32& size) const;
+
uint32 _authSeed;
WorldPacketCrypt _authCrypt;
diff --git a/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.cpp b/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.cpp
index b9d9b86005c..69198c18df0 100644
--- a/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.cpp
+++ b/src/server/shared/Cryptography/Authentication/WorldPacketCrypt.cpp
@@ -28,11 +28,11 @@ WorldPacketCrypt::WorldPacketCrypt() : PacketCrypt(SHA_DIGEST_LENGTH)
void WorldPacketCrypt::Init(BigNumber* K)
{
- uint8 ServerEncryptionKey[SEED_KEY_SIZE] = { 0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57 };
+ uint8 ServerEncryptionKey[SEED_KEY_SIZE] = { 0x08, 0xF1, 0x95, 0x9F, 0x47, 0xE5, 0xD2, 0xDB, 0xA1, 0x3D, 0x77, 0x8F, 0x3F, 0x3E, 0xE7, 0x00 };
HmacSha1 serverEncryptHmac(SEED_KEY_SIZE, (uint8*)ServerEncryptionKey);
uint8 *encryptHash = serverEncryptHmac.ComputeHash(K);
- uint8 ServerDecryptionKey[SEED_KEY_SIZE] = { 0xC2, 0xB3, 0x72, 0x3C, 0xC6, 0xAE, 0xD9, 0xB5, 0x34, 0x3C, 0x53, 0xEE, 0x2F, 0x43, 0x67, 0xCE };
+ uint8 ServerDecryptionKey[SEED_KEY_SIZE] = { 0x40, 0xAA, 0xD3, 0x92, 0x26, 0x71, 0x43, 0x47, 0x3A, 0x31, 0x08, 0xA6, 0xE7, 0xDC, 0x98, 0x2A };
HmacSha1 clientDecryptHmac(SEED_KEY_SIZE, (uint8*)ServerDecryptionKey);
uint8 *decryptHash = clientDecryptHmac.ComputeHash(K);