diff options
Diffstat (limited to 'src/mscorlib/src/System/Security/PermissionListSet.cs')
-rw-r--r-- | src/mscorlib/src/System/Security/PermissionListSet.cs | 554 |
1 files changed, 554 insertions, 0 deletions
diff --git a/src/mscorlib/src/System/Security/PermissionListSet.cs b/src/mscorlib/src/System/Security/PermissionListSet.cs new file mode 100644 index 0000000000..7eb13a72cf --- /dev/null +++ b/src/mscorlib/src/System/Security/PermissionListSet.cs @@ -0,0 +1,554 @@ +// 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. + +/*============================================================================= +** +** +** +** +** +** Purpose: Holds state about A/G/R permissionsets in a callstack or appdomain +** (Replacement for PermissionListSet) +** +=============================================================================*/ + +namespace System.Security +{ + using System.Globalization; + using System.Reflection; + using System.Runtime.InteropServices; + using System.Security; + using System.Security.Permissions; + using System.Threading; + using System.Collections; + using System.Collections.Generic; + using System.Diagnostics.Contracts; + + [Serializable] + sealed internal class PermissionListSet + { + // Only internal (public) methods are creation methods and demand evaluation methods. + // Scroll down to the end to see them. + private PermissionSetTriple m_firstPermSetTriple; + private ArrayList m_permSetTriples; +#if FEATURE_COMPRESSEDSTACK + private ArrayList m_zoneList; + private ArrayList m_originList; +#endif // FEATURE_COMPRESSEDSTACK + + internal PermissionListSet() {} + + private void EnsureTriplesListCreated() + { + if (m_permSetTriples == null) + { + m_permSetTriples = new ArrayList(); + if (m_firstPermSetTriple != null) + { + m_permSetTriples.Add(m_firstPermSetTriple); + m_firstPermSetTriple = null; + } + } + } + +#if FEATURE_PLS + [System.Security.SecurityCritical] // auto-generated + internal void UpdateDomainPLS (PermissionListSet adPLS) { + if (adPLS != null && adPLS.m_firstPermSetTriple != null) + UpdateDomainPLS(adPLS.m_firstPermSetTriple.GrantSet, adPLS.m_firstPermSetTriple.RefusedSet); + } + + [System.Security.SecurityCritical] // auto-generated + internal void UpdateDomainPLS (PermissionSet grantSet, PermissionSet deniedSet) { + Contract.Assert(m_permSetTriples == null, "m_permSetTriples != null"); + if (m_firstPermSetTriple == null) + m_firstPermSetTriple = new PermissionSetTriple(); + + // update the grant and denied sets + m_firstPermSetTriple.UpdateGrant(grantSet); + m_firstPermSetTriple.UpdateRefused(deniedSet); + } +#endif // FEATURE_PLS + + private void Terminate(PermissionSetTriple currentTriple) + { + UpdateTripleListAndCreateNewTriple(currentTriple, null); + } + + [System.Security.SecurityCritical] // auto-generated + private void Terminate(PermissionSetTriple currentTriple, PermissionListSet pls) + { +#if FEATURE_COMPRESSEDSTACK + this.UpdateZoneAndOrigin(pls); +#endif // FEATURE_COMPRESSEDSTACK + this.UpdatePermissions(currentTriple, pls); + this.UpdateTripleListAndCreateNewTriple(currentTriple, null); + } + + [System.Security.SecurityCritical] // auto-generated + private bool Update(PermissionSetTriple currentTriple, PermissionListSet pls) + { +#if FEATURE_COMPRESSEDSTACK + this.UpdateZoneAndOrigin(pls); +#endif // FEATURE_COMPRESSEDSTACK + return this.UpdatePermissions(currentTriple, pls); + } + + [System.Security.SecurityCritical] // auto-generated + private bool Update(PermissionSetTriple currentTriple, FrameSecurityDescriptor fsd) + { +#if FEATURE_COMPRESSEDSTACK + FrameSecurityDescriptorWithResolver fsdWithResolver = fsd as FrameSecurityDescriptorWithResolver; + if (fsdWithResolver != null) + { + return Update2(currentTriple, fsdWithResolver); + } +#endif // FEATURE_COMPRESSEDSTACK + + // check imperative + bool fHalt = Update2(currentTriple, fsd, false); + if (!fHalt) + { + // then declarative + fHalt = Update2(currentTriple, fsd, true); + } + return fHalt; + } + +#if FEATURE_COMPRESSEDSTACK + [System.Security.SecurityCritical] + private bool Update2(PermissionSetTriple currentTriple, FrameSecurityDescriptorWithResolver fsdWithResolver) + { + System.Reflection.Emit.DynamicResolver resolver = fsdWithResolver.Resolver; + CompressedStack dynamicCompressedStack = resolver.GetSecurityContext(); + dynamicCompressedStack.CompleteConstruction(null); + return this.Update(currentTriple, dynamicCompressedStack.PLS); + } +#endif // FEATURE_COMPRESSEDSTACK + + [System.Security.SecurityCritical] // auto-generated + private bool Update2(PermissionSetTriple currentTriple, FrameSecurityDescriptor fsd, bool fDeclarative) + { + // Deny + PermissionSet deniedPset = fsd.GetDenials(fDeclarative); + if (deniedPset != null) + { + currentTriple.UpdateRefused(deniedPset); + } + + // permit only + PermissionSet permitOnlyPset = fsd.GetPermitOnly(fDeclarative); + if (permitOnlyPset != null) + { + currentTriple.UpdateGrant(permitOnlyPset); + } + + // Assert all possible + if (fsd.GetAssertAllPossible()) + { + // If we have no grant set, it means that the only assembly we've seen on the stack so + // far is mscorlib. Since mscorlib will always be fully trusted, the grant set of the + // compressed stack is also FullTrust. + if (currentTriple.GrantSet == null) + currentTriple.GrantSet = PermissionSet.s_fullTrust; + + UpdateTripleListAndCreateNewTriple(currentTriple, m_permSetTriples); + currentTriple.GrantSet = PermissionSet.s_fullTrust; + currentTriple.UpdateAssert(fsd.GetAssertions(fDeclarative)); + return true; + } + + // Assert + PermissionSet assertPset = fsd.GetAssertions(fDeclarative); + if (assertPset != null) + { + if (assertPset.IsUnrestricted()) + { + // If we have no grant set, it means that the only assembly we've seen on the stack so + // far is mscorlib. Since mscorlib will always be fully trusted, the grant set of the + // compressed stack is also FullTrust. + if (currentTriple.GrantSet == null) + currentTriple.GrantSet = PermissionSet.s_fullTrust; + + UpdateTripleListAndCreateNewTriple(currentTriple, m_permSetTriples); + currentTriple.GrantSet = PermissionSet.s_fullTrust; + currentTriple.UpdateAssert(assertPset); + return true; + } + + PermissionSetTriple retTriple = currentTriple.UpdateAssert(assertPset); + if (retTriple != null) + { + EnsureTriplesListCreated(); + m_permSetTriples.Add(retTriple); + } + } + + return false; + } + [System.Security.SecurityCritical] // auto-generated + private void Update(PermissionSetTriple currentTriple, PermissionSet in_g, PermissionSet in_r) + { +#if FEATURE_COMPRESSEDSTACK + ZoneIdentityPermission z; + UrlIdentityPermission u; + currentTriple.UpdateGrant(in_g, out z, out u); + currentTriple.UpdateRefused(in_r); + AppendZoneOrigin(z, u); +#else // !FEATURE_COMPRESEDSTACK + currentTriple.UpdateGrant(in_g); + currentTriple.UpdateRefused(in_r); +#endif // FEATURE_COMPRESSEDSTACK + } + + // Called from the VM for HG CS construction + [System.Security.SecurityCritical] // auto-generated + private void Update(PermissionSet in_g) + { + if (m_firstPermSetTriple == null) + m_firstPermSetTriple = new PermissionSetTriple(); + Update(m_firstPermSetTriple, in_g, null); + } + +#if FEATURE_COMPRESSEDSTACK + private void UpdateZoneAndOrigin(PermissionListSet pls) + { + if (pls != null) + { + if (this.m_zoneList == null && pls.m_zoneList != null && pls.m_zoneList.Count > 0) + this.m_zoneList = new ArrayList(); + UpdateArrayList(this.m_zoneList, pls.m_zoneList); + if (this.m_originList == null && pls.m_originList != null && pls.m_originList.Count > 0) + this.m_originList = new ArrayList(); + UpdateArrayList(this.m_originList, pls.m_originList); + } + } +#endif // FEATURE_COMPRESSEDSTACK + + [System.Security.SecurityCritical] // auto-generated + private bool UpdatePermissions(PermissionSetTriple currentTriple, PermissionListSet pls) + { + if (pls != null) + { + if (pls.m_permSetTriples != null) + { + // DCS has an AGR List. So we need to add the AGR List + UpdateTripleListAndCreateNewTriple(currentTriple,pls.m_permSetTriples); + } + else + { + // Common case: One AGR set + + PermissionSetTriple tmp_psTriple = pls.m_firstPermSetTriple; + PermissionSetTriple retTriple; + // First try and update currentTriple. Return value indicates if we can stop construction + if (currentTriple.Update(tmp_psTriple, out retTriple)) + return true; + // If we got a non-null retTriple, what it means is that compression failed, + // and we now have 2 triples to deal with: retTriple and currentTriple. + // retTriple has to be appended first. then currentTriple. + if (retTriple != null) + { + EnsureTriplesListCreated(); + // we just created a new triple...add the previous one (returned) to the list + m_permSetTriples.Add(retTriple); + } + } + } + else + { + // pls can be null only outside the loop in CreateCompressedState + UpdateTripleListAndCreateNewTriple(currentTriple, null); + } + + + return false; + + } + + + private void UpdateTripleListAndCreateNewTriple(PermissionSetTriple currentTriple, ArrayList tripleList) + { + if (!currentTriple.IsEmpty()) + { + if (m_firstPermSetTriple == null && m_permSetTriples == null) + { + m_firstPermSetTriple = new PermissionSetTriple(currentTriple); + } + else + { + EnsureTriplesListCreated(); + m_permSetTriples.Add(new PermissionSetTriple(currentTriple)); + } + currentTriple.Reset(); + } + if (tripleList != null) + { + EnsureTriplesListCreated(); + m_permSetTriples.AddRange(tripleList); + } + } + + private static void UpdateArrayList(ArrayList current, ArrayList newList) + { + if (newList == null) + return; + + for(int i=0;i < newList.Count; i++) + { + if (!current.Contains(newList[i])) + current.Add(newList[i]); + } + + } + +#if FEATURE_COMPRESSEDSTACK + private void AppendZoneOrigin(ZoneIdentityPermission z, UrlIdentityPermission u) + { + + if (z != null) + { + if (m_zoneList == null) + m_zoneList = new ArrayList(); + z.AppendZones(m_zoneList); + } + + if (u != null) + { + if (m_originList == null) + m_originList = new ArrayList(); + u.AppendOrigin(m_originList); + } + } + +[System.Security.SecurityCritical] // auto-generated +[System.Runtime.InteropServices.ComVisible(true)] + // public(internal) interface begins... + // Creation functions + static internal PermissionListSet CreateCompressedState(CompressedStack cs, CompressedStack innerCS) + { + // function that completes the construction of the compressed stack if not done so already (bottom half for demand evaluation) + + bool bHaltConstruction = false; + if (cs.CompressedStackHandle == null) + return null; // FT case or Security off + + PermissionListSet pls = new PermissionListSet(); + PermissionSetTriple currentTriple = new PermissionSetTriple(); + int numDomains = CompressedStack.GetDCSCount(cs.CompressedStackHandle); + for (int i=numDomains-1; (i >= 0 && !bHaltConstruction) ; i--) + { + DomainCompressedStack dcs = CompressedStack.GetDomainCompressedStack(cs.CompressedStackHandle, i); + if (dcs == null) + continue; // we hit a FT Domain + if (dcs.PLS == null) + { + // We failed on some DCS + throw new SecurityException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Security_Generic"))); + } + pls.UpdateZoneAndOrigin(dcs.PLS); + pls.Update(currentTriple, dcs.PLS); + bHaltConstruction = dcs.ConstructionHalted; + } + if (!bHaltConstruction) + { + PermissionListSet tmp_pls = null; + // Construction did not halt. + if (innerCS != null) + { + innerCS.CompleteConstruction(null); + tmp_pls = innerCS.PLS; + } + pls.Terminate(currentTriple, tmp_pls); + } + else + { + pls.Terminate(currentTriple); + } + + return pls; + } + + [System.Security.SecurityCritical] // auto-generated + static internal PermissionListSet CreateCompressedState(IntPtr unmanagedDCS, out bool bHaltConstruction) + { + PermissionListSet pls = new PermissionListSet(); + PermissionSetTriple currentTriple = new PermissionSetTriple(); + + PermissionSet tmp_g, tmp_r; + // Construct the descriptor list + int descCount = DomainCompressedStack.GetDescCount(unmanagedDCS); + bHaltConstruction = false; + for(int i=0; (i < descCount && !bHaltConstruction); i++) + { + FrameSecurityDescriptor fsd; + Assembly assembly; + if (DomainCompressedStack.GetDescriptorInfo(unmanagedDCS, i, out tmp_g, out tmp_r, out assembly, out fsd)) + { + // Got an FSD + bHaltConstruction = pls.Update(currentTriple, fsd); + } + else + { + pls.Update(currentTriple, tmp_g, tmp_r); + } + + } + if (!bHaltConstruction) + { + // domain + if (!DomainCompressedStack.IgnoreDomain(unmanagedDCS)) + { + DomainCompressedStack.GetDomainPermissionSets(unmanagedDCS, out tmp_g, out tmp_r); + pls.Update(currentTriple, tmp_g, tmp_r); + } + } + pls.Terminate(currentTriple); + + + // return the created object + return pls; + + } + [System.Security.SecurityCritical] // auto-generated + static internal PermissionListSet CreateCompressedState_HG() + { + PermissionListSet pls = new PermissionListSet(); + CompressedStack.GetHomogeneousPLS(pls); + return pls; + } +#endif // #if FEATURE_COMPRESSEDSTACK + // Private Demand evaluation functions - only called from the VM + [System.Security.SecurityCritical] // auto-generated + internal bool CheckDemandNoThrow(CodeAccessPermission demand) + { + // AppDomain permissions - no asserts. So there should only be one triple to work with + Contract.Assert(m_permSetTriples == null && m_firstPermSetTriple != null, "More than one PermissionSetTriple encountered in AD PermissionListSet"); + + + + PermissionToken permToken = null; + if (demand != null) + permToken = PermissionToken.GetToken(demand); + + return m_firstPermSetTriple.CheckDemandNoThrow(demand, permToken); + + + } + [System.Security.SecurityCritical] // auto-generated + internal bool CheckSetDemandNoThrow(PermissionSet pSet) + { + // AppDomain permissions - no asserts. So there should only be one triple to work with + Contract.Assert(m_permSetTriples == null && m_firstPermSetTriple != null, "More than one PermissionSetTriple encountered in AD PermissionListSet"); + + + return m_firstPermSetTriple.CheckSetDemandNoThrow(pSet); + } + + // Demand evauation functions + [System.Security.SecurityCritical] // auto-generated + internal bool CheckDemand(CodeAccessPermission demand, PermissionToken permToken, RuntimeMethodHandleInternal rmh) + { + bool bRet = SecurityRuntime.StackContinue; + if (m_permSetTriples != null) + { + for (int i=0; (i < m_permSetTriples.Count && bRet != SecurityRuntime.StackHalt) ; i++) + { + PermissionSetTriple psTriple = (PermissionSetTriple)m_permSetTriples[i]; + bRet = psTriple.CheckDemand(demand, permToken, rmh); + } + } + else if (m_firstPermSetTriple != null) + { + bRet = m_firstPermSetTriple.CheckDemand(demand, permToken, rmh); + } + + return bRet; + } + + [System.Security.SecurityCritical] // auto-generated + internal bool CheckSetDemand(PermissionSet pset , RuntimeMethodHandleInternal rmh) + { + PermissionSet unused; + CheckSetDemandWithModification(pset, out unused, rmh); + return SecurityRuntime.StackHalt; // CS demand check always terminates the stackwalk + } + + [System.Security.SecurityCritical] + internal bool CheckSetDemandWithModification(PermissionSet pset, out PermissionSet alteredDemandSet, RuntimeMethodHandleInternal rmh) + { + bool bRet = SecurityRuntime.StackContinue; + PermissionSet demandSet = pset; + alteredDemandSet = null; + if (m_permSetTriples != null) + { + for (int i=0; (i < m_permSetTriples.Count && bRet != SecurityRuntime.StackHalt) ; i++) + { + PermissionSetTriple psTriple = (PermissionSetTriple)m_permSetTriples[i]; + bRet = psTriple.CheckSetDemand(demandSet, out alteredDemandSet, rmh); + if (alteredDemandSet != null) + demandSet = alteredDemandSet; + } + } + else if (m_firstPermSetTriple != null) + { + bRet = m_firstPermSetTriple.CheckSetDemand(demandSet, out alteredDemandSet, rmh); + } + + return bRet; + } + + /// <summary> + /// Check to see if the PLS satisfies a demand for the special permissions encoded in flags + /// </summary> + /// <param name="flags">set of flags to check (See PermissionType)</param> + [System.Security.SecurityCritical] // auto-generated + private bool CheckFlags(int flags) + { + Contract.Assert(flags != 0, "Invalid permission flag demand"); + + bool check = true; + + if (m_permSetTriples != null) + { + for (int i = 0; i < m_permSetTriples.Count && check && flags != 0; i++) + { + check &= ((PermissionSetTriple)m_permSetTriples[i]).CheckFlags(ref flags); + } + } + else if (m_firstPermSetTriple != null) + { + check = m_firstPermSetTriple.CheckFlags(ref flags); + } + + return check; + } + + /// <summary> + /// Demand which succeeds if either a set of special permissions or a permission set is granted + /// to the call stack + /// </summary> + /// <param name="flags">set of flags to check (See PermissionType)</param> + /// <param name="grantSet">alternate permission set to check</param> + [System.Security.SecurityCritical] // auto-generated + internal void DemandFlagsOrGrantSet(int flags, PermissionSet grantSet) + { + if (CheckFlags(flags)) + return; + + CheckSetDemand(grantSet, RuntimeMethodHandleInternal.EmptyHandle); + } + +#if FEATURE_COMPRESSEDSTACK + internal void GetZoneAndOrigin(ArrayList zoneList, ArrayList originList, PermissionToken zoneToken, PermissionToken originToken) + { + if (m_zoneList != null) + zoneList.AddRange(m_zoneList); + if (m_originList != null) + originList.AddRange(m_originList); + } +#endif + } + +} |