Features
.NET Feature — Writing Client Components in .NET
Universal solutions PART 2
Jun. 26, 2007 03:15 AM
Determining the Set of Permissions and Creating the Permission Set
At this point, we should think about the permissions our component needs. We're creating our own code group and permission set, so we start from scratch: this means that we'll have no permissions at all to start with.
So, in addition to the permission to call unmanaged code (which we need to solve the event-handling problem that got us into this mess), we also need to include the permission for our assembly to execute. If we forget to include "execute permission," our component will simply refuse to load.
But wait, there's more: when Internet Explorer creates the AppDomain to load our assembly, it first determines the set of permissions that can be granted to it. That set of permissions is based on "evidence." Internet Explorer uses three evidence classes:
- Site: the Web site the assembly is coming from
- Zone: this is the security zone defined in Internet Explorer security properties associated with the site. This evidence class is included because different users can assign different zones to the same Web site.
- URL: the URL of the assembly.
The important thing to note here is that this evidence is gathered before our assembly is loaded, and so does NOT include the assembly's own permissions since the public key isn't yet known (remember: the assembly isn't loaded yet!).
We'll get our permissions once the assembly is loaded, but to exercise them, we need to explicitly assert the permissions we need when we need them.
And guess what: asserting permissions requires... permission to assert!
I guess this is the reason why books about .NET Security are so thick.
Fortunately, it's simpler to code than to explain. The following snippet creates a permission set called "My Permission Set" and adds the three security permissions we've talked about:
- Execute permission to allow our assembly to execute
- Assert permission to allow our assembly to assert its permissions (we'll use this later)
- Unmanaged Code permission to allow calls to unmanaged code
private const string PermissionSetName = "My Permission Set";
NamedPermissionSet permSet = new NamedPermissionSet(PermissionSetName, PermissionState.None);
permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution |
SecurityPermissionFlag.UnmanagedCode | SecurityPermissionFlag.Assertion));
Finally, the permission set should be added to the Machine policy level which we got previously:
machinePolicyLevel.AddNamedPermissionSet(permSet);
Creating the Code Group
Now that we have our permission set, we have to create a code group containing the set, and associate that group with our public key. Here's the corresponding snippet:
private static readonly byte[] PublicKey ={ ... };
private const string CodeGroupName = "My signed assemblies";
CodeGroup group = new UnionCodeGroup(new StrongNameMembershipCondition(new StrongNamePublicKeyBlob(PublicKey),
null, null), new PolicyStatement(permSet));
group.Description = "Permission for my assemblies";
group.Name = CodeGroupName;
The PublicKey byte array is the public key we got earlier, of course. Just like permission sets, the code group is added to the Machine policy level:
machinePolicyLevel.RootCodeGroup.AddChild(group);
Finally, we need to commit our changes to the security manager:
SecurityManager.SavePolicy();
Installing the Permissions
Up till now, all the code and explanations have avoided one question: how do you install the permissions on the users' machines? How do you make the code above execute on the client's machine?
As you may have guessed by now, to install permissions you need... permission. Writing a link to an executable program with the code above won't work, since running an executable from a link in a Web page won't run with the required permissions.
The best solution is to write an install program (an .MSI or Microsoft Installer) file in which the "install" and "uninstall" custom actions add (resp. remove) your permissions. The accompanying code has two projects for this purpose:
1. A project called PermissionInstaller, which contains the necessary code to install and uninstall the permissions. The assembly implements a type PermissionInstaller derived from System.Configuration.Install.Installer, and with the explanation above you should have no trouble finding out what's going on. The type implements the Install and Uninstall methods.
2. A project called DeployPermissions, which generates the actual installer file (DeployPermissions.msi). This install project installs the PermissionInstaller.dll assembly and executes the above Install and Uninstall methods as custom actions.
About Vincent Van Den BergheVincent Van Den Berghe works as a software developer for Bureau van Dijk Electronic Publishing (bvdep.com). He develops Internet applications, mostly for bibliographic or other text-oriented databases, using C++, COM, ASP, and .NET as implementation technologies.