From 9f932a42057b4a9cd4517c90007a7c31c98277c6 Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Fri, 5 Jun 2009 09:47:42 +0000
Subject: Thank you, thomax, for a patch to provide finer-grained access
 control to scripting. Fixes Mantis #2862

---
 .../World/Permissions/PermissionsModule.cs         | 69 ++++++++++++++++++++++
 .../Region/Framework/Scenes/Scene.Permissions.cs   | 20 +++++++
 .../ScriptEngine/DotNetEngine/ScriptManager.cs     |  2 +-
 .../Region/ScriptEngine/Interfaces/ICompiler.cs    |  3 +-
 .../ScriptEngine/Shared/CodeTools/Compiler.cs      | 10 +++-
 OpenSim/Region/ScriptEngine/XEngine/XEngine.cs     |  2 +-
 6 files changed, 102 insertions(+), 4 deletions(-)

diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index 6b46176..9298380 100644
--- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
+++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
@@ -87,6 +87,11 @@ namespace OpenSim.Region.CoreModules.World.Permissions
         /// permissions are not being bypassed.  This overrides normal permissions.-
         /// </value>        
         private UserSet m_allowedScriptEditors = UserSet.All;
+        
+        private Dictionary<string, bool> GrantLSL = new Dictionary<string, bool>();
+        private Dictionary<string, bool> GrantCS = new Dictionary<string, bool>();
+        private Dictionary<string, bool> GrantVB = new Dictionary<string, bool>();
+        private Dictionary<string, bool> GrantJS = new Dictionary<string, bool>();
 
         #endregion
 
@@ -143,6 +148,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions
             m_scene.Permissions.OnRezObject += CanRezObject; //MAYBE FULLY IMPLEMENTED
             m_scene.Permissions.OnRunConsoleCommand += CanRunConsoleCommand;
             m_scene.Permissions.OnRunScript += CanRunScript; //NOT YET IMPLEMENTED
+            m_scene.Permissions.OnCompileScript += CanCompileScript;
             m_scene.Permissions.OnSellParcel += CanSellParcel;
             m_scene.Permissions.OnTakeObject += CanTakeObject;
             m_scene.Permissions.OnTakeCopyObject += CanTakeCopyObject;
@@ -184,6 +190,40 @@ namespace OpenSim.Region.CoreModules.World.Permissions
                     "debug permissions <true / false>",
                     "Enable permissions debugging",
                     HandleDebugPermissions);
+                    
+                    
+			string grant = myConfig.GetString("GrantLSL","");
+			if(grant.Length > 0) {
+	            foreach (string uuidl in grant.Split(',')) {
+	                string uuid = uuidl.Trim(" \t".ToCharArray());
+					GrantLSL.Add(uuid, true);
+				}	            
+            }
+
+			grant = myConfig.GetString("GrantCS","");
+			if(grant.Length > 0) {
+	            foreach (string uuidl in grant.Split(',')) {
+	                string uuid = uuidl.Trim(" \t".ToCharArray());
+					GrantCS.Add(uuid, true);
+				}
+            }
+
+			grant = myConfig.GetString("GrantVB","");
+			if(grant.Length > 0) {
+				foreach (string uuidl in grant.Split(',')) {
+	                string uuid = uuidl.Trim(" \t".ToCharArray());
+					GrantVB.Add(uuid, true);
+				}
+            }
+
+			grant = myConfig.GetString("GrantJS","");
+			if(grant.Length > 0) {
+				foreach (string uuidl in grant.Split(',')) {
+	                string uuid = uuidl.Trim(" \t".ToCharArray());
+					GrantJS.Add(uuid, true);
+				}
+            }
+			
         }
 
         public void HandleBypassPermissions(string module, string[] args)
@@ -1584,5 +1624,34 @@ namespace OpenSim.Region.CoreModules.World.Permissions
 
             return GenericParcelPermission(client.AgentId, parcel);
         }
+        
+        private bool CanCompileScript(UUID ownerUUID, int scriptType, Scene scene) {
+     		//m_log.DebugFormat("check if {0} is allowed to compile {1}", ownerUUID, scriptType);
+        	switch(scriptType) {
+        		case 0:
+        			if(GrantLSL.Count == 0 || GrantLSL.ContainsKey(ownerUUID.ToString())) {
+        				return(true);
+					}
+					break;
+				case 1:
+        			if(GrantCS.Count == 0 || GrantCS.ContainsKey(ownerUUID.ToString())) {
+        				return(true);
+					}
+					break;
+				case 2:
+        			if(GrantVB.Count == 0 || GrantVB.ContainsKey(ownerUUID.ToString())) {
+        				return(true);
+					}
+					break;
+				case 3:
+        			if(GrantJS.Count == 0 || GrantJS.ContainsKey(ownerUUID.ToString())) {
+        				return(true);
+					}
+					break;
+			}
+			return(false);
+		}
+					
+        	
     }
 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
index ab5f264..d0da618 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
@@ -56,6 +56,7 @@ namespace OpenSim.Region.Framework.Scenes
     public delegate bool EditScriptHandler(UUID script, UUID objectID, UUID user, Scene scene);
     public delegate bool EditNotecardHandler(UUID notecard, UUID objectID, UUID user, Scene scene);
     public delegate bool RunScriptHandler(UUID script, UUID objectID, UUID user, Scene scene);
+    public delegate bool CompileScriptHandler(UUID ownerUUID, int scriptType, Scene scene);
     public delegate bool StartScriptHandler(UUID script, UUID user, Scene scene);
     public delegate bool StopScriptHandler(UUID script, UUID user, Scene scene);
     public delegate bool ResetScriptHandler(UUID prim, UUID script, UUID user, Scene scene);
@@ -113,6 +114,7 @@ namespace OpenSim.Region.Framework.Scenes
         public event EditScriptHandler OnEditScript;
         public event EditNotecardHandler OnEditNotecard;
         public event RunScriptHandler OnRunScript;
+        public event CompileScriptHandler OnCompileScript;
         public event StartScriptHandler OnStartScript;
         public event StopScriptHandler OnStopScript;
         public event ResetScriptHandler OnResetScript;
@@ -510,6 +512,24 @@ namespace OpenSim.Region.Framework.Scenes
 
         #endregion
 
+        #region COMPILE SCRIPT (When Script needs to get (re)compiled)
+        public bool CanCompileScript(UUID ownerUUID, int scriptType)
+        {
+            CompileScriptHandler handler = OnCompileScript;
+            if (handler != null)
+            {
+                Delegate[] list = handler.GetInvocationList();
+                foreach (CompileScriptHandler h in list)
+                {
+                    if (h(ownerUUID, scriptType, m_scene) == false)
+                        return false;
+                }
+            }
+            return true;
+        }
+
+        #endregion
+
         #region START SCRIPT (When Script run box is Checked after placed in object)
         public bool CanStartScript(UUID script, UUID user)
         {
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs
index 9897267..15d6c2c 100644
--- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs
+++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs
@@ -153,7 +153,7 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine
                 // Compile (We assume LSL)
                 CompiledScriptFile =
                         LSLCompiler.PerformScriptCompile(Script,
-                        assetID.ToString());
+                        assetID.ToString(), taskInventoryItem.OwnerID);
 
                 if (presence != null && (!postOnRez))
                     presence.ControllingClient.SendAgentAlertMessage(
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/ICompiler.cs b/OpenSim/Region/ScriptEngine/Interfaces/ICompiler.cs
index 1bba878..2fd819d 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/ICompiler.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/ICompiler.cs
@@ -27,13 +27,14 @@
 
 using System;
 using System.Collections.Generic;
+using OpenMetaverse;
 using Nini.Config;
 
 namespace OpenSim.Region.ScriptEngine.Interfaces
 {
     public interface ICompiler
     {
-        string PerformScriptCompile(string source, string asset);
+        string PerformScriptCompile(string source, string asset, UUID ownerID);
         string[] GetWarnings();
         Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>
                 LineMap();
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
index fcb3339..911da5b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
@@ -37,6 +37,7 @@ using Microsoft.VisualBasic;
 using log4net;
 using OpenSim.Region.Framework.Interfaces;
 using OpenSim.Region.ScriptEngine.Interfaces;
+using OpenMetaverse;
 
 namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
 {
@@ -263,7 +264,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
         /// </summary>
         /// <param name="Script">LSL script</param>
         /// <returns>Filename to .dll assembly</returns>
-        public string PerformScriptCompile(string Script, string asset)
+        public string PerformScriptCompile(string Script, string asset, UUID ownerUUID)
         {
             m_positionMap = null;
             m_warnings.Clear();
@@ -341,6 +342,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
                 throw new Exception(errtext);
             }
 
+			if(m_scriptEngine.World.Permissions.CanCompileScript(ownerUUID, (int)l) == false) {
+				// Not allowed to compile to this language!
+				string errtext = String.Empty;
+				errtext += ownerUUID + " is not in list of allowed users for this scripting language. Script will not be executed!";
+				throw new Exception(errtext);
+			}
+			
             string compileScript = Script;
 
             if (l == enumCompileType.lsl)
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index cfabda1..34f8145 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -579,7 +579,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
                 lock (m_AddingAssemblies) 
                 {
                     assembly = m_Compiler.PerformScriptCompile(script,
-                                                               assetID.ToString());
+                                                               assetID.ToString(), item.OwnerID);
                     if (!m_AddingAssemblies.ContainsKey(assembly)) {
                         m_AddingAssemblies[assembly] = 1;
                     } else {
-- 
cgit v1.1