Skip to content

Commit

Permalink
Mini Auth (#1465)
Browse files Browse the repository at this point in the history
* initial commit

* IOC

* no lists in toml

* maybe

* hm

* dependent

* undo

* no tolerance

* maybe no instantiate

* double

* maybe strings

* patch

* proper string handling

* go back

* redo

* lets try this way eh

* auth cmon

* test logging

* whoops

* our own record

* put it inside the if

* eh

* the worlds a stage

* or not

* hu

* cleanup

* rearrange the try catch to include the initial connection call as well

* shorten it up try to simplify

* no jack

* locale
  • Loading branch information
Cheackraze authored Jun 5, 2024
1 parent 1622c31 commit 652b8e9
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 4 deletions.
8 changes: 7 additions & 1 deletion Content.Client/RCD/RCDMenu.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public RCDMenu(EntityUid owner, RCDMenuBoundUserInterface bui)
tooltip = Loc.GetString(entProto.Name);
}

tooltip = char.ToUpper(tooltip[0]) + tooltip.Remove(0, 1);
tooltip = OopsConcat(char.ToUpper(tooltip[0]).ToString(), tooltip.Remove(0, 1));

var button = new RCDMenuButton()
{
Expand Down Expand Up @@ -119,6 +119,12 @@ public RCDMenu(EntityUid owner, RCDMenuBoundUserInterface bui)
SendRCDSystemMessageAction += bui.SendRCDSystemMessage;
}

private static string OopsConcat(string a, string b)
{
// This exists to prevent Roslyn being clever and compiling something that fails sandbox checks.
return a + b;
}

private void AddRCDMenuButtonOnClickActions(Control control)
{
var radialContainer = control as RadialContainer;
Expand Down
1 change: 1 addition & 0 deletions Content.Server.Database/Model.cs
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,7 @@ public enum ConnectionDenyReason : byte
Whitelist = 1,
Full = 2,
Panic = 3,
Connected = 4,
}

public class ServerBanHit
Expand Down
4 changes: 2 additions & 2 deletions Content.Server/Administration/ServerApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void IPostInjectInit.PostInject()
_sawmill = _logManager.GetSawmill("serverApi");

// Get
RegisterActorHandler(HttpMethod.Get, "/admin/info", InfoHandler);
RegisterHandler(HttpMethod.Get, "/admin/info", InfoHandler); //frontier - not sure why this action needs an actor
RegisterHandler(HttpMethod.Get, "/admin/game_rules", GetGameRules);
RegisterHandler(HttpMethod.Get, "/admin/presets", GetPresets);

Expand Down Expand Up @@ -452,7 +452,7 @@ await context.RespondJsonAsync(new GameruleResponse
/// <summary>
/// Handles fetching information.
/// </summary>
private async Task InfoHandler(IStatusHandlerContext context, Actor actor)
private async Task InfoHandler(IStatusHandlerContext context) //frontier - we had an actor here and never used it so we drop it for now until im compelled to re-add it
{
/*
Information to display
Expand Down
20 changes: 20 additions & 0 deletions Content.Server/Connection/ConnectionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System.Runtime.InteropServices;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using Content.Server._NF.Auth;
using Content.Server.Administration;
using Content.Server.Database;
using Content.Server.GameTicking;
using Content.Server.Preferences.Managers;
Expand Down Expand Up @@ -48,6 +50,9 @@ public sealed class ConnectionManager : IConnectionManager
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly ILogManager _logManager = default!;

//frontier
[Dependency] private readonly MiniAuthManager _authManager = default!;

private readonly Dictionary<NetUserId, TimeSpan> _temporaryBypasses = [];
private ISawmill _sawmill = default!;

Expand Down Expand Up @@ -228,6 +233,21 @@ private async Task NetMgrOnConnecting(NetConnectingArgs e)
}
}

//Frontier
//This is our little chunk that serves as a dAuth. It takes in a comma seperated list of IP:PORT, and chekcs
//the requesting player against the list of players logged in to other servers. It is intended to be failsafe.
//In the case of Admins, it shares the same bypass setting as the soft_max_player_limit
if (!_cfg.GetCVar(CCVars.AllowMultiConnect) && !adminBypass)
{
var serverListString = _cfg.GetCVar(CCVars.ServerAuthList);
var serverList = serverListString.Split(",");
foreach (var server in serverList)
{
if (await _authManager.IsPlayerConnected(server, userId))
return (ConnectionDenyReason.Connected, Loc.GetString("multiauth-already-connected"), null);
}
}
// end Frontier
return null;
}

Expand Down
2 changes: 2 additions & 0 deletions Content.Server/Entry/EntryPoint.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Content.Server._NF.Auth;
using Content.Server.Acz;
using Content.Server.Administration;
using Content.Server.Administration.Logs;
Expand Down Expand Up @@ -103,6 +104,7 @@ public override void Init()
IoCManager.Resolve<GhostKickManager>().Initialize();
IoCManager.Resolve<ServerInfoManager>().Initialize();
IoCManager.Resolve<ServerApi>().Initialize();
IoCManager.Resolve<MiniAuthManager>();

_voteManager.Initialize();
_updateManager.Initialize();
Expand Down
3 changes: 3 additions & 0 deletions Content.Server/IoC/ServerContentIoC.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Content.Server._NF.Auth;
using Content.Server.Administration;
using Content.Server.Administration.Logs;
using Content.Server.Administration.Managers;
Expand Down Expand Up @@ -61,6 +62,8 @@ public static void Register()
IoCManager.Register<ServerDbEntryManager>();
IoCManager.Register<ISharedPlaytimeManager, PlayTimeTrackingManager>();
IoCManager.Register<ServerApi>();
IoCManager.Register<MiniAuthManager>(); //Frontier

}
}
}
88 changes: 88 additions & 0 deletions Content.Server/_NF/Auth/Auth.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Json;
using System.Net.Http.Headers;
using Content.Shared.CCVar;
using Robust.Shared.Configuration;
using JetBrains.Annotations;

namespace Content.Server._NF.Auth;

public sealed class MiniAuthManager
{
[Dependency] private readonly IConfigurationManager _cfg = default!;

private readonly HttpClient _http = new();

/// <summary>
/// Frontier function to ping a server and check to see if the given player is currently connected to the given server.
/// Servers using this function must share an admin_api token as defined in their respective server_config.toml
/// </summary>
/// <param name="address">The address of the server to ping.</param>
/// <param name="player">the GUID of the player to check for connection.</param>
/// <returns>True if the response from the server is successful and the player is connected. False in any case of error, timeout, or failure.</returns>
public async Task<bool> IsPlayerConnected(string address, Guid player)
{
var connected = false;
var statusAddress = "http://" + address + "/admin/info";

var cancel = new CancellationToken();
var linkedToken = CancellationTokenSource.CreateLinkedTokenSource(cancel);
linkedToken.CancelAfter(TimeSpan.FromSeconds(10));

_http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SS14Token", _cfg.GetCVar(CCVars.AdminApiToken));

//We need to do a try catch here because theres essentially no way to guarantee our json response is proper.
//Throughout all of this, we want it to fail to deny, not fail to allow, so if any step of our auth goes wrong,
//people can still connect.
try
{
var status = await _http.GetFromJsonAsync<InfoResponse>(statusAddress, linkedToken.Token);

foreach (var connectedPlayer in status!.Players)
{
if (connectedPlayer.UserId == player)
{
connected = true;
break;
}
}
}
catch (Exception e)
{
}
return connected;
}

/// <summary>
/// Record used to send the response for the info endpoint.
/// Frontier - This is a direct copy of ServerAPI.InfoResponse to match the json format. they kept it private so i just copied it
/// </summary>
[UsedImplicitly]
private sealed record InfoResponse
{
public required int RoundId { get; init; }
public required List<Player> Players { get; init; }
public required List<string> GameRules { get; init; }
public required string? GamePreset { get; init; }
public required MapInfo? Map { get; init; }
public required string? MOTD { get; init; }
public required Dictionary<string, object> PanicBunker { get; init; }

public sealed class Player
{
public required Guid UserId { get; init; }
public required string Name { get; init; }
public required bool IsAdmin { get; init; }
public required bool IsDeadminned { get; init; }
}

public sealed class MapInfo
{
public required string Id { get; init; }
public required string Name { get; init; }
}
}
}
5 changes: 5 additions & 0 deletions Content.Shared/CCVar/CCVars.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2045,6 +2045,11 @@ public static readonly CVarDef<float>
public static readonly CVarDef<string> TippyEntity =
CVarDef.Create("tippy.entity", "TippyClippy", CVar.SERVER | CVar.REPLICATED); // Frontier - Tippy<TippyClippy

public static readonly CVarDef<string> ServerAuthList =
CVarDef.Create("frontier.auth_servers", "", CVar.CONFIDENTIAL | CVar.SERVERONLY);

public static readonly CVarDef<bool> AllowMultiConnect =
CVarDef.Create("frontier.allow_multi_connect", true, CVar.CONFIDENTIAL | CVar.SERVERONLY);
/*
* DEBUG
*/
Expand Down
8 changes: 7 additions & 1 deletion Content.Shared/Chat/SharedChatSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -152,10 +152,16 @@ public string SanitizeMessageCapital(string message)
if (string.IsNullOrEmpty(message))
return message;
// Capitalize first letter
message = char.ToUpper(message[0]) + message.Remove(0, 1);
message = OopsConcat(char.ToUpper(message[0]).ToString(), message.Remove(0, 1));
return message;
}

private static string OopsConcat(string a, string b)
{
// This exists to prevent Roslyn being clever and compiling something that fails sandbox checks.
return a + b;
}

public string SanitizeMessageCapitalizeTheWordI(string message, string theWordI = "i")
{
if (string.IsNullOrEmpty(message))
Expand Down
1 change: 1 addition & 0 deletions Resources/Locale/en-US/_NF/adventure/adventure.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ shipyard-rules-default2 =
shuttle-ftl-proximity = Nearby objects too massive for FTL!
changelog-tab-title-Upstream = Upstream Changelog
multiauth-already-connected = Already connected to Frontier Official servers.
public-transit-departure = Now departing for {$destination}. Estimated travel time: {$flytime} seconds.
public-transit-arrival = Thank you for choosing NT Public Transit. Next transfer to {$destination} departs in {$waittime} seconds.

0 comments on commit 652b8e9

Please sign in to comment.