The Labs \ Source Viewer \ SSCLI \ System.Security.Policy \ PolicyLevel

  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. // PolicyLevel.cs
  17. //
  18. // Abstraction for a level of policy (e.g. Enterprise, Machine, User)
  19. //
  20. namespace System.Security.Policy
  21. {
  22.     using Microsoft.Win32;
  23.     using System.Collections;
  24.     using System.Globalization;
  25.     using System.IO;
  26.     using System.Reflection;
  27.     using System.Security.Permissions;
  28.     using System.Security.Util;
  29.     using System.Runtime.InteropServices;
  30.     using System.Runtime.Remoting;
  31.     using System.Runtime.Serialization;
  32.     using System.Runtime.Versioning;
  33.     using System.Text;
  34.     using System.Threading;
  35.    
  36.     // Duplicated in vm\SecurityConfig.h
  37.     [Serializable()]
  38.     internal enum ConfigId
  39.     {
  40.         None = 0,
  41.         MachinePolicyLevel = 1,
  42.         UserPolicyLevel = 2,
  43.         EnterprisePolicyLevel = 3
  44.     }
  45.    
  46.     static internal class PolicyLevelData
  47.     {
  48.         // Note: any changes to the default permission sets means that you
  49.         // must recontemplate the default quick cache settings below.
  50.        
  51.         static internal readonly string s_defaultPermissionSets = "<NamedPermissionSets>" + "<PermissionSet class=\"System.Security.NamedPermissionSet\"" + "version=\"1\" " + "Unrestricted=\"true\" " + "Name=\"FullTrust\" " + "Description=\"{Policy_PS_FullTrust}\"/>" + "<PermissionSet class=\"System.Security.NamedPermissionSet\"" + "version=\"1\" " + "Name=\"Everything\" " + "Description=\"{Policy_PS_Everything}\">" + "<Permission class=\"System.Security.Permissions.IsolatedStorageFilePermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Unrestricted=\"true\"/>" + "<Permission class=\"System.Security.Permissions.EnvironmentPermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Unrestricted=\"true\"/>" + "<Permission class=\"System.Security.Permissions.FileIOPermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Unrestricted=\"true\"/>" + "<Permission class=\"System.Security.Permissions.FileDialogPermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Unrestricted=\"true\"/>" + "<Permission class=\"System.Security.Permissions.ReflectionPermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Unrestricted=\"true\"/>" + "<Permission class=\"System.Security.Permissions.SecurityPermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Flags=\"Assertion, UnmanagedCode, Execution, ControlThread, ControlEvidence, ControlPolicy, ControlAppDomain, SerializationFormatter, ControlDomainPolicy, ControlPrincipal, RemotingConfiguration, Infrastructure, BindingRedirects\"/>" + "<Permission class=\"System.Security.Permissions.UIPermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Unrestricted=\"true\"/>" + "<IPermission class=\"System.Net.SocketPermission, System, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Unrestricted=\"true\"/>" + "<IPermission class=\"System.Net.WebPermission, System, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Unrestricted=\"true\"/>" + "<IPermission class=\"System.Net.DnsPermission, System, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Unrestricted=\"true\"/>" + "</PermissionSet>" + "<PermissionSet class=\"System.Security.NamedPermissionSet\"" + "version=\"1\" " + "Name=\"Nothing\" " + "Description=\"{Policy_PS_Nothing}\"/>" + "<PermissionSet class=\"System.Security.NamedPermissionSet\"" + "version=\"1\" " + "Name=\"Execution\" " + "Description=\"{Policy_PS_Execution}\">" + "<Permission class=\"System.Security.Permissions.SecurityPermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Flags=\"Execution\"/>" + "</PermissionSet>" + "<PermissionSet class=\"System.Security.NamedPermissionSet\"" + "version=\"1\" " + "Name=\"SkipVerification\" " + "Description=\"{Policy_PS_SkipVerification}\">" + "<Permission class=\"System.Security.Permissions.SecurityPermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Flags=\"SkipVerification\"/>" + "</PermissionSet>" + "</NamedPermissionSets>";
  52.     }
  53.    
  54.     [Serializable()]
  55.     [System.Runtime.InteropServices.ComVisible(true)]
  56.     public sealed class PolicyLevel
  57.     {
  58.         private ArrayList m_fullTrustAssemblies;
  59.         private ArrayList m_namedPermissionSets;
  60.         private CodeGroup m_rootCodeGroup;
  61.         private string m_label;
  62.         [OptionalField(VersionAdded = 2)]
  63.         private PolicyLevelType m_type;
  64.        
  65.         #pragma warning disable 169
  66.         private ConfigId m_configId;
  67.         private bool m_useDefaultCodeGroupsOnReset;
  68.         private bool m_generateQuickCacheOnLoad;
  69.         private bool m_caching;
  70.         private bool m_throwOnLoadError;
  71.         private Encoding m_encoding;
  72.         #pragma warning restore 169
  73.        
  74.         private bool m_loaded;
  75.         private SecurityElement m_permSetElement;
  76.         private string m_path;
  77.        
  78.         private static object s_InternalSyncObject;
  79.         private static object InternalSyncObject {
  80.             get {
  81.                 if (s_InternalSyncObject == null) {
  82.                     object o = new object();
  83.                     Interlocked.CompareExchange(ref s_InternalSyncObject, o, null);
  84.                 }
  85.                 return s_InternalSyncObject;
  86.             }
  87.         }
  88.        
  89.         private static readonly string[] s_FactoryPolicySearchStrings = {"{VERSION}", "{Policy_PS_FullTrust}", "{Policy_PS_Everything}", "{Policy_PS_Nothing}", "{Policy_PS_SkipVerification}", "{Policy_PS_Execution}"};
  90.        
  91.         private static readonly string[] s_InternetPolicySearchStrings = {"{VERSION}", "{Policy_PS_Internet}"};
  92.        
  93.         private static readonly string[] s_LocalIntranetPolicySearchStrings = {"{VERSION}", "{Policy_PS_LocalIntranet}"};
  94.        
  95.         // We use the XML representation to load our default permission sets. This
  96.         // allows us to load permissions that are not defined in mscorlib
  97.        
  98.         private static readonly string s_internetPermissionSet = "<PermissionSet class=\"System.Security.NamedPermissionSet\"" + "version=\"1\" " + "Name=\"Internet\" " + "Description=\"{Policy_PS_Internet}\">" + "<Permission class=\"System.Security.Permissions.FileDialogPermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Access=\"Open\"/>" + "<Permission class=\"System.Security.Permissions.IsolatedStorageFilePermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "UserQuota=\"512000\" " + "Allowed=\"ApplicationIsolationByUser\"/>" + "<Permission class=\"System.Security.Permissions.SecurityPermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Flags=\"Execution\"/>" + "<Permission class=\"System.Security.Permissions.UIPermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Window=\"SafeTopLevelWindows\" " + "Clipboard=\"OwnClipboard\"/>" + "</PermissionSet>";
  99.        
  100.         private static readonly string s_localIntranetPermissionSet = "<PermissionSet class=\"System.Security.NamedPermissionSet\"" + "version=\"1\" " + "Name=\"LocalIntranet\" " + "Description=\"{Policy_PS_LocalIntranet}\">" + "<Permission class=\"System.Security.Permissions.EnvironmentPermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Read=\"USERNAME\"/>" + "<Permission class=\"System.Security.Permissions.FileDialogPermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Unrestricted=\"true\"/>" + "<Permission class=\"System.Security.Permissions.IsolatedStorageFilePermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Allowed=\"AssemblyIsolationByUser\" " + "UserQuota=\"9223372036854775807\" " + "Expiry=\"9223372036854775807\" " + "Permanent=\"true\"/>" + "<Permission class=\"System.Security.Permissions.ReflectionPermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Flags=\"ReflectionEmit\"/>" + "<Permission class=\"System.Security.Permissions.SecurityPermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Flags=\"Execution, Assertion, BindingRedirects\"/>" + "<Permission class=\"System.Security.Permissions.UIPermission, mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Unrestricted=\"true\"/>" + "<IPermission class=\"System.Net.DnsPermission, System, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "\"" + "version=\"1\" " + "Unrestricted=\"true\"/>" + "</PermissionSet>";
  101.        
  102.         private static readonly Version s_mscorlibVersion = Assembly.GetExecutingAssembly().GetVersion();
  103.        
  104.         private static readonly string[] s_reservedNamedPermissionSets = {"FullTrust", "Nothing", "Execution", "SkipVerification", "Internet", "LocalIntranet"};
  105.        
  106.         private static readonly string[] s_extensibleNamedPermissionSets = {"Internet", "LocalIntranet"};
  107.        
  108.         [OnDeserialized()]
  109.         private void OnDeserialized(StreamingContext ctx)
  110.         {
  111.             if (m_label != null)
  112.                 DeriveTypeFromLabel();
  113.         }
  114.        
  115.         private void DeriveTypeFromLabel()
  116.         {
  117.             if (m_label.Equals(Environment.GetResourceString("Policy_PL_User")))
  118.                 m_type = System.Security.PolicyLevelType.User;
  119.             else if (m_label.Equals(Environment.GetResourceString("Policy_PL_Machine")))
  120.                 m_type = System.Security.PolicyLevelType.Machine;
  121.             else if (m_label.Equals(Environment.GetResourceString("Policy_PL_Enterprise")))
  122.                 m_type = System.Security.PolicyLevelType.Enterprise;
  123.             else if (m_label.Equals(Environment.GetResourceString("Policy_PL_AppDomain")))
  124.                 m_type = System.Security.PolicyLevelType.AppDomain;
  125.             else
  126.                 throw new ArgumentException(Environment.GetResourceString("Policy_Default"));
  127.         }
  128.        
  129.         private string DeriveLabelFromType()
  130.         {
  131.             switch (m_type) {
  132.                 case System.Security.PolicyLevelType.User:
  133.                     return Environment.GetResourceString("Policy_PL_User");
  134.                 case System.Security.PolicyLevelType.Machine:
  135.                     return Environment.GetResourceString("Policy_PL_Machine");
  136.                 case System.Security.PolicyLevelType.Enterprise:
  137.                     return Environment.GetResourceString("Policy_PL_Enterprise");
  138.                 case System.Security.PolicyLevelType.AppDomain:
  139.                     return Environment.GetResourceString("Policy_PL_AppDomain");
  140.                 default:
  141.                     throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Arg_EnumIllegalVal"), (int)m_type));
  142.                     break;
  143.             }
  144.         }
  145.        
  146.         //
  147.         // Constructors.
  148.         // No public constructors are exposed. CreateAppDomainLevel is the only public API to create
  149.         // an AppDomain policy level, and it ensures it is an AppDomain policy level.
  150.         //
  151.        
  152.         private PolicyLevel()
  153.         {
  154.         }
  155.        
  156.         internal PolicyLevel(PolicyLevelType type) : this(type, GetLocationFromType(type))
  157.         {
  158.         }
  159.         internal PolicyLevel(PolicyLevelType type, string path) : this(type, path, ConfigId.None)
  160.         {
  161.         }
  162.         internal PolicyLevel(PolicyLevelType type, string path, ConfigId configId)
  163.         {
  164.             m_type = type;
  165.             m_path = path;
  166.             m_loaded = (path == null);
  167.             if (m_path == null) {
  168.                 m_rootCodeGroup = CreateDefaultAllGroup();
  169.                 SetFactoryPermissionSets();
  170.                 SetDefaultFullTrustAssemblies();
  171.             }
  172.             m_configId = configId;
  173.         }
  174.        
  175.         static internal string GetLocationFromType(PolicyLevelType type)
  176.         {
  177.             switch (type) {
  178.                 case PolicyLevelType.User:
  179.                     return Config.UserDirectory + "security.config";
  180.                 case PolicyLevelType.Machine:
  181.                     return Config.MachineDirectory + "security.config";
  182.                 case PolicyLevelType.Enterprise:
  183.                     return Config.MachineDirectory + "enterprisesec.config";
  184.                 default:
  185.                     return null;
  186.             }
  187.         }
  188.        
  189.         public static PolicyLevel CreateAppDomainLevel()
  190.         {
  191.             return new PolicyLevel(System.Security.PolicyLevelType.AppDomain);
  192.         }
  193.        
  194.         public string Label {
  195.             get {
  196.                 if (m_label == null)
  197.                     m_label = DeriveLabelFromType();
  198.                 return m_label;
  199.             }
  200.         }
  201.        
  202.         //
  203.         // Public properties and methods.
  204.         //
  205.        
  206.         [ComVisible(false)]
  207.         public PolicyLevelType Type {
  208.             get { return m_type; }
  209.         }
  210.        
  211.         internal ConfigId ConfigId {
  212.             get { return m_configId; }
  213.         }
  214.        
  215.         internal string Path {
  216.             get { return m_path; }
  217.         }
  218.        
  219.         public string StoreLocation {
  220.             [SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlPolicy)]
  221.             get { return GetLocationFromType(m_type); }
  222.         }
  223.        
  224.         public CodeGroup RootCodeGroup {
  225.             get {
  226.                 CheckLoaded();
  227.                 return m_rootCodeGroup;
  228.             }
  229.             set {
  230.                 if (value == null)
  231.                     throw new ArgumentNullException("RootCodeGroup");
  232.                
  233.                 CheckLoaded();
  234.                 m_rootCodeGroup = value.Copy();
  235.             }
  236.         }
  237.        
  238.         public IList NamedPermissionSets {
  239.             get {
  240.                 CheckLoaded();
  241.                 LoadAllPermissionSets();
  242.                
  243.                 ArrayList newList = new ArrayList(m_namedPermissionSets.Count);
  244.                
  245.                 IEnumerator enumerator = m_namedPermissionSets.GetEnumerator();
  246.                 while (enumerator.MoveNext()) {
  247.                     newList.Add(((NamedPermissionSet)enumerator.Current).Copy());
  248.                 }
  249.                
  250.                 return newList;
  251.             }
  252.         }
  253.        
  254.         public CodeGroup ResolveMatchingCodeGroups(Evidence evidence)
  255.         {
  256.             if (evidence == null)
  257.                 throw new ArgumentNullException("evidence");
  258.            
  259.             return this.RootCodeGroup.ResolveMatchingCodeGroups(evidence);
  260.         }
  261.        
  262.         [Obsolete("Because all GAC assemblies always get full trust, the full trust list is no longer meaningful. You should install any assemblies that are used in security policy in the GAC to ensure they are trusted.")]
  263.         public void AddFullTrustAssembly(StrongName sn)
  264.         {
  265.             if (sn == null)
  266.                 throw new ArgumentNullException("sn");
  267.            
  268.             AddFullTrustAssembly(new StrongNameMembershipCondition(sn.PublicKey, sn.Name, sn.Version));
  269.         }
  270.        
  271.         [Obsolete("Because all GAC assemblies always get full trust, the full trust list is no longer meaningful. You should install any assemblies that are used in security policy in the GAC to ensure they are trusted.")]
  272.         public void AddFullTrustAssembly(StrongNameMembershipCondition snMC)
  273.         {
  274.             if (snMC == null)
  275.                 throw new ArgumentNullException("snMC");
  276.            
  277.             CheckLoaded();
  278.            
  279.             IEnumerator enumerator = m_fullTrustAssemblies.GetEnumerator();
  280.             while (enumerator.MoveNext()) {
  281.                 if (((StrongNameMembershipCondition)enumerator.Current).Equals(snMC))
  282.                     throw new ArgumentException(Environment.GetResourceString("Argument_AssemblyAlreadyFullTrust"));
  283.             }
  284.            
  285.             lock (m_fullTrustAssemblies) {
  286.                 m_fullTrustAssemblies.Add(snMC);
  287.             }
  288.         }
  289.        
  290.         [Obsolete("Because all GAC assemblies always get full trust, the full trust list is no longer meaningful. You should install any assemblies that are used in security policy in the GAC to ensure they are trusted.")]
  291.         public void RemoveFullTrustAssembly(StrongName sn)
  292.         {
  293.             if (sn == null)
  294.                 throw new ArgumentNullException("assembly");
  295.            
  296.             RemoveFullTrustAssembly(new StrongNameMembershipCondition(sn.PublicKey, sn.Name, sn.Version));
  297.         }
  298.        
  299.         [Obsolete("Because all GAC assemblies always get full trust, the full trust list is no longer meaningful. You should install any assemblies that are used in security policy in the GAC to ensure they are trusted.")]
  300.         public void RemoveFullTrustAssembly(StrongNameMembershipCondition snMC)
  301.         {
  302.             if (snMC == null)
  303.                 throw new ArgumentNullException("snMC");
  304.            
  305.             CheckLoaded();
  306.            
  307.             object toRemove = null;
  308.             IEnumerator enumerator = m_fullTrustAssemblies.GetEnumerator();
  309.            
  310.             while (enumerator.MoveNext()) {
  311.                 if (((StrongNameMembershipCondition)enumerator.Current).Equals(snMC)) {
  312.                     toRemove = enumerator.Current;
  313.                     break;
  314.                 }
  315.             }
  316.            
  317.             if (toRemove == null)
  318.                 throw new ArgumentException(Environment.GetResourceString("Argument_AssemblyNotFullTrust"));
  319.            
  320.             lock (m_fullTrustAssemblies) {
  321.                 m_fullTrustAssemblies.Remove(toRemove);
  322.             }
  323.         }
  324.        
  325.         [Obsolete("Because all GAC assemblies always get full trust, the full trust list is no longer meaningful. You should install any assemblies that are used in security policy in the GAC to ensure they are trusted.")]
  326.         public IList FullTrustAssemblies {
  327.             get {
  328.                 CheckLoaded();
  329.                 return new ArrayList(m_fullTrustAssemblies);
  330.             }
  331.         }
  332.        
  333.         public void AddNamedPermissionSet(NamedPermissionSet permSet)
  334.         {
  335.             if (permSet == null)
  336.                 throw new ArgumentNullException("permSet");
  337.            
  338.             CheckLoaded();
  339.             LoadAllPermissionSets();
  340.            
  341.             lock (this) {
  342.                 IEnumerator enumerator = m_namedPermissionSets.GetEnumerator();
  343.                 while (enumerator.MoveNext()) {
  344.                     if (((NamedPermissionSet)enumerator.Current).Name.Equals(permSet.Name))
  345.                         throw new ArgumentException(Environment.GetResourceString("Argument_DuplicateName"));
  346.                 }
  347.                
  348.                 NamedPermissionSet npsCopy = (NamedPermissionSet)permSet.Copy();
  349.                 npsCopy.IgnoreTypeLoadFailures = true;
  350.                 m_namedPermissionSets.Add(npsCopy);
  351.             }
  352.         }
  353.        
  354.         public NamedPermissionSet RemoveNamedPermissionSet(NamedPermissionSet permSet)
  355.         {
  356.             if (permSet == null)
  357.                 throw new ArgumentNullException("permSet");
  358.            
  359.             return RemoveNamedPermissionSet(permSet.Name);
  360.         }
  361.        
  362.         public NamedPermissionSet RemoveNamedPermissionSet(string name)
  363.         {
  364.             CheckLoaded();
  365.             LoadAllPermissionSets();
  366.            
  367.             if (name == null)
  368.                 throw new ArgumentNullException("name");
  369.            
  370.             int permSetIndex = -1;
  371.            
  372.             // First, make sure it's not a reserved permission set.
  373.             for (int index = 0; index < s_reservedNamedPermissionSets.Length; ++index) {
  374.                 if (s_reservedNamedPermissionSets[index].Equals(name))
  375.                     throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_ReservedNPMS"), name));
  376.             }
  377.            
  378.             // Then, find out if a named permission set of that name exists
  379.             // and remember its index;
  380.            
  381.             ArrayList namedPermissionSets = m_namedPermissionSets;
  382.            
  383.             for (int index = 0; index < namedPermissionSets.Count; ++index) {
  384.                 if (((NamedPermissionSet)namedPermissionSets[index]).Name.Equals(name)) {
  385.                     permSetIndex = index;
  386.                     break;
  387.                 }
  388.             }
  389.            
  390.             if (permSetIndex == -1)
  391.                 throw new ArgumentException(Environment.GetResourceString("Argument_NoNPMS"));
  392.            
  393.             // Now, as best as we can in the face of custom CodeGroups figure
  394.             // out if the permission set is in use. If it is we don't allow
  395.             // it to be removed.
  396.            
  397.             ArrayList groups = new ArrayList();
  398.             groups.Add(this.m_rootCodeGroup);
  399.            
  400.             for (int index = 0; index < groups.Count; ++index) {
  401.                 CodeGroup group = (CodeGroup)groups[index];
  402.                
  403.                 if (group.PermissionSetName != null && group.PermissionSetName.Equals(name)) {
  404.                     throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_NPMSInUse"), name));
  405.                 }
  406.                
  407.                 IEnumerator childEnumerator = group.Children.GetEnumerator();
  408.                
  409.                 if (childEnumerator != null) {
  410.                     while (childEnumerator.MoveNext()) {
  411.                         groups.Add(childEnumerator.Current);
  412.                     }
  413.                 }
  414.             }
  415.            
  416.             NamedPermissionSet permSet = (NamedPermissionSet)namedPermissionSets[permSetIndex];
  417.             namedPermissionSets.RemoveAt(permSetIndex);
  418.             return permSet;
  419.         }
  420.        
  421.         public NamedPermissionSet ChangeNamedPermissionSet(string name, PermissionSet pSet)
  422.         {
  423.             if (name == null)
  424.                 throw new ArgumentNullException("name");
  425.             if (pSet == null)
  426.                 throw new ArgumentNullException("pSet");
  427.            
  428.             // First, make sure it's not a reserved permission set.
  429.             for (int index = 0; index < s_reservedNamedPermissionSets.Length; ++index) {
  430.                 if (s_reservedNamedPermissionSets[index].Equals(name))
  431.                     throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_ReservedNPMS"), name));
  432.             }
  433.            
  434.             // Get the current permission set (don't copy it).
  435.             NamedPermissionSet currentPSet = GetNamedPermissionSetInternal(name);
  436.            
  437.             // If the permission set doesn't exist, throw an argument exception
  438.             if (currentPSet == null)
  439.                 throw new ArgumentException(Environment.GetResourceString("Argument_NoNPMS"));
  440.            
  441.             // Copy the current permission set so that we can return it.
  442.             NamedPermissionSet retval = (NamedPermissionSet)currentPSet.Copy();
  443.            
  444.             // Reset the permission set
  445.             currentPSet.Reset();
  446.             currentPSet.SetUnrestricted(pSet.IsUnrestricted());
  447.            
  448.             IEnumerator enumerator = pSet.GetEnumerator();
  449.             while (enumerator.MoveNext()) {
  450.                 currentPSet.SetPermission(((IPermission)enumerator.Current).Copy());
  451.             }
  452.            
  453.             if (pSet is NamedPermissionSet) {
  454.                 currentPSet.Description = ((NamedPermissionSet)pSet).Description;
  455.             }
  456.            
  457.             return retval;
  458.         }
  459.        
  460.         public NamedPermissionSet GetNamedPermissionSet(string name)
  461.         {
  462.             if (name == null)
  463.                 throw new ArgumentNullException("name");
  464.            
  465.             NamedPermissionSet permSet = GetNamedPermissionSetInternal(name);
  466.            
  467.             // Copy it so that no corruption can occur.
  468.             if (permSet != null)
  469.                 return new NamedPermissionSet(permSet);
  470.             else
  471.                 return null;
  472.         }
  473.        
  474.         public void Recover()
  475.         {
  476.             if (m_configId == ConfigId.None)
  477.                 throw new PolicyException(Environment.GetResourceString("Policy_RecoverNotFileBased"));
  478.            
  479.             lock (this) {
  480.                 // This call will safely swap the files.
  481.                 if (!Config.RecoverData(m_configId))
  482.                     throw new PolicyException(Environment.GetResourceString("Policy_RecoverNoConfigFile"));
  483.                
  484.                 // Now we need to blank out the level
  485.                 m_loaded = false;
  486.                 m_rootCodeGroup = null;
  487.                 m_namedPermissionSets = null;
  488.                 m_fullTrustAssemblies = new ArrayList();
  489.             }
  490.         }
  491.        
  492.         public void Reset()
  493.         {
  494.             SetDefault();
  495.         }
  496.        
  497.         public PolicyStatement Resolve(Evidence evidence)
  498.         {
  499.             return Resolve(evidence, 0, null);
  500.         }
  501.        
  502.         public SecurityElement ToXml()
  503.         {
  504.             // Make sure we have loaded everything and that all the
  505.             // permission sets are loaded.
  506.            
  507.             CheckLoaded();
  508.             LoadAllPermissionSets();
  509.            
  510.             IEnumerator enumerator;
  511.             SecurityElement e = new SecurityElement("PolicyLevel");
  512.             e.AddAttribute("version", "1");
  513.            
  514.             Hashtable classes = new Hashtable();
  515.             lock (this) {
  516.                 SecurityElement elPermSets = new SecurityElement("NamedPermissionSets");
  517.                 enumerator = m_namedPermissionSets.GetEnumerator();
  518.                 while (enumerator.MoveNext()) {
  519.                     elPermSets.AddChild(NormalizeClassDeep(((NamedPermissionSet)enumerator.Current).ToXml(), classes));
  520.                 }
  521.                
  522.                 SecurityElement elCodeGroup = NormalizeClassDeep(m_rootCodeGroup.ToXml(this), classes);
  523.                
  524.                 SecurityElement elFullTrust = new SecurityElement("FullTrustAssemblies");
  525.                 enumerator = m_fullTrustAssemblies.GetEnumerator();
  526.                 while (enumerator.MoveNext()) {
  527.                     elFullTrust.AddChild(NormalizeClassDeep(((StrongNameMembershipCondition)enumerator.Current).ToXml(), classes));
  528.                 }
  529.                
  530.                 SecurityElement elClasses = new SecurityElement("SecurityClasses");
  531.                 IDictionaryEnumerator dicEnumerator = classes.GetEnumerator();
  532.                 while (dicEnumerator.MoveNext()) {
  533.                     SecurityElement elClass = new SecurityElement("SecurityClass");
  534.                     elClass.AddAttribute("Name", (string)dicEnumerator.Value);
  535.                     elClass.AddAttribute("Description", (string)dicEnumerator.Key);
  536.                     elClasses.AddChild(elClass);
  537.                 }
  538.                
  539.                 e.AddChild(elClasses);
  540.                 e.AddChild(elPermSets);
  541.                 e.AddChild(elCodeGroup);
  542.                 e.AddChild(elFullTrust);
  543.             }
  544.            
  545.             return e;
  546.         }
  547.        
  548.         public void FromXml(SecurityElement e)
  549.         {
  550.             if (e == null)
  551.                 throw new ArgumentNullException("e");
  552.            
  553.             Hashtable classes;
  554.             lock (this) {
  555.                 ArrayList fullTrustAssemblies = new ArrayList();
  556.                
  557.                 SecurityElement eClasses = e.SearchForChildByTag("SecurityClasses");
  558.                 if (eClasses != null) {
  559.                     classes = new Hashtable();
  560.                     IEnumerator enumerator = eClasses.Children.GetEnumerator();
  561.                     while (enumerator.MoveNext()) {
  562.                         SecurityElement current = (SecurityElement)enumerator.Current;
  563.                         if (current.Tag.Equals("SecurityClass")) {
  564.                             string name = current.Attribute("Name");
  565.                             string description = current.Attribute("Description");
  566.                            
  567.                             if (name != null && description != null)
  568.                                 classes.Add(name, description);
  569.                         }
  570.                     }
  571.                 }
  572.                 else {
  573.                     classes = null;
  574.                 }
  575.                
  576.                 SecurityElement elFullTrust = e.SearchForChildByTag("FullTrustAssemblies");
  577.                 if (elFullTrust != null && elFullTrust.InternalChildren != null) {
  578.                     string className = typeof(System.Security.Policy.StrongNameMembershipCondition).AssemblyQualifiedName;
  579.                    
  580.                     IEnumerator enumerator = elFullTrust.Children.GetEnumerator();
  581.                     while (enumerator.MoveNext()) {
  582.                         StrongNameMembershipCondition sn = new StrongNameMembershipCondition();
  583.                         sn.FromXml((SecurityElement)enumerator.Current);
  584.                         fullTrustAssemblies.Add(sn);
  585.                     }
  586.                 }
  587.                
  588.                 m_fullTrustAssemblies = fullTrustAssemblies;
  589.                
  590.                 ArrayList namedPermissionSets = new ArrayList();
  591.                
  592.                 SecurityElement elPermSets = e.SearchForChildByTag("NamedPermissionSets");
  593.                 SecurityElement permSetElement = null;
  594.                
  595.                 // Here we just find the parent element for the named permission sets and
  596.                 // store it so that we can lazily load them later.
  597.                
  598.                 if (elPermSets != null && elPermSets.InternalChildren != null) {
  599.                     permSetElement = UnnormalizeClassDeep(elPermSets, classes);
  600.                    
  601.                     // Call FindElement for each of the reserved sets (this removes their xml from
  602.                     // permSetElement).
  603.                    
  604.                     FindElement(permSetElement, "FullTrust");
  605.                     FindElement(permSetElement, "SkipVerification");
  606.                     FindElement(permSetElement, "Execution");
  607.                     FindElement(permSetElement, "Nothing");
  608.                     FindElement(permSetElement, "Internet");
  609.                     FindElement(permSetElement, "LocalIntranet");
  610.                 }
  611.                
  612.                 if (permSetElement == null)
  613.                     permSetElement = new SecurityElement("NamedPermissionSets");
  614.                
  615.                 // Then we add in the immutable permission sets (this prevents any alterations
  616.                 // to them in the XML file from impacting the runtime versions).
  617.                
  618.                 namedPermissionSets.Add(CreateFullTrustSet());
  619.                 namedPermissionSets.Add(CreateSkipVerificationSet());
  620.                 namedPermissionSets.Add(CreateExecutionSet());
  621.                 namedPermissionSets.Add(CreateNothingSet());
  622.                
  623.                 permSetElement.AddChild(GetInternetElement());
  624.                 permSetElement.AddChild(GetLocalIntranetElement());
  625.                
  626.                 foreach (PermissionSet ps in namedPermissionSets)
  627.                     ps.IgnoreTypeLoadFailures = true;
  628.                
  629.                 m_namedPermissionSets = namedPermissionSets;
  630.                 m_permSetElement = permSetElement;
  631.                
  632.                 // Parse the root code group.
  633.                 SecurityElement elCodeGroup = e.SearchForChildByTag("CodeGroup");
  634.                 if (elCodeGroup == null)
  635.                     throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_InvalidXMLElement"), "CodeGroup", this.GetType().FullName));
  636.                
  637.                 CodeGroup rootCodeGroup = System.Security.Util.XMLUtil.CreateCodeGroup(UnnormalizeClassDeep(elCodeGroup, classes));
  638.                 if (rootCodeGroup == null)
  639.                     throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Argument_InvalidXMLElement"), "CodeGroup", this.GetType().FullName));
  640.                
  641.                 rootCodeGroup.FromXml(elCodeGroup, this);
  642.                 m_rootCodeGroup = rootCodeGroup;
  643.             }
  644.         }
  645.        
  646.         //
  647.         // Internal methods.
  648.         //
  649.        
  650.         static internal PermissionSet GetBuiltInSet(string name)
  651.         {
  652.             // Used by PermissionSetAttribute to create one of the built-in,
  653.             // immutable permission sets.
  654.            
  655.             if (name == null)
  656.                 return null;
  657.             else if (name.Equals("FullTrust"))
  658.                 return CreateFullTrustSet();
  659.             else if (name.Equals("Nothing"))
  660.                 return CreateNothingSet();
  661.             else if (name.Equals("Execution"))
  662.                 return CreateExecutionSet();
  663.             else if (name.Equals("SkipVerification"))
  664.                 return CreateSkipVerificationSet();
  665.             else if (name.Equals("Internet"))
  666.                 return CreateInternetSet();
  667.             else if (name.Equals("LocalIntranet"))
  668.                 return CreateLocalIntranetSet();
  669.             else
  670.                 return null;
  671.         }
  672.        
  673.         internal NamedPermissionSet GetNamedPermissionSetInternal(string name)
  674.         {
  675.             CheckLoaded();
  676.            
  677.             lock (InternalSyncObject) {
  678.                 // First, try to find it in the list.
  679.                 IEnumerator enumerator = m_namedPermissionSets.GetEnumerator();
  680.                 while (enumerator.MoveNext()) {
  681.                     NamedPermissionSet current = (NamedPermissionSet)enumerator.Current;
  682.                     if (current.Name.Equals(name))
  683.                         return current;
  684.                 }
  685.                
  686.                 // We didn't find it in the list, so if we have a stored element
  687.                 // see if it is there.
  688.                
  689.                 if (m_permSetElement != null) {
  690.                     SecurityElement elem = FindElement(name);
  691.                     if (elem != null) {
  692.                         NamedPermissionSet permSet = new NamedPermissionSet();
  693.                         permSet.Name = name;
  694.                         m_namedPermissionSets.Add(permSet);
  695.                         try {
  696.                             // We play it conservative here and just say that we are loading policy
  697.                             // anytime we have to decode a permission set.
  698.                             permSet.FromXml(elem, false, true);
  699.                         }
  700.                         catch {
  701.                             m_namedPermissionSets.Remove(permSet);
  702.                             return null;
  703.                         }
  704.                        
  705.                         if (permSet.Name != null) {
  706.                             return permSet;
  707.                         }
  708.                         else {
  709.                             m_namedPermissionSets.Remove(permSet);
  710.                             return null;
  711.                         }
  712.                     }
  713.                 }
  714.                
  715.                 return null;
  716.             }
  717.         }
  718.        
  719.         internal PolicyStatement Resolve(Evidence evidence, int count, char[] serializedEvidence)
  720.         {
  721.             if (evidence == null)
  722.                 throw new ArgumentNullException("evidence");
  723.            
  724.             PolicyStatement policy = null;
  725.             if (serializedEvidence != null)
  726.                 policy = CheckCache(count, serializedEvidence);
  727.            
  728.             if (policy == null) {
  729.                 CheckLoaded();
  730.                
  731.                 bool allConst;
  732.                 bool isFullTrust = m_fullTrustAssemblies != null && IsFullTrustAssembly(m_fullTrustAssemblies, evidence);
  733.                 if (isFullTrust) {
  734.                     policy = new PolicyStatement(new PermissionSet(true), PolicyStatementAttribute.Nothing);
  735.                     allConst = true;
  736.                 }
  737.                 else {
  738.                     ArrayList list = GenericResolve(evidence, out allConst);
  739.                     policy = new PolicyStatement();
  740.                     // This will set the permission set to the empty set.
  741.                     policy.PermissionSet = null;
  742.                    
  743.                     IEnumerator enumerator = list.GetEnumerator();
  744.                     while (enumerator.MoveNext()) {
  745.                         PolicyStatement ps = ((CodeGroupStackFrame)enumerator.Current).policy;
  746.                         if (ps != null) {
  747.                             policy.GetPermissionSetNoCopy().InplaceUnion(ps.GetPermissionSetNoCopy());
  748.                             policy.Attributes |= ps.Attributes;
  749.                         }
  750.                     }
  751.                 }
  752.                 if (allConst && serializedEvidence != null)
  753.                     Cache(count, serializedEvidence, policy);
  754.             }
  755.            
  756.             return policy;
  757.         }
  758.        
  759.         //
  760.         // Private methods.
  761.         //
  762.        
  763.         private void CheckLoaded()
  764.         {
  765.             if (!m_loaded) {
  766.                 lock (InternalSyncObject) {
  767.                     if (!m_loaded)
  768.                         LoadPolicyLevel();
  769.                 }
  770.             }
  771.         }
  772.        
  773.         private static byte[] ReadFile(string fileName)
  774.         {
  775.             using (FileStream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read)) {
  776.                 int size = (int)stream.Length;
  777.                 byte[] data = new byte[size];
  778.                 size = stream.Read(data, 0, size);
  779.                 stream.Close();
  780.                 return data;
  781.             }
  782.         }
  783.        
  784.         private void LoadPolicyLevel()
  785.         {
  786.             SecurityElement elRoot;
  787.             Exception exception = null;
  788.            
  789.             CodeAccessPermission.AssertAllPossible();
  790.             if (!File.InternalExists(m_path))
  791.                 goto SETDEFAULT;
  792.            
  793.             Encoding encoding = Encoding.UTF8;
  794.            
  795.             try {
  796.                 string data = encoding.GetString(ReadFile(m_path));
  797.                 elRoot = SecurityElement.FromString(data);
  798.             }
  799.             catch (Exception ex) {
  800.                 string message;
  801.                 if (!String.IsNullOrEmpty(ex.Message)) {
  802.                     message = ex.Message;
  803.                 }
  804.                 else {
  805.                     message = ex.GetType().AssemblyQualifiedName;
  806.                 }
  807.                 exception = LoadError(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Error_SecurityPolicyFileParseEx"), Label, message));
  808.                 goto SETDEFAULT;
  809.             }
  810.            
  811.             if (elRoot == null) {
  812.                 exception = LoadError(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Error_SecurityPolicyFileParse"), Label));
  813.                 goto SETDEFAULT;
  814.             }
  815.            
  816.             SecurityElement elMscorlib = elRoot.SearchForChildByTag("mscorlib");
  817.             if (elMscorlib == null) {
  818.                 exception = LoadError(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Error_SecurityPolicyFileParse"), Label));
  819.                 goto SETDEFAULT;
  820.             }
  821.            
  822.             SecurityElement elSecurity = elMscorlib.SearchForChildByTag("security");
  823.             if (elSecurity == null) {
  824.                 exception = LoadError(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Error_SecurityPolicyFileParse"), Label));
  825.                 goto SETDEFAULT;
  826.             }
  827.            
  828.             SecurityElement elPolicy = elSecurity.SearchForChildByTag("policy");
  829.             if (elPolicy == null) {
  830.                 exception = LoadError(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Error_SecurityPolicyFileParse"), Label));
  831.                 goto SETDEFAULT;
  832.             }
  833.            
  834.             SecurityElement elPolicyLevel = elPolicy.SearchForChildByTag("PolicyLevel");
  835.             if (elPolicyLevel != null) {
  836.                 try {
  837.                     this.FromXml(elPolicyLevel);
  838.                 }
  839.                 catch (Exception) {
  840.                     exception = LoadError(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Error_SecurityPolicyFileParse"), Label));
  841.                     goto SETDEFAULT;
  842.                 }
  843.             }
  844.             else {
  845.                 exception = LoadError(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("Error_SecurityPolicyFileParse"), Label));
  846.                 goto SETDEFAULT;
  847.             }
  848.            
  849.             m_loaded = true;
  850.             return;
  851.             SETDEFAULT:
  852.            
  853.             SetDefault();
  854.             m_loaded = true;
  855.            
  856.             if (exception != null)
  857.                 throw exception;
  858.         }
  859.        
  860.         private Exception LoadError(string message)
  861.         {
  862.             //
  863.             // We ignore TypeLoadExceptions in the case of user, machine
  864.             // and Enterprise policy levels as some clients depend on that
  865.             // behavior. We'll throw an exception for any other policy levels.
  866.             //
  867.            
  868.             if (m_type != PolicyLevelType.User && m_type != PolicyLevelType.Machine && m_type != PolicyLevelType.Enterprise) {
  869.                 return new ArgumentException(message);
  870.             }
  871.             else {
  872.                 Config.WriteToEventLog(message);
  873.                 return null;
  874.             }
  875.         }
  876.        
  877.         private void Cache(int count, char[] serializedEvidence, PolicyStatement policy)
  878.         {
  879.             if (m_configId == ConfigId.None)
  880.                 return;
  881.            
  882.             byte[] policyArray = new SecurityDocument(policy.ToXml(null, true)).m_data;
  883.             Config.AddCacheEntry(m_configId, count, serializedEvidence, policyArray);
  884.         }
  885.        
  886.         private PolicyStatement CheckCache(int count, char[] serializedEvidence)
  887.         {
  888.             if (m_configId == ConfigId.None)
  889.                 return null;
  890.            
  891.             byte[] cachedValue;
  892.             if (!Config.GetCacheEntry(m_configId, count, serializedEvidence, out cachedValue))
  893.                 return null;
  894.            
  895.             PolicyStatement cachedSet = new PolicyStatement();
  896.             SecurityDocument doc = new SecurityDocument(cachedValue);
  897.             cachedSet.FromXml(doc, 0, null, true);
  898.             return cachedSet;
  899.         }
  900.        
  901.         private static NamedPermissionSet CreateFullTrustSet()
  902.         {
  903.             NamedPermissionSet permSet = new NamedPermissionSet("FullTrust", PermissionState.Unrestricted);
  904.             permSet.m_descrResource = "Policy_PS_FullTrust";
  905.             return permSet;
  906.         }
  907.        
  908.         private static NamedPermissionSet CreateNothingSet()
  909.         {
  910.             NamedPermissionSet permSet = new NamedPermissionSet("Nothing", PermissionState.None);
  911.             permSet.m_descrResource = "Policy_PS_Nothing";
  912.             return permSet;
  913.         }
  914.        
  915.         private static NamedPermissionSet CreateExecutionSet()
  916.         {
  917.             NamedPermissionSet permSet = new NamedPermissionSet("Execution", PermissionState.None);
  918.             permSet.m_descrResource = "Policy_PS_Execution";
  919.             permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
  920.             return permSet;
  921.         }
  922.        
  923.         private static NamedPermissionSet CreateSkipVerificationSet()
  924.         {
  925.             NamedPermissionSet permSet = new NamedPermissionSet("SkipVerification", PermissionState.None);
  926.             permSet.m_descrResource = "Policy_PS_SkipVerification";
  927.             permSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.SkipVerification));
  928.             return permSet;
  929.         }
  930.        
  931.         private static NamedPermissionSet CreateInternetSet()
  932.         {
  933.             PolicyLevel level = new PolicyLevel(System.Security.PolicyLevelType.User);
  934.             return level.GetNamedPermissionSet("Internet");
  935.         }
  936.        
  937.         private static NamedPermissionSet CreateLocalIntranetSet()
  938.         {
  939.             PolicyLevel level = new PolicyLevel(System.Security.PolicyLevelType.User);
  940.             return level.GetNamedPermissionSet("LocalIntranet");
  941.         }
  942.        
  943.         private static bool IsFullTrustAssembly(ArrayList fullTrustAssemblies, Evidence evidence)
  944.         {
  945.             if (fullTrustAssemblies.Count == 0)
  946.                 return false;
  947.            
  948.             if (evidence != null) {
  949.                 lock (fullTrustAssemblies) {
  950.                     IEnumerator enumerator = fullTrustAssemblies.GetEnumerator();
  951.                    
  952.                     while (enumerator.MoveNext()) {
  953.                         StrongNameMembershipCondition snMC = (StrongNameMembershipCondition)enumerator.Current;
  954.                         if (snMC.Check(evidence)) {
  955.                             if (Environment.GetCompatibilityFlag(CompatibilityFlag.FullTrustListAssembliesInGac)) {
  956.                                 if (new ZoneMembershipCondition().Check(evidence))
  957.                                     return true;
  958.                             }
  959.                             else {
  960.                                 if (new GacMembershipCondition().Check(evidence))
  961.                                     return true;
  962.                             }
  963.                         }
  964.                     }
  965.                 }
  966.             }
  967.             return false;
  968.         }
  969.        
  970.         private static SecurityElement GetInternetElement()
  971.         {
  972.             string[] repStrs = new string[s_InternetPolicySearchStrings.Length];
  973.            
  974.             repStrs[0] = ThisAssembly.Version;
  975.             repStrs[1] = Environment.GetResourceString("Policy_PS_Internet");
  976.            
  977.             SecurityElement internetSet = new Parser(s_internetPermissionSet, s_InternetPolicySearchStrings, repStrs).GetTopElement();
  978.             AppendRegistryInfoToNamedPermissionSet(internetSet, 0);
  979.             return internetSet;
  980.         }
  981.        
  982.         private static SecurityElement GetLocalIntranetElement()
  983.         {
  984.             string[] repStrs = new string[s_LocalIntranetPolicySearchStrings.Length];
  985.            
  986.             repStrs[0] = ThisAssembly.Version;
  987.             repStrs[1] = Environment.GetResourceString("Policy_PS_LocalIntranet");
  988.            
  989.             SecurityElement intranetSet = new Parser(s_localIntranetPermissionSet, s_LocalIntranetPolicySearchStrings, repStrs).GetTopElement();
  990.             AppendRegistryInfoToNamedPermissionSet(intranetSet, 1);
  991.             return intranetSet;
  992.         }
  993.        
  994.         private static void AppendRegistryInfoToNamedPermissionSet(SecurityElement securityElement, int namedPermissionSetIndex)
  995.         {
  996.         }
  997.        
  998.         private CodeGroup CreateDefaultAllGroup()
  999.         {
  1000.             UnionCodeGroup group = new UnionCodeGroup();
  1001.             group.FromXml(CreateCodeGroupElement("UnionCodeGroup", "FullTrust", new AllMembershipCondition().ToXml()), this);
  1002.             group.Name = Environment.GetResourceString("Policy_AllCode_Name");
  1003.             group.Description = Environment.GetResourceString("Policy_AllCode_DescriptionFullTrust");
  1004.             return group;
  1005.         }
  1006.        
  1007.         private CodeGroup CreateDefaultMachinePolicy()
  1008.         {
  1009.             UnionCodeGroup root = new UnionCodeGroup();
  1010.             root.FromXml(CreateCodeGroupElement("UnionCodeGroup", "Nothing", new AllMembershipCondition().ToXml()), this);
  1011.             root.Name = Environment.GetResourceString("Policy_AllCode_Name");
  1012.             root.Description = Environment.GetResourceString("Policy_AllCode_DescriptionNothing");
  1013.            
  1014.             UnionCodeGroup myComputerCodeGroup = new UnionCodeGroup();
  1015.             myComputerCodeGroup.FromXml(CreateCodeGroupElement("UnionCodeGroup", "FullTrust", new ZoneMembershipCondition(SecurityZone.MyComputer).ToXml()), this);
  1016.             myComputerCodeGroup.Name = Environment.GetResourceString("Policy_MyComputer_Name");
  1017.             myComputerCodeGroup.Description = Environment.GetResourceString("Policy_MyComputer_Description");
  1018.            
  1019.             // This code give trust to anything StrongName signed by Microsoft.
  1020.             StrongNamePublicKeyBlob blob = new StrongNamePublicKeyBlob(AssemblyRef.MicrosoftPublicKeyFull);
  1021.             UnionCodeGroup microsoft = new UnionCodeGroup();
  1022.             microsoft.FromXml(CreateCodeGroupElement("UnionCodeGroup", "FullTrust", new StrongNameMembershipCondition(blob, null, null).ToXml()), this);
  1023.             microsoft.Name = Environment.GetResourceString("Policy_Microsoft_Name");
  1024.             microsoft.Description = Environment.GetResourceString("Policy_Microsoft_Description");
  1025.             myComputerCodeGroup.AddChildInternal(microsoft);
  1026.            
  1027.             // This code give trust to anything StrongName signed using the ECMA
  1028.             // public key (core system assemblies).
  1029.             blob = new StrongNamePublicKeyBlob(AssemblyRef.EcmaPublicKeyFull);
  1030.             UnionCodeGroup ecma = new UnionCodeGroup();
  1031.             ecma.FromXml(CreateCodeGroupElement("UnionCodeGroup", "FullTrust", new StrongNameMembershipCondition(blob, null, null).ToXml()), this);
  1032.             ecma.Name = Environment.GetResourceString("Policy_Ecma_Name");
  1033.             ecma.Description = Environment.GetResourceString("Policy_Ecma_Description");
  1034.             myComputerCodeGroup.AddChildInternal(ecma);
  1035.            
  1036.             root.AddChildInternal(myComputerCodeGroup);
  1037.            
  1038.             // do the rest of the zones
  1039.             CodeGroup intranet = new UnionCodeGroup();
  1040.             intranet.FromXml(CreateCodeGroupElement("UnionCodeGroup", "LocalIntranet", new ZoneMembershipCondition(SecurityZone.Intranet).ToXml()), this);
  1041.             intranet.Name = Environment.GetResourceString("Policy_Intranet_Name");
  1042.             intranet.Description = Environment.GetResourceString("Policy_Intranet_Description");
  1043.            
  1044.             CodeGroup intranetNetCode = new NetCodeGroup(new AllMembershipCondition());
  1045.             intranetNetCode.Name = Environment.GetResourceString("Policy_IntranetNet_Name");
  1046.             intranetNetCode.Description = Environment.GetResourceString("Policy_IntranetNet_Description");
  1047.             intranet.AddChildInternal(intranetNetCode);
  1048.            
  1049.             CodeGroup intranetFileCode = new FileCodeGroup(new AllMembershipCondition(), FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery);
  1050.             intranetFileCode.Name = Environment.GetResourceString("Policy_IntranetFile_Name");
  1051.             intranetFileCode.Description = Environment.GetResourceString("Policy_IntranetFile_Description");
  1052.             intranet.AddChildInternal(intranetFileCode);
  1053.            
  1054.             root.AddChildInternal(intranet);
  1055.            
  1056.             CodeGroup internet = new UnionCodeGroup();
  1057.             internet.FromXml(CreateCodeGroupElement("UnionCodeGroup", "Internet", new ZoneMembershipCondition(SecurityZone.Internet).ToXml()), this);
  1058.             internet.Name = Environment.GetResourceString("Policy_Internet_Name");
  1059.             internet.Description = Environment.GetResourceString("Policy_Internet_Description");
  1060.            
  1061.             CodeGroup internetNet = new NetCodeGroup(new AllMembershipCondition());
  1062.             internetNet.Name = Environment.GetResourceString("Policy_InternetNet_Name");
  1063.             internetNet.Description = Environment.GetResourceString("Policy_InternetNet_Description");
  1064.             internet.AddChildInternal(internetNet);
  1065.            
  1066.             root.AddChildInternal(internet);
  1067.            
  1068.             CodeGroup untrusted = new UnionCodeGroup();
  1069.             untrusted.FromXml(CreateCodeGroupElement("UnionCodeGroup", "Nothing", new ZoneMembershipCondition(SecurityZone.Untrusted).ToXml()), this);
  1070.             untrusted.Name = Environment.GetResourceString("Policy_Untrusted_Name");
  1071.             untrusted.Description = Environment.GetResourceString("Policy_Untrusted_Description");
  1072.             root.AddChildInternal(untrusted);
  1073.            
  1074.             CodeGroup trusted = new UnionCodeGroup();
  1075.             trusted.FromXml(CreateCodeGroupElement("UnionCodeGroup", "Internet", new ZoneMembershipCondition(SecurityZone.Trusted).ToXml()), this);
  1076.             trusted.Name = Environment.GetResourceString("Policy_Trusted_Name");
  1077.             trusted.Description = Environment.GetResourceString("Policy_Trusted_Description");
  1078.             CodeGroup trustedNet = new NetCodeGroup(new AllMembershipCondition());
  1079.             trustedNet.Name = Environment.GetResourceString("Policy_TrustedNet_Name");
  1080.             trustedNet.Description = Environment.GetResourceString("Policy_TrustedNet_Description");
  1081.             trusted.AddChildInternal(trustedNet);
  1082.            
  1083.             root.AddChildInternal(trusted);
  1084.            
  1085.             return root;
  1086.         }
  1087.        
  1088.         private static SecurityElement CreateCodeGroupElement(string codeGroupType, string permissionSetName, SecurityElement mshipElement)
  1089.         {
  1090.             SecurityElement root = new SecurityElement("CodeGroup");
  1091.             root.AddAttribute("class", "System.Security." + codeGroupType + ", mscorlib, Version={VERSION}, Culture=neutral, PublicKeyToken=" + AssemblyRef.EcmaPublicKeyToken + "");
  1092.             root.AddAttribute("version", "1");
  1093.             root.AddAttribute("PermissionSetName", permissionSetName);
  1094.            
  1095.             root.AddChild(mshipElement);
  1096.            
  1097.             return root;
  1098.         }
  1099.        
  1100.         private static string[] EcmaFullTrustAssemblies = new string[] {"mscorlib.resources", "System", "System.resources", "System.Xml", "System.Xml.resources", "System.Windows.Forms", "System.Windows.Forms.resources"};
  1101.         private static string[] MicrosoftFullTrustAssemblies = new string[] {};
  1102.        
  1103.         private void SetDefaultFullTrustAssemblies()
  1104.         {
  1105.             m_fullTrustAssemblies = new ArrayList();
  1106.            
  1107.             StrongNamePublicKeyBlob ecmaBlob = new StrongNamePublicKeyBlob(AssemblyRef.EcmaPublicKeyFull);
  1108.             for (int index = 0; index < EcmaFullTrustAssemblies.Length; index++) {
  1109.                 StrongNameMembershipCondition sn = new StrongNameMembershipCondition(ecmaBlob, EcmaFullTrustAssemblies[index], s_mscorlibVersion);
  1110.                 m_fullTrustAssemblies.Add(sn);
  1111.             }
  1112.            
  1113.             StrongNamePublicKeyBlob microsoftBlob = new StrongNamePublicKeyBlob(AssemblyRef.MicrosoftPublicKeyFull);
  1114.             for (int index = 0; index < MicrosoftFullTrustAssemblies.Length; index++) {
  1115.                 StrongNameMembershipCondition sn = new StrongNameMembershipCondition(microsoftBlob, MicrosoftFullTrustAssemblies[index], s_mscorlibVersion);
  1116.                 m_fullTrustAssemblies.Add(sn);
  1117.             }
  1118.         }
  1119.        
  1120.         private void SetDefault()
  1121.         {
  1122.             lock (this) {
  1123.                 string path = GetLocationFromType(m_type) + ".default";
  1124.                 if (File.InternalExists(path)) {
  1125.                     PolicyLevel level = new PolicyLevel(m_type, path);
  1126.                     m_rootCodeGroup = level.RootCodeGroup;
  1127.                     m_namedPermissionSets = (ArrayList)level.NamedPermissionSets;
  1128.                     #pragma warning disable 618 // for obsolete FullTrustAssemblies property.
  1129.                     m_fullTrustAssemblies = (ArrayList)level.FullTrustAssemblies;
  1130.                     #pragma warning restore 618
  1131.                     m_loaded = true;
  1132.                 }
  1133.                 else {
  1134.                     m_namedPermissionSets = null;
  1135.                     m_rootCodeGroup = null;
  1136.                     m_permSetElement = null;
  1137.                     m_rootCodeGroup = (m_type == PolicyLevelType.Machine ? CreateDefaultMachinePolicy() : CreateDefaultAllGroup());
  1138.                     SetFactoryPermissionSets();
  1139.                     SetDefaultFullTrustAssemblies();
  1140.                     m_loaded = true;
  1141.                 }
  1142.             }
  1143.         }
  1144.        
  1145.         private void SetFactoryPermissionSets()
  1146.         {
  1147.             lock (this) {
  1148.                 m_namedPermissionSets = new ArrayList();
  1149.                 string[] repStrs = new string[s_FactoryPolicySearchStrings.Length];
  1150.                
  1151.                 repStrs[0] = ThisAssembly.Version;
  1152.                 repStrs[1] = Environment.GetResourceString("Policy_PS_FullTrust");
  1153.                 repStrs[2] = Environment.GetResourceString("Policy_PS_Everything");
  1154.                 repStrs[3] = Environment.GetResourceString("Policy_PS_Nothing");
  1155.                 repStrs[4] = Environment.GetResourceString("Policy_PS_SkipVerification");
  1156.                 repStrs[5] = Environment.GetResourceString("Policy_PS_Execution");
  1157.                
  1158.                 m_permSetElement = new Parser(PolicyLevelData.s_defaultPermissionSets, s_FactoryPolicySearchStrings, repStrs).GetTopElement();
  1159.                 m_permSetElement.AddChild(GetInternetElement());
  1160.                 m_permSetElement.AddChild(GetLocalIntranetElement());
  1161.             }
  1162.         }
  1163.        
  1164.         private SecurityElement FindElement(string name)
  1165.         {
  1166.             SecurityElement element = FindElement(m_permSetElement, name);
  1167.            
  1168.             if (m_permSetElement.InternalChildren.Count == 0)
  1169.                 m_permSetElement = null;
  1170.            
  1171.             return element;
  1172.         }
  1173.        
  1174.         private SecurityElement FindElement(SecurityElement element, string name)
  1175.         {
  1176.             // This method searches through the children of the saved element
  1177.             // for a named permission set that matches the input name.
  1178.             // If it finds a matching set, the appropriate xml element is
  1179.             // removed from as a child of the parent and then returned.
  1180.            
  1181.             IEnumerator elemEnumerator = element.Children.GetEnumerator();
  1182.            
  1183.             while (elemEnumerator.MoveNext()) {
  1184.                 SecurityElement elPermSet = (SecurityElement)elemEnumerator.Current;
  1185.                 if (elPermSet.Tag.Equals("PermissionSet")) {
  1186.                     string elName = elPermSet.Attribute("Name");
  1187.                    
  1188.                     if (elName != null && elName.Equals(name)) {
  1189.                         element.InternalChildren.Remove(elPermSet);
  1190.                         return elPermSet;
  1191.                     }
  1192.                 }
  1193.             }
  1194.            
  1195.             return null;
  1196.         }
  1197.        
  1198.         private void LoadAllPermissionSets()
  1199.         {
  1200.             // This function loads all the permission sets held in the m_permSetElement member.
  1201.             // This is useful when you know that an arbitrary permission set loaded from
  1202.             // the config file could be accessed so you just want to forego the lazy load
  1203.             // and play it safe.
  1204.            
  1205.             if (m_permSetElement != null && m_permSetElement.InternalChildren != null) {
  1206.                 lock (InternalSyncObject) {
  1207.                     while (m_permSetElement != null && m_permSetElement.InternalChildren.Count != 0) {
  1208.                         SecurityElement elPermSet = (SecurityElement)m_permSetElement.Children[m_permSetElement.InternalChildren.Count - 1];
  1209.                         m_permSetElement.InternalChildren.RemoveAt(m_permSetElement.InternalChildren.Count - 1);
  1210.                        
  1211.                         if (elPermSet.Tag.Equals("PermissionSet") && elPermSet.Attribute("class").Equals("System.Security.NamedPermissionSet")) {
  1212.                             NamedPermissionSet permSet = new NamedPermissionSet();
  1213.                             permSet.FromXmlNameOnly(elPermSet);
  1214.                            
  1215.                             if (permSet.Name != null) {
  1216.                                 m_namedPermissionSets.Add(permSet);
  1217.                                 try {
  1218.                                     permSet.FromXml(elPermSet, false, true);
  1219.                                 }
  1220.                                 catch {
  1221.                                     m_namedPermissionSets.Remove(permSet);
  1222.                                 }
  1223.                             }
  1224.                         }
  1225.                     }
  1226.                    
  1227.                     m_permSetElement = null;
  1228.                 }
  1229.             }
  1230.         }
  1231.        
  1232.         private ArrayList GenericResolve(Evidence evidence, out bool allConst)
  1233.         {
  1234.             CodeGroupStack stack = new CodeGroupStack();
  1235.            
  1236.             // Note: if m_rootCodeGroup is null it means that we've
  1237.             // hit a recursive load case and ended up needing to
  1238.             // do a resolve on an assembly used in policy but is
  1239.             // not covered by the full trust assemblies list. We'll
  1240.             // throw a policy exception to cover this case.
  1241.            
  1242.             CodeGroupStackFrame frame;
  1243.             CodeGroup rootCodeGroupRef = m_rootCodeGroup;
  1244.            
  1245.             if (rootCodeGroupRef == null)
  1246.                 throw new PolicyException(Environment.GetResourceString("Policy_NonFullTrustAssembly"));
  1247.            
  1248.             frame = new CodeGroupStackFrame();
  1249.             frame.current = rootCodeGroupRef;
  1250.             frame.parent = null;
  1251.            
  1252.             stack.Push(frame);
  1253.            
  1254.             ArrayList accumulator = new ArrayList();
  1255.            
  1256.             bool foundExclusive = false;
  1257.            
  1258.             allConst = true;
  1259.            
  1260.             Exception storedException = null;
  1261.            
  1262.             while (!stack.IsEmpty()) {
  1263.                 frame = stack.Pop();
  1264.                 IUnionSemanticCodeGroup unionGroup = frame.current as IUnionSemanticCodeGroup;
  1265.                 FirstMatchCodeGroup firstMatchGroup = frame.current as FirstMatchCodeGroup;
  1266.                
  1267.                 if (!(frame.current.MembershipCondition is IConstantMembershipCondition) || (unionGroup == null && firstMatchGroup == null)) {
  1268.                     allConst = false;
  1269.                 }
  1270.                
  1271.                 try {
  1272.                     if (unionGroup != null)
  1273.                         frame.policy = unionGroup.InternalResolve(evidence);
  1274.                     else
  1275.                         frame.policy = frame.current.Resolve(evidence);
  1276.                 }
  1277.                 catch (Exception e) {
  1278.                     // If any exception occurs while attempting a resolve, we catch it here and
  1279.                     // set the equivalent of the resolve not matching to the evidence.
  1280.                     //frame.policy = null;
  1281.                    
  1282.                     if (storedException == null)
  1283.                         storedException = e;
  1284.                 }
  1285.                
  1286.                 if (frame.policy != null) {
  1287.                     if ((frame.policy.Attributes & PolicyStatementAttribute.Exclusive) != 0) {
  1288.                         if (foundExclusive)
  1289.                             throw new PolicyException(Environment.GetResourceString("Policy_MultipleExclusive"));
  1290.                        
  1291.                         accumulator.RemoveRange(0, accumulator.Count);
  1292.                         accumulator.Add(frame);
  1293.                         foundExclusive = true;
  1294.                     }
  1295.                    
  1296.                     // We unroll the recursion in the case where we have UnionCodeGroups or NetCodeGroups.
  1297.                     if (unionGroup != null) {
  1298.                         IList children = ((CodeGroup)frame.current).GetChildrenInternal();
  1299.                        
  1300.                         if (children != null && children.Count > 0) {
  1301.                             IEnumerator enumerator = children.GetEnumerator();
  1302.                            
  1303.                             while (enumerator.MoveNext()) {
  1304.                                 CodeGroupStackFrame newFrame = new CodeGroupStackFrame();
  1305.                                
  1306.                                 newFrame.current = (CodeGroup)enumerator.Current;
  1307.                                 newFrame.parent = frame;
  1308.                                
  1309.                                 stack.Push(newFrame);
  1310.                             }
  1311.                         }
  1312.                     }
  1313.                    
  1314.                     if (!foundExclusive) {
  1315.                         accumulator.Add(frame);
  1316.                     }
  1317.                 }
  1318.             }
  1319.            
  1320.             if (storedException != null)
  1321.                 throw storedException;
  1322.            
  1323.             return accumulator;
  1324.         }
  1325.        
  1326.         private static string GenerateFriendlyName(string className, Hashtable classes)
  1327.         {
  1328.             if (classes.ContainsKey(className))
  1329.                 return (string)classes[className];
  1330.            
  1331.             Type type = System.Type.GetType(className, false, false);
  1332.             if (type != null && !type.IsVisible)
  1333.                 type = null;
  1334.            
  1335.             if (type == null)
  1336.                 return className;
  1337.            
  1338.             if (!classes.ContainsValue(type.Name)) {
  1339.                 classes.Add(className, type.Name);
  1340.                 return type.Name;
  1341.             }
  1342.             else if (!classes.ContainsValue(type.FullName)) {
  1343.                 classes.Add(className, type.FullName);
  1344.                 return type.FullName;
  1345.             }
  1346.             else {
  1347.                 classes.Add(className, type.AssemblyQualifiedName);
  1348.                 return type.AssemblyQualifiedName;
  1349.             }
  1350.         }
  1351.        
  1352.         private SecurityElement NormalizeClassDeep(SecurityElement elem, Hashtable classes)
  1353.         {
  1354.             NormalizeClass(elem, classes);
  1355.            
  1356.             if (elem.InternalChildren != null && elem.InternalChildren.Count > 0) {
  1357.                 IEnumerator enumerator = elem.Children.GetEnumerator();
  1358.                 while (enumerator.MoveNext()) {
  1359.                     NormalizeClassDeep((SecurityElement)enumerator.Current, classes);
  1360.                 }
  1361.             }
  1362.            
  1363.             return elem;
  1364.         }
  1365.        
  1366.         private SecurityElement NormalizeClass(SecurityElement elem, Hashtable classes)
  1367.         {
  1368.             if (elem.m_lAttributes == null || elem.m_lAttributes.Count == 0)
  1369.                 return elem;
  1370.            
  1371.             int iMax = elem.m_lAttributes.Count;
  1372.             BCLDebug.Assert(iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly");
  1373.            
  1374.             for (int i = 0; i < iMax; i += 2) {
  1375.                 string strAttrName = (string)elem.m_lAttributes[i];
  1376.                
  1377.                 if (strAttrName.Equals("class")) {
  1378.                     string strAttrValue = (string)elem.m_lAttributes[i + 1];
  1379.                    
  1380.                     elem.m_lAttributes[i + 1] = GenerateFriendlyName(strAttrValue, classes);
  1381.                    
  1382.                     // only one class attribute so we can stop once we found it
  1383.                     break;
  1384.                 }
  1385.             }
  1386.            
  1387.             return elem;
  1388.         }
  1389.        
  1390.         private SecurityElement UnnormalizeClassDeep(SecurityElement elem, Hashtable classes)
  1391.         {
  1392.             UnnormalizeClass(elem, classes);
  1393.            
  1394.             if (elem.InternalChildren != null && elem.InternalChildren.Count > 0) {
  1395.                 IEnumerator enumerator = elem.Children.GetEnumerator();
  1396.                
  1397.                 while (enumerator.MoveNext()) {
  1398.                     UnnormalizeClassDeep((SecurityElement)enumerator.Current, classes);
  1399.                 }
  1400.             }
  1401.            
  1402.             return elem;
  1403.         }
  1404.        
  1405.         private SecurityElement UnnormalizeClass(SecurityElement elem, Hashtable classes)
  1406.         {
  1407.             if (classes == null || elem.m_lAttributes == null || elem.m_lAttributes.Count == 0)
  1408.                 return elem;
  1409.            
  1410.             int iMax = elem.m_lAttributes.Count;
  1411.             BCLDebug.Assert(iMax % 2 == 0, "Odd number of strings means the attr/value pairs were not added correctly");
  1412.            
  1413.             for (int i = 0; i < iMax; i += 2) {
  1414.                 string strAttrName = (string)elem.m_lAttributes[i];
  1415.                
  1416.                 if (strAttrName.Equals("class")) {
  1417.                     string strAttrValue = (string)elem.m_lAttributes[i + 1];
  1418.                     string className = (string)classes[strAttrValue];
  1419.                    
  1420.                     if (className != null)
  1421.                         elem.m_lAttributes[i + 1] = className;
  1422.                    
  1423.                     // only one class attribute so we can stop after we found it
  1424.                     // no other matches are possible
  1425.                     break;
  1426.                 }
  1427.             }
  1428.            
  1429.             return elem;
  1430.         }
  1431.     }
  1432.    
  1433.     internal sealed class CodeGroupStackFrame
  1434.     {
  1435.         internal CodeGroup current;
  1436.         internal PolicyStatement policy;
  1437.         internal CodeGroupStackFrame parent;
  1438.     }
  1439.    
  1440.     internal sealed class CodeGroupStack
  1441.     {
  1442.         private ArrayList m_array;
  1443.        
  1444.         internal CodeGroupStack()
  1445.         {
  1446.             m_array = new ArrayList();
  1447.         }
  1448.        
  1449.         internal void Push(CodeGroupStackFrame element)
  1450.         {
  1451.             m_array.Add(element);
  1452.         }
  1453.        
  1454.         internal CodeGroupStackFrame Pop()
  1455.         {
  1456.             if (IsEmpty())
  1457.                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EmptyStack"));
  1458.            
  1459.             int count = m_array.Count;
  1460.             CodeGroupStackFrame temp = (CodeGroupStackFrame)m_array[count - 1];
  1461.             m_array.RemoveAt(count - 1);
  1462.             return temp;
  1463.         }
  1464.        
  1465.         internal bool IsEmpty()
  1466.         {
  1467.             return m_array.Count == 0;
  1468.         }
  1469.     }
  1470. }

Developer Fusion