Skip to content

Commit

Permalink
citizen:server: msec changes, support license identifier type, de…
Browse files Browse the repository at this point in the history
…terministic identifier ordering
  • Loading branch information
blattersturm committed Aug 13, 2017
1 parent 5d8265c commit dd42666
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 24 deletions.
5 changes: 5 additions & 0 deletions code/components/citizen-server-impl/include/GameServer.h
Expand Up @@ -11,6 +11,11 @@

#include <enet/enet.h>

inline std::chrono::milliseconds msec()
{
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now().time_since_epoch());
}

namespace fx
{
struct enet_host_deleter
Expand Down
Expand Up @@ -9,7 +9,7 @@ namespace fx
{
server->SetRunLoop([=]()
{
auto lastTime = msec();
auto lastTime = msec().count();

auto waiter = TWait();
auto ticker = TTick();
Expand All @@ -20,11 +20,11 @@ namespace fx

while (true)
{
auto now = msec() - lastTime;
auto now = msec().count() - lastTime;

residualTime += now;

lastTime = msec();
lastTime = msec().count();

if (now >= 150)
{
Expand Down
5 changes: 0 additions & 5 deletions code/components/citizen-server-impl/src/Client.cpp
Expand Up @@ -2,11 +2,6 @@
#include <Client.h>
#include <GameServer.h>

inline static std::chrono::milliseconds msec()
{
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now().time_since_epoch());
}

namespace fx
{
Client::Client(const std::string& guid)
Expand Down
Expand Up @@ -37,4 +37,4 @@ static InitFunction initFunction([]()
} idp;

fx::RegisterServerIdentityProvider(&idp);
});
}, 150);
11 changes: 3 additions & 8 deletions code/components/citizen-server-impl/src/GameServer.cpp
Expand Up @@ -11,11 +11,6 @@

#include <PrintListener.h>

inline static uint64_t msec()
{
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
}

namespace fx
{
ENetAddress GetENetAddress(const net::PeerAddress& peerAddress)
Expand Down Expand Up @@ -61,7 +56,7 @@ namespace fx
static std::map<ENetHost*, GameServer*> g_hostInstances;

GameServer::GameServer()
: m_residualTime(0), m_serverTime(msec()), m_nextHeartbeatTime(0)
: m_residualTime(0), m_serverTime(msec().count()), m_nextHeartbeatTime(0)
{
seCreateContext(&m_seContext);

Expand Down Expand Up @@ -313,7 +308,7 @@ namespace fx
}

// if we should heartbeat
if ((int64_t)msec() >= m_nextHeartbeatTime)
if (msec().count() >= m_nextHeartbeatTime)
{
// loop through each master
for (auto& master : m_masters)
Expand Down Expand Up @@ -358,7 +353,7 @@ namespace fx
}
}

m_nextHeartbeatTime = msec() + (180 * 1000);
m_nextHeartbeatTime = msec().count() + (180 * 1000);
}

{
Expand Down
103 changes: 103 additions & 0 deletions code/components/citizen-server-impl/src/InitConnectMethod.cpp
Expand Up @@ -122,6 +122,87 @@ static bool VerifyTicket(const std::string& guid, const std::string& ticket)
return true;
}

struct TicketData
{
std::optional<std::array<uint8_t, 20>> entitlementHash;
};

static std::optional<TicketData> VerifyTicketEx(const std::string& ticket)
{
auto ticketData = Botan::base64_decode(ticket);

// validate ticket length
if (ticketData.size() < 20 + 4 + 128 + 4)
{
return {};
}

uint32_t length = *(uint32_t*)&ticketData[20 + 4 + 128];

// validate full length
if (ticketData.size() < 20 + 4 + 128 + 4 + length)
{
return {};
}

// copy extra data
std::vector<uint8_t> extraData(length);

if (!extraData.empty())
{
memcpy(&extraData[0], &ticketData[20 + 4 + 128 + 4], length);
}

// check the RSA signature
uint32_t sigLength = *(uint32_t*)&ticketData[20 + 4 + 128 + 4 + length];

if (sigLength != 128)
{
return {};
}

Botan::SHA_160 hashFunction;
auto result = hashFunction.process(&ticketData[4], ticketData.size() - 128 - 4 - 4);

std::vector<uint8_t> msg(result.size() + 1);
msg[0] = 2;
memcpy(&msg[1], &result[0], result.size());

auto modulus = Botan::base64_decode("1DNT1go22VUAU3BON+jCfXxs7Ow9Zxwng4ARTX/vrv6I65bsSYbdBrcc"
"w/50Fu7AJr8zy8+sXK8wUO4gx00frtA0adaGeZOeBqNq7/K3Gprv98wc"
"ftbxWjUv75pVl9Ush5yxpBPbuYUnGR/Nh2+K3GRrIrKxWYpNSF1JZYzE"
"+5k=");

auto exponent = Botan::base64_decode("AQAB");

Botan::BigInt n(modulus.data(), modulus.size());
Botan::BigInt e(exponent.data(), exponent.size());

auto pk = Botan::RSA_PublicKey(n, e);

auto signer = std::make_unique<Botan::PK_Verifier>(pk, "EMSA_PKCS1(SHA-1)");

bool valid = signer->verify_message(msg.data(), msg.size(), &ticketData[length + 4 + 4 + 128 + 20 + 4], sigLength);

if (!valid)
{
trace("Connecting player: ticket RSA signature not matching\n");
return {};
}

TicketData outData;

if (length >= 20)
{
std::array<uint8_t, 20> entitlementHash;
memcpy(entitlementHash.data(), &extraData[0], entitlementHash.size());

outData.entitlementHash = entitlementHash;
}

return outData;
}

static InitFunction initFunction([]()
{
fx::ServerInstanceBase::OnServerCreate.Connect([](fx::ServerInstanceBase* instance)
Expand Down Expand Up @@ -154,6 +235,8 @@ static InitFunction initFunction([]()
auto guid = guidIt->second;
auto protocol = atoi(protocolIt->second.c_str());

TicketData ticketData;

if (!lanVar->GetValue())
{
auto ticketIt = postMap.find("cfxTicket");
Expand All @@ -169,6 +252,16 @@ static InitFunction initFunction([]()
cb(json::object({ { "error", "FiveM ticket authorization failed." } }));
return;
}

auto optionalTicket = VerifyTicketEx(ticketIt->second);

if (!optionalTicket)
{
cb(json::object({ { "error", "FiveM ticket authorization failed. (2)" } }));
return;
}

ticketData = *optionalTicket;
}

std::string token = boost::uuids::to_string(boost::uuids::basic_random_generator<boost::random_device>()());
Expand Down Expand Up @@ -202,6 +295,16 @@ static InitFunction initFunction([]()
client->SetConnectionToken(token);
client->SetTcpEndPoint(ra.substr(0, ra.find_last_of(':')));
client->SetNetId(0x10000 + tempId);

// add the entitlement hash if needed
if (ticketData.entitlementHash)
{
auto& hash = *ticketData.entitlementHash;
client->SetData("entitlementHash", fmt::sprintf("%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
hash[0], hash[1], hash[2], hash[3], hash[4], hash[5], hash[6], hash[7], hash[8], hash[9],
hash[10], hash[11], hash[12], hash[13], hash[14], hash[15], hash[16], hash[17], hash[18], hash[19]));
}

client->Touch();

auto it = g_serverProviders.begin();
Expand Down
@@ -0,0 +1,44 @@
/*
* This file is part of FiveM: https://fivem.net/
*
* See LICENSE and MENTIONS in the root of the source tree for information
* regarding licensing.
*/

#include "StdInc.h"
#include <ServerIdentityProvider.h>

static InitFunction initFunction([]()
{
static struct LicenseIdProvider : public fx::ServerIdentityProviderBase
{
virtual std::string GetIdentifierPrefix() override
{
return "license";
}

virtual int GetVarianceLevel() override
{
return 1;
}

virtual int GetTrustLevel() override
{
return 5;
}

virtual void RunAuthentication(const std::shared_ptr<fx::Client>& clientPtr, const std::map<std::string, std::string>& postMap, const std::function<void(std::optional<std::string>)>& cb) override
{
auto& any = clientPtr->GetData("entitlementHash");

if (any.has_value())
{
clientPtr->AddIdentifier(fmt::sprintf("license:%s", std::any_cast<std::string>(any)));
}

cb({});
}
} idp;

fx::RegisterServerIdentityProvider(&idp);
}, 151);
Expand Up @@ -11,11 +11,6 @@

#include <se/Security.h>

inline static uint64_t msec()
{
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now().time_since_epoch()).count();
}

static InitFunction initFunction([]()
{
auto makeClientFunction = [](auto fn)
Expand Down Expand Up @@ -103,7 +98,7 @@ static InitFunction initFunction([]()

fx::ScriptEngine::RegisterNativeHandler("GET_PLAYER_LAST_MSG", makeClientFunction([](fx::ScriptContext& context, const std::shared_ptr<fx::Client>& client)
{
return msec() - client->GetLastSeen().count();
return (msec() - client->GetLastSeen()).count();
}));

fx::ScriptEngine::RegisterNativeHandler("DROP_PLAYER", makeClientFunction([](fx::ScriptContext& context, const std::shared_ptr<fx::Client>& client)
Expand Down
Expand Up @@ -85,4 +85,4 @@ static InitFunction initFunction([]()
} idp;

fx::RegisterServerIdentityProvider(&idp);
});
}, 152);

0 comments on commit dd42666

Please sign in to comment.