Code Access Security - A

 

We first run Visual Studio .net and click on menu File, New, Project and choose C# and Windows Applications, call the project name c2 and the location c:\s4 and then click on OK. We next drag and drop a button into the form and then double click on the button and write out the following lines of code.

 

using System.IO;

 

private void button1_Click(object sender, EventArgs e)

{

StreamReader f = new StreamReader(“C:\\a.txt”);

char[] b = new char[100];

f.ReadBlock(b, 0, b.Length);

}

 

All that we do is use the StreamReader class to read the file called a.txt in the root directory c:\. We first pass the full path name of the file c:\\a.txt to the StreamReader constructor and then use the ReadBlock function to read up to 100 bytes into the char buffer b. This class comes from the System.IO namespace. When we run the program and click on the button we get no error as we already have created a file a.txt in the root.

 

Now lets use the Code Access Security feature of .net to make sure that if the user tries to open any other file, an exception should be thrown. We also created a file b.txt in the root which our program is able to open. Replace a.txt with b.txt and we will get no error.

 

Visual Studio .net creates a directory structure C:\s4\s2\s2 for us and within this is a directory properties which has a file assemblyInfo.cs. We click on menu View, Solution explorer and then in the solution c2, we click on the plus of properties and then double click on the file assemblyInfo.cs. This brings us the code of the cs program. Here we write out a single line of code.

 

[assembly: AssemblyKeyFile("a.snk")]

 

When we now press F5 to run the program, we get an error, cannot find file. We now move to the directory C:\s4\c2\c2 and run the following command.

 

Sn –k a.snk

 

Sn is the strong name utility supplied by Microsoft and the –k option generates the file a.snk which has a key that we will explain later.

We now click on the Windows Start menu, Programs, Adminstrative Tools, .net 2.0 Configuration. This brings up a program that allows us to configure .net. We see two panes and on the left pane we see My Computer and click on the plus sign to expand it. We now see another plus on Runtime Security Policy and expand it. We then click on plus of machine and then right mouse button on permission sets, and then choose new. For the name of the permission we write vijayp2, any name will do and for the description, we leave it to you.  We click on next and at this dialog box we do first choose security from the left pane and then click on button Add >>. We see another dialog box and select the first check box only Enable Assembly execution. We then click on Ok and then finish. We have created a new permission set called vijayp2.

 

We then click on the plus of the option above Code Groups and then right mouse button on all_code, where we choose new. For the name of code group we write c2, description as usual we elave to you and click on next. For the condition type we choose the strong name option after click on the list box down arrow.

 

This opens up two text boxes and instead of writing something we click on button import.  Here we navigate to where our exe file is stored i.e. C:\s4\c2\c2\bin\debug and select the file c2.exe. The public key text box gets filled up with a value. This is how we associate the code group with our file c2.exe.

 

We click on next and for the permission set we use the premisiion we created vijayc2 by choosing it from the drop down list box. We then click on finish. We then click on copy of c2 in all_code with the right mouse button and then choose properties. Here we choose the first check box at the bottom, This policy level will only have . We then close the configuration manager or else the settings do not take effect. When we run the application an exception is thrown and we have to choose menu Debug, End debuging.

 

The reason we get an error is that we have not allowed any user interface to run. We start the configuration manager, come to our permissions vijayp2 and click on right mouse button, change permissions. We choose user interface from the left pane and once click on Add >>. At the dialog box shown we chose safe top level windows from the list box, click on ok and then finish and close the manager.

 

At times run the application twice and the error goes away. Now we get no error as we are allowed to have a top level window. We see a information message and when we click on the button, we see the same exception window now saying no file permissions. We once again choose menu Debug, End debugging.

 

We now need to add File permissions so we go back to the maanger, choose vijayp2, then choose File Io and click on Add. For the first column we write the File name c:\a.txt and then choose the check box Read, click on Ok, Finish and close the manager.

 

We always run the program twice as for some reason things do not work the first time. We see the same information message and when we click on the button, no exception is thrown. We are thus allowed to read the file a.txt. We change the nameto b.txt and we get an exception thrown.

 

      private void button1_Click(object sender, EventArgs e)

            {

                  try

                  {

                        StreamReader f = new StreamReader("c:\\a.txt");

                        char[] b = new char[100];

                        f.ReadBlock(b, 0, b.Length);

                        MessageBox.Show("All Ok");

                  }

                  catch (Exception ee)

                  {

                        MessageBox.Show(ee.Message);

                  }

            }

 

We add some exception handling code so that we handle the exception ourselves. When we use the file name a.txt we get the All Ok messaage box, if we use the name b.txt we get the messagebox of the catch called. Even if we use a non existentent file name like c.txt we get a file permission exception thrown. Thus we are able to make sure that our application can only open the file a.txt.

 

We now bring in a textbox from the toolbox that is called textbox1 and change a single line of code to

 

StreamReader f = new StreamReader(textBox1.Text);

 

Now when we run our program we write c:\a.txt in the textbox and then click on the button. We get th eok message box, any other file name written by us in the text box gives us an error. This is how we make sure that our program accesses only those files names that he is autbhorized to.

 

[FileIOPermission(System.Security.Permissions.SecurityAction.Demand,Read = @"C:\b.txt")]

public partial class Form1 : Form

 

We add the attribute FileIOPermission to the class Form1 in file Form1.cs. This attribute belongs to the System.Security.Permissions namespace and we have to add the following to our code.

 

using System.Security.Permissions;

 

Now when we run our program we get a exception thrown at runtime, we do not even get to see our initial window at all. We as always choose menu debug, stop debugging. The Demand enum value tells the framework to demand the security permissions and if not availa ble do not allow the application to start.

 

We then specify the rights on which file, we are asking for Read rights on C:\b.txt that our assembly does not have at all. Change the file name to a.txt and we get no exception thrown at all. Remove the attribute from the class and now double click on the form in design mode and write out the function as

 

private void Form1_Load(object sender, EventArgs e)

{

FileIOPermission f = new FileIOPermission( FileIOPermissionAccess.Read, @"C:\b.txt");

try

{

f.Demand();

MessageBox.Show("Permission OK");

}

catch (Exception ee)

{

MessageBox.Show(ee.Message, "form1");

}

}

 

One of the first functions to be called is Form1_Load and instaed of using attributes we check for permissions ourselves. We first create a instance of the FileIOPermission and specify what type of permissions we want on the file. We use the enum value Read and then the name of the file b.txt. The demand function actually chacks if we have the read permission on the file. As we do not the exception gets thrown.

 

We change the value of the file name to a.txt and the exception does not thrown. We do not handle the exception and normally we should not let th eprogram proceed, we should quit out. If we change the enum value Read to AllAccess, we will again get a error as we only have read access to the file, not write. Thus we do the same thing that attributes do but now with our own code.

 

We remove the code we have written in the Form_Load function and write out two lines of code in the assemblyinfo.cs which is present in the properties item in the solution explorer.

 

using System.Security.Permissions;

 

[assembly: FileIOPermission(SecurityAction.RequestMinimum, Read=@"C:/a.txt")]

 

When we run our program nothing happens and all works as advertised. This is because we have read permissions on the file C:/a.txt. We change the above line as follows

 

[assembly: FileIOPermission(SecurityAction.RequestMinimum, Write=@"C:/a.txt")]

 

As we do not have write permission on the file a.txt we get our familiar exception thrown before we can see our window. The requestminimum enum value means that this is the minimum permissions we require or else do not run our program.

 

We change it to the following and once again get an error.

 

[assembly: FileIOPermission(SecurityAction.RequestMinimum, Read=@"C:/b.txt")]

 

This time we get an error as we do not have read access on b.txt only a.txt. This is a good thing to do as before our code starts we know that we are not allowed access to resources as we do not have permission to do so.

 

[assembly: RegistryPermission(SecurityAction.RequestMinimum,Read=@"HKEY_LOCAL_MACHINE\SOFTWARE")]

 

We now add the above assembly attribute that uses the RegistryPermissions to allow access to the software key in the registry. As we have no such access permission from the configuration manager, we get a exception thrown at runtime. We now run the configuration manager, choose my computer plus, then plus on security policy and then plus on machine, permission sets. Here we choose permission vijayp2 and then right mouse button change permissions. In the dialog box we choose Registry and then clcik on Add >>. We see a similair dialog box as for IO permissions, we write our registry key HKEY_CLASSES_ROOT\SOFTWARE and seelct the check box Read. We click on Finish and Ok and close the manager. We run our program twice and we get no exception thrown as we are allowed to access the registry now.

 

using System;

using System.Windows.Forms;

using System.Drawing;

using System.IO;

using System.Security.Permissions;

using System.Reflection;

using System.Runtime.InteropServices;

[assembly: AssemblyKeyFile("a.snk")]

public class zzz : Form

{

Button b;

TextBox t;

static void Main()

{

Application.Run(new zzz());

}

public zzz()

{

b = new Button();

t = new TextBox();

b.Location = new Point(78, 59);

b.Text = "button1";

b.Click += new System.EventHandler(abc);

t.Location = new Point(98, 116);

Controls.Add(t);

Controls.Add(b);

}

private void abc(object o, EventArgs e)

{

try

{

StreamReader f = new StreamReader(t.Text);

char[] b = new char[100];

f.ReadBlock(b, 0, b.Length);

MessageBox.Show("All Ok");

}

catch (Exception ee)

{

MessageBox.Show(ee.Message);

}

}

}

 

 

 

Code Access Security

 

We first create a Visual Studio project by using menu File, New, Project, Class library name zzz and  under the s4 directory and write the following lines of code in the file Class1.cs

Class1.cs

public class Class1

      {

            public void a1()

            {

                  System.Console.WriteLine("a1");

            }

            public void a2()

            {

                  System.Console.WriteLine("a2");

            }

 

}

Nothing to explain in this program, all that we have a simple class Class1 that has two functions a1 and a2. We compile this into a dll by using the menu option build followed by  build.

 

We then load Visual Studio.Net and chooses menu, File, New , Project, Console  Application C# and give c6 as the name and c:\s4 as the location. We click on OK In the main function we would like to call the above two functions. We first call the Solution Explorer and then right click on the References item. We choose the first item Add Reference and choose the tab browse. Here we navigate to the file a.dll placed in the directory c:\s4\zzz\zzz\bin\debug\zzz.dll.

 

In the references tab we now see a list of dll’s with our a.dll heading the list. We now write the following code in main.

 

      static void Main(string[] args)

            {

                        zzz.Class1 a = new zzz.Class1();                a.a1();

                  a.a2();

            }

 

To run the we physically go into the directory c:\s4\c6\c6\bin\debug and execute the file c6.exe. Here we see that both a1 and a2 functions get called. We now repeat the same procedure once again but now call the project c7. Eevrything remains the same but the name. The point is that both c6 and c7 are allowed to call the code from the dll. Let us now restrict this code from being called by c6.

 

We first move into the directory c:\s4\ and run the following command

 

Sn –k dll.snk

 

This creates a file first.snk in the directory c:\s4, in which we ran the program, sn means string name. This file is 596 bytes large and contains some keys that we will explain later. We want our dll to be identified with this number or public key. We open our dll project zzz and then we click on the plus of properties in the solution explorer and then double click on the only file name displayed assemblyinfo.cs. We add the following line of code in it.

 

[assembly: AssemblyKeyFile("c:\\s4\\dll.snk")]

 

We have asscoiated our dll with the strong name stored in the file dll.snk. We once again move to c:\s4 and run the stong name utility as

 

Sn –k exe.snk

 

This creates one more snk file exe.snk for us and we now open the project c6 and double click on the file assemblyinfo.cs.   Here we write the same line as above but with a change in file name only.

 

When we run the exe file by pressing F5 we get no error and for the momemt nothing seems amiss. We now move back to our dll and write the following lines of code.