Now that the preliminaries are out of the way, let's look at the actual administration of security policy. I'll also give code examples, which will demonstrate the net effect of the modifications we make to the security policy.
The command line tool caspol.exe or the MMC Snap-in mscorcfg.msc can be used to edit the XML files that define the security policy (at the Enterprise, Machine and User levels). If our intention is to create scripts to alter security policy for a large number of machines, caspol.exe would be the best tool to use. Throughout this article, we will be using the MMC Snap-in. To run the snap-in, go to a command prompt and enter
%Systemroot%\Microsoft.NET\Framework\version\Mscorcfg.msc.
After the UI appears, expand Runtime Security Policy\Machine\Code Groups\All_Code. We will then be presented with a graphical representation of the hierarchy of the Machine level code groups as defined on our machine. See diagram 4 below:

Figure 1 -Machine level code groups
The default Enterprise and User level code group hierarchies are much less interesting because they consist of only the All_Code code group. We can expand the expandable code group nodes to view all of the code groups in the hierarchy. Click on the LocalIntranet_Zone code group and then click on the Edit Code Group Properties link in the right pane. When the 'LocalIntranet_Zone Properties' dialog appears, click on the 'Permission Set' tab. We will see a list of permissions that are granted to the LocalIntranet_Zone code group.

Figure 2 -LocalIntranet_Zone Permissions
By default the LocalIntranet_Zone code group does not have permissions to several resources, including the registry and the file system. Click here to view a complete list of the .NET Framework code access permissions.
When we click on the 'Membership Condition' tab, we will see that the membership condition type is 'Zone' and the specific zone is 'Local Intranet'. By default, assemblies that originate on an organization's intranet and assemblies that are loaded via a UNC path meet this membership condition. We can configure the 'Internet', 'Local Intranet', 'Trusted Sites' and 'Restricted Sites' zones through the 'Internet Options' dialog in Internet Explorer.
The following simple code example will help demonstrate how Code Access Security permissions effect the execution of managed code. This console application will read the registry sub-keys under the HKLM\Software\Microsoft\.NetFramework registry key and display the key names in the console:
using System;
namespace ConsoleReadRegistry
{
/// <summary>
///
Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point
for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
Microsoft.Win32.RegistryKey
rk;
try
{
rk =
Microsoft.Win32.Registry.LocalMachine.OpenSubKey(
"Software\\Microsoft\\.NetFramework",false);
string[] skNames = rk.GetSubKeyNames();
for (int
i=0;i<skNames.Length;++i)
{
Console.WriteLine("Registry Key: {0}",
skNames[i]);
}
rk.Close();
}
catch(System.Security.SecurityException e)
{
Console.WriteLine("Security
Exception Encountered: {0}", e.Message);
}
}
}
}
If we compile and execute the application, we will see that the names of the registry keys under the .NetFramework key are displayed. The CLR granted our assembly permissions to execute and read the registry.

Figure 3
Let's recap what just happened. The code was compiled and an assembly was created that resides on our hard drive. Assuming that the default security policy is in place, at the User and Enterprise security policy levels the assembly was assigned to the All_Code code group. At these two policy levels all assemblies assigned to the All_Code group are granted FullTrust permissions.
At the Machine policy level our assembly satisfies the membership condition for the All_Code AND the My_Computer_Zone code groups (because it's loaded from a local hard drive). Therefore, at this policy level our assembly is granted a union of the permissions of the two code groups. We can see from Diagram 1 that no permissions are associated with the Machine policy level's All_Code code group and FullTrust (unlimited) permissions are associated with the My_Computer_Zone code group. Thus, our assembly is granted FullTrust permissions at the Machine policy level.
The Enterprise, Machine, and User security policy levels each grant a set of permissions based on the evidence gathered. The intersection of the permissions granted at each of the policy levels determines the permissions that will be granted to our assembly (see Diagram 3). The AppDomain policy level was not programmatically specified in this example so it does not apply (Enabling the AppDomain security policy level will be covered later in the article). In the scenario above our assembly was granted FullTrust permissions at all three levels so it has unlimited access to local resources.
If we copy our assembly to a shared folder and run the application by entering a UNC path at the command line, we would see a result different from what we saw in Figure 3. For example, if we start the application by entering \\MyMachine\MyShare\ConsoleReadRegistry.exe at a command prompt, we would see the following:

Figure 4
The difference is that the assembly is now being loaded using a UNC path. The default 'Local Intranet Zone' configuration specifies that all assemblies loaded via a UNC path are assigned to the LocalIntranet_Zone code group. The assembly is not assigned to the My_Computer_Zone code group even if the file share is on the local machine. Thus, at the Machine policy level the assembly is granted the permissions listed in Figure 2 (which does not include 'Registry' permissions). As a result, the following method call causes a SecurityException:
rk =
Microsoft.Win32.Registry.LocalMachine.OpenSubKey(
"Software\\Microsoft\\.NetFramework",false);
Suppose we wanted to grant assemblies from a specific file share permissions to read from the registry? We could simply use the configuration tool to associate the "FullTrust" or "Everything" permission set with the LocalIntranet_Zone code group. This wouldn't be the best approach because it would leave our machine vulnerable to attack. A better solution would be to add a custom code group with 'Registry' access permissions to the Machine policy level. We would then give the code group a URL membership condition which would specify the UNC path of our file share. Let's use the configuration tool to add our custom code group as a child of the LocalIntranet_Zone code group.
First, let's create a custom permission set that contains permissions to access the registry. Using the MMC Snap-in, right click on the Runtime Security Policy\Machine\Permission Sets node and select New... from the popup menu. When the 'Create Permission Set' dialog appears select the 'Create a New Permission Set' radio button and enter a name and description for the new permission set.

Figure 5
Click on 'Next'. When the next dialog appears select the Registry permission from the list and click on 'Add >>'. When the 'Permission Settings' dialog appears select the Grant assemblies unrestricted access to the registry radio button. Click on 'Ok' and 'Finish'.
To create the new code group right click on the Runtime Security Policy\Machine\Code Groups\All_Code\LocalIntranet_Zone node and select New... from the popup menu. Enter a name and description for the new code group and click on 'Next >'. When the 'Choose a condition type' dialog appears, select the URL condition type from the drop down list box and enter the UNC path to your assembly. Click on 'Next >'.

Figure 6
When the 'Assign a Permission Set to the Code Group' dialog appears, select our newly created permission set from the drop down list box. Click on 'Next >' and 'Finish'.
At this point our assembly satisfies the membership conditions of All_Code, LocalIntranet_Zone and our newly created code group. The effective union of the permissions granted at the Machine policy level is the set of permissions granted by LocalIntranet_Zone plus the registry permission granted by the new code group. If we re-run our application by entering the UNC path, a SecurityException is not encountered and our code is permitted to read from the registry.