Skip to content

Commit

Permalink
Adding better way of server verify.
Browse files Browse the repository at this point in the history
  • Loading branch information
Aleksandar Ovcharov committed Aug 20, 2024
1 parent 4055881 commit c7e2a10
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 42 deletions.
14 changes: 12 additions & 2 deletions Entities/ApiResponseEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,23 @@ public CommandsResponseEntity(int status, List<CommandDataEntity> data)
public class ServerResponseEntity
{

public int id { get; set; }
public int id { get; set; } = 0;

public ServerResponseEntity(int id)
public ServerResponseEntity(int id = 0)
{
this.id = id;
}

}

public class ServerVerifyResponseEntity
{

public string message { get; set; } = "";
public ServerVerifyResponseEntity(string message)
{
this.message = message;
}
}

}
15 changes: 0 additions & 15 deletions Entities/PlayerUpdateDto.cs

This file was deleted.

125 changes: 113 additions & 12 deletions GameCMSPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using System.Text.RegularExpressions;
using MySqlConnector;
using Dapper;
using CounterStrikeSharp.API.Modules.Cvars;

public sealed partial class GameCMSPlugin : BasePlugin, IPluginConfig<GameCMSConfig>
{
Expand All @@ -24,13 +25,16 @@ public sealed partial class GameCMSPlugin : BasePlugin, IPluginConfig<GameCMSCon
public GameCMSConfig Config { get; set; } = new();
private readonly HttpClient client = new();
private int serverId = 0;
private bool dbConnected = false;
private Helper _helper;
private WebstoreService _webStoreService;
private AdminService _adminService;
private HttpServerSerivce _httpServer;

private PlayingTimeService _playingTimeService;

private string API_URI_BASE = "https://api.gamecms.org/v2";


public GameCMSPlugin(Helper helper, WebstoreService webstoreService, AdminService adminService, HttpServerSerivce httpServer, PlayingTimeService playingTimeService)
{
Expand All @@ -47,7 +51,7 @@ public override void Load(bool hotReload)
int ServerHttpPort = Config.ServerHttpPort;
string serverApiKey = Config.ServerApiKey;
_httpServer.Start(ServerHttpPort, serverApiKey);
_webStoreService.ListenForCommands(serverApiKey);
_webStoreService.ListenForCommands(serverApiKey, API_URI_BASE);
_playingTimeService.Start(hotReload, serverId);

//load all player cache.
Expand All @@ -68,11 +72,6 @@ public override void Unload(bool hotReload)

}

private void OnMapStart(string OnMapStart)
{
//serverId = GetServerId();
// _adminService.ProgressAdminsData(serverId, Config.DeleteExpiredAdmins);
}

public int GetServerId()
{
Expand All @@ -81,7 +80,7 @@ public int GetServerId()

private int SetServerId()
{
var url = "https://api.gamecms.org/v2/cs2/server";
var url = $"{API_URI_BASE}/server";
HttpRequestMessage request = _helper.GetServerRequestHeaders(Config.ServerApiKey);
request.RequestUri = new Uri(url);
request.Method = HttpMethod.Get;
Expand All @@ -105,29 +104,130 @@ private int SetServerId()
catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException)
{
Logger.LogWarning("The request timed out. Please check your network connection or try again later.");
// Specifically catching the TaskCanceledException that results from a timeout
}
catch (Exception ex)
{
Logger.LogError(ex, "Failed to get server ID.");
}
return 0; // Return 0 in case of any exceptions, including timeout
return 0;
}


[ConsoleCommand("css_gcms_force_store")]
[ConsoleCommand("css_gcms_store_force")]
[CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
[RequiresPermissions("@css/root")]
public void OnCMSForceStoreCommands(CCSPlayerController? player, CommandInfo command)
public void onCommandStoreForce(CCSPlayerController? player, CommandInfo command)
{
_webStoreService.TryToFetchStoreCommands(true);
}

[ConsoleCommand("css_gcms_server_verify")]
[CommandHelper(minArgs: 1, usage: "<server-api-key>", whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
[RequiresPermissions("@css/root")]
public void onCommandServerVerifyAsync(CCSPlayerController? player, CommandInfo command)
{
var moduleFolderName = Path.GetFileName(ModuleDirectory);
var filePath = _helper.GetFilePath($"configs/plugins");
filePath = _helper.GetFilePath($"{filePath}/{moduleFolderName}");
filePath = _helper.GetFilePath($"{filePath}/{moduleFolderName}.json");



if (!_httpServer.IsHttpServerRunning())
{
command.ReplyToCommand("GameCMS is no listening for requiests, please ensure you have entered free and open ServerHttpPort, and you have give your server a restart.");
return;
}

if (!dbConnected)
{
command.ReplyToCommand("Database not connected! Please ensure you have connected your database. Before run this command.");
return;
}

string ServerKey = command.GetArg(1);

if (ServerKey.Length < 64)
{
command.ReplyToCommand("Invalid Server API Key! Please ensure you have copied the right Server API Key!");
return;
}

var url = $"{API_URI_BASE}/server-verify/cs2";

HttpRequestMessage request = _helper.GetServerRequestHeaders(ServerKey);
request.RequestUri = new Uri(url);
request.Method = HttpMethod.Post;

var address = _helper.GetServerIp();
var port = ConVar.Find("hostport")?.GetPrimitiveValue<int>()!.ToString() ?? "27015";
var httpPort = Config.ServerHttpPort;

string encryptionKey = ServerKey.Substring(0, 32);
var formData = new Dictionary<string, string>
{
{ "address", address },
{ "port", port.ToString() },
{ "httpPort", httpPort.ToString() },
{ "dbHost", _helper.EncryptString(Config.database.host, encryptionKey) },
{ "dbPort", _helper.EncryptString(Config.database.port.ToString(), encryptionKey) },
{ "dbName", _helper.EncryptString(Config.database.name, encryptionKey) },
{ "dbUsername", _helper.EncryptString(Config.database.username, encryptionKey) },
{ "dbPassword", _helper.EncryptString(Config.database.password, encryptionKey) }
};

request.Content = new FormUrlEncodedContent(formData);
try
{
var responseTask = client.SendAsync(request).ConfigureAwait(false);
var response = responseTask.GetAwaiter().GetResult();
var readTask = response.Content.ReadAsStringAsync().ConfigureAwait(false);
string responseBody = readTask.GetAwaiter().GetResult();
if (response.StatusCode == HttpStatusCode.OK)
{
var apiResponse = JsonSerializer.Deserialize<ServerResponseEntity>(responseBody);
if (apiResponse != null)
{
serverId = apiResponse.id;
Config.ServerApiKey = ServerKey;
string jsonString = JsonSerializer.Serialize(Config, new JsonSerializerOptions { WriteIndented = true });
File.WriteAllText(filePath, jsonString);
command.ReplyToCommand($"[GameCMS.ORG] Server verified successfully!");
}
else
{
command.ReplyToCommand("[GameCMS.ORG] Server verification failed: Unexpected response from the server.");
}
}
else
{

var apiResponse = JsonSerializer.Deserialize<ServerVerifyResponseEntity>(responseBody);
string message = "[GameCMS.ORG] Server verification failed: Unexpected error occurred";
if (apiResponse != null)
{
message = $"[GameCMS.ORG] {apiResponse.message}";
}
command.ReplyToCommand(message);
}
}
catch (Exception ex)
{
command.ReplyToCommand($"[GameCMS.ORG] Exception occurred during server verification: {ex.Message}");
}






}


[ConsoleCommand("css_gcms_reload_admins")]
[CommandHelper(minArgs: 0, whoCanExecute: CommandUsage.CLIENT_AND_SERVER)]
[RequiresPermissions("@css/root")]
public void OnCMSReloadAdmins(CCSPlayerController? player, CommandInfo command)
public void onCommandReloadAdmins(CCSPlayerController? player, CommandInfo command)
{
_adminService.ProgressAdminsData(serverId, Config.DeleteExpiredAdmins);
}
Expand Down Expand Up @@ -199,6 +299,7 @@ public void OnConfigParsed(GameCMSConfig config)
try
{
Database.Initialize(config, Logger);
dbConnected = true;
Logger.LogInformation("Connected to the database.");
}
catch (Exception ex)
Expand Down
4 changes: 3 additions & 1 deletion GameCMSPlugin.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<GenerateDependencyFile>false</GenerateDependencyFile>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
Expand All @@ -19,10 +19,12 @@
</PackageReference>
<PackageReference Include="Dapper" Version="2.1.44" />
<PackageReference Include="MySqlConnector" Version="2.3.6" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>
<ItemGroup>
<Reference Include="VipCoreApi">
<HintPath>C:\Users\ovcha\Desktop\gamecms-cs2\shared-apis\VipCoreApi.dll</HintPath>
<Private>false</Private>
</Reference>
</ItemGroup>
</Project>
68 changes: 68 additions & 0 deletions Helper.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
namespace GameCMS
{


using System;
using System.Security.Cryptography;
using System.Text;
using System.Net.Http.Headers;
using System.Runtime.InteropServices;
using System.Text.Json;
using System.Text.RegularExpressions;
using CounterStrikeSharp.API;
Expand All @@ -12,8 +17,44 @@ public class Helper
{

private string _directory = string.Empty;

public delegate nint CNetworkSystem_UpdatePublicIp(nint a1);
public static CNetworkSystem_UpdatePublicIp? _networkSystemUpdatePublicIp;


private Dictionary<ulong, long> _playersTimeCollection = new Dictionary<ulong, long>();


// This method is taken from
//https://github.com/daffyyyy/CS2-SimpleAdmin/blob/main/Helper.cs
//thanks to daffyyyy
public string GetServerIp()
{
var networkSystem = NativeAPI.GetValveInterface(0, "NetworkSystemVersion001");

unsafe
{
if (_networkSystemUpdatePublicIp == null)
{
var funcPtr = *(nint*)(*(nint*)(networkSystem) + 256);
_networkSystemUpdatePublicIp = Marshal.GetDelegateForFunctionPointer<CNetworkSystem_UpdatePublicIp>(funcPtr);
}
/*
struct netadr_t
{
uint32_t type
uint8_t ip[4]
uint16_t port
}
*/
// + 4 to skip type, because the size of uint32_t is 4 bytes
var ipBytes = (byte*)(_networkSystemUpdatePublicIp(networkSystem) + 4);
// port is always 0, use the one from convar "hostport"
return $"{ipBytes[0]}.{ipBytes[1]}.{ipBytes[2]}.{ipBytes[3]}";
}
}


public void AddPlayerToTimeCollection(ulong steam_id)
{
long currentUnixTimestampSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
Expand Down Expand Up @@ -92,6 +133,33 @@ public HttpRequestMessage GetServerRequestHeaders(string serverApiKey)
return request;
}

public string EncryptString(string text, string key)
{
// Ensure the key is 32 bytes long for AES-256
using (Aes aes = Aes.Create())
{
aes.Key = Encoding.UTF8.GetBytes(key.Substring(0, 32)); // Use first 32 bytes (64 hex characters)
aes.GenerateIV();
aes.Mode = CipherMode.CBC;

ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);

using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
ms.Write(aes.IV, 0, aes.IV.Length); // Prepend IV to the ciphertext
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter sw = new StreamWriter(cs))
{
sw.Write(text);
}
}

return Convert.ToBase64String(ms.ToArray());
}
}
}

public string[] DeserializeJsonStringArray(string json)
{
if (string.IsNullOrWhiteSpace(json) || json == "{}")
Expand Down
10 changes: 10 additions & 0 deletions Services/HttpServerSerice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ private async Task HandleCommandsRoute(HttpListenerContext context)
await SendJsonResponse(context, new { message = "Command processed" });
}

private async Task HandlePluginsListRoute(HttpListenerContext context)
{

}

private async Task HandlePlayersRoute(HttpListenerContext context)
{
TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
Expand Down Expand Up @@ -450,6 +455,7 @@ private void SetRoutings()
{("/check-connection", "GET"), HandleCheckConnection},
{("/command", "POST"), HandleCommandsRoute},
{("/players", "GET"), HandlePlayersRoute},
{("/plugins", "GET"), HandlePluginsListRoute},

{("/main-configs/admins", "GET"), (context) => HandleGetFile(context, "Admins")},
{("/main-configs/admins", "POST"), (context) => HandleUpdateFile(context, "Admins") },
Expand All @@ -471,5 +477,9 @@ private void SetRoutings()
};
}

public bool IsHttpServerRunning()
{
return isRunning;
}
}
}
Loading

0 comments on commit c7e2a10

Please sign in to comment.