The Labs \ Source Viewer \ SSCLI \ System.Configuration \ RuntimeConfigurationFactory

  1. //------------------------------------------------------------------------------
  2. // <copyright file="RuntimeConfigurationRecord.cs" company="Microsoft">
  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. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Configuration
  16. {
  17.     using System.Collections;
  18.     using System.Collections.Specialized;
  19.     using System.Globalization;
  20.     using System.IO;
  21.     using System.Reflection;
  22.     using System.Security;
  23.     using System.Security.Permissions;
  24.     using System.Security.Policy;
  25.     using System.Xml;
  26.     using System.Net;
  27.     using System.Configuration.Internal;
  28.     using Assembly = System.Reflection.Assembly;
  29.    
  30.     internal sealed class RuntimeConfigurationRecord : BaseConfigurationRecord
  31.     {
  32.        
  33.         static internal IInternalConfigRecord Create(InternalConfigRoot configRoot, IInternalConfigRecord parent, string configPath)
  34.         {
  35.            
  36.             RuntimeConfigurationRecord configRecord = new RuntimeConfigurationRecord();
  37.             configRecord.Init(configRoot, (BaseConfigurationRecord)parent, configPath, null);
  38.             return configRecord;
  39.         }
  40.        
  41.         private RuntimeConfigurationRecord()
  42.         {
  43.         }
  44.        
  45.         static readonly SimpleBitVector32 RuntimeClassFlags = new SimpleBitVector32(ClassSupportsChangeNotifications | ClassSupportsRefresh | ClassSupportsImpersonation | ClassSupportsRestrictedPermissions | ClassSupportsDelayedInit);
  46.        
  47.         protected override SimpleBitVector32 ClassFlags {
  48.             get { return RuntimeClassFlags; }
  49.         }
  50.        
  51.         // Create the factory that will evaluate configuration
  52.         protected override object CreateSectionFactory(FactoryRecord factoryRecord)
  53.         {
  54.             return new RuntimeConfigurationFactory(this, factoryRecord);
  55.         }
  56.        
  57.         // parentConfig contains the config that we'd merge with.
  58.         protected override object CreateSection(bool inputIsTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, object parentConfig, ConfigXmlReader reader)
  59.         {
  60.             // Get the factory used to create a section.
  61.             RuntimeConfigurationFactory factory = (RuntimeConfigurationFactory)factoryRecord.Factory;
  62.            
  63.             // Use the factory to create a section.
  64.             object config = factory.CreateSection(inputIsTrusted, this, factoryRecord, sectionRecord, parentConfig, reader);
  65.            
  66.             return config;
  67.         }
  68.        
  69.         protected override object UseParentResult(string configKey, object parentResult, SectionRecord sectionRecord)
  70.         {
  71.             return parentResult;
  72.         }
  73.        
  74.         // Ignore user code on the stack
  75.         [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
  76.         private object GetRuntimeObjectWithFullTrust(ConfigurationSection section)
  77.         {
  78.             return section.GetRuntimeObject();
  79.         }
  80.        
  81.         private object GetRuntimeObjectWithRestrictedPermissions(ConfigurationSection section)
  82.         {
  83.             // Run configuration section handlers as if user code was on the stack
  84.             bool revertPermitOnly = false;
  85.            
  86.             try {
  87.                 PermissionSet permissionSet = GetRestrictedPermissions();
  88.                 if (permissionSet != null) {
  89.                     permissionSet.PermitOnly();
  90.                     revertPermitOnly = true;
  91.                 }
  92.                
  93.                 return section.GetRuntimeObject();
  94.             }
  95.             finally {
  96.                 if (revertPermitOnly) {
  97.                     CodeAccessPermission.RevertPermitOnly();
  98.                 }
  99.             }
  100.         }
  101.        
  102.         protected override object GetRuntimeObject(object result)
  103.         {
  104.             object runtimeObject;
  105.             ConfigurationSection section = result as ConfigurationSection;
  106.             if (section == null) {
  107.                 runtimeObject = result;
  108.             }
  109.             else {
  110.                 // Call into config section while impersonating process or UNC identity
  111.                 // so that the section could read files from disk if needed
  112.                 try {
  113.                     using (Impersonate()) {
  114.                         // If this configRecord is trusted, ignore user code on stack
  115.                         if (_flags[IsTrusted]) {
  116.                             runtimeObject = GetRuntimeObjectWithFullTrust(section);
  117.                         }
  118.                         else {
  119.                             // Run configuration section handlers as if user code was on the stack
  120.                             runtimeObject = GetRuntimeObjectWithRestrictedPermissions(section);
  121.                         }
  122.                     }
  123.                 }
  124.                 catch (Exception e) {
  125.                     throw new ConfigurationErrorsException(SR.GetString(SR.Config_exception_in_config_section_handler, section.SectionInformation.SectionName), e);
  126.                 }
  127.                 catch {
  128.                     throw new ConfigurationErrorsException(SR.GetString(SR.Config_exception_in_config_section_handler, section.SectionInformation.SectionName));
  129.                 }
  130.             }
  131.            
  132.             return runtimeObject;
  133.         }
  134.        
  135.         [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
  136.         protected override string CallHostDecryptSection(string encryptedXml, ProtectedConfigurationProvider protectionProvider, ProtectedConfigurationSection protectedConfig)
  137.         {
  138.             return base.CallHostDecryptSection(encryptedXml, protectionProvider, protectedConfig);
  139.         }
  140.        
  141.         private class RuntimeConfigurationFactory
  142.         {
  143.             ConstructorInfo _sectionCtor;
  144.             IConfigurationSectionHandler _sectionHandler;
  145.            
  146.             internal RuntimeConfigurationFactory(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord)
  147.             {
  148.                 // If the factory record was defined in a trusted config record, ignore user code on stack
  149.                 if (factoryRecord.IsFromTrustedConfigRecord) {
  150.                     InitWithFullTrust(configRecord, factoryRecord);
  151.                 }
  152.                 else {
  153.                     // Run configuration section handlers as if user code was on the stack
  154.                     InitWithRestrictedPermissions(configRecord, factoryRecord);
  155.                 }
  156.             }
  157.            
  158.             private void Init(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord)
  159.             {
  160.                 // Get the type of the factory
  161.                 Type type = TypeUtil.GetTypeWithReflectionPermission(configRecord.Host, factoryRecord.FactoryTypeName, true);
  162.                
  163.                 // If the type is a ConfigurationSection, that's the type.
  164.                 if (typeof(ConfigurationSection).IsAssignableFrom(type)) {
  165.                     _sectionCtor = TypeUtil.GetConstructorWithReflectionPermission(type, typeof(ConfigurationSection), true);
  166.                 }
  167.                 else {
  168.                     // Note: in v1, IConfigurationSectionHandler is in effect a factory that has a Create method
  169.                     // that creates the real section object.
  170.                    
  171.                     // throws if type does not implement IConfigurationSectionHandler
  172.                     TypeUtil.VerifyAssignableType(typeof(IConfigurationSectionHandler), type, true);
  173.                    
  174.                     // Create an instance of the handler
  175.                     _sectionHandler = (IConfigurationSectionHandler)TypeUtil.CreateInstanceWithReflectionPermission(type);
  176.                 }
  177.             }
  178.            
  179.             // Ignore user code on the stack
  180.             [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
  181.             private void InitWithFullTrust(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord)
  182.             {
  183.                 Init(configRecord, factoryRecord);
  184.             }
  185.            
  186.             private void InitWithRestrictedPermissions(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord)
  187.             {
  188.                 // Run configuration section handlers as if user code was on the stack
  189.                 bool revertPermitOnly = false;
  190.                 try {
  191.                     PermissionSet permissionSet = configRecord.GetRestrictedPermissions();
  192.                     if (permissionSet != null) {
  193.                         permissionSet.PermitOnly();
  194.                         revertPermitOnly = true;
  195.                     }
  196.                    
  197.                     Init(configRecord, factoryRecord);
  198.                 }
  199.                 finally {
  200.                     if (revertPermitOnly) {
  201.                         CodeAccessPermission.RevertPermitOnly();
  202.                     }
  203.                 }
  204.             }
  205.            
  206.             //
  207.             // Throw an exception if an attribute within a legacy section is one of our
  208.             // reserved locking attributes. We do not want admins to think they can lock
  209.             // an attribute or element within a legacy section.
  210.             //
  211.             private static void CheckForLockAttributes(string sectionName, XmlNode xmlNode)
  212.             {
  213.                 XmlAttributeCollection attributes = xmlNode.Attributes;
  214.                 if (attributes != null) {
  215.                     foreach (XmlAttribute attribute in attributes) {
  216.                         if (ConfigurationElement.IsLockAttributeName(attribute.Name)) {
  217.                             throw new ConfigurationErrorsException(SR.GetString(SR.Config_element_locking_not_supported, sectionName), attribute);
  218.                         }
  219.                     }
  220.                 }
  221.                
  222.                 foreach (XmlNode child in xmlNode.ChildNodes) {
  223.                     if (xmlNode.NodeType == XmlNodeType.Element) {
  224.                         CheckForLockAttributes(sectionName, child);
  225.                     }
  226.                 }
  227.             }
  228.            
  229.             private object CreateSectionImpl(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord, object parentConfig, ConfigXmlReader reader)
  230.             {
  231.                
  232.                 object config;
  233.                
  234.                 if (_sectionCtor != null) {
  235.                     ConfigurationSection configSection = (ConfigurationSection)TypeUtil.InvokeCtorWithReflectionPermission(_sectionCtor);
  236.                    
  237.                     configSection.SectionInformation.SetRuntimeConfigurationInformation(configRecord, factoryRecord, sectionRecord);
  238.                    
  239.                     configSection.CallInit();
  240.                    
  241.                     ConfigurationSection parentSection = (ConfigurationSection)parentConfig;
  242.                     configSection.Reset(parentSection);
  243.                    
  244.                     if (reader != null) {
  245.                         configSection.DeserializeSection(reader);
  246.                     }
  247.                    
  248.                     // throw if there are any cached errors
  249.                     ConfigurationErrorsException errors = configSection.GetErrors();
  250.                     if (errors != null) {
  251.                         throw errors;
  252.                     }
  253.                    
  254.                     // don't allow changes to sections at runtime
  255.                     configSection.SetReadOnly();
  256.                    
  257.                     // reset the modified bit
  258.                     configSection.ResetModified();
  259.                    
  260.                     config = configSection;
  261.                 }
  262.                 else {
  263.                     if (reader != null) {
  264.                         XmlNode xmlNode = ErrorInfoXmlDocument.CreateSectionXmlNode(reader);
  265.                        
  266.                         CheckForLockAttributes(factoryRecord.ConfigKey, xmlNode);
  267.                        
  268.                         // In v1, our old section handler expects a context that contains the virtualPath from the configPath
  269.                         object configContext = configRecord.Host.CreateDeprecatedConfigContext(configRecord.ConfigPath);
  270.                        
  271.                         config = _sectionHandler.Create(parentConfig, configContext, xmlNode);
  272.                     }
  273.                     else {
  274.                         config = null;
  275.                     }
  276.                 }
  277.                
  278.                 return config;
  279.             }
  280.            
  281.             // Ignore user code on the stack
  282.             [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
  283.             private object CreateSectionWithFullTrust(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord, object parentConfig, ConfigXmlReader reader)
  284.             {
  285.                
  286.                 return CreateSectionImpl(configRecord, factoryRecord, sectionRecord, parentConfig, reader);
  287.             }
  288.            
  289.             private object CreateSectionWithRestrictedPermissions(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord, object parentConfig, ConfigXmlReader reader)
  290.             {
  291.                
  292.                 // run configuration section handlers as if user code was on the stack
  293.                 bool revertPermitOnly = false;
  294.                 try {
  295.                     PermissionSet permissionSet = configRecord.GetRestrictedPermissions();
  296.                     if (permissionSet != null) {
  297.                         permissionSet.PermitOnly();
  298.                         revertPermitOnly = true;
  299.                     }
  300.                    
  301.                     return CreateSectionImpl(configRecord, factoryRecord, sectionRecord, parentConfig, reader);
  302.                 }
  303.                 finally {
  304.                     if (revertPermitOnly) {
  305.                         CodeAccessPermission.RevertPermitOnly();
  306.                     }
  307.                 }
  308.             }
  309.            
  310.             internal object CreateSection(bool inputIsTrusted, RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord, object parentConfig, ConfigXmlReader reader)
  311.             {
  312.                
  313.                 if (inputIsTrusted) {
  314.                     return CreateSectionWithFullTrust(configRecord, factoryRecord, sectionRecord, parentConfig, reader);
  315.                 }
  316.                 else {
  317.                     return CreateSectionWithRestrictedPermissions(configRecord, factoryRecord, sectionRecord, parentConfig, reader);
  318.                 }
  319.             }
  320.         }
  321.     }
  322. }

Developer Fusion