User Tools

Site Tools


notes:csharp:code_access_security

Code Access Security in C#

Code access security (CAS) is used to restrict the resources and operations an application can access and execute.

CAS primarily affects library code and partially trusted applications. Library developers must protect their code from unauthorized access from partially trusted applications. Partially trusted applications are applications that are loaded from external sources such as the Internet. Applications that are installed on your desktop or on the local intranet run in full trust. Full-trust applications are not affected by code access security (unless they are marked as security-transparent) because they are fully trusted.

With CAS, applications running in a sandboxed environment such as Internet Explorer can be restricted on the types of resources they can access and the operations they can execute.

Each code access permission represents one of the following rights:

  • The right to access a protected resource, such as a file
  • The right to perform a protected operation, such as accessing unmanaged code

Functions performed by CAS:

  • Define permissions for accessing system resources.
  • Enable code to demand that its callers have specific permissions. For example, a library that exposes methods that create files should enforce that its callers have the right for file input/output.
  • Enable code to demand that its callers possess a digital signature. This way, code can make sure that it is only called by callers from a particular organization or location.
  • Enforce all those restrictions at runtime.

One important concept of CAS is that each and every element on the current call stack is checked. CAS walks the call stack and checks if every element on the stack has the required permissions. This way, a less-trusted method cannot call some restricted code through a trusted method.

The base class for CAS is System.Security.CodeAccessPermission. Permissions that inherit from CodeAccessPermission are FileIOPermission, ReflectionPermission, SecurityPermission, etc. When applying one of those permissions, you ask the CLR for the permission to execute a protected operation or access a resource.

You can specify CAS in two ways:

  • declarative - use attributes to apply security information to your code
  • imperative - explicitly ask for permissions in the code

Example - declarative CAS: Ask for the permission to read all local files by using the FileIOPermissionAttribute:

[FileIOPermission(SecurityAction.Demand, 
    AllLocalFiles = FileIOPermissionAccess.Read)]
public void DeclarativeCAS()
{ 
    // ... 
}

Example - imperative CAS: Create an instance of FileIOPermission and demand certain rights.

FileIOPermission f = new FileIOPermission(PermissionState.None); 
f.AllLocalFiles = FileIOPermissionAccess.Read;
try
{
    f.Demand();
}
catch (SecurityException s)
{
    Console.WriteLine(s.Message);
}

Example: Control permissions for resources by using the System.Security.Permission classes:

  • The application needs to have permission for file input and output operations in order to execute.
  • If file input and output permissions are not available, the application should not execute.

The SecurityAction.RequestMinimum value requests for the minimum set of permissions that are required by the application to execute. If these permissions are not available, the application will not execute.

Apply the following attribute at the assembly level to grant permission for file input and output operations in order to execute. If file input and output permissions are not available, the application should not execute:

[assembly:FileIOPermission(SecurityAction.RequestMinimum, Unrestricted = true)]

The SecurityAction.RequestRefuse value specifies the permissions that the application should not be granted:

[assembly:FileIOPermission(SecurityAction.RequestRefuse, Unrestricted = true)]

The SecurityAction.RequestOptional value specifies that the requested permissions are optional. The application executes but if the requested permissions are not available when needed, an exception is thrown.

[assembly:FileIOPermission(SecurityAction.RequestOptional, Unrestricted = true)]

Example: Combine PrincipalPermission objects:

// The identity strings name1 and name2 are always different. 
PrincipalPermission principalPerm1 = new PrincipalPermission(name1, role1); 
PrincipalPermission principalPerm2 = new PrincipalPermission(name2, role2); 
 
// Make sure that both name1 and name2 belong to the same security role. 
// The Union method takes a permission object and returns a permission object that represents all 
// permissions for that permission object and the current object. 
(principalPerm1.Union(principalPerm2)).Demand();
 
// The Intersect method intersects identity and roles independent of each other. If the identities are different, 
// their interaction will be identity="", which is an unauthenticated user. 
(principalPerm1.Intersect(principalPerm2)).Demand();
 
// Determine if one PrincipalPermission class is a full subset of another PrincipalPermission class. 
principalPerm1.IsSubsetOf(principalPerm2);

Links

notes/csharp/code_access_security.txt · Last modified: 2018/01/09 by leszek