[Server]: Complete sv_privatePassword implementation (#908)
This commit is contained in:
parent
bd0acdb6cb
commit
44ca51e11b
@ -19,10 +19,12 @@ namespace Components
|
|||||||
0xf7e33c4081337fa3,
|
0xf7e33c4081337fa3,
|
||||||
0x6f5597f103cc50e9
|
0x6f5597f103cc50e9
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool Auth::HasAccessToReservedSlot;
|
||||||
|
|
||||||
void Auth::Frame()
|
void Auth::Frame()
|
||||||
{
|
{
|
||||||
if (Auth::TokenContainer.generating)
|
if (TokenContainer.generating)
|
||||||
{
|
{
|
||||||
static double mseconds = 0;
|
static double mseconds = 0;
|
||||||
static Utils::Time::Interval interval;
|
static Utils::Time::Interval interval;
|
||||||
@ -31,38 +33,38 @@ namespace Components
|
|||||||
{
|
{
|
||||||
interval.update();
|
interval.update();
|
||||||
|
|
||||||
int diff = Game::Sys_Milliseconds() - Auth::TokenContainer.startTime;
|
int diff = Game::Sys_Milliseconds() - TokenContainer.startTime;
|
||||||
double hashPMS = (Auth::TokenContainer.hashes * 1.0) / diff;
|
double hashPMS = (TokenContainer.hashes * 1.0) / diff;
|
||||||
double requiredHashes = std::pow(2, Auth::TokenContainer.targetLevel + 1) - Auth::TokenContainer.hashes;
|
double requiredHashes = std::pow(2, TokenContainer.targetLevel + 1) - TokenContainer.hashes;
|
||||||
mseconds = requiredHashes / hashPMS;
|
mseconds = requiredHashes / hashPMS;
|
||||||
if (mseconds < 0) mseconds = 0;
|
if (mseconds < 0) mseconds = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Localization::Set("MPUI_SECURITY_INCREASE_MESSAGE", Utils::String::VA("Increasing security level from %d to %d (est. %s)", Auth::GetSecurityLevel(), Auth::TokenContainer.targetLevel, Utils::String::FormatTimeSpan(static_cast<int>(mseconds)).data()));
|
Localization::Set("MPUI_SECURITY_INCREASE_MESSAGE", Utils::String::VA("Increasing security level from %d to %d (est. %s)",GetSecurityLevel(), TokenContainer.targetLevel, Utils::String::FormatTimeSpan(static_cast<int>(mseconds)).data()));
|
||||||
}
|
}
|
||||||
else if (Auth::TokenContainer.thread.joinable())
|
else if (TokenContainer.thread.joinable())
|
||||||
{
|
{
|
||||||
Auth::TokenContainer.thread.join();
|
TokenContainer.thread.join();
|
||||||
Auth::TokenContainer.generating = false;
|
TokenContainer.generating = false;
|
||||||
|
|
||||||
Auth::StoreKey();
|
StoreKey();
|
||||||
Logger::Debug("Security level is {}", Auth::GetSecurityLevel());
|
Logger::Debug("Security level is {}",GetSecurityLevel());
|
||||||
Command::Execute("closemenu security_increase_popmenu", false);
|
Command::Execute("closemenu security_increase_popmenu", false);
|
||||||
|
|
||||||
if (!Auth::TokenContainer.cancel)
|
if (!TokenContainer.cancel)
|
||||||
{
|
{
|
||||||
if (Auth::TokenContainer.command.empty())
|
if (TokenContainer.command.empty())
|
||||||
{
|
{
|
||||||
Game::ShowMessageBox(Utils::String::VA("Your new security level is %d", Auth::GetSecurityLevel()), "Success");
|
Game::ShowMessageBox(Utils::String::VA("Your new security level is %d", GetSecurityLevel()), "Success");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Toast::Show("cardicon_locked", "Success", Utils::String::VA("Your new security level is %d", Auth::GetSecurityLevel()), 5000);
|
Toast::Show("cardicon_locked", "Success", Utils::String::VA("Your new security level is %d", GetSecurityLevel()), 5000);
|
||||||
Command::Execute(Auth::TokenContainer.command, false);
|
Command::Execute(TokenContainer.command, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Auth::TokenContainer.cancel = false;
|
TokenContainer.cancel = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,15 +72,15 @@ namespace Components
|
|||||||
{
|
{
|
||||||
// Ensure our certificate is loaded
|
// Ensure our certificate is loaded
|
||||||
Steam::SteamUser()->GetSteamID();
|
Steam::SteamUser()->GetSteamID();
|
||||||
if (!Auth::GuidKey.isValid())
|
if (!GuidKey.isValid())
|
||||||
{
|
{
|
||||||
Logger::Error(Game::ERR_SERVERDISCONNECT, "Connecting failed: Guid key is invalid!");
|
Logger::Error(Game::ERR_SERVERDISCONNECT, "Connecting failed: Guid key is invalid!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::find(Auth::BannedUids.begin(), Auth::BannedUids.end(), Steam::SteamUser()->GetSteamID().bits) != Auth::BannedUids.end())
|
if (std::find(BannedUids.begin(), BannedUids.end(), Steam::SteamUser()->GetSteamID().bits) != BannedUids.end())
|
||||||
{
|
{
|
||||||
Auth::GenerateKey();
|
GenerateKey();
|
||||||
Logger::Error(Game::ERR_SERVERDISCONNECT, "Your online profile is invalid. A new key has been generated.");
|
Logger::Error(Game::ERR_SERVERDISCONNECT, "Your online profile is invalid. A new key has been generated.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -121,9 +123,9 @@ namespace Components
|
|||||||
Game::SV_Cmd_EndTokenizedString();
|
Game::SV_Cmd_EndTokenizedString();
|
||||||
|
|
||||||
Proto::Auth::Connect connectData;
|
Proto::Auth::Connect connectData;
|
||||||
connectData.set_token(Auth::GuidToken.toString());
|
connectData.set_token(GuidToken.toString());
|
||||||
connectData.set_publickey(Auth::GuidKey.getPublicKey());
|
connectData.set_publickey(GuidKey.getPublicKey());
|
||||||
connectData.set_signature(Utils::Cryptography::ECC::SignMessage(Auth::GuidKey, challenge));
|
connectData.set_signature(Utils::Cryptography::ECC::SignMessage(GuidKey, challenge));
|
||||||
connectData.set_infostring(connectString);
|
connectData.set_infostring(connectString);
|
||||||
|
|
||||||
Network::SendCommand(sock, adr, "connect", connectData.SerializeAsString());
|
Network::SendCommand(sock, adr, "connect", connectData.SerializeAsString());
|
||||||
@ -182,7 +184,7 @@ namespace Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parse the infostring
|
// Parse the infostring
|
||||||
Utils::InfoString infostr(params[2]);
|
Utils::InfoString infostr(params.get(2));
|
||||||
|
|
||||||
// Read the required data
|
// Read the required data
|
||||||
const auto steamId = infostr.get("xuid");
|
const auto steamId = infostr.get("xuid");
|
||||||
@ -206,13 +208,13 @@ namespace Components
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::find(Auth::BannedUids.begin(), Auth::BannedUids.end(), xuid) != Auth::BannedUids.end())
|
if (std::find(BannedUids.begin(), BannedUids.end(), xuid) != BannedUids.end())
|
||||||
{
|
{
|
||||||
Network::Send(address, "error\nYour online profile is invalid. Delete your players folder and restart ^2IW4x^7.");
|
Network::Send(address, "error\nYour online profile is invalid. Delete your players folder and restart ^2IW4x^7.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xuid != Auth::GetKeyHash(connectData.publickey()))
|
if (xuid != GetKeyHash(connectData.publickey()))
|
||||||
{
|
{
|
||||||
Network::Send(address, "error\nXUID doesn't match the certificate!");
|
Network::Send(address, "error\nXUID doesn't match the certificate!");
|
||||||
return;
|
return;
|
||||||
@ -230,7 +232,7 @@ namespace Components
|
|||||||
|
|
||||||
// Verify the security level
|
// Verify the security level
|
||||||
auto ourLevel = Dvar::Var("sv_securityLevel").get<unsigned int>();
|
auto ourLevel = Dvar::Var("sv_securityLevel").get<unsigned int>();
|
||||||
auto userLevel = Auth::GetZeroBits(connectData.token(), connectData.publickey());
|
auto userLevel = GetZeroBits(connectData.token(), connectData.publickey());
|
||||||
|
|
||||||
if (userLevel < ourLevel)
|
if (userLevel < ourLevel)
|
||||||
{
|
{
|
||||||
@ -252,7 +254,7 @@ namespace Components
|
|||||||
lea eax, [esp + 20h]
|
lea eax, [esp + 20h]
|
||||||
push eax
|
push eax
|
||||||
push esi
|
push esi
|
||||||
call Auth::ParseConnectData
|
call ParseConnectData
|
||||||
pop esi
|
pop esi
|
||||||
pop eax
|
pop eax
|
||||||
popad
|
popad
|
||||||
@ -262,6 +264,44 @@ namespace Components
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* Auth::Info_ValueForKeyStub(const char* s, const char* key)
|
||||||
|
{
|
||||||
|
auto* value = Game::Info_ValueForKey(s, key);
|
||||||
|
|
||||||
|
HasAccessToReservedSlot = std::strcmp((*Game::sv_privatePassword)->current.string, value) == 0;
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
__declspec(naked) void Auth::DirectConnectPrivateClientStub()
|
||||||
|
{
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
push eax
|
||||||
|
|
||||||
|
mov al, HasAccessToReservedSlot
|
||||||
|
test al, al
|
||||||
|
|
||||||
|
pop eax
|
||||||
|
|
||||||
|
je noAccess
|
||||||
|
|
||||||
|
// Set the number of private clients to 0 if the client has the right password
|
||||||
|
xor eax, eax
|
||||||
|
jmp safeContinue
|
||||||
|
|
||||||
|
noAccess:
|
||||||
|
mov eax, dword ptr [edx + 0x10]
|
||||||
|
|
||||||
|
safeContinue:
|
||||||
|
// Game code skipped by hook
|
||||||
|
add esp, 0xC
|
||||||
|
|
||||||
|
push 0x460FB3
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsigned __int64 Auth::GetKeyHash(const std::string& key)
|
unsigned __int64 Auth::GetKeyHash(const std::string& key)
|
||||||
{
|
{
|
||||||
std::string hash = Utils::Cryptography::SHA1::Compute(key);
|
std::string hash = Utils::Cryptography::SHA1::Compute(key);
|
||||||
@ -276,18 +316,18 @@ namespace Components
|
|||||||
|
|
||||||
unsigned __int64 Auth::GetKeyHash()
|
unsigned __int64 Auth::GetKeyHash()
|
||||||
{
|
{
|
||||||
Auth::LoadKey();
|
LoadKey();
|
||||||
return Auth::GetKeyHash(Auth::GuidKey.getPublicKey());
|
return GetKeyHash(GuidKey.getPublicKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Auth::StoreKey()
|
void Auth::StoreKey()
|
||||||
{
|
{
|
||||||
if (!Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled() && Auth::GuidKey.isValid())
|
if (!Dedicated::IsEnabled() && !ZoneBuilder::IsEnabled() && GuidKey.isValid())
|
||||||
{
|
{
|
||||||
Proto::Auth::Certificate cert;
|
Proto::Auth::Certificate cert;
|
||||||
cert.set_token(Auth::GuidToken.toString());
|
cert.set_token(GuidToken.toString());
|
||||||
cert.set_ctoken(Auth::ComputeToken.toString());
|
cert.set_ctoken(ComputeToken.toString());
|
||||||
cert.set_privatekey(Auth::GuidKey.serialize(PK_PRIVATE));
|
cert.set_privatekey(GuidKey.serialize(PK_PRIVATE));
|
||||||
|
|
||||||
Utils::IO::WriteFile("players/guid.dat", cert.SerializeAsString());
|
Utils::IO::WriteFile("players/guid.dat", cert.SerializeAsString());
|
||||||
}
|
}
|
||||||
@ -295,30 +335,30 @@ namespace Components
|
|||||||
|
|
||||||
void Auth::GenerateKey()
|
void Auth::GenerateKey()
|
||||||
{
|
{
|
||||||
Auth::GuidToken.clear();
|
GuidToken.clear();
|
||||||
Auth::ComputeToken.clear();
|
ComputeToken.clear();
|
||||||
Auth::GuidKey = Utils::Cryptography::ECC::GenerateKey(512);
|
GuidKey = Utils::Cryptography::ECC::GenerateKey(512);
|
||||||
Auth::StoreKey();
|
StoreKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Auth::LoadKey(bool force)
|
void Auth::LoadKey(bool force)
|
||||||
{
|
{
|
||||||
if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) return;
|
if (Dedicated::IsEnabled() || ZoneBuilder::IsEnabled()) return;
|
||||||
if (!force && Auth::GuidKey.isValid()) return;
|
if (!force && GuidKey.isValid()) return;
|
||||||
|
|
||||||
Proto::Auth::Certificate cert;
|
Proto::Auth::Certificate cert;
|
||||||
if (cert.ParseFromString(::Utils::IO::ReadFile("players/guid.dat")))
|
if (cert.ParseFromString(::Utils::IO::ReadFile("players/guid.dat")))
|
||||||
{
|
{
|
||||||
Auth::GuidKey.deserialize(cert.privatekey());
|
GuidKey.deserialize(cert.privatekey());
|
||||||
Auth::GuidToken = cert.token();
|
GuidToken = cert.token();
|
||||||
Auth::ComputeToken = cert.ctoken();
|
ComputeToken = cert.ctoken();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Auth::GuidKey.free();
|
GuidKey.free();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Auth::GuidKey.isValid())
|
if (!GuidKey.isValid())
|
||||||
{
|
{
|
||||||
Auth::GenerateKey();
|
Auth::GenerateKey();
|
||||||
}
|
}
|
||||||
@ -326,32 +366,32 @@ namespace Components
|
|||||||
|
|
||||||
uint32_t Auth::GetSecurityLevel()
|
uint32_t Auth::GetSecurityLevel()
|
||||||
{
|
{
|
||||||
return Auth::GetZeroBits(Auth::GuidToken, Auth::GuidKey.getPublicKey());
|
return GetZeroBits(GuidToken, GuidKey.getPublicKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Auth::IncreaseSecurityLevel(uint32_t level, const std::string& command)
|
void Auth::IncreaseSecurityLevel(uint32_t level, const std::string& command)
|
||||||
{
|
{
|
||||||
if (Auth::GetSecurityLevel() >= level) return;
|
if (GetSecurityLevel() >= level) return;
|
||||||
|
|
||||||
if (!Auth::TokenContainer.generating)
|
if (!TokenContainer.generating)
|
||||||
{
|
{
|
||||||
Auth::TokenContainer.cancel = false;
|
TokenContainer.cancel = false;
|
||||||
Auth::TokenContainer.targetLevel = level;
|
TokenContainer.targetLevel = level;
|
||||||
Auth::TokenContainer.command = command;
|
TokenContainer.command = command;
|
||||||
|
|
||||||
// Open menu
|
// Open menu
|
||||||
Command::Execute("openmenu security_increase_popmenu", true);
|
Command::Execute("openmenu security_increase_popmenu", true);
|
||||||
|
|
||||||
// Start thread
|
// Start thread
|
||||||
Auth::TokenContainer.thread = std::thread([&level]()
|
TokenContainer.thread = std::thread([&level]()
|
||||||
{
|
{
|
||||||
Auth::TokenContainer.generating = true;
|
TokenContainer.generating = true;
|
||||||
Auth::TokenContainer.hashes = 0;
|
TokenContainer.hashes = 0;
|
||||||
Auth::TokenContainer.startTime = Game::Sys_Milliseconds();
|
TokenContainer.startTime = Game::Sys_Milliseconds();
|
||||||
Auth::IncrementToken(Auth::GuidToken, Auth::ComputeToken, Auth::GuidKey.getPublicKey(), Auth::TokenContainer.targetLevel, &Auth::TokenContainer.cancel, &Auth::TokenContainer.hashes);
|
IncrementToken(GuidToken, ComputeToken, GuidKey.getPublicKey(), TokenContainer.targetLevel, &TokenContainer.cancel, &TokenContainer.hashes);
|
||||||
Auth::TokenContainer.generating = false;
|
TokenContainer.generating = false;
|
||||||
|
|
||||||
if (Auth::TokenContainer.cancel)
|
if (TokenContainer.cancel)
|
||||||
{
|
{
|
||||||
Logger::Print("Token incrementation thread terminated\n");
|
Logger::Print("Token incrementation thread terminated\n");
|
||||||
}
|
}
|
||||||
@ -399,7 +439,7 @@ namespace Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if we already have the desired security level
|
// Check if we already have the desired security level
|
||||||
uint32_t lastLevel = Auth::GetZeroBits(token, publicKey);
|
uint32_t lastLevel = GetZeroBits(token, publicKey);
|
||||||
uint32_t level = lastLevel;
|
uint32_t level = lastLevel;
|
||||||
if (level >= zeroBits) return;
|
if (level >= zeroBits) return;
|
||||||
|
|
||||||
@ -407,7 +447,7 @@ namespace Components
|
|||||||
{
|
{
|
||||||
++computeToken;
|
++computeToken;
|
||||||
if (count) ++(*count);
|
if (count) ++(*count);
|
||||||
level = Auth::GetZeroBits(computeToken, publicKey);
|
level = GetZeroBits(computeToken, publicKey);
|
||||||
|
|
||||||
// Store level if higher than the last one
|
// Store level if higher than the last one
|
||||||
if (level >= lastLevel)
|
if (level >= lastLevel)
|
||||||
@ -425,30 +465,36 @@ namespace Components
|
|||||||
|
|
||||||
Auth::Auth()
|
Auth::Auth()
|
||||||
{
|
{
|
||||||
Auth::TokenContainer.cancel = false;
|
TokenContainer.cancel = false;
|
||||||
Auth::TokenContainer.generating = false;
|
TokenContainer.generating = false;
|
||||||
|
|
||||||
|
HasAccessToReservedSlot = false;
|
||||||
|
|
||||||
Localization::Set("MPUI_SECURITY_INCREASE_MESSAGE", "");
|
Localization::Set("MPUI_SECURITY_INCREASE_MESSAGE", "");
|
||||||
|
|
||||||
// Load the key
|
// Load the key
|
||||||
Auth::LoadKey(true);
|
LoadKey(true);
|
||||||
Steam::SteamUser()->GetSteamID();
|
Steam::SteamUser()->GetSteamID();
|
||||||
|
|
||||||
Scheduler::Loop(Auth::Frame, Scheduler::Pipeline::MAIN);
|
Scheduler::Loop(Frame, Scheduler::Pipeline::MAIN);
|
||||||
|
|
||||||
// Register dvar
|
// Register dvar
|
||||||
Dvar::Register<int>("sv_securityLevel", 23, 0, 512, Game::DVAR_SERVERINFO, "Security level for GUID certificates (POW)");
|
Dvar::Register<int>("sv_securityLevel", 23, 0, 512, Game::DVAR_SERVERINFO, "Security level for GUID certificates (POW)");
|
||||||
|
|
||||||
// Install registration hook
|
// Install registration hook
|
||||||
Utils::Hook(0x6265F9, Auth::DirectConnectStub, HOOK_JUMP).install()->quick();
|
Utils::Hook(0x6265F9, DirectConnectStub, HOOK_JUMP).install()->quick();
|
||||||
Utils::Hook(0x41D3E3, Auth::SendConnectDataStub, HOOK_CALL).install()->quick();
|
Utils::Hook(0x460EF5, Info_ValueForKeyStub, HOOK_CALL).install()->quick();
|
||||||
|
Utils::Hook(0x460FAD, DirectConnectPrivateClientStub, HOOK_JUMP).install()->quick();
|
||||||
|
Utils::Hook::Nop(0x460FAD + 5, 1);
|
||||||
|
|
||||||
|
Utils::Hook(0x41D3E3, SendConnectDataStub, HOOK_CALL).install()->quick();
|
||||||
|
|
||||||
// SteamIDs can only contain 31 bits of actual 'id' data.
|
// SteamIDs can only contain 31 bits of actual 'id' data.
|
||||||
// The other 33 bits are steam internal data like universe and so on.
|
// The other 33 bits are steam internal data like universe and so on.
|
||||||
// Using only 31 bits for fingerprints is pretty insecure.
|
// Using only 31 bits for fingerprints is pretty insecure.
|
||||||
// The function below verifies the integrity steam's part of the SteamID.
|
// The function below verifies the integrity steam's part of the SteamID.
|
||||||
// Patching that check allows us to use 64 bit for fingerprints.
|
// Patching that check allows us to use 64 bit for fingerprints.
|
||||||
Utils::Hook::Set<DWORD>(0x4D0D60, 0xC301B0);
|
Utils::Hook::Set<std::uint32_t>(0x4D0D60, 0xC301B0);
|
||||||
|
|
||||||
// Guid command
|
// Guid command
|
||||||
Command::Add("guid", []
|
Command::Add("guid", []
|
||||||
@ -462,42 +508,42 @@ namespace Components
|
|||||||
{
|
{
|
||||||
if (params->size() < 2)
|
if (params->size() < 2)
|
||||||
{
|
{
|
||||||
const auto level = Auth::GetZeroBits(Auth::GuidToken, Auth::GuidKey.getPublicKey());
|
const auto level = GetZeroBits(GuidToken, GuidKey.getPublicKey());
|
||||||
Logger::Print("Your current security level is {}\n", level);
|
Logger::Print("Your current security level is {}\n", level);
|
||||||
Logger::Print("Your security token is: {}\n", Utils::String::DumpHex(Auth::GuidToken.toString(), ""));
|
Logger::Print("Your security token is: {}\n", Utils::String::DumpHex(GuidToken.toString(), ""));
|
||||||
Logger::Print("Your computation token is: {}\n", Utils::String::DumpHex(Auth::ComputeToken.toString(), ""));
|
Logger::Print("Your computation token is: {}\n", Utils::String::DumpHex(ComputeToken.toString(), ""));
|
||||||
|
|
||||||
Toast::Show("cardicon_locked", "^5Security Level", Utils::String::VA("Your security level is %d", level), 3000);
|
Toast::Show("cardicon_locked", "^5Security Level", Utils::String::VA("Your security level is %d", level), 3000);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const auto level = std::strtoul(params->get(1), nullptr, 10);
|
const auto level = std::strtoul(params->get(1), nullptr, 10);
|
||||||
Auth::IncreaseSecurityLevel(level);
|
IncreaseSecurityLevel(level);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
UIScript::Add("security_increase_cancel", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info)
|
UIScript::Add("security_increase_cancel", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info)
|
||||||
{
|
{
|
||||||
Auth::TokenContainer.cancel = true;
|
TokenContainer.cancel = true;
|
||||||
Logger::Print("Token incrementation process canceled!\n");
|
Logger::Print("Token incrementation process canceled!\n");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Auth::~Auth()
|
Auth::~Auth()
|
||||||
{
|
{
|
||||||
Auth::StoreKey();
|
StoreKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Auth::preDestroy()
|
void Auth::preDestroy()
|
||||||
{
|
{
|
||||||
Auth::TokenContainer.cancel = true;
|
TokenContainer.cancel = true;
|
||||||
Auth::TokenContainer.generating = false;
|
TokenContainer.generating = false;
|
||||||
|
|
||||||
// Terminate thread
|
// Terminate thread
|
||||||
if (Auth::TokenContainer.thread.joinable())
|
if (TokenContainer.thread.joinable())
|
||||||
{
|
{
|
||||||
Auth::TokenContainer.thread.join();
|
TokenContainer.thread.join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,10 +44,14 @@ namespace Components
|
|||||||
static Utils::Cryptography::Token ComputeToken;
|
static Utils::Cryptography::Token ComputeToken;
|
||||||
static Utils::Cryptography::ECC::Key GuidKey;
|
static Utils::Cryptography::ECC::Key GuidKey;
|
||||||
static std::vector<std::uint64_t> BannedUids;
|
static std::vector<std::uint64_t> BannedUids;
|
||||||
|
|
||||||
|
static bool HasAccessToReservedSlot;
|
||||||
|
|
||||||
static void SendConnectDataStub(Game::netsrc_t sock, Game::netadr_t adr, const char* format, int len);
|
static void SendConnectDataStub(Game::netsrc_t sock, Game::netadr_t adr, const char* format, int len);
|
||||||
static void ParseConnectData(Game::msg_t* msg, Game::netadr_t* addr);
|
static void ParseConnectData(Game::msg_t* msg, Game::netadr_t* addr);
|
||||||
static void DirectConnectStub();
|
static void DirectConnectStub();
|
||||||
|
static char* Info_ValueForKeyStub(const char* s, const char* key);
|
||||||
|
static void DirectConnectPrivateClientStub();
|
||||||
|
|
||||||
static void Frame();
|
static void Frame();
|
||||||
};
|
};
|
||||||
|
@ -936,7 +936,7 @@ namespace Components
|
|||||||
UIScript::Add("CreateListFavorite", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info)
|
UIScript::Add("CreateListFavorite", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info)
|
||||||
{
|
{
|
||||||
auto* serverInfo = GetCurrentServer();
|
auto* serverInfo = GetCurrentServer();
|
||||||
if (info)
|
if (info && serverInfo && serverInfo->addr.isValid())
|
||||||
{
|
{
|
||||||
StoreFavourite(serverInfo->addr.getString());
|
StoreFavourite(serverInfo->addr.getString());
|
||||||
}
|
}
|
||||||
@ -944,7 +944,11 @@ namespace Components
|
|||||||
|
|
||||||
UIScript::Add("CreateFavorite", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info)
|
UIScript::Add("CreateFavorite", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info)
|
||||||
{
|
{
|
||||||
StoreFavourite(Dvar::Var("ui_favoriteAddress").get<std::string>());
|
const auto value = Dvar::Var("ui_favoriteAddress").get<std::string>();
|
||||||
|
if (!value.empty())
|
||||||
|
{
|
||||||
|
StoreFavourite(value);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
UIScript::Add("CreateCurrentServerFavorite", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info)
|
UIScript::Add("CreateCurrentServerFavorite", []([[maybe_unused]] const UIScript::Token& token, [[maybe_unused]] const Game::uiInfo_s* info)
|
||||||
|
Loading…
Reference in New Issue
Block a user