Different Sources of Evidence

for RuBoard

I mentioned earlier that evidence is a collection of information. This was meant very literally. Evidence is represented by the System.Security.Policy.Evidence class, and this class implements the System.Collections.ICollection interface. This means that it is a container class for instances of other classes. Actually, each evidence object has two separate collections to cover two different sources of evidence:

  • Host-provided evidence

  • Assembly-provided evidence

TIP

To gain a more practical understanding of what evidence looks like on an assembly, compile and run the program from Listing 5.1. It simply looks at the Evidence property on a System.Reflection.Assembly object.


Listing 5.1 Program That Prints Out Its Own Evidence
 using System; using System.Collections; using System.Reflection; using System.Security; using System.Security.Policy; public class ShowEvidence {   public static void Main()   {     Assembly thisAssembly = Assembly.GetExecutingAssembly();     Evidence ev = thisAssembly.Evidence;     Console.WriteLine("Host Evidence:");     IEnumerator enumerator = ev.GetHostEnumerator();     while (enumerator.MoveNext())     {       Console.WriteLine(enumerator.Current + Environment.NewLine);     }     Console.WriteLine(Environment.NewLine);     Console.WriteLine("Assembly Evidence:");     enumerator = ev.GetAssemblyEnumerator();     while (enumerator.MoveNext())     {       Console.WriteLine(enumerator.Current + Environment.NewLine);     }   } } 

Host-Provided Evidence

Host-provided evidence is the evidence that has been discussed so far. For purposes here, a "host" is one of two things. First, a host could be something that initiates the Common Language Runtime. This is some unmanaged code that calls CorBindToRuntimeEx (an exported function from mscoree.dll ). Second, a host could be a managed piece of code that can launch other managed pieces of code.

Regardless of the type of host being discussed, the Common Language Runtime provides some types of evidence by default. Table 5.2 lists those default types of evidence. Thus, a host does not necessarily have to provide any additional evidence itself. If a host does provide evidence that contradicts some evidence provided by the Common Language Runtime, then the host-provided evidence overrides the other evidence. Any host-provided evidence that doesn't override evidence provided by the Common Language Runtime is just merged into the collection of host-provided evidence.

Unmanaged Hosts

An unmanaged host is necessary to run any .NET Framework application. Certainly, something must start the Common Language Runtime. The .NET Framework ships with several different hosts. Some examples are ASP.NET, Internet Explorer, and the command-line host. All three of these hosts are capable of starting a .NET application, and all three can provide evidence about the applications they start.

The security functionality of the .NET Framework depends on another entity providing prior knowledge of managed code. The host provides the .NET Framework with information such as the root directory for an application, because the Common Language Runtime cannot determine this information. This can be done by using the ICorRuntimeHost interface. When a call is made to CorBindToRuntimeEx to start the Common Language Runtime, an interface pointer to ICorRuntimeHost is returned. Using that pointer, calls can be made to CreateEvidence and CreateDomain / CreateDomainEx to create evidence objects and apply them to an app domain, respectively.

An unmanaged host can only provide evidence on an app domain. There is no unmanaged method that loads an assembly, but the unmanaged host can transfer control to a managed piece of code that will load and provide evidence about assemblies.

To learn more about unmanaged hosts, see the .NET Framework SDK documentation under "Programming with the .NET Framework," "Hosting the Common Language Runtime."

Managed Hosts

A managed host is simply some code that loads and executes other arbitrary, managed code. Not all managed code can do this due to security mechanisms that will be explained later in this section. Suffice it to say that it takes a high degree of trust for a piece of managed code to act as a host.

Most unmanaged hosts will also have a managed piece with which to work. This is because it is simpler and more efficient to transfer control to a managed host that then launches managed user code. Thus, a likely scenario would be to have a host use its unmanaged code to set evidence on an app domain, while its managed code sets evidence on user assemblies.

Table 5.1 lists several methods a managed host might call to provide evidence on assemblies and app domains. Note that these methods often have several forms, some of which do not have arguments for passing evidence. The forms without evidence arguments simply use the default evidence provided by the Common Language Runtime.

Table 5.1. Methods a Managed Host Might Call to Provide Evidence About Code It Loads and Executes
Method Description
 System.Reflection.Assembly.Load System.Reflection.Assembly.LoadFrom System.Reflection.Assembly.LoadWithPartialName 
These methods load an assembly. They allow a trusted host to state additional evidence that the Common Language Runtime should take into account when determining how much trust should be granted to the assembly. Load loads an assembly from the Global Assembly Cache given its full name (friendly name , version, public key, and culture). LoadFrom loads an assembly from the file system. LoadWithPartialName loads an assembly from the Global Assembly Cache given just part of its full name.
 System.Activator.CreateInstance System.Activator.CreateInstanceFrom 
These methods create an instance of a class from a specified assembly. Evidence can be provided to apply to the assembly that contains the given class. CreateInstance loads an assembly from the Global Assembly Cache given its full name (friendly name, version, public key, and culture). CreateInstanceFrom loads an assembly from the file system.
 System.AppDomain.CreateInstance System.AppDomain.CreateInstanceAndUnwrap System.AppDomain.CreateInstanceFrom System.AppDomain.CreateInstanceFromAndUnwrap 
Similar to the Activator methods, these methods create an instance of a class from a specified assembly. However, in this case, the instance of the class is created in the calling AppDomain instead of the current AppDomain . As before, the methods without From load the assembly from the Global Assembly Cache, while the methods with From load the assembly from the file system. The methods without AndUnwrap return an ObjectHandle , while the methods with AndUnwrap return an Object . Note that if the class of the object being created does not inherit from MarshalByRefObject , cross-domain access is marshaled by value, which can lead to unexpected results.
System.AppDomain.CreateDomain This method creates an app domain with the specified evidence.
System.AppDomain.DefineDynamicAssembly This method is used to define an assembly in a specific AppDomain at runtime that wasn't previously persisted on disk. When the assembly is defined, evidence is provided so that the Common Language Runtime can determine how much trust to give it when it is used.
System.AppDomain.ExecuteAssembly This method is used to execute an assembly in the calling AppDomain . A simple managed host might create a specific AppDomain and call this method to execute a user assembly with specific evidence.
System.AppDomain.Load This method is identical in purpose to Assembly.Load except that the specified assembly is loaded into the calling AppDomain .

Assembly-Provided Evidence

While hosts provide trusted evidence regarding an assembly, an assembly is permitted to provide evidence about itself. This evidence, however, cannot override any evidence provided by a host because that would be a security hole. In fact, all default evidence classes used in assembly evidence are completely ignored by the Common Language Runtime.

Because the Evidence class uses generic collections to store information, it can contain any object as evidence. Consequently, an assembly could provide evidence as plain as an integer or as rich as a signed XML statement. They are all equally simple to add to evidence, though they may not all be equally useful.

TIP

If you want to author a class that will be assembly evidence, there are two optional interfaces to consider implementing. The first is IIdentityPermissionFactory . (Permissions are discussed in detail in Chapter 6, "Permissions: The Workhorse of Code Access Security.") If you have an identity permission class that corresponds to your evidence, this interface defines a standard way for the Common Language Runtime to create a corresponding identity permission object. The second interface is InormalizeForIsolatedStorage . ( IsolatedStorage is discussed in detail in Chapter 29, "Writing a Semi-Trusted Application.") If you want to create an IsolatedStorage class that uses your custom evidence for isolation, this interface provides a way for the Common Language Runtime to compare serialized evidence objects.


Assembly-provided evidence can be used to state more information about how much an assembly should be trusted. For example, an assembly developer may have submitted his or her application to a third-party software certification lab. The certification lab could provide a signed statement that the developer could attach to his or her assembly as evidence. This statement could say that the lab certifies that the application can safely be granted a high level of trust.

Note that simply providing additional evidence on an assembly will do nothing by itself. To see the real benefits of providing assembly evidence, the Common Language Runtime will have to do something with it. That will probably mean implementing a custom membership condition and modifying the default security policy. (Both of these topics are discussed in Chapter 8.) With the signed statement example, the security policy could look for assemblies with signed statements and assign them more trust than other assemblies.

There is a good whitepaper and some example code that goes into detail about how to add assembly evidence to your assembly. It is located on http://www.gotdotnet.com. I encourage you to read the whitepaper and its example code if you want to provide evidence on some assembly you are writing. Basically, the steps are:

  1. Create an object that represents the evidence you want your assembly to provide. This will probably be an instance of a class that you created.

  2. Serialize that object to a file using the System.Runtime.Serialization.Formatters.Binary class.

  3. Compile your .NET Framework code to a module or several modules. For the C# and VB compilers, this is done by using the /target:module option. Modules are much like .lib files used in C and C++. They are pieces of executable files or libraries.

  4. Combine the module(s) and the serialized evidence into an assembly using the ALink tool ( al.exe ) from the .NET Framework SDK. ALink has a /evidence option that is used to point to a serialized evidence file.

Because assembly evidence is something added explicitly by developers, there is no assembly evidence by default in any assemblies. You can see this if you compile and execute the code from Listing 5.1.

for RuBoard


. NET Framework Security
.NET Framework Security
ISBN: 067232184X
EAN: 2147483647
Year: 2000
Pages: 235

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