mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-04-17 17:43:52 +00:00
Fix LOGON_CHALLENGE security flags buffer corruption and improve auth diagnostics
Account for PIN/matrix/authenticator extra data in packet size calculation to prevent receive buffer corruption. Add hex dump of raw auth packets and show actual server error codes.
This commit is contained in:
parent
738dafb65b
commit
61147a08af
3 changed files with 55 additions and 12 deletions
|
|
@ -2,6 +2,8 @@
|
||||||
#include "network/tcp_socket.hpp"
|
#include "network/tcp_socket.hpp"
|
||||||
#include "network/packet.hpp"
|
#include "network/packet.hpp"
|
||||||
#include "core/logger.hpp"
|
#include "core/logger.hpp"
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
namespace wowee {
|
namespace wowee {
|
||||||
namespace auth {
|
namespace auth {
|
||||||
|
|
@ -114,6 +116,16 @@ void AuthHandler::handleLogonChallengeResponse(network::Packet& packet) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (response.securityFlags != 0) {
|
||||||
|
LOG_WARNING("Server sent security flags: 0x", std::hex, (int)response.securityFlags, std::dec);
|
||||||
|
if (response.securityFlags & 0x01) LOG_WARNING(" PIN required (not supported)");
|
||||||
|
if (response.securityFlags & 0x02) LOG_WARNING(" Matrix card required (not supported)");
|
||||||
|
if (response.securityFlags & 0x04) LOG_WARNING(" Authenticator required (not supported)");
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("Challenge: N=", response.N.size(), "B g=", response.g.size(), "B salt=",
|
||||||
|
response.salt.size(), "B secFlags=0x", std::hex, (int)response.securityFlags, std::dec);
|
||||||
|
|
||||||
// Feed SRP with server challenge data
|
// Feed SRP with server challenge data
|
||||||
srp->feed(response.B, response.g, response.N, response.salt);
|
srp->feed(response.B, response.g, response.N, response.salt);
|
||||||
|
|
||||||
|
|
@ -145,7 +157,9 @@ void AuthHandler::handleLogonProofResponse(network::Packet& packet) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!response.isSuccess()) {
|
if (!response.isSuccess()) {
|
||||||
fail("Login failed - incorrect username or password");
|
std::string reason = "Login failed: ";
|
||||||
|
reason += getAuthResultString(static_cast<AuthResult>(response.status));
|
||||||
|
fail(reason);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -227,7 +241,16 @@ void AuthHandler::handlePacket(network::Packet& packet) {
|
||||||
|
|
||||||
AuthOpcode opcode = static_cast<AuthOpcode>(opcodeValue);
|
AuthOpcode opcode = static_cast<AuthOpcode>(opcodeValue);
|
||||||
|
|
||||||
LOG_DEBUG("Received auth packet, opcode: 0x", std::hex, (int)opcodeValue, std::dec);
|
// Hex dump first bytes for diagnostics
|
||||||
|
{
|
||||||
|
const auto& raw = packet.getData();
|
||||||
|
std::ostringstream hs;
|
||||||
|
for (size_t i = 0; i < std::min<size_t>(raw.size(), 40); ++i)
|
||||||
|
hs << std::hex << std::setfill('0') << std::setw(2) << (int)raw[i];
|
||||||
|
if (raw.size() > 40) hs << "...";
|
||||||
|
LOG_INFO("Auth pkt 0x", std::hex, (int)opcodeValue, std::dec,
|
||||||
|
" (", raw.size(), "B): ", hs.str());
|
||||||
|
}
|
||||||
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case AuthOpcode::LOGON_CHALLENGE:
|
case AuthOpcode::LOGON_CHALLENGE:
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@
|
||||||
#include "core/logger.hpp"
|
#include "core/logger.hpp"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
namespace wowee {
|
namespace wowee {
|
||||||
namespace auth {
|
namespace auth {
|
||||||
|
|
@ -68,7 +70,20 @@ void SRP::feed(const std::vector<uint8_t>& B_bytes,
|
||||||
// 5. Compute proofs (M1, M2)
|
// 5. Compute proofs (M1, M2)
|
||||||
computeProofs(stored_username);
|
computeProofs(stored_username);
|
||||||
|
|
||||||
LOG_INFO("SRP authentication data ready!");
|
// Log key values for debugging auth issues
|
||||||
|
auto hexStr = [](const std::vector<uint8_t>& v, size_t maxBytes = 8) -> std::string {
|
||||||
|
std::ostringstream ss;
|
||||||
|
for (size_t i = 0; i < std::min(v.size(), maxBytes); ++i)
|
||||||
|
ss << std::hex << std::setfill('0') << std::setw(2) << (int)v[i];
|
||||||
|
if (v.size() > maxBytes) ss << "...";
|
||||||
|
return ss.str();
|
||||||
|
};
|
||||||
|
auto A_wire = A.toArray(true, 32);
|
||||||
|
auto s_dbg = s.toArray(true);
|
||||||
|
auto B_dbg = B.toArray(true);
|
||||||
|
LOG_INFO("SRP ready: A=", hexStr(A_wire), " M1=", hexStr(M1),
|
||||||
|
" s_nat=", s_dbg.size(), " A_nat=", A.toArray(true).size(),
|
||||||
|
" B_nat=", B_dbg.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> SRP::computeAuthHash(const std::string& username,
|
std::vector<uint8_t> SRP::computeAuthHash(const std::string& username,
|
||||||
|
|
|
||||||
|
|
@ -196,23 +196,28 @@ size_t TCPSocket::getExpectedPacketSize(uint8_t opcode) {
|
||||||
|
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case 0x00: // LOGON_CHALLENGE response
|
case 0x00: // LOGON_CHALLENGE response
|
||||||
// Need to read second byte to determine success/failure
|
// Need to read status byte to determine success/failure
|
||||||
if (receiveBuffer.size() >= 3) {
|
if (receiveBuffer.size() >= 3) {
|
||||||
uint8_t status = receiveBuffer[2];
|
uint8_t status = receiveBuffer[2];
|
||||||
if (status == 0x00) {
|
if (status == 0x00) {
|
||||||
// Success - need to calculate full size
|
// Success: opcode(1) + unk(1) + status(1) + B(32) + gLen(1) + g(gLen) +
|
||||||
// Minimum: opcode(1) + unknown(1) + status(1) + B(32) + glen(1) + g(1) + Nlen(1) + N(32) + salt(32) + unk(16) + flags(1)
|
// nLen(1) + N(nLen) + salt(32) + crcHash(16) + securityFlags(1)
|
||||||
// With typical values: 1 + 1 + 1 + 32 + 1 + 1 + 1 + 32 + 32 + 16 + 1 = 119 bytes minimum
|
// + optional security flag data
|
||||||
// But N is usually 256 bytes, so more like: 1 + 1 + 1 + 32 + 1 + 1 + 1 + 256 + 32 + 16 + 1 = 343 bytes
|
|
||||||
|
|
||||||
// For safety, let's parse dynamically:
|
|
||||||
if (receiveBuffer.size() >= 36) { // enough to read g_len
|
if (receiveBuffer.size() >= 36) { // enough to read g_len
|
||||||
uint8_t gLen = receiveBuffer[35];
|
uint8_t gLen = receiveBuffer[35];
|
||||||
size_t minSize = 36 + gLen + 1; // up to N_len
|
size_t minSize = 36 + gLen + 1; // up to N_len
|
||||||
if (receiveBuffer.size() >= minSize) {
|
if (receiveBuffer.size() >= minSize) {
|
||||||
uint8_t nLen = receiveBuffer[36 + gLen];
|
uint8_t nLen = receiveBuffer[36 + gLen];
|
||||||
size_t totalSize = 36 + gLen + 1 + nLen + 32 + 16 + 1;
|
size_t baseSize = 36 + gLen + 1 + nLen + 32 + 16 + 1;
|
||||||
return totalSize;
|
// Need to read securityFlags to account for extra data
|
||||||
|
if (receiveBuffer.size() >= baseSize) {
|
||||||
|
uint8_t secFlags = receiveBuffer[baseSize - 1];
|
||||||
|
size_t extra = 0;
|
||||||
|
if (secFlags & 0x01) extra += 20; // PIN: seed(4) + salt(16)
|
||||||
|
if (secFlags & 0x02) extra += 12; // Matrix: w(1)+h(1)+digits(1)+challenges(1)+seed(8)
|
||||||
|
if (secFlags & 0x04) extra += 1; // Authenticator: required(1)
|
||||||
|
return baseSize + extra;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0; // Need more data
|
return 0; // Need more data
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue