Code Access Security C# Help

What is the importance of code access security? With role-based security, you can define what the user is allowed to do. Code access security defines what the code is allowed to do. It depends on the evidence of the code –  here is the code coming from? Depending on the origin of the code, different permissions apply. Of course, role-based security still applies. The code cannot do more than the user is allowed to do.

rode access security is a feature of the run time that manages code, according to your revel of trust. If the LLR trusts the code enough to allow it to run, it will begin executing the code. Depending on the _ permissions given to the assembly, however, it might run within a restricted environment. If the code is not trusted enough to run, or if it runs but then attempts to perform an action for which it does not have the relevant permissions, a security  xception (of type Security Exception or a subclass of it) is thrown. The code access security system means that you can stop malicious code from running, but you can also allow code to run within a protected environment where you are confident that it cannot do any damage.

There are different scenarios in which code access security becomes important. With ClickOnce deployment, in many scenarios it is okay to use full trust, meaning the code is allowed to do anything that the user is allowed to do. If the ClickOnce deployed application is installed within the company, then maybe you trust your own application. An application certificate that is coming with the application can also give enough information about a vendor that you trust, so you can deploy the vendor’s application using ClickOnce with full rights to your own system. Of course, restricted rights are also possible with CIickOnce. Scenarios in which code access security becomes more important than with ClickOnce are in hosting environments and with add-ins. If you create an add-in host, you might not want to give all your rights to the add-ins that are loaded from your application. You can restrict the permissions for assemblies that are called. A Web site hosting company does not want Web application  from different customers running on the server to have full rights to the system. They could break a
server that night run hundreds or thousands of Web applications. Restricting permissions for Web applications is a good option.

“Deployment,” explains ClickOnce in detail. Creating add-ins is discussed ill Chapter 36 , “Add-Ins.”

Code access security is based on these concepts: permissions, permission sets, code groups, and policies. Take a look at them now, because they form the foundations of the sections that follow:

¤  Permissions are the actions that you allow each code group to perform. For example, permissions include “read files from the file system,” “write to the Active Directory,” and “use sockets to open network connections.” Several predefined permissions exist, but you can also create your own permissions.

¤  Permission sets are collections of permissions. With permission sets, it is not necessary to apply every single permission to code; permissions are grouped to permission sets. Some examples of permission sets are FullTrust, LocalIntranet, and Internet. You can create a permission set that includes required permissions. An -assembly that has FullTrust permissions has full access to all resources. With LocalIntranet, the assembly is restricted, that is, it is not allowed to write to the file system other than using the isolated storage.

¤  Code groups bring together code with similar characteristics. A code group defines the origin of the code. Examples for existing code groups are Internet and Intranet. The group Internet defines code that is sourced from the Internet, and the group Intranet defines code sourced from the LAN. The information used to place assemblies into code groups is called evidence. Other evidence is collected by the CLR, including the publisher of the code, the strong name, and (where applicable) the URI from which it was downloaded. Code groups are arranged in a

hierarchy, and assemblies are nearly always matched to several code groups. The code group at the root of the hierarchy is called All Code and contains all other code groups. The hierarchy is used for deciding which code groups an assembly belongs to; if an assembly does not provide evidence that matches it to a group in the tree, no attempt is made to match it to code groups below.

¤  Policies allow the system administrator to define different levels of permissions for the . complete company, machines, and users. Code groups are defined within all of these policies, and the permissions are combined.

Permissions

by the CLR. An assembly demands a permission for a specific operation (for example, the File class demands the FileIOPermission), and the CLR verifies if the assembly has the permission granted so that it can continue.

There is a very fine-grained list of permissions that you can apply to an assembly or request from code. The following list shows a few of the code access permissions provided by the CLR; as you can see, you have great control of what code is or is not permitted to do:

¤  DirectoryServicesPennission controls the ability to access Active Directory through the System. DirectoryServices classes.

¤  DnsPennission controls the ability to use the TCP lIP Domain Name System (DNS).

¤  EnvironmentPennission controls the ability to read and write environment variables

¤  EventLogPennission controls the ability to read and write to the event log.

¤  FileDialo$Pennission controls the ability to access files that have been selected by the user in the Open-dialog box. This permission is commonly used when FileIOPermission is not granted to allow limited access to files.

¤  FileIOPennission controls the ability to work with files (reading, writing, and appending to files, as well as creating, altering, and accessing folders).

¤  IsolatedStorageFilePennission controls the ability to access private virtual file systems

¤  IsolatedStora.gePennission controls the ability to access isolated storage; storage that is associated with an individual user and with some aspect of the code’s identity. Isolated storage is discussed in,Chapter 25, “Manipulating Files and the Registry.”

¤  MessageQueuePennission controls the ability to use message queues through the Microsoft Message Queue.

¤  PerfonnanceCounterPermission controls the ability to make use of performance counters.

¤  PrintingPermission controls the ability to print.

¤  ReflectionPennission controls the ability to discover information about a type at runtime. by using System. Reflection.

¤  RegistryPermission controls the ability to read, write, create, or delete registry keys and values.

¤  SecurityPermission controls the ability to execute, assert permissions, call into unmanaged
code, skip verification, and other rights.

¤  ServiceControllerPermission controls the ability to control Windows services

¤  SocketPermission controls the ability to make or accept TCP lIP connections on a network transport address.

¤  SQLClientPermission controls the ability to access SQL Server databases with the .NET data provider for SQL Server

¤  SQLClientPermission controls the ability to access SQL Server databases with the .NET data provider for SQL Server

¤  WebPermission controls the ability to make or accept connections to or from the Web.

With each of these permission classes, it is often possible to specify an even deeper level of granularity; for example, the DirectoryServicesPermission allows you to differentiate between read and write access, and also allow’s you to define which entries in the directory services are allowed or denied access. In terms of best practice, you should ensure that any attempts to use resources require permissions to be enclosed within try/catch error-handling blocks, so that your application degrades gracefully, should it be running under restricted permissions. The design of your application should specify how your application should act under these circumstances. Do not assume that it will be running under the same security policy under which it has been developed. For example, if your application cannot access the local drive, should it exit or operate in an alternative fashion? Another set of permissions is assigned by the CLR on the basis of the identity of the code, which cannot be granted. These permissions relate to the evidence the CLR has collated about the assembly and are called identity permissions. Here are the names of the classes for the identity permissions:

¤  PublisherldentityPermission refers to the software publisher’s digital signature

¤  SiteldentityPermission refers to the name of the Web site from which the code originated

¤  .StrongNameldentityPermission refers to the assembly’s strong name.

¤  URLIdentityPermission refers to the URL from which the code came (including the protocol;
;. for example, https: / f).

¤  ZoneldentityPermission refers to the zone from which the assembly originates.

By assigning the permission to code groups, there is no need to deal with every single permission. Instead, the permissions are applied in blocks, which is why .NET has the concept of permission sets. These are lists of code access permissions grouped into a named set. The following list explains the named. permission sets you get out of the box:

¤  Full Trust means no permission restrictions

¤  SkipVerification means that verification is not done.

¤  Execution grants the ability to run, but not to access any protected resources

¤  Nothing grants no permissions and prevents the code from executing.

¤  LocalIntranet specifies the default policy for the local intranet, a subset of the full set of permissions. For example, file 10 is restricted to read access on the share where the assembly originates.

¤  Internet specifies the default policy for code of unknown origin. This is the most restrictive policy listed. For example, code executing in this permission set has no file 10 capability, cannot read or write event logs, and cannot read or write environment variables.

¤  Everything grants all the permissions that are listed under this set, except the permission to skip code verification. The administrator can alter any of the permissions in this permission set. This is useful when the default policy needs to be tighter.

Note that of these you can change the definitions of only the Everything permission set – the other sets arefixed an~ cannot be changed. Of course, you can also create your own permission set.

Identity permissions cannot be included in permission sets because the CLR is the only body able to grant identity permissions to code. For example, if a piece of code is from a specific publisher, it would make little sense for the administrator to assign the identity permissions associated with another publisher. The CLR grants identity permissions where necessary, and if you want, you can use them.

Demanding PermisSions Programmatically

  An assembly can demand permissions declaratively or programmatically. To see how demanding permissions works, create a Windows Forms application that contains just a button. When the button is clicked, a file on the local file system is accessed. If the application does not have the relevant permission to access the local drive (FileIOPermission), the button will be marked as disabled (dimmed).

If you import the namespace System. Securi ty . Permissions, you can change the constructor of the class Forml to check for permissions by creating a FileIOPermission object, calling its Demand () method, and then acting on the result:

FileIOPermission is contained.within the System. Security. Permissions namespace, which is home to the full set of permissions and also provides classes for declarative permission attributes and enumerations .for the parameters that are used to create permissions objects (for example, creating a FileIOPermission specifying whether read-only or full access is needed).

If you run the application from the local drive where the default security policy allows access to local storage, you will see a dialog box with a button that is enabled. However, if you copy the executable to a network share and run it again, you are operating within the LocalIntranet permission set, which blocks access to local storage, and the button will be disabled.

Within the implementation of the click event handler, there is no need to check the required security because the relevant class in the .NET Framework already demands the file permission, and the CLR ensures that each caller up the stack has those permissions before proceeding. If you run the application from the intranet, and it attempts to open a file on the local disk, you will see an exception unless the security policy has been altered to grant access to the local drive.

To catch exceptions thrown by the CLR when code attempts to act contrary to its granted permissions, you can catch the exception of the type Securi tyException, which provides access to a number of useful pieces of information, including a.human-readable stack trace (Securi tyException. StackTrace) and a reference to the method that threw the exception (Securi tyException. TargetSi te). Securi tyException even provides you with the
SecurityException. PermissionType property, which returns the type of Permission object that

caused the security exception to occur. If you have problems with security exceptions, this should be one of your first parts to diagnose. Simply remove the try and ca tch blocks from the previous code to see the security exception,

Declarative Permissions

You can deny, demand, and assert permissions by invoking permission classes programmatically. However, you can also use attributes and specify permission requirements declaratively, The main benefit of using declarative security is that the settings are accessible through reflection. This can be of enormous benefit to system administrators, who often will want to view the security requirements of applications. For example, you can specify that a method must have permission to read from C: \ to execute:

Be aware that if you use attributes to assert or demand permissions, you cannot catch any exceptions that are r<l.isedif the action fails, because there is no imperative code around in which you can place a try-catch-finally clause.

Requesting Permissions

As discussed in the previous section, demanding permissions (either by code or declaratively) is where you state clearly what you need at runtime; however, you can configure an assembly so it makes a softer request for permissions right at the start of execution. The assembly can specify the required permissions before it begins’ executing. ,

You can request permissions in three ways:

¤  Minimum permissions specify the permissions your code must run.

¤  Optional permissions specify the permissions your code can use but is able to run effectively without.

¤  Refused permissions specify the permissions that you want to ensure are not granted to your code.

Why would you want to request permissions when your assembly starts? There are several reasons:

¤  If your assembly needs certain permissions to run, it makes sense to state this at the start of execution rather than during execution to ensure that the user does not experience a road block after beginning to work in your program.

¤  You will be granted only the permissions you request and nothing more. Without explicitly requesting permissions your assembly might be granted more permissions than it needs to execute. This increases the risk of your assembly being used for malicious purposes by other code.

¤   If you request only a minimum set of permissions, you are increasing the probability that your assembly will run, because you cannot predict the security policies that are effective at the user’s location.

Requesting permissions is likely to be most useful if you are doing more complex deployment, and there
a igher risk that your application will be installed on a machine that does not grant the required
permissions. It is usually preferable for the application to know right at the start if it will not be
granted permissions, rather than halfway through execution.

granted permissions, rather than halfway through execution. • ith Visual Studio, you can get help to calculate the required permissions of an application by selecting the Security tab with the properties (see Figure 20-4). Clicking the Calculate Permissions button checks the code of the assembly and lists all required permissions,

Figure 20-4

Figure 20-4

Instead of using Visual Studio, you can use the command-line tool perrncalc. exe to calculate the required permissions of an assembly.

The command line

permcalc.exe’ -show -stacks -cleancache DemandingPermissions.exe

creates an XML file that contains all required permissions. With the option -show, the XML file is opened immediately. The option -stacks adds the stack information to the XML file for you to see where the permissions demand originated from.

The required permissions can be added as attributes to the assembly. Following are three examples that demonstrate using attributes to request permissions. If you are following this with the code download, you can find these examples in the RequestingPerrnissions project. The first attribute requests that the assembly have UIPerrnission granted, which will allow the application access to the user interface. The request is for the minimum permissions, so if this permission is not granted, the assembly will fail to start:

In this scenario, you want to add this attribute to an application that accesses unmanaged code in at least one place. In this case, it is specified that this permission is optional, which means that the application can run without the permission to access unmanaged code. If the assembly is not granted permission to access unmanaged code and attempts to do so, a securi tyException will be raised, which the application should expect and handle accordingly. The following table shows the full list of available SecurityAction enumeration values; some of these values are covered in more detail later 1Il this ch~pter

When you consider the permission requirements of your application, you need to decide between two options:

¤  Request all the permissions you need at the start of execution, and degrade gracefully or exit if those permissions are not granted.

¤   Avoid requesting permissions at the start of execution, but be prepared to handle security exceptions throughout your application.

After an assembly has been configured using permission attributes in this way, you can use the perrncalc . exe utility to show the required permissions by aiming at the assembly file that contains the assembly manifest using the -assembly option of the perrncalc. exe utility:

RequestingPermissions.exe~
Minimal permission set:
<PermissionSet class=’Systern.Security.PermissionSet’
version=’1′> .
<IPermissi~n class=’Systern.Security.Permissions.UIPermission. mscorlib.
Version=2.0.0.0. Culture=neutral. PublicKeyToken=b77a5c561934e089′ version=’1′
Unrestricted=’true’/>
</PermissionSet>

Optional permission set: .
<PermissionSet class=’System.Security.PermissionSet’
version=’1′>
<IPermission class=’System.Security.Permissions.SecurityPermisslon. msco~lib.
Version=2.0.0.0. Culture=neutral. PublicKeyToken=b77aScS61934e089″ version=’1′ Flag
s=”SecurityPermissionFlag.UnrnanagedCode” />
</PermissionSet>

Refused permission set:
<PermissionSet class=”System.Security.PermissionSet”
version=”l”>
<IPermission class=”System.Security.Permissions.FileIOPermission. mscorlib.
Version=2.0.0.0. Culture=neutral. PubliCKeyToken~b77a5c561934e089″ version=”l”
Read=’C:’/>

</PermissionSet>
static void Main()
(
Generating output …
Writing file: RequestingPermissions.exe.PermCalc.xml

In addition to requesting permissions. you can also request a complete permissions set; the advantage is that you don’t have to deal with every single permission. However. you can only request permission sets that cannot be altered. The Everything permission set can be altered through the security policy while an assembly is running. so it cannot be requested. Here is an example of how to request a built-in permission set:[assembly:permissionSet(SecuritYAction.Re~estMinimum.  name = “FullTrust’)J

In this example. the assembly requests that as a minimum it needs the FullTrust built-in permission set granted. If this set of permissions is not granted, the assembly will throw a security exception at runtime.

Implicit Permissions

When permissions are granted. there is often an implicit statement that you are also granted other permissions. For example. if you assign the FileIOPermission for c . \. there is an implicit assumption that there is also access to its subdirectories. To check -w. hether a granted permission implicitly brings another permission as a subset. you can do this

 The output Jooks like this:
PermissionB is a subset of PermissionA

Denying Permissions

Under certain circumstances, you might want to perform an action and be absolutely sure that the method that is called is acting within a protected environment. An assembly shouldn’t be allowed to do anything unexpected. For example, say that you want to make a call to an add-in component in a way

that it will not access the local disk. Create an instance of the permission you want to ensure that the method is not granted, and then call its Deny () method before making the call to the class:

using System;
using System.IO;
using System. Security;
using System. Security. Permissions;

If you build this code, the output will state Failed to open file, because the untrustworthy class does not have access to the local disk.

Note that the Deny() call is made on an instance of the permission object, whereas the RevertDeny () call is made statically. The reason for this is that the RevertDeny () call reverts all deny requests within the current stack frame; if you have made several calls to Deny ( ), you need to make only one follow-up call to RevertDeny ( ).

Asserting Permissions

Imagine that an assembly has been installed with full trust on a user’s system. Within that assembly there is a method that saves auditing information to a text file on the local disk. If, later, an application is installed that wants to make use of the auditing feature, it will be necessary for the application to have the relevant FileIOPermission permissions to save the data to disk.

This seems excessive, however, because all you really want to do is perform a highly restricted action on the local disk. In these situations, it would be useful if assemblies with limiting permissions could make calls to more trusted assemblies that can temporarily increase the scope of the permissions on the stack, and perform operations on behalf of the caller. The caller, itself, doesn’t need to have the permissions.

Another example in which asserts become important is when you create assemblies that invoke native code using platform invoke. The assembly invoking native methods requires full trust. But is it really necessary that all callers of this assembly require full trust as well? Take a look at how this is done with the .NET Framework assemblies. The File class invokes the native Windows API CreateFile () and thus needs full trust. The File class itself asserts the permission it requires by itself so that the caller does not require having this permission itself, but demands the FileIOPermission. (Platform invoke is discussed in Chapter 24, “Interoperability,”)

Assemblies with a high enough level of trust can assert permissions that they require. If the assembly has the permissions it needs to assert additional permissions, it removes the need for callers up the stack to have such wide-ranging permissions.

The code that follows contains a class called Audi tClass that implements a method called Save ( ), which takes a string and saves audit data to C: \audi t. txt. The Audi tClass method asserts the permissions it needs to add the audit lines to the file. For testing it, the Main () method for the application explicitly denies the file permission that the Audi t method needs:

using System;
usin~ System.IO;
using System. Security;
using System. Security. Permissions;

When this code isexecuted,you will find that the callto the AuditClass method does not cause a security exception, even though when it was called it did not have the required permissions to carry out the disk access. Like RevertDeny (), RevertAssert () is a static method, and it reverts all assertions within the current frame.

It is important to be very careful.when using assertions. Youare explicitly assigning permissions to a method that has been called by code that might not have those permissions, and this could open a security hole. For example, in the auditing example, even if the security policy dictated that an installed application cannot write to the local disk, your assembly would be able to write to the disk when the auditing assembly asserts FileIOPermissions for writing.

However, to perform the assertion, the auditing assembly must have been installed with permission for FileIOAccess and SecurityPermission. The Securi tyPermission allows an assembly to perform an assert, and the assembly will need both the Securi tyP.ermission and the permission being asserted to complete successfully.

Code Group.

This sectiori’gets into management of assemblies and their permissions. Instead of managing every
assembly on its own, code groups are defined. Code groups have an entry requirement called membership
condition. For an assembly to be filed in a code group, it must match the group’s membership condition.
Membership conditions include “the assembly is from the site www.microsoft.com ••or “the publisher
of this software is Microsoft Corporation.”
E”ch code group has one, and only one, membership condition. Assemblies can be within multiple code
groups. The following list provides the types of code group membership conditions available in .NET:

¤  Zone -:; The region from which the code originated.

¤  Site – The Website from which the code originated.

¤  Strong name – A unique, verifiable name for the code. Strong names are discussed in Chapter 17, “Assemblies.

¤  Publisher – The publisher of the code

¤  Hash value – The hash value for the assembly

¤  Skip verification – This condition requests that it bypass code verification checks. Code verification ensures that the code accesses types in a well-defined and acceptable way. The runtime cannot enforce security on code that is not type-safe.

¤  Application directory – The location of the assembly within the application.

¤  All code – All code fulfills this condition.

¤  Custom – A user-specified condition.

The first, and most commonly used, type of membership condition is the Zone condition. A zone is the region of origin of a piece of code and refers to one of the following: ~yComputer, Internet, Intranet, Trusted, or Untrusted. These zones can be managed by using the Internet Options in Windows Security Center. .

Code groups are arranged hierarchically with the All Code membership condition at the root (see Figure 20-5). You can see that each code group has a single membership condition and specifies the permissions that the code group has been granted. Note that if an assembly does not match the membership condition in a code group, the CLR does not attempt to match code groups below 1

Figure 20-5

Figure 20-5

caspol.exe – The Code Access Security Policy Too

This section spends a good deal of time looking at the command-line Code Access Security Policy tool. To get a list of options for the tool, just type the following at the command prompt:

caspol.e~e -?
To send the output to a text file, use:
caspol.exe > output.txt

Take a look at the code groups on a machine using caspol. exe. The output of the command lists the
hierarchical structure of the code groups on the machine, and next to each group there is a description of
the code group. Type this command:
caspol.exe -listdescription

Alternatively, the -listdescription parameter has a shortcut: -ld. A part of the output is shown here:
Microsoft (R) .NET Framework CasPol 2.0.50727.1426
Copyright (e) Microsoft Corporation. All rights reserved.
Security is O

Execution checking is ON
policy change prompt is ON
Level = Machine
Full Trust Assemblies:

1. All_Code: Code group grants no permissions and forms the root of the code
group tree.
1.1. My_Computer_Zone: Code group grants full trust to all code originating
on the local computer
1.1.1. Microsoft_Strong_Name: Code group grants full trust to code
signed with the Microsoft strong name.
1.1.2. EC~Strong_Name: Code group grants full trust to code signed
with the ECMA strong name.
1.2. LocalIntranet_Zone: Code group grants the intranet permission set to
code from the intranet zone. This permission set grants intranet code
the right to use isolated storage, full UI access, some capability to
do reflection, and limited access to environment variables.
1.2.1. Intranet_Same_Site_Access: All intranet code gets the right to
connect back to the I!ite of its origin ..
1.2.2. Intranet_Same_Directory_Access: All intranet code gets the right
to read from its install directory.
1.3. Internet_Zone: Code group grants code from the Internet zone the
. Internet permission set. This permission set grants Internet code the
right to use isolated storage and limited UI access.

The .NET security subsystem ensures that code from each code group is all~wed to do only certain things. For example, code from the Internet zone will, by default, have, much stricter limits than code from the loca!:sirive. Code from the local drive is normally granted access to data stored on the local drive, but assemblies from the Internet are not granted this permission by default.

Using caspol and its equivalent in the Microsoft Management Console, you can specify what level of trust you have for each code access group, as well as managing code groups and permissions in a more granular fashion.

Take another look at the code access ‘groups, but this time in a slightly more compact view. Make sure that you are logged in as a local administrator, go to a command prompt, and type this command:

caspol.exe .-.listgroups
You will see something like this:
Microsoft (R) .NET Framework CasPo1 2.0.50727.1426
Copyright (c! Microsoft Corporation. All rights reserved.

Security is ON
Execution checking is ON
Policy change prompt is ON
Level = Machine
Code Groups:

You will notice that near the start of the output it says Securi ty is ON.Later in the chapter you will see that it can be turned off and then turned on again

The Execution Checking setting is on by default, which means that all assemblies must be granted the permission to execute before they can run. If execution checking is turned off using caspol (caspol. exe -execution on Ioff), assemblies that do not have the permission to run can execute, although they might cause security exceptions if they attempt to act contrary to the security policy later in their exee,u.tion.

The Policy Change Prompt option specifies whether you see an “Are you sure” warning message when you attempt to alter the security policy.

As code is broken down into these groups, you can manage security at a more granular level, and apply full trust to a much smaller percentage of code. Note that each group has a label (for example, 1.2). These labels are auto-generated by .NET, and can differ between machines. Generally, security is not managed for each assembly, but for a code group instead. When a machine has several side-by-side installations of CLR, the copy of caspol . exe that you run will alter the security policy only for the installation of .NET with which it is associated.

Viewing an Assembly’s Code Groups

Assemblies are matched to code groups according to the membership conditions they match. If you were to go back to the code groups example and load an assombly from the ht tps: / / intranet/ Web site, it would match the code groups shown in Figure 20-6. TI,e assembly is a member of the root code group (All Code); because it carne from the local network, it i also a member of the Intranet code group. However, because it was loaded from the specific site J t tps: / / intranet, it is also granted FullTrust, which means that it can run unrestricted.

Figure 2().6

Figure 2().6

You can easily view tlie code groups that an assembly is a member of using this command:
caspol.exe -resolvegroup assernbly.dll
Running this command on an assembly on the local drive produces the foll~wing output:
Microsoft (R) .NET Framework CasPol 2.0.50727.1426
Copyright (c).~icrosoft Corporation. All rights reserved

Level = Enterprise
Code Groups:
1. All code: FullTrust
Level = Machine
Code Groups:
1. All code: Nothing
1.1. Zone – MyComputer: FullTrust
Level = User
Code Groups:
1. All code: FullTrust
Success
You will notice that code groups are listed on three levels – Enterprise, Machine, and User. For now, stay focused on thE machine level. In case you are curious about the relationship among the three, the effective permission given to an assembly is the intersection of the permissions from tile three levels. For example, if you remove the FullTrust permission from the Internet zone at the enterprise-level policy, ….all.

permissions are revoked for code from the Internet zone, and the settings of the other two levels become irrelevant.

Now use this command once more with the same assembly to read the code groups. However, this time, the assembly is accessed from a Web server using the H1TP protocol. You can see that the assembly is a member of different groups that have much more restrictive permissions:

caspol.exe -resolvegroup http://server/assembly.dll
Microsoft (R) .NET Framework CasPol 2.0.50727.1426
Copyright (c) Microsoft Corporation. All rights reserved.

Level = Enterprise
Code Groups:
1. All code: FullTrust
Level = Machine
Code Groups:
1. All code: Nothing
1.1. Zone – Internet: Internet
1.1.1. All code: Same site Web.

Level = User
Code Groups:
1. .J.ll code: Full Trust
Success
The assembly grants the Internet and the Same Site Web permissions. The intersection of the permissionsallows the code limited VI access. It also permits the code to establish connections to the site it
originated from.

Code Access. Permissions and Permissions Sets

Imagine yo~self administering security policy on a network of desktop machines in a large enterprise scenario. In this environment, it is immensely useful for the CLR to collect evidence information on code before the code is allowed to execute. Likewise, you, as the administrator, must have the opportunity to control what code is allowed on the several hundred machines you manage once the CLR has identified its origin. This is where permissions start to act.

After an assembly has been matched to code groups, the CLR looks at the security policy to calculate the permissions it grants to an assembly. When .nanaging permissions in Windows, you generally don’t want to apply permissions to users, but you apply permissions to user groups instead. This is also true with assemblies; permissions are applied to code groups rather than to individual assemblies, which makes the management of security policy in .NET a much easier task.

Look more closely at viewing an assembly’s permissions. Imagine using a Microsoft application in which you use a feature that you have not used before. The application does not have a copy of the code stored locally, so the code is requested from the Internet and downloaded into the Download Assembly Cache. Figure 20-7 illustrates what an assembly’s code group membership might look like with code from the Internet published by a named organization that has signed the assembly with a certifitate.

Figure 20-7

Figure 20-7

Although the All Code and Internet code groups have only limited permissions according to the policy in this example, membership of the code group in the bottom right-hand comer grants the assembly the FullTrust permission. The overall effective permission is the union of permissions across the matching code groups. When the permissions are merged this way, the effective permission is that of all permissions granted, that is, each code group to which an assembly belongs brings additional permissions. Just as you can check what code groups an assembly belongs to, it is also possible to look at the permissions assi~ed to the code groups. By doing this you will see not only the code access permissions (what the code is allowed to do), but also the code identity permissions that will give you access to the evidence the code presented to the runtime. To see the permissions for an assembly’s code groups, use a command like this:

caspol.exe -resolveperm assemb1y.dll

Try this on an assembly and look at the granted code access and identity permissions when the assembly
is accessed over a local intranet. When you type the following command, you will see the code access
permissions and then tJ’tethree identity permissions at the end:

 Grant =
<PermissionSet class=·System.Security.PermissionSet·
version=·1·>
<IPermission class=·System.Security.Permissions.EnvironmentPermission,
mscorlib, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089· Version=·1· Read=·USERNAME·/>

The output shows each of the permissions in XML, including the class defining the permission, the assembly containing the class, the permission version, and an encryption token. The output suggests that it is possible for you to create your own permissions. Youcan also see that each of the identity permissions includes’rnore detailed information on, for example, the UrlIdentityPermission class, which provides access to the URLfrom which the code originated.

Note how at the start of the output, caspol . exe resolved the permissions at the enterprise, machine, and user levels and then listed the effective granted permissions, which is worth a closer look.

Policy Levels: Machine, User, and Enterprise

Up to now, you have dealt with security in the context of a single machine. It’s often necessary to specify security policies for specific users or for an entire organization, and that is why .NET provides not one but three policy levels

¤  Machine

¤  Enterprise

¤  User

The code group levels are independently managed and exist in parallel, as shown in Figure 20-8.

Figure 20-8

Figure 20-8

If there are three security policies, how do you know which one applies? The effective permis~ion is the intersection of the permissions from these three levels. Each of the three levels has the ability to veto the permissions allowed by another – this is really good news for administrators because their settings will override user settings.· .

To work with code groups and permissions on the user or enterprise levels using caspol . exe, add either the -enterprise or -user argument to change the command’s mode. caspol. exe works at the machine level by default and that’s how you’ve been using ituntil now. Use the following command to see the code groups listing at the user level:

caspol.exe -user ,listgroups

The output of the command on a default installation looks like this:

Security is ON
Execution checking is ON
Policy change prompt is ON
Level = User
Code Groups:
1. All code: FullTrust
Success

Now run the same command, but this time with the code groups at the enterprise level:

caspol.exe -enterprise -listgroups

The output of the command looks like this:

Security is ON
Execution checking is ON
Policy change prompt is ON
Level = Enterprise
Code .g.•roups:
1. All code: FullTrust
Success

As you can see, by default, both the user level and the enterprise level are configured to allow FullTrust for the single code group All Code. The result of this is that the default setting for .NET security places _ no restrictions at the enterprise or user levels, and the enforced policy is dictated solely by the machinelevel policy. For example, if you were to assign a more restrictive permission or permission set than FullTrust to either the enterprise or user levels, those restrictions would restrict the overall permissions, and probably override permissions at the machine level. The effective permissions are intersected. lf you want to apply FullTrust to a code group, this permission must be assigned to the code group on each of the three policy levels.

When you run caspol. exe as an administrator, it defaults to the machine level, but if you log out and log back in as a user who is not in the Administrator user group, caspol . exe will default to the user level_instead. In addition, caspol. exe will not allow you to alter the security policy in a way that renders the caspol . exe utility itself inoperable.

Posted on November 2, 2015 in Localization

Share the Story

Back to Top