4. Permission Set Classes
Instead of constructing
individual permissions and demanding them, or using a permission to
modify a stack walk, you can programmatically construct permission sets.
In fact, the main reason for using a permission set is to install a
stack-walk modifier that combines multiple permissions (remember that
you can install only a single stack-walk modifier). Creating a
permission set programmatically is similar to composing a new permission
set using the .NET Configuration tool—you create individual permission
objects and aggregate them in a permission set object. Using a
permission set is an easy way to install a stack-walk modifier that
denies, permits, or asserts multiple permissions. Example 9
demonstrates composing a permission set with file I/O and UI
permissions and denying it before accessing a questionable component.
Example 9. Creating and denying a permission set
public void SomeMethod( ) { PermissionSet permissionSet; //Create an empty permission set permissionSet = new PermissionSet(PermissionState.None); IPermission filePermision; string path = @"C:\"; filePermision = new FileIOPermission(FileIOPermissionAccess.AllAccess,path); permissionSet.AddPermission(filePermision); IPermission UIPerm; UIPerm = new UIPermission(PermissionState.Unrestricted); permissionSet.AddPermission(UIPerm); IStackWalk stackWalker = permissionSet; stackWalker.Deny( ); QuestionableComponent obj = new QuestionableComponent( ); obj.DoSomething( ); CodeAccessPermission.RevertDeny( ); }
|
You can explicitly revert a stalk-walk modifier set by a permission set using the static methods of CodeAccessPermission, or you can wait for the method to return, as with an individual permission modifier.
4.1. Permission set collection
Using individual permissions, as in Example 1,
you can demand that all callers up the stack have a particular
permission. If you have multiple permissions to demand, you can build a
permission set (as in Example 9) and demand that the callers are granted all the permissions in the permission set:
PermissionSet permissionSet = new PermissionSet(PermissionState.None);
permissionSet.AddPermission(...);
permissionSet.AddPermission(...);
permissionSet.Demand( );
.NET 2.0 introduces an
interesting use of permission sets: the ability to demand that the
callers up the stack are granted at least one of any number of
permissions sets specified. The class PermissionSetCollection is defined as:
public sealed class PermissionSetCollection : ICollection,IEnumerable
{
public PermissionSetCollection( );
public void Add(PermissionSet permSet);
public void Demand( );
//Rest of the members
}
This is a simple collection of permission sets. You can add new permission sets using the Add( ) method. When you call the Demand( )
method, it performs a stack walk, demanding that every caller up the
stack satisfies at least one of the permission sets in the collection
(that is, satisfies all the permissions in at least one of the
permission sets in the collection). This is akin to performing a
programmatic (instead of declarative) demand choice for the permission
sets in the collection. Since a permission set can contain a single
permission, effectively you can use PermissionSetCollection
to generate a demand choice for individual permissions (this is the
only way in .NET to perform a programmatic demand choice for individual
permissions). For example, consider the code in Example 1.
You could relax the strict demand for file I/O permission by demanding
that the callers up the stack either have file I/O permissions or were
installed in the GAC. As mentioned at the beginning of this chapter,
because only an administrator can install assemblies in the GAC, such
assemblies are somewhat more trustworthy than assemblies installed by
non-administrators. You can demand GAC installation using the GacIdentityPermission class.
Example 10 demonstrates the use of PermissionSetCollection with the modified Save( ) method from Example 1. It defines the static helper class SecurityUtil, with the DemandChoice( ) method. DemandChoice( ) accepts an array of IPermission objects. For each permission object in the array, DemandChoice( ) creates a PermissionSet object and adds it to a PermissionSetCollection object. DemandChoice( ) then demands the permission set collection, thus triggering a demand choice. The use of the params array qualifier in DemandChoice( ) makes it easy to call it with any number of permissions.
Example 10. Using PermissionSetCollection
public static class SecurityUtil
{
public static void DemandChoice(params IPermission[] permissions)
{
PermissionSetCollection collection = new PermissionSetCollection( );
foreach(IPermission permission in permissions)
{
PermissionSet permisssionSet = new PermissionSet(PermissionState.None);
permisssionSet.AddPermission(permission);
collection.Add(permisssionSet);
}
collection.Demand( );
}
}
//Replaces the Save( ) method of Example 12-1
public void Save(string text)
{
IPermission permission1;
permission1 = new FileIOPermission(FileIOPermissionAccess.Write,m_FileName);
IPermission permission2;
permission2 = new GacIdentityPermission( );
SecurityUtil.DemandChoice(permission1,permission2);
m_Stream.WriteLine(text);
}