Permissions-basically the rights to do something-are used in the .NET Framework
to implement security mechanisms in managed code. As the smallest unit of the
security system, permissions are the key concept upon which the whole security
system is based.
Developers can and should always request the permissions that the code will
need, even if they do not really need to make the request. This protects against
unexpected situations and makes the maintenance of an application easier for
both developers and administrators. Administrators too can assign permissions to
an application through code access security. Regardless of your position-
developer or administrator-you should
never request or grant more permission
than necessary. This protects the system from code segments accessing unknown
resources and helps developers find bugs earlier. You can think of this as a
type of defensive development.
Permissions are divided into three major groups: code access permissions,
identity permissions, and role-based permissions. Code access permissions
contain the set of permissions used to request the right to execute or access
protected operations or devices. As they are of central interest to software
developers and administrators, let's examine them first.
Code Access Permissions
Code access permissions are used to protect resources, devices, or operations
from unauthorized users. They represent the right to access or execute
something. Because code access permissions form a major part of the .NET
security system, developers and administrators must understand how these
permissions work.
Programmers who opt to use layering to simplify code may compromise security.
One layer can misuse the authorization or access it obtains, which can lead to
the compromise of another layer. In general, partially trusted code presents a
security risk. It can be disguised and manipulated to perform actions on behalf
of malicious code, even though the malicious code lacks permission to access the
demanded resource. Consequently, malicious code can achieve greater security
access than it should be allowed.
In .NET, code access security uses a stack-walking mechanism to defend the
system against such attacks. The CLR protects managed code by running a stack
walk on all calls. The stack walk checks that all code in the call stack of
functions has permission to access the implicitly or explicitly demanded
protected resource. Since any suspicious code, like all other code, resides
somewhere in the call stack, it cannot exceed its own cumulative or intersected
security permissions.
The stack walk mainly prevents an assembly with low authorization from calling a
highly trusted component to perform an action on its behalf that it would not
otherwise have permission to perform. Code access security uses a hidden code
manager to examine the stack for special security markers indicating permissions
granted to executing procedures. These markers may be allocated on the stack by
the JIT compiler and are accessible only through the hidden code manager.
Figure 22.6 illustrates the stack walk that results when a method in Assembly 3
demands that its callers (Assembly 2 and Assembly 1) have Permission X.
Figure 22.6: Permission Stack Walk
The runtime's security system patrols the call stack to determine whether code
is authorized to access a resource or perform an operation. It compares the
granted permissions of each caller to the permission being demanded. If any
caller in the call stack does not have the permission being demanded, a security
exception is thrown and access is refused. Demanding permissions of all callers
at runtime affects performance; however, it is essential to protect from attacks
by partially trusted code.
What is the sense in examining the whole call stack to determine if the
executing method should be granted the requested permission? Suppose you have a
component that accesses your corporate employee database. This works well for
your purposes, but what happens when another component connects to your database
component and misuses it? You certainly do not want to explain to your
supervisor how someone got confidential information through your component.
Because the security system makes sure that every callee in the chain has the
necessary permissions, this scenario, which presents a significant problem in
other common security systems, should not happen within the .NET architecture.
With the handling of permission requests, the security system checks not only
the actual context but also the whole environment in which a piece of code
executes. This major step toward secure execution of code protects the operating
system, your code, and the code that you access.
In general, it is desirable to have the CLR perform a stack walk whenever
permissions are requested; yet, in certain situations you may want to bypass
this stack walk. This gives other assemblies the opportunity to execute an
operation they are not authorized to perform. Stopping stack walk-ups for an
extra security check is possible by calling the Assert method of the
CodeAccessPermission object. As you will see later, use of the Assert method
also requires permissions.
Understanding the process by which the CLR grants or denies requests for code
access permissions starts with the administrator's actions. The administrator
creates code groups, which function as connectors between identities and code
access permissions. After creating a group, the administrator assigns some code
access permissions to that group. Whenever the CLR loads an assembly, it
examines evidence in the assembly to determine its identity and assigns the
assembly to a code group. A request is thus granted or denied by examining the
code access permissions of the code group to which the assembly belongs.
You can increase permissions for an assembly by following these steps: