Relying on the AppDomain for Managed Code


Relying on the AppDomain for Managed Code

The application domain in which your program executes determines its access to resources and services. The application domain is a kind of container that determines the security settings for an application and isolates it (from a security perspective) from other applications. A single application can have more than one application domain—you can create a different application domain for each assembly that you load. In short, every assembly for an application can have different security settings, which means your control over the assemblies is robust. At the center of all this control is the AppDomain class.

We initially discussed the AppDomain class in Chapter 1 as part of the “Using Role-based Security” section discussion. The example in Chapter 1 assumed that the application has a single application domain and used that fact to determine information about the principal of that domain. The context in which the program executes determines how role-based security works. (See the “Understanding the System.Runtime.Remoting.Contexts Namespace” section of Chapter 2 for a discussion of the effects of context on your application.) By controlling the application domain, you not only control the application, but also the code access and role-based security for that application.

Accessing Another Application

The example in this section goes further than simply telling you that every application has at least one AppDomain object you can use to discover information about the user’s role or the ability of code to access specific features. The example demonstrates how you can create multiple application domains in which you can load assemblies to control their access to specific functionality. Listing 6.2 shows the code you need for this example. (You can find this example in the \Chapter 06\C#\ManagedAppDomain or \Chapter 06\VB\ManagedAppDomain folder of the source code located on the Sybex Web site.)

Listing 6.2 Using Multiple AppDomain Objects to Control Access

start example
private void btnTest2_Click(object sender, System.EventArgs e) {    AppDomainSetup APS;        // Setup information for the domain.    Evidence       EV;         // New evidence for the domain.    AppDomain      LoadApp;    // The application domain.    DoSomething    MyComp;     // An intance of the component.    // Create the domain setup information.    APS = new AppDomainSetup();    APS.ApplicationName = "MyLoadedApplication";    // Get evidence for the domain.    EV = AppDomain.CurrentDomain.Evidence;    // Create the application domain.    LoadApp = AppDomain.CreateDomain("MyLoadedApplication", EV, APS);    // Execute the program.    LoadApp.ExecuteAssembly(Application.StartupPath +                            "\\LoadedApplication.EXE");    // Create a local copy of the test component.    MyComp = new DoSomething();    // Execute the SayHello() method.    MessageBox.Show(MyComp.GetDomain()); }
end example

The code begins by creating a new application domain setup. CLR passes this object to the new application domain and can contain any of a number of values. The example is defined only the ApplicationName property because that’s all you really need to verify the actual domain the other application uses. In general, you want to define the AppDomainSetup object to ensure that the new domain uses the features you want and for testing purposes—to ensure that the security measures work the way you think they will.

You also need to create evidence for the new AppDomain object. This evidence can include anything we’ve discussed in other areas of the book. For example, you can provide specific permissions as part of the evidence. The point is that you can define the security environment to meet specific needs.

The next step is to create the application domain and execute the application. The code uses the CreateDomain() method to create the new application domain. You can use other sets of arguments. For that matter, you can create a domain by providing the friendly name, which is MyLoadedApplication for the example. Executing the code is relatively easy—just use the ExecuteAssembly() method as shown. Some versions of this call even accept command line parameters.

This portion of the example ends by creating a copy of the text component used by the sample application. It uses the MyComp.GetDomain() method to display the AppDomain value of the current assembly. You’ll find that the sample application has an AppDomain value of MyLoadedApplication, while the current assembly uses ManagedAppDomain.EXE. Listing 6.3 shows the code used for the sample application.

Listing 6.3 A Simple Test Application

start example
namespace LoadedApplication {    public class LoadTest    {       [STAThread]       static void Main()       {          DoSomething MyComp;   // Create the test component.          // Instantiate the component.          MyComp = new DoSomething();          // Display the friendly name.          MessageBox.Show(MyComp.GetDomain());       }    } }
end example

All this application does is load a test component and use the text component’s GetDomain() method to detect the current domain FriendlyName value. The example doesn’t even use a full Windows application—this is a modified console application used to display a MessageBox object. Listing 6.4 shows the test component used for this example.

Listing 6.4 Domain FriendlyName Detection Component

start example
namespace LoadedAssembly {    public class DoSomething    {       public String GetDomain()       {          AppDomain   MyDomain;   // The current domain.          // Get the current domain.          MyDomain = Thread.GetDomain();          // Return the friendly name to the caller.          return MyDomain.FriendlyName;       }    } }
end example

This component obtains a copy of the current domain using the Thread.GetDomain() method. It uses this object to return the FriendlyName value to the caller. Using this simple component lets you see that the sample application is actually executing in its own AppDomain because the name differs from the AppDomain value of the main application.

Understanding Component Access Problems

Executing code in a separate AppDomain is relatively easy. The code in Listing 6.2 shows that you only need to add a few lines of code to create the AppDomain, place an application in it, and execute that application. Some people may confuse the idea of an AppDomain and a thread. However, if you spend some time in the debugger, you’ll find that the example in Listing 6.2 executes in the current thread. Threads can have multiple AppDomain objects (they can only use one at a time) and AppDomain objects can use multiple threads.

Components present a problem that you might not consider because of the ease with which you can create an application. Listing 6.5 shows how you would use an AppDomain to create an instance of a component. (You can find this example in the \Chapter 06\C#\ManagedAppDomain or \Chapter 06\VB\ManagedAppDomain folder of the source code located on the Sybex Web site.)

Listing 6.5 Creating a Component from an AppDomain Object

start example
private void btnTest_Click(object sender, System.EventArgs e) {    AppDomainSetup APS;        // Setup information for the domain.    Evidence       EV;         // New evidence for the domain.    AppDomain      LoadComp;   // The application domain.    Assembly       ExtComp;    // External assembly.    DoSomething    CompInst;   // An instance of the component.    // Create the domain setup information.    APS = new AppDomainSetup();    APS.ApplicationName = "LoadedComponent";    // Get evidence for the domain.    EV = AppDomain.CurrentDomain.Evidence;    // Create the application domain.    LoadComp = AppDomain.CreateDomain("LoadedComponent", EV, APS);    // Load the assembly.    ExtComp = LoadComp.Load("LoadedAssembly");    // Create an instance of the component.    CompInst =      (DoSomething)ExtComp.CreateInstance("LoadedAssembly.DoSomething");    // Execute the SayHello() method.    MessageBox.Show(CompInst.GetDomain()); }
end example

Notice that this example (Listing 6.5) uses the same three step process to create the application domain as Listing 6.2: create the AppDomainSetup object, create an Evidence object, and then create the AppDomain using the CreateDomain() method. You know from the previous example that the AppDomain is most definitely different from the AppDomain used by the current application. It would seem that anything you do with that AppDomain would remain separate.

The example code uses the Load() method to load an assembly that contains a component. Note that you can’t use the ExecuteAssembly() method because you have to instantiate the component. The loaded assembly is, in fact, in a separate domain. However, the moment you use the CreateInstance() method to create an instance of the component located in the loaded assembly, something happens. CLR moves the component from the AppDomain of the loaded assembly into the AppDomain of the current application. The MessageBox.Show(CompInst.GetDomain()) call proves that the component is executing in the ManagedAppDomain.EXE AppDomain and not the LoadedComponent AppDomain.

The important thing to remember is that you must test the security setup you create to determine how CLR actually uses the objects you create. An incorrect assumption can give you the illusion of executing in a separate AppDomain even when the separation doesn’t exist. This code executes without error—you would never know there’s a potential security hole without checking the FriendlyName value. (See Listing 6.4 for an example of the FriendlyName property in use.)




.Net Development Security Solutions
.NET Development Security Solutions
ISBN: 0782142664
EAN: 2147483647
Year: 2003
Pages: 168

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