| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- //------------------------------------------------------------------------------
- // <copyright file="SecurityUtils.cs" company="Microsoft">
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- //------------------------------------------------------------------------------
- /*
- */
- #if WINFORMS_NAMESPACE
- namespace System.Windows.Forms
- #elif DRAWING_NAMESPACE
- namespace System.Drawing
- #elif WINFORMS_PUBLIC_GRAPHICS_LIBRARY
- namespace System.Internal
- #elif SYSTEM_NAMESPACE
- namespace System
- #elif SYSTEM_WEB
- namespace System.Web
- #elif SYSTEM_DATA_LINQ
- namespace System.Data.Linq
- #else
- namespace System.Windows.Forms
- #endif
- {
- using System;
- using System.Reflection;
- using System.Diagnostics.CodeAnalysis;
- using System.Security;
- using System.Security.Permissions;
- /// <devdoc>
- /// Useful methods to securely call 'dangerous' managed APIs (especially reflection).
- /// See http://wiki/default.aspx/Microsoft.Projects.DotNetClient.SecurityConcernsAroundReflection
- /// for more information specifically about why we need to be careful about reflection invocations.
- /// </devdoc>
- internal static class SecurityUtils {
- #if FEATURE_MONO_CAS
- private static volatile ReflectionPermission memberAccessPermission = null;
- private static volatile ReflectionPermission restrictedMemberAccessPermission = null;
- private static ReflectionPermission MemberAccessPermission
- {
- get {
- if (memberAccessPermission == null) {
- memberAccessPermission = new ReflectionPermission(ReflectionPermissionFlag.MemberAccess);
- }
- return memberAccessPermission;
- }
- }
- private static ReflectionPermission RestrictedMemberAccessPermission {
- get {
- if (restrictedMemberAccessPermission == null) {
- restrictedMemberAccessPermission = new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess);
- }
- return restrictedMemberAccessPermission;
- }
- }
- #endif
- private static void DemandReflectionAccess(Type type) {
- #if FEATURE_MONO_CAS
- try {
- MemberAccessPermission.Demand();
- }
- catch (SecurityException) {
- DemandGrantSet(type.Assembly);
- }
- #endif
- }
- [SecuritySafeCritical]
- private static void DemandGrantSet(Assembly assembly) {
- #if FEATURE_MONO_CAS
- PermissionSet targetGrantSet = assembly.PermissionSet;
- targetGrantSet.AddPermission(RestrictedMemberAccessPermission);
- targetGrantSet.Demand();
- #endif
- }
- private static bool HasReflectionPermission(Type type) {
- #if FEATURE_MONO_CAS
- try {
- DemandReflectionAccess(type);
- return true;
- }
- catch (SecurityException) {
- }
- return false;
- #else
- return true;
- #endif
- }
-
- /// <devdoc>
- /// This helper method provides safe access to Activator.CreateInstance.
- /// NOTE: This overload will work only with public .ctors.
- /// </devdoc>
- internal static object SecureCreateInstance(Type type) {
- return SecureCreateInstance(type, null, false);
- }
- /// <devdoc>
- /// This helper method provides safe access to Activator.CreateInstance.
- /// Set allowNonPublic to true if you want non public ctors to be used.
- /// </devdoc>
- internal static object SecureCreateInstance(Type type, object[] args, bool allowNonPublic) {
- if (type == null) {
- throw new ArgumentNullException("type");
- }
- BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.CreateInstance;
-
- // if it's an internal type, we demand reflection permission.
- if (!type.IsVisible) {
- DemandReflectionAccess(type);
- }
- else if (allowNonPublic && !HasReflectionPermission(type)) {
- // Someone is trying to instantiate a public type in *our* assembly, but does not
- // have full reflection permission. We shouldn't pass BindingFlags.NonPublic in this case.
- // The reason we don't directly demand the permission here is because we don't know whether
- // a public or non-public .ctor will be invoked. We want to allow the public .ctor case to
- // succeed.
- allowNonPublic = false;
- }
-
- if (allowNonPublic) {
- flags |= BindingFlags.NonPublic;
- }
- return Activator.CreateInstance(type, flags, null, args, null);
- }
- #if (!WINFORMS_NAMESPACE)
- /// <devdoc>
- /// This helper method provides safe access to Activator.CreateInstance.
- /// NOTE: This overload will work only with public .ctors.
- /// </devdoc>
- internal static object SecureCreateInstance(Type type, object[] args) {
- return SecureCreateInstance(type, args, false);
- }
- /// <devdoc>
- /// Helper method to safely invoke a .ctor. You should prefer SecureCreateInstance to this.
- /// Set allowNonPublic to true if you want non public ctors to be used.
- /// </devdoc>
- internal static object SecureConstructorInvoke(Type type, Type[] argTypes, object[] args, bool allowNonPublic) {
- return SecureConstructorInvoke(type, argTypes, args, allowNonPublic, BindingFlags.Default);
- }
- /// <devdoc>
- /// Helper method to safely invoke a .ctor. You should prefer SecureCreateInstance to this.
- /// Set allowNonPublic to true if you want non public ctors to be used.
- /// The 'extraFlags' parameter is used to pass in any other flags you need,
- /// besides Public, NonPublic and Instance.
- /// </devdoc>
- internal static object SecureConstructorInvoke(Type type, Type[] argTypes, object[] args,
- bool allowNonPublic, BindingFlags extraFlags) {
- if (type == null) {
- throw new ArgumentNullException("type");
- }
-
- // if it's an internal type, we demand reflection permission.
- if (!type.IsVisible) {
- DemandReflectionAccess(type);
- }
- else if (allowNonPublic && !HasReflectionPermission(type)) {
- // Someone is trying to invoke a ctor on a public type, but does not
- // have full reflection permission. We shouldn't pass BindingFlags.NonPublic in this case.
- allowNonPublic = false;
- }
- BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | extraFlags;
- if (!allowNonPublic) {
- flags &= ~BindingFlags.NonPublic;
- }
- ConstructorInfo ctor = type.GetConstructor(flags, null, argTypes, null);
- if (ctor != null) {
- return ctor.Invoke(args);
- }
- return null;
- }
- private static bool GenericArgumentsAreVisible(MethodInfo method) {
- if (method.IsGenericMethod) {
- Type[] parameterTypes = method.GetGenericArguments();
- foreach (Type type in parameterTypes) {
- if (!type.IsVisible) {
- return false;
- }
- }
- }
- return true;
- }
-
- /// <devdoc>
- /// This helper method provides safe access to FieldInfo's GetValue method.
- /// </devdoc>
- internal static object FieldInfoGetValue(FieldInfo field, object target) {
- Type type = field.DeclaringType;
- if (type == null) {
- // Type is null for Global fields.
- if (!field.IsPublic) {
- DemandGrantSet(field.Module.Assembly);
- }
- } else if (!(type != null && type.IsVisible && field.IsPublic)) {
- DemandReflectionAccess(type);
- }
- return field.GetValue(target);
- }
- /// <devdoc>
- /// This helper method provides safe access to MethodInfo's Invoke method.
- /// </devdoc>
- internal static object MethodInfoInvoke(MethodInfo method, object target, object[] args) {
- Type type = method.DeclaringType;
- if (type == null) {
- // Type is null for Global methods. In this case we would need to demand grant set on
- // the containing assembly for internal methods.
- if (!(method.IsPublic && GenericArgumentsAreVisible(method))) {
- DemandGrantSet(method.Module.Assembly);
- }
- } else if (!(type.IsVisible && method.IsPublic && GenericArgumentsAreVisible(method))) {
- // this demand is required for internal types in system.dll and its friend assemblies.
- DemandReflectionAccess(type);
- }
- return method.Invoke(target, args);
- }
- /// <devdoc>
- /// This helper method provides safe access to ConstructorInfo's Invoke method.
- /// Constructors can't be generic, so we don't check if argument types are visible
- /// </devdoc>
- internal static object ConstructorInfoInvoke(ConstructorInfo ctor, object[] args) {
- Type type = ctor.DeclaringType;
- if ((type != null) && !(type.IsVisible && ctor.IsPublic)) {
- DemandReflectionAccess(type);
- }
- return ctor.Invoke(args);
- }
- /// <devdoc>
- /// This helper method provides safe access to Array.CreateInstance.
- /// </devdoc>
- internal static object ArrayCreateInstance(Type type, int length) {
- if (!type.IsVisible) {
- DemandReflectionAccess(type);
- }
- return Array.CreateInstance(type, length);
- }
- #endif
- }
- }
|