File: System\Activities\Expressions\OperatorPermissionHelper.cs
Project: ndp\cdf\src\NetFx40\System.Activities\System.Activities.csproj (System.Activities)
// <copyright>
//   Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
 
namespace System.Activities.Expressions
{
    using System.Linq.Expressions;
    using System.Reflection;
    using System.Runtime;
    using System.Security;
    using System.Security.Permissions;
 
    internal static class OperatorPermissionHelper
    {
        // The function we are returning from here may be cached in a static during CacheMetadata. This means the function would be used by multiple
        // workflow definitions using the same activity. In this case when CacheMetadata
        // is called in the second thru Nth usage, we will use the same cached function. If the operator overload method is not public and
        // any of the invocations of the workflow definitions are done without ReflectionPermission(MemberAccess), we would be opening up a security hole because
        // the user should not have the ability to invoke the non-public operator overload, but we would be allowing it because we cached the method during a
        // CacheMetadata episode when the permission was granted.
        // So, if the operator method is NOT public, we need to insert a Demand for ReflectionPermission.MemberAccess
        // into the function we are generating so that each usage will ensure that the permission is granted before calling
        // the operator method. If the operator method is public, we don't need the demand.
        // We don't need to check the public visibility of the declaring type because the user must have already constructed a generic activity
        // that is parameterized by the declaring type (i.e. new Add<Foo,Foo,Foo>).
        [Fx.Tag.SecurityNote(Miscellaneous =
            "RequiresReview - Functions invoking non-public overloaded operators get cached in a static and thus could get invoked under different permission sets."
             + " Ensure that the function contains a demand for ReflectionPermission(MemberAccess) if the method is non-public.")]
        internal static Expression InjectReflectionPermissionIfNecessary(MethodInfo method, Expression expression)
        {
            if (method == null)
            {
                return expression;
            }
 
            if (method.IsPublic)
            {
                return expression;
            }
            else
            {
                ReflectionPermission reflectionMemberAccessPermission = new ReflectionPermission(ReflectionPermissionFlag.MemberAccess);
                Expression demandExpression = Expression.Call(Expression.Constant(reflectionMemberAccessPermission), "Demand", null, null);
                return Expression.Block(expression.Type, demandExpression, expression);
            }
        }
    }
}