Secure
ASP.NET
LANGUAGES: ALL
ASP.NET VERSIONS: 1.1
Protecting Resources with Permission Objects
Clarify, Don t Conflict
By Don Kiely
One of the things that wasn t
initially clear to me about CAS permissions is that they are used in two basic
ways: 1) to protect resources, and 2) to determine whether calling code has the
permission it needs to access the protected resource. Without keeping that
distinction crystal clear, permissions can be a sticky morass of seemingly
conflicting details. Fortunately, most of the code that goes into custom .NET
applications is not protecting a resource directly, so you can focus your
efforts on one use of permissions.
In this installation of columns about .NET permissions, I ll
look at using permission classes to protect resources. Next time I ll look at
the other side namely, how to make the calling code handle permission
requirements gracefully.
System.Security.CodeAccessPermission is the mother of most
permission objects in .NET, so we ll start there to develop an understanding of
how permissions can protect a resource. It has three broad groups of methods
you can use:
- Resource protection, such as Assert, Demand, and
Deny. These methods specify how far up the call stack the code has the
specified permission. More about these later in this column.
- Permission set manipulation, such as Intersect,
IsSubsetOf, and Union. These methods let you hook into
security policy that defines multiple permissions to extract another permission
set. I ll delve into these in a future column.
- Other generic object methods, such as Copy and
ToString. These are the methods that are incidental to the CodeAccessPermission
class as a .NET object. I ll not explore these any further since they are not
directly related to code access security.
Keep in mind, of course, that permission objects that
derive from CodeAccessPermission can and do add to this basic interface.
The most important part of the CodeAccessPermission
interface, as well as for other permission objects, is that they implement the IPermission
interface. IPermission requires implementations of the Copy, Demand, Intersect,
IsSubsetOf, and Union methods, then build on that
minimal interface.
Let s say that you re writing a Web application that makes
use of your company s highly sensitive and secret algorithms for finding out
who is a person s secret Santa. This is highly privileged information obviously!
so you want to allow only the elite members of the
SecretSantaAdmin group on the domain to have access to the information. Furthermore,
this information is SO secretive that you practice defense in depth and
implement Windows-integrated security for the ASP.NET application, but you also
need to make sure that the GetSecretSanta method can be executed only by the
admin group.
The code to protect the secret algorithms is actually very
simple. This is the complete GetSecretSanta method, which takes an employee
name as input and returns that person s secret Santa:
Private Function GetSecretSanta(ByVal sEmpName As String) As
String
Dim pp As New
PrincipalPermission(Nothing, "RIVERCHASER\SecretSantaAdmin")
pp.Demand()
'Do the secret stuff
Dim sSanta As String
Select Case sEmpName
Case "Carol"
sSanta =
"Don"
Case Else
sSanta =
"Sorry! No Santa for that employee!"
End Select
Return sSanta
End Function
The important part of the code is these two lines:
Dim pp As New PrincipalPermission(Nothing, "RIVERCHASER\SecretSantaAdmin")
pp.Demand()
The first line instantiates a
System.Security.Permissions.PrincipalPermission class. This permission
class does not derive from the CodeAccessPermission class because it interacts
directly with the Windows security system. The first parameter in the
constructor used here takes a user name and the second is either a local or
domain group name. You can specify either parameter or both, so here the code
uses Nothing for the user name and a string for the
domain (RIVERCHASER) group.
After the permission object is instantiated, the call to
the Demand method is the step that enforces that this method is runable only by
members of the specified group. At this point the Common Language Runtime (CLR)
makes sure that the code is running by a member of the specified group. If it
isn t, the code throws a catchable SecurityException with a message Request
for principal permission failed. Robust applications would, of course, catch
that exception and handle it in some way.
You can do the same sort of demand declaratively using a
method attribute:
<PrincipalPermissionAttribute(SecurityAction.Demand,
Role:="RIVERCHASER\SecretSantaAdmin")> _
Private Function GetSecretSanta(ByVal sEmpName As String) As
String
In this case, you can use named parameters in VB.NET to
avoid passing Nothing as the user name.
And that s all there is to it! The secrets of the secret
Santa are safe for another year.
Next time I ll explore how to interact with permissions
from the calling code s point of view, then follow up
with an exploration of stack walks.
Don Kiely
is senior technology consultant for Information Insights, a business and
technology consultancy in Fairbanks, AK. E-mail him at mailto:donkiely@computer.org.