diff --git a/src/net/grunt/ClientLink.cpp b/src/net/grunt/ClientLink.cpp index 2a58ce1..cad47e5 100644 --- a/src/net/grunt/ClientLink.cpp +++ b/src/net/grunt/ClientLink.cpp @@ -2,6 +2,8 @@ #include "net/connection/WowConnection.hpp" #include "net/grunt/ClientResponse.hpp" #include "net/grunt/Command.hpp" +#include "net/srp/SRP6_Random.hpp" +#include #include #include #include @@ -45,8 +47,160 @@ void Grunt::ClientLink::Call() { } int32_t Grunt::ClientLink::CmdAuthLogonChallenge(CDataStore& msg) { + if (msg.m_read > msg.m_size || msg.m_size - msg.m_read < 2) { + return 0; + } + + uint8_t v30; + msg.Get(v30); + + if (v30 != 0) { + return 1; + } + + uint8_t result; + msg.Get(result); + + // Auth failure (success == 0) + if (result != 0) { + if (msg.m_read > msg.m_size) { + return 1; + } + + this->SetState(2); + + if (result >= GRUNT_RESULT_LAST) { + // TODO WLog error + } + + this->m_clientResponse->LogonResult(static_cast(result), nullptr, 0, 0); + + return 2; + } + + if (msg.m_read > msg.m_size) { + return 0; + } + + if (msg.m_size - msg.m_read < 33) { + return 0; + } + + uint8_t* serverPublicKey; + msg.GetDataInSitu(reinterpret_cast(serverPublicKey), 32); + + uint8_t generatorLen; + msg.Get(generatorLen); + // TODO - return 0; + // if (!msg.Sub8CBBF0(v31 + 1)) { + // return 0; + // } + + uint8_t* generator; + msg.GetDataInSitu(reinterpret_cast(generator), generatorLen); + + uint8_t largeSafePrimeLen; + msg.Get(largeSafePrimeLen); + + // TODO + // if (!msg.sub_8CBBF0(v32 + 48)) { + // return 0; + // } + + uint8_t* largeSafePrime; + msg.GetDataInSitu(reinterpret_cast(largeSafePrime), largeSafePrimeLen); + + uint8_t* salt; + msg.GetDataInSitu(reinterpret_cast(salt), 32); + + uint8_t* crcSalt; + msg.GetDataInSitu(reinterpret_cast(crcSalt), 16); + + // TODO + // if (!msg.Sub8CBBF0(1)) { + // return 0; + // } + + uint8_t logonFlags; + msg.Get(logonFlags); + + uint32_t pinGridSeed = 0; + uint8_t* pinSalt = nullptr; + + uint8_t matrixWidth = 0; + uint8_t matrixHeight = 0; + uint8_t matrixDigitCount = 0; + uint8_t matrixChallengeCount = 0; + uint64_t matrixSeed = 0; + + uint8_t tokenRequired = 0; + + // PIN + if (logonFlags & 0x1) { + // TODO + // if (!msg.Sub8CBBF0(20)) { + // return 0; + // } + + msg.Get(pinGridSeed); + msg.GetDataInSitu(reinterpret_cast(pinSalt), 16); + } + + // MATRIX + if (logonFlags & 0x2) { + // TODO + /* + if (msg.Sub8CBBF0(12)) { + msg.Get(matrixWidth); + msg.Get(matrixHeight); + msg.Get(matrixDigitCount); + msg.Get(matrixChallengeCount); + msg.Get(matrixSeed); + + if ((logonFlags & 0x2) && matrixChallengeCount == 0) { + return 1; + } + } else { + return 0; + } + */ + } + + // TOKEN (authenticator) + if (logonFlags & 0x4) { + // TODO + // if (!msg.Sub8CBBF0(1)) { + // return 0; + // } + + msg.Get(tokenRequired); + } + + if (msg.m_read > msg.m_size) { + return 1; + } + + memcpy(this->m_serverPublicKey, serverPublicKey, sizeof(this->m_serverPublicKey)); + + char randomSeed[16]; + // TODO + // OsSecureRandom(randomSeed, sizeof(randomSeed)); + SRP6_Random srpRandom(randomSeed, sizeof(randomSeed)); + + if (this->m_srpClient.CalculateProof(largeSafePrime, largeSafePrimeLen, generator, generatorLen, salt, 32, serverPublicKey, 32, srpRandom)) { + this->SetState(2); + this->m_clientResponse->LogonResult(GRUNT_RESULT_5, nullptr, 0, 0); + } else { + this->SetState(4); + this->m_clientResponse->SetPinInfo(logonFlags & 0x1, pinGridSeed, pinSalt); + // TODO + // this->m_clientResponse->SetMatrixInfo(logonFlags & 0x2, matrixWidth, matrixHeight, matrixDigitCount, matrixDigitCount, 0, matrixChallengeCount, matrixSeed, this->m_srpClient.buf20, 40); + this->m_clientResponse->SetTokenInfo(logonFlags & 0x4, tokenRequired); + this->m_clientResponse->GetVersionProof(crcSalt); + } + + return 2; } int32_t Grunt::ClientLink::CmdAuthLogonProof(CDataStore& msg) { diff --git a/src/net/grunt/ClientLink.hpp b/src/net/grunt/ClientLink.hpp index 2717c53..2fa7d7a 100644 --- a/src/net/grunt/ClientLink.hpp +++ b/src/net/grunt/ClientLink.hpp @@ -48,6 +48,7 @@ class Grunt::ClientLink : public WowConnectionResponse, Grunt::Pending, Grunt::T WowConnection* m_connection = nullptr; ClientResponse* m_clientResponse; char m_accountName[1280]; + char m_serverPublicKey[32]; // Virtual member functions virtual void WCConnected(WowConnection* conn, WowConnection* inbound, uint32_t timeStamp, const NETCONNADDR* addr); diff --git a/src/net/grunt/ClientResponse.hpp b/src/net/grunt/ClientResponse.hpp index 82956c6..1556880 100644 --- a/src/net/grunt/ClientResponse.hpp +++ b/src/net/grunt/ClientResponse.hpp @@ -11,6 +11,11 @@ class Grunt::ClientResponse { virtual bool Connected(const NETADDR& addr) = 0; virtual bool OnlineIdle() = 0; virtual void GetLogonMethod() = 0; + virtual void GetVersionProof(const uint8_t* a2) = 0; + virtual void SetPinInfo(bool enabled, uint32_t a3, const uint8_t* a4) = 0; + virtual void SetMatrixInfo(bool enabled, uint8_t a3, uint8_t a4, uint8_t a5, uint8_t a6, bool a7, uint8_t a8, uint64_t a9, const uint8_t* a10, uint32_t a11) = 0; + virtual void SetTokenInfo(bool enabled, uint8_t required) = 0; + virtual void LogonResult(Result result, const uint8_t* a3, uint32_t a4, uint16_t a5) = 0; virtual void GetRealmList() = 0; virtual void Logon(const char* a2, const char* a3) = 0; virtual void Logoff() = 0; diff --git a/src/net/grunt/Grunt.hpp b/src/net/grunt/Grunt.hpp index 8c0dc77..10dd425 100644 --- a/src/net/grunt/Grunt.hpp +++ b/src/net/grunt/Grunt.hpp @@ -10,6 +10,43 @@ namespace Grunt { class Timer; extern Command s_clientCommands[]; + + enum Result { + GRUNT_RESULT_0 = 0, + GRUNT_RESULT_1 = 1, + GRUNT_RESULT_2 = 2, + GRUNT_RESULT_3 = 3, + GRUNT_RESULT_4 = 4, + GRUNT_RESULT_5 = 5, + GRUNT_RESULT_6 = 6, + GRUNT_RESULT_7 = 7, + GRUNT_RESULT_8 = 8, + GRUNT_RESULT_9 = 9, + GRUNT_RESULT_10 = 10, + GRUNT_RESULT_11 = 11, + GRUNT_RESULT_12 = 12, + GRUNT_RESULT_13 = 13, + GRUNT_RESULT_14 = 14, + GRUNT_RESULT_15 = 15, + GRUNT_RESULT_16 = 16, + GRUNT_RESULT_17 = 17, + GRUNT_RESULT_18 = 18, + GRUNT_RESULT_19 = 19, + GRUNT_RESULT_20 = 20, + GRUNT_RESULT_21 = 21, + GRUNT_RESULT_22 = 22, + GRUNT_RESULT_23 = 23, + GRUNT_RESULT_24 = 24, + GRUNT_RESULT_25 = 25, + GRUNT_RESULT_26 = 26, + GRUNT_RESULT_27 = 27, + GRUNT_RESULT_28 = 28, + GRUNT_RESULT_29 = 29, + GRUNT_RESULT_30 = 30, + GRUNT_RESULT_31 = 31, + GRUNT_RESULT_32 = 32, + GRUNT_RESULT_LAST, + }; } #endif diff --git a/src/net/login/GruntLogin.cpp b/src/net/login/GruntLogin.cpp index 7446131..73893a2 100644 --- a/src/net/login/GruntLogin.cpp +++ b/src/net/login/GruntLogin.cpp @@ -88,6 +88,10 @@ void GruntLogin::GetRealmList() { // TODO } +void GruntLogin::GetVersionProof(const uint8_t* a2) { + // TODO +} + void GruntLogin::Init(LoginResponse* loginResponse) { this->m_loginResponse = loginResponse; @@ -124,3 +128,19 @@ void GruntLogin::Logon(const char* a2, const char* a3) { this->m_clientLink->Connect(a2); } + +void GruntLogin::LogonResult(Grunt::Result result, const uint8_t* a3, uint32_t a4, uint16_t a5) { + // TODO +} + +void GruntLogin::SetMatrixInfo(bool enabled, uint8_t a3, uint8_t a4, uint8_t a5, uint8_t a6, bool a7, uint8_t a8, uint64_t a9, const uint8_t* a10, uint32_t a11) { + // TODO +} + +void GruntLogin::SetPinInfo(bool enabled, uint32_t a3, const uint8_t* a4) { + // TODO +} + +void GruntLogin::SetTokenInfo(bool enabled, uint8_t tokenRequired) { + // TODO +} diff --git a/src/net/login/GruntLogin.hpp b/src/net/login/GruntLogin.hpp index 1d80904..0adf872 100644 --- a/src/net/login/GruntLogin.hpp +++ b/src/net/login/GruntLogin.hpp @@ -14,6 +14,11 @@ class GruntLogin : public Login { virtual ~GruntLogin(); virtual bool Connected(const NETADDR& addr); virtual void GetLogonMethod(); + virtual void GetVersionProof(const uint8_t* a2); + virtual void SetPinInfo(bool enabled, uint32_t a3, const uint8_t* a4); + virtual void SetMatrixInfo(bool enabled, uint8_t a3, uint8_t a4, uint8_t a5, uint8_t a6, bool a7, uint8_t a8, uint64_t a9, const uint8_t* a10, uint32_t a11); + virtual void SetTokenInfo(bool enabled, uint8_t tokenRequired); + virtual void LogonResult(Grunt::Result result, const uint8_t* a3, uint32_t a4, uint16_t a5); virtual void GetRealmList(); virtual void Logon(const char* a2, const char* a3); virtual void Logoff(); diff --git a/src/net/srp/SRP6_Client.cpp b/src/net/srp/SRP6_Client.cpp index f01b5da..60fe115 100644 --- a/src/net/srp/SRP6_Client.cpp +++ b/src/net/srp/SRP6_Client.cpp @@ -22,3 +22,9 @@ int32_t SRP6_Client::BeginAuthentication(const char* accountName, const char* pa return 0; } + +int32_t SRP6_Client::CalculateProof(const uint8_t* largeSafePrime, uint32_t largeSafePrimeLen, const uint8_t* generator, uint32_t generatorLen, const uint8_t* salt, uint32_t saltLen, const uint8_t* publicKey, uint32_t publicKeyLen, SRP6_Random& random) { + // TODO + + return 0; +} diff --git a/src/net/srp/SRP6_Client.hpp b/src/net/srp/SRP6_Client.hpp index fd07453..53269dc 100644 --- a/src/net/srp/SRP6_Client.hpp +++ b/src/net/srp/SRP6_Client.hpp @@ -3,6 +3,8 @@ #include +class SRP6_Random; + class SRP6_Client { public: // Member variables @@ -12,6 +14,7 @@ class SRP6_Client { // Member functions int32_t BeginAuthentication(const char* accountName, const char* password); + int32_t CalculateProof(const uint8_t* largeSafePrime, uint32_t largeSafePrimeLen, const uint8_t* generator, uint32_t generatorLen, const uint8_t* salt, uint32_t saltLen, const uint8_t* publicKey, uint32_t publicKeyLen, SRP6_Random& random); }; #endif