2008-05-30 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / corlib / System.Security / SecurityManager.cs
index 5d134a1dc677365ec0ab20067a2ad499e3e201aa..100fe29efff746ee1fcbf715cc02cd706d14d88e 100644 (file)
@@ -43,13 +43,28 @@ using Mono.Xml;
 
 namespace System.Security {
 
+       // Must match MonoDeclSecurityActions in /mono/metadata/reflection.h
+       internal struct RuntimeDeclSecurityActions {
+               public RuntimeDeclSecurityEntry cas;
+               public RuntimeDeclSecurityEntry noncas;
+               public RuntimeDeclSecurityEntry choice;
+       }
+
+#if NET_2_0
+       [ComVisible (true)]
+       public static class SecurityManager {
+#else
        public sealed class SecurityManager {
 
+               private SecurityManager ()
+               {
+               }
+#endif
                private static object _lockObject;
                private static ArrayList _hierarchy;
-               private static PermissionSet _fullTrust; // for [AllowPartiallyTrustedCallers]
                private static IPermission _unmanagedCode;
                private static Hashtable _declsecCache;
+               private static PolicyLevel _level;
 
                static SecurityManager () 
                {
@@ -58,10 +73,6 @@ namespace System.Security {
                        _lockObject = new object ();
                }
 
-               private SecurityManager ()
-               {
-               }
-
                // properties
 
                extern public static bool CheckExecutionRights {
@@ -69,23 +80,30 @@ namespace System.Security {
                        get;
 
                        [MethodImplAttribute (MethodImplOptions.InternalCall)]
-                       [SecurityPermission (SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPolicy)]
+                       [SecurityPermission (SecurityAction.Demand, ControlPolicy = true)]
                        set;
                }
 
+#if NET_2_0
+               [Obsolete ("The security manager cannot be turned off on MS runtime")]
+#endif
                extern public static bool SecurityEnabled {
                        [MethodImplAttribute (MethodImplOptions.InternalCall)]
                        get;
 
                        [MethodImplAttribute (MethodImplOptions.InternalCall)]
-                       [SecurityPermission (SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPolicy)]
+                       [SecurityPermission (SecurityAction.Demand, ControlPolicy = true)]
                        set;
                }
 
                // methods
 
-#if NET_2_0
-               [MonoTODO]
+#if NET_1_1
+               // NOTE: This method doesn't show in the class library status page because
+               // it cannot be "found" with the StrongNameIdentityPermission for ECMA key.
+               // But it's there!
+               // FIXME works for fulltrust (empty), documentation doesn't really make sense, type wise
+               [MonoTODO ("CAS support is experimental (and unsupported). This method only works in FullTrust.")]
                [StrongNameIdentityPermission (SecurityAction.LinkDemand, PublicKey = "0x00000000000000000400000000000000")]
                public static void GetZoneAndOrigin (out ArrayList zone, out ArrayList origin) 
                {
@@ -106,42 +124,80 @@ namespace System.Security {
                        // - Not affected by overrides (like Assert, Deny and PermitOnly)
                        // - calls IsSubsetOf even for non CAS permissions
                        //   (i.e. it does call Demand so any code there won't be executed)
+#if NET_2_0
+                       // with 2.0 identity permission are unrestrictable
                        return IsGranted (Assembly.GetCallingAssembly (), perm);
+#else
+                       if (perm is IUnrestrictedPermission)
+                               return IsGranted (Assembly.GetCallingAssembly (), perm);
+                       else
+                               return IsGrantedRestricted (Assembly.GetCallingAssembly (), perm);
+#endif
                }
 
-               internal static bool IsGranted (Assembly a, IPermission perm)
+#if !NET_2_0
+               // only for permissions that do not implement IUnrestrictedPermission
+               internal static bool IsGrantedRestricted (Assembly a, IPermission perm)
                {
-                       CodeAccessPermission grant = null;
-
-                       if (a.GrantedPermissionSet != null) {
-                               grant = (CodeAccessPermission) a.GrantedPermissionSet.GetPermission (perm.GetType ());
-                               if (grant == null) {
-                                       if (!a.GrantedPermissionSet.IsUnrestricted () || !(perm is IUnrestrictedPermission)) {
-                                               return false;
-                                       }
-                               } else if (!perm.IsSubsetOf (grant)) {
+                       PermissionSet granted = a.GrantedPermissionSet;\r
+                       if (granted != null) {\r
+                               CodeAccessPermission grant = (CodeAccessPermission) granted.GetPermission (perm.GetType ());
+                               if (!perm.IsSubsetOf (grant)) {
                                        return false;
                                }
                        }
 
-                       if (a.DeniedPermissionSet != null) {
+                       PermissionSet denied = a.DeniedPermissionSet;
+                       if (denied != null) {\r
                                CodeAccessPermission refuse = (CodeAccessPermission) a.DeniedPermissionSet.GetPermission (perm.GetType ());
                                if ((refuse != null) && perm.IsSubsetOf (refuse))
                                        return false;
                        }
                        return true;
                }
-
-               internal static bool IsGranted (Assembly a, PermissionSet ps, bool noncas)
+#endif
+               // note: in 2.0 *all* permissions (including identity permissions) support unrestricted
+               internal static bool IsGranted (Assembly a, IPermission perm)
+               {
+                       PermissionSet granted = a.GrantedPermissionSet;\r
+                       if ((granted != null) && !granted.IsUnrestricted ()) {\r
+                               CodeAccessPermission grant = (CodeAccessPermission) granted.GetPermission (perm.GetType ());\r
+                               if (!perm.IsSubsetOf (grant)) {\r
+                                       return false;\r
+                               }\r
+                       }\r
+\r
+                       PermissionSet denied = a.DeniedPermissionSet;\r
+                       if ((denied != null) && !denied.IsEmpty ()) {\r
+                               if (denied.IsUnrestricted ())\r
+                                       return false;\r
+                               CodeAccessPermission refuse = (CodeAccessPermission) a.DeniedPermissionSet.GetPermission (perm.GetType ());\r
+                               if ((refuse != null) && perm.IsSubsetOf (refuse))\r
+                                       return false;\r
+                       }\r
+                       return true;\r
+               }
+
+               internal static IPermission CheckPermissionSet (Assembly a, PermissionSet ps, bool noncas)
                {
                        if (ps.IsEmpty ())
-                               return true;
+                               return null;
 
                        foreach (IPermission p in ps) {
                                // note: this may contains non CAS permissions
                                if ((!noncas) && (p is CodeAccessPermission)) {
-                                       if (!SecurityManager.IsGranted (a, p))
-                                               return false;
+#if NET_2_0
+                                       if (!IsGranted (a, p))
+                                               return p;
+#else
+                                       if (p is IUnrestrictedPermission) {
+                                               if (!IsGranted (a, p))
+                                                       return p;
+                                       } else {
+                                               if (!IsGrantedRestricted (a, p))
+                                                       return p;
+                                       }
+#endif
                                } else {
                                        // but non-CAS will throw on failure...
                                        try {
@@ -149,14 +205,57 @@ namespace System.Security {
                                        }
                                        catch (SecurityException) {
                                                // ... so we catch
-                                               return false;
+                                               return p;
                                        }
                                }
                        }
-                       return true;
+                       return null;
+               }
+
+               internal static IPermission CheckPermissionSet (AppDomain ad, PermissionSet ps)
+               {
+                       if ((ps == null) || ps.IsEmpty ())
+                               return null;
+
+                       PermissionSet granted = ad.GrantedPermissionSet;
+                       if (granted == null)
+                               return null;
+#if NET_2_0
+                       if (granted.IsUnrestricted ())
+                               return null;
+#else
+                       if ((granted.Count == 0) && granted.IsUnrestricted ())
+                               return null;
+#endif
+                       if (ps.IsUnrestricted ())
+                               return new SecurityPermission (SecurityPermissionFlag.NoFlags);
+
+                       foreach (IPermission p in ps) {
+                               if (p is CodeAccessPermission) {
+                                       CodeAccessPermission grant = (CodeAccessPermission) granted.GetPermission (p.GetType ());
+                                       if (grant == null) {
+                                               if (!granted.IsUnrestricted () || !(p is IUnrestrictedPermission)) {
+                                                       if (!p.IsSubsetOf (null))
+                                                               return p;
+                                               }
+                                       } else if (!p.IsSubsetOf (grant)) {
+                                               return p;
+                                       }
+                               } else {
+                                       // but non-CAS will throw on failure...
+                                       try {
+                                               p.Demand ();
+                                       }
+                                       catch (SecurityException) {
+                                               // ... so we catch
+                                               return p;
+                                       }
+                               }
+                       }
+                       return null;
                }
 
-               [SecurityPermission (SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPolicy)]
+               [SecurityPermission (SecurityAction.Demand, ControlPolicy = true)]
                public static PolicyLevel LoadPolicyLevelFromFile (string path, PolicyLevelType type)
                {
                        if (path == null)
@@ -173,7 +272,7 @@ namespace System.Security {
                        return pl;
                }
 
-               [SecurityPermission (SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPolicy)]
+               [SecurityPermission (SecurityAction.Demand, ControlPolicy = true)]
                public static PolicyLevel LoadPolicyLevelFromString (string str, PolicyLevelType type)
                {
                        if (null == str)
@@ -190,7 +289,7 @@ namespace System.Security {
                        return pl;
                }
 
-               [SecurityPermission (SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPolicy)]
+               [SecurityPermission (SecurityAction.Demand, ControlPolicy = true)]
                public static IEnumerator PolicyHierarchy ()
                {
                        return Hierarchy;
@@ -213,11 +312,12 @@ namespace System.Security {
                        }
 
                        ResolveIdentityPermissions (ps, evidence);
+
                        return ps;
                }
 
 #if NET_2_0
-               [MonoTODO ("more tests are needed")]
+               [MonoTODO ("(2.0) more tests are needed")]
                public static PermissionSet ResolvePolicy (Evidence[] evidences)
                {
                        if ((evidences == null) || (evidences.Length == 0) ||
@@ -257,7 +357,6 @@ namespace System.Security {
 
                static private SecurityPermission _execution = new SecurityPermission (SecurityPermissionFlag.Execution);
 
-               [MonoTODO()]
                public static PermissionSet ResolvePolicy (Evidence evidence, PermissionSet reqdPset, PermissionSet optPset, PermissionSet denyPset, out PermissionSet denied)
                {
                        PermissionSet resolved = ResolvePolicy (evidence);
@@ -266,17 +365,26 @@ namespace System.Security {
                                throw new PolicyException (Locale.GetText (
                                        "Policy doesn't grant the minimal permissions required to execute the assembly."));
                        }
-                       // do we have the right to execute ?
+
+                       // do we check for execution rights ?
                        if (CheckExecutionRights) {
-                               // unless we have "Full Trust"...
-                               if (!resolved.IsUnrestricted ()) {
-                                       // ... we need to find a SecurityPermission
-                                       IPermission security = resolved.GetPermission (typeof (SecurityPermission));
-                                       if (!_execution.IsSubsetOf (security)) {
-                                               throw new PolicyException (Locale.GetText (
-                                                       "Policy doesn't grant the right to execute to the assembly."));
+                               bool execute = false;
+                               // an empty permissionset doesn't include Execution
+                               if (resolved != null) {
+                                       // unless we have "Full Trust"...
+                                       if (resolved.IsUnrestricted ()) {
+                                               execute = true;
+                                       } else {
+                                               // ... we need to find a SecurityPermission
+                                               IPermission security = resolved.GetPermission (typeof (SecurityPermission));
+                                               execute = _execution.IsSubsetOf (security);
                                        }
                                }
+
+                               if (!execute) {
+                                       throw new PolicyException (Locale.GetText (
+                                               "Policy doesn't grant the right to execute the assembly."));
+                               }
                        }
 
                        denied = denyPset;
@@ -299,7 +407,7 @@ namespace System.Security {
                        return al.GetEnumerator ();
                }
 
-               [SecurityPermission (SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPolicy)]
+               [SecurityPermission (SecurityAction.Demand, ControlPolicy = true)]
                public static void SavePolicy () 
                {
                        IEnumerator e = Hierarchy;
@@ -309,7 +417,7 @@ namespace System.Security {
                        }
                }
 
-               [SecurityPermission (SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPolicy)]
+               [SecurityPermission (SecurityAction.Demand, ControlPolicy = true)]
                public static void SavePolicyLevel (PolicyLevel level) 
                {
                        // Yes this will throw a NullReferenceException, just like MS (see FDBK13121)
@@ -320,12 +428,9 @@ namespace System.Security {
 
                private static IEnumerator Hierarchy {
                        get {
-                               // double-lock pattern
-                               if (_hierarchy == null) {
-                                       lock (_lockObject) {
-                                               if (_hierarchy == null)
-                                                       InitializePolicyHierarchy ();
-                                       }
+                               lock (_lockObject) {
+                                       if (_hierarchy == null)
+                                               InitializePolicyHierarchy ();
                                }
                                return _hierarchy.GetEnumerator ();
                        }
@@ -337,17 +442,25 @@ namespace System.Security {
                        // note: use InternalGetFolderPath to avoid recursive policy initialization
                        string userPolicyPath = Path.Combine (Environment.InternalGetFolderPath (Environment.SpecialFolder.ApplicationData), "mono");
 
-                       ArrayList al = new ArrayList ();
-                       al.Add (new PolicyLevel ("Enterprise", PolicyLevelType.Enterprise,
-                               Path.Combine (machinePolicyPath, "enterprisesec.config")));
+                       PolicyLevel enterprise = new PolicyLevel ("Enterprise", PolicyLevelType.Enterprise);
+                       _level = enterprise;
+                       enterprise.LoadFromFile (Path.Combine (machinePolicyPath, "enterprisesec.config"));
 
-                       al.Add (new PolicyLevel ("Machine", PolicyLevelType.Machine,
-                               Path.Combine (machinePolicyPath, "security.config")));
+                       PolicyLevel machine = new PolicyLevel ("Machine", PolicyLevelType.Machine);
+                       _level = machine;
+                       machine.LoadFromFile (Path.Combine (machinePolicyPath, "security.config"));
 
-                       al.Add (new PolicyLevel ("User", PolicyLevelType.User,
-                               Path.Combine (userPolicyPath, "security.config")));
+                       PolicyLevel user = new PolicyLevel ("User", PolicyLevelType.User);
+                       _level = user;
+                       user.LoadFromFile (Path.Combine (userPolicyPath, "security.config"));
+
+                       ArrayList al = new ArrayList ();
+                       al.Add (enterprise);
+                       al.Add (machine);
+                       al.Add (user);
 
                        _hierarchy = ArrayList.Synchronized (al);
+                       _level = null;
                }
 
                internal static bool ResolvePolicyLevel (ref PermissionSet ps, PolicyLevel pl, Evidence evidence)
@@ -371,9 +484,13 @@ namespace System.Security {
                        return false;
                }
 
-               // TODO: this changes in 2.0 as identity permissions can now be unrestricted
                internal static void ResolveIdentityPermissions (PermissionSet ps, Evidence evidence)
                {
+#if NET_2_0
+                       // in 2.0 identity permissions can now be unrestricted
+                       if (ps.IsUnrestricted ())
+                               return;
+#endif
                        // Only host evidence are used for policy resolution
                        IEnumerator ee = evidence.GetHostEnumerator ();
                        while (ee.MoveNext ()) {
@@ -385,21 +502,22 @@ namespace System.Security {
                        }
                }
 
+               internal static PolicyLevel ResolvingPolicyLevel {
+                       get { return _level; }
+                       set { _level = value; }
+               }
+
                internal static PermissionSet Decode (IntPtr permissions, int length)
                {
                        // Permission sets from the runtime (declarative security) can be cached
                        // for performance as they can never change (i.e. they are read-only).
+                       PermissionSet ps = null;
 
-                       if (_declsecCache == null) {
-                               lock (_lockObject) {
-                                       if (_declsecCache == null) {
-                                               _declsecCache = new Hashtable ();
-                                       }
+                       lock (_lockObject) {
+                               if (_declsecCache == null) {
+                                       _declsecCache = new Hashtable ();
                                }
-                       }
 
-                       PermissionSet ps = null;
-                       lock (_lockObject) {
                                object key = (object) (int) permissions;
                                ps = (PermissionSet) _declsecCache [key];
                                if (ps == null) {
@@ -425,78 +543,103 @@ namespace System.Security {
                                string xml = Encoding.Unicode.GetString (encodedPermissions);
                                return new PermissionSet (xml);
                        case 0x2E:
-                               // TODO: Fx 2.0
-                               throw new SecurityException ("Unsupported 2.0 metadata format.");
+                               // Fx 2.0 are encoded "somewhat, but not enough, like" custom attributes
+                               // note: we still support the older format!
+                               return PermissionSet.CreateFromBinaryFormat (encodedPermissions);
                        default:
-                               throw new SecurityException ("Unknown metadata format.");
+                               throw new SecurityException (Locale.GetText ("Unknown metadata format."));
                        }
                }
 
-               private static PermissionSet Union (byte[] classPermissions, byte[] methodPermissions)
-               {
-                       if (classPermissions != null) {
-                               PermissionSet ps = Decode (classPermissions);
-                               if (methodPermissions != null) {
-                                       ps = ps.Union (Decode (methodPermissions));
+               private static IPermission UnmanagedCode {
+                       get {
+                               lock (_lockObject) {
+                                       if (_unmanagedCode == null)
+                                               _unmanagedCode = new SecurityPermission (SecurityPermissionFlag.UnmanagedCode);
                                }
-                               return ps;
+                               return _unmanagedCode;
                        }
-
-                       return Decode (methodPermissions);
                }
 
                //  security check when using reflection
 
-               internal static void ReflectedLinkDemand ()
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private static unsafe extern bool GetLinkDemandSecurity (MethodBase method, RuntimeDeclSecurityActions *cdecl, RuntimeDeclSecurityActions *mdecl);
+
+               // When using reflection LinkDemand are promoted to full Demand (i.e. stack walk)
+               internal unsafe static void ReflectedLinkDemandInvoke (MethodBase mb)
                {
-                       // TODO - get the declarative LinkDemand permission set
+                       RuntimeDeclSecurityActions klass;
+                       RuntimeDeclSecurityActions method;
+
+                       if (!GetLinkDemandSecurity (mb, &klass, &method))
+                               return;
+
                        PermissionSet ps = null;
 
-                       Assembly corlib = typeof (int).Assembly;
-                       // find the real caller of the icall
-                       foreach (SecurityFrame f in SecurityFrame.GetStack (0)) {
-                               // ignore System.Reflection class in corlib
-                               if ((f.Assembly != corlib) || !f.Method.Name.StartsWith ("System.Reflection")) {
-                                       if (!SecurityManager.IsGranted (f.Assembly, ps, false))
-                                               LinkDemandSecurityException (1, f.Assembly, f.Method);
-                               }
+                       if (klass.cas.size > 0) {
+                               ps = Decode (klass.cas.blob, klass.cas.size);
+                       }
+                       if (klass.noncas.size > 0) {
+                               PermissionSet p = Decode (klass.noncas.blob, klass.noncas.size);
+                               ps = (ps == null) ? p : ps.Union (p);
+                       }
+
+                       if (method.cas.size > 0) {
+                               PermissionSet p = Decode (method.cas.blob, method.cas.size);
+                               ps = (ps == null) ? p : ps.Union (p);
+                       }
+                       if (method.noncas.size > 0) {
+                               PermissionSet p = Decode (method.noncas.blob, method.noncas.size);
+                               ps = (ps == null) ? p : ps.Union (p);
                        }
+
+                       // in this case we union-ed the permission sets because we want to do 
+                       // a single stack walk (not up to 4).
+                       if (ps != null)
+                               ps.Demand ();
+               }
+
+               internal unsafe static bool ReflectedLinkDemandQuery (MethodBase mb)
+               {
+                       RuntimeDeclSecurityActions klass;
+                       RuntimeDeclSecurityActions method;
+
+                       if (!GetLinkDemandSecurity (mb, &klass, &method))
+                               return true;
+
+                       return LinkDemand (mb.ReflectedType.Assembly, &klass, &method);
                }
 
                // internal - get called at JIT time
 
-               private static bool LinkDemand (
-                       Assembly a,
-                       IntPtr casClassPermission, int casClassLength,
-                       IntPtr nonCasClassPermission, int nonCasClassLength,
-                       IntPtr choiceClassPermission, int choiceClassLength,
-                       IntPtr casMethodPermission, int casMethodLength,
-                       IntPtr nonCasMethodPermission, int nonCasMethodLength,
-                       IntPtr choiceMethodPermission, int choiceMethodLength)
+               private static void DemandUnmanaged ()
+               {
+                       UnmanagedCode.Demand ();
+               }
+
+               private unsafe static bool LinkDemand (Assembly a, RuntimeDeclSecurityActions *klass, RuntimeDeclSecurityActions *method)
                {
                        try {
                                PermissionSet ps = null;
                                bool result = true;
-
-                               if (casClassLength > 0) {
-                                       ps = Decode (casClassPermission, casClassLength);
-                                       result = SecurityManager.IsGranted (a, ps, false);
+                               if (klass->cas.size > 0) {
+                                       ps = Decode (klass->cas.blob, klass->cas.size);
+                                       result = (SecurityManager.CheckPermissionSet (a, ps, false) == null);
                                }
-                               if (nonCasClassLength > 0) {
-                                       ps = Decode (nonCasClassPermission, nonCasClassLength);
-                                       result = SecurityManager.IsGranted (a, ps, true);
+                               if (result && (klass->noncas.size > 0)) {
+                                       ps = Decode (klass->noncas.blob, klass->noncas.size);
+                                       result = (SecurityManager.CheckPermissionSet (a, ps, true) == null);
                                }
 
-                               if (casMethodLength > 0) {
-                                       ps = Decode (casMethodPermission, casMethodLength);
-                                       result = SecurityManager.IsGranted (a, ps, false);
+                               if (result && (method->cas.size > 0)) {
+                                       ps = Decode (method->cas.blob, method->cas.size);
+                                       result = (SecurityManager.CheckPermissionSet (a, ps, false) == null);
                                }
-                               if (nonCasMethodLength > 0) {
-                                       ps = Decode (nonCasMethodPermission, nonCasMethodLength);
-                                       result = SecurityManager.IsGranted (a, ps, true);
+                               if (result && (method->noncas.size > 0)) {
+                                       ps = Decode (method->noncas.blob, method->noncas.size);
+                                       result = (SecurityManager.CheckPermissionSet (a, ps, true) == null);
                                }
-
-                               // TODO LinkDemandChoice (2.0)
                                return result;
                        }
                        catch (SecurityException) {
@@ -506,38 +649,32 @@ namespace System.Security {
 
                private static bool LinkDemandFullTrust (Assembly a)
                {
-                       // double-lock pattern
-                       if (_fullTrust == null) {
-                               lock (_lockObject) {
-                                       if (_fullTrust == null)
-                                               _fullTrust = new NamedPermissionSet ("FullTrust");
-                               }
-                       }
+                       // FullTrust is immutable (and means Unrestricted) 
+                       // so we can skip the subset operations and jump to IsUnrestricted.
+                       PermissionSet granted = a.GrantedPermissionSet;
+                       if ((granted != null) && !granted.IsUnrestricted ())
+                               return false;
 
-                       try {
-                               return SecurityManager.IsGranted (a, _fullTrust, false);
-                       }
-                       catch (SecurityException) {
+                       PermissionSet denied = a.DeniedPermissionSet;
+                       if ((denied != null) && !denied.IsEmpty ())
                                return false;
-                       }
+
+                       return true;
                }
 
                private static bool LinkDemandUnmanaged (Assembly a)
                {
-                       // double-lock pattern
-                       if (_unmanagedCode == null) {
-                               lock (_lockObject) {
-                                       if (_unmanagedCode == null)
-                                               _unmanagedCode = new SecurityPermission (SecurityPermissionFlag.UnmanagedCode);
-                               }
-                       }
-
-                       return IsGranted (a, _unmanagedCode);
+                       // note: we know that UnmanagedCode (SecurityPermission) implements IUnrestrictedPermission
+                       return IsGranted (a, UnmanagedCode);
                }
 
                // we try to provide as much details as possible to help debugging
-               private static void LinkDemandSecurityException (int securityViolation, Assembly a, MethodInfo method)
+               private static void LinkDemandSecurityException (int securityViolation, IntPtr methodHandle)
                {
+                       RuntimeMethodHandle runtimeHandle = new RuntimeMethodHandle (methodHandle);
+                       MethodInfo method = (MethodInfo)(MethodBase.GetMethodFromHandle (runtimeHandle));
+                       Assembly a = method.DeclaringType.Assembly;
+
                        string message = null;
                        AssemblyName an = null;
                        PermissionSet granted = null;
@@ -546,7 +683,7 @@ namespace System.Security {
                        IPermission failed = null;
 
                        if (a != null) {
-                               an = a.GetName ();
+                               an = a.UnprotectedGetName ();
                                granted = a.GrantedPermissionSet;
                                refused = a.DeniedPermissionSet;
                        }
@@ -557,7 +694,7 @@ namespace System.Security {
                                break;
                        case 2: // MONO_JIT_LINKDEMAND_APTC
                                message = Locale.GetText ("Partially trusted callers aren't allowed to call into this assembly.");
-                               demanded = (object) _fullTrust;
+                               demanded = (object) DefaultPolicies.FullTrust; // immutable
                                break;
                        case 4: // MONO_JIT_LINKDEMAND_ECMA
                                message = Locale.GetText ("Calling internal calls is restricted to ECMA signed assemblies.");
@@ -575,42 +712,91 @@ namespace System.Security {
                        throw new SecurityException (message, an, granted, refused, method, SecurityAction.LinkDemand, demanded, failed, null);
                }
 
+               private static void InheritanceDemandSecurityException (int securityViolation, Assembly a, Type t, MethodInfo method)
+               {
+                       string message = null;
+                       AssemblyName an = null;
+                       PermissionSet granted = null;
+                       PermissionSet refused = null;
+
+                       if (a != null) {
+                               an = a.UnprotectedGetName ();
+                               granted = a.GrantedPermissionSet;
+                               refused = a.DeniedPermissionSet;
+                       }
+
+                       switch (securityViolation) {
+                       case 1: // MONO_METADATA_INHERITANCEDEMAND_CLASS
+                               message = String.Format (Locale.GetText ("Class inheritance refused for {0}."), t);
+                               break;
+                       case 2: // MONO_METADATA_INHERITANCEDEMAND_CLASS
+                               message = Locale.GetText ("Method override refused.");
+                               break;
+                       default:
+                               message = Locale.GetText ("Load time InheritDemand failed.");
+                               break;
+                       }
+
+                       throw new SecurityException (message, an, granted, refused, method, SecurityAction.InheritanceDemand, null, null, null);
+               }
+
+#if NET_2_1
+               private static void MethodAccessException (IntPtr caller, IntPtr callee)
+               {
+                       throw new MethodAccessException (Locale.GetText ("Method call not allowed."));
+               }
+
+               private static void VerificationException ()
+               {
+                       throw new VerificationException (Locale.GetText ("Unsafe code encountered."));
+               }
+#endif
+
                // internal - get called by the class loader
 
                // Called when
                // - class inheritance
                // - method overrides
-               private static bool InheritanceDemand (Assembly a, byte[] permissions, byte[] nonCasPermissions)
+               private unsafe static bool InheritanceDemand (AppDomain ad, Assembly a, RuntimeDeclSecurityActions *actions)
                {
-                       bool result = true;
-                       if (permissions != null) {
-                               PermissionSet ps = Decode (permissions);
-                               result = SecurityManager.IsGranted (a, ps, false);
+                       try {
+                               PermissionSet ps = null;
+                               bool result = true;
+                               if (actions->cas.size > 0) {
+                                       ps = Decode (actions->cas.blob, actions->cas.size);
+                                       result = (SecurityManager.CheckPermissionSet (a, ps, false) == null);
+                                       if (result) {
+                                               // also check appdomain
+                                               result = (SecurityManager.CheckPermissionSet (ad, ps) == null);
+                                       }
+                               }
+                               if (actions->noncas.size > 0) {
+                                       ps = Decode (actions->noncas.blob, actions->noncas.size);
+                                       result = (SecurityManager.CheckPermissionSet (a, ps, true) == null);
+                                       if (result) {
+                                               // also check appdomain
+                                               result = (SecurityManager.CheckPermissionSet (ad, ps) == null);
+                                       }
+                               }
+                               return result;
                        }
-                       if (nonCasPermissions != null) {
-                               PermissionSet ps = Decode (nonCasPermissions);
-                               result &= SecurityManager.IsGranted (a, ps, true);
+                       catch (SecurityException) {
+                               return false;
                        }
-                       return result;
                }
 
+
                // internal - get called by JIT generated code
 
                private static void InternalDemand (IntPtr permissions, int length)
                {
-Console.WriteLine ("InternalDemand {0} {1}", permissions, length);
                        PermissionSet ps = Decode (permissions, length);
                        ps.Demand ();
                }
 
                private static void InternalDemandChoice (IntPtr permissions, int length)
                {
-#if NET_2_0
-                       PermissionSet ps = Decode (permissions, length);
-                       // TODO
-#else
-                       throw new SecurityException ("SecurityAction.DemandChoice is only possible in 2.0");
-#endif
+                       throw new SecurityException ("SecurityAction.DemandChoice was removed from 2.0");
                }
        }
 }