The default implementation of the .NET Framework’s code access security (CAS) has the potential to add significant processing overhead to an application, especially in a situation where the object accessing the secured resource is several layers deep in the call stack. This is because the CLR will verify that every caller in the calling chain has the needed permissions before it will attempt to carry out the requested operation. The CLR throws a security exception if any component in the calling chain lacks the necessary permission to execute against a protected resource. From a security standpoint, that may be exactly what we want to happen. But from a performance standpoint, it could be disastrous if not implemented properly. This is because the CLR will perform this complete security check any time that access to a protected resource is attempted. We’ll look at a way to prevent a complete security check and how to architect your applications in such a way to maintain tight security without degrading the user experience.

Asserting your rights
The .NET Framework provides the Assert method to allow developers to limit the performance implications of adding CAS. The Assert method limits the stack walk operation performed by the CLR when checking for required permissions. When using Assert, only the current code stack frame is checked by the CLR when evaluating permissions. The CLR will not check the CAS permissions of any other calling components. In a heavily component-based system, this will significantly improve performance. You should use the Assert method carefully. It can weaken security because it removes the requirement that all calling code in the stack must have permission to access a protected resource.

Don’t forget the user
Although you can selectively circumvent security checks using Assert, you can get the advantages of increased security and improve the user experience by requiring your applications to request permissions before starting. The .NET Framework provides a set of attributes that the developer can use to request permissions before attempting to run methods in an assembly. When the CLR loads the code into memory, it checks the requests for permission against the security context assigned to the code based on where it came from and who’s attempting to execute it. For example, if you want to make sure that a section of code that needs to call into unmanaged code will be allowed to do so at the point in the code where it’s required, you can apply the following attribute at the assembly level:

For C#[assembly:SecurityPermissionAttribute(SecurityAction.RequestMinimum, Flags = SecurityPermissionFlag.UnmanagedCode)]

For VB<assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum,_ Flags := SecurityPermissionFlag.UnmanagedCode)>

By requesting permissions in advance, administrators can configure your applications to run with the proper permissions level. A system administrator can use the PermView tool to examine an assembly and then configure the system to allow the application to use those permissions. If you rely on Try/Catch blocks and Exceptions to manage security, the PermView tool has no way of returning the required permissions. But requesting permissions lets PermView interrogate the metadata of the assembly and return the required permissions to a system administrator. The administrator can then use the .NET Framework Security tools in the Control panel to allow the assembly the appropriate level of access in order to execute.

Requesting permissions in advance also lets you manage the user interface more effectively. Suppose your system allows users to create files that are stored on the local hard disk. If you don’t check for appropriate security until the user attempts to save, he or she might enter a significant amount of data before pressing the Save button and receiving a security exception. Whether the exception is caught in your code or by the CLR at the application level, the user still loses the work.

Optional and refused permissions
In addition to requesting the minimum permissions required, you can also request optional permissions. You’ll use the RequestOptional security attribute in cases where you want to mix compile time permission requests with runtime permission requests based on the user. This lets the administrator know what potential security requests may arise from the assembly. In order to prevent malicious code from calling your object and misusing your security attributes, you can also set the assembly level permission to RequestRefuse. Setting RequestRefuse will guarantee that the calling code can’t use your object to access a specific set of resources.

It’s important to note that your code doesn’t have to request permissions in order to compile. However, using permission requests is an effective way to manage access to protected resources without littering your code with Try/Catch blocks and Security Exception traps.

Code access security

What standards have you put in place to support code access security for your .NET applications? Post a response in the discussion below, or send us an e-mail.