diff --git a/Application/ApplicationManager.cs b/Application/ApplicationManager.cs index 4bea9731e..21e3b9489 100644 --- a/Application/ApplicationManager.cs +++ b/Application/ApplicationManager.cs @@ -22,6 +22,7 @@ using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; +using static SharedLibraryCore.GameEvent; namespace IW4MAdmin.Application { @@ -32,8 +33,6 @@ namespace IW4MAdmin.Application public ILogger Logger => GetLogger(0); public bool Running { get; private set; } public bool IsInitialized { get; private set; } - // define what the delagate function looks like - public delegate void OnServerEventEventHandler(object sender, GameEventArgs e); // expose the event handler so we can execute the events public OnServerEventEventHandler OnServerEvent { get; set; } public DateTime StartTime { get; private set; } diff --git a/Plugins/AutomessageFeed/AutomessageFeed.csproj b/Plugins/AutomessageFeed/AutomessageFeed.csproj index b4eab9727..86211ef43 100644 --- a/Plugins/AutomessageFeed/AutomessageFeed.csproj +++ b/Plugins/AutomessageFeed/AutomessageFeed.csproj @@ -3,6 +3,7 @@ netcoreapp3.0 true + true 7.1 Debug;Release;Prerelease diff --git a/Plugins/ScriptPlugins/SharedGUIDKick.js b/Plugins/ScriptPlugins/SharedGUIDKick.js index 4fd7a0974..77f4827f5 100644 --- a/Plugins/ScriptPlugins/SharedGUIDKick.js +++ b/Plugins/ScriptPlugins/SharedGUIDKick.js @@ -19,6 +19,10 @@ var plugin = { gameEvent.Origin.NetworkId === -6492697076432899192 || gameEvent.Origin.NetworkId === 1145760003260769995 || gameEvent.Origin.NetworkId === -7102887284306116957 || + gameEvent.Origin.NetworkId === 3474936520447289592 || + gameEvent.Origin.NetworkId === -1168897558496584395 || + gameEvent.Origin.NetworkId === 8348020621355817691 || + gameEvent.Origin.NetworkId === 3259219574061214058 || gameEvent.Origin.NetworkId === 3304388024725980231) { gameEvent.Origin.Kick('Your GUID is generic. Delete players/guids.dat and rejoin', _IW4MAdminClient); } diff --git a/RunPublishPre.cmd b/RunPublishPre.cmd index f046f5a50..a6ee9f45a 100644 --- a/RunPublishPre.cmd +++ b/RunPublishPre.cmd @@ -1,6 +1,6 @@ -dotnet publish WebfrontCore/WebfrontCore.csproj -c Prerelease -o X:\IW4MAdmin\Publish\WindowsPrerelease /p:PublishProfile=Prerelease -dotnet publish Application/Application.csproj -c Prerelease -o X:\IW4MAdmin\Publish\WindowsPrerelease /p:PublishProfile=Prerelease -dotnet publish GameLogServer/GameLogServer.pyproj -c Release -o X:\IW4MAdmin\Publish\WindowsPrerelease\GameLogServer +dotnet publish WebfrontCore/WebfrontCore.csproj -c Prerelease -f netcoreapp2.2 --force -o X:\IW4MAdmin\Publish\WindowsPrerelease /p:PublishProfile=Prerelease +dotnet publish Application/Application.csproj -c Prerelease -f netcoreapp2.2 --force -o X:\IW4MAdmin\Publish\WindowsPrerelease /p:PublishProfile=Prerelease +dotnet publish GameLogServer/GameLogServer.pyproj -c Release -f netcoreapp2.2 --force -o X:\IW4MAdmin\Publish\WindowsPrerelease\GameLogServer call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\Tools\VsDevCmd.bat" msbuild GameLogServer/GameLogServer.pyproj /p:PublishProfile=PreRelease /p:DeployOnBuild=true /p:PublishProfileRootFolder=X:\IW4MAdmin\GameLogServer\ cd "X:\IW4MAdmin\DEPLOY\" diff --git a/SharedLibraryCore/Events/GameEvent.cs b/SharedLibraryCore/Events/GameEvent.cs index 309a8483d..ff9d6d75c 100644 --- a/SharedLibraryCore/Events/GameEvent.cs +++ b/SharedLibraryCore/Events/GameEvent.cs @@ -1,4 +1,5 @@ using SharedLibraryCore.Database.Models; +using SharedLibraryCore.Events; using System; using System.Threading; using System.Threading.Tasks; @@ -7,6 +8,9 @@ namespace SharedLibraryCore { public class GameEvent { + // define what the delagate function looks like + public delegate void OnServerEventEventHandler(object sender, GameEventArgs e); + public enum EventFailReason { /// diff --git a/SharedLibraryCore/Interfaces/IManager.cs b/SharedLibraryCore/Interfaces/IManager.cs index fd62a0a5f..8d48b72f5 100644 --- a/SharedLibraryCore/Interfaces/IManager.cs +++ b/SharedLibraryCore/Interfaces/IManager.cs @@ -6,6 +6,7 @@ using System.Reflection; using SharedLibraryCore.Database.Models; using System.Threading; using System.Collections; +using static SharedLibraryCore.GameEvent; namespace SharedLibraryCore.Interfaces { @@ -54,5 +55,6 @@ namespace SharedLibraryCore.Interfaces string ExternalIPAddress { get; } CancellationToken CancellationToken { get; } bool IsRestartRequested { get; } + OnServerEventEventHandler OnServerEvent { get; set; } } } diff --git a/WebfrontCore/Middleware/ClaimsPermissionRemoval.cs b/WebfrontCore/Middleware/ClaimsPermissionRemoval.cs new file mode 100644 index 000000000..5a99d3556 --- /dev/null +++ b/WebfrontCore/Middleware/ClaimsPermissionRemoval.cs @@ -0,0 +1,91 @@ +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Http; +using SharedLibraryCore.Events; +using SharedLibraryCore.Interfaces; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using static SharedLibraryCore.Database.Models.EFClient; +using static SharedLibraryCore.GameEvent; + +namespace WebfrontCore.Middleware +{ + /// + /// Facilitates the removal of identity claims when client is demoted + /// + internal class ClaimsPermissionRemoval + { + private readonly IManager _manager; + private readonly List _privilegedClientIds; + private readonly RequestDelegate _nextRequest; + + public ClaimsPermissionRemoval(RequestDelegate nextRequest, IManager manager) + { + _manager = manager; + _manager.OnServerEvent += OnGameEvent; + _privilegedClientIds = new List(); + _nextRequest = nextRequest; + } + + /// + /// Callback for the game event + /// + /// + /// + private void OnGameEvent(object sender, GameEventArgs args) + { + if (args.Event.Type == EventType.ChangePermission && + args.Event.Extra is Permission perm) + { + // we want to remove the claims when the client is demoted + if (perm < Permission.Trusted) + { + lock (_privilegedClientIds) + { + _privilegedClientIds.RemoveAll(id => id == args.Event.Target.ClientId); + } + } + // and add if promoted + else if (perm > Permission.Trusted && + !_privilegedClientIds.Contains(args.Event.Target.ClientId)) + { + lock (_privilegedClientIds) + { + _privilegedClientIds.Add(args.Event.Target.ClientId); + } + } + } + } + + public async Task Invoke(HttpContext context) + { + // we want to load the initial list of privileged clients + if (_privilegedClientIds.Count == 0) + { + var ids = (await _manager.GetClientService().GetPrivilegedClients()) + .Select(_client => _client.ClientId); + + lock (_privilegedClientIds) + { + _privilegedClientIds.AddRange(ids); + } + } + + // sid stores the clientId + string claimsId = context.User.Claims.FirstOrDefault(_claim => _claim.Type == ClaimTypes.Sid)?.Value; + + if (!string.IsNullOrEmpty(claimsId)) + { + int clientId = int.Parse(claimsId); + // they've been removed + if (!_privilegedClientIds.Contains(clientId) && clientId != 1) + { + await context.SignOutAsync(); + } + } + + await _nextRequest.Invoke(context); + } + } +} diff --git a/WebfrontCore/Startup.cs b/WebfrontCore/Startup.cs index b0ec8d816..61eeec9c4 100644 --- a/WebfrontCore/Startup.cs +++ b/WebfrontCore/Startup.cs @@ -112,6 +112,9 @@ namespace WebfrontCore app.UseAuthorization(); app.UseCors("AllowAll"); + // prevents banned/demoted users from keeping their claims + app.UseMiddleware(Program.Manager); + app.UseRouting(); app.UseEndpoints(endpoints => {