From 1bdb12c5588e03a453de935078a5074107ac5cb0 Mon Sep 17 00:00:00 2001 From: Jak Daniels Date: Sat, 17 Oct 2015 11:51:10 +0100 Subject: [PATCH] Added basic security. Module can now be limited ton accept commands from ESTATE_OWNER, ESTATE_MANAGER or list of UUIDs --- Module/BirdsModule/FlockingModule.cs | 176 ++++++++++++++++----------- README.md | 11 ++ config/OpenSimBirds.ini.example | 4 + 3 files changed, 122 insertions(+), 69 deletions(-) diff --git a/Module/BirdsModule/FlockingModule.cs b/Module/BirdsModule/FlockingModule.cs index 188f53c..f401c25 100644 --- a/Module/BirdsModule/FlockingModule.cs +++ b/Module/BirdsModule/FlockingModule.cs @@ -59,7 +59,7 @@ namespace Flocking private Scene m_scene; private ICommandConsole m_console; private FlockingModel m_model; - private FlockingView m_view; + private FlockingView m_view; private bool m_startup = true; private bool m_enabled = false; private bool m_ready = false; @@ -77,7 +77,8 @@ namespace Flocking private float m_borderSize; private int m_maxHeight; private Vector3 m_shoutPos = new Vector3(128f, 128f, 30f); - static object m_sync = new object(); + static object m_sync = new object(); + private List m_allowedControllers = new List(); public IConfigSource m_config; @@ -127,54 +128,90 @@ namespace Flocking m_enabled = false; return; } - } - - m_startup = cnf.GetBoolean("BirdsModuleStartup", true); - - if (m_startup) - { - m_enabled = cnf.GetBoolean("BirdsEnabled", false); - m_chatChannel = cnf.GetInt("BirdsChatChannel", 118); - m_birdPrim = cnf.GetString("BirdsPrim", "birdPrim"); - m_flockSize = cnf.GetInt("BirdsFlockSize", 50); - m_maxFlockSize = cnf.GetInt("BirdsMaxFlockSize", 100); - m_maxSpeed = cnf.GetFloat("BirdsMaxSpeed", 3f); - m_maxForce = cnf.GetFloat("BirdsMaxForce", 0.25f); - m_neighbourDistance = cnf.GetFloat("BirdsNeighbourDistance", 25f); - m_desiredSeparation = cnf.GetFloat("BirdsDesiredSeparation", 20f); - m_tolerance = cnf.GetFloat("BirdsTolerance", 5f); - m_borderSize = cnf.GetFloat("BirdsRegionBorderSize", 5f); - m_maxHeight = cnf.GetInt("BirdsMaxHeight", 256); - m_frameUpdateRate = cnf.GetInt("BirdsUpdateEveryNFrames", 1); - - m_log.InfoFormat("[{0}] Module is {1} listening for commands on channel {2} with Flock Size {3}", m_name, m_enabled?"enabled and":"disabled, but", m_chatChannel, m_flockSize); - - m_scene = scene; - m_console = MainConsole.Instance; - - //register commands with the scene - RegisterCommands(); - - //register handlers - m_scene.EventManager.OnFrame += FlockUpdate; - m_scene.EventManager.OnChatFromClient += SimChatSent; //listen for commands sent from the client - m_scene.EventManager.OnChatFromWorld += SimChatSent; - m_scene.EventManager.OnPrimsLoaded += PrimsLoaded; - - // init module - m_model = new FlockingModel(m_name, m_maxSpeed, m_maxForce, m_neighbourDistance, m_desiredSeparation, m_tolerance, m_borderSize); - m_view = new FlockingView(m_name, m_scene); - m_view.BirdPrim = m_birdPrim; - m_frame = 0; - m_shoutPos = new Vector3(scene.RegionInfo.RegionSizeX / 2f, scene.RegionInfo.RegionSizeY / 2f, 30f); - - FlockInitialise(); - } + + m_startup = cnf.GetBoolean("BirdsModuleStartup", true); + + if (m_startup) + { + m_scene = scene; + m_enabled = cnf.GetBoolean("BirdsEnabled", false); + m_chatChannel = cnf.GetInt("BirdsChatChannel", 118); + m_birdPrim = cnf.GetString("BirdsPrim", "birdPrim"); + m_flockSize = cnf.GetInt("BirdsFlockSize", 20); + m_maxFlockSize = cnf.GetInt("BirdsMaxFlockSize", 100); + m_maxSpeed = cnf.GetFloat("BirdsMaxSpeed", 1.5f); + m_maxForce = cnf.GetFloat("BirdsMaxForce", 0.2f); + m_neighbourDistance = cnf.GetFloat("BirdsNeighbourDistance", 25f); + m_desiredSeparation = cnf.GetFloat("BirdsDesiredSeparation", 10f); + m_tolerance = cnf.GetFloat("BirdsTolerance", 5f); + m_borderSize = cnf.GetFloat("BirdsRegionBorderSize", 5f); + m_maxHeight = cnf.GetInt("BirdsMaxHeight", 75); + m_frameUpdateRate = cnf.GetInt("BirdsUpdateEveryNFrames", 1); + + string allowedControllers = cnf.GetString("BirdsAllowedControllers", UUID.Zero.ToString()); + if (allowedControllers != UUID.Zero.ToString()) + { + string[] ac = allowedControllers.Split(new char[] { ',' }); + UUID acUUID; + for (int i = 0; i < ac.Length; i++) + { + string value = ac[i].Trim(); + if (value == "ESTATE_OWNER") + { + UUID eoUUID = m_scene.RegionInfo.EstateSettings.EstateOwner; + m_allowedControllers.Add(eoUUID); + m_log.InfoFormat("[{0}] Added Estate Owner UUID: {1} to list of allowed users", m_name, eoUUID.ToString()); + continue; + } + if (value == "ESTATE_MANAGER") + { + foreach (UUID emUUID in m_scene.RegionInfo.EstateSettings.EstateManagers) + { + m_allowedControllers.Add(emUUID); + m_log.InfoFormat("[{0}] Added Estate Manager UUID: {1} to list of allowed users", m_name, emUUID.ToString()); + } + continue; + } + if (UUID.TryParse(ac[i].Trim(), out acUUID)) + { + m_allowedControllers.Add(acUUID); + m_log.InfoFormat("[{0}] Added UUID: {1} to list of allowed users", m_name, acUUID.ToString()); + } + } + } + else + { + m_log.InfoFormat("[{0}] No command security was defined in the config. Any user may possibly configure this module from a script!", m_name); + } + + m_log.InfoFormat("[{0}] Module is {1} listening for commands on channel {2} with Flock Size {3}", m_name, m_enabled ? "enabled and" : "disabled, but still", m_chatChannel, m_flockSize); + + m_console = MainConsole.Instance; + //register commands with the scene + RegisterCommands(); + + //register handlers + m_scene.EventManager.OnFrame += FlockUpdate; + m_scene.EventManager.OnChatFromClient += SimChatSent; //listen for commands sent from the client + m_scene.EventManager.OnChatFromWorld += SimChatSent; + m_scene.EventManager.OnPrimsLoaded += PrimsLoaded; + + // init module + m_model = new FlockingModel(m_name, m_maxSpeed, m_maxForce, m_neighbourDistance, m_desiredSeparation, m_tolerance, m_borderSize); + m_view = new FlockingView(m_name, m_scene); + m_view.BirdPrim = m_birdPrim; + m_frame = 0; + m_shoutPos = new Vector3(scene.RegionInfo.RegionSizeX / 2f, scene.RegionInfo.RegionSizeY / 2f, 30f); + + FlockInitialise(); + + } + else m_log.InfoFormat("[{0}] Module is disabled in Region {1}", m_name, scene.RegionInfo.RegionName); } public void RegionLoaded (Scene scene) - { + { if (m_startup) { // Mark Module Ready for duty @@ -190,25 +227,25 @@ namespace Flocking public void RemoveRegion (Scene scene) { - m_log.InfoFormat("[{0}]: Removing region {1} from this module", m_name, scene.RegionInfo.RegionName); + m_log.InfoFormat("[{0}]: Removing region {1} from this module", m_name, scene.RegionInfo.RegionName); if (m_startup) { m_view.Clear(); scene.EventManager.OnFrame -= FlockUpdate; scene.EventManager.OnChatFromClient -= SimChatSent; - scene.EventManager.OnChatFromWorld -= SimChatSent; - scene.EventManager.OnPrimsLoaded -= PrimsLoaded; + scene.EventManager.OnChatFromWorld -= SimChatSent; + scene.EventManager.OnPrimsLoaded -= PrimsLoaded; m_ready = false; } } public void Close() - { + { if (m_startup) { m_scene.EventManager.OnFrame -= FlockUpdate; m_scene.EventManager.OnChatFromClient -= SimChatSent; - m_scene.EventManager.OnChatFromWorld -= SimChatSent; - m_scene.EventManager.OnPrimsLoaded -= PrimsLoaded; + m_scene.EventManager.OnChatFromWorld -= SimChatSent; + m_scene.EventManager.OnPrimsLoaded -= PrimsLoaded; m_ready = false; } } @@ -255,8 +292,8 @@ namespace Flocking #region EventHandlers public void FlockUpdate () - { - if (!m_ready || !m_enabled || ((m_frame++ % m_frameUpdateRate) != 0)) + { + if (!m_ready || !m_enabled || ((m_frame++ % m_frameUpdateRate) != 0)) { return; } @@ -273,8 +310,9 @@ namespace Flocking protected void SimChatSent (Object x, OSChatMessage msg) { - if (msg.Channel != m_chatChannel) - return; // not for us + if (msg.Channel != m_chatChannel) return; // not for us + + if (m_allowedControllers.Count>0 & !m_allowedControllers.Contains(msg.SenderUUID)) return; // not for us // try and parse a valid cmd from this msg string cmd = msg.Message; //.ToLower (); @@ -435,8 +473,8 @@ namespace Flocking } void HandleSetFrameRateCmd (string module, string[] args) - { - if (m_ready && ShouldHandleCmd()) + { + if (m_ready && ShouldHandleCmd()) { int frameRate = Convert.ToInt32( args[1] ); m_frameUpdateRate = frameRate; @@ -445,8 +483,8 @@ namespace Flocking } public void HandleSetSizeCmd (string module, string[] args) - { - if (m_ready && ShouldHandleCmd()) + { + if (m_ready && ShouldHandleCmd()) { lock( m_sync ) { int newSize = Convert.ToInt32(args[1]); @@ -460,8 +498,8 @@ namespace Flocking } public void HandleShowStatsCmd (string module, string[] args) - { - if (m_ready && ShouldHandleCmd()) + { + if (m_ready && ShouldHandleCmd()) { bool inWorld = IsInWorldCmd (ref args); int i; @@ -515,8 +553,8 @@ namespace Flocking } public void HandleSetPrimCmd (string module, string[] args) - { - if (m_ready && ShouldHandleCmd()) + { + if (m_ready && ShouldHandleCmd()) { string primName = args[1]; lock(m_sync) { @@ -528,7 +566,7 @@ namespace Flocking } public void HandleSetMaxSpeedCmd(string module, string[] args) - { + { if (m_ready && ShouldHandleCmd()) { float maxSpeed = (float)Convert.ToDecimal(args[1]); @@ -541,7 +579,7 @@ namespace Flocking } public void HandleSetMaxForceCmd(string module, string[] args) - { + { if (m_ready && ShouldHandleCmd()) { float maxForce = (float)Convert.ToDecimal(args[1]); @@ -554,7 +592,7 @@ namespace Flocking } public void HandleSetNeighbourDistanceCmd(string module, string[] args) - { + { if (m_ready && ShouldHandleCmd()) { float neighbourDistance = (float)Convert.ToDecimal(args[1]); @@ -567,7 +605,7 @@ namespace Flocking } public void HandleSetDesiredSeparationCmd(string module, string[] args) - { + { if (m_ready && ShouldHandleCmd()) { float desiredSeparation = (float)Convert.ToDecimal(args[1]); @@ -580,7 +618,7 @@ namespace Flocking } public void HandleSetToleranceCmd(string module, string[] args) - { + { if (m_ready && ShouldHandleCmd()) { float tolerance = (float)Convert.ToDecimal(args[1]); diff --git a/README.md b/README.md index 7eea31b..d4baca4 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,9 @@ Here is an example config: ;however this can be overridden to the name of an existing prim that ;needs to already exist in the scene - i.e. be rezzed in the region. + ;who is allowed to send commands via chat or script: list of UUIDs or ESTATE_OWNER or ESTATE_MANAGER + ;or everyone if not specified + BirdsAllowedControllers = ESTATE_OWNER, ESTATE_MANAGER, 12345678-1234-1234-1234-123456789abc Various runtime commands control the flocking module behaviour - described below. These can either be invoked @@ -114,6 +117,14 @@ These commands are great for playing with the flock dynamics in real time: Of course if distance is less than separation then the birds will never flock. The other way around and they will always eventually form one or more flocks. +Security: + +By default anyone can send commands to the module from within a script or via the in-world chat on the 'BirdsChatChannel' channel. +You should use a high negative value for channel if you want to allow script access, but not in-world chat. Further you can restrict +which users are allowed to control the module using the 'BirdsAllowedControllers' setting. This is a comma separated list of user UUIDs, +but it may also contain one of the pre-defined constants ESTATE_OWNER (evaluates to the UUID of the estate owner) and ESTATE_MANAGER +(evaluates to a list of estate manager UUIDS). + Bird prims: Any currently rezzed in-scene-object can be used as the bird prim. However fps is very much affected by the diff --git a/config/OpenSimBirds.ini.example b/config/OpenSimBirds.ini.example index 7b53a7e..7ad67f0 100644 --- a/config/OpenSimBirds.ini.example +++ b/config/OpenSimBirds.ini.example @@ -16,3 +16,7 @@ BirdsPrim = SeaGull1 ;By default the module will create a flock of plain wooden spheres, ;however this can be overridden to the name of an existing prim that ;needs to already exist in the scene - i.e. be rezzed in the region. + + ;who is allowed to send commands via chat or script: list of UUIDs or ESTATE_OWNER or ESTATE_MANAGER + ;or everyone if not specified + BirdsAllowedControllers = ESTATE_OWNER, ESTATE_MANAGER, 12345678-1234-1234-1234-123456789abc \ No newline at end of file