Increasing Permissions


Although it's certainly possible to build full-featured applications that run within the confines of a reduced permission set, you can easily eliminate these restrictions by allowing well-known assemblies increased or even unrestricted permissions. This is especially useful in a corporate intranet in which client machines are configured by the same staff that deploys the NTD applications.

There are a number of ways to increase permissions for an assembly. For example, if you're unhappy with the changes that were made in .NET 1.0 SP1, you can raise or lower permissions for any zone as a whole using the Adjust .NET Security Wizard (available via the Microsoft .NET Framework Wizards item on the Administration Tools menu), as shown in Figure 15.6.

Figure 15.6. Adjusting .NET Security

If you'd like to be a little less sweeping in your security changes (a practice I heartily recommend), you can use the Internet Control Panel to configure your system to trust all assemblies from a specific site, as shown in Figure 15.7.

Figure 15.7. Using the Internet Control Panel to Add Trusted Sites

Any sites listed as trusted in the Internet Control Panel settings are awarded Internet permissions. If this is still too broad, you can be even more restrictive by setting permissions on an assembly-by-assembly basis.

If you'd like to adjust permission for a specific assembly, you can set up a custom code group using the Microsoft .NET Framework Configuration tool, or you can use the Trust an Assembly Wizard. This tool creates a code group named Wizard_N, where the N varies according to the number of times you run the wizard. When you run this tool, you enter the URL to the assembly you'd like to trust:

http://trustedmachine/hr452/hr452.exe

Based on that URL, you'll be asked whether you'd like to trust only this assembly, all assemblies from the same publisher, or all of the assemblies having the same public key. To simplify security configuration, it's a good idea to sign all your assemblies with the same public/private key pair. For example, I signed both wahoo.exe and wahooControl.dll and can adjust both of their permissions at once by choosing to trust assemblies having the same key, as shown in Figure 15.8.

Figure 15.8. Trusting All Assemblies Having the Same Public Key

Here I've set all assemblies having the same public key, regardless of version, to be trusted. This is a good policy because it allows an entire family of trusted applications to be trusted with a single code group.

After you've specified which assemblies to trust in the Trust an Assembly Wizard, you'll be asked how much trust you'd like them to have on a sliding scale. It's hard to tell from the user interface shown in Figure 15.9, but the tick marks, from bottom to top, assign the permission sets Nothing, Internet, LocalIntranet, and FullTrust.

Figure 15.9. How Much an Assembly Is Trusted

With the new code group in place, the next time you surf to the URL .NET will match the membership condition to the new code group and will give the assembly the adjusted permissions.

Awarding permissions to your own assemblies is a matter of creating a code group with a membership condition that matches your assemblies ”which site it came from, which URL it came from, which key it's signed with, and so on ”and matching it to a set of permissions.

Furthermore, you can build your own custom permission set or use one of the default permission sets. Deciding whether to build your own custom permission set is a matter of being familiar with the built-in permission sets, although creating a new one that overlaps with a built-in one won't hurt anyone .

However, if you need access to any assemblies not marked with APTCA, then you'll need to create a code group that awards your assembly the FullTrust permission set. None of the other default named permission sets, even the Everything permission set, can award permissions to access assemblies not marked with APTCA.

Increasing Permissions Programmatically

As facile as you may become with the .NET permission policy administration tools, you never want to wander to each of your clients ' machines to create the necessary code groups and permissions sets that they need to run your code, especially if that code is to be deployed across the Internet. Luckily, .NET provides classes to create code groups and permission sets. For example, the following code is used to create a custom code group to award all Internet permission to assemblies signed with a known key:

 using System.Security; using System.Security.Permissions; using System.Security.Policy; // Generated with 'secutil -c -s wahoo.exe' byte[] publicKey = { 0, 36, ... }; // Find the machine policy level PolicyLevel machinePolicyLevel = null; System.Collections.IEnumerator ph =   SecurityManager.PolicyHierarchy(); while( ph.MoveNext() ) {   PolicyLevel pl = (PolicyLevel)ph.Current;   if( pl.Label == "Machine" ) {     machinePolicyLevel = pl;     break;   } } if( machinePolicyLevel == null ) return; // Create a new code group giving Wahoo! Internet permissions PermissionSet permSet1 = new NamedPermissionSet("Internet"); StrongNamePublicKeyBlob key = new StrongNamePublicKeyBlob(publicKey); IMembershipCondition membership1 =   new StrongNameMembershipCondition(key, null, null); // Create the code group PolicyStatement policy1 = new PolicyStatement(permSet1); CodeGroup codeGroup1 = new UnionCodeGroup(membership1, policy1); codeGroup1.Description =   "Internet permissions for Sells Brothers Wahoo!"; codeGroup1.Name = "Sells Brothers Wahoo!"; // Add the code group machinePolicyLevel.RootCodeGroup.AddChild(codeGroup1); // Create a new code group giving all of // sellsbrothers.com Execute permission PermissionSet permSet2 = new NamedPermissionSet("Execution"); IMembershipCondition membership2 =   new SiteMembershipCondition("www.sellsbrothers.com"); // Create the code group PolicyStatement  policy2 = new PolicyStatement(permSet2); CodeGroup  codeGroup2 = new UnionCodeGroup(membership2, policy2); codeGroup2.Description =   "Minimal execute permissions for sellsbrothers.com"; codeGroup2.Name = "sellsbrothers.com minimal execute"; // Add the code group machinePolicyLevel.RootCodeGroup.AddChild(codeGroup2); // Save changes SecurityManager.SavePolicy(); 

This code actually adds two code groups: one to award Internet permissions to all assemblies signed with a known strong name, and a second one to work around an "issue" that emerged in .NET 1.0 SP1 whereby a site as a whole must have at least Execute permission for any other permissions awarded a strong name to take effect. We start by using SecurityManager to find the top of the Machine runtime policy hierarchy, where we'll add the new code groups. We then grab the Internet NamedPermissionSet and join it with StrongNameMembershipCondition to produce the new code group. We then name the new code group something that'll make sense in the administration tools and add it to the root code group along with all the existing code groups. (If we had wanted to award our assemblies full trust, we'd have passed the string "FullTrust" instead of "Internet" when creating this NamedPermissionSet object.) After creating the first permission set, we do the same thing again with the Execution NamedPermissionSet and the SiteMembershipCondition, naming them and adding them as well.

To commit the changes to the Machine runtime security policy, we ask SecurityManager to save, and that's it. This code is all that's necessary to award permissions from existing permission sets to your assemblies.

If you want to create a custom permission set, the code is similar except that you create an instance of an empty NamedPermissionSet object and add permission objects that derive from CodeAccessPermission, such as FileIOPermission and DirectoryServicesPermission. You then add new permission sets to the machine policy via the AddNamedPermissionSet method:

 // Create a named, empty permission set NamedPermissionSet permSet =   new NamedPermissionSet("My Permission Set", PermissionState.None); // Add a permission IPermission perm = new DirectoryServicesPermission(); permSet.AddPermission(perm); machinePolicyLevel.AddNamedPermissionSet(permSet); 

Notice the use of PermissionState.None passed to the NamedPermissionSet constructor. Without that, you get a permission set just like FullTrust, with all permissions. Instead, you want an empty permission set that has only those permissions that you explicitly add.

Deploying Permissions

After you've got managed code to award permissions, it needs to run on the machine with FullTrust. Otherwise, it won't have permission to modify the permission policy (it must also be running as a Win32 Administrator). Placing an EXE on a Web server and asking users to click on a link won't do, because then the code will be in a partially trusted environment and we're back where we started.

The easiest way to package managed code for fully trusted execution on the client machine is to use a Microsoft Installer file. MSI files are executed by a runtime engine that downloads the code to the machine before running it, thereby giving us the permissions we need to award other permissions. Also, MSI files have built-in support in the intranet world for deployment tools such as Systems Management Server and Active Directory. In a less sophisticated deployment environment, such as smaller businesses or the Internet, you can provide a link that, after a prompt, executes the MSI file on the user's machine. Even if all your users have to run the MSI themselves , that still requires only one installation to enable the permissions needed for, say, every NTD application deployed from the IT group's internal Web site.

There are many ways to build MSI files, but the most readily available one comes with advanced versions of VS.NET. The trick is to convince a setup project to execute your code during installation. Assuming you've got a VS.NET solution with a setup project and a class library project, you have only two major tasks left to do this convincing.

The first task is to add a class to your class library project that derives from System.Configuration.Install.Installer and is tagged with the RunInstaller(true) attribute. An instance of any such class will be created by the MSI engine during setup, so that's where you put your custom code. The easiest way to get such a class is to right-click on your class library project in Solution Explorer and choose Add New Item Code Installer Class. It will create a place for your permission award code in the constructor:

  [RunInstaller(true)]  public class Installer1 :  System.Configuration.Install.Installer  {   public Installer1() {     ...  // TODO: Add your permission award code here  } } 

Your second task is to add this assembly to the list of custom actions that your setup will perform during installation. To do that, right-click on your setup project in Solution Explorer and choose View Custom Actions. This will show you a list of the custom actions at each phase of the setup, as shown in Figure 15.10.

Figure 15.10. Setup Project Custom Actions

To add a custom action to the install phase, right-click on the Install custom action list and choose Add Custom Action. This will show the list of folders to place your custom action code into, as shown in Figure 15.11.

Figure 15.11. Choosing a Folder for a Custom Action

Double-click Application Folder and choose Add Output to choose the output from one of the other projects in the solution. Make sure the class library project with your installer class is selected at the top, and choose Primary Output, as shown in Figure 15.12.

Figure 15.12. Choosing the Primary Output of Your Class Library Project to Act as a Custom Action

These settings will cause the installer classes in your class library assembly to be created during the Install phase of your MSI setup. Now, when you build and execute the MSI file produced by the setup project, your code will execute at FullTrust and can award permissions for your assemblies.



Windows Forms Programming in C#
Windows Forms Programming in C#
ISBN: 0321116208
EAN: 2147483647
Year: 2003
Pages: 136
Authors: Chris Sells

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