Understanding the System.Security Namespace


Understanding the System.Security Namespace

The System.Security namespace acts as the starting point for the majority of the other security namespaces discussed in the book. This is the first namespace that many people look at when they begin working with security features in the .NET Framework. Actually, this namespace contains a number of utility-type classes. You’ll probably use it in every program you create, yet it doesn’t contain the underpinnings of the security features. The following sections tell you more about this namespace.

Security Namespace Overview

The System.Security namespace contains a number of interesting classes and attributes, including the AllowPartiallyTrustedCallersAttribute attribute. You use this attribute to allow partially trusted code to call strongly named assemblies. This attribute is one of the double-edged sword decisions you must make when working with security. If you add the attribute to your strongly named assembly, there’s a chance that a partially trusted assembly could cause a security breach. On the other hand, not adding the attribute means that some code won’t be able to call your strongly named assembly at all.

You always need to add this namespace to your code because it contains the SecurityException exception, which allows you to handle security errors, such as authentication failures, gracefully. Normally, you’ll want to access secure calls using a try…catch structure. When a SecurityException exception occurs, your code can catch it and use any logic you have in place for handling the problem. In many cases, the program will exit and send a message to the network administrator. However, you could do something as simple as ask the user to enter a password again.

Tip

You can find a complete description of the System.Security namespace at http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemSecurity.asp. You may be surprised at the limited number of classes, interfaces, and enumerations associated with this namespace. To get the bigger picture, make sure you check the namespace hierarchy.

Of all the classes in this namespace, the SecurityManager class is one of the most useful because it helps you determine user and code rights to perform certain tasks. In fact, this particular class is so useful, that you may want to commit the routines you write to a separate library so that you can use them in every program. It’s important to know what security settings are in place so that you know what the user and the code can do in the current environment. The interesting part about .NET security is that it’s flexible enough that you can write a generic routine. You don’t have to know the user’s name while writing the code because this information is easy to obtain using other means. You’ll see this class in action in the next section, “SecurityManager Class Example.”

SecurityManager Class Example

This example doesn’t show you all of the features of the SecurityManager class. However, it gets you started using this important class by demonstrating some basic security features. For example, the class tells you whether the administrator has actually enabled security in the current environment and whether the code has execution rights. Listing 2.2 shows the details of how to use these class features. (You can find this code in the \Chapter 02\C#\SecureManage or \Chapter 02\VB\SecureManage folder of the source code located on the Sybex Web site.)

Listing 2.2 Obtaining information with the SecurityManager class

start example
private void btnTest_Click(object sender, System.EventArgs e) {    StringBuilder        Output;     // Output data.    CodeAccessPermission CAP;        // Permissions object for code.    PrincipalPermission  PP;         // Permissions object for users.    IEnumerator          Policies;   // Security policies.    PolicyLevel          Policy;     // A single policy.    // Initialize the output string.    Output = new StringBuilder();    // Create the code permissions object.    CAP = new FileIOPermission(FileIOPermissionAccess.AllAccess,                               @"C:\");    // Create the user permission object.    PP = new PrincipalPermission(SystemInformation.UserName,                                 "Administrator");    // Determine if security is enabled.    if (SecurityManager.SecurityEnabled)    {       // Security is enabled.       Output.Append("Security is enabled.");       // Check the code execution requirements.       if (SecurityManager.CheckExecutionRights)          Output.Append("\r\nCode requires execution rights.");       else          Output.Append("\r\nCode doesn’t require execution rights.");       // Determine if the caller has administrative rights.       if (SecurityManager.IsGranted(PP))          Output.Append("\r\n" + SystemInformation.UserName +             " has administratrive rights.");       // Determine if the code can perform all access to drive C.       if (SecurityManager.IsGranted(CAP))          Output.Append("\r\nCode can access Drive C.");       // Get the all of the policies.       Policies = SecurityManager.PolicyHierarchy();       Output.Append("\r\n\r\nPolicy Hierarchy:");       while (Policies.MoveNext())       {          // Get the current policy.          Policy = (PolicyLevel)Policies.Current;          // Add its label to the output.          Output.Append("\r\n" + Policy.Label);       }    }    else       // Security isn’t enabled.       Output.Append("Security Not Enabled!");    // Output the result.    MessageBox.Show(Output.ToString(),                    "SecurityManager Results",                    MessageBoxButtons.OK,                    MessageBoxIcon.Information); }
end example

The code begins by creating two types of permissions. A CodeAccessPermission determines what the code can do. For example, even though the user has the right (permission) to access the disk drive, the code may not have this right or the administrator may limit the code’s access. When you create a new CodeAccessPermission object, you can ask about specific code execution rights without worrying about details of other rights the code might have. Note that you don’t use the CodeAccessPermission constructor directly. You need to create a permission object from one of the resource permissions, such as the FileIOPermission shown.

A PrincipalPermission object focuses on the user. Notice how the constructor uses the SystemInformation.UserName property to determine the current user. Actually, you’ll want to view all of the features of the SystemInformation class because it’s very useful. This class helps you learn more about the system using simple calls. The second argument determines what right you want to check for the given user. In this case, PP will contain the administrator permission for the current user.

After the code creates the two permission objects, it checks the current security state using the SecurityManager.SecurityEnabled property. You must make this check before you do anything else because there’s a chance that the administrator hasn’t enabled security. When this occurs, many of the other SecurityManager features won’t work properly.

The code checks execution rights next using the SecurityManager.CheckExecutionRights. Theoretically, the program should end if it doesn’t have proper execution rights. In addition, you’ll probably want to create an Event Log entry and raise an error (if one hasn’t occurred already). The example simply makes note of the fact and continues with the next check.

The documentation for the SecurityManager.IsGranted() method isn’t very clear. It tells you that the method requires an object that implements the IPermission interface as input, without really telling you what that means. You can theoretically create your own permissions, but the CodeAccessPermission and PrincipalPermission classes serve most needs. In fact, I can’t think of a reason to create another IPermission interface class implementation. The example shows how to use both of these classes with the SecurityManager.IsGranted() method.

The final element in this example is a quick view of the policy hierarchy. You can actually follow the hierarchy down all the levels, but the example shows just the first level. Because this is a collection, you have several methods of following it at your disposal. The example moves from one entry to the next using the MoveNext() method. You must issue a MoveNext() call to access the first element, which is why the code is set up this way. The PolicyLevel object, Policy, provides complete information about the current level. In this case, the code returns the Label property value, which is the friendly name for that level. If you want to go to the next level, you use the NamedPermissionSets collection. Figure 2.2 shows the output from this program.


Figure 2.2: Rely on the SecurityManager class to learn about code and user rights.

The output shows that the example has security enabled and execution rights. In addition, the user has administrative privileges and the code has all access rights to the C drive. Notice that the policy hierarchy includes Enterprise, Machine, and User—the three standard hierarchy members.




.Net Development Security Solutions
.NET Development Security Solutions
ISBN: 0782142664
EAN: 2147483647
Year: 2003
Pages: 168

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