In today's fast growing Information Technologyworld, security is a major concern. Security is important not just toauthenticate users but also to authorize their actions. Common businessscenarios where we need more control over security are
1. To restrict the user's access to the application, based on their identity
2. To restrict the user's access to protected resources and certain functions of the application.
3. To verify the identity of the calling program, to check if the caller is trusted or not.
In this article I will be taking a close lookat .NET Security. Code Access Security addresses these issues. Thefoundation of CAS is the Permission Object.
Download codeaccesssecurity.zip from attachments
Permission:
CLR requires that the code should have required permissions to accessthe protected resources. For example if the code has to read from anenvironment variable or write information to a file, the code shouldhave enough permission to perform these operations. Permission Objectsare used to enforce these security issues. Lets take a look at whatkind of Permission Objects are available in .Net and how we can usethem to secure our application. There are three different kinds ofpermission objects, each serving a specific purpose: IdentityPermission, Code Access Permission and Role Based Security Permission.
Identity Permission:
CLR validatesthe identity of the assembly provided to it by the loader or host. Thehost can be a server host (Asp.Net) or a shell host (command line). Theidentity, called the Evidence, can be a strong name(StrongNameIdentityPermission), originating Zone that is Intranet,Internet or Trusted site (ZoneIdentitypermission), publishers digitalsignature (PublisherIdentityPermission), originating URL(URLIdentityPermission) or originating website(WebSiteIdentityPermission). I will explain in detail with examples theformer two
StrongNameIdentityPermission:
Thispermission object identifies the caller with a strong name. In order tohave a strong name for your assembly, the code should be signed by akey pair. .Net provides the utility, sn.exe, to generate a key pair. sn-k KeyPairFileName.snk Once the keyfile is generated, you can place thefollowing line of code in AssemblyInfo.cs [assembly: AssemblyKeyFile(@"..\..\KeyPair.snk")] The above line will make sure that the assemblyis signed with a strong name.
Let us look at an example to understand how wecan use StrongNameIdentity Permission to identify the caller. Create aconsole application called TestPermissionObjects.exe. The assembly issigned with a strong name as shown above. We can demand the strong nameidentity permission in our component using the public key counter partof the key pair generated.
public bool TestStrongNameIDentityPermission(string strongname,string version)
{
try
{
byte[] publickey = { 0, 36, 0, 0, 4, 128, 0, 0, 148, 0, 0, 0, 6, 2, 0, 0, 0, 36, 0, 0, 82, 83,
65, 49, 0, 4, 0, 0, 1, 0, 1, 0, 45, 25, 102, 36, 141, 31, 69, 83, 150, 31, 81, 170, 101, 131,
2, 136, 254, 120, 34, 55, 22, 245, 242, 91, 151, 25, 32, 206, 224, 156, 198, 240, 123, 2, 52,
230, 50, 196, 88, 84, 15, 86, 232, 53, 147, 140, 161, 64, 59, 200, 217, 15, 237, 100, 152, 230,
19, 148, 160, 187, 218, 36, 45, 168, 159, 92, 13, 58, 46, 43, 195, 106, 134, 98, 68, 226, 206,
166, 236, 88, 33, 160, 82, 254, 165, 38, 19, 22, 64, 28, 247, 127, 175, 225, 92, 214, 63, 102,
232, 124, 196, 242, 22, 144, 31, 64, 92, 248, 164, 148, 109, 130, 18, 103, 206, 177, 173, 104,
190, 221, 164, 102, 34, 150, 110, 25, 127, 189 } ;
// publickey can be extracted using utility secutil.
// secutil -strongname AssemblyNameWithFulpath
StrongNamePublicKeyBlob publickeyblob = new StrongNamePublicKeyBlob (publickey);
System.Version ver = new Version(version);
StrongNameIdentityPermission sip = new StrongNameIdentityPermission(publickeyblob,strongname,ver);
sip.Demand();
return true ;
}
catch(SecurityException se)
{
Console.WriteLine ("Identity Permission Failed — Strong Name " + strongname + "–version — " + version );
return false;
}
}
Any client that is calling the above method ofthe component should have the strong name, key pair and correct versionotherwise the call to this method will throw a Security Exception.
ZoneIdentitytPermission:
Thispermission object identifies the caller with the zone the calloriginates from. Defined Security Zones are Internet, Intranet,MyComputer, NoZone, Trusted, and Untrusted. Code can demandZoneIdentityPermission to ensure that the caller is from the specifiedzone. The following example explains how to use ZoneIdentityPermissionobject to ensure that the callers are from the local computer, that isfrom the MyComputer zone.
public string TestZoneIdentityPermission()
{
ZoneIDentityPermission zip = new ZoneIdentityPermission(SecurityZone.MyComputer)
zip.Demand();
//The line below will succeed only if the calling code is from the zone MyComputer.
// If the same component is called from Intranet the call will fail.
StreamWriter sw = new StreamWriter("TestPermission.txt")
sw.write("Sucess ZoneIDentityPermisson");
sw.close();
}
PublisherIDentityPermission:
This permission object identifies the caller with the Digitalsignature. The caller should be signed with a Digital Certificate.
URLIdentityPermission:
This permission object identifies the caller with the URL from which the call originates.
SiteIdentityPermission: This permission object identifies the caller with the website from which the call originates.
Code Access Permission: Identifying the caller using identity permission is not adequate tosecure an application. Various resources like file, environment,variables and message queues should be protected along with thecritical operations that the code performs. These Security policies canbe enforced using CodeAccessPermission. There are variousCodeAcessPermission objects available in .NET such as FileIOPermission,EnvironmentPermission and EventlogPermission. For a list ofCodeAcessPermission refer tohttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguidnf/html/cpconidentitypermissions.asp
CodeAccessPermission object restricts accessto the protected resources, identifies if all the callers in the callstack have sufficient permission and provides functionality to createthe object from xml. These are basically the implementations of theinterfaces IstackWalk, Ipermission and IsecurityEncodable.IstackInterface implementation in CodeAcessPermission objects ensuresthat all callers in the hierarchy have enough permission to access theprotected resources. IPermission interface has the methods: Demand,Copy, Union, IsSubsetOf and Intersect. Every CodeAccessPermissionobject has this interface implemented and the client can call theDemand() method of the permission object to make certain that therequested permissions are available.
CodeAccessPermission can be implemented
in two ways. One is Imperative syntax and the other is Declarative syntax.
Imperative Syntax:
You can protectaccess to the resources and functions by creating an instance ofappropriate permission object and demanding the permission. Lets take alook at FileIOPermissionObject and how we can confine access to filesand folders.
public void TestFileIOPermission(string path , string filename)
{
try
{
FileIOPermission fip = new FileIOPermission(FileIOPermissionAccess.Read , path);
fip.PermitOnly();
StreamWriter sr = new StreamWriter (path +"\"+ filename);
sr.WriteLine ("FileIOPermision success");
sr.Close();
}
catch(SecurityException se)
{
Console.WriteLine (se.StackTrace);
}
}