* 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.arthursv
parent
cbd454d692
commit
fa921ec147
|
@ -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>(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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an AppDomain that contains policy restricting code to execute
|
||||
/// with only the permissions granted by a named permission set
|
||||
/// </summary>
|
||||
/// <param name="permissionSetName">name of the permission set to restrict to</param>
|
||||
/// <param name="appDomainName">'friendly' name of the appdomain to be created</param>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// if <paramref name="permissionSetName"/> is null
|
||||
/// </exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException">
|
||||
/// if <paramref name="permissionSetName"/> is empty
|
||||
/// </exception>
|
||||
/// <returns>AppDomain with a restricted security policy</returns>
|
||||
/// <remarks>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
|
||||
/// </remarks>
|
||||
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.");
|
||||
|
||||
MRMBase mmb = (MRMBase)AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap(
|
||||
string domainName = UUID.Random().ToString();
|
||||
AppDomain target = CreateRestrictedDomain(m_config.GetString("permissionLevel", "Internet"),
|
||||
domainName);
|
||||
|
||||
MRMBase mmb = (MRMBase) target.CreateInstanceFromAndUnwrap(
|
||||
CompileFromDotNetText(script, itemID.ToString()),
|
||||
"OpenSim.MiniModule");
|
||||
|
||||
|
|
Loading…
Reference in New Issue