Support PIN-required auth servers

This commit is contained in:
Kelsi 2026-02-13 00:22:01 -08:00
parent f247d53309
commit 62a49644a5
9 changed files with 271 additions and 13 deletions

View file

@ -5,6 +5,7 @@
#include <memory>
#include <string>
#include <functional>
#include <array>
namespace wowee {
namespace network { class TCPSocket; class Packet; }
@ -19,6 +20,7 @@ enum class AuthState {
CONNECTED,
CHALLENGE_SENT,
CHALLENGE_RECEIVED,
PIN_REQUIRED,
PROOF_SENT,
AUTHENTICATED,
REALM_LIST_REQUESTED,
@ -44,6 +46,9 @@ public:
// Authentication
void authenticate(const std::string& username, const std::string& password);
void authenticateWithHash(const std::string& username, const std::vector<uint8_t>& authHash);
// Optional: when the auth server requires a PIN (securityFlags & 0x01), call this to continue.
// PIN must be 4-10 digits.
void submitPin(const std::string& pin);
// Set client version info (call before authenticate)
void setClientInfo(const ClientInfo& info) { clientInfo = info; }
@ -96,6 +101,12 @@ private:
// Receive buffer
std::vector<uint8_t> receiveBuffer;
// Challenge security extension (PIN)
uint8_t securityFlags_ = 0;
uint32_t pinGridSeed_ = 0;
std::array<uint8_t, 16> pinServerSalt_{}; // from LOGON_CHALLENGE response
std::string pendingPin_;
};
} // namespace auth

View file

@ -5,6 +5,7 @@
#include <string>
#include <vector>
#include <cstdint>
#include <array>
namespace wowee {
namespace auth {
@ -38,6 +39,10 @@ struct LogonChallengeResponse {
std::vector<uint8_t> salt; // Salt (32 bytes)
uint8_t securityFlags;
// PIN extension (securityFlags & 0x01)
uint32_t pinGridSeed = 0;
std::array<uint8_t, 16> pinSalt{};
bool isSuccess() const { return result == AuthResult::SUCCESS; }
};
@ -52,6 +57,11 @@ class LogonProofPacket {
public:
static network::Packet build(const std::vector<uint8_t>& A,
const std::vector<uint8_t>& M1);
static network::Packet build(const std::vector<uint8_t>& A,
const std::vector<uint8_t>& M1,
uint8_t securityFlags,
const std::array<uint8_t, 16>* pinClientSalt,
const std::array<uint8_t, 20>* pinHash);
};
// LOGON_PROOF response data

28
include/auth/pin_auth.hpp Normal file
View file

@ -0,0 +1,28 @@
#pragma once
#include <array>
#include <cstdint>
#include <string>
namespace wowee {
namespace auth {
struct PinProof {
std::array<uint8_t, 16> clientSalt{};
std::array<uint8_t, 20> hash{};
};
// Implements the "PIN" security extension used in the WoW auth protocol (securityFlags & 0x01).
// Algorithm based on documented client behavior:
// - Remap digits using pinGridSeed (a permutation of 0..9)
// - Convert user-entered PIN digits into randomized indices in that permutation
// - Compute: pin_hash = SHA1(client_salt || SHA1(server_salt || randomized_pin_ascii))
//
// PIN must be 4-10 ASCII digits.
PinProof computePinProof(const std::string& pinDigits,
uint32_t pinGridSeed,
const std::array<uint8_t, 16>& serverSalt);
} // namespace auth
} // namespace wowee