The Labs \ Source Viewer \ SSCLI \ System.Windows.Forms \ SecurityUtils

  1. //------------------------------------------------------------------------------
  2. // <copyright file="SecurityUtils.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. /*
  16. */
  17. #if SYSTEM_NAMESPACE
  18. namespace System
  19. {
  20.     #else
  21.     namespace System.Windows.Forms
  22.     {
  23.         #endif
  24.         using System;
  25.         using System.Reflection;
  26.         using System.Diagnostics.CodeAnalysis;
  27.         using System.Security;
  28.         using System.Security.Permissions;
  29.        
  30.         /// <devdoc>
  31.         /// Useful methods to securely call 'dangerous' managed APIs (especially reflection).
  32.         /// See http://wiki/default.aspx/Microsoft.Projects.DotNetClient.SecurityConcernsAroundReflection
  33.         /// for more information specifically about why we need to be careful about reflection invocations.
  34.         /// </devdoc>
  35.         static internal class SecurityUtils
  36.         {
  37.            
  38.             private static bool HasReflectionPermission {
  39.                 get {
  40.                     try {
  41.                         (new ReflectionPermission(PermissionState.Unrestricted)).Demand();
  42.                         return true;
  43.                     }
  44.                     catch (SecurityException) {
  45.                     }
  46.                    
  47.                     return false;
  48.                 }
  49.             }
  50.            
  51.             /// <devdoc>
  52.             /// This helper method provides safe access to Activator.CreateInstance.
  53.             /// NOTE: This overload will work only with public .ctors.
  54.             /// </devdoc>
  55.             static internal object SecureCreateInstance(Type type)
  56.             {
  57.                 return SecureCreateInstance(type, null);
  58.             }
  59.            
  60.            
  61.             /// <devdoc>
  62.             /// This helper method provides safe access to Activator.CreateInstance.
  63.             /// NOTE: This overload will work only with public .ctors.
  64.             /// </devdoc>
  65.             static internal object SecureCreateInstance(Type type, object[] args)
  66.             {
  67.                 if (type == null) {
  68.                     throw new ArgumentNullException("type");
  69.                 }
  70.                
  71.                 // The only case we need to worry about is when the type is in the same assembly
  72.                 // as us. In all other cases, reflection will take care of security.
  73.                 if (type.Assembly == typeof(SecurityUtils).Assembly && !(type.IsPublic || type.IsNestedPublic)) {
  74.                     (new ReflectionPermission(PermissionState.Unrestricted)).Demand();
  75.                 }
  76.                
  77.                 return Activator.CreateInstance(type, args);
  78.             }
  79.            
  80.             /// <devdoc>
  81.             /// This helper method provides safe access to Activator.CreateInstance.
  82.             /// Set allowNonPublic to true if you want non public ctors to be used.
  83.             /// </devdoc>
  84.             static internal object SecureCreateInstance(Type type, object[] args, bool allowNonPublic)
  85.             {
  86.                 if (type == null) {
  87.                     throw new ArgumentNullException("type");
  88.                 }
  89.                
  90.                 BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance;
  91.                
  92.                 // The only case we need to worry about is when the type is in the same assembly
  93.                 // as us. In all other cases, reflection will take care of security.
  94.                 if (type.Assembly == typeof(SecurityUtils).Assembly) {
  95.                     // if it's an internal type, we demand reflection permission.
  96.                     if (!(type.IsPublic || type.IsNestedPublic)) {
  97.                         (new ReflectionPermission(PermissionState.Unrestricted)).Demand();
  98.                     }
  99.                     else if (allowNonPublic && !HasReflectionPermission) {
  100.                         // Someone is trying to instantiate a public type in *our* assembly, but does not
  101.                         // have full reflection permission. We shouldn't pass BindingFlags.NonPublic in this case.
  102.                         // The reason we don't directly demand the permission here is because we don't know whether
  103.                         // a public nr non-public .ctor will be invoked. We want to allow the public .ctor case to
  104.                         // succeed.
  105.                         allowNonPublic = false;
  106.                     }
  107.                 }
  108.                
  109.                 if (allowNonPublic) {
  110.                     flags |= BindingFlags.NonPublic;
  111.                 }
  112.                
  113.                 return Activator.CreateInstance(type, flags, null, args, null);
  114.             }
  115.            
  116.             /// <devdoc>
  117.             /// Helper method to safely invoke a .ctor. You should prefer SecureCreateInstance to this.
  118.             /// Set allowNonPublic to true if you want non public ctors to be used.
  119.             /// </devdoc>
  120.             static internal object SecureConstructorInvoke(Type type, Type[] argTypes, object[] args, bool allowNonPublic)
  121.             {
  122.                 return SecureConstructorInvoke(type, argTypes, args, allowNonPublic, BindingFlags.Default);
  123.             }
  124.            
  125.             /// <devdoc>
  126.             /// Helper method to safely invoke a .ctor. You should prefer SecureCreateInstance to this.
  127.             /// Set allowNonPublic to true if you want non public ctors to be used.
  128.             /// The 'extraFlags' parameter is used to pass in any other flags you need,
  129.             /// besides Public, NonPublic and Instance.
  130.             /// </devdoc>
  131.             static internal object SecureConstructorInvoke(Type type, Type[] argTypes, object[] args, bool allowNonPublic, BindingFlags extraFlags)
  132.             {
  133.                 if (type == null) {
  134.                     throw new ArgumentNullException("type");
  135.                 }
  136.                
  137.                 BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | extraFlags;
  138.                
  139.                 // The only case we need to worry about is when the type is in the same assembly
  140.                 // as us. In all other cases, reflection will take care of security.
  141.                 if (type.Assembly == typeof(SecurityUtils).Assembly) {
  142.                     // if it's an internal type, we demand reflection permission.
  143.                     if (!(type.IsPublic || type.IsNestedPublic)) {
  144.                         (new ReflectionPermission(PermissionState.Unrestricted)).Demand();
  145.                     }
  146.                     else if (allowNonPublic && !HasReflectionPermission) {
  147.                         // Someone is trying to invoke a ctor on a public type in *our* assembly, but does not
  148.                         // have full reflection permission. We shouldn't pass BindingFlags.NonPublic in this case.
  149.                         allowNonPublic = false;
  150.                     }
  151.                 }
  152.                
  153.                 if (allowNonPublic) {
  154.                     flags |= BindingFlags.NonPublic;
  155.                 }
  156.                
  157.                 ConstructorInfo ctor = type.GetConstructor(flags, null, argTypes, null);
  158.                 if (ctor != null) {
  159.                     return ctor.Invoke(args);
  160.                 }
  161.                
  162.                 return null;
  163.             }
  164.         }
  165.     }
  166. }

Developer Fusion