4. Programming Application Domain Policy
Application domain policy is the final
layer of security policy evaluated when determining the code-access
permissions to grant an assembly. Regardless of the permissions
granted to an assembly based on the enterprise, machine, and user
policies, you can further lock down its permissions using application
domain policy. Application domain policy is resolved even if the
assembly is a member of a LevelFinal code group in
a higher policy level.
You configure application domain policy by calling the
AppDomain.SetAppDomainPolicy
method and passing a configured
PolicyLevel object. Application domain policy can
be set only once per application domain—setting it a second
time results in a
System.Security.Policy.PolicyException. Your code
must have the
ControlDomainPolicy permission to call the
SetAppDomainPolicy method.
ControlDomainPolicy is an element of
SecurityPermission:
# C#
public void SetAppDomainPolicy(
PolicyLevel domainPolicy
);
# Visual Basic .NET
NotOverridable Public Sub SetAppDomainPolicy( _
ByVal domainPolicy As PolicyLevel
)
Any assemblies loaded into an application domain before you configure
the application domain policy are subject to the standard policy
resolution results from the enterprise, machine, and user levels.
Application domain policy affects only those assemblies loaded after
it's set. This allows you to load assemblies that
require higher trust, before locking down the application domain
through the additional layer of policy.
The need to implement application domain policy will not be an
everyday occurrence, but when writing applications that are
responsible for loading other code, the capability is invaluable.
Example 4 uses the
SetDomainPolicy method to create a policy level
with the code group structure shown in Figure 3
and assign it to a specified application domain. The root code group
matches all code but grants the Nothing permission
set. The second layer of code groups determines the permissions to
grant based on Url evidence of a loaded assembly.
You grant assemblies loaded from the Trusted
folder the FullTrust permission set, assemblies
loaded from the Untrusted folder the
Internet permission set, and assemblies loaded
from the Demo the Execution
permission set. You grant all other assemblies no permissions.
Because we expect an assembly to have only one piece of
Url evidence, we make the root code group of type
FirstMatchCodeGroup, saving the runtime from
performing unnecessary policy resolution processing.
Example 4. Creating a policy level and assigning it to an application domain
# C#
private static void SetDomainPolicy(AppDomain domain) {
// Create a new PolicyLevel for the application domain
PolicyLevel policy = PolicyLevel.CreateAppDomainLevel( );
// Create a new FirstMatchCodeGroup that matches all code and
// grants the named permission set "Nothing".
policy.RootCodeGroup = new FirstMatchCodeGroup(
new AllMembershipCondition( ),
new PolicyStatement(policy.GetNamedPermissionSet("Nothing"))
);
// Determine the base path name for the URL evidence
String basePath = "file://" + AppDomain.CurrentDomain.BaseDirectory;
// Create the code groups that apply to the assemblies loaded
// from specific folders. Make each of the the code groups
// Exclusive so that they set the absolut maximum permisisons a
// plugin can have.
policy.RootCodeGroup.AddChild(new UnionCodeGroup(
new UrlMembershipCondition(basePath + "Trusted/*"),
new PolicyStatement(policy.GetNamedPermissionSet("FullTrust"),
PolicyStatementAttribute.Exclusive)
));
policy.RootCodeGroup.AddChild(new UnionCodeGroup(
new UrlMembershipCondition(basePath + "Untrusted/*"),
new PolicyStatement(policy.GetNamedPermissionSet("Internet"),
PolicyStatementAttribute.Exclusive)
));
policy.RootCodeGroup.AddChild(new UnionCodeGroup(
new UrlMembershipCondition(basePath + "Demo/*"),
new PolicyStatement(policy.GetNamedPermissionSet("Execution"),
PolicyStatementAttribute.Exclusive)
));
// Assign the policy to the specified application domain.
domain.SetAppDomainPolicy(policy);
}
# Visual Basic .NET
Private Shared Sub SetDomainPolicy(ByVal domain As AppDomain)
' Create a new PolicyLevel for the application domain
Dim policy As PolicyLevel = _
PolicyLevel.CreateAppDomainLevel( )
' Create a new FirstMatchCodeGroup that matches all code and
' grants the named permission set "Nothing".
policy.RootCodeGroup = New FirstMatchCodeGroup( _
New AllMembershipCondition( ), _
New PolicyStatement(policy.GetNamedPermissionSet("Nothing")))
' Determine the base path name for the URL evidence
Dim basePath As String = _
"file://" & AppDomain.CurrentDomain.BaseDirectory;
' Create the code groups that apply to the assemblies loaded
' from specific folders. Make each of the the code groups
' Exclusive so that they set the absolut maximum permisisons a
' plugin can have.
policy.RootCodeGroup.AddChild(New UnionCodeGroup( _
New UrlMembershipCondition(basePath & "Trusted/*"), _
New PolicyStatement(policy.GetNamedPermissionSet("FullTrust"), _
PolicyStatementAttribute.Exclusive)))
policy.RootCodeGroup.AddChild(New UnionCodeGroup( _
New UrlMembershipCondition(basePath & "Untrusted/*"), _
New PolicyStatement(policy.GetNamedPermissionSet("Internet"), _
PolicyStatementAttribute.Exclusive)))
policy.RootCodeGroup.AddChild(New UnionCodeGroup( _
New UrlMembershipCondition(basePath & "Demo/*"), _
New PolicyStatement(policy.GetNamedPermissionSet("Execution"), _
PolicyStatementAttribute.Exclusive)))
' Assign the policy to the specified application domain.
domain.SetAppDomainPolicy(policy)
End Sub