The Labs \ Source Viewer \ SSCLI \ System.Security \ PermissionListSet

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. /*=============================================================================
  16. **
  17. ** Class: PermissionListSet.cs
  18. **
  19. ** Purpose: Holds state about A/G/R permissionsets in a callstack or appdomain
  20. **          (Replacement for PermissionListSet)
  21. **
  22. =============================================================================*/
  23. namespace System.Security
  24. {
  25.     using System.Globalization;
  26.     using System.Reflection;
  27.     using System.Runtime.InteropServices;
  28.     using System.Security;
  29.     using System.Security.Permissions;
  30.     using System.Threading;
  31.     using System.Collections;
  32.    
  33.     [Serializable()]
  34.     internal sealed class PermissionListSet
  35.     {
  36.         // Only internal (public) methods are creation methods and demand evaluation methods.
  37.         // Scroll down to the end to see them.
  38.         private PermissionSetTriple m_firstPermSetTriple;
  39.         private ArrayList m_permSetTriples;
  40.         private ArrayList m_zoneList;
  41.         private ArrayList m_originList;
  42.        
  43.         internal PermissionListSet()
  44.         {
  45.         }
  46.        
  47.         private void EnsureTriplesListCreated()
  48.         {
  49.             if (m_permSetTriples == null) {
  50.                 m_permSetTriples = new ArrayList();
  51.                 if (m_firstPermSetTriple != null) {
  52.                     m_permSetTriples.Add(m_firstPermSetTriple);
  53.                     m_firstPermSetTriple = null;
  54.                 }
  55.             }
  56.         }
  57.        
  58.         internal void UpdateDomainPLS(PermissionListSet adPLS)
  59.         {
  60.             if (adPLS != null && adPLS.m_firstPermSetTriple != null)
  61.                 UpdateDomainPLS(adPLS.m_firstPermSetTriple.GrantSet, adPLS.m_firstPermSetTriple.RefusedSet);
  62.         }
  63.        
  64.         internal void UpdateDomainPLS(PermissionSet grantSet, PermissionSet deniedSet)
  65.         {
  66.             BCLDebug.Assert(m_permSetTriples == null, "m_permSetTriples != null");
  67.             if (m_firstPermSetTriple == null)
  68.                 m_firstPermSetTriple = new PermissionSetTriple();
  69.            
  70.             // update the grant and denied sets
  71.             m_firstPermSetTriple.UpdateGrant(grantSet);
  72.             m_firstPermSetTriple.UpdateRefused(deniedSet);
  73.         }
  74.        
  75.         private void Terminate(PermissionSetTriple currentTriple)
  76.         {
  77.             UpdateTripleListAndCreateNewTriple(currentTriple, null);
  78.         }
  79.        
  80.         private void Terminate(PermissionSetTriple currentTriple, PermissionListSet pls)
  81.         {
  82.             this.UpdateZoneAndOrigin(pls);
  83.             this.UpdatePermissions(currentTriple, pls);
  84.             this.UpdateTripleListAndCreateNewTriple(currentTriple, null);
  85.         }
  86.        
  87.         private bool Update(PermissionSetTriple currentTriple, PermissionListSet pls)
  88.         {
  89.             this.UpdateZoneAndOrigin(pls);
  90.             return this.UpdatePermissions(currentTriple, pls);
  91.         }
  92.        
  93.         private bool Update(PermissionSetTriple currentTriple, FrameSecurityDescriptor fsd)
  94.         {
  95.             // check imperative
  96.             bool fHalt = Update2(currentTriple, fsd, false);
  97.             if (!fHalt) {
  98.                 // then declarative
  99.                 fHalt = Update2(currentTriple, fsd, true);
  100.             }
  101.             return fHalt;
  102.         }
  103.        
  104.         private bool Update2(PermissionSetTriple currentTriple, FrameSecurityDescriptor fsd, bool fDeclarative)
  105.         {
  106.             // Deny
  107.             PermissionSet deniedPset = fsd.GetDenials(fDeclarative);
  108.             if (deniedPset != null) {
  109.                 currentTriple.UpdateRefused(deniedPset);
  110.             }
  111.            
  112.             // permit only
  113.             PermissionSet permitOnlyPset = fsd.GetPermitOnly(fDeclarative);
  114.             if (permitOnlyPset != null) {
  115.                 currentTriple.UpdateGrant(permitOnlyPset);
  116.             }
  117.            
  118.             // Assert all possible
  119.             if (fsd.GetAssertAllPossible())
  120.                 return true;
  121.             // halt the construction
  122.             // Assert
  123.             PermissionSet assertPset = fsd.GetAssertions(fDeclarative);
  124.             if (assertPset != null) {
  125.                 if (assertPset.IsUnrestricted())
  126.                     return true;
  127.                 // halt the construction
  128.                 PermissionSetTriple retTriple = currentTriple.UpdateAssert(assertPset);
  129.                 if (retTriple != null) {
  130.                     EnsureTriplesListCreated();
  131.                     m_permSetTriples.Add(retTriple);
  132.                 }
  133.             }
  134.            
  135.             return false;
  136.         }
  137.         private void Update(PermissionSetTriple currentTriple, PermissionSet in_g, PermissionSet in_r)
  138.         {
  139.             ZoneIdentityPermission z;
  140.             UrlIdentityPermission u;
  141.             currentTriple.UpdateGrant(in_g, out z, out u);
  142.             currentTriple.UpdateRefused(in_r);
  143.             AppendZoneOrigin(z, u);
  144.         }
  145.        
  146.         // Called from the VM for HG CS construction
  147.         private void Update(PermissionSet in_g)
  148.         {
  149.             if (m_firstPermSetTriple == null)
  150.                 m_firstPermSetTriple = new PermissionSetTriple();
  151.             Update(m_firstPermSetTriple, in_g, null);
  152.         }
  153.        
  154.         private void UpdateZoneAndOrigin(PermissionListSet pls)
  155.         {
  156.             if (pls != null) {
  157.                 if (this.m_zoneList == null && pls.m_zoneList != null && pls.m_zoneList.Count > 0)
  158.                     this.m_zoneList = new ArrayList();
  159.                 UpdateArrayList(this.m_zoneList, pls.m_zoneList);
  160.                 if (this.m_originList == null && pls.m_originList != null && pls.m_originList.Count > 0)
  161.                     this.m_originList = new ArrayList();
  162.                 UpdateArrayList(this.m_originList, pls.m_originList);
  163.             }
  164.         }
  165.        
  166.         private bool UpdatePermissions(PermissionSetTriple currentTriple, PermissionListSet pls)
  167.         {
  168.             if (pls != null) {
  169.                 if (pls.m_permSetTriples != null) {
  170.                     // DCS has an AGR List. So we need to add the AGR List
  171.                     UpdateTripleListAndCreateNewTriple(currentTriple, pls.m_permSetTriples);
  172.                 }
  173.                 else {
  174.                     // Common case: One AGR set
  175.                    
  176.                     PermissionSetTriple tmp_psTriple = pls.m_firstPermSetTriple;
  177.                     PermissionSetTriple retTriple;
  178.                     // First try and update currentTriple. Return value indicates if we can stop construction
  179.                     if (currentTriple.Update(tmp_psTriple, out retTriple))
  180.                         return true;
  181.                     // If we got a non-null retTriple, what it means is that compression failed,
  182.                     // and we now have 2 triples to deal with: retTriple and currentTriple.
  183.                     // retTriple has to be appended first. then currentTriple.
  184.                     if (retTriple != null) {
  185.                         EnsureTriplesListCreated();
  186.                         // we just created a new triple...add the previous one (returned) to the list
  187.                         m_permSetTriples.Add(retTriple);
  188.                     }
  189.                 }
  190.             }
  191.             else {
  192.                 // pls can be null only outside the loop in CreateCompressedState
  193.                 UpdateTripleListAndCreateNewTriple(currentTriple, null);
  194.             }
  195.            
  196.            
  197.             return false;
  198.            
  199.         }
  200.        
  201.        
  202.         private void UpdateTripleListAndCreateNewTriple(PermissionSetTriple currentTriple, ArrayList tripleList)
  203.         {
  204.             if (!currentTriple.IsEmpty()) {
  205.                 if (m_firstPermSetTriple == null && m_permSetTriples == null) {
  206.                     m_firstPermSetTriple = new PermissionSetTriple(currentTriple);
  207.                 }
  208.                 else {
  209.                     EnsureTriplesListCreated();
  210.                     m_permSetTriples.Add(new PermissionSetTriple(currentTriple));
  211.                 }
  212.                 currentTriple.Reset();
  213.             }
  214.             if (tripleList != null) {
  215.                 EnsureTriplesListCreated();
  216.                 m_permSetTriples.AddRange(tripleList);
  217.             }
  218.         }
  219.        
  220.         private static void UpdateArrayList(ArrayList current, ArrayList newList)
  221.         {
  222.             if (newList == null)
  223.                 return;
  224.            
  225.             for (int i = 0; i < newList.Count; i++) {
  226.                 if (!current.Contains(newList[i]))
  227.                     current.Add(newList[i]);
  228.             }
  229.            
  230.         }
  231.        
  232.         private void AppendZoneOrigin(ZoneIdentityPermission z, UrlIdentityPermission u)
  233.         {
  234.            
  235.             if (z != null) {
  236.                 if (m_zoneList == null)
  237.                     m_zoneList = new ArrayList();
  238.                 m_zoneList.Add(z.SecurityZone);
  239.             }
  240.            
  241.             if (u != null) {
  242.                 if (m_originList == null)
  243.                     m_originList = new ArrayList();
  244.                 m_originList.Add(u.Url);
  245.             }
  246.         }
  247.        
  248.         [System.Runtime.InteropServices.ComVisible(true)]
  249.         // public(internal) interface begins...
  250.         // Creation functions
  251.         static internal PermissionListSet CreateCompressedState(CompressedStack cs, CompressedStack innerCS)
  252.         {
  253.             // function that completes the construction of the compressed stack if not done so already (bottom half for demand evaluation)
  254.            
  255.             bool bHaltConstruction = false;
  256.             if (cs.CompressedStackHandle == null)
  257.                 return null;
  258.             // FT case or Security off
  259.             PermissionListSet pls = new PermissionListSet();
  260.             PermissionSetTriple currentTriple = new PermissionSetTriple();
  261.             int numDomains = CompressedStack.GetDCSCount(cs.CompressedStackHandle);
  262.             for (int i = numDomains - 1; (i >= 0 && !bHaltConstruction); i--) {
  263.                 DomainCompressedStack dcs = CompressedStack.GetDomainCompressedStack(cs.CompressedStackHandle, i);
  264.                 if (dcs == null)
  265.                     continue;
  266.                 // we hit a FT Domain
  267.                 if (dcs.PLS == null) {
  268.                     // We failed on some DCS
  269.                     throw new SecurityException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Security_Generic")));
  270.                 }
  271.                 pls.UpdateZoneAndOrigin(dcs.PLS);
  272.                 pls.Update(currentTriple, dcs.PLS);
  273.                 bHaltConstruction = dcs.ConstructionHalted;
  274.             }
  275.             if (!bHaltConstruction) {
  276.                 PermissionListSet tmp_pls = null;
  277.                 // Construction did not halt.
  278.                 if (innerCS != null) {
  279.                     innerCS.CompleteConstruction(null);
  280.                     tmp_pls = innerCS.PLS;
  281.                 }
  282.                 pls.Terminate(currentTriple, tmp_pls);
  283.             }
  284.             else {
  285.                 pls.Terminate(currentTriple);
  286.             }
  287.            
  288.             return pls;
  289.         }
  290.        
  291.         static internal PermissionListSet CreateCompressedState(IntPtr unmanagedDCS, out bool bHaltConstruction)
  292.         {
  293.             PermissionListSet pls = new PermissionListSet();
  294.             PermissionSetTriple currentTriple = new PermissionSetTriple();
  295.            
  296.             PermissionSet tmp_g;
  297.             PermissionSet tmp_r;
  298.             // Construct the descriptor list
  299.             int descCount = DomainCompressedStack.GetDescCount(unmanagedDCS);
  300.             bHaltConstruction = false;
  301.             for (int i = 0; (i < descCount && !bHaltConstruction); i++) {
  302.                 FrameSecurityDescriptor fsd;
  303.                 Assembly assembly;
  304.                 if (DomainCompressedStack.GetDescriptorInfo(unmanagedDCS, i, out tmp_g, out tmp_r, out assembly, out fsd)) {
  305.                     // Got an FSD
  306.                     bHaltConstruction = pls.Update(currentTriple, fsd);
  307.                 }
  308.                 else {
  309.                     pls.Update(currentTriple, tmp_g, tmp_r);
  310.                 }
  311.                
  312.             }
  313.             if (!bHaltConstruction) {
  314.                 // domain
  315.                 if (!DomainCompressedStack.IgnoreDomain(unmanagedDCS)) {
  316.                     DomainCompressedStack.GetDomainPermissionSets(unmanagedDCS, out tmp_g, out tmp_r);
  317.                     pls.Update(currentTriple, tmp_g, tmp_r);
  318.                 }
  319.             }
  320.             pls.Terminate(currentTriple);
  321.            
  322.            
  323.             // return the created object
  324.             return pls;
  325.            
  326.         }
  327.         static internal PermissionListSet CreateCompressedState_HG()
  328.         {
  329.             PermissionListSet pls = new PermissionListSet();
  330.             CompressedStack.GetHomogeneousPLS(pls);
  331.             return pls;
  332.         }
  333.        
  334.         // Private Demand evaluation functions - only called from the VM
  335.         internal bool CheckDemandNoThrow(CodeAccessPermission demand)
  336.         {
  337.             // AppDomain permissions - no asserts. So there should only be one triple to work with
  338.             BCLDebug.Assert(m_permSetTriples == null && m_firstPermSetTriple != null, "More than one PermissionSetTriple encountered in AD PermissionListSet");
  339.            
  340.            
  341.            
  342.             PermissionToken permToken = null;
  343.             if (demand != null)
  344.                 permToken = PermissionToken.GetToken(demand);
  345.            
  346.             return m_firstPermSetTriple.CheckDemandNoThrow(demand, permToken);
  347.            
  348.            
  349.         }
  350.         internal bool CheckSetDemandNoThrow(PermissionSet pSet)
  351.         {
  352.             // AppDomain permissions - no asserts. So there should only be one triple to work with
  353.             BCLDebug.Assert(m_permSetTriples == null && m_firstPermSetTriple != null, "More than one PermissionSetTriple encountered in AD PermissionListSet");
  354.            
  355.            
  356.             return m_firstPermSetTriple.CheckSetDemandNoThrow(pSet);
  357.         }
  358.        
  359.         // Demand evauation functions
  360.         internal bool CheckDemand(CodeAccessPermission demand, PermissionToken permToken, RuntimeMethodHandle rmh)
  361.         {
  362.             bool bRet = SecurityRuntime.StackContinue;
  363.             if (m_permSetTriples != null) {
  364.                 for (int i = 0; (i < m_permSetTriples.Count && bRet != SecurityRuntime.StackHalt); i++) {
  365.                    
  366.                     PermissionSetTriple psTriple = (PermissionSetTriple)m_permSetTriples[i];
  367.                     bRet = psTriple.CheckDemand(demand, permToken, rmh);
  368.                 }
  369.             }
  370.             else if (m_firstPermSetTriple != null) {
  371.                 bRet = m_firstPermSetTriple.CheckDemand(demand, permToken, rmh);
  372.             }
  373.            
  374.             return SecurityRuntime.StackHalt;
  375.             // CS demand check always terminates the stackwalk
  376.         }
  377.        
  378.         internal bool CheckSetDemand(PermissionSet pset, RuntimeMethodHandle rmh)
  379.         {
  380.             bool bRet = SecurityRuntime.StackContinue;
  381.             PermissionSet demandSet = pset;
  382.             PermissionSet alteredDemandSet;
  383.             if (m_permSetTriples != null) {
  384.                 for (int i = 0; (i < m_permSetTriples.Count && bRet != SecurityRuntime.StackHalt); i++) {
  385.                    
  386.                     PermissionSetTriple psTriple = (PermissionSetTriple)m_permSetTriples[i];
  387.                     bRet = psTriple.CheckSetDemand(demandSet, out alteredDemandSet, rmh);
  388.                     if (alteredDemandSet != null)
  389.                         demandSet = alteredDemandSet;
  390.                 }
  391.             }
  392.             else if (m_firstPermSetTriple != null) {
  393.                 bRet = m_firstPermSetTriple.CheckSetDemand(demandSet, out alteredDemandSet, rmh);
  394.             }
  395.            
  396.             return SecurityRuntime.StackHalt;
  397.             // CS demand check always terminates the stackwalk
  398.         }
  399.        
  400.         internal void GetZoneAndOrigin(ArrayList zoneList, ArrayList originList, PermissionToken zoneToken, PermissionToken originToken)
  401.         {
  402.             if (m_zoneList != null)
  403.                 zoneList.AddRange(m_zoneList);
  404.             if (m_originList != null)
  405.                 originList.AddRange(m_originList);
  406.         }
  407.     }
  408. }

Developer Fusion