Jump to navigation

Poupou's Corner of the Web

Looking for perfect security? Try a wireless brick.
Otherwise you may find some unperfect stuff here...

Weblog

Mono Security Manager Part I - Using CAS permissions

Here's the first promised CAS sample for Mono.

using System; using System.Security; using System.Security.Permissions; public class Program { public void Quit (int rc) { Console.WriteLine ("Trying to quit with {0}...", rc); // this requires permission to execute unmanaged code Environment.Exit (rc); } [SecurityPermission (SecurityAction.Deny, UnmanagedCode=true)] public void Loop () { while (true) { Console.Write ("> "); switch (Console.ReadLine ().ToLower ()) { case "endloop": // quit loop return; case "quit": try { Quit (1); } catch (SecurityException se) { Console.WriteLine (se.ToString ()); } break; default: Console.WriteLine ("* Unknown command. Try 'quit' or 'endloop'"); break; } } } static void Main () { Console.WriteLine ("Security is {0}", SecurityManager.SecurityEnabled ? "ON" : "OFF"); Program p = new Program (); p.Loop (); // if we're running at FullTrust (default) then this will work // without problem (i.e. no SecurityException) p.Quit (0); } }

As you can see the sample is quite simple - the Loop method denies any request to call unmanaged code. Either via directly using P/Invoke or by using framework methods that requires the privilege to call unmanaged code. The later case is being demonstrated in the sample when calling the Environment.Exit static method.

Here's the definition for System.Environment.Exit(Int32):

[MethodImplAttribute (MethodImplOptions.InternalCall)] [SecurityPermission (SecurityAction.Demand, UnmanagedCode=true)] public extern static void Exit (int exitCode);

First line:
The MethodImplOptions.InternalCall indicates that the actual implementation of the method resides in the Mono runtime. The security manager doesn't enforce any restriction to execute this icall because the type, Environment, and the method, Exit are both public and because Mono 1.1.4 doesn't (yet) enforce restrictions on calling runtime's icalls (but this feature is already in SVN for HEAD users).

Second line:
The security manager (if active) will initiate a stack walk to ensure that all callers on the stack have the rights to call unmanaged code. In this case both the executing assembly (e.g. exit.exe) and mscorlib.dll are in the local file system and are granted FullTrust. This means that, under normal condition, the call to Exit should succeed.

Third line:
The definition of the method call.

Now let's compile the sample code and try to execute it without enabling the security manager.

> mcs exit.cs > mono exit.exe Security is OFF >

The sample starts by indicating the status of the security manager. In this case (OFF) nothing can stop you from quiting the application before ending the loop. Type quit followed by ENTER to quit the sample. While this isn't a big problem when running an application at FullTrust it's more a problem if you are hosting mono inside your application (e.g. a database server supporting C# stored proc) or if you have a plug-in system.

Next execute again the sample code with the security manager enabled:

mono --security exit.exe Security is ON >

In this case (ON) the security manager will stops you from quitting the application directly from inside the loop (i.e. where the Deny declarative security attribute applies). Type quit followed by ENTER. You should see the text from the SecurityException thrown from the security manager. Now type endloop followed by ENTER to quit the sample.

Note that this sample isn't very secure (i.e. don't use that pattern) as the loop is still running at FullTrust - there are much better way to sandbox code than to use Deny. You will also get the same behaviour (by default) using MS Framework on Windows. However calling "exit" in a Windows' shell will close the shell - not execute the program - so be sure to specify the ending .exe in the command line.

Now this sample works because Demand (i.e. stack walks) is functional in Mono 1.1.4 as are the declarative stack modifiers (e.g. Deny) and most important because I added the proper security checks (either in declarative or imperative form) to the System.Environment class before the 1.1.4 release. This means that similar cases with different classes won't work because there is no security permission to protect them (yet)! But nothings stops you from adding permissions into your own code today ;-)

Next stop... identity permissions!


2/21/2005 08:51:50 | Comments

The views expressed on this website/weblog are mine alone and do not necessarily reflect the views of my employer.