diff options
author | Sebastien Pouliot <sebastien@ximian.com> | 2005-02-10 15:36:48 +0300 |
---|---|---|
committer | Sebastien Pouliot <sebastien@ximian.com> | 2005-02-10 15:36:48 +0300 |
commit | 556928c51719b936a1a9eb56da1d9bb11572402b (patch) | |
tree | 6dcf740f8d22a1c3107f42e783e476c503499c2d /mcs/class/corlib/System.Security/SecurityManager.cs | |
parent | 84c0a9163439dc3a9a31074202af7c9d724d5106 (diff) |
2005-02-10 Sebastien Pouliot <sebastien@ximian.com>
* SecurityException.cs: Show more information when a SecurityException
occurs to help debugging.
* SecurityManager.cs: Reworked LinkDemand implementation. Supply more
informations when throwing a SecurityException for LinkDemand.
* PermissionSet.cs: Remove (now) unused code for LinkDemand.
svn path=/trunk/mcs/; revision=40392
Diffstat (limited to 'mcs/class/corlib/System.Security/SecurityManager.cs')
-rw-r--r-- | mcs/class/corlib/System.Security/SecurityManager.cs | 109 |
1 files changed, 77 insertions, 32 deletions
diff --git a/mcs/class/corlib/System.Security/SecurityManager.cs b/mcs/class/corlib/System.Security/SecurityManager.cs index cf8f1cee62d..5d134a1dc67 100644 --- a/mcs/class/corlib/System.Security/SecurityManager.cs +++ b/mcs/class/corlib/System.Security/SecurityManager.cs @@ -48,6 +48,7 @@ namespace System.Security { private static object _lockObject; private static ArrayList _hierarchy; private static PermissionSet _fullTrust; // for [AllowPartiallyTrustedCallers] + private static IPermission _unmanagedCode; private static Hashtable _declsecCache; static SecurityManager () @@ -131,6 +132,30 @@ namespace System.Security { return true; } + internal static bool IsGranted (Assembly a, PermissionSet ps, bool noncas) + { + if (ps.IsEmpty ()) + return true; + + foreach (IPermission p in ps) { + // note: this may contains non CAS permissions + if ((!noncas) && (p is CodeAccessPermission)) { + if (!SecurityManager.IsGranted (a, p)) + return false; + } else { + // but non-CAS will throw on failure... + try { + p.Demand (); + } + catch (SecurityException) { + // ... so we catch + return false; + } + } + } + return true; + } + [SecurityPermission (SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPolicy)] public static PolicyLevel LoadPolicyLevelFromFile (string path, PolicyLevelType type) { @@ -391,6 +416,9 @@ namespace System.Security { internal static PermissionSet Decode (byte[] encodedPermissions) { + if ((encodedPermissions == null) || (encodedPermissions.Length < 1)) + throw new SecurityException ("Invalid metadata format."); + switch (encodedPermissions [0]) { case 60: // Fx 1.0/1.1 declarative security permissions metadata is in Unicode-encoded XML @@ -419,23 +447,18 @@ namespace System.Security { // security check when using reflection - internal static void ReflectedLinkDemandEcma () + internal static void ReflectedLinkDemand () { + // TODO - get the declarative LinkDemand permission set + 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")) { - // else check for the ECMA key - byte[] pk = f.Assembly.GetName ().GetPublicKey (); - if ((pk != null) && (pk.Length == 16) && (pk [8] == 0x04)) { - int n = 0; - for (int i=0; i < pk.Length; i++) - n += pk [i]; - if (n == 4) - return; - } - LinkDemandSecurityException (4, f.Assembly); + if (!SecurityManager.IsGranted (f.Assembly, ps, false)) + LinkDemandSecurityException (1, f.Assembly, f.Method); } } } @@ -443,6 +466,7 @@ namespace System.Security { // internal - get called at JIT time private static bool LinkDemand ( + Assembly a, IntPtr casClassPermission, int casClassLength, IntPtr nonCasClassPermission, int nonCasClassLength, IntPtr choiceClassPermission, int choiceClassLength, @@ -452,26 +476,28 @@ namespace System.Security { { try { PermissionSet ps = null; + bool result = true; + if (casClassLength > 0) { ps = Decode (casClassPermission, casClassLength); - ps.ImmediateCallerDemand (); + result = SecurityManager.IsGranted (a, ps, false); } if (nonCasClassLength > 0) { ps = Decode (nonCasClassPermission, nonCasClassLength); - ps.ImmediateCallerNonCasDemand (); + result = SecurityManager.IsGranted (a, ps, true); } if (casMethodLength > 0) { ps = Decode (casMethodPermission, casMethodLength); - ps.ImmediateCallerDemand (); + result = SecurityManager.IsGranted (a, ps, false); } if (nonCasMethodLength > 0) { ps = Decode (nonCasMethodPermission, nonCasMethodLength); - ps.ImmediateCallerNonCasDemand (); + result = SecurityManager.IsGranted (a, ps, true); } // TODO LinkDemandChoice (2.0) - return true; + return result; } catch (SecurityException) { return false; @@ -487,10 +513,9 @@ namespace System.Security { _fullTrust = new NamedPermissionSet ("FullTrust"); } } + try { - // FIXME: to be optimized with a flag - _fullTrust.ImmediateCallerDemand (); - return true; + return SecurityManager.IsGranted (a, _fullTrust, false); } catch (SecurityException) { return false; @@ -499,36 +524,55 @@ namespace System.Security { private static bool LinkDemandUnmanaged (Assembly a) { - return IsGranted (a, new SecurityPermission (SecurityPermissionFlag.UnmanagedCode)); + // double-lock pattern + if (_unmanagedCode == null) { + lock (_lockObject) { + if (_unmanagedCode == null) + _unmanagedCode = new SecurityPermission (SecurityPermissionFlag.UnmanagedCode); + } + } + + return IsGranted (a, _unmanagedCode); } - private static void LinkDemandSecurityException (int securityViolation, Assembly a) + // we try to provide as much details as possible to help debugging + private static void LinkDemandSecurityException (int securityViolation, Assembly a, MethodInfo method) { string message = null; + AssemblyName an = null; + PermissionSet granted = null; + PermissionSet refused = null; + object demanded = null; + IPermission failed = null; + + if (a != null) { + an = a.GetName (); + granted = a.GrantedPermissionSet; + refused = a.DeniedPermissionSet; + } + switch (securityViolation) { case 1: // MONO_JIT_LINKDEMAND_PERMISSION message = Locale.GetText ("Permissions refused to call this method."); break; case 2: // MONO_JIT_LINKDEMAND_APTC message = Locale.GetText ("Partially trusted callers aren't allowed to call into this assembly."); + demanded = (object) _fullTrust; break; case 4: // MONO_JIT_LINKDEMAND_ECMA message = Locale.GetText ("Calling internal calls is restricted to ECMA signed assemblies."); break; case 8: // MONO_JIT_LINKDEMAND_PINVOKE message = Locale.GetText ("Calling unmanaged code isn't allowed from this assembly."); + demanded = (object) _unmanagedCode; + failed = _unmanagedCode; break; default: message = Locale.GetText ("JIT time LinkDemand failed."); break; } - AssemblyName an = null; - if (a != null) - an = a.GetName (); - - // TODO - add more details to the exception - throw new SecurityException (message, an, null, null, null, SecurityAction.LinkDemand, null, null, null); + throw new SecurityException (message, an, granted, refused, method, SecurityAction.LinkDemand, demanded, failed, null); } // internal - get called by the class loader @@ -536,24 +580,25 @@ namespace System.Security { // Called when // - class inheritance // - method overrides - private static void InheritanceDemand (byte[] permissions, byte[] nonCasPermissions) + private static bool InheritanceDemand (Assembly a, byte[] permissions, byte[] nonCasPermissions) { + bool result = true; if (permissions != null) { PermissionSet ps = Decode (permissions); - if (ps != null) - ps.ImmediateCallerDemand (); + result = SecurityManager.IsGranted (a, ps, false); } if (nonCasPermissions != null) { PermissionSet ps = Decode (nonCasPermissions); - if (ps != null) - ps.ImmediateCallerNonCasDemand (); + result &= SecurityManager.IsGranted (a, ps, true); } + 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 (); } |