Estoy intentando usar C# como lenguaje de scripting usando CSharpCodeProvider (usando VS2010 y .NET 4.0). Quiero que los scripts se ejecuten en un AppDomain restringido con permisos mínimos. Actualmente, recibo una excepción al intentar crear una instancia de una clase en el Dominio de la aplicación (La llamada al CreateInstanceAndUnwrap()). Aquí hay un código simplificado que reproduce la excepción:SecurityException en Sandboxed AppDomain
using System;
using System.Collections.Generic;
using Microsoft.CSharp;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Security;
using System.Security.Policy;
using System.Security.Permissions;
using System.Reflection;
using System.Runtime.Remoting;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
// set permissions
PermissionSet permissions = new PermissionSet(PermissionState.None);
permissions.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
AppDomainSetup adSetup = new AppDomainSetup();
adSetup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
//Create a list of fully trusted assemblies
Assembly[] asms = AppDomain.CurrentDomain.GetAssemblies();
List<StrongName> sns = new List<StrongName>();
for (int x = 0; x < asms.Length; x++)
{
StrongName sn = asms[x].Evidence.GetHostEvidence<StrongName>();
if (sn != null && sns.Contains(sn) == false)
sns.Add(sn);
}
//this includes: "mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
AppDomain domain = AppDomain.CreateDomain("NewAppDomain", AppDomain.CurrentDomain.Evidence, adSetup, permissions);//, sns);//, sn4, sn, sn2, sn3);
try
{
String asmName = Assembly.GetExecutingAssembly().FullName;
String typeName = typeof(ConsoleApp.ScriptRunner).FullName;
//Throws exception here
ScriptRunner scriptRunner = domain.CreateInstanceAndUnwrap(asmName, typeName) as ScriptRunner;
}
catch (SecurityException se)
{
System.Diagnostics.Debug.WriteLine(se.Message);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
}
public class ScriptRunner : MarshalByRefObject
{
public ScriptRunner()
{
//A breakpoint placed here is never reached.
CompilerParameters param;
param = new CompilerParameters();
param.CompilerOptions = "";
param.GenerateExecutable = false;
param.GenerateInMemory = true;
param.IncludeDebugInformation = false;
// C# compiler
CSharpCodeProvider codeProvider = new CSharpCodeProvider();
CompilerResults results = codeProvider.CompileAssemblyFromFile(param, "Danger.cs");
}
}
}
La excepción está siendo lanzada desde mscorlib y es un System.Reflection.TargetInvocationException que tiene un interior System.Security.SecurityException. Aquí está la excepción:
System.Reflection.TargetInvocationException was unhandled
Message=Exception has been thrown by the target of an invocation.
Source=mscorlib
StackTrace:
at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck)
at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache)
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache)
at System.Activator.CreateInstance(Type type, Boolean nonPublic)
at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
at System.Activator.CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes)
at System.Activator.CreateInstance(String assemblyName, String typeName, Boolean ignoreCase, BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object[] activationAttributes, Evidence securityInfo, StackCrawlMark& stackMark)
at System.Activator.CreateInstance(String assemblyName, String typeName)
at System.AppDomain.CreateInstance(String assemblyName, String typeName)
at System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName)
at System.AppDomain.CreateInstanceAndUnwrap(String assemblyName, String typeName)
at ConsoleApp.Program.Main(String[] args) in C:\Documents and Settings\NaultyCS\my documents\visual studio 2010\Projects\ConsoleApplication4\ConsoleApplication4\Program.cs:line 46
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException: System.Security.SecurityException
Message=Request failed.
Source=ConsoleApplication4
GrantedSet=<PermissionSet class="System.Security.PermissionSet"
version="1">
<IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
version="1"
Flags="Execution"/>
</PermissionSet>
PermissionState=<PermissionSet class="System.Security.PermissionSet"
version="1"
Unrestricted="true"/>
RefusedSet=""
Url=file:///C:/Documents and Settings/NaultyCS/my documents/visual studio 2010/Projects/ConsoleApplication4/ConsoleApplication4/bin/Debug/ConsoleApplication4.EXE
StackTrace:
at ConsoleApp.ScriptRunner..ctor()
InnerException:
Me parece que mscorlib exige plena confianza. Lo he agregado como un ensamblado totalmente confiable, pero no tiene ningún efecto. El código anterior funciona si fijo a los permisos sin restricciones:
PermissionSet permissions = new PermissionSet(PermissionState.Unrestricted);
Pero quiero para restringir el dominio de aplicación. ¿Qué estoy haciendo mal aquí?
No, el código funciona bien si fijo el conjunto de permisos a restricciones. Olvidé mencionar eso, así que actualicé la pregunta. El problema es un problema de permisos de seguridad. La excepción de seguridad ocurre primero en mscorlib. A medida que la excepción sube la pila genera una TargetInvocationException. Pero la SecurityException es el problema real. – Galen
Cambié la respuesta en función de las ediciones de la pregunta y el comentario anterior. – Simon
Si agrego lo anterior, sigo recibiendo la misma SecurityException. – Galen