* Use different crypt types for different client versions
TODO: TBC is completely missing
This commit is contained in:
parent
bee304a453
commit
e8a10d26f1
@ -4,11 +4,17 @@
|
||||
#include "WorldSocket.h"
|
||||
#include "Opcodes.h"
|
||||
|
||||
|
||||
|
||||
WorldSocket::WorldSocket(SocketHandler &h, WorldSession *s) : TcpSocket(h)
|
||||
{
|
||||
_session = s;
|
||||
_gothdr = false;
|
||||
_ok=false;
|
||||
|
||||
//Dummy functions for unencrypted packets on WorldSocket
|
||||
pDecryptRecv = &AuthCrypt::DecryptRecvDummy;
|
||||
pEncryptSend = &AuthCrypt::EncryptSendDummy;
|
||||
}
|
||||
|
||||
bool WorldSocket::IsOk(void)
|
||||
@ -78,31 +84,43 @@ void WorldSocket::OnRead()
|
||||
break;
|
||||
}
|
||||
|
||||
// read first byte and check if size is 3 or 2 bytes
|
||||
uint8 firstSizeByte;
|
||||
ibuf.Read((char*)&firstSizeByte, 1);
|
||||
_crypt.DecryptRecv(&firstSizeByte, 1);
|
||||
|
||||
if (firstSizeByte & 0x80) // got large packet
|
||||
if(GetSession()->GetInstance()->GetConf()->clientbuild > 6005)
|
||||
{
|
||||
ServerPktHeaderBig hdr;
|
||||
ibuf.Read(((char*)&hdr) + 1, sizeof(ServerPktHeaderBig) - 1); // read *big* header, except first byte
|
||||
_crypt.DecryptRecv(((uint8*)&hdr) + 1, sizeof(ServerPktHeaderBig) - 1); // decrypt 2 of 3 bytes (first one already decrypted above) of size, and cmd
|
||||
hdr.size[0] = firstSizeByte; // assign missing first byte
|
||||
// read first byte and check if size is 3 or 2 bytes
|
||||
uint8 firstSizeByte;
|
||||
ibuf.Read((char*)&firstSizeByte, 1);
|
||||
(_crypt.*pDecryptRecv)(&firstSizeByte, 1);
|
||||
if (firstSizeByte & 0x80) // got large packet
|
||||
{
|
||||
ServerPktHeaderBig hdr;
|
||||
ibuf.Read(((char*)&hdr) + 1, sizeof(ServerPktHeaderBig) - 1); // read *big* header, except first byte
|
||||
(_crypt.*pDecryptRecv)(((uint8*)&hdr) + 1, sizeof(ServerPktHeaderBig) - 1); // decrypt 2 of 3 bytes (first one already decrypted above) of size, and cmd
|
||||
hdr.size[0] = firstSizeByte; // assign missing first byte
|
||||
|
||||
uint32 realsize = ((hdr.size[0]&0x7F) << 16) | (hdr.size[1] << 8) | hdr.size[2];
|
||||
_remaining = realsize - 2;
|
||||
_opcode = hdr.cmd;
|
||||
uint32 realsize = ((hdr.size[0]&0x7F) << 16) | (hdr.size[1] << 8) | hdr.size[2];
|
||||
_remaining = realsize - 2;
|
||||
_opcode = hdr.cmd;
|
||||
}
|
||||
else // "normal" packet
|
||||
{
|
||||
ServerPktHeader hdr;
|
||||
ibuf.Read(((char*)&hdr) + 1, sizeof(ServerPktHeader) - 1); // read header, except first byte
|
||||
(_crypt.*pDecryptRecv)(((uint8*)&hdr) + 1, sizeof(ServerPktHeader) - 1); // decrypt all except first
|
||||
hdr.size |= firstSizeByte; // add already decrypted first byte
|
||||
|
||||
_remaining = ntohs(hdr.size) - 2;
|
||||
_opcode = hdr.cmd;
|
||||
}
|
||||
}
|
||||
else // "normal" packet
|
||||
else
|
||||
{
|
||||
ServerPktHeader hdr;
|
||||
ibuf.Read(((char*)&hdr) + 1, sizeof(ServerPktHeader) - 1); // read header, except first byte
|
||||
_crypt.DecryptRecv(((uint8*)&hdr) + 1, sizeof(ServerPktHeader) - 1); // decrypt all except first
|
||||
hdr.size |= firstSizeByte; // add already decrypted first byte
|
||||
ServerPktHeader hdr;
|
||||
ibuf.Read(((char*)&hdr), sizeof(ServerPktHeader)); // read header, except first byte
|
||||
(_crypt.*pDecryptRecv)(((uint8*)&hdr), sizeof(ServerPktHeader)); // decrypt all except first
|
||||
|
||||
_remaining = ntohs(hdr.size) - 2;
|
||||
_opcode = hdr.cmd;
|
||||
_remaining = ntohs(hdr.size) - 2;
|
||||
_opcode = hdr.cmd;
|
||||
|
||||
}
|
||||
|
||||
if(_opcode > MAX_OPCODE_ID)
|
||||
@ -114,7 +132,6 @@ void WorldSocket::OnRead()
|
||||
// TODO: invent some way how to recover the crypt (reconnect?)
|
||||
return;
|
||||
}
|
||||
|
||||
// the header is fine, now check if there are more data
|
||||
if(_remaining == 0) // this is a packet with no data (like CMSG_NULL_ACTION)
|
||||
{
|
||||
@ -138,7 +155,7 @@ void WorldSocket::SendWorldPacket(WorldPacket &pkt)
|
||||
memset(&hdr,0,sizeof(ClientPktHeader));
|
||||
hdr.size = ntohs(pkt.size()+4);
|
||||
hdr.cmd = pkt.GetOpcode();
|
||||
_crypt.EncryptSend((uint8*)&hdr, 6);
|
||||
(_crypt.*pEncryptSend)((uint8*)&hdr, 6);
|
||||
ByteBuffer final(pkt.size()+6);
|
||||
final.append((uint8*)&hdr,sizeof(ClientPktHeader));
|
||||
if(pkt.size())
|
||||
@ -148,7 +165,27 @@ void WorldSocket::SendWorldPacket(WorldPacket &pkt)
|
||||
|
||||
void WorldSocket::InitCrypt(BigNumber *k)
|
||||
{
|
||||
_crypt.Init(k);
|
||||
//As crypt
|
||||
switch(GetSession()->GetInstance()->GetConf()->clientbuild)
|
||||
{
|
||||
case 6005:
|
||||
{
|
||||
logdebug("Setting Crypt to Build 6005");
|
||||
pInit = &AuthCrypt::Init_6005;
|
||||
pDecryptRecv = &AuthCrypt::DecryptRecv_6005;
|
||||
pEncryptSend = &AuthCrypt::EncryptSend_6005;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
logdebug("Setting Crypt to Build 12340");
|
||||
pInit = &AuthCrypt::Init_12340;
|
||||
pDecryptRecv = &AuthCrypt::DecryptRecv_12340;
|
||||
pEncryptSend = &AuthCrypt::EncryptSend_12340;
|
||||
break;
|
||||
}
|
||||
}
|
||||
(_crypt.*pInit)(k);
|
||||
const char *hexstr = k->AsHexStr();
|
||||
logdebug("WorldSocket: Crypt initialized [%s]",hexstr);
|
||||
OPENSSL_free((void*)hexstr);
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
class WorldSession;
|
||||
class BigNumber;
|
||||
|
||||
|
||||
#if defined( __GNUC__ )
|
||||
#pragma pack(1)
|
||||
#else
|
||||
@ -60,6 +61,9 @@ public:
|
||||
private:
|
||||
WorldSession *_session;
|
||||
AuthCrypt _crypt;
|
||||
void (AuthCrypt::*pInit)(BigNumber *);
|
||||
void (AuthCrypt::*pDecryptRecv)(uint8 *, size_t);
|
||||
void (AuthCrypt::*pEncryptSend)(uint8 *, size_t);
|
||||
bool _gothdr; // true if only the header was recieved yet
|
||||
uint16 _opcode; // stores the last recieved opcode
|
||||
uint32 _remaining; // bytes amount of the next data packet
|
||||
|
||||
@ -30,7 +30,8 @@ AuthCrypt::~AuthCrypt()
|
||||
|
||||
}
|
||||
|
||||
void AuthCrypt::Init(BigNumber *K)
|
||||
// 3.3.5
|
||||
void AuthCrypt::Init_12340(BigNumber *K)
|
||||
{
|
||||
uint8 ClientDecryptionKey[SEED_KEY_SIZE] = { 0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57 };
|
||||
HmacHash serverEncryptHmac(SEED_KEY_SIZE, (uint8*)ClientDecryptionKey);
|
||||
@ -60,7 +61,7 @@ void AuthCrypt::Init(BigNumber *K)
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
void AuthCrypt::DecryptRecv(uint8 *data, size_t len)
|
||||
void AuthCrypt::DecryptRecv_12340(uint8 *data, size_t len)
|
||||
{
|
||||
if (!_initialized)
|
||||
return;
|
||||
@ -68,10 +69,65 @@ void AuthCrypt::DecryptRecv(uint8 *data, size_t len)
|
||||
_decrypt.UpdateData(len, data);
|
||||
}
|
||||
|
||||
void AuthCrypt::EncryptSend(uint8 *data, size_t len)
|
||||
void AuthCrypt::EncryptSend_12340(uint8 *data, size_t len)
|
||||
{
|
||||
if (!_initialized)
|
||||
return;
|
||||
|
||||
_encrypt.UpdateData(len, data);
|
||||
}
|
||||
|
||||
|
||||
//1.12.2
|
||||
void AuthCrypt::Init_6005(BigNumber *K)
|
||||
{
|
||||
_send_i = _send_j = _recv_i = _recv_j = 0;
|
||||
|
||||
SetKey_6005(K->AsByteArray(),40);
|
||||
_initialized = true;
|
||||
|
||||
}
|
||||
|
||||
void AuthCrypt::DecryptRecv_6005(uint8 *data, size_t len)
|
||||
{
|
||||
if (!_initialized)
|
||||
return;
|
||||
|
||||
if (len < CRYPTED_RECV_LEN_6005)
|
||||
return;
|
||||
|
||||
for (size_t t = 0; t < CRYPTED_RECV_LEN_6005; t++)
|
||||
{
|
||||
_recv_i %= _key.size();
|
||||
uint8 x = (data[t] - _recv_j) ^ _key[_recv_i];
|
||||
++_recv_i;
|
||||
_recv_j = data[t];
|
||||
data[t] = x;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AuthCrypt::EncryptSend_6005(uint8 *data, size_t len)
|
||||
{
|
||||
if (!_initialized)
|
||||
return;
|
||||
if (len < CRYPTED_SEND_LEN_6005)
|
||||
return;
|
||||
|
||||
for (size_t t = 0; t < CRYPTED_SEND_LEN_6005; t++)
|
||||
{
|
||||
_send_i %= _key.size();
|
||||
uint8 x = (data[t] ^ _key[_send_i]) + _send_j;
|
||||
++_send_i;
|
||||
data[t] = _send_j = x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AuthCrypt::SetKey_6005(uint8 *key, size_t len)
|
||||
{
|
||||
_key.resize(len);
|
||||
std::copy(key, key + len, _key.begin());
|
||||
}
|
||||
|
||||
@ -30,15 +30,35 @@ class AuthCrypt
|
||||
AuthCrypt();
|
||||
~AuthCrypt();
|
||||
|
||||
void Init(BigNumber *K);
|
||||
void DecryptRecv(uint8 *, size_t);
|
||||
void EncryptSend(uint8 *, size_t);
|
||||
//Dummy
|
||||
void DecryptRecvDummy(uint8 *, size_t){return;};
|
||||
void EncryptSendDummy(uint8 *, size_t){return;};
|
||||
|
||||
//3.3.5
|
||||
void Init_12340(BigNumber *K);
|
||||
void DecryptRecv_12340(uint8 *, size_t);
|
||||
void EncryptSend_12340(uint8 *, size_t);
|
||||
|
||||
//1.12.X
|
||||
void Init_6005(BigNumber *K);
|
||||
void SetKey_6005(uint8 *, size_t);
|
||||
void DecryptRecv_6005(uint8 *, size_t);
|
||||
void EncryptSend_6005(uint8 *, size_t);
|
||||
|
||||
bool IsInitialized() { return _initialized; }
|
||||
|
||||
const static size_t CRYPTED_SEND_LEN_6005 = 6;
|
||||
const static size_t CRYPTED_RECV_LEN_6005 = 4;
|
||||
|
||||
|
||||
private:
|
||||
bool _initialized;
|
||||
//3.3.5
|
||||
SARC4 _decrypt;
|
||||
SARC4 _encrypt;
|
||||
bool _initialized;
|
||||
|
||||
//1.12.2
|
||||
std::vector<uint8> _key;
|
||||
uint8 _send_i, _send_j, _recv_i, _recv_j;
|
||||
};
|
||||
#endif
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user