summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Security/CodeAccessPermission.cs
blob: 70504d902edd798b10e806cfca556da7300a9fe0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

namespace System.Security
{
    using System.IO;
    using System.Threading;
    using System.Security;
    using System.Security.Util;
    using System.Security.Permissions;
    using System.Runtime.CompilerServices;
    using System.Collections;
    using System.Text;
    using System;
    using System.Diagnostics;
    using System.Diagnostics.Contracts;
    using IUnrestrictedPermission = System.Security.Permissions.IUnrestrictedPermission;

    [Serializable]
    [System.Runtime.InteropServices.ComVisible(true)]
    abstract public class CodeAccessPermission
        : IPermission, ISecurityEncodable, IStackWalk
    {
        // Static methods for manipulation of stack
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public static void RevertAssert()
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            SecurityRuntime.RevertAssert(ref stackMark);
        }

        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        [Obsolete("Deny is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
        public static void RevertDeny()
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            SecurityRuntime.RevertDeny(ref stackMark);
        }

        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public static void RevertPermitOnly()
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            SecurityRuntime.RevertPermitOnly(ref stackMark);
        }

        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public static void RevertAll()
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            SecurityRuntime.RevertAll(ref stackMark);
        }

        //
        // Standard implementation of IPermission methods for
        // code-access permissions.
        //

        // Mark this method as requiring a security object on the caller's frame
        // so the caller won't be inlined (which would mess up stack crawling).
        [DynamicSecurityMethodAttribute()]
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public void Demand()
        {
            if (!this.CheckDemand( null ))
            {
                StackCrawlMark stackMark = StackCrawlMark.LookForMyCallersCaller;
                CodeAccessSecurityEngine.Check(this, ref stackMark);
            }
        }

        [DynamicSecurityMethodAttribute()]
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        internal static void Demand(PermissionType permissionType)
        {
            //    The intent of the method is to be an internal mscorlib helper that Demands a specific permissiontype
            //    without having to create objects.
            //    The security annotation fxcop rule that flags all methods with a Demand() has logic
            //    which checks for methods named Demand in types that implement IPermission or IStackWalk. 
            Debug.Assert(new StackFrame().GetMethod().Name.Equals("Demand"), "This method needs to be named Demand");
            
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCallersCaller;
            CodeAccessSecurityEngine.SpecialDemand(permissionType, ref stackMark);
        }

        // Metadata for this method should be flaged with REQ_SQ so that
        // EE can allocate space on the stack frame for FrameSecurityDescriptor

        [DynamicSecurityMethodAttribute()]
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public void Assert()
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            CodeAccessSecurityEngine.Assert(this, ref stackMark);
        }


        [DynamicSecurityMethodAttribute()]
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable    
        static internal void Assert(bool allPossible)
        {
            //    The intent of the method is to be an internal mscorlib helper that easily asserts for all possible permissions
            //    without having to new a PermissionSet.
            //    The security annotation fxcop rule that flags all methods with an Assert() has logic
            //    which checks for methods named Assert in types that implement IPermission or IStackWalk. 
            Debug.Assert(new StackFrame().GetMethod().Name.Equals("Assert"), "This method needs to be named Assert");
            
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            SecurityRuntime.AssertAllPossible(ref stackMark);
        }
    
        // Metadata for this method should be flaged with REQ_SQ so that
        // EE can allocate space on the stack frame for FrameSecurityDescriptor

        [DynamicSecurityMethodAttribute()]
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        [Obsolete("Deny is obsolete and will be removed in a future release of the .NET Framework. See http://go.microsoft.com/fwlink/?LinkID=155570 for more information.")]
        public void Deny()
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            CodeAccessSecurityEngine.Deny(this, ref stackMark);
        }
        
        // Metadata for this method should be flaged with REQ_SQ so that
        // EE can allocate space on the stack frame for FrameSecurityDescriptor

        [DynamicSecurityMethodAttribute()]
        [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
        public void PermitOnly()
        {
            StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
            CodeAccessSecurityEngine.PermitOnly(this, ref stackMark);
        }

        // IPermission interfaces

        // We provide a default implementation of Union here.
        // Any permission that doesn't provide its own representation 
        // of Union will get this one and trigger CompoundPermission
        // We can take care of simple cases here...

        public virtual IPermission Union(IPermission other) {
            // The other guy could be null
            if (other == null) return(this.Copy());
            
            // otherwise we don't support it.
            throw new NotSupportedException(Environment.GetResourceString( "NotSupported_SecurityPermissionUnion" ));
        }

        //
        // HELPERS FOR IMPLEMENTING ABSTRACT METHODS
        //

        //
        // Protected helper
        //

        internal bool VerifyType(IPermission perm)
        {
            // if perm is null, then obviously not of the same type
            if ((perm == null) || (perm.GetType() != this.GetType())) {
                return(false);
            } else {
                return(true);
            }
        }

        // The IPermission Interface
        public abstract IPermission Copy();
        public abstract IPermission Intersect(IPermission target);
        public abstract bool IsSubsetOf(IPermission target);

        [System.Runtime.InteropServices.ComVisible(false)]
        public override bool Equals(Object obj)
        {
            IPermission perm = obj as IPermission;
            if(obj != null && perm == null)
                return false;
            try {
                if(!this.IsSubsetOf(perm))
                    return false;
                if(perm != null && !perm.IsSubsetOf(this))
                    return false;
            }
            catch (ArgumentException)
            {
                // Any argument exception implies inequality
                // Note that we require a try/catch block here because we have to deal with
                // custom permissions that may throw exceptions indiscriminately.
                return false;
            }
            return true;
        }

        [System.Runtime.InteropServices.ComVisible(false)]
        public override int GetHashCode()
        {
            // This implementation is only to silence a compiler warning.
            return base.GetHashCode();
        }


        internal bool CheckDemand(CodeAccessPermission grant)
        {
            Debug.Assert( grant == null || grant.GetType().Equals( this.GetType() ), "CheckDemand not defined for permissions of different type" );
            return IsSubsetOf( grant );
        }

        internal bool CheckPermitOnly(CodeAccessPermission permitted)
        {
            Debug.Assert( permitted == null || permitted.GetType().Equals( this.GetType() ), "CheckPermitOnly not defined for permissions of different type" );
            return IsSubsetOf( permitted );
        }

        internal bool CheckDeny(CodeAccessPermission denied)
        {
            Debug.Assert( denied == null || denied.GetType().Equals( this.GetType() ), "CheckDeny not defined for permissions of different type" );
            IPermission intersectPerm = Intersect(denied);
            return (intersectPerm == null || intersectPerm.IsSubsetOf(null));
        }

        internal bool CheckAssert(CodeAccessPermission asserted)
        {
            Debug.Assert( asserted == null || asserted.GetType().Equals( this.GetType() ), "CheckPermitOnly not defined for permissions of different type" );
            return IsSubsetOf( asserted );
        }
    }
}