This section looks at the most common type of permissions - programmatic access - and how they are used. This example uses a Windows Form with four buttons on it. This Windows Form illustrates the concept previously mentioned - namely, that when a method fails, an exception object is generated, which contains your feedback. Note at this point that in the case of a real-world example, you would be setting up permissions for a calling application. In many instances, you don’t want a calling application to be able to access the registry, or you want a calling application to be able to read memory variables, but not change them.
However, in order to demonstrate the syntax of the commands, in the examples that follow we have placed the attempts against the objects we have secured in the same module. We first set up the permission that we want and grant the code the appropriate access level we wish it to be able to utilize. Then we use code that accesses our security object to illustrate the effect our permissions have on the code that accesses the objects. We’ll also be tying together many of the concepts discussed so far by way of these examples.
To begin, let’s look at an example of trying to access a file in the file system, which illustrates the use of the FileIOPermission class in our Permissions namespace. In the first example, the file C:\testse- curity\testing.txt has been secured at the operating system level so that no one can access it. In order to do this, the system administrator sets the operating system security on the file to no access:
Imports System.Security.Principal Imports System.Security.Permissions Imports System.IO Private Sub FileIO_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles FileIO.Click Dim oFp As FileIOPermission = New _ FileIOPermission(FileIOPermissionAccess.Write, "C:\testsecurity\testing.txt") oFp.Assert() Try Dim objWriter As New IO.StreamWriter _ (File.Open("C:\testsecurity\testing.txt", IO.FileMode.Open)) objWriter.WriteLine("Hi there!") objWriter.Flush() objWriter.Close() objWriter = Nothing Catch objA As System.Exception MessageBox.Show(objA.Message) End Try End Sub
Let’s walk through the code. In this example, we are going to attempt to open a file in the C:\testse- curity directory called testing.txt. We set the file access permissions within our code so that the method, irrespective of who called it, should be able to get to it with the following lines:
Dim oFp As FileIOPermission = New _ FileIOPermission(FileIOPermissionAccess.Write, "C:\testsecurity\testing.txt") oFp.Assert()
This example used the Assert() method, which declares that the resource should be accessible even if the caller has not been granted permission to access the resource. However, in this case, because the file is secured at the operating system level (by the system administrator), we get the error shown in Figure 12-2, which was caught by exception handling.
Figure 12-2
Now let’s look at that example again with full operating system rights, but the code permissions set to Deny:
Protected Sub btnFileIO_Click(ByVal sender As Object, ByVal e As System.EventArgs) Dim oFp As FileIOPermission = New _ FileIOPermission(FileIOPermissionAccess.Write, _ "C:\testsecurity\testing.txt") oFp.Deny() Try Dim objWriter As New IO.StreamWriter _ (File.Open("C:\testsecurity\testing.txt", _ IO.FileMode.Open)) objwriter.WriteLine("Hi There!") objWriter.Flush() objWriter.Close() objWriter = Nothing Catch objA As System.Exception messagebox.Show(objA.Message) End Try End Sub
The Deny() method denies all callers access to the object, regardless of whether the operating system granted them permission. This is usually a good thing to put into place, as not every method you implement needs full and unfettered access to system resources. This helps prevent accidental security vulnerabilities that your method may expose. With the Deny() method, we catch the error shown in Figure 12-3 in the exception handler.
Figure 12-3
As you can see, this error differs from the first by reflecting a System.Security.Permissions .FileIOPermission failure, as opposed to an OS-level exception.
The following example shows how you would use the EnvironmentPermission class of the namespace to look at EnvironmentVariables:
Protected Sub TestEnvironmentPermissions_Click _ (ByVal sender As Object, ByVal e As System.EventArgs) _ Handles TestEnvironmentPermissions.Click Dim oEp As EnvironmentPermission = New EnvironmentPermission _ (EnvironmentPermissionAccess.Read, "Temp") Dim sEv As String oEp.Assert() Try sEv = Environment.GetEnvironmentVariable("Temp") MessageBox.Show("Assert was a success") Catch objA As System.Exception MessageBox.Show("Assert failed") End Try System.Security.CodeAccessPermission.RevertAssert() oEp.Deny() Try sEv = Environment.GetEnvironmentVariable("Temp") MessageBox.Show("Deny was a success") Catch objA As System.Exception MessageBox.Show("Deny failed") End Try MessageBox.Show(oEp.ToString) End Sub
There is a lot going on in this example, so consider it carefully. We first establish an environment variable permission and use the Assert() method to ensure access to the code that follows:
Dim oEp As EnvironmentPermission = New EnvironmentPermission _ (EnvironmentPermissionAccess.Read, "Temp") Dim sEv As String oEp.Assert()
We then try to read the environment variable into a string. If the string read succeeds, then we then pop up a message box to reflect the success. If the read fails, a message box reflects the failure:
Try sEv = Environment.GetEnvironmentVariable("Temp") MessageBox.Show("Assert was a success") Catch objA As System.Exception MessageBox.Show("Assert failed") End Try
Next, we revoke the assert we previously issued by using the RevertAssert() method, and establish Deny permissions:
System.Security.CodeAccessPermission.RevertAssert() oEp.Deny()
We then try again to read the variable, and write the appropriate result to a message box:
Try sEv = Environment.GetEnvironmentVariable("Temp") MessageBox.Show("Deny failed") Catch objA As System.Exception MessageBox.Show("Deny was a success") End Try
Finally, we write the ToString() of the method to another message box. Following is the output of all three message boxes as a result of running this subroutine. The first two message box messages give us the feedback from our Assert() and Deny() code, followed by the output of our ToString() method:
Assert was a success Deny failed <IPermission version="1" Read="Temp" />
As you can see, the ToString() method is an XML representation of the permission object currently in effect. The first and second message boxes that are output reflect the system information of the version of the Visual Basic security environment that was running at the time the button was clicked. The third message box is the environment variable name surrounded by the Read tags, which was the permission in effect at the time the ToString() method was executed.
Look at one more example of where the permissions would affect you in your program functionality, that of accessing the registry. You would generally access the registry on the computer that was the central server for a component in your Windows Forms application.
When you use the EventLog methods to create entries in the machine Event Logs, you access the registry. To illustrate this concept, the following code example denies permissions to the registry:
Protected Sub TestRegistryPermissions_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) _ Handles TestRegistryPermissions.Click Dim oRp As New _ RegistryPermission(Security.Permissions.PermissionState.Unrestricted) oRp.Deny() Dim objLog As New EventLog Dim objLogEntryType As EventLogEntryType Try Throw (New EntryPointNotFoundException) Catch objA As System.EntryPointNotFoundException Try If Not System.Diagnostics.EventLog.SourceExists("Example") Then System.Diagnostics.EventLog.CreateEventSource("Example", "System") End If objLog.Source = "Example" objLog.Log = "System" objLogEntryType = EventLogEntryType.Information objLog.WriteEntry("Error: " & objA.message, objLogEntryType) Catch objB As System.Exception MessageBox.Show(objB.Message) End Try End Try End Sub
Walking through the code, you start with setting up the registry permission and setting it to Deny access:
Dim oRp As New _ RegistryPermission(Security.Permissions.PermissionState.Unrestricted) oRp.Deny()
Next, you Throw an exception on purpose in order to set up writing to an Event Log:
Throw (New EntryPointNotFoundException)
When the exception is caught, it checks the registry to make sure a specific type of registry entry source is already in existence:
If Not System.Diagnostics.EventLog.SourceExists("Example") Then System.Diagnostics.EventLog.CreateEventSource("Example", "System") End If
At this point, the code fails with the error message shown in Figure 12-4.
Figure 12-4
These examples can serve as a good basis for use in developing classes that access the other objects within the scope of the Permissions namespace, such as reflections and UI permissions.