Team LiB
Previous Section Next Section

Introduction to CAS

Code Access Security is a mechanism that is built into the .NET Framework to limit access to resources for managed code. A resource can be anything that might need to be secured, such as a file on disk, a CD-ROM drive, a TCP/IP connection, a database connection, or any number of things.

CAS defines standard permissions and permission sets that apply to all activities and all code run within the .NET Framework. When code is written with CAS in mind, code can request permissions from the system based on the activities that it needs to perform. It can also list the permissions that it would like to have but are not required for proper operation. Administrators can configure a security policy that dictates which sets of code (called code groups) have which permissions.

This chapter covers permissions and code groups and requesting permissions later. For now, it might be helpful if you knew how the .NET Framework authorized code. The code authorization process determines the permissions granted to a piece of code that is running.

To do this, the .NET Framework iterates through all the methods in the call stack and compares the permissions that have been granted to each item on the call stack with the permissions being demanded by those items. Obviously, if an item is demanding more permission than it has been granted, a security exception will occur and the item will be unable to complete its process.

If a semi-trusted (or untrusted) assembly makes a call to a fully trusted assembly without some additional precaution, the untrusted assembly could take advantage of the second assembly's security clearance and potentially cause severe damage to the system. To counteract this, .NET assigns permissions to individual callers on the call stack. Each caller has its own set of permissions. When the highly trusted code requests a permission, the stack is walked backward and the aggregate of permissions is examined. If one of the previous callers has been denied that permission, the execution will fail even if the most recent caller has been granted that permission. Figure 34.1 supplies a visual overview of this process.

Figure 34.1. Illustration of call-stack based permission resolution.


From the figure, you can see that there are three different assemblies, each with a different trust level (set of permissions). When Assembly 1 initiates Action A, whenever subsequently executed code demands permissions, those permissions will be resolved against the trust level of Assembly 1. Even if the request for permission occurs in Assembly 3 (a fully trusted assembly), the stack-walk that the .NET Framework performs will reveal that the call was initiated by a caller with little or no permissions granted and the call will more than likely fail. Action B is initiated by a semi-trusted assembly and will have more permissions than Action A, but less than Action C, because Action C is initiated by an assembly that has been fully trusted.

All of this complexity and depth in resolving permissions associated with code is designed to prevent your code from being abused by malicious code. The idea is that if someone writes malicious code that attempts to use an API that can destroy files, the malicious code will be unable to do so, even though that API has full permissions on the file system. This is possible because the stack of execution calls contains the permission information associated with the malicious code (hopefully untrusted) and can react accordingly.

Before discussing the permissions themselves, let's summarize the way that CAS works with assemblies. When an assembly is loaded, evidence such as the identity, public key, filename, version number, and zone (Internet, Intranet, so on) is combined with the configurable policy (you will see this policy later in the chapter) to produce a set of permissions that have been granted to the assembly. This set of permissions is then assigned to each caller on the stack to allow CAS to determine what callers from the assembly can and cannot do.

Using Code Access Security Permissions

By now you're probably wondering what a permission is. A permission is a discrete unit of ability. When code has a permission, it means that the code will be allowed to perform the task associated with the permission. In the list of permissions that you will see later, all the permissions refer to very specific actions to be taken by code when permission has been granted.

Code Access Permissions

Code access permissions are designed to protect resources and operations from unauthorized code and inappropriate, potentially harmful use. Each of the permissions in Table 34.1 grants the privilege to access a protected resource or to perform a particular secured task.

Table 34.1. Common Code Access Permissions

Permission Class

Privilege Granted

AspNetHostingPermission

The ability to access resources in ASP.NET-hosted environments

DirectoryServicesPermission

Access Directory services

DnsPermission

Resolve hostnames via DNS

EnvironmentPermission

Access (read/write) environment variables

EventLogPermission

Read or write event log entries

FileDialogPermission

Open a file dialog

FileIOPermission

Read/write files on disk

IsolatedStorageFilePermission

Access isolated storage

MessageQueuePermission

Access MSMQ queues and messages

OdbcPermission

Access ODBC data sources

OleDbPermission

Access OLE DB data sources

OraclePermission

Access an Oracle database server

PerformanceCounterPermission

Access performance counters

PrintingPermission

Access printer resources

ReflectionPermission

Access the metadata of other objects via Reflection

RegistryPermission

Access the system registry

SecurityPermission

Assert permissions and bypass other security measures

ServiceControllerPermission

Start and stop currently installed services via the ServiceController class

SocketPermission

Initiate or receive network data via sockets

SqlClientPermission

Access a SQL server database

UIPermission

Manipulate the user interface

WebPermission

Initiate or accept connections on a Web address

DbDataPermission

Abstract permission class from which you can inherit to create your own database access permission

IsolatedStoragePermission

Abstract permission class from which you can inherit to create your own isolated storage permission

ResourcePermissionBase

Abstract permission class from which you can inherit to create your own system resource access permission


Identity Permissions

When protecting your code from unauthorized use, it is often necessary to require that only calling code with a certain identity be given execute access to your code. For this purpose, and many others, there are identity permissions. Identity permissions are designed to represent various pieces of identity-related evidence that is associated with an assembly. Table 34.2 is a list of the identity permissions in the .NET Framework.

Table 34.2. Common Identity Permissions

Permission Class

Privilege Granted

PublisherIdentityPermission

Indicates the software publisher's digital signature.

SiteIdentityPermission

The identity of the website where the code originated.

StrongNameIdentityPermission

Refers to the strong name of an assembly.

URLIdentityPermission

The URL where the code originated. This is not the same as SiteIdentityPermission, and can be from any protocol such as HTTP, FTP, HTTPS, and so on.

ZoneIdentityPermission

Refers to the zone from which the code originated. Can be any of the following: Internet, Intranet, MyComputer, NoZone, trusted, Untrusted.


Role-Based Security Permissions

There is only one role-based security permission class within CAS: PrincipalPermission. This is an identity-style permission. Instead of checking for the identity of the calling code, it checks the identity of the current security context, allowing code to demand identity and role membership of the current security context.

    Team LiB
    Previous Section Next Section