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:[email protected].