1 //------------------------------------------------------------------------------
2 // <copyright file="SecurityUtils.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
11 #if WINFORMS_NAMESPACE
12 namespace System.Windows.Forms
13 #elif DRAWING_NAMESPACE
14 namespace System.Drawing
15 #elif WINFORMS_PUBLIC_GRAPHICS_LIBRARY
16 namespace System.Internal
17 #elif SYSTEM_NAMESPACE
21 #elif SYSTEM_DATA_LINQ
22 namespace System.Data.Linq
24 namespace System.Windows.Forms
28 using System.Reflection;
29 using System.Diagnostics.CodeAnalysis;
30 using System.Security;
31 using System.Security.Permissions;
34 /// Useful methods to securely call 'dangerous' managed APIs (especially reflection).
35 /// See http://wiki/default.aspx/Microsoft.Projects.DotNetClient.SecurityConcernsAroundReflection
36 /// for more information specifically about why we need to be careful about reflection invocations.
38 internal static class SecurityUtils {
40 private static volatile ReflectionPermission memberAccessPermission = null;
41 private static volatile ReflectionPermission restrictedMemberAccessPermission = null;
43 private static ReflectionPermission MemberAccessPermission
46 if (memberAccessPermission == null) {
47 memberAccessPermission = new ReflectionPermission(ReflectionPermissionFlag.MemberAccess);
49 return memberAccessPermission;
53 private static ReflectionPermission RestrictedMemberAccessPermission {
55 if (restrictedMemberAccessPermission == null) {
56 restrictedMemberAccessPermission = new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess);
58 return restrictedMemberAccessPermission;
62 private static void DemandReflectionAccess(Type type) {
65 MemberAccessPermission.Demand();
67 catch (SecurityException) {
68 DemandGrantSet(type.Assembly);
73 [SecuritySafeCritical]
74 private static void DemandGrantSet(Assembly assembly) {
76 PermissionSet targetGrantSet = assembly.PermissionSet;
77 targetGrantSet.AddPermission(RestrictedMemberAccessPermission);
78 targetGrantSet.Demand();
82 private static bool HasReflectionPermission(Type type) {
84 DemandReflectionAccess(type);
87 catch (SecurityException) {
95 /// This helper method provides safe access to Activator.CreateInstance.
96 /// NOTE: This overload will work only with public .ctors.
98 internal static object SecureCreateInstance(Type type) {
99 return SecureCreateInstance(type, null, false);
104 /// This helper method provides safe access to Activator.CreateInstance.
105 /// Set allowNonPublic to true if you want non public ctors to be used.
107 internal static object SecureCreateInstance(Type type, object[] args, bool allowNonPublic) {
109 throw new ArgumentNullException("type");
112 BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance;
114 // if it's an internal type, we demand reflection permission.
115 if (!type.IsVisible) {
116 DemandReflectionAccess(type);
118 else if (allowNonPublic && !HasReflectionPermission(type)) {
119 // Someone is trying to instantiate a public type in *our* assembly, but does not
120 // have full reflection permission. We shouldn't pass BindingFlags.NonPublic in this case.
121 // The reason we don't directly demand the permission here is because we don't know whether
122 // a public or non-public .ctor will be invoked. We want to allow the public .ctor case to
124 allowNonPublic = false;
127 if (allowNonPublic) {
128 flags |= BindingFlags.NonPublic;
131 return Activator.CreateInstance(type, flags, null, args, null);
134 #if (!WINFORMS_NAMESPACE)
137 /// This helper method provides safe access to Activator.CreateInstance.
138 /// NOTE: This overload will work only with public .ctors.
140 internal static object SecureCreateInstance(Type type, object[] args) {
141 return SecureCreateInstance(type, args, false);
146 /// Helper method to safely invoke a .ctor. You should prefer SecureCreateInstance to this.
147 /// Set allowNonPublic to true if you want non public ctors to be used.
149 internal static object SecureConstructorInvoke(Type type, Type[] argTypes, object[] args, bool allowNonPublic) {
150 return SecureConstructorInvoke(type, argTypes, args, allowNonPublic, BindingFlags.Default);
154 /// Helper method to safely invoke a .ctor. You should prefer SecureCreateInstance to this.
155 /// Set allowNonPublic to true if you want non public ctors to be used.
156 /// The 'extraFlags' parameter is used to pass in any other flags you need,
157 /// besides Public, NonPublic and Instance.
159 internal static object SecureConstructorInvoke(Type type, Type[] argTypes, object[] args,
160 bool allowNonPublic, BindingFlags extraFlags) {
162 throw new ArgumentNullException("type");
165 // if it's an internal type, we demand reflection permission.
166 if (!type.IsVisible) {
167 DemandReflectionAccess(type);
169 else if (allowNonPublic && !HasReflectionPermission(type)) {
170 // Someone is trying to invoke a ctor on a public type, but does not
171 // have full reflection permission. We shouldn't pass BindingFlags.NonPublic in this case.
172 allowNonPublic = false;
175 BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | extraFlags;
176 if (!allowNonPublic) {
177 flags &= ~BindingFlags.NonPublic;
180 ConstructorInfo ctor = type.GetConstructor(flags, null, argTypes, null);
182 return ctor.Invoke(args);
188 private static bool GenericArgumentsAreVisible(MethodInfo method) {
189 if (method.IsGenericMethod) {
190 Type[] parameterTypes = method.GetGenericArguments();
191 foreach (Type type in parameterTypes) {
192 if (!type.IsVisible) {
201 /// This helper method provides safe access to FieldInfo's GetValue method.
203 internal static object FieldInfoGetValue(FieldInfo field, object target) {
204 Type type = field.DeclaringType;
206 // Type is null for Global fields.
207 if (!field.IsPublic) {
208 DemandGrantSet(field.Module.Assembly);
210 } else if (!(type != null && type.IsVisible && field.IsPublic)) {
211 DemandReflectionAccess(type);
213 return field.GetValue(target);
217 /// This helper method provides safe access to MethodInfo's Invoke method.
219 internal static object MethodInfoInvoke(MethodInfo method, object target, object[] args) {
220 Type type = method.DeclaringType;
222 // Type is null for Global methods. In this case we would need to demand grant set on
223 // the containing assembly for internal methods.
224 if (!(method.IsPublic && GenericArgumentsAreVisible(method))) {
225 DemandGrantSet(method.Module.Assembly);
227 } else if (!(type.IsVisible && method.IsPublic && GenericArgumentsAreVisible(method))) {
228 // this demand is required for internal types in system.dll and its friend assemblies.
229 DemandReflectionAccess(type);
231 return method.Invoke(target, args);
235 /// This helper method provides safe access to ConstructorInfo's Invoke method.
236 /// Constructors can't be generic, so we don't check if argument types are visible
238 internal static object ConstructorInfoInvoke(ConstructorInfo ctor, object[] args) {
239 Type type = ctor.DeclaringType;
240 if ((type != null) && !(type.IsVisible && ctor.IsPublic)) {
241 DemandReflectionAccess(type);
243 return ctor.Invoke(args);
247 /// This helper method provides safe access to Array.CreateInstance.
249 internal static object ArrayCreateInstance(Type type, int length) {
250 if (!type.IsVisible) {
251 DemandReflectionAccess(type);
253 return Array.CreateInstance(type, length);