|
Code Access Security
The C# Column - Yashawant Kanetkar
Code
Access Security is a new concept brought in by the .NET framework.
Code access security essentially involves granting permissions to
an assembly. Code access security uses the location of assembly
and other information about the identity of code as a primary factor
in determining permissions to be granted to the assembly. This information
about the identity of an assembly is called evidence.
Once loaded in runtime, the code starts
executing in the restricted environment depending upon permissions
granted to it. If the code is not trusted enough to run or runs
but performs an action for which it has no permissions, then a security
exception is thrown.
The code access security system means we
can stop running of malicious code and also restrict the code to
run in a restricted environment where we are sure that it won’t
do any damage to the resources. Let us now see few cases where code
access security becomes
crucial.
Suppose an organisation is working with
some extremely important data, we would use a code access security
system to state which code is allowed to access the database and
which is not. Similarly if we run an application from a network
drive and it tries to access the file on a local drive an exception
must be thrown. This can be done using a code access security system.
It is important to know that code access
security protects resources like local disk, network, user interface
from malicious code. It is not a tool for protecting software from
users.
Code access security works on the basis
of Code Groups and Permissions.
Code Groups
Code groups are a grouping of assemblies
with same privileges. For example, code groups include "Internet"
and "Intranet".
The group Internet includes code downloaded
from the Internet and the group Intranet includes code sourced from
the LAN. The information based on which the assemblies are grouped
is called evidence. The assembly loader is responsible for collecting
the evidence at load time, based on where the code is loaded from.
The Common Language Runtime (CLR) ships
with seven types of evidence, as listed in the table above. Collectively
these seven types of evidence are called ‘host evidence’ as they
are implemented by the host environment.
| Zone |
Region
from which the code originated |
| Site |
Website
from which the code was downloaded |
| URL |
Specific
location of the code |
| Application
Directory |
Location
of the assembly |
| Strong
name |
The unique
name for the code |
| Publisher |
Publisher
of the code |
| Hash
value |
Hash
value for the assembly |
Permission
Permission means authorisation to perform
actions. These actions often involve accessing certain resources.
These permissions are exposed programmatically through the System.Security.PermissionSet
namespace.
Whenever a code is running, the CLR has
to decide which permissions to grant that code and which ones to
deny. The CLR decides which permissions to grant and which to deny
by means of a simple trick, it checks whether the caller of our
code has the permission ‘perm1’ or not.
CLR repeats this process for the callers
of our assembly till no more callers are left. If all the callers
have that permission, our code is granted the requested permission.
This can be better explained by the following
example:
Consider an assembly A. which calls Assembly
B, and B in turn calls C. C finally calls our assembly D.
If assembly D demands a certain permission,
for example perm1, the CLR will first check whether our assembly’s
caller (C in this case) has the necessary permission.
If it has, the CLR further looks and checks
whether B has it or not. If B has that permission, the CLR finally
checks to see whether the root assembly A has the demanded permission.
If all of the preceding assemblies C, B and A have that permission,
our assembly is also granted the permission.
Even if any one intermediate assembly does
not have the demanded permission, our assembly is denied perm1.
This process of checking permissions of
all the parent assemblies is known as Stack Walking. Stack Walking
is a costly activity, but considering the gains it has to offer
in terms of security implementation, Microsoft decided to implement
it in the CLR.
Assemblies demand permissions when it is
clear that without those permissions the assembly will not execute.
Demanding permissions is done programmatically. The following program
shows us how.
Our program will read a file from the local
disk and display the first line. In our program we will demand complete
access to the ‘C:\ ’ drive. If the access demand is denied, an exception
will be raised which we will catch.
Create a Windows-based application and design
the form as shown in the picture.
Assign control names as follows:
- Text box: t
- Read button: bread
- Exit button: bexit.
Add the following code in the constructor of the
Form1 class just below the call to InitializeComponent( ) method.
FileIOPermission fp;
try
{
fp = new FileIOPermission(
FileIOPermissionAccess.AllAccess,
@"C:\ " );
fp.Demand();
}
catch ( Exception e1 )
{
MessageBox.Show ( e1.Message ) ;
}
Here we create a reference of type FileIOPermission.
We have initialised the reference in the try block.
In the constructor we have passed the AllAccess
enumerated type to specify that our code needs complete access permissions
to the ‘C:\ ’ drive of the machine where our application is to execute.
The constructor is followed by a demand for the above permission.
It is necessary to place the demand part
in a try-catch block because if the permission is denied, the Demand(
) method would raise an exception and our program would be terminated
abruptly.
Now add a handler for the Read button. Write
the code as shown below to it.
private void bread_Click
(object sender, EventArgs e)
{
StreamReader sr = new StreamReader ( "c:\ \ hi.txt" );
t.Text = sr.ReadLine();
sr.Close();
}
We have created a stream reader object to
read the "c:\ hi.txt" file. Next we have read a line from
that file and displayed it in the text box t.

Now add a handler for the Exit button and
call Dispose( ) method from it. Calling Dispose( ) would terminate
the application if the Exit button is clicked.
Finally add the following declarations at
the beginning of the program:
using System.IO ;
using System.Security ;
using System.Security.Permissions ;
Run this application in various scenarios,
like on the local machine with security on, local machine with security
off, copy it to another machine and run it from the remote computer.
Configure the security policy to give full trust for code from the
remote machine and run the program. Also try out running the program
from the remote computer with security switched off. To switch the
security on/off we can use the ‘caspol’ utility that is shipped
with Visual Studio.NET.
This exercise will give you a better insight
into the working of code access security.
 |
Yashavant Kanetkar, one of the first
Express Computer columnists, is an established software expert,
speaker and author with several best-sellers to his credit,
including titles like “Let Us C” and the “Fundas” series. Contact
him at kanet@nagpur.dot.net.in |
|