From 0840a29ff3cd9b2ab94d37456b64b4a55bfaf276 Mon Sep 17 00:00:00 2001 From: Joonas Rikkonen Date: Sun, 3 Dec 2017 22:54:28 +0200 Subject: [PATCH] Started overhauling the client permission system to make it a bit more flexible. Now the clients can have the permission to use specific console commands (atm these commands are relayed to the server as-is). TODO: make it possible to give clients console command permissions via the menus and the console, save command permissions, deal with commands that don't work as intended when simply relayed to the server and executed server-side, add "ranks" (preconfigured or custom sets of permissions, e.g. moderator, admin, etc). --- .../BarotraumaClient/Source/DebugConsole.cs | 2 +- .../Source/Networking/GameClient.cs | 43 +++++++++++++++++-- .../BarotraumaShared/Source/DebugConsole.cs | 23 +++++++--- .../Source/Networking/Client.cs | 5 ++- .../Source/Networking/GameServer.cs | 12 ++++++ .../Source/Networking/GameServerSettings.cs | 8 +++- 6 files changed, 80 insertions(+), 13 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Source/DebugConsole.cs b/Barotrauma/BarotraumaClient/Source/DebugConsole.cs index 0283ec3d6..626969eb5 100644 --- a/Barotrauma/BarotraumaClient/Source/DebugConsole.cs +++ b/Barotrauma/BarotraumaClient/Source/DebugConsole.cs @@ -134,7 +134,7 @@ namespace Barotrauma case "entitylist": return true; default: - return false; + return client.HasConsoleCommandPermission(command); } } diff --git a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs index aafe2d4ac..0acf9b10e 100644 --- a/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs +++ b/Barotrauma/BarotraumaClient/Source/Networking/GameClient.cs @@ -19,6 +19,7 @@ namespace Barotrauma.Networking private GUITickBox endVoteTickBox; private ClientPermissions permissions = ClientPermissions.None; + private List permittedConsoleCommands = new List(); private bool connected; @@ -596,14 +597,24 @@ namespace Barotrauma.Networking private void ReadPermissions(NetIncomingMessage inc) { + List permittedConsoleCommands = new List(); ClientPermissions newPermissions = (ClientPermissions)inc.ReadByte(); + if (newPermissions.HasFlag(ClientPermissions.ConsoleCommands)) + { + UInt16 consoleCommandCount = inc.ReadUInt16(); + for (int i = 0; i < consoleCommandCount; i++) + { + permittedConsoleCommands.Add(inc.ReadString()); + } + } + if (newPermissions != permissions) { - SetPermissions(newPermissions); + SetPermissions(newPermissions, permittedConsoleCommands); } } - private void SetPermissions(ClientPermissions newPermissions) + private void SetPermissions(ClientPermissions newPermissions, List permittedConsoleCommands) { if (newPermissions == permissions) return; GUIMessageBox.MessageBoxes.RemoveAll(mb => mb.UserData as string == "permissions"); @@ -623,6 +634,8 @@ namespace Barotrauma.Networking DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); msg += " - " + attributes[0].Description + "\n"; } + + //TODO: display permitted console commands } permissions = newPermissions; new GUIMessageBox("Permissions changed", msg).UserData = "permissions"; @@ -800,7 +813,7 @@ namespace Barotrauma.Networking gameStarted = inc.ReadBoolean(); bool allowSpectating = inc.ReadBoolean(); - SetPermissions((ClientPermissions)inc.ReadByte()); + ReadPermissions(inc); if (gameStarted) { @@ -1161,6 +1174,14 @@ namespace Barotrauma.Networking return permissions.HasFlag(permission); } + public bool HasConsoleCommandPermission(string command) + { + if (!permissions.HasFlag(ClientPermissions.ConsoleCommands)) return false; + + command = command.ToLowerInvariant(); + return permittedConsoleCommands.Any(c => c.ToLowerInvariant() == command); + } + public override void Draw(Microsoft.Xna.Framework.Graphics.SpriteBatch spriteBatch) { base.Draw(spriteBatch); @@ -1351,6 +1372,22 @@ namespace Barotrauma.Networking client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered); } + public void SendConsoleCommand(string command) + { + if (string.IsNullOrWhiteSpace(command)) + { + DebugConsole.ThrowError("Cannot send an empty console command to the server!\n" + Environment.StackTrace); + return; + } + + NetOutgoingMessage msg = client.CreateMessage(); + msg.Write((byte)ClientPacketHeader.SERVER_COMMAND); + msg.Write((byte)ClientPermissions.ConsoleCommands); + msg.Write(command); + + client.SendMessage(msg, NetDeliveryMethod.ReliableUnordered); + } + /// /// Tell the server to select a submarine (permission required) /// diff --git a/Barotrauma/BarotraumaShared/Source/DebugConsole.cs b/Barotrauma/BarotraumaShared/Source/DebugConsole.cs index 7c237cb9d..6c9f0105c 100644 --- a/Barotrauma/BarotraumaShared/Source/DebugConsole.cs +++ b/Barotrauma/BarotraumaShared/Source/DebugConsole.cs @@ -27,12 +27,14 @@ namespace Barotrauma static partial class DebugConsole { - class Command + public class Command { public readonly string[] names; public readonly string help; private Action onExecute; + private bool relayToServer; + public Command(string name, string help, Action onExecute) { names = name.Split('|'); @@ -40,7 +42,7 @@ namespace Barotrauma this.onExecute = onExecute; } - + public void Execute(string[] args) { onExecute(args); @@ -967,10 +969,19 @@ namespace Barotrauma } #if !DEBUG && CLIENT - if (GameMain.Client != null && !IsCommandPermitted(splitCommand[0].ToLowerInvariant(), GameMain.Client)) + if (GameMain.Client != null) { - ThrowError("You're not permitted to use the command \"" + splitCommand[0].ToLowerInvariant() + "\"!"); - return; + if (GameMain.Client.HasConsoleCommandPermission(splitCommand[0].ToLowerInvariant())) + { + GameMain.Client.SendConsoleCommand(command); + NewMessage("Server command: "+command, Color.White); + return; + } + if (!IsCommandPermitted(splitCommand[0].ToLowerInvariant(), GameMain.Client)) + { + ThrowError("You're not permitted to use the command \"" + splitCommand[0].ToLowerInvariant() + "\"!"); + return; + } } #endif @@ -987,7 +998,7 @@ namespace Barotrauma if (!commandFound) { - ThrowError("Command \""+splitCommand[0]+"\" not found."); + ThrowError("Command \"" + splitCommand[0] + "\" not found."); } } diff --git a/Barotrauma/BarotraumaShared/Source/Networking/Client.cs b/Barotrauma/BarotraumaShared/Source/Networking/Client.cs index 5a0caf60e..9497ddd10 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/Client.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/Client.cs @@ -21,7 +21,9 @@ namespace Barotrauma.Networking [Description("Select game mode")] SelectMode = 16, [Description("Manage campaign")] - ManageCampaign = 32 + ManageCampaign = 32, + [Description("Console commands")] + ConsoleCommands = 64 } class Client @@ -79,6 +81,7 @@ namespace Barotrauma.Networking public float DeleteDisconnectedTimer; public ClientPermissions Permissions = ClientPermissions.None; + public List PermittedConsoleCommands = new List(); public bool SpectateOnly; diff --git a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs index e62b9a155..5248ddf13 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs @@ -1928,6 +1928,18 @@ namespace Barotrauma.Networking var msg = server.CreateMessage(); msg.Write((byte)ServerPacketHeader.PERMISSIONS); msg.Write((byte)client.Permissions); + if (client.Permissions.HasFlag(ClientPermissions.ConsoleCommands)) + { + msg.Write((UInt16)client.PermittedConsoleCommands.Sum(c => c.names.Length)); + foreach (DebugConsole.Command command in client.PermittedConsoleCommands) + { + foreach (string commandName in command.names) + { + msg.Write(commandName); + } + } + } + server.SendMessage(msg, client.Connection, NetDeliveryMethod.ReliableUnordered); SaveClientPermissions(); diff --git a/Barotrauma/BarotraumaShared/Source/Networking/GameServerSettings.cs b/Barotrauma/BarotraumaShared/Source/Networking/GameServerSettings.cs index 9034eb514..44558c72c 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/GameServerSettings.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/GameServerSettings.cs @@ -316,6 +316,8 @@ namespace Barotrauma.Networking public void LoadClientPermissions() { + //TODO: load console command permissions + if (!File.Exists(ClientPermissionsFile)) return; string[] lines; @@ -348,13 +350,15 @@ namespace Barotrauma.Networking public void SaveClientPermissions() { - GameServer.Log("Saving client permissions", ServerLog.MessageType.ServerMessage); + //TODO: save console command permissions + + Log("Saving client permissions", ServerLog.MessageType.ServerMessage); List lines = new List(); foreach (SavedClientPermission clientPermission in clientPermissions) { - lines.Add(clientPermission.Name + "|" + clientPermission.IP+"|"+clientPermission.Permissions.ToString()); + lines.Add(clientPermission.Name + "|" + clientPermission.IP + "|" + clientPermission.Permissions.ToString()); } try