Permission Sets


Permission sets allow you to combine multiple IPermission objects together in a single group that can then be collectively manipulated via familiar methods , such as Deny, Demand , and Assert . You may recall we said earlier that you cannot call methods such as Deny and PermitOnly twice in the same stackframe unless there is an intervening reversion. That effectively means that you must work with a permission set if you want to work with two or more permissions at the same time in the same stackframe. We look at the PermissionSet example now, which uses the PermissionSet class to manage multiple permissions simultaneously .

The PermissionSet Class

The PermissionSet class has the same basic set of methods as the IPermission -derived classes that we have already seen, including Deny, Demand , and Assert . But in addition to those, it has the AddPermission method used to combine multiple permission objects into a collection. The IPermission interface includes all of the permission classes, such as FileIOPermission, UrlIdentityPermission , and so on.

 public virtual IPermission AddPermission(    IPermission perm ); 

Let's look now at an example in which we use a permission set to group together several permissions and deal with the collection as a single object.

THE PERMISSIONSET EXAMPLE

The PermissionSet example combines the three permissions EnvironmentPermission, FileIOPermission , and UIPermission into a single permission set. It provides a simple user interface for determining the aspects of these three permissions that are to be put into effect. The user interface also allows you to call on the Deny or PermitOnly methods of the permission set to demonstrate their effects. Finally, the user interface allows you to call on either of two methods that test the effect of the permission set on file access and environment variable access.

The fact that the program attempts to communicate the resulting effects via a message box also tests the effect of the UIPermission . By running this program and experimenting with the effects of the various checkboxes, you gain a sense of how a permission set works. By studying the EstablishPermissionSet, buttonAttemptFileAccess_Click , and buttonAttemptEnvVarAccess_Click methods in this program, you can learn how to achieve these effects within your own programs. Figure 8-21 shows the PermissionSet example with file read access denied , and Figure 8-22 shows the result of attempting file read access under that condition.

Figure 8-21. The PermissionSet example: Denying read access.

graphics/08fig21.gif

Figure 8-22. The PermissionSet example: Attempt File read access.

graphics/08fig22.gif

Here are the three significant method source code listings for this example.

 //PermissionSetForm.cs ... namespace PermissionSetForm {    ...    public class PermissionSetForm :       System.Windows.Forms.Form    {       ...       private void buttonAttemptFileAccess_Click(          object sender, System.EventArgs e)       {          //build perm set according to radio buttons          EstablishPermissionSet();          //Deny, or PermitOnly          if (radioButtonDeny.Checked)             ps.Deny();          if (radioButtonPermitOnly.Checked)             ps.PermitOnly();          //attempt to open or create file          FileStream fs = null; //for TestFile.txt file          try          {             fs = new FileStream(                "TestFile.txt",                FileMode.OpenOrCreate,                FileAccess.ReadWrite);          }          catch (Exception)          {          }          if (fs == null)          {             try             {                fs = new FileStream(                   "TestFile.txt",                   FileMode.OpenOrCreate,                   FileAccess.Read);             }             catch (Exception)             {             }          }          if (fs == null)          {             try             {                fs = new FileStream(                   "TestFile.txt",                   FileMode.OpenOrCreate,                   FileAccess.Write);             }             catch (Exception)             {             }          }          if (fs == null)          {             MessageBox.Show(                "FAILURE: open file");             return;          }          String strMessageBox =             "SUCCESS: open file" +             ", CanWrite: " + fs.CanWrite +             ", CanRead: " + fs.CanRead +             ".\n";          //attempt to write file          String strDataOut = "Some Data";          byte [] bytes=             Encoding.UTF8.GetBytes(strDataOut);          try          {             fs.Write(bytes, 0, bytes.Length);             strMessageBox += "SUCCESS: write file - "                + strDataOut + "\n";          }          catch (Exception)          {             strMessageBox +=                "FAILURE: write file.\n";          }          //attempt to read file          bytes = new byte[256];          try          {             fs.Seek(0, SeekOrigin.Begin);             fs.Read(bytes, 0, bytes.Length);             String strDataIn = Encoding.UTF8.GetString(                bytes, 0, bytes.Length);             strMessageBox +=                "SUCCESS: read file - " + strDataIn;          }          catch (Exception)          {             strMessageBox += "FAILURE: read file.\n";          }          //show result of attempts          MessageBox.Show(strMessageBox);          fs.Close();          //RevertDeny or RevertPermitOnly          if (radioButtonDeny.Checked)             CodeAccessPermission.RevertDeny();          if (radioButtonPermitOnly.Checked)             CodeAccessPermission.RevertPermitOnly();          //clean up permission set          DestroyPermissionSet();       }       private void buttonAttemptEnvVarAccess_Click(          object sender, System.EventArgs e)       {          //build perm set according to radio buttons          EstablishPermissionSet();          //Deny or PermitOnly          if (radioButtonDeny.Checked)             ps.Deny();          if (radioButtonPermitOnly.Checked)             ps.PermitOnly();          //attempt to read TEMP environment variable          String ev = null;          try          {             ev = Environment.GetEnvironmentVariable(                "TEMP");             //show result of attempt             MessageBox.Show(                "SUCCESS: read environment variable - " +                ev);          }          catch (Exception)          {             MessageBox.Show(                "FAILURE: read environment variable");          }          //RevertDeny or RevertPermitOnly          if (radioButtonDeny.Checked)             CodeAccessPermission.RevertDeny();          if (radioButtonPermitOnly.Checked)             CodeAccessPermission.RevertPermitOnly();          //clean up permission set          DestroyPermissionSet();       }       //build permission set according to radio buttons       private void EstablishPermissionSet()       {          ps = new PermissionSet(PermissionState.None);          //establish EnvironmentPermission          EnvironmentPermission ep =             new EnvironmentPermission(                EnvironmentPermissionAccess.NoAccess,                "TEMP");          if (checkBoxEnvironmentPermissionRead.Checked)          {             ep.AddPathList(                EnvironmentPermissionAccess.Read,                "TEMP");          }          ps.AddPermission(ep);          //establish FileIOPermission          FileIOPermission fp =             new FileIOPermission(                FileIOPermissionAccess.NoAccess,                Path.GetFullPath("TestFile.txt"));          if (checkBoxFileIOPermissionAccessRead.Checked)          {             fp.AddPathList(                FileIOPermissionAccess.Read,                Path.GetFullPath("TestFile.txt"));          }          if (checkBoxFileIOPermissionAccessWrite.Checked)          {             fp.AddPathList(                FileIOPermissionAccess.Write,                Path.GetFullPath("TestFile.txt"));          }          ps.AddPermission(fp);          //establish UIPermission          UIPermission  uip = new UIPermission(             UIPermissionWindow.NoWindows);          if (checkBoxAllWindows.Checked)          {             uip.Window =                UIPermissionWindow.AllWindows;          }          ps.AddPermission(uip);       }       void DestroyPermissionSet()       {          ps.RemovePermission(             typeof(EnvironmentPermission));          ps.RemovePermission(             typeof(FileIOPermission));          ps.RemovePermission(             typeof(UIPermission));          ps = null;       }       PermissionSet ps;    } } 

Defining a Permission Set in a Configuration File

Let's see how to configure security for an application by defining a permission set in an application configuration file, which can then be used by the application to grant or deny the permissions defined in the permission set. By configuring the security characteristics in an external XML-based application configuration file, the programmer has less to worry about, and the end user or administrator has greater flexibility in defining security policy for the application. Configuring security after deployment is a very powerful capability, especially considering that an application may be used in many situations that have very different security requirements.

THE CONFIGUREDFILEIOPERMISSION EXAMPLE

The ConfiguredFileIOPermission example is very much like the FileIOPermission example program we saw earlier in this chapter except that rather than creating a permission object programmatically, the permission [27] is defined in a permission set, which is defined in an XML application configuration file. This example is again composed of three separate projects. Two of them are DLLs, and one is an EXE project. One of the DLLs, AttemptIO , attempts to perform IO operations on a particular file, and the other, AvoidIO , does not attempt any IO. The EXE project, ConfiguredFileIOPermission , calls on the public methods, DoFileIO and DoNoFileIO , which are exposed by these two DLLs. Here is the source code for the two DLL projects, which is identical to the code we saw earlier in the FileIOPermission example.

[27] Actually, this example is slightly different from the FileIOPermission example in a couple of other subtle ways. Rather than working with a single independent permission, we instead work with a permission set containing the single permission. It may be worthwhile to compare this example program with the PermissionSet example program as well, since it shows how to work with a permission set directly in a programmatic manner as opposed to defining a permission set in an application configuration file. Also, whereas the FileIOPermission example disallowed all file IO privileges, this example is more selective in that it limits only read and write operations on a particular file.

 //AttemptIO.cs using System; using System.IO; public class AttemptIO {    public void  DoFileIO  ()    {       Console.WriteLine("DoFileIO called...");       String text = "Here is some data to write";       FileStream fs = new FileStream(          "outputdata.txt",          FileMode.Create, FileAccess.Write);       StreamWriter sw = new StreamWriter(fs);       sw.  Write  (text);       sw.Close();       fs.Close();       Console.WriteLine(          "Written to outputdata.txt: " + text);    } } //AvoidIO.CS using System; public class  AvoidIO  {    public void DoNoFileIO()    {       Console.WriteLine("DoNoFileIO called...");       Console.WriteLine("Nothing written.");    } } 

Here is the initial source code for the EXE project. As you can see, the code is almost the same as what we saw in the FileIOPermission example; however, there is a small yet significant difference. Unlike the previous example, this example does not create a FileIOPermission object directly in the source code. Instead, we have an attribute that denies the permission set defined in an XML file. We shall soon see how this permission set is defined within an application configuration file and brought into play within the program source code.

 //ConfiguredFileIOPermission.cs //must add ref to AvoidIO.dll //must add ref to AttemptIO.dll using System; using System.IO; using System.Security.Permissions; using System.Security; class FileIOPermissionExample {    public static void Main()    {       try       {          AvoidIO avoidio = new AvoidIO();          avoidio.  DoNoFileIO  ();          AttemptIO attemptio = new AttemptIO();          attemptio.  DoFileIO  ();       }       catch(SecurityException se)       {          Console.WriteLine(se.Message);       }    } } 

Before we get into configuring the permission set in the configuration file, let's look at the result of running this program without any permission set being defined. The result is shown in the following code, where you can see that the program does in fact perform IO on the file named outputdata.txt .

 DoNoFileIO called... Nothing written.  DoFileIO  called...  Written to outputdata.txt  : Here is some data to write 

Next, we create an XML file named MyPermissionSet.xml in the EXE project directory that will serve as an application configuration file for the program. The following XML shows the contents of this file. We use the PermissionSet tag to define a permission set, which in turn contains the IPermission tag to define a permission object that will be used to control access to the file named outputdata.txt . The full path is actually required, but we have shortened the path here so that the XML file can be displayed on this printed page. The permission specifies both read and write permissions on this file.

 <  PermissionSet  class="System.Security.NamedPermissionSet"    version="1"    Name="MyPermissionSet"    Description="My Permission set for outputdata.txt IO">    <  IPermission  class=       "System.Security.Permissions.FileIOPermission ...  Read="C:\OI\...\outputdata.txt  "  Write="C:\OI\...\outputdata.txt  "/> </PermissionSet> 

Now, for the permission set in this XML file to be used by the application, we use a PermissionSetAttribute attribute on the program's Main method, which will deny the access permission defined in the permission set. Again, the full path to the file named MyPermissionSet.xml is shortened for the printed page. You do not have to deny this permission set via an attribute, as shown here. You could just as easily have done this programmatically. The key difference that we are focusing on here is simply that the permission set is itself defined in a separate XML configuration file rather than in the actual program source code. This can buy us much flexibility, allowing security configuration decisions to be left until deployment time or even later.

 class FileIOPermissionExample {    //PermissionSetAttribute that denies the permissions    //defined in the MyPermissionSet.xml app config file  [PermissionSetAttribute(   SecurityAction.Deny,   File="C:\OI\...\MyPermissionSet.xml")]  public static void Main()    {       try       {          AvoidIO avoidio = new AvoidIO();          avoidio.DoNoFileIO();          AttemptIO attemptio = new AttemptIO();          attemptio.  DoFileIO  ();       }       catch(SecurityException se)       {          Console.WriteLine(se.Message);       }    } } 

When you run this program, you will see the following output. As you can see, the program now throws an exception when the attempt is made to perform IO on the specified file. The permission set denial is still made in our program source code, but the permission set itself is defined independently in the MyPermissionSet.xml file. Therefore, the permission set can be modified independently after compile time.

 DoNoFileIO called... Nothing written.  DoFileIO  called... Request for the permission of type    System.Security.Permissions.FileIOPermission,    mscorlib, Version=1.0.3300.0, Culture=neutral,    PublicKeyToken=b77a5c561934e089  failed  . 


.NET Security and Cryptography
.NET Security and Cryptography
ISBN: 013100851X
EAN: 2147483647
Year: 2003
Pages: 126

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net