feat(net): handle realm server auth challenge

This commit is contained in:
fallenoak 2023-03-23 23:01:11 -05:00
parent 0b7970101a
commit 5d11881372
No known key found for this signature in database
GPG Key ID: 7628F8E61AEA070D
5 changed files with 141 additions and 5 deletions

View File

@ -140,7 +140,7 @@ void NetClient::Connect(const char* addrStr) {
port = atoi(portDelim + 1);
}
this->m_serverConnection->SetEncryptionType(WC_ENCRYPT_0);
this->m_serverConnection->SetEncryption(false);
this->m_netState = NS_INITIALIZED;
this->ConnectInternal(host, port);
}
@ -166,6 +166,21 @@ void NetClient::DelRef() {
}
}
void NetClient::EnableEncryption(WowConnection* conn, uint8_t* seed, uint8_t seedLen) {
conn->SetEncryptionKey(
this->m_loginData.m_sessionKey,
sizeof(this->m_loginData.m_sessionKey),
1,
seed,
seedLen
);
conn->uint375 = 4;
conn->uint376 = 2;
conn->SetEncryption(true);
}
bool NetClient::GetDelete() {
return this->m_deleteMe;
}
@ -261,6 +276,12 @@ void NetClient::Send(CDataStore* msg) {
this->m_serverConnection->Send(msg, 0);
// TODO
this->m_bytesSent += v4;
if (!this->m_serverConnection->m_encrypt) {
this->EnableEncryption(this->m_serverConnection, nullptr, 0);
}
}
}

View File

@ -64,6 +64,7 @@ class NetClient : public WowConnectionResponse {
void Connect(const char* addrStr);
int32_t ConnectInternal(const char* host, uint16_t port);
void DelRef();
void EnableEncryption(WowConnection* conn, uint8_t* seed, uint8_t seedLen);
bool GetDelete();
const LoginData& GetLoginData();
NETSTATE GetState();

View File

@ -1,5 +1,8 @@
#include "net/connection/RealmConnection.hpp"
#include "net/Types.hpp"
#include <common/DataStore.hpp>
#include <common/SHA1.hpp>
#include <storm/String.hpp>
SCritSect RealmConnection::s_AllRealmConnectionsCrit;
STORM_LIST(RealmConnection::REALMCONNECTIONNODE) RealmConnection::s_AllRealmConnections;
@ -46,6 +49,53 @@ RealmConnection::RealmConnection(RealmResponse* realmResponse) {
int32_t RealmConnection::HandleAuthChallenge(AuthenticationChallenge* challenge) {
// TODO
// TODO switch to WDataStore
CDataStore msg;
uint32_t localChallenge;
msg.Put(static_cast<uint32_t>(CMSG_AUTH_SESSION));
msg.Put(static_cast<uint32_t>(12340));
msg.Put(static_cast<uint32_t>(this->GetLoginData().m_loginServerID));
msg.PutString(this->GetLoginData().m_account);
msg.Put(static_cast<uint32_t>(this->GetLoginData().m_loginServerType));
// TODO
msg.Put(localChallenge);
// TODO
msg.Put(static_cast<uint32_t>(0));
msg.Put(static_cast<uint32_t>(0));
msg.Put(static_cast<uint32_t>(1));
// TODO
msg.Put(static_cast<uint64_t>(0));
uint32_t msgId = 0;
SHA1_CONTEXT ctx;
SHA1_Init(&ctx);
SHA1_Update(&ctx, reinterpret_cast<const uint8_t*>(this->GetLoginData().m_account), SStrLen(this->GetLoginData().m_account));
SHA1_Update(&ctx, reinterpret_cast<uint8_t*>(&msgId), sizeof(msgId));
SHA1_Update(&ctx, reinterpret_cast<uint8_t*>(&localChallenge), sizeof(localChallenge));
SHA1_Update(&ctx, reinterpret_cast<uint8_t*>(&challenge->uint0), sizeof(challenge->uint0));
SHA1_Update(&ctx, this->GetLoginData().m_sessionKey, sizeof(this->GetLoginData().m_sessionKey));
uint8_t clientProof[SHA1_DIGEST_SIZE];
SHA1_Final(clientProof, &ctx);
msg.PutData(clientProof, sizeof(clientProof));
// TODO addons
msg.Put(static_cast<uint32_t>(0));
msg.Finalize();
this->Send(&msg);
return 1;
}

View File

@ -1,6 +1,7 @@
#include "net/connection/WowConnection.hpp"
#include "net/connection/WowConnectionNet.hpp"
#include "net/connection/WowConnectionResponse.hpp"
#include "util/HMAC.hpp"
#include <common/DataStore.hpp>
#include <common/Time.hpp>
#include <storm/Error.hpp>
@ -33,6 +34,15 @@ WowConnectionNet* WowConnection::s_network;
ATOMIC32 WowConnection::s_numWowConnections;
bool (*WowConnection::s_verifyAddr)(const NETADDR*);
static uint8_t s_arc4drop1024[1024] = { 0x00 };
static uint8_t s_arc4seed[] = {
// Receive key
0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57,
// Send key
0xC2, 0xB3, 0x72, 0x3C, 0xC6, 0xAE, 0xD9, 0xB5, 0x34, 0x3C, 0x53, 0xEE, 0x2F, 0x43, 0x67, 0xCE,
};
WowConnection::SENDNODE::SENDNODE(void* data, int32_t size, uint8_t* buf, bool raw) : TSLinkedNode<WowConnection::SENDNODE>() {
if (data) {
this->data = buf;
@ -451,7 +461,18 @@ void WowConnection::DoMessageReads() {
}
if (this->m_encrypt) {
// TODO encryption
auto v22 = headerSize + this->uint376 - this->m_readBytes;
auto v23 = v22 <= 0 ? 0 : v22;
if (v23 >= bytesRead) {
v23 = bytesRead;
}
SARC4ProcessBuffer(
&this->m_readBuffer[this->m_readBytes],
v23,
&this->m_receiveKey,
&this->m_receiveKey
);
}
this->m_readBytes += bytesRead;
@ -832,8 +853,43 @@ WC_SEND_RESULT WowConnection::SendRaw(uint8_t* data, int32_t len, bool a4) {
return WC_SEND_ERROR;
}
void WowConnection::SetEncryptionType(WC_ENCRYPT_TYPE encryptType) {
// TODO
void WowConnection::SetEncryption(bool enabled) {
this->m_lock.Enter();
this->m_encrypt = enabled;
SARC4PrepareKey(this->m_sendKeyInit, sizeof(this->m_sendKeyInit), &this->m_sendKey);
SARC4PrepareKey(this->m_receiveKeyInit, sizeof(this->m_receiveKeyInit), &this->m_receiveKey);
SARC4ProcessBuffer(s_arc4drop1024, sizeof(s_arc4drop1024), &this->m_sendKey, &this->m_sendKey);
SARC4ProcessBuffer(s_arc4drop1024, sizeof(s_arc4drop1024), &this->m_receiveKey, &this->m_receiveKey);
this->m_lock.Leave();
}
void WowConnection::SetEncryptionKey(const uint8_t* key, uint8_t keyLen, uint8_t a4, const uint8_t* seedData, uint8_t seedLen) {
if (!seedData) {
seedData = s_arc4seed;
seedLen = sizeof(s_arc4seed);
}
const uint8_t* seeds[] = {
seedData,
&seedData[seedLen / 2]
};
// Note: The original HMAC-SHA1 implementation uses a second SHA1 implementation shipped in
// the client. For simplicity's sake, we're currently using a custom util function built on
// top of the SHA1 implementation used for SRP6 authentication.
HMAC_SHA1(seeds[a4], seedLen / 2, key, keyLen, this->m_sendKeyInit);
HMAC_SHA1(seeds[a4 ^ 1], seedLen / 2, key, keyLen, this->m_receiveKeyInit);
SARC4PrepareKey(this->m_sendKeyInit, sizeof(this->m_sendKeyInit), &this->m_sendKey);
SARC4PrepareKey(this->m_receiveKeyInit, sizeof(this->m_receiveKeyInit), &this->m_receiveKey);
SARC4ProcessBuffer(s_arc4drop1024, sizeof(s_arc4drop1024), &this->m_sendKey, &this->m_sendKey);
SARC4ProcessBuffer(s_arc4drop1024, sizeof(s_arc4drop1024), &this->m_receiveKey, &this->m_receiveKey);
}
void WowConnection::SetState(WOW_CONN_STATE state) {

View File

@ -4,6 +4,7 @@
#include "net/Types.hpp"
#include <cstdint>
#include <storm/Atomic.hpp>
#include <storm/Crypto.hpp>
#include <storm/List.hpp>
#include <storm/Thread.hpp>
@ -70,7 +71,13 @@ class WowConnection {
ATOMIC32 m_serviceCount;
void* m_event;
WOWC_TYPE m_type;
SARC4Key m_sendKey;
SARC4Key m_receiveKey;
uint8_t m_sendKeyInit[20];
uint8_t m_receiveKeyInit[20];
bool m_encrypt;
uint8_t uint375;
uint8_t uint376;
// Member functions
WowConnection(WowConnectionResponse* response, void (*func)(void));
@ -97,7 +104,8 @@ class WowConnection {
void ReleaseResponseRef();
WC_SEND_RESULT Send(CDataStore* msg, int32_t a3);
WC_SEND_RESULT SendRaw(uint8_t* data, int32_t len, bool a4);
void SetEncryptionType(WC_ENCRYPT_TYPE encryptType);
void SetEncryption(bool enabled);
void SetEncryptionKey(const uint8_t* key, uint8_t keyLen, uint8_t a4, const uint8_t* seed, uint8_t seedLen);
void SetState(WOW_CONN_STATE state);
void SetType(WOWC_TYPE type);
void StartConnect();