2011-11-22 14 views
5

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í?

Respuesta

2

Perdón por la edición tardía. Prueba lo siguiente. Lo preparé y ejecuté en Visual Studio con una aplicación de prueba. En una nota lateral, personalmente no me gusta la "lógica" en los constructores porque el verdadero error tiende a ocultarse un poco. Los pasos a continuación tienen la lógica de compilación movida desde el constructor a un nuevo método.

  1. Asegúrese de que su aplicación de consola tenga un StrongName/Signed.
  2. Incluye la variable sns como el último parámetro para llamar a AppDomain.CreateDomain. El permiso de LinkDemand requiere que ConsoleApp sea totalmente confiable.

    AppDomain domain = AppDomain.CreateDomain("NewAppDomain", AppDomain.CurrentDomain.Evidence, adSetup, permissions, sns.ToArray()); 
    
  3. Cambie el asmName para usar la ruta completa del archivo a su ensamblaje.

    String asmName = Assembly.GetExecutingAssembly().ManifestModule.FullyQualifiedName; 
    
  4. eliminar la llamada CreateInstanceAndUnwrap a los siguientes 2 líneas de código

    var handle = Activator.CreateInstanceFrom(domain, asmName, typeName); 
    var scriptRunner = (ScriptRunner)handle.Unwrap(); 
    
  5. Mover todo el código del constructor de un nuevo método como "Inicio".

  6. Agregue la línea para llamar al método de Inicio.

    scriptRunner.Start(); 
    
  7. Añadir la FileIOPermission leer el fichero de Danger.cs.

    permissions.AddPermission(new FileIOPermission(PermissionState.None) { AllFiles = FileIOPermissionAccess.Read }); 
    
+0

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

+0

Cambié la respuesta en función de las ediciones de la pregunta y el comentario anterior. – Simon

+0

Si agrego lo anterior, sigo recibiendo la misma SecurityException. – Galen

Cuestiones relacionadas