Some more authentication stuff.

This commit is contained in:
momo5502 2016-02-22 13:37:13 +01:00
parent 99af8fbae7
commit 00b7e3f920
7 changed files with 48 additions and 14 deletions

View File

@ -103,7 +103,7 @@ workspace "iw4x"
-- Pre-compiled header
pchheader "STDInclude.hpp" -- must be exactly same as used in #include directives
pchsource "src/STDInclude.cpp" -- real path
buildoptions { "/Zm100 -Zm100" }
buildoptions { "/Zm96 -Zm96" }
filter "files:**.pb.*"
flags {
"NoPCH",

View File

@ -24,13 +24,13 @@ namespace Components
// Not sending a response might allow the player to connect for a few seconds (<= 5) until the timeout is reached.
if (client->state >= 5)
{
if (info->state == Auth::STATE_NEGOTIATING && (Game::Com_Milliseconds() - info->time) > 1000 * 3)
if (info->state == Auth::STATE_NEGOTIATING && (Game::Com_Milliseconds() - info->time) > 1000 * 5)
{
info->state = Auth::STATE_INVALID;
info->time = Game::Com_Milliseconds();
Game::SV_KickClientError(client, "XUID verification timed out!");
}
else if (info->state == Auth::STATE_UNKNOWN && info->time && (Game::Com_Milliseconds() - info->time) > 1000 * 2) // Wait 2 seconds (error delay)
else if (info->state == Auth::STATE_UNKNOWN && info->time && (Game::Com_Milliseconds() - info->time) > 1000 * 5) // Wait 5 seconds (error delay)
{
Logger::Print("Sending XUID authentication request to %s\n", Network::Address(client->adr).GetString());
@ -90,6 +90,9 @@ namespace Components
// Only accept requests from the server we're connected to
if (address != *Game::connectedHost) return;
// Ensure our certificate is loaded
Steam::SteamUser()->GetSteamID();
if (!Steam::User::GuidKey.IsValid()) return;
Proto::Auth::Response response;
@ -104,12 +107,6 @@ namespace Components
{
Logger::Print("Received XUID authentication response from %s\n", address.GetString());
Proto::Auth::Response response;
response.ParseFromString(data);
if (response.signature().empty()) return;
if (response.publickey().empty()) return;
for (int i = 0; i < *Game::svs_numclients; i++)
{
Game::client_t* client = &Game::svs_clients[i];
@ -117,14 +114,24 @@ namespace Components
if (client->state >= 3 && address == client->adr && info->state == Auth::STATE_NEGOTIATING)
{
Proto::Auth::Response response;
unsigned int id = static_cast<unsigned int>(~0x110000100000000 & client->steamid);
// Check if response is valid
if (!response.ParseFromString(data) || response.signature().empty() || response.publickey().empty())
{
info->state = Auth::STATE_INVALID;
Game::SV_KickClientError(client, "XUID authentication response was invalid!");
}
// Check if guid matches the certificate
if (id != (Utils::OneAtATime(response.publickey().data(), response.publickey().size()) & ~0x80000000))
else if (id != (Utils::OneAtATime(response.publickey().data(), response.publickey().size()) & ~0x80000000))
{
info->state = Auth::STATE_INVALID;
Game::SV_KickClientError(client, "XUID doesn't match the certificate!");
}
// Verify GUID using the signature and certificate
else
{
info->publicKey.Set(response.publickey());
@ -140,6 +147,8 @@ namespace Components
Game::SV_KickClientError(client, "Challenge signature was invalid!");
}
}
break;
}
}
});

View File

@ -7,3 +7,9 @@ message Response
bytes signature = 1;
bytes publickey = 2;
}
message Certificate
{
bytes privatekey = 1;
bytes token = 2;
}

View File

@ -2,6 +2,7 @@
namespace Steam
{
::Utils::Cryptography::Token User::GuidToken;
::Utils::Cryptography::ECDSA::Key User::GuidKey;
int User::GetHSteamUser()
@ -30,12 +31,23 @@ namespace Steam
{
if (!User::GuidKey.IsValid())
{
User::GuidKey.Import(::Utils::ReadFile("players/guid.dat"), PK_PRIVATE);
Proto::Auth::Certificate cert;
if (cert.ParseFromString(::Utils::ReadFile("players/guid.dat")))
{
User::GuidKey.Import(cert.privatekey(), PK_PRIVATE);
User::GuidToken = cert.token();
}
if (!User::GuidKey.IsValid())
{
User::GuidToken.Clear();
User::GuidKey = ::Utils::Cryptography::ECDSA::GenerateKey(512);
::Utils::WriteFile("players/guid.dat", User::GuidKey.Export(PK_PRIVATE));
cert.set_token(User::GuidToken.ToString());
cert.set_privatekey(User::GuidKey.Export(PK_PRIVATE));
::Utils::WriteFile("players/guid.dat", cert.SerializeAsString());
}
}

View File

@ -21,6 +21,7 @@ namespace Steam
virtual void CancelAuthTicket(unsigned int hAuthTicket);
virtual unsigned int UserHasLicenseForApp(SteamID steamID, unsigned int appID);
static ::Utils::Cryptography::Token GuidToken;
static ::Utils::Cryptography::ECDSA::Key GuidKey;
};
}

View File

@ -19,6 +19,7 @@ namespace Utils
void Rand::Initialize()
{
ltc_mp = ltm_desc;
register_prng(&fortuna_desc);
rng_make_prng(128, find_prng("fortuna"), &Rand::State, NULL);
}

View File

@ -6,6 +6,7 @@ namespace Utils
{
public:
Token() { this->TokenString.clear(); };
Token(const Token& obj) : TokenString(obj.TokenString) { };
Token(std::string token) : TokenString(token.begin(), token.end()) { };
Token(std::basic_string<uint8_t> token) : TokenString(token.begin(), token.end()) { };
@ -50,8 +51,7 @@ namespace Utils
std::string ToString()
{
auto str = this->ToUnsignedString();
return std::string(str.begin(), str.end());
return std::string(this->TokenString.begin(), this->TokenString.end());
}
std::basic_string<uint8_t> ToUnsignedString()
@ -59,6 +59,11 @@ namespace Utils
return this->TokenString;
}
void Clear()
{
this->TokenString.clear();
}
private:
std::basic_string<uint8_t> TokenString;
};