13.12 Manipulate Runtime Security Using Application Domain Security Policy


Problem

You need programmatic control over the permissions granted to assemblies.

Solution

Programmatically configure the security policy of the application domain into which you load the assemblies.

Discussion

Security policy consists of four policy levels: enterprise, machine, user , and application domain. The runtime resolves which permissions to grant to an assembly by determining the permission set granted by each policy level and then calculating the intersection (logical AND) of the four permissions sets. The permissions within this intersection are the assembly's final grant set.

Important  

Even if the enterprise, machine, or user policy levels specify a LevelFinal code group , which instructs the runtime not to evaluate lower policy levels, the runtime always uses the policy level of the containing application domain to calculate an assembly's grant set.

Only the enterprise, machine, and user policy levels are statically configured using administrative tools. Because application domains do not exist outside the context of the runtime, it's not possible to configure application domain policy statically. To configure the security policy of an application domain, you must create a policy level programmatically and then assign the policy level to the application domain.

Constructing a policy level in code can be a lengthy coding exercise depending on the complexity of the security policy you need to express. The System.Security.Policy.PolicyLevel class represents a security policy level. Within a PolicyLevel object, you must build a hierarchy of code groups, defining the membership conditions, permission sets, and attributes of each code group. There are many different types used to build the policy level, and a discussion of these types is beyond the scope of this book. Programming .NET Security , mentioned earlier, provides detailed coverage of each of these classes and demonstrates how to construct a policy level programmatically.

Tip  

Most commonly, you would develop a tool to assist in the creation of a policy level and write the policy level definition to a file, you can then load this definition from disk as required. The PolicyLevel class includes two methods to simplify this process: ToXml renders a PolicyLevel object to a form that is easy to store, and FromXml reconstructs a PolicyLevel object from its stored form.

Once you have a PolicyLevel object that expresses the desired security policy, you can assign it to an application domain. Obtain a System.AppDomain reference to the application domain you want to configure, and pass the PolicyLevel object to the AppDomain.SetAppDomainPolicy method. Your code must have the ControlDomainPolicy element of SecurityPermission to call SetAppDomainPolicy . You can call SetAppDomainPolicy only once on each application domain; if you call SetAppDomainPolicy a second time, it throws the exception System.Security.Policy.PolicyException .

You do not have to assign the PolicyLevel object to an application domain before loading assemblies into the application domain. Assemblies loaded before you set the application domain security policy have grant sets based only on the enterprise, machine, and user policy levels. The application domain policy applies only to those assemblies loaded after it's configured. Commonly, you use this capability to load trusted shared assemblies into the application domain that should not be constrained by application domain policy.

The application AppDomainPolicyExample listed here demonstrates the process of creating a policy level and assigning it to an application domain. The example creates a policy level that grants permissions based on the publisher of an assembly ” expressed in terms of System.Security.Policy.Publisher evidence.

 using System; using System.Security; using System.Security.Policy; using System.Security.Cryptography.X509Certificates; public class AppDomainPolicyExample {     public static void Main() {                  // Create a new application domain in which to load the downloaded         // assemblies.         AppDomain domain = AppDomain.CreateDomain("modules");         // Load assemblies into the application domain that you do not want         // constrained by the application domain security policy.                           // Configure the security policy for the new AppDomain object.         SetDomainPolicy(domain);                  // Load downloaded assemblies into secured application domain         // for execution.              }     // A method that configures the security policy of the AppDomain     // object passed to it. The security policy will assign different     // permissions to each assembly based on the publisher of the      // assembly. Assemblies from unknown publishers are assigned no      // permissions.     private static void SetDomainPolicy(AppDomain domain) {         // Create a new empty PolicyLevel for the application domain.         PolicyLevel policy = PolicyLevel.CreateAppDomainLevel();              // Create a new FirstMatchCodeGroup to use as the root node of          // the code group hierarchy. Configure this group to match all code         // by using the membership condition AllMembershipCondition and          // grant members the named permission set Nothing. This means         // all assemblies start with an empty grant set for the application         // domain policy level.         policy.RootCodeGroup = new FirstMatchCodeGroup(new AllMembershipCondition(),             new PolicyStatement(policy.GetNamedPermissionSet("Nothing")));                      // Create the set of code groups that determine which permissions         // to assign an assembly created by a particular publisher. Because         // the root code group is a FirstMatchCodeGroup, policy resolution         // only matches the assembly against these child groups until it          // finds the first match. Each code group is created with the          // Exclusive attribute to ensure that the assembly does not pick          // up any additional permissions from other code groups.                  // Create the code group that grants the FullTrust permission set          // to assemblies published by Microsoft.         X509Certificate microsoftCert =              X509Certificate.CreateFromCertFile("microsoft.cer");                  policy.RootCodeGroup.AddChild(new UnionCodeGroup(new PublisherMembershipCondition(microsoftCert),             new PolicyStatement(policy.GetNamedPermissionSet("FullTrust"),             PolicyStatementAttribute.Exclusive)));         // Create the code group that grants the Internet permission set         // to assemblies published by Litware, Inc.         X509Certificate litwareCert =              X509Certificate.CreateFromCertFile("litware.cer");              policy.RootCodeGroup.AddChild(new UnionCodeGroup(new PublisherMembershipCondition(litwareCert),             new PolicyStatement(policy.GetNamedPermissionSet("Internet"),             PolicyStatementAttribute.Exclusive)));         // Create the code group that grants the Execution permission set          // to assemblies published by Fabrikam, Inc.         X509Certificate fabrikamCert =              X509Certificate.CreateFromCertFile("fabrikam.cer");              policy.RootCodeGroup.AddChild(new UnionCodeGroup(new PublisherMembershipCondition(fabrikamCert),             new PolicyStatement(policy.GetNamedPermissionSet("Execution"),             PolicyStatementAttribute.Exclusive)));         // Add a final code group to catch all assemblies that are not         // matched by one of the publisher specific groups. Assign this         // group the permission set Nothing. Because the group is Exclusive         // the assembly will get no permissions from any other group, even          // from higher policy levels (enterprise, machine, and user).         policy.RootCodeGroup.AddChild(new UnionCodeGroup(new AllMembershipCondition(),             new PolicyStatement(policy.GetNamedPermissionSet("Nothing"),             PolicyStatementAttribute.Exclusive)));           // Assign the policy to the provided application domain.         domain.SetAppDomainPolicy(policy);     } } 



C# Programmer[ap]s Cookbook
C# Programmer[ap]s Cookbook
ISBN: 735619301
EAN: N/A
Year: 2006
Pages: 266

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net