From fa921ec147cae620f3126c01b1db94a8f6e90c7e Mon Sep 17 00:00:00 2001 From: Adam Frisby Date: Mon, 17 Aug 2009 02:25:00 +1000 Subject: * Implements AppDomain Security for MRM Scripts. * Added permissionLevel attribute to [MRM] section in OpenSim.ini. Default is 'Internet', however may be any of the following (case sensitive), FullTrust, SkipVerification, Execution, Nothing, LocalIntranet, Internet, Everything. For previous functionality, set to FullTrust or Execution. --- .../Scripting/Minimodule/MRMModule.cs | 103 ++++++++++++++++++++- 1 file changed, 101 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/OptionalModules/Scripting/Minimodule') diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs index 6daae29..9042e0d 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs @@ -27,9 +27,14 @@ using System; using System.CodeDom.Compiler; +using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Reflection; +using System.Security; +using System.Security.Permissions; +using System.Security.Policy; using System.Text; using log4net; using Microsoft.CSharp; @@ -54,6 +59,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule private readonly MicroScheduler m_microthreads = new MicroScheduler(); + + private IConfig m_config; + public void RegisterExtension(T instance) { m_extensions[typeof (T)] = instance; @@ -63,6 +71,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule { if (source.Configs["MRM"] != null) { + m_config = source.Configs["MRM"]; + if (source.Configs["MRM"].GetBoolean("Enabled", false)) { m_log.Info("[MRM] Enabling MRM Module"); @@ -112,6 +122,91 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule return script; } + /// + /// Create an AppDomain that contains policy restricting code to execute + /// with only the permissions granted by a named permission set + /// + /// name of the permission set to restrict to + /// 'friendly' name of the appdomain to be created + /// + /// if is null + /// + /// + /// if is empty + /// + /// AppDomain with a restricted security policy + /// Substantial portions of this function from: http://blogs.msdn.com/shawnfa/archive/2004/10/25/247379.aspx + /// Valid permissionSetName values are: + /// * FullTrust + /// * SkipVerification + /// * Execution + /// * Nothing + /// * LocalIntranet + /// * Internet + /// * Everything + /// + public static AppDomain CreateRestrictedDomain(string permissionSetName, string appDomainName) + { + if (permissionSetName == null) + throw new ArgumentNullException("permissionSetName"); + if (permissionSetName.Length == 0) + throw new ArgumentOutOfRangeException("permissionSetName", permissionSetName, + "Cannot have an empty permission set name"); + + // Default to all code getting nothing + PolicyStatement emptyPolicy = new PolicyStatement(new PermissionSet(PermissionState.None)); + UnionCodeGroup policyRoot = new UnionCodeGroup(new AllMembershipCondition(), emptyPolicy); + + bool foundName = false; + PermissionSet setIntersection = new PermissionSet(PermissionState.Unrestricted); + + // iterate over each policy level + IEnumerator levelEnumerator = SecurityManager.PolicyHierarchy(); + while (levelEnumerator.MoveNext()) + { + PolicyLevel level = levelEnumerator.Current as PolicyLevel; + + // if this level has defined a named permission set with the + // given name, then intersect it with what we've retrieved + // from all the previous levels + if (level != null) + { + PermissionSet levelSet = level.GetNamedPermissionSet(permissionSetName); + if (levelSet != null) + { + foundName = true; + if (setIntersection != null) + setIntersection = setIntersection.Intersect(levelSet); + } + } + } + + // Intersect() can return null for an empty set, so convert that + // to an empty set object. Also return an empty set if we didn't find + // the named permission set we were looking for + if (setIntersection == null || !foundName) + setIntersection = new PermissionSet(PermissionState.None); + else + setIntersection = new NamedPermissionSet(permissionSetName, setIntersection); + + // if no named permission sets were found, return an empty set, + // otherwise return the set that was found + PolicyStatement permissions = new PolicyStatement(setIntersection); + policyRoot.AddChild(new UnionCodeGroup(new AllMembershipCondition(), permissions)); + + // create an AppDomain policy level for the policy tree + PolicyLevel appDomainLevel = PolicyLevel.CreateAppDomainLevel(); + appDomainLevel.RootCodeGroup = policyRoot; + + // create an AppDomain where this policy will be in effect + string domainName = appDomainName; + AppDomain restrictedDomain = AppDomain.CreateDomain(domainName); + restrictedDomain.SetAppDomainPolicy(appDomainLevel); + + return restrictedDomain; + } + + void EventManager_OnRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource) { if (script.StartsWith("//MRM:C#")) @@ -125,9 +220,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule try { - m_log.Info("[MRM] Found C# MRM"); + m_log.Info("[MRM] Found C# MRM - Starting in AppDomain with " + m_config.GetString("permissionLevel", "Internet") + "-level security."); + + string domainName = UUID.Random().ToString(); + AppDomain target = CreateRestrictedDomain(m_config.GetString("permissionLevel", "Internet"), + domainName); - MRMBase mmb = (MRMBase)AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap( + MRMBase mmb = (MRMBase) target.CreateInstanceFromAndUnwrap( CompileFromDotNetText(script, itemID.ToString()), "OpenSim.MiniModule"); -- cgit v1.1 From 58d2775ff29c1a4faa26302515c7a6cbd8bdb764 Mon Sep 17 00:00:00 2001 From: Jeff Ames Date: Mon, 17 Aug 2009 02:05:12 +0900 Subject: Add copyright header. Formatting cleanup. --- .../Minimodule/Interfaces/IAvatarAttachment.cs | 27 ++++++++++++++++++++++ .../Scripting/Minimodule/SOPObject.cs | 4 ++-- 2 files changed, 29 insertions(+), 2 deletions(-) (limited to 'OpenSim/Region/OptionalModules/Scripting/Minimodule') diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/Interfaces/IAvatarAttachment.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/Interfaces/IAvatarAttachment.cs index 22b4605..1993948 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/Interfaces/IAvatarAttachment.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/Interfaces/IAvatarAttachment.cs @@ -1,3 +1,30 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + namespace OpenSim.Region.OptionalModules.Scripting.Minimodule { public interface IAvatarAttachment diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs index 35b0a0f..292e345 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs @@ -71,7 +71,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule private bool CanEdit() { - if(!m_security.CanEditObject(this)) + if (!m_security.CanEditObject(this)) { throw new SecurityException("Insufficient Permission to edit object with UUID [" + GetSOP().UUID + "]"); } @@ -672,7 +672,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule get { return m_sculptType; } set { - if(!CanEdit()) + if (!CanEdit()) return; m_sculptType = value; -- cgit v1.1