n case you ask yourself how this security
model can be useful, just consider if the Windows operating system could
currently apply a CAS such that no code downloaded from the Internet as a mail
attachment was allowed to run (no matter if who’s running Outlook Express is the
computer administrator). Got the point? No mail virus would have ever appeared.
CAS Code Evidence
The first problem that arises when defining a
security model on "block of codes" is to define the entity to apply security
checks on, since code has nothing like a unique "user identity" (aka
principal) as we can find in NTLM, Kerberos or any standard security model.
CAS identifies an assembly on its evidence,
that is, a list of property nameproperty value pair that describes it. The
CLR comes with a predefined set of "evidence categories" as listed in the
following table
| Evidence | Description |
| Application directory | The application's installation directory |
| Hash | Cryptographic hash such as SHA1 |
| Publisher | Software publisher signature; that is, the Authenticode signer of the code |
| Site | Site of origin, such as http://www.microsoft.com |
| Strong name | Cryptographically strong name of the assembly |
| URL | URL of origin |
| Zone | Zone of origin, such as Internet Zone |
Here is a sample of the evidence list that makes an assembly identity.
| Evidence Category | Evidence Value |
| Strong name | Public key: 01 34 67 9A
CD Simple name: TestApp Version: 1.0.0.0 |
| URL | http://www.microsoft.com/test/application.exe |
| Site | www.microsoft.com |
| Zone | Internet |
| Publisher | <none> (no Authenticode signature) |
Note that not all the assemblies have the same set of evidence since it depends
on the host loading the assembly (for instance an assembly loaded from the file
system will have no site evidence associated with it).
Know that some evidences are stronger then
other, depending on how easy they can be tampered. For instance, the strong name
evidence of an assembly is stronger then its site evidence (Websites and DNS can
be hacked). It’s also possible to define custom application or system based
evidence types. See the IEvidence interface on the .NET framework SDK for
more info.
CAS Code Permissions
Now that we’ve assessed what we mean for an assembly identity we move on
examining the kind of code permissions the CAS can deal with. We’ll then soon
move to the next paragraph, where will examine how permissions are associated to
code evidence.
In the table that follows you can see a list of the built in access
permissions.
All the permissions in this list have a counterpart security class gathered in
the System.Security.Permissions namespace. As you can see in the table, code
access permissions are very grained, nevertheless, it’s possible to define your
custom access permissions in the situation where built-in permissions cannot
fulfill your needs. See
Creating Your Own Code Access Permissions on the MSDN library for more info.
| Code access permission | Resource protected |
| DirectoryServicesPermission | Directory services |
| DNS services | |
| EnvironmentPermission | Environment variables |
| EventLogPermission | Event logs |
| FileDialogPermission | File dialog boxes in the UI |
| FileIOPermission | Files and folders on the file system |
| IsolatedStorgeFilePermission | Isolated storage |
| MessageQueuePermission | Message queues |
| OleDbPermission | Databases accessed by the OLEDB data access provider |
| PerformanceCounterPermission | Performance counters |
| PrintingPermission | Printers |
| ReflectionPermission | Type information at run time |
| RegistryPermission | Registry |
| SecurityPermission | Execute code, assert permissions, call unmanaged code, skip verification, and other rights |
| ServiceControllerPermission | Running or stopping services |
| SocketPermission | Connections to other computers via sockets |
| SqlClientPermission | Databases accessed by the SQL Server data access provider |
| UIPermission | Windows and other UI elements |
| WebPermission | Connections to other computers via HTTP |
Permissions Sets, Code Groups, and Code Access Policies
Code groups are the building blocks of security
policies. A Code Group is made of an association between an evidence value,
also known in this case as a membership condition, and a permission set
(that gathers together a set of permissions).
For instance, a fictitious code group could be the WindowsUpdate code group
defined as
URL=http://www.microsoft.com (evidence membership condition) / Everything (permission set).
A hierarchical structure of Code Groups defines a security
policy. The .NET framework comes with three different security policies:
Enterprise, Machine, User. Additionally an host can define application
domain-level policy by calling the AppDomain.SetAppDomainPolicy method on
the System.AppDomain class. The first three policies are typically set by
administrator while the latter is eventually defined by developers.
The .NET framework comes with a number of built-in permission sets as shown
below.
You can define additional custom permission sets if
necessary gathering together the desired code access permissions listed in the
previous paragraph. Note that you cannot assign directly a list of permission to
a membership condition to define a Code Group.
Custom permission sets are defined in XML files and then loaded in the desired
policy.
The code permissions an assembly is granted is made of the intersection of the permissions each policy assign to the assembly (unless the -Levelfinal attribute is specified). The order of policy level evaluation for the LevelFinal attribute is enterprise, machine, and then user. The application domain policy level, if present, is always intersected with other levels even if the LevelFinal attribute is in effect for one of those levels.
Now there is just thing left to explain: How a policy is
applied to a given assembly, that is, how each policy, separately, builds up the
list of permissions sets an assembly is granted. The procedure is as follows:
This logic is described graphically in the picture below,
where green blocks represent granted membership; red blocks represent denied
membership and yellow ones are code groups that are not evaluated.

Code groups, permission sets and policy
structures can be queried and modified using the caspol.exe command line tool or
using a much more friendly tool called the Microsoft .NET Framework
Configuration Management Console snap-in.
Here I’ve included a snapshot of the CAS entities as shown by the snap-in

Code Access Permission Requests
CAS let’s you declare via a set of attributes at assembly level what permissions
(or permissions sets) your code
thus interacting/modifying the permissions assigned by the evidence vs. security
policy mechanism described in the previous chapters.
In this code snippet a VB.NET assembly refuses the permissions associated with
the FullTrust permission set and requires the File I/O permission.
<assembly: FileIOPermission(SecurityAction.RequestMinimum, Unrestricted :=
True)>
<assembly: PermissionSetAttribute(SecurityAction.RequestRefuse, Name :=
"FullTrust")>
When the CLR loads the assembly it evaluates the assembly permission requests
against the permissions that have been assigned to it by CAS policies. If the
assembly has not been granted the RequestMinimum permissions the assembly won’t
load and an exception will be thrown, additionally the CLR will, eventually,
remove permissions that have been granted to the assembly due its evidence but
that have been explicitly refused by RequestRefuse declarations.
CAS Requests are not compulsory, still there are number of reason why you would
won’t to evaluate to use them: the main reason is to avoid having to assembly
loaded if the permissions restrictions would make its functionalities
unacceptably limited.
Moreover, when declaring CAS requests your code is not required to gracefully
handle any and all situations where not being granted some permission might
prevent it from executing properly.
One last advantage is that putting permissions requests into the assembly
metadata let administrators easily explore the assembly requirements with the
Permission View tool (Permview.exe) to adjust, eventually, security
policies.
Code Security Demands
What we’ve covered till at this point is just half of the
story. You might have been asking yourself: what if an evil component calls into
a trusted component and ask to perform some sensitive tasks on its behalf ?
Enter Security Demands.
When placing Imperative or Declarative security demands on your code you
enforce only assemblies that have been granted the demanded permissions
(according to their evidence) to call into your code.
Security Demands have the CLR parse the whole call stack to check if all the
assemblies involved in the call have the required permission.
Making Declarative Security Demands is done using the standard attribute based
mechanism and it can be done at assembly, class and method level specifying
SecurityAction.Demand.
<FileIOPermission(SecurityAction.Demand, Unrestricted := True)>
Public Shared Function ReadData() As String
...
End Function
In the following code snippet the same permission
demand is executed imperatively
Public Shared Sub ReadData()
Dim MyFileIOPermission As New FileIOPermission (PermissionState.Unrestricted)
MyFileIOPermission.Demand()
End Sub
There are actually other two Security demands type in
addition to the one described above: Link demand and Inheritance
demand.
Overriding Demands Checks
There might be situations where you might want have your code
perform (directly or calling into other assemblies) some actions that require
permissions other assemblies in the upper call stack should not necessarily
have.
For instance: assembly A is used as an entry point for
assembly B downloaded from the internet. Among other things assembly A calls
into assembly C that writes some info into a log file.
If assembly B makes a FileIO security request, this security request would fail
since, walking up the call stack, the CLR would find that assembly A is not
allowed to perform such action.
To have CAS stop walking the stack on a specific permission check request, the
assert method come to rescue: assembly A will call
<FileIOPermission(SecurityAction.Assert, All := "C:\Log.txt")> _
Public Sub MakeLog()
or, imperatively:
Dim MyFileIOPermission As New FileIOPermission (PermissionState.Unrestricted)
MyFileIOPermission.Assert()
Of course, Assert is ignored when called against a permission
not granted to the assembly trying to asserting it.
Calling SecurityAction.Deny on the permission class
object has the opposite effect of calling Assert: it blocks a stack walk
on the method that called deny, even if the assembly had enough rights to have
the security check succeed.
Finally, calling SecurityAction.PermitOnly is similar to Deny: in
both cause stack walks to fail when they would otherwise succeed.
The difference is that Deny specifies permissions that will cause the
stack walk to fail, but PermitOnly specifies the only permissions that do
not cause the stack walk to fail.
In the following picture the net effect on the permissions available after a
call to Assert, Deny or Permitonly is shown graphically.

Conclusions
Literature on code access security is still rather scarce at
present. Certainly this feature lets us tighten the security of our
applications, covering security domains where identity based security is
inadequate or inappropriate.
I bet all of you have thought of a couple of situations where CAS could have
been helpful in your previous projects, the .NET programmer community will learn
in the future the best effective way to take full advantage of this new feature.
| DevX is a division of Internet.com. © Copyright 2010 Internet.com. All Rights Reserved. Legal Notices |