SgDotNet
Singapore Professional .NET User Group -For Cool Developers

SandBox: CAS

rated by 0 users
This post has 0 Replies | 0 Followers

Top 25 Contributor
Posts 232
Thanh Posted: 11-22-2005 1:49 AM

V2.0 CAS has been improved quite a lot over its predecessor. One of the enhancement is how to build a SandBox using AppDomain to control the access of resources and the loading of assemblies into an isolated sandbox.

Below are codes showing how it is done and requires some understanding of .NET security policy, code group and permission sets.

Interface.cs
namespace AddIn
{
  public interface IAddIn
  {
    void Start();
  }

It's just a simple interface and there is not much to explain here.

AddInManager.cs
using System;
using AddIn;

namespace AssemblyManager

  public class AddInManager : MarshalByRefObject
  {
    public void RunAddIn(Type MyAssembly)
    {
      IAddIn addIn = Activator.CreateInstance(MyAssembly) as IAddIn;
      if(addIn != null)
        addIn.Start(); 
    }
  } 
}

MarshalByRefObject is intended for Remoting. The method RunAddIn receives the type of object which in this case is the type of class declared by your code. In my case, it's the declared class InternetZone or ComputerZone. It then goes on to create the instance of the class as an interface and start the process.

AssemblyTest.cs
using System.IO;
using System.Text;
using System.Reflection;
using System.Security;
using System.Security.Policy;
using System.Security.Permissions;

using AddIn;
using AssemblyManager;

namespace TestingAssembly
{
  public class InternetZone : IAddIn
  {
    public void Start()
    {
      Console.WriteLine("Enter Internet Zone");
      try
      {
        using (Stream S = new FileStream("Test.txt", FileMode.Create))
        {
          Console.WriteLine("Do something to file");
        }
      }
      catch(SecurityException se)
      {
        Console.WriteLine(se.Message);
      }
    }
  } 
 
  public class MyComputerZone : IAddIn
  {
    public void Start()
    {
      Console.WriteLine("Enter MyComputer Zone");
      try
      {
        using (Stream S = new FileStream("Test.txt", FileMode.Create))
        {
          Console.WriteLine("Do something to file");
        }      
      }
      catch(SecurityException se)
      {
        Console.WriteLine(se.Message);
      }
    }
  }
 
  public class SandBox
  {
    public void SandBoxAssembly(Type MyAssembly, SecurityZone ZoneType)
    {
      // Host evidence from which to create the new instance
      Evidence UserEvidence = new Evidence(
      new object[] { new Zone(ZoneType) }, new object[] {}); 
     
      // Determine what permission to grant to code based on the evidence
      PermissionSet UserPermissions = SecurityManager.ResolvePolicy(UserEvidence);
   
      // Create a sandboxed domain
      AppDomainSetup setup = new AppDomainSetup();
      AppDomain SandboxedDomain = AppDomain.CreateDomain(
        "AddInDomain", UserEvidence, setup,
        UserPermissions, new StrongName[] { });
       
      Type AddInManagerType = typeof(AddInManager);
      AddInManager Manager = (AddInManager) SandboxedDomain.CreateInstanceAndUnwrap(
        AddInManagerType.Assembly.FullName, AddInManagerType.FullName);
       
      Manager.RunAddIn(MyAssembly);     
    }
  } 
}

The 2 classes InternetZone and ComputerZone just create a text file using the FileStream class. They both do exactly the same thing here for a reason. The SandBox class however deserves some explanation to see how it works. First, it receives a type of object and the SecurityZone telling the Security Manager where is comes from (MyComputer, Internet, LocalIntranet and ....). Create the evidence using the SecurityZone to determine what resources the code is allowed to access. Create a seperate AppDomain with the specific Evidence and PermissionSets. Notice that I ignore the StrongName policy for simplicity because I don't want to deal with the GAC for this demonstration. The next step is to load the AddInManager into the newly created AppDomain and load the assembly which now runs apart from the Main Domain. This is how you can seperate the loading of dll into different AppDomain so that if it crashes won't affect the main application. I suggest you to read more about AppDomain, Assembly and Security policy to obtain a better understanding how this whole things work.

Client.cs
using System;
using System.Security;
using System.Security.Policy;

using TestingAssembly;
namespace Test
{
  public class TestSandBox
  {  
    public static void Main()
    {   
      SandBox sb = new SandBox();
     
      Type MyAssembly;
     
      MyAssembly = typeof(InternetZone);
      sb.SandBoxAssembly(MyAssembly, SecurityZone.Internet); 
     
      MyAssembly = typeof(MyComputerZone);
      sb.SandBoxAssembly(MyAssembly, SecurityZone.MyComputer);      
    } 
  } 
}     

This is the main application which runs in its own domain. If you compile and run the above code, the InternetZone will fail because the default security policy will not allow anything coning from the InternetZone to manipulate the file system. However, when it detects that it comes from the ComputerZone which is set at FullTrust, the code can access all available resources on the computer.

Compile the whole project as indicated below or using VS 200* if you want.

csc /t:library Interface.cs
csc /r:Interface.dll /t:library AddinManager.cs
csc /r:Interface.dll /r:AddinManager.dll /t:library AssemblyTest.cs
csc /r:Interface.dll /r:AssemblyTest.dll Client.cs

Have fun

Page 1 of 1 (1 items) | RSS
Copyright SgDotNet 2004-2008
Powered by Community Server (Commercial Edition), by Telligent Systems