NullifyNetwork

The blog and home page of Simon Soanes
Skip to content
[ Log On ]

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 appdomain'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