2.3. Developing for Permissions
When CLR loads an assembly, the
assembly lacks any rights — it can't even execute code. Consequently,
the first task CLR must perform with the assembly is to use the
evidence and the code group memberships to determine what permissions
the assembly has. To perform this task, CLR must run the evidence
through the policies set up by the network administrator. The following
sections discuss how to obtain two types of permissions within an
application.
2.3.1. Configuring the Obtain Permissions Example
The example begins with a Windows Forms application. Add two buttons, Test (btnTest) and URL Test (btnUrlTest).
The first button checks the user's local permissions. The second checks
the user's access to an URL. The application also requires access to a
textbox, txtUrl, for the URL to check and txtOutput for the application output. You must add the following using statements to the application:
using System.Reflection;
using System.Security;
using System.Security.Policy;
2.3.2. Creating the Local Permissions Code
The first part of the application obtains a list of
permissions for the user on the local machine. In most cases, unless
the administrator has set policies using the CASPol utility, the output
will simply say that the user has unrestricted rights. Listing 4 shows the code needed for this example.
Example 4. Getting a permission list using a policy
private void btnTest_Click(object sender, System.EventArgs e) { IEnumerator Policies; // Security policies. PolicyLevel Policy; // A single policy. PolicyStatement Statement; // A list of permissions. Assembly Asm; // Current assembly. Evidence EV; // Security evidence. StringBuilder Output; // Output data.
// Initialize the output. Output = new StringBuilder();
// Get the current assembly. Asm = Assembly.GetExecutingAssembly();
// Get the evidence from the assembly. EV = Asm.Evidence;
// Get all of the policies. Policies = SecurityManager.PolicyHierarchy(); while (Policies.MoveNext()) { // Get the current policy. Policy = (PolicyLevel)Policies.Current;
// Get the policy name. Output.Append("Policy: " + Policy.Label);
// Determine the permissions for this policy. Statement = Policy.Resolve(EV); Output.Append("\r\n" + Statement.PermissionSet.Count + " Permissions:\r\n" + Statement.PermissionSet);
// Get the attributes. Output.Append("Attributes: " + Statement.Attributes + "\r\n\r\n"); }
// Display the results. txtOutput.Text = Output.ToString(); }
|
The code begins by getting the executing assembly
and the evidence it contains. It uses this information to create a list
of policies using the SecurityManager.PolicyHierarchy() method. The SecurityManager
is another of the CAS policy features, so it's obsolete in the .NET
Framework 4. This method actually returns a list of policy objects you
can enumerate using an IEnumerator object, Policies.
The PolicyLevel object, Policy, contains the individual policies associated with the assembly. Notice the Policy.Resolve() method call. This call sends the assembly evidence to the policy for evaluation. The output is a PolicyStatement object, which includes the permissions generated by the policy. Each PolicyStatement includes a PermissionSet property that defines the permissions for the assembly based on that policy. Figure 2
shows typical output for this part of the example on a machine that
hasn't been configured by the administrator to use specific policies.
2.3.3. Creating the URL Permissions Code
You can use other techniques to build a set of
permissions. For example, you can determine the permissions for a
Website. However, you must build the evidence because it doesn't
already exist in a neat package. In addition, you need to consider
which evidence to present to the policy. Listing 5 shows an example of building evidence to access a Website (you can supply any URL you wish).
Example 5. Building evidence to obtain permissions
private void btnUrlTest_Click(object sender, EventArgs e) { PermissionSet Perms; // A single policy. Evidence EV; // Security evidence.
// Create evidence based on the URL. EV = new Evidence();
// Fill the evidence with information. EV.AddHostEvidence(new Url(txtUrl.Text)); EV.AddHostEvidence(Zone.CreateFromUrl(txtUrl.Text));
// Determine the current permissions. Perms = SecurityManager.ResolvePolicy(EV);
// Create the output. txtOutput.Text = Perms.ToString(); }
|
This example still relies on evidence. However, you must build the evidence using the AddHostEvidence()
method. The evidence consists of an URL and a Zone in this situation,
but you can use any acceptable form of evidence. Notice that this
example uses the SecurityManager object to resolve the policy. Figure 4 shows the output from this example.
Notice that the information uses an XML format. Each
of the permissions listed includes the full class information, which
makes it easier to determine precisely what the permission means. For
example, the first permission is System.Security.Permissions.FileDialogPermission.
This permission controls access to the file dialog box. The Website in
question can't access all the file dialog features, but it can open the
file dialog, which is all that the user needs in order to open or save
a file in most cases. One of the last items in the list (at least for
this URL) is the System.Security.Permissions.ZoneIdentityPermission.
This permission shows that the URL is within the Internet zone for my
machine. Testing URLs on the Web correctly shows zone change.
Once you have access to permission objects, you can modify the permissions for the object by using the PermissionSet members. For example, you can add a permission using either the AddPermission() or the Assert() methods. Be aware, however, that the Assert()
method can cause security vulnerabilities by giving an object rights
that other objects in the hierarchy don't have. In addition, the Assert() method requires that the code have the SecurityPermissionFlag.Assertion permission, which CLR doesn't grant in some cases (making an Assert() method call harder to make than AddPermission()).
Neither of these methods will allow you to add permissions that the
current policy doesn't allow — you can't use these calls to circumvent
security measures. You can also use the FromXml() method to load an XML formatted file that contains rights the object should have.