As you might imagine, there are security classes to express security for a wide variety of resources. An exhaustive list would require a considerable amount of space; I will leave this to the VS .NET help files. However, as an appetizer I'll mention that you can express security requests to determine whether operations like file I/O are permitted, whether common file dialogs can be shown, whether the registry can be written to ”you can even check whether assemblies can be linked. You can begin your exploration by reading the Introduction to Code Access Security help documentation in the Visual Studio .NET IDE. To get you started I have included here some common security checks you might want to use in your code.
The examples in this section all use security demands. There are several other kinds of checks as well, which we will get to in a moment. Additionally, the examples demonstrate both declarative and imperative security. All the examples in this section are derived from the System.Security.CodeAccessPermission class. (You can check the IDE help documentation for examples of classes derived from the CodeAccessPermission class.)
What Is a Demand?
The notion of a demand in .NET seems a bit misleading. Dictionary.com defines demand as "to claim as just or due." To me this sounds as if a demand in .NET ought to mean that you are taking a permission from the operating system, as in, "My code demands that it be allowed to print." Perhaps the Demand method should instead be named request because when you demand a permission, the security policy might just say "No!"
Invoking Demand does mean that your code needs a permission, but it doesn't mean that it will get it. The security policy is like a good parent: sometimes a parent says no because something isn't good for the child. For example, code downloaded from the Internet might demand to be allowed to write to the %WINDIR% folder or the registry, but this might not be good for your PC, so the response is no. And it is the most preemptive no possible: an exception is thrown.
Security demands help enforce the contracts between various pieces of code. If your code needs to do something and isn't allowed to do it, you need to handle this problem. Generally , handling it means to catch the exception and tell the user. The code can electively do something else or bubble the command to the user . In turn , the user can ask for an amendment to the security policy, if the thing demanded is desirable, or let out a sigh of relief, realizing that a catastrophic mishap was handily avoided.
Demanding Printing Permission
The greater variety and number of projects a developer works on, the less often that developer will be surprised by requirements made by various applications. Printing is one of those things we often take for granted. In my home office network I print without a moment's hesitation. But what if you are writing software that is capable of printing medical records or a release from the county jail? Clearly you don't want code to be able to print someone's medical records or a jail release form without proper permissions. Under these circumstances a customer clearly would not tolerate a security policy that permitted any code to invoke the printing behavior; however, if you are writing the module that legitimately prints these kinds of things, printing is required. Listing 18.2 demonstrates how we can write code to demand (or indicate ) that printing is required. Keep in mind that the policy may not permit it, although in our scenario the policy would need to be adjusted to allow the legitimate printing assembly to print.
Listing 18.2 Demanding Printing Permission
Imports System.Drawing.Printing Private Sub PrintDemand() Try Dim Permission As PrintingPermission = _ New PrintingPermission(PrintingPermissionLevel.AllPrinting) Permission.Demand() ' Print here MessageBox.Show("This code can print.") Catch MessageBox.Show("This code can't print!") End Try End Sub
It is important to note that the default policy is defined to permit code that originates from your computer to be allowed to perform relatively unrestricted operations. This does not mean, however, that the default security policy where you work hasn't been amended. In addition, keep in mind that code originating from your computer could cause accidental errors, but generally code that originates outside your computer is riskier and likely to have significantly fewer permissions.
Demanding Registry Read Permission
The registry is organized similarly to the file system. When code needs to access the registry, you can demand registry permission, specifying the location in the registry that the code can write to or read from. Listing 18.3 demonstrates a demand to ensure that the code can read from anywhere in the registry. (To cause the demand to fail, create a policy for the DemandExamples.exe assembly that denies registry access.)
Listing 18.3 Demanding Registry Read Permission
1: Private Sub ReadRegistry() 2: Try 3: Dim Permission As RegistryPermission = _ 4: New RegistryPermission(RegistryPermissionAccess.Read, "*") 5: 6: Permission.Demand() 7: MessageBox.Show( _ 8: "This code can read from anywhere in the registry") 9: Catch 10: MessageBox.Show( 11: "This code can't read from anywhere in the registry.") 12: End Try 13: End Sub
Suppose, for example, that you download a cool program from the Internet that keeps track of your favorite music playlists. It is unlikely that your company wants that vendor reading the registry to figure out if you are running a competitor's software. In fact, it is unlikely that you want to give the vendor any access to the registry unless it is perhaps to store configured playlists. By defining a policy that limits registry access, you could allow the vendor to store playlists but prevent it from poking around.
There are a dozen or more code access permission classes. Each has constructor arguments (if applicable ) that refine how a particular instance of the permission fits in its context. You also have the option of creating custom security classes. Regardless of how you initialize the permission, relative to the Demand method, they all behave the same way: if the permission is supported by the policy based on the evidence supplied, the demand succeeds. Failure is exhibited by an exception.