MinecraftConsoles/Minecraft.Client/PendingConnection.h
MrTheShy 4f2352361a Add Mojang/Ely.by/offline authentication system
The old Windows64 port had no real player identity — it used hardcoded
fake XUIDs, so anyone could impersonate anyone. This replaces that with
proper auth supporting Mojang, Ely.by, and offline accounts.

MCAuth library (new, MCAuth/):
  Mojang auth via MSA device code flow (XBL, SISU, MC services),
  Ely.by via Yggdrasil with 2FA, offline UUID generation matching
  Java Edition (MD5 v3 from "OfflinePlayer:<name>"). Multi-account
  manager with background token refresh, per-slot sessions, and
  on-disk token persistence. Server-side session verification via
  Mojang/Ely.by hasJoined API. Skin fetching and PNG validation
  from texture servers.

Network protocol (version bumped to 80):
  Three new packets (AuthScheme, AuthResponse, AuthResult) implement
  a server-driven auth handshake before login completes. Player
  identity migrated from 64-bit XUID to 128-bit GameUUID backed by
  two uint64 fields (hi/lo). readPlayerUID/writePlayerUID now
  serialize 16 bytes on the wire. Old and new clients cannot connect
  to each other — version mismatch is rejected at PreLogin.

Save migration:
  Map data mappings auto-migrate from old format: the old 64-bit
  XUID is placed in hi, lo is set to 0 as a sentinel. On first
  access by the real player, the sentinel entry is upgraded in-place
  to the full 128-bit UUID. Format detection is by file size (2080,
  2112, or 4160 bytes). Player .dat filenames inside saveData.ms
  change from decimal XUID to dashed UUID — old saves need manual
  entry renaming in the archive.

UI:
  NativeUIRenderer: immediate-mode drawing system (quads, text,
  9-slice panels, scrollbars, focus lists) for rendering auth
  screens without Flash/Scaleform. UIScene_MSAuth handles device
  code display, Ely.by credential input with 2FA, per-account
  skin head preview, and multi-account add/remove/switch.

Server:
  online-mode and auth-provider (mojang/elyby) in server.properties.
  Whitelist and ban checks validate against the server-verified UUID.
  Incompatible auth scheme logs which provider the server expects
  vs what the client is using.

Also fixes a pre-existing exploit where any client could send a
DebugOptionsPacket to grant themselves CraftAnything and other debug
privileges on any server — now requires OP status server-side.
2026-03-23 01:14:23 +01:00

81 lines
2.7 KiB
C++

#pragma once
#include "..\Minecraft.World\PacketListener.h"
#include <string>
#include <atomic>
#include <mutex>
#include <vector>
class MinecraftServer;
class Socket;
class LoginPacket;
class Connection;
class Random;
class AuthResponsePacket;
using namespace std;
class PendingConnection : public PacketListener
{
private:
static const int FAKE_LAG = 0;
static const int MAX_TICKS_BEFORE_LOGIN = 20 * 30;
// public static Logger logger = Logger.getLogger("Minecraft");
static Random *random;
public:
Connection *connection;
public:
bool done;
private:
MinecraftServer *server;
int _tick;
wstring name;
shared_ptr<LoginPacket> acceptedLogin;
wstring loginKey;
// Auth handshake state
enum eAuthState { eAuth_None, eAuth_WaitingResponse, eAuth_Verifying, eAuth_WaitingAck, eAuth_Done };
eAuthState m_authState = eAuth_None;
std::string m_serverId; // random hex challenge
std::string m_authUsername; // username from auth response
std::string m_authUuid; // uuid from auth response (dashed)
std::string m_authScheme; // "mojang" or "offline"
// Thread-safe verification result (heap-allocated so detached thread cannot UAF)
struct AuthVerifyResult {
std::atomic<bool> ready{false};
std::atomic<bool> cancelled{false};
std::mutex mutex; // protects fields below
bool success = false;
std::string username;
std::string uuid; // undashed from HasJoined
std::string skinUrl; // Mojang skin texture URL
std::vector<uint8_t> skinData; // downloaded skin PNG bytes
std::string errorDetail; // diagnostic info on failure
};
std::shared_ptr<AuthVerifyResult> m_authVerifyResult;
// Skin data received from Mojang after auth verification
std::string m_authSkinUrl; // texture key for this player's skin
std::vector<uint8_t> m_authSkinData; // raw PNG bytes
public:
PendingConnection(MinecraftServer *server, Socket *socket, const wstring& id);
~PendingConnection();
void tick();
void disconnect(DisconnectPacket::eDisconnectReason reason);
virtual void handlePreLogin(shared_ptr<PreLoginPacket> packet);
virtual void handleLogin(shared_ptr<LoginPacket> packet);
virtual void handleAcceptedLogin(shared_ptr<LoginPacket> packet);
virtual void handleAuthResponse(shared_ptr<AuthResponsePacket> packet);
virtual void onDisconnect(DisconnectPacket::eDisconnectReason reason, void *reasonObjects);
virtual void handleGetInfo(shared_ptr<GetInfoPacket> packet);
virtual void handleKeepAlive(shared_ptr<KeepAlivePacket> packet);
virtual void onUnhandledPacket(shared_ptr<Packet> packet);
void send(shared_ptr<Packet> packet);
wstring getName();
virtual bool isServerPacketListener();
virtual bool isDisconnected();
private:
void sendPreLoginResponse();
};