SecurityUtils.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. //------------------------------------------------------------------------------
  2. // <copyright file="SecurityUtils.cs" company="Microsoft">
  3. // Copyright (c) Microsoft Corporation. All rights reserved.
  4. // </copyright>
  5. //------------------------------------------------------------------------------
  6. /*
  7. */
  8. #if WINFORMS_NAMESPACE
  9. namespace System.Windows.Forms
  10. #elif DRAWING_NAMESPACE
  11. namespace System.Drawing
  12. #elif WINFORMS_PUBLIC_GRAPHICS_LIBRARY
  13. namespace System.Internal
  14. #elif SYSTEM_NAMESPACE
  15. namespace System
  16. #elif SYSTEM_WEB
  17. namespace System.Web
  18. #elif SYSTEM_DATA_LINQ
  19. namespace System.Data.Linq
  20. #else
  21. namespace System.Windows.Forms
  22. #endif
  23. {
  24. using System;
  25. using System.Reflection;
  26. using System.Diagnostics.CodeAnalysis;
  27. using System.Security;
  28. using System.Security.Permissions;
  29. /// <devdoc>
  30. /// Useful methods to securely call 'dangerous' managed APIs (especially reflection).
  31. /// See http://wiki/default.aspx/Microsoft.Projects.DotNetClient.SecurityConcernsAroundReflection
  32. /// for more information specifically about why we need to be careful about reflection invocations.
  33. /// </devdoc>
  34. internal static class SecurityUtils {
  35. #if FEATURE_MONO_CAS
  36. private static volatile ReflectionPermission memberAccessPermission = null;
  37. private static volatile ReflectionPermission restrictedMemberAccessPermission = null;
  38. private static ReflectionPermission MemberAccessPermission
  39. {
  40. get {
  41. if (memberAccessPermission == null) {
  42. memberAccessPermission = new ReflectionPermission(ReflectionPermissionFlag.MemberAccess);
  43. }
  44. return memberAccessPermission;
  45. }
  46. }
  47. private static ReflectionPermission RestrictedMemberAccessPermission {
  48. get {
  49. if (restrictedMemberAccessPermission == null) {
  50. restrictedMemberAccessPermission = new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess);
  51. }
  52. return restrictedMemberAccessPermission;
  53. }
  54. }
  55. #endif
  56. private static void DemandReflectionAccess(Type type) {
  57. #if FEATURE_MONO_CAS
  58. try {
  59. MemberAccessPermission.Demand();
  60. }
  61. catch (SecurityException) {
  62. DemandGrantSet(type.Assembly);
  63. }
  64. #endif
  65. }
  66. [SecuritySafeCritical]
  67. private static void DemandGrantSet(Assembly assembly) {
  68. #if FEATURE_MONO_CAS
  69. PermissionSet targetGrantSet = assembly.PermissionSet;
  70. targetGrantSet.AddPermission(RestrictedMemberAccessPermission);
  71. targetGrantSet.Demand();
  72. #endif
  73. }
  74. private static bool HasReflectionPermission(Type type) {
  75. #if FEATURE_MONO_CAS
  76. try {
  77. DemandReflectionAccess(type);
  78. return true;
  79. }
  80. catch (SecurityException) {
  81. }
  82. return false;
  83. #else
  84. return true;
  85. #endif
  86. }
  87. /// <devdoc>
  88. /// This helper method provides safe access to Activator.CreateInstance.
  89. /// NOTE: This overload will work only with public .ctors.
  90. /// </devdoc>
  91. internal static object SecureCreateInstance(Type type) {
  92. return SecureCreateInstance(type, null, false);
  93. }
  94. /// <devdoc>
  95. /// This helper method provides safe access to Activator.CreateInstance.
  96. /// Set allowNonPublic to true if you want non public ctors to be used.
  97. /// </devdoc>
  98. internal static object SecureCreateInstance(Type type, object[] args, bool allowNonPublic) {
  99. if (type == null) {
  100. throw new ArgumentNullException("type");
  101. }
  102. BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance;
  103. // if it's an internal type, we demand reflection permission.
  104. if (!type.IsVisible) {
  105. DemandReflectionAccess(type);
  106. }
  107. else if (allowNonPublic && !HasReflectionPermission(type)) {
  108. // Someone is trying to instantiate a public type in *our* assembly, but does not
  109. // have full reflection permission. We shouldn't pass BindingFlags.NonPublic in this case.
  110. // The reason we don't directly demand the permission here is because we don't know whether
  111. // a public or non-public .ctor will be invoked. We want to allow the public .ctor case to
  112. // succeed.
  113. allowNonPublic = false;
  114. }
  115. if (allowNonPublic) {
  116. flags |= BindingFlags.NonPublic;
  117. }
  118. return Activator.CreateInstance(type, flags, null, args, null);
  119. }
  120. #if (!WINFORMS_NAMESPACE)
  121. /// <devdoc>
  122. /// This helper method provides safe access to Activator.CreateInstance.
  123. /// NOTE: This overload will work only with public .ctors.
  124. /// </devdoc>
  125. internal static object SecureCreateInstance(Type type, object[] args) {
  126. return SecureCreateInstance(type, args, false);
  127. }
  128. /// <devdoc>
  129. /// Helper method to safely invoke a .ctor. You should prefer SecureCreateInstance to this.
  130. /// Set allowNonPublic to true if you want non public ctors to be used.
  131. /// </devdoc>
  132. internal static object SecureConstructorInvoke(Type type, Type[] argTypes, object[] args, bool allowNonPublic) {
  133. return SecureConstructorInvoke(type, argTypes, args, allowNonPublic, BindingFlags.Default);
  134. }
  135. /// <devdoc>
  136. /// Helper method to safely invoke a .ctor. You should prefer SecureCreateInstance to this.
  137. /// Set allowNonPublic to true if you want non public ctors to be used.
  138. /// The 'extraFlags' parameter is used to pass in any other flags you need,
  139. /// besides Public, NonPublic and Instance.
  140. /// </devdoc>
  141. internal static object SecureConstructorInvoke(Type type, Type[] argTypes, object[] args,
  142. bool allowNonPublic, BindingFlags extraFlags) {
  143. if (type == null) {
  144. throw new ArgumentNullException("type");
  145. }
  146. // if it's an internal type, we demand reflection permission.
  147. if (!type.IsVisible) {
  148. DemandReflectionAccess(type);
  149. }
  150. else if (allowNonPublic && !HasReflectionPermission(type)) {
  151. // Someone is trying to invoke a ctor on a public type, but does not
  152. // have full reflection permission. We shouldn't pass BindingFlags.NonPublic in this case.
  153. allowNonPublic = false;
  154. }
  155. BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | extraFlags;
  156. if (!allowNonPublic) {
  157. flags &= ~BindingFlags.NonPublic;
  158. }
  159. ConstructorInfo ctor = type.GetConstructor(flags, null, argTypes, null);
  160. if (ctor != null) {
  161. return ctor.Invoke(args);
  162. }
  163. return null;
  164. }
  165. private static bool GenericArgumentsAreVisible(MethodInfo method) {
  166. if (method.IsGenericMethod) {
  167. Type[] parameterTypes = method.GetGenericArguments();
  168. foreach (Type type in parameterTypes) {
  169. if (!type.IsVisible) {
  170. return false;
  171. }
  172. }
  173. }
  174. return true;
  175. }
  176. /// <devdoc>
  177. /// This helper method provides safe access to FieldInfo's GetValue method.
  178. /// </devdoc>
  179. internal static object FieldInfoGetValue(FieldInfo field, object target) {
  180. Type type = field.DeclaringType;
  181. if (type == null) {
  182. // Type is null for Global fields.
  183. if (!field.IsPublic) {
  184. DemandGrantSet(field.Module.Assembly);
  185. }
  186. } else if (!(type != null && type.IsVisible && field.IsPublic)) {
  187. DemandReflectionAccess(type);
  188. }
  189. return field.GetValue(target);
  190. }
  191. /// <devdoc>
  192. /// This helper method provides safe access to MethodInfo's Invoke method.
  193. /// </devdoc>
  194. internal static object MethodInfoInvoke(MethodInfo method, object target, object[] args) {
  195. Type type = method.DeclaringType;
  196. if (type == null) {
  197. // Type is null for Global methods. In this case we would need to demand grant set on
  198. // the containing assembly for internal methods.
  199. if (!(method.IsPublic && GenericArgumentsAreVisible(method))) {
  200. DemandGrantSet(method.Module.Assembly);
  201. }
  202. } else if (!(type.IsVisible && method.IsPublic && GenericArgumentsAreVisible(method))) {
  203. // this demand is required for internal types in system.dll and its friend assemblies.
  204. DemandReflectionAccess(type);
  205. }
  206. return method.Invoke(target, args);
  207. }
  208. /// <devdoc>
  209. /// This helper method provides safe access to ConstructorInfo's Invoke method.
  210. /// Constructors can't be generic, so we don't check if argument types are visible
  211. /// </devdoc>
  212. internal static object ConstructorInfoInvoke(ConstructorInfo ctor, object[] args) {
  213. Type type = ctor.DeclaringType;
  214. if ((type != null) && !(type.IsVisible && ctor.IsPublic)) {
  215. DemandReflectionAccess(type);
  216. }
  217. return ctor.Invoke(args);
  218. }
  219. /// <devdoc>
  220. /// This helper method provides safe access to Array.CreateInstance.
  221. /// </devdoc>
  222. internal static object ArrayCreateInstance(Type type, int length) {
  223. if (!type.IsVisible) {
  224. DemandReflectionAccess(type);
  225. }
  226. return Array.CreateInstance(type, length);
  227. }
  228. #endif
  229. }
  230. }