Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Framework / MS / Internal / AppModel / AssemblyFilter.cs / 1 / AssemblyFilter.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // This class is used to filter assemblies as they are loaded into an application domain. // The intent is to bring the AppDomain down in the case that one of these is on a disallowed list // similar to the kill bit for Activex // // History: // 11/15/05: akaza Created. //--------------------------------------------------------------------------- using System; using System.Windows; using MS.Internal.PresentationFramework; using System.Collections.Generic; using MS.Win32; using Microsoft.Win32; using System.Security; using System.Security.Permissions; using System.Reflection; using System.Text; using MS.Internal.AppModel; using MS.Internal; using System.Windows.Resources; using System.Diagnostics; using System.Runtime.InteropServices; namespace MS.Internal { internal class AssemblyFilter { ////// Critical: This code sets the allowed assemblies on AssemblyList /// TreatAsSafe: Initializing the data is ok since it does not expose anything /// [SecurityCritical,SecurityTreatAsSafe] static AssemblyFilter() { _disallowedListExtracted = new SecurityCriticalDataForSet(false); _assemblyList = new SecurityCriticalDataForSet >(new System.Collections.Generic.List ()); } /// /// Critical: This code calls into unmanaged Api that has a SUC on this (IAssemblCache related) /// [SecurityCritical] internal void FilterCallback(Object sender, AssemblyLoadEventArgs args) { // This code is reentrant lock (_lock) { // Extract assembly Assembly a = args.LoadedAssembly; // xmlns cache loads assemblies as reflection only and we cannot inspect these using the code below // so we ignore also keeping this first is super important because the first time cost is really high // other wise also we cannot do any processing on a reflection only assembly aside from reflection based actions if (!a.ReflectionOnly) { // check if it is in the Gac , this ensures that we eliminate any non GAC assembly which are of no risk if (a.GlobalAssemblyCache) { object[] aptca = a.GetCustomAttributes(typeof(AllowPartiallyTrustedCallersAttribute), false); // if the dll has APTCA if (aptca.Length > 0 && aptca[0] is AllowPartiallyTrustedCallersAttribute) { string assemblyName = AssemblyNameWithFileVersion(a); // If we are on the disallowed list kill the application domain if (AssemblyOnDisallowedList(assemblyName)) { // Kill the application domain UnsafeNativeMethods.ProcessUnhandledException_DLL(SR.Get(SRID.KillBitEnforcedShutdown) + assemblyName); // I want to ensure that the process really dies new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();//BlessedAssert try { System.Environment.Exit(-1); } finally { SecurityPermission.RevertAssert(); Debug.Fail("Environment.Exit() failed."); } } } } } } } //appends assembly name with file version to generate a unique entry for the assembly lookup process ////// Critical: This code elevates to extract assembly name /// [SecurityCritical] private string AssemblyNameWithFileVersion(Assembly a) { FileVersionInfo fileVersionInfo; StringBuilder sb = new StringBuilder(a.FullName); // we need unrestricted here because the location is demands too. (new FileIOPermission(PermissionState.Unrestricted)).Assert();//BlessedAssert try { fileVersionInfo = FileVersionInfo.GetVersionInfo(a.Location); } finally { FileIOPermission.RevertAssert(); } if (fileVersionInfo != null && fileVersionInfo.ProductVersion != null) { sb.Append(FILEVERSION_STRING + fileVersionInfo.ProductVersion); } return ((sb.ToString()).ToLower(System.Globalization.CultureInfo.InvariantCulture)).Trim(); } ////// Critical: This code populates _assemblyList with Disallowed Elements and sets the bit that dictates whether to repopulate it /// [SecurityCritical] private bool AssemblyOnDisallowedList(String assemblyToCheck) { bool retVal = false; // if the list disallowed list is not populated populate it once if (_disallowedListExtracted.Value == false) { // hit the registry one time and read ExtractDisallowedRegistryList(); _disallowedListExtracted.Value = true; } if (_assemblyList.Value.Contains(assemblyToCheck)) { retVal = true; } return retVal; } ////// Critical: This code opens an HKLM registry location and reads it. We do not want /// to call this over and over as it could cause performance issues /// [SecurityCritical] private void ExtractDisallowedRegistryList() { string[] disallowedAssemblies; RegistryKey featureKey; //Assert for read access to HKLM\Software\Microsoft\.NetFramework\Policy\APTCA (new RegistryPermission(RegistryPermissionAccess.Read, KILL_BIT_REGISTRY_HIVE + KILL_BIT_REGISTRY_LOCATION)).Assert();//BlessedAssert try { // open the key and read the value featureKey = Registry.LocalMachine.OpenSubKey(KILL_BIT_REGISTRY_LOCATION); if (featureKey != null) { // Enumerate through all keys and populate dictionary disallowedAssemblies = featureKey.GetSubKeyNames(); // iterate over this list and for each extract the APTCA_FLAG value and set it in the // dictionary foreach (string assemblyName in disallowedAssemblies) { featureKey = Registry.LocalMachine.OpenSubKey(KILL_BIT_REGISTRY_LOCATION + @"\" + assemblyName); object keyValue = featureKey.GetValue(SUBKEY_VALUE); // if there exists a value and it is 1 add to hash table if ((keyValue != null) && (int)(keyValue) == 1) { if (!_assemblyList.Value.Contains(assemblyName)) { _assemblyList.Value.Add(assemblyName.ToLower(System.Globalization.CultureInfo.InvariantCulture).Trim()); } } } } } finally { RegistryPermission.RevertAssert(); } } ////// Critical: This holds a list of assemblies that are on an allowed and disallowed list and can be exploited to load /// unsafe dll's into appdomain /// static SecurityCriticalDataForSet> _assemblyList; /// /// Critical: This bit determines whether we need to hit the registry and load the disallowed elements. /// We would like to see this happen only once per appdomain and delay it as much as possible /// static SecurityCriticalDataForSet_disallowedListExtracted; static object _lock = new object(); private const string FILEVERSION_STRING = @", FileVersion="; // This is the location in the registry where all the keys are stored private const string KILL_BIT_REGISTRY_HIVE = @"HKEY_LOCAL_MACHINE\"; private const string KILL_BIT_REGISTRY_LOCATION = @"Software\Microsoft\.NetFramework\policy\APTCA"; private const string SUBKEY_VALUE = @"APTCA_FLAG"; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- // // // Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // This class is used to filter assemblies as they are loaded into an application domain. // The intent is to bring the AppDomain down in the case that one of these is on a disallowed list // similar to the kill bit for Activex // // History: // 11/15/05: akaza Created. //--------------------------------------------------------------------------- using System; using System.Windows; using MS.Internal.PresentationFramework; using System.Collections.Generic; using MS.Win32; using Microsoft.Win32; using System.Security; using System.Security.Permissions; using System.Reflection; using System.Text; using MS.Internal.AppModel; using MS.Internal; using System.Windows.Resources; using System.Diagnostics; using System.Runtime.InteropServices; namespace MS.Internal { internal class AssemblyFilter { ////// Critical: This code sets the allowed assemblies on AssemblyList /// TreatAsSafe: Initializing the data is ok since it does not expose anything /// [SecurityCritical,SecurityTreatAsSafe] static AssemblyFilter() { _disallowedListExtracted = new SecurityCriticalDataForSet(false); _assemblyList = new SecurityCriticalDataForSet >(new System.Collections.Generic.List ()); } /// /// Critical: This code calls into unmanaged Api that has a SUC on this (IAssemblCache related) /// [SecurityCritical] internal void FilterCallback(Object sender, AssemblyLoadEventArgs args) { // This code is reentrant lock (_lock) { // Extract assembly Assembly a = args.LoadedAssembly; // xmlns cache loads assemblies as reflection only and we cannot inspect these using the code below // so we ignore also keeping this first is super important because the first time cost is really high // other wise also we cannot do any processing on a reflection only assembly aside from reflection based actions if (!a.ReflectionOnly) { // check if it is in the Gac , this ensures that we eliminate any non GAC assembly which are of no risk if (a.GlobalAssemblyCache) { object[] aptca = a.GetCustomAttributes(typeof(AllowPartiallyTrustedCallersAttribute), false); // if the dll has APTCA if (aptca.Length > 0 && aptca[0] is AllowPartiallyTrustedCallersAttribute) { string assemblyName = AssemblyNameWithFileVersion(a); // If we are on the disallowed list kill the application domain if (AssemblyOnDisallowedList(assemblyName)) { // Kill the application domain UnsafeNativeMethods.ProcessUnhandledException_DLL(SR.Get(SRID.KillBitEnforcedShutdown) + assemblyName); // I want to ensure that the process really dies new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();//BlessedAssert try { System.Environment.Exit(-1); } finally { SecurityPermission.RevertAssert(); Debug.Fail("Environment.Exit() failed."); } } } } } } } //appends assembly name with file version to generate a unique entry for the assembly lookup process ////// Critical: This code elevates to extract assembly name /// [SecurityCritical] private string AssemblyNameWithFileVersion(Assembly a) { FileVersionInfo fileVersionInfo; StringBuilder sb = new StringBuilder(a.FullName); // we need unrestricted here because the location is demands too. (new FileIOPermission(PermissionState.Unrestricted)).Assert();//BlessedAssert try { fileVersionInfo = FileVersionInfo.GetVersionInfo(a.Location); } finally { FileIOPermission.RevertAssert(); } if (fileVersionInfo != null && fileVersionInfo.ProductVersion != null) { sb.Append(FILEVERSION_STRING + fileVersionInfo.ProductVersion); } return ((sb.ToString()).ToLower(System.Globalization.CultureInfo.InvariantCulture)).Trim(); } ////// Critical: This code populates _assemblyList with Disallowed Elements and sets the bit that dictates whether to repopulate it /// [SecurityCritical] private bool AssemblyOnDisallowedList(String assemblyToCheck) { bool retVal = false; // if the list disallowed list is not populated populate it once if (_disallowedListExtracted.Value == false) { // hit the registry one time and read ExtractDisallowedRegistryList(); _disallowedListExtracted.Value = true; } if (_assemblyList.Value.Contains(assemblyToCheck)) { retVal = true; } return retVal; } ////// Critical: This code opens an HKLM registry location and reads it. We do not want /// to call this over and over as it could cause performance issues /// [SecurityCritical] private void ExtractDisallowedRegistryList() { string[] disallowedAssemblies; RegistryKey featureKey; //Assert for read access to HKLM\Software\Microsoft\.NetFramework\Policy\APTCA (new RegistryPermission(RegistryPermissionAccess.Read, KILL_BIT_REGISTRY_HIVE + KILL_BIT_REGISTRY_LOCATION)).Assert();//BlessedAssert try { // open the key and read the value featureKey = Registry.LocalMachine.OpenSubKey(KILL_BIT_REGISTRY_LOCATION); if (featureKey != null) { // Enumerate through all keys and populate dictionary disallowedAssemblies = featureKey.GetSubKeyNames(); // iterate over this list and for each extract the APTCA_FLAG value and set it in the // dictionary foreach (string assemblyName in disallowedAssemblies) { featureKey = Registry.LocalMachine.OpenSubKey(KILL_BIT_REGISTRY_LOCATION + @"\" + assemblyName); object keyValue = featureKey.GetValue(SUBKEY_VALUE); // if there exists a value and it is 1 add to hash table if ((keyValue != null) && (int)(keyValue) == 1) { if (!_assemblyList.Value.Contains(assemblyName)) { _assemblyList.Value.Add(assemblyName.ToLower(System.Globalization.CultureInfo.InvariantCulture).Trim()); } } } } } finally { RegistryPermission.RevertAssert(); } } ////// Critical: This holds a list of assemblies that are on an allowed and disallowed list and can be exploited to load /// unsafe dll's into appdomain /// static SecurityCriticalDataForSet> _assemblyList; /// /// Critical: This bit determines whether we need to hit the registry and load the disallowed elements. /// We would like to see this happen only once per appdomain and delay it as much as possible /// static SecurityCriticalDataForSet_disallowedListExtracted; static object _lock = new object(); private const string FILEVERSION_STRING = @", FileVersion="; // This is the location in the registry where all the keys are stored private const string KILL_BIT_REGISTRY_HIVE = @"HKEY_LOCAL_MACHINE\"; private const string KILL_BIT_REGISTRY_LOCATION = @"Software\Microsoft\.NetFramework\policy\APTCA"; private const string SUBKEY_VALUE = @"APTCA_FLAG"; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ClientUrlResolverWrapper.cs
- RegionInfo.cs
- AttachedPropertyBrowsableForChildrenAttribute.cs
- XmlSchemaGroup.cs
- AcceptorSessionSymmetricTransportSecurityProtocol.cs
- InplaceBitmapMetadataWriter.cs
- ToolboxComponentsCreatedEventArgs.cs
- InvalidProgramException.cs
- GradientBrush.cs
- BlobPersonalizationState.cs
- ObjectDataProvider.cs
- WindowsEditBox.cs
- DataGridViewCellValueEventArgs.cs
- Converter.cs
- DesignerActionGlyph.cs
- TextStore.cs
- EditBehavior.cs
- PenThreadPool.cs
- TextTabProperties.cs
- ReceiveSecurityHeaderEntry.cs
- CustomLineCap.cs
- DynamicResourceExtensionConverter.cs
- GAC.cs
- BaseDataListActionList.cs
- AsymmetricAlgorithm.cs
- HighContrastHelper.cs
- DbFunctionCommandTree.cs
- RoleBoolean.cs
- AspNetHostingPermission.cs
- MachineKeyValidationConverter.cs
- SecureEnvironment.cs
- StringFunctions.cs
- DesignTimeValidationFeature.cs
- StatusStrip.cs
- PackageRelationshipCollection.cs
- PtsHelper.cs
- AttributeQuery.cs
- MailMessageEventArgs.cs
- SqlMethodCallConverter.cs
- TrackingServices.cs
- RayMeshGeometry3DHitTestResult.cs
- DecoderBestFitFallback.cs
- Brush.cs
- Debug.cs
- PersistChildrenAttribute.cs
- WindowsListViewItemStartMenu.cs
- UserControlFileEditor.cs
- ObjectStateEntryOriginalDbUpdatableDataRecord.cs
- DataGridViewLinkCell.cs
- ValueType.cs
- System.Data_BID.cs
- Vector3DConverter.cs
- SystemPens.cs
- WebControlsSection.cs
- QualifiedCellIdBoolean.cs
- Timer.cs
- PublisherIdentityPermission.cs
- DBPropSet.cs
- EndpointConfigContainer.cs
- ColorConvertedBitmap.cs
- TransactionScope.cs
- VirtualizingStackPanel.cs
- RecognizerStateChangedEventArgs.cs
- SymbolResolver.cs
- RtfControlWordInfo.cs
- DbQueryCommandTree.cs
- StrokeNodeData.cs
- BindingNavigator.cs
- SspiSafeHandles.cs
- CryptoConfig.cs
- ToolBarTray.cs
- ChangesetResponse.cs
- ChildTable.cs
- AxParameterData.cs
- MenuItem.cs
- HostingPreferredMapPath.cs
- PeerObject.cs
- GB18030Encoding.cs
- _UncName.cs
- TemplateKey.cs
- EntityClassGenerator.cs
- DataGridViewComboBoxCell.cs
- CacheDict.cs
- NetDataContractSerializer.cs
- RSAOAEPKeyExchangeFormatter.cs
- EdgeProfileValidation.cs
- ItemsControl.cs
- DomNameTable.cs
- PrivilegedConfigurationManager.cs
- XamlSerializer.cs
- AnnotationMap.cs
- WmiPutTraceRecord.cs
- connectionpool.cs
- ConnectionPoint.cs
- Path.cs
- PackageStore.cs
- PathData.cs
- ImportOptions.cs
- ConfigurationLockCollection.cs
- Pkcs7Signer.cs