summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Security/FrameSecurityDescriptor.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Security/FrameSecurityDescriptor.cs')
-rw-r--r--src/mscorlib/src/System/Security/FrameSecurityDescriptor.cs564
1 files changed, 564 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Security/FrameSecurityDescriptor.cs b/src/mscorlib/src/System/Security/FrameSecurityDescriptor.cs
new file mode 100644
index 0000000000..8f25bda617
--- /dev/null
+++ b/src/mscorlib/src/System/Security/FrameSecurityDescriptor.cs
@@ -0,0 +1,564 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Security {
+ using System.Text;
+ using System.Runtime.CompilerServices;
+ using System.Threading;
+ using System;
+ using System.Collections;
+ using System.Security.Permissions;
+ using System.Globalization;
+ using System.Runtime.ConstrainedExecution;
+ using System.Runtime.Versioning;
+ using System.Diagnostics.Contracts;
+#if !FEATURE_PAL
+ using Microsoft.Win32.SafeHandles;
+#endif
+ //FrameSecurityDescriptor.cs
+ //
+ // Internal use only.
+ // DO NOT DOCUMENT
+ //
+
+ [Serializable]
+ internal class FrameSecurityDescriptor
+ {
+
+ /* EE has native FrameSecurityDescriptorObject definition in object.h
+ Make sure to update that structure as well, if you make any changes here.
+ */
+ private PermissionSet m_assertions; // imperative asserts
+ private PermissionSet m_denials; // imperative denials
+ private PermissionSet m_restriction; // imperative permitonlys
+ private PermissionSet m_DeclarativeAssertions;
+ private PermissionSet m_DeclarativeDenials;
+ private PermissionSet m_DeclarativeRestrictions;
+
+#if !FEATURE_PAL
+ // if this frame contains a call to any WindowsIdentity.Impersonate(),
+ // we save the previous SafeTokenHandles here (in the next two fields)
+ // Used during exceptionstackwalks to revert impersonation before calling filters
+ [System.Security.SecurityCritical] // auto-generated
+ [NonSerialized]
+ private SafeAccessTokenHandle m_callerToken;
+ [System.Security.SecurityCritical] // auto-generated
+ [NonSerialized]
+ private SafeAccessTokenHandle m_impToken;
+#endif
+
+ private bool m_AssertFT;
+ private bool m_assertAllPossible;
+#pragma warning disable 169
+ private bool m_declSecComputed; // set from the VM to indicate that the declarative A/PO/D on this frame has been populated
+#pragma warning restore 169
+
+
+
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void IncrementOverridesCount();
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void DecrementOverridesCount();
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void IncrementAssertCount();
+ [System.Security.SecurityCritical] // auto-generated
+ [MethodImplAttribute(MethodImplOptions.InternalCall)]
+ private static extern void DecrementAssertCount();
+
+
+ // Default constructor.
+ internal FrameSecurityDescriptor()
+ {
+ //m_flags = 0;
+ }
+ //-----------------------------------------------------------+
+ // H E L P E R
+ //-----------------------------------------------------------+
+
+ private PermissionSet CreateSingletonSet(IPermission perm)
+ {
+ PermissionSet permSet = new PermissionSet(false);
+ permSet.AddPermission(perm.Copy());
+ return permSet;
+ }
+
+ //-----------------------------------------------------------+
+ // A S S E R T
+ //-----------------------------------------------------------+
+
+ internal bool HasImperativeAsserts()
+ {
+ // we store declarative actions in both fields, so check if they are different
+ return (m_assertions != null);
+ }
+ internal bool HasImperativeDenials()
+ {
+ // we store declarative actions in both fields, so check if they are different
+ return (m_denials != null);
+ }
+ internal bool HasImperativeRestrictions()
+ {
+ // we store declarative actions in both fields, so check if they are different
+ return (m_restriction != null);
+ }
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetAssert(IPermission perm)
+ {
+ m_assertions = CreateSingletonSet(perm);
+ IncrementAssertCount();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetAssert(PermissionSet permSet)
+ {
+ m_assertions = permSet.Copy();
+ m_AssertFT = m_AssertFT || m_assertions.IsUnrestricted();
+ IncrementAssertCount();
+ }
+
+ internal PermissionSet GetAssertions(bool fDeclarative)
+ {
+ return (fDeclarative) ? m_DeclarativeAssertions : m_assertions;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetAssertAllPossible()
+ {
+ m_assertAllPossible = true;
+ IncrementAssertCount();
+ }
+
+ internal bool GetAssertAllPossible()
+ {
+ return m_assertAllPossible;
+ }
+
+ //-----------------------------------------------------------+
+ // D E N Y
+ //-----------------------------------------------------------+
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetDeny(IPermission perm)
+ {
+#if FEATURE_CAS_POLICY
+ BCLDebug.Assert(AppDomain.CurrentDomain.IsLegacyCasPolicyEnabled, "Deny is only valid in legacy CAS mode");
+#endif // FEATURE_CAS_POLICY
+
+ m_denials = CreateSingletonSet(perm);
+ IncrementOverridesCount();
+
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetDeny(PermissionSet permSet)
+ {
+ m_denials = permSet.Copy();
+ IncrementOverridesCount();
+ }
+
+ internal PermissionSet GetDenials(bool fDeclarative)
+ {
+ return (fDeclarative) ? m_DeclarativeDenials: m_denials;
+ }
+
+ //-----------------------------------------------------------+
+ // R E S T R I C T
+ //-----------------------------------------------------------+
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetPermitOnly(IPermission perm)
+ {
+ m_restriction = CreateSingletonSet(perm);
+ IncrementOverridesCount();
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetPermitOnly(PermissionSet permSet)
+ {
+ // permSet must not be null
+ m_restriction = permSet.Copy();
+ IncrementOverridesCount();
+ }
+
+ internal PermissionSet GetPermitOnly(bool fDeclarative)
+ {
+
+ return (fDeclarative) ? m_DeclarativeRestrictions : m_restriction;
+ }
+#if !FEATURE_PAL
+ //-----------------------------------------------------------+
+ // SafeAccessTokenHandle (Impersonation + EH purposes)
+ //-----------------------------------------------------------+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void SetTokenHandles (SafeAccessTokenHandle callerToken, SafeAccessTokenHandle impToken)
+ {
+ m_callerToken = callerToken;
+ m_impToken = impToken;
+ }
+#endif
+ //-----------------------------------------------------------+
+ // R E V E R T
+ //-----------------------------------------------------------+
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void RevertAssert()
+ {
+ if (m_assertions != null)
+ {
+ m_assertions = null;
+ DecrementAssertCount();
+ }
+
+
+ if (m_DeclarativeAssertions != null)
+ {
+ m_AssertFT = m_DeclarativeAssertions.IsUnrestricted();
+ }
+ else
+ {
+ m_AssertFT = false;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void RevertAssertAllPossible()
+ {
+ if (m_assertAllPossible)
+ {
+ m_assertAllPossible = false;
+ DecrementAssertCount();
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void RevertDeny()
+ {
+ if (HasImperativeDenials())
+ {
+ DecrementOverridesCount();
+ m_denials = null;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void RevertPermitOnly()
+ {
+ if (HasImperativeRestrictions())
+ {
+ DecrementOverridesCount();
+ m_restriction= null;;
+ }
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal void RevertAll()
+ {
+ RevertAssert();
+ RevertAssertAllPossible();
+ RevertDeny();
+ RevertPermitOnly();
+ }
+
+
+ //-----------------------------------------------------------+
+ // Demand Evaluation
+ //-----------------------------------------------------------+
+
+
+ // This will get called when we hit a FSD while evaluating a demand on the call stack or compressedstack
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool CheckDemand(CodeAccessPermission demand, PermissionToken permToken, RuntimeMethodHandleInternal rmh)
+ {
+ // imperative security
+ bool fContinue = CheckDemand2(demand, permToken, rmh, false);
+ if (fContinue == SecurityRuntime.StackContinue)
+ {
+ // declarative security
+ fContinue = CheckDemand2(demand, permToken, rmh, true);
+ }
+ return fContinue;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool CheckDemand2(CodeAccessPermission demand, PermissionToken permToken, RuntimeMethodHandleInternal rmh, bool fDeclarative)
+ {
+ PermissionSet permSet;
+
+ // If the demand is null, there is no need to continue
+ Contract.Assert(demand != null && !demand.CheckDemand(null), "Empty demands should have been filtered out by this point");
+
+ // decode imperative
+ if (GetPermitOnly(fDeclarative) != null)
+ GetPermitOnly(fDeclarative).CheckDecoded(demand, permToken);
+
+ if (GetDenials(fDeclarative) != null)
+ GetDenials(fDeclarative).CheckDecoded(demand, permToken);
+
+ if (GetAssertions(fDeclarative) != null)
+ GetAssertions(fDeclarative).CheckDecoded(demand, permToken);
+
+ // NOTE: See notes about exceptions and exception handling in FrameDescSetHelper
+
+ bool bThreadSecurity = SecurityManager._SetThreadSecurity(false);
+
+ // Check Reduction
+
+ try
+ {
+ permSet = GetPermitOnly(fDeclarative);
+ if (permSet != null)
+ {
+ CodeAccessPermission perm = (CodeAccessPermission)permSet.GetPermission(demand);
+
+ // If the permit only set does not contain the demanded permission, throw a security exception
+ if (perm == null)
+ {
+ if (!permSet.IsUnrestricted())
+ throw new SecurityException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Security_Generic"), demand.GetType().AssemblyQualifiedName), null, permSet, SecurityRuntime.GetMethodInfo(rmh), demand, demand);
+ }
+ else
+ {
+ bool bNeedToThrow = true;
+
+ try
+ {
+ bNeedToThrow = !demand.CheckPermitOnly(perm);
+ }
+ catch (ArgumentException)
+ {
+ }
+
+ if (bNeedToThrow)
+ throw new SecurityException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Security_Generic"), demand.GetType().AssemblyQualifiedName), null, permSet, SecurityRuntime.GetMethodInfo(rmh), demand, demand);
+ }
+ }
+
+ // Check Denials
+
+ permSet = GetDenials(fDeclarative);
+ if (permSet != null)
+ {
+ CodeAccessPermission perm = (CodeAccessPermission)permSet.GetPermission(demand);
+
+ // If an unrestricted set was denied and the demand implements IUnrestricted
+ if (permSet.IsUnrestricted())
+ throw new SecurityException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Security_Generic"), demand.GetType().AssemblyQualifiedName), permSet, null, SecurityRuntime.GetMethodInfo(rmh), demand, demand);
+
+ // If the deny set does contain the demanded permission, throw a security exception
+ bool bNeedToThrow = true;
+ try
+ {
+ bNeedToThrow = !demand.CheckDeny(perm);
+ }
+ catch (ArgumentException)
+ {
+ }
+ if (bNeedToThrow)
+ throw new SecurityException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Security_Generic"), demand.GetType().AssemblyQualifiedName), permSet, null, SecurityRuntime.GetMethodInfo(rmh), demand, demand);
+ }
+
+ if (GetAssertAllPossible())
+ {
+ return SecurityRuntime.StackHalt;
+ }
+
+ permSet = GetAssertions(fDeclarative);
+ // Check Assertions
+ if (permSet != null)
+ {
+
+ CodeAccessPermission perm = (CodeAccessPermission)permSet.GetPermission(demand);
+
+ // If the assert set does contain the demanded permission, halt the stackwalk
+
+ try
+ {
+ if (permSet.IsUnrestricted() || demand.CheckAssert(perm))
+ {
+ return SecurityRuntime.StackHalt;
+ }
+ }
+ catch (ArgumentException)
+ {
+ }
+ }
+
+ }
+ finally
+ {
+ if (bThreadSecurity)
+ SecurityManager._SetThreadSecurity(true);
+ }
+
+ return SecurityRuntime.StackContinue;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool CheckSetDemand(PermissionSet demandSet,
+ out PermissionSet alteredDemandSet,
+ RuntimeMethodHandleInternal rmh)
+ {
+ // imperative security
+ PermissionSet altPset1 = null, altPset2 = null;
+ bool fContinue = CheckSetDemand2(demandSet, out altPset1, rmh, false);
+ if (altPset1 != null)
+ {
+ demandSet = altPset1;
+ }
+
+ if (fContinue == SecurityRuntime.StackContinue)
+ {
+ // declarative security
+ fContinue = CheckSetDemand2(demandSet, out altPset2, rmh, true);
+ }
+ // Return the most recent altered set
+ // If both declarative and imperative asserts modified the demand set: return altPset2
+ // Else if imperative asserts modified the demand set: return altPset1
+ // else no alteration: return null
+ if (altPset2 != null)
+ alteredDemandSet = altPset2;
+ else if (altPset1 != null)
+ alteredDemandSet = altPset1;
+ else
+ alteredDemandSet = null;
+
+ return fContinue;
+ }
+
+ [System.Security.SecurityCritical] // auto-generated
+ internal bool CheckSetDemand2(PermissionSet demandSet,
+ out PermissionSet alteredDemandSet,
+ RuntimeMethodHandleInternal rmh, bool fDeclarative)
+ {
+ PermissionSet permSet;
+
+ // In the common case we are not going to alter the demand set, so just to
+ // be safe we'll set it to null up front.
+ alteredDemandSet = null;
+
+ // There's some oddness in here to deal with exceptions. The general idea behind
+ // this is that we need some way of dealing with custom permissions that may not
+ // handle all possible scenarios of Union(), Intersect(), and IsSubsetOf() properly
+ // (they don't support it, throw null reference exceptions, etc.).
+
+ // An empty demand always succeeds.
+ if (demandSet == null || demandSet.IsEmpty())
+ return SecurityRuntime.StackHalt;
+
+ if (GetPermitOnly(fDeclarative) != null)
+ GetPermitOnly(fDeclarative).CheckDecoded( demandSet );
+ if (GetDenials(fDeclarative) != null)
+ GetDenials(fDeclarative).CheckDecoded( demandSet );
+ if (GetAssertions(fDeclarative) != null)
+ GetAssertions(fDeclarative).CheckDecoded( demandSet );
+
+
+ bool bThreadSecurity = SecurityManager._SetThreadSecurity(false);
+
+ try
+ {
+ // In the case of permit only, we define an exception to be failure of the check
+ // and therefore we throw a security exception.
+
+ permSet = GetPermitOnly(fDeclarative);
+ if (permSet != null)
+ {
+ IPermission permFailed = null;
+ bool bNeedToThrow = true;
+
+ try
+ {
+ bNeedToThrow = !demandSet.CheckPermitOnly(permSet, out permFailed);
+ }
+ catch (ArgumentException)
+ {
+ }
+ if (bNeedToThrow)
+ throw new SecurityException(Environment.GetResourceString("Security_GenericNoType"), null, permSet, SecurityRuntime.GetMethodInfo(rmh), demandSet, permFailed);
+ }
+
+ // In the case of denial, we define an exception to be failure of the check
+ // and therefore we throw a security exception.
+
+ permSet = GetDenials(fDeclarative);
+
+
+ if (permSet != null)
+ {
+ IPermission permFailed = null;
+
+ bool bNeedToThrow = true;
+
+ try
+ {
+ bNeedToThrow = !demandSet.CheckDeny(permSet, out permFailed);
+ }
+ catch (ArgumentException)
+ {
+ }
+
+ if (bNeedToThrow)
+ throw new SecurityException(Environment.GetResourceString("Security_GenericNoType"), permSet, null, SecurityRuntime.GetMethodInfo(rmh), demandSet, permFailed);
+ }
+
+ // The assert case is more complex. Since asserts have the ability to "bleed through"
+ // (where part of a demand is handled by an assertion, but the rest is passed on to
+ // continue the stackwalk), we need to be more careful in handling the "failure" case.
+ // Therefore, if an exception is thrown in performing any operation, we make sure to keep
+ // that permission in the demand set thereby continuing the demand for that permission
+ // walking down the stack.
+
+ if (GetAssertAllPossible())
+ {
+ return SecurityRuntime.StackHalt;
+ }
+
+ permSet = GetAssertions(fDeclarative);
+ if (permSet != null)
+ {
+ // If this frame asserts a superset of the demand set we're done
+
+ if (demandSet.CheckAssertion( permSet ))
+ return SecurityRuntime.StackHalt;
+
+ // Determine whether any of the demand set asserted. We do this by
+ // copying the demand set and removing anything in it that is asserted.
+
+ if (!permSet.IsUnrestricted())
+ {
+ PermissionSet.RemoveAssertedPermissionSet(demandSet, permSet, out alteredDemandSet);
+ }
+ }
+
+ }
+ finally
+ {
+ if (bThreadSecurity)
+ SecurityManager._SetThreadSecurity(true);
+ }
+
+ return SecurityRuntime.StackContinue;
+ }
+ }
+
+#if FEATURE_COMPRESSEDSTACK
+ // Used by the stack compressor to communicate a DynamicResolver to managed code during a stackwalk.
+ // The JIT will not actually place these on frames.
+ internal class FrameSecurityDescriptorWithResolver : FrameSecurityDescriptor
+ {
+ private System.Reflection.Emit.DynamicResolver m_resolver;
+
+ public System.Reflection.Emit.DynamicResolver Resolver
+ {
+ get
+ {
+ return m_resolver;
+ }
+ }
+ }
+#endif // FEATURE_COMPRESSEDSTACK
+}