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

  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. // PolicyManager.cs
  17. //
  18. namespace System.Security
  19. {
  20.     using System.Collections;
  21.     using System.Globalization;
  22.     using System.IO;
  23.     using System.Runtime.CompilerServices;
  24.     using System.Runtime.Versioning;
  25.     using System.Security.Util;
  26.     using System.Security.Policy;
  27.     using System.Security.Permissions;
  28.     using System.Text;
  29.     using System.Threading;
  30.    
  31.     internal class PolicyManager
  32.     {
  33.         // Only parse the system CAS policy levels when needed. In particular,
  34.         // we do not use these when the AppDomain is homogeneous for example.
  35.         private object m_policyLevels;
  36.         private IList PolicyLevels {
  37.             get {
  38.                 if (m_policyLevels == null) {
  39.                     ArrayList policyLevels = new ArrayList();
  40.                    
  41.                     string enterpriseConfig = PolicyLevel.GetLocationFromType(System.Security.PolicyLevelType.Enterprise);
  42.                     policyLevels.Add(new PolicyLevel(System.Security.PolicyLevelType.Enterprise, enterpriseConfig, ConfigId.EnterprisePolicyLevel));
  43.                    
  44.                     string machineConfig = PolicyLevel.GetLocationFromType(System.Security.PolicyLevelType.Machine);
  45.                     policyLevels.Add(new PolicyLevel(System.Security.PolicyLevelType.Machine, machineConfig, ConfigId.MachinePolicyLevel));
  46.                    
  47.                     // The user directory could be null if the user does not have a user profile for example.
  48.                     if (Config.UserDirectory != null) {
  49.                         string userConfig = PolicyLevel.GetLocationFromType(System.Security.PolicyLevelType.User);
  50.                         policyLevels.Add(new PolicyLevel(System.Security.PolicyLevelType.User, userConfig, ConfigId.UserPolicyLevel));
  51.                     }
  52.                     Interlocked.CompareExchange(ref m_policyLevels, policyLevels, null);
  53.                 }
  54.                 return m_policyLevels as ArrayList;
  55.             }
  56.         }
  57.        
  58.         internal PolicyManager()
  59.         {
  60.         }
  61.        
  62.         internal void AddLevel(PolicyLevel level)
  63.         {
  64.             PolicyLevels.Add(level);
  65.         }
  66.        
  67.         [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPolicy)]
  68.         internal IEnumerator PolicyHierarchy()
  69.         {
  70.             return PolicyLevels.GetEnumerator();
  71.         }
  72.        
  73.         internal PermissionSet Resolve(Evidence evidence)
  74.         {
  75.             // The host might have implemented a ResolvePolicy method in their HostSecurityManager,
  76.             // so take that into account for non-GAC assemblies.
  77.             if (!IsGacAssembly(evidence)) {
  78.                 HostSecurityManager securityManager = AppDomain.CurrentDomain.HostSecurityManager;
  79.                 if ((securityManager.Flags & HostSecurityManagerOptions.HostResolvePolicy) == HostSecurityManagerOptions.HostResolvePolicy)
  80.                     return securityManager.ResolvePolicy(evidence);
  81.             }
  82.             return ResolveHelper(evidence);
  83.         }
  84.        
  85.         internal PermissionSet ResolveHelper(Evidence evidence)
  86.         {
  87.             PermissionSet grant = null;
  88.             if (IsGacAssembly(evidence)) {
  89.                 // GAC assemblies get FullTrust
  90.                 grant = new PermissionSet(PermissionState.Unrestricted);
  91.             }
  92.             else {
  93.                 {
  94.                     // Resolve the CAS policy levels on the machine
  95.                     grant = CodeGroupResolve(evidence, false);
  96.                 }
  97.             }
  98.             return grant;
  99.         }
  100.        
  101.         internal PermissionSet CodeGroupResolve(Evidence evidence, bool systemPolicy)
  102.         {
  103.             PermissionSet grant = null;
  104.             PolicyStatement policy;
  105.             PolicyLevel currentLevel = null;
  106.            
  107.             IEnumerator levelEnumerator = PolicyLevels.GetEnumerator();
  108.            
  109.             char[] serializedEvidence = MakeEvidenceArray(evidence, false);
  110.             int count = evidence.Count;
  111.            
  112.             bool legacyIgnoreSystemPolicy = (AppDomain.CurrentDomain.GetData("IgnoreSystemPolicy") != null);
  113.             bool testApplicationLevels = false;
  114.             while (levelEnumerator.MoveNext()) {
  115.                 currentLevel = (PolicyLevel)levelEnumerator.Current;
  116.                 if (systemPolicy) {
  117.                     if (currentLevel.Type == PolicyLevelType.AppDomain)
  118.                         continue;
  119.                 }
  120.                 else if (legacyIgnoreSystemPolicy && currentLevel.Type != PolicyLevelType.AppDomain)
  121.                     continue;
  122.                
  123.                 policy = currentLevel.Resolve(evidence, count, serializedEvidence);
  124.                
  125.                 // If the grant is "AllPossible", the intersection is just the other permission set.
  126.                 // Otherwise, do an inplace intersection (since we know we can alter the grant set since
  127.                 // it is a copy of the first policy statement's permission set).
  128.                
  129.                 if (grant == null)
  130.                     grant = policy.PermissionSet;
  131.                 else
  132.                     grant.InplaceIntersect(policy.GetPermissionSetNoCopy());
  133.                
  134.                 if (grant == null || grant.FastIsEmpty()) {
  135.                     break;
  136.                 }
  137.                 else if ((policy.Attributes & PolicyStatementAttribute.LevelFinal) == PolicyStatementAttribute.LevelFinal) {
  138.                     if (currentLevel.Type != PolicyLevelType.AppDomain) {
  139.                         testApplicationLevels = true;
  140.                     }
  141.                     break;
  142.                 }
  143.             }
  144.            
  145.             if (grant != null && testApplicationLevels) {
  146.                 PolicyLevel appDomainLevel = null;
  147.                
  148.                 for (int i = PolicyLevels.Count - 1; i >= 0; --i) {
  149.                     currentLevel = (PolicyLevel)PolicyLevels[i];
  150.                     if (currentLevel.Type == PolicyLevelType.AppDomain) {
  151.                         appDomainLevel = currentLevel;
  152.                         break;
  153.                     }
  154.                 }
  155.                
  156.                 if (appDomainLevel != null) {
  157.                     policy = appDomainLevel.Resolve(evidence, count, serializedEvidence);
  158.                     grant.InplaceIntersect(policy.GetPermissionSetNoCopy());
  159.                 }
  160.             }
  161.            
  162.             if (grant == null)
  163.                 grant = new PermissionSet(PermissionState.None);
  164.            
  165.             // Each piece of evidence can possibly create an identity permission that we
  166.             // need to add to our grant set. Therefore, for all pieces of evidence that
  167.             // implement the IIdentityPermissionFactory interface, ask it for its
  168.             // adjoining identity permission and add it to the grant.
  169.            
  170.             if (!CodeAccessSecurityEngine.DoesFullTrustMeanFullTrust() || !grant.IsUnrestricted()) {
  171.                 IEnumerator enumerator = evidence.GetHostEnumerator();
  172.                 while (enumerator.MoveNext()) {
  173.                     object obj = enumerator.Current;
  174.                     IIdentityPermissionFactory factory = obj as IIdentityPermissionFactory;
  175.                     if (factory != null) {
  176.                         IPermission perm = factory.CreateIdentityPermission(evidence);
  177.                         if (perm != null)
  178.                             grant.AddPermission(perm);
  179.                     }
  180.                 }
  181.             }
  182.            
  183.             grant.IgnoreTypeLoadFailures = true;
  184.             return grant;
  185.         }
  186.        
  187.         static internal bool IsGacAssembly(Evidence evidence)
  188.         {
  189.             return new GacMembershipCondition().Check(evidence);
  190.         }
  191.        
  192.        
  193.         internal IEnumerator ResolveCodeGroups(Evidence evidence)
  194.         {
  195.             ArrayList accumList = new ArrayList();
  196.             IEnumerator levelEnumerator = PolicyLevels.GetEnumerator();
  197.            
  198.             while (levelEnumerator.MoveNext()) {
  199.                 CodeGroup temp = ((PolicyLevel)levelEnumerator.Current).ResolveMatchingCodeGroups(evidence);
  200.                 if (temp != null)
  201.                     accumList.Add(temp);
  202.             }
  203.            
  204.             return accumList.GetEnumerator(0, accumList.Count);
  205.         }
  206.        
  207.         internal void Save()
  208.         {
  209.             EncodeLevel(Environment.GetResourceString("Policy_PL_Enterprise"));
  210.             EncodeLevel(Environment.GetResourceString("Policy_PL_Machine"));
  211.             EncodeLevel(Environment.GetResourceString("Policy_PL_User"));
  212.         }
  213.        
  214.         private void EncodeLevel(string label)
  215.         {
  216.             for (int i = 0; i < PolicyLevels.Count; ++i) {
  217.                 PolicyLevel currentLevel = (PolicyLevel)PolicyLevels[i];
  218.                 if (currentLevel.Label.Equals(label)) {
  219.                     EncodeLevel(currentLevel);
  220.                     return;
  221.                 }
  222.             }
  223.         }
  224.        
  225.         static internal void EncodeLevel(PolicyLevel level)
  226.         {
  227.             SecurityElement elConf = new SecurityElement("configuration");
  228.             SecurityElement elMscorlib = new SecurityElement("mscorlib");
  229.             SecurityElement elSecurity = new SecurityElement("security");
  230.             SecurityElement elPolicy = new SecurityElement("policy");
  231.            
  232.             elConf.AddChild(elMscorlib);
  233.             elMscorlib.AddChild(elSecurity);
  234.             elSecurity.AddChild(elPolicy);
  235.             elPolicy.AddChild(level.ToXml());
  236.            
  237.             try {
  238.                 StringBuilder sb = new StringBuilder();
  239.                 Encoding encoding = Encoding.UTF8;
  240.                
  241.                 SecurityElement format = new SecurityElement("xml");
  242.                 format.m_type = SecurityElementType.Format;
  243.                 format.AddAttribute("version", "1.0");
  244.                 format.AddAttribute("encoding", encoding.WebName);
  245.                 sb.Append(format.ToString());
  246.                 sb.Append(elConf.ToString());
  247.                
  248.                 byte[] data = encoding.GetBytes(sb.ToString());
  249.                
  250.                 // Write out the new config.
  251.                 if (level.Path == null || !Config.SaveDataByte(level.Path, data, 0, data.Length))
  252.                     throw new PolicyException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Policy_UnableToSave"), level.Label));
  253.             }
  254.             catch (Exception e) {
  255.                 if (e is PolicyException)
  256.                     throw e;
  257.                 else
  258.                     throw new PolicyException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Policy_UnableToSave"), level.Label), e);
  259.             }
  260.             catch {
  261.                 throw new PolicyException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Policy_UnableToSave"), level.Label));
  262.             }
  263.            
  264.             Config.ResetCacheData(level.ConfigId);
  265.             if (CanUseQuickCache(level.RootCodeGroup))
  266.                 Config.SetQuickCache(level.ConfigId, GenerateQuickCache(level));
  267.         }
  268.        
  269.         // Here is the managed portion of the QuickCache code. It
  270.         // is mainly concerned with detecting whether it is valid
  271.         // for us to use the quick cache, and then calculating the
  272.         // proper mapping of partial evidence to partial mapping.
  273.         //
  274.         // The choice of the partial evidence sets is fairly arbitrary
  275.         // and in this case is tailored to give us meaningful
  276.         // results from default policy.
  277.         //
  278.         // The choice of whether or not we can use the quick cache
  279.         // is far from arbitrary. There are a number of conditions that must
  280.         // be true for the QuickCache to produce valid result. These
  281.         // are:
  282.         //
  283.         // * equivalent evidence objects must produce the same
  284.         // grant set (i.e. it must be independent of time of day,
  285.         // space on the harddisk, other "external" factors, and
  286.         // cannot be random).
  287.         //
  288.         // * evidence must be used positively (i.e. if evidence A grants
  289.         // permission X, then evidence A+B must grant at least permission
  290.         // X).
  291.         //
  292.         // In particular for our implementation, this means that we
  293.         // limit the classes that can be used by policy to just
  294.         // the ones defined within mscorlib and that there are
  295.         // no Exclusive bits set on any code groups.
  296.        
  297.         static internal bool CanUseQuickCache(CodeGroup group)
  298.         {
  299.             ArrayList list = new ArrayList();
  300.            
  301.             list.Add(group);
  302.            
  303.             for (int i = 0; i < list.Count; ++i) {
  304.                 group = (CodeGroup)list[i];
  305.                
  306.                 IUnionSemanticCodeGroup unionGroup = group as IUnionSemanticCodeGroup;
  307.                
  308.                 if (unionGroup != null) {
  309.                     if (!TestPolicyStatement(group.PolicyStatement))
  310.                         return false;
  311.                 }
  312.                 else {
  313.                     return false;
  314.                 }
  315.                
  316.                 IMembershipCondition cond = group.MembershipCondition;
  317.                 if (cond != null && !(cond is IConstantMembershipCondition)) {
  318.                     return false;
  319.                 }
  320.                
  321.                 IList children = group.Children;
  322.                
  323.                 if (children != null && children.Count > 0) {
  324.                     IEnumerator enumerator = children.GetEnumerator();
  325.                    
  326.                     while (enumerator.MoveNext()) {
  327.                         list.Add(enumerator.Current);
  328.                     }
  329.                 }
  330.             }
  331.            
  332.             return true;
  333.         }
  334.        
  335.         private static bool TestPolicyStatement(PolicyStatement policy)
  336.         {
  337.             if (policy == null)
  338.                 return true;
  339.             return (policy.Attributes & PolicyStatementAttribute.Exclusive) == 0;
  340.         }
  341.        
  342.         private static QuickCacheEntryType GenerateQuickCache(PolicyLevel level)
  343.         {
  344.             QuickCacheEntryType[] FullTrustMap = new QuickCacheEntryType[] {QuickCacheEntryType.FullTrustZoneMyComputer, QuickCacheEntryType.FullTrustZoneIntranet, QuickCacheEntryType.FullTrustZoneInternet, QuickCacheEntryType.FullTrustZoneTrusted, QuickCacheEntryType.FullTrustZoneUntrusted};
  345.            
  346.             QuickCacheEntryType accumulator = (QuickCacheEntryType)0;
  347.            
  348.             Evidence noEvidence = new Evidence();
  349.            
  350.             PermissionSet policy = null;
  351.            
  352.             try {
  353.                 policy = level.Resolve(noEvidence).PermissionSet;
  354.                 if (policy.IsUnrestricted())
  355.                     accumulator |= QuickCacheEntryType.FullTrustAll;
  356.             }
  357.             catch (PolicyException) {
  358.             }
  359.            
  360.             Array zones = Enum.GetValues(typeof(SecurityZone));
  361.            
  362.             for (int i = 0; i < zones.Length; ++i) {
  363.                 if (((SecurityZone)zones.GetValue(i)) == SecurityZone.NoZone)
  364.                     continue;
  365.                
  366.                 Evidence zoneEvidence = new Evidence();
  367.                 zoneEvidence.AddHost(new Zone((SecurityZone)zones.GetValue(i)));
  368.                
  369.                 PermissionSet zonePolicy = null;
  370.                
  371.                 try {
  372.                     zonePolicy = level.Resolve(zoneEvidence).PermissionSet;
  373.                     if (zonePolicy.IsUnrestricted())
  374.                         accumulator |= FullTrustMap[i];
  375.                 }
  376.                 catch (PolicyException) {
  377.                 }
  378.             }
  379.            
  380.             return accumulator;
  381.         }
  382.        
  383.         static internal char[] MakeEvidenceArray(Evidence evidence, bool verbose)
  384.         {
  385.             // We only support caching on our built-in evidence types (excluding hash b/c it would
  386.             // make our caching scheme just match up the same assembly from the same location which
  387.             // doesn't gain us anything).
  388.            
  389.             IEnumerator enumerator = evidence.GetEnumerator();
  390.             int requiredLength = 0;
  391.            
  392.             while (enumerator.MoveNext()) {
  393.                 IBuiltInEvidence obj = enumerator.Current as IBuiltInEvidence;
  394.                
  395.                 if (obj == null)
  396.                     return null;
  397.                
  398.                 requiredLength += obj.GetRequiredSize(verbose);
  399.             }
  400.            
  401.             enumerator.Reset();
  402.            
  403.             char[] buffer = new char[requiredLength];
  404.            
  405.             int position = 0;
  406.            
  407.             while (enumerator.MoveNext()) {
  408.                 position = ((IBuiltInEvidence)enumerator.Current).OutputToBuffer(buffer, position, verbose);
  409.             }
  410.            
  411.             return buffer;
  412.         }
  413.        
  414.         #if _DEBUG
  415.         [MethodImplAttribute(MethodImplOptions.InternalCall)]
  416.         static internal extern int _DebugOut(string file, string message);
  417.         #endif
  418.     }
  419. }

Developer Fusion