Just a quick example:-
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Security.Policy; using System.Security; using System.Security.Permissions; using System.Threading; using System.Reflection; using System.IO; namespace RestrictedAppDomainTest { class Program { /// <summary> /// Example program demonstrating AppDomains with restrictive security /// Note that it requires the existance of C:\windows\win.ini to actually demonstrate it, but you /// can modify this to any other file. /// </summary> /// <param name="args"></param> static void Main(string[] args) { //we want to define a level of access for this appdomain to have PolicyLevel levelOfAccess = PolicyLevel.CreateAppDomainLevel(); //now we grant the permissions to do something specific:- PermissionSet executeOnly = new PermissionSet(PermissionState.None); //bare minimum to run at all executeOnly.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution)); //if you wanted to grant the rights to read files then you need to grant FileIO:- //uncommenting this means that the appdomain created can complete its task rather than erroring //as intended:- // executeOnly.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read, "C:\\Windows\\")); PolicyStatement executeOnlyStatement = new PolicyStatement(executeOnly); UnionCodeGroup applicablePolicy = new UnionCodeGroup(new AllMembershipCondition(), executeOnlyStatement); //and tie the code group we defined to the level of access levelOfAccess.RootCodeGroup = applicablePolicy; //now we could add rights for things we trust, so they can assert that they //want to perform operations that the appdomain normally can't:- /* * This is commented out because it grants the running assembly those rights, but this is an * example of how to do it:- * * After using this, you can use a MessageBox or form from inside the plugin. * * (Change to a using multiple assemblies to restrict each one seperately) * //this example results in the UI being available PermissionSet displayUI = new PermissionSet(PermissionState.None); displayUI.AddPermission(new UIPermission(PermissionState.Unrestricted)); //wrap the permission set in a statement PolicyStatement displayUIPolicyStatement = new PolicyStatement(displayUI); //And only grant this permission when the assembly has been strong named AssemblyName exampleAssembly = Assembly.GetExecutingAssembly().GetName(); UnionCodeGroup selectPolicy = new UnionCodeGroup(new StrongNameMembershipCondition( new StrongNamePublicKeyBlob(exampleAssembly.GetPublicKey() ), exampleAssembly.Name, exampleAssembly.Version ), displayUIPolicyStatement); //and finally we add this new policy to the previous one so there's a chain applicablePolicy.AddChild(selectPolicy); */ //create the appdomain with our basic permission set! AppDomain domain = AppDomain.CreateDomain("RestrictedDomain", null, AppDomain.CurrentDomain.SetupInformation); //do not supply the level permission using this // constructor, you can't change it later using//SetAppDomainPolicy //define the total security policy here domain.SetAppDomainPolicy(levelOfAccess); //now we load our example class from below, for this example we are using the currently executing //assemblies name this can be replaced with another filename, or full assembly name to load a //particular one from the GAC for example string thisAssemblyName = Assembly.GetExecutingAssembly().GetName().Name; IPlugin examplePlugin = (IPlugin)domain.CreateInstanceAndUnwrap(thisAssemblyName, "RestrictedAppDomainTest.ExampleClass"); //this starts running a thread and doing other things that are potentially dodgy. examplePlugin.DoSomething(); //(note that if this didn't choose to start a thread it would still run in a seperate thread anyway) //no (security) exception here, just to show we are unaffected by the appdomai's restrictions! string dummyData = File.ReadAllText("C:\\windows\\win.ini"); Console.WriteLine("An app domain is now started and running in the background."); Console.WriteLine(); Console.WriteLine("Press any key to terminate and unload the restricted appdomain!"); Console.ReadKey(); //This results in the termination of the thread the AppDomain//started, and unloading of //any resources (including locked files or assemblies). AppDomain.Unload(domain); Console.WriteLine("Domain has been unloaded. Press any key to end."); Console.ReadKey(); } } /// <summary> /// Defines an example plugin /// </summary> public interface IPlugin { void DoSomething(); } /// <summary> /// An example (malicious) plugin /// </summary> public class ExampleClass : MarshalByRefObject, IPlugin { /// <summary> /// This is called from the unrestricted AppDomain /// </summary> public void DoSomething() { voidDelegate startDoingThings = new voidDelegate(longNaughtyOperation); //run the method on a different thread to demonstrate we can //even start threads here startDoingThings.BeginInvoke(null, null); } private delegate void voidDelegate(); private void longNaughtyOperation() { while (true) { try { //this is denied so will fail string dummyData = File.ReadAllText("C:\\windows\\win.ini"); //this won't ever happen hopefully :) Console.WriteLine("Restricted AppDomain completed its work!!!"); //stop looping if the above works! break; } catch (SecurityException) { Console.WriteLine("Security exception as expected, trying again so you can terminate this thread... :)"); } Thread.Sleep(1000); } } } }Permalink