Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System.Data.Linq / misc / SecurityUtils.cs
blob7a86773c1a811b3c157ba45eee4947ea4ed92b6f
1 //------------------------------------------------------------------------------
2 // <copyright file="SecurityUtils.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
7 /*
8 */
11 #if Microsoft_NAMESPACE
12 namespace System.Windows.Forms
13 #elif DRAWING_NAMESPACE
14 namespace System.Drawing
15 #elif Microsoft_PUBLIC_GRAPHICS_LIBRARY
16 namespace System.Internal
17 #elif SYSTEM_NAMESPACE
18 namespace System
19 #elif SYSTEM_WEB
20 namespace System.Web
21 #elif SYSTEM_DATA_LINQ
22 namespace System.Data.Linq
23 #else
24 namespace System.Windows.Forms
25 #endif
27 using System;
28 using System.Reflection;
29 using System.Diagnostics.CodeAnalysis;
30 using System.Security;
31 using System.Security.Permissions;
33 /// <devdoc>
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.
37 /// </devdoc>
38 internal static class SecurityUtils {
40 #if MONO_FEATURE_CAS
41 private static volatile ReflectionPermission memberAccessPermission = null;
42 private static volatile ReflectionPermission restrictedMemberAccessPermission = null;
44 private static ReflectionPermission MemberAccessPermission
46 get {
47 if (memberAccessPermission == null) {
48 memberAccessPermission = new ReflectionPermission(ReflectionPermissionFlag.MemberAccess);
50 return memberAccessPermission;
54 private static ReflectionPermission RestrictedMemberAccessPermission {
55 get {
56 if (restrictedMemberAccessPermission == null) {
57 restrictedMemberAccessPermission = new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess);
59 return restrictedMemberAccessPermission;
62 #endif
64 private static void DemandReflectionAccess(Type type) {
65 #if MONO_FEATURE_CAS
66 try {
67 MemberAccessPermission.Demand();
69 catch (SecurityException) {
70 DemandGrantSet(type.Assembly);
72 #endif
75 [SecuritySafeCritical]
76 private static void DemandGrantSet(Assembly assembly) {
77 #if MONO_FEATURE_CAS
78 PermissionSet targetGrantSet = assembly.PermissionSet;
79 targetGrantSet.AddPermission(RestrictedMemberAccessPermission);
80 targetGrantSet.Demand();
81 #endif
84 private static bool HasReflectionPermission(Type type) {
85 #if MONO_FEATURE_CAS
86 try {
87 DemandReflectionAccess(type);
88 return true;
90 catch (SecurityException) {
93 return false;
94 #else
95 return true;
96 #endif
100 /// <devdoc>
101 /// This helper method provides safe access to Activator.CreateInstance.
102 /// NOTE: This overload will work only with public .ctors.
103 /// </devdoc>
104 internal static object SecureCreateInstance(Type type) {
105 return SecureCreateInstance(type, null, false);
109 /// <devdoc>
110 /// This helper method provides safe access to Activator.CreateInstance.
111 /// Set allowNonPublic to true if you want non public ctors to be used.
112 /// </devdoc>
113 internal static object SecureCreateInstance(Type type, object[] args, bool allowNonPublic) {
114 if (type == null) {
115 throw new ArgumentNullException("type");
118 BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance;
120 // if it's an internal type, we demand reflection permission.
121 if (!type.IsVisible) {
122 DemandReflectionAccess(type);
124 else if (allowNonPublic && !HasReflectionPermission(type)) {
125 // Someone is trying to instantiate a public type in *our* assembly, but does not
126 // have full reflection permission. We shouldn't pass BindingFlags.NonPublic in this case.
127 // The reason we don't directly demand the permission here is because we don't know whether
128 // a public or non-public .ctor will be invoked. We want to allow the public .ctor case to
129 // succeed.
130 allowNonPublic = false;
133 if (allowNonPublic) {
134 flags |= BindingFlags.NonPublic;
137 return Activator.CreateInstance(type, flags, null, args, null);
140 #if (!Microsoft_NAMESPACE)
142 /// <devdoc>
143 /// This helper method provides safe access to Activator.CreateInstance.
144 /// NOTE: This overload will work only with public .ctors.
145 /// </devdoc>
146 internal static object SecureCreateInstance(Type type, object[] args) {
147 return SecureCreateInstance(type, args, false);
151 /// <devdoc>
152 /// Helper method to safely invoke a .ctor. You should prefer SecureCreateInstance to this.
153 /// Set allowNonPublic to true if you want non public ctors to be used.
154 /// </devdoc>
155 internal static object SecureConstructorInvoke(Type type, Type[] argTypes, object[] args, bool allowNonPublic) {
156 return SecureConstructorInvoke(type, argTypes, args, allowNonPublic, BindingFlags.Default);
159 /// <devdoc>
160 /// Helper method to safely invoke a .ctor. You should prefer SecureCreateInstance to this.
161 /// Set allowNonPublic to true if you want non public ctors to be used.
162 /// The 'extraFlags' parameter is used to pass in any other flags you need,
163 /// besides Public, NonPublic and Instance.
164 /// </devdoc>
165 internal static object SecureConstructorInvoke(Type type, Type[] argTypes, object[] args,
166 bool allowNonPublic, BindingFlags extraFlags) {
167 if (type == null) {
168 throw new ArgumentNullException("type");
171 // if it's an internal type, we demand reflection permission.
172 if (!type.IsVisible) {
173 DemandReflectionAccess(type);
175 else if (allowNonPublic && !HasReflectionPermission(type)) {
176 // Someone is trying to invoke a ctor on a public type, but does not
177 // have full reflection permission. We shouldn't pass BindingFlags.NonPublic in this case.
178 allowNonPublic = false;
181 BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | extraFlags;
182 if (!allowNonPublic) {
183 flags &= ~BindingFlags.NonPublic;
186 ConstructorInfo ctor = type.GetConstructor(flags, null, argTypes, null);
187 if (ctor != null) {
188 return ctor.Invoke(args);
191 return null;
194 private static bool GenericArgumentsAreVisible(MethodInfo method) {
195 if (method.IsGenericMethod) {
196 Type[] parameterTypes = method.GetGenericArguments();
197 foreach (Type type in parameterTypes) {
198 if (!type.IsVisible) {
199 return false;
203 return true;
206 /// <devdoc>
207 /// This helper method provides safe access to FieldInfo's GetValue method.
208 /// </devdoc>
209 internal static object FieldInfoGetValue(FieldInfo field, object target) {
210 Type type = field.DeclaringType;
211 if (type == null) {
212 // Type is null for Global fields.
213 if (!field.IsPublic) {
214 DemandGrantSet(field.Module.Assembly);
216 } else if (!(type != null && type.IsVisible && field.IsPublic)) {
217 DemandReflectionAccess(type);
219 return field.GetValue(target);
222 /// <devdoc>
223 /// This helper method provides safe access to MethodInfo's Invoke method.
224 /// </devdoc>
225 internal static object MethodInfoInvoke(MethodInfo method, object target, object[] args) {
226 Type type = method.DeclaringType;
227 if (type == null) {
228 // Type is null for Global methods. In this case we would need to demand grant set on
229 // the containing assembly for internal methods.
230 if (!(method.IsPublic && GenericArgumentsAreVisible(method))) {
231 DemandGrantSet(method.Module.Assembly);
233 } else if (!(type.IsVisible && method.IsPublic && GenericArgumentsAreVisible(method))) {
234 // this demand is required for internal types in system.dll and its friend assemblies.
235 DemandReflectionAccess(type);
237 return method.Invoke(target, args);
240 /// <devdoc>
241 /// This helper method provides safe access to ConstructorInfo's Invoke method.
242 /// Constructors can't be generic, so we don't check if argument types are visible
243 /// </devdoc>
244 internal static object ConstructorInfoInvoke(ConstructorInfo ctor, object[] args) {
245 Type type = ctor.DeclaringType;
246 if ((type != null) && !(type.IsVisible && ctor.IsPublic)) {
247 DemandReflectionAccess(type);
249 return ctor.Invoke(args);
252 /// <devdoc>
253 /// This helper method provides safe access to Array.CreateInstance.
254 /// </devdoc>
255 internal static object ArrayCreateInstance(Type type, int length) {
256 if (!type.IsVisible) {
257 DemandReflectionAccess(type);
259 return Array.CreateInstance(type, length);
261 #endif