Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / mscorlib / system / security / permissionlistset.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 /*=============================================================================
7 **
8 ** Class: PermissionListSet.cs
9 ** 
10 ** <OWNER>[....]</OWNER>
11 ** <OWNER>[....]</OWNER>
12 **
13 ** Purpose: Holds state about A/G/R permissionsets in a callstack or appdomain
14 **          (Replacement for PermissionListSet)
15 **
16 =============================================================================*/
17
18 namespace System.Security
19 {
20     using System.Globalization;
21     using System.Reflection;
22     using System.Runtime.InteropServices;
23     using System.Security;
24     using System.Security.Permissions;
25     using System.Threading;
26     using System.Collections;
27     using System.Collections.Generic;
28     using System.Diagnostics.Contracts;
29
30     [Serializable]
31     sealed internal class PermissionListSet
32     {
33         // Only internal (public) methods are creation methods and demand evaluation methods.
34         // Scroll down to the end to see them.
35         private PermissionSetTriple m_firstPermSetTriple;
36         private ArrayList m_permSetTriples;
37 #if FEATURE_COMPRESSEDSTACK
38         private ArrayList m_zoneList;
39         private ArrayList m_originList;
40 #endif // FEATURE_COMPRESSEDSTACK
41
42         internal PermissionListSet() {}
43
44         private void EnsureTriplesListCreated()
45         {
46             if (m_permSetTriples == null)
47             {
48                 m_permSetTriples = new ArrayList();
49                 if (m_firstPermSetTriple != null)
50                 {
51                     m_permSetTriples.Add(m_firstPermSetTriple);
52                     m_firstPermSetTriple = null;
53                 }
54             }
55         }
56
57 #if FEATURE_PLS
58         [System.Security.SecurityCritical]  // auto-generated
59         internal void UpdateDomainPLS (PermissionListSet adPLS) {
60             if (adPLS != null && adPLS.m_firstPermSetTriple != null)
61                 UpdateDomainPLS(adPLS.m_firstPermSetTriple.GrantSet, adPLS.m_firstPermSetTriple.RefusedSet);
62         }
63
64         [System.Security.SecurityCritical]  // auto-generated
65         internal void UpdateDomainPLS (PermissionSet grantSet, PermissionSet deniedSet) {
66             Contract.Assert(m_permSetTriples == null, "m_permSetTriples != null");
67             if (m_firstPermSetTriple == null)
68                 m_firstPermSetTriple = new PermissionSetTriple();
69
70             // update the grant and denied sets
71             m_firstPermSetTriple.UpdateGrant(grantSet);
72             m_firstPermSetTriple.UpdateRefused(deniedSet);
73         }
74 #endif // FEATURE_PLS
75
76         private void Terminate(PermissionSetTriple currentTriple)
77         {
78             UpdateTripleListAndCreateNewTriple(currentTriple, null);
79         }
80
81         [System.Security.SecurityCritical]  // auto-generated
82         private void Terminate(PermissionSetTriple currentTriple, PermissionListSet pls)
83         {
84 #if FEATURE_COMPRESSEDSTACK
85             this.UpdateZoneAndOrigin(pls);
86 #endif // FEATURE_COMPRESSEDSTACK
87             this.UpdatePermissions(currentTriple, pls);
88             this.UpdateTripleListAndCreateNewTriple(currentTriple, null);
89         }
90
91         [System.Security.SecurityCritical]  // auto-generated
92         private bool Update(PermissionSetTriple currentTriple, PermissionListSet pls)
93         {
94 #if FEATURE_COMPRESSEDSTACK
95             this.UpdateZoneAndOrigin(pls);
96 #endif // FEATURE_COMPRESSEDSTACK
97             return this.UpdatePermissions(currentTriple, pls);
98         }
99
100         [System.Security.SecurityCritical]  // auto-generated
101         private bool Update(PermissionSetTriple currentTriple, FrameSecurityDescriptor fsd)
102         {
103 #if FEATURE_COMPRESSEDSTACK
104            FrameSecurityDescriptorWithResolver fsdWithResolver = fsd as FrameSecurityDescriptorWithResolver;
105            if (fsdWithResolver != null)
106            {
107                return Update2(currentTriple, fsdWithResolver);
108            }
109 #endif // FEATURE_COMPRESSEDSTACK
110
111            // check imperative
112            bool fHalt = Update2(currentTriple, fsd, false);
113            if (!fHalt)            
114            {
115                 // then declarative
116                 fHalt = Update2(currentTriple, fsd, true);
117            }
118            return fHalt;
119         }
120
121 #if FEATURE_COMPRESSEDSTACK
122         [System.Security.SecurityCritical]
123         private bool Update2(PermissionSetTriple currentTriple, FrameSecurityDescriptorWithResolver fsdWithResolver)
124         {
125             System.Reflection.Emit.DynamicResolver resolver = fsdWithResolver.Resolver;
126             CompressedStack dynamicCompressedStack = resolver.GetSecurityContext();
127             dynamicCompressedStack.CompleteConstruction(null);
128             return this.Update(currentTriple, dynamicCompressedStack.PLS);
129         }
130 #endif // FEATURE_COMPRESSEDSTACK
131
132         [System.Security.SecurityCritical]  // auto-generated
133         private bool Update2(PermissionSetTriple currentTriple, FrameSecurityDescriptor fsd, bool fDeclarative)
134         {
135             // Deny
136             PermissionSet deniedPset = fsd.GetDenials(fDeclarative);
137             if (deniedPset != null)
138             {
139                 currentTriple.UpdateRefused(deniedPset);
140             }
141
142             // permit only
143             PermissionSet permitOnlyPset = fsd.GetPermitOnly(fDeclarative);
144             if (permitOnlyPset != null)
145             {
146                 currentTriple.UpdateGrant(permitOnlyPset);
147             }
148
149             // Assert all possible
150             if (fsd.GetAssertAllPossible())
151             {
152                 // If we have no grant set, it means that the only assembly we've seen on the stack so
153                 // far is mscorlib. Since mscorlib will always be fully trusted, the grant set of the
154                 // compressed stack is also FullTrust.
155                 if (currentTriple.GrantSet == null)
156                     currentTriple.GrantSet = PermissionSet.s_fullTrust;
157
158                 UpdateTripleListAndCreateNewTriple(currentTriple, m_permSetTriples);
159                 currentTriple.GrantSet = PermissionSet.s_fullTrust;
160                 currentTriple.UpdateAssert(fsd.GetAssertions(fDeclarative));
161                 return true;
162             }
163                 
164             // Assert
165             PermissionSet assertPset = fsd.GetAssertions(fDeclarative);
166             if (assertPset != null)
167             {
168                 if (assertPset.IsUnrestricted())
169                 {
170                     // If we have no grant set, it means that the only assembly we've seen on the stack so
171                     // far is mscorlib. Since mscorlib will always be fully trusted, the grant set of the
172                     // compressed stack is also FullTrust.
173                     if (currentTriple.GrantSet == null)
174                         currentTriple.GrantSet = PermissionSet.s_fullTrust;
175
176                     UpdateTripleListAndCreateNewTriple(currentTriple, m_permSetTriples);
177                     currentTriple.GrantSet = PermissionSet.s_fullTrust;
178                     currentTriple.UpdateAssert(assertPset);
179                     return true;
180                 }
181
182                 PermissionSetTriple retTriple = currentTriple.UpdateAssert(assertPset);
183                 if (retTriple != null)
184                 {
185                     EnsureTriplesListCreated();
186                     m_permSetTriples.Add(retTriple);
187                 }
188             }
189
190             return false;
191         }
192         [System.Security.SecurityCritical]  // auto-generated
193         private void Update(PermissionSetTriple currentTriple, PermissionSet in_g, PermissionSet in_r)
194         {
195 #if FEATURE_COMPRESSEDSTACK
196             ZoneIdentityPermission z;
197             UrlIdentityPermission u;
198             currentTriple.UpdateGrant(in_g, out z, out u);
199             currentTriple.UpdateRefused(in_r);
200             AppendZoneOrigin(z, u);
201 #else // !FEATURE_COMPRESEDSTACK
202             currentTriple.UpdateGrant(in_g);
203             currentTriple.UpdateRefused(in_r);
204 #endif // FEATURE_COMPRESSEDSTACK
205         }
206
207         // Called from the VM for HG CS construction        
208         [System.Security.SecurityCritical]  // auto-generated
209         private void Update(PermissionSet in_g)
210         {
211             if (m_firstPermSetTriple == null)
212                 m_firstPermSetTriple = new PermissionSetTriple();
213             Update(m_firstPermSetTriple, in_g, null);
214         }
215         
216 #if FEATURE_COMPRESSEDSTACK
217         private void UpdateZoneAndOrigin(PermissionListSet pls)
218         {
219             if (pls != null)
220             {
221                 if (this.m_zoneList == null && pls.m_zoneList != null && pls.m_zoneList.Count > 0)
222                     this.m_zoneList = new ArrayList();
223                 UpdateArrayList(this.m_zoneList, pls.m_zoneList);
224                 if (this.m_originList == null && pls.m_originList != null && pls.m_originList.Count > 0)
225                     this.m_originList = new ArrayList();                                
226                 UpdateArrayList(this.m_originList, pls.m_originList);
227             }
228         }
229 #endif // FEATURE_COMPRESSEDSTACK
230
231         [System.Security.SecurityCritical]  // auto-generated
232         private bool UpdatePermissions(PermissionSetTriple currentTriple, PermissionListSet pls)
233         {
234             if (pls != null)
235             {
236                 if (pls.m_permSetTriples != null)
237                 {
238                     // DCS has an AGR List. So we need to add the AGR List
239                     UpdateTripleListAndCreateNewTriple(currentTriple,pls.m_permSetTriples);
240                 }
241                 else
242                 {
243                     // Common case: One AGR set
244                     
245                     PermissionSetTriple tmp_psTriple = pls.m_firstPermSetTriple;
246                     PermissionSetTriple retTriple;
247                     // First try and update currentTriple. Return value indicates if we can stop construction
248                     if (currentTriple.Update(tmp_psTriple, out retTriple))
249                         return true;
250                     // If we got a non-null retTriple, what it means is that compression failed,
251                     // and we now have 2 triples to deal with: retTriple and currentTriple.
252                     // retTriple has to be appended first. then currentTriple.
253                     if (retTriple != null)
254                     {
255                         EnsureTriplesListCreated();
256                         // we just created a new triple...add the previous one (returned) to the list
257                         m_permSetTriples.Add(retTriple);
258                     }
259                 }
260             }
261             else
262             {
263                 // pls can be null only outside the loop in CreateCompressedState
264                 UpdateTripleListAndCreateNewTriple(currentTriple, null);
265             }
266             
267
268             return false;
269             
270         }
271
272
273         private void UpdateTripleListAndCreateNewTriple(PermissionSetTriple currentTriple, ArrayList tripleList)
274         {
275             if (!currentTriple.IsEmpty())
276             {
277                 if (m_firstPermSetTriple == null && m_permSetTriples == null)
278                 {
279                     m_firstPermSetTriple = new PermissionSetTriple(currentTriple);
280                 }
281                 else
282                 {
283                     EnsureTriplesListCreated();
284                     m_permSetTriples.Add(new PermissionSetTriple(currentTriple));
285                 }
286                 currentTriple.Reset();
287             }
288             if (tripleList != null)
289             {
290                 EnsureTriplesListCreated();
291                 m_permSetTriples.AddRange(tripleList);
292             }
293         }
294
295         private static void UpdateArrayList(ArrayList current, ArrayList newList)
296         {
297             if (newList == null)
298                 return;
299
300             for(int i=0;i < newList.Count; i++)
301             {
302                 if (!current.Contains(newList[i]))
303                     current.Add(newList[i]);
304             }
305
306         }
307
308 #if FEATURE_COMPRESSEDSTACK
309         private void AppendZoneOrigin(ZoneIdentityPermission z, UrlIdentityPermission u)
310         {
311
312             if (z != null)
313             {
314                 if (m_zoneList == null)
315                     m_zoneList = new ArrayList();
316                 z.AppendZones(m_zoneList);
317             }
318
319             if (u != null)
320             {
321                 if (m_originList == null)
322                     m_originList = new ArrayList();
323                 u.AppendOrigin(m_originList);
324             }
325         }
326
327 [System.Security.SecurityCritical]  // auto-generated
328 [System.Runtime.InteropServices.ComVisible(true)]
329         // public(internal) interface begins...
330         // Creation functions
331         static internal PermissionListSet CreateCompressedState(CompressedStack cs, CompressedStack innerCS)
332         {
333             // function that completes the construction of the compressed stack if not done so already (bottom half for demand evaluation)
334             
335             bool bHaltConstruction = false;
336             if (cs.CompressedStackHandle == null)
337                 return null; //  FT case or Security off
338    
339             PermissionListSet pls = new PermissionListSet();
340             PermissionSetTriple currentTriple = new PermissionSetTriple();
341             int numDomains = CompressedStack.GetDCSCount(cs.CompressedStackHandle);
342             for (int i=numDomains-1; (i >= 0 && !bHaltConstruction) ; i--)
343             {
344                 DomainCompressedStack dcs = CompressedStack.GetDomainCompressedStack(cs.CompressedStackHandle, i);
345                 if (dcs == null)
346                     continue; // we hit a FT Domain
347                 if (dcs.PLS == null)
348                 {
349                     // We failed on some DCS
350                     throw new SecurityException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Security_Generic")));
351                 }
352                 pls.UpdateZoneAndOrigin(dcs.PLS);
353                 pls.Update(currentTriple, dcs.PLS); 
354                 bHaltConstruction = dcs.ConstructionHalted;
355             }
356             if (!bHaltConstruction)
357             {
358                 PermissionListSet tmp_pls = null;
359                 // Construction did not halt. 
360                 if (innerCS != null)
361                 {
362                     innerCS.CompleteConstruction(null);
363                     tmp_pls = innerCS.PLS;
364                 }
365                 pls.Terminate(currentTriple, tmp_pls);
366             }
367             else
368             {
369                 pls.Terminate(currentTriple);
370             }
371
372             return pls;
373         }
374
375         [System.Security.SecurityCritical]  // auto-generated
376         static internal PermissionListSet CreateCompressedState(IntPtr unmanagedDCS, out bool bHaltConstruction)
377         {
378             PermissionListSet pls = new PermissionListSet();
379             PermissionSetTriple currentTriple = new PermissionSetTriple();
380
381             PermissionSet tmp_g, tmp_r;
382             // Construct the descriptor list
383             int descCount = DomainCompressedStack.GetDescCount(unmanagedDCS);
384             bHaltConstruction = false;
385             for(int i=0; (i < descCount && !bHaltConstruction); i++)
386             {
387                 FrameSecurityDescriptor fsd;
388                 Assembly assembly;
389                 if (DomainCompressedStack.GetDescriptorInfo(unmanagedDCS, i, out tmp_g, out tmp_r, out assembly, out fsd))
390                 {
391                     // Got an FSD
392                     bHaltConstruction = pls.Update(currentTriple, fsd);
393                 }
394                 else
395                 {
396                     pls.Update(currentTriple, tmp_g, tmp_r);
397                 }
398                 
399             }
400             if (!bHaltConstruction)
401             {
402                 // domain
403                 if (!DomainCompressedStack.IgnoreDomain(unmanagedDCS))
404                 {
405                     DomainCompressedStack.GetDomainPermissionSets(unmanagedDCS, out tmp_g, out tmp_r);
406                     pls.Update(currentTriple, tmp_g, tmp_r);
407                 }
408             }
409             pls.Terminate(currentTriple);
410
411
412             // return the created object
413             return pls;
414             
415         }
416         [System.Security.SecurityCritical]  // auto-generated
417         static internal PermissionListSet CreateCompressedState_HG()
418         {
419             PermissionListSet pls = new PermissionListSet();
420             CompressedStack.GetHomogeneousPLS(pls);
421             return pls;
422         }
423 #endif // #if FEATURE_COMPRESSEDSTACK
424         // Private Demand evaluation functions - only called from the VM
425         [System.Security.SecurityCritical]  // auto-generated
426         internal bool CheckDemandNoThrow(CodeAccessPermission demand)
427         {
428             // AppDomain permissions - no asserts. So there should only be one triple to work with
429             Contract.Assert(m_permSetTriples == null && m_firstPermSetTriple != null, "More than one PermissionSetTriple encountered in AD PermissionListSet");
430             
431
432             
433             PermissionToken permToken = null;
434             if (demand != null)
435                 permToken = PermissionToken.GetToken(demand);
436
437             return m_firstPermSetTriple.CheckDemandNoThrow(demand, permToken);
438                 
439
440         }
441         [System.Security.SecurityCritical]  // auto-generated
442         internal bool CheckSetDemandNoThrow(PermissionSet pSet)
443         {
444             // AppDomain permissions - no asserts. So there should only be one triple to work with
445             Contract.Assert(m_permSetTriples == null && m_firstPermSetTriple != null, "More than one PermissionSetTriple encountered in AD PermissionListSet");
446
447             
448             return m_firstPermSetTriple.CheckSetDemandNoThrow(pSet);
449         }
450
451         // Demand evauation functions
452         [System.Security.SecurityCritical]  // auto-generated
453         internal bool CheckDemand(CodeAccessPermission demand, PermissionToken permToken, RuntimeMethodHandleInternal rmh)
454         {
455             bool bRet = SecurityRuntime.StackContinue;
456             if (m_permSetTriples != null)
457             {
458                 for (int i=0; (i < m_permSetTriples.Count && bRet != SecurityRuntime.StackHalt) ; i++)
459                 {
460                     PermissionSetTriple psTriple = (PermissionSetTriple)m_permSetTriples[i];
461                     bRet = psTriple.CheckDemand(demand, permToken, rmh);
462                 }
463             }
464             else if (m_firstPermSetTriple != null)
465             {
466                 bRet = m_firstPermSetTriple.CheckDemand(demand, permToken, rmh);
467             }
468
469             return bRet;
470         }
471
472         [System.Security.SecurityCritical]  // auto-generated
473         internal bool CheckSetDemand(PermissionSet pset , RuntimeMethodHandleInternal rmh)
474         {
475             PermissionSet unused;
476             CheckSetDemandWithModification(pset, out unused, rmh);
477             return SecurityRuntime.StackHalt; //  CS demand check always terminates the stackwalk    
478         }
479
480         [System.Security.SecurityCritical]
481         internal bool CheckSetDemandWithModification(PermissionSet pset, out PermissionSet alteredDemandSet, RuntimeMethodHandleInternal rmh)
482         {
483             bool bRet = SecurityRuntime.StackContinue;
484             PermissionSet demandSet = pset;
485             alteredDemandSet = null;
486             if (m_permSetTriples != null)
487             {
488                 for (int i=0; (i < m_permSetTriples.Count && bRet != SecurityRuntime.StackHalt) ; i++)
489                 {
490                     PermissionSetTriple psTriple = (PermissionSetTriple)m_permSetTriples[i];
491                     bRet = psTriple.CheckSetDemand(demandSet, out alteredDemandSet, rmh);
492                     if (alteredDemandSet != null)
493                         demandSet = alteredDemandSet;
494                 }
495             }
496             else if (m_firstPermSetTriple != null)
497             {
498                 bRet = m_firstPermSetTriple.CheckSetDemand(demandSet, out alteredDemandSet, rmh);
499             }
500
501             return bRet;
502         }
503
504         /// <summary>
505         ///     Check to see if the PLS satisfies a demand for the special permissions encoded in flags
506         /// </summary>
507         /// <param name="flags">set of flags to check (See PermissionType)</param>
508         [System.Security.SecurityCritical]  // auto-generated
509         private bool CheckFlags(int flags)
510         {
511             Contract.Assert(flags != 0, "Invalid permission flag demand");
512
513             bool check = true;
514
515             if (m_permSetTriples != null)
516             {
517                 for (int i = 0; i < m_permSetTriples.Count && check && flags != 0; i++)
518                 {
519                     check &= ((PermissionSetTriple)m_permSetTriples[i]).CheckFlags(ref flags);
520                 }
521             }
522             else if (m_firstPermSetTriple != null)
523             {
524                 check = m_firstPermSetTriple.CheckFlags(ref flags);
525             }
526             
527             return check;
528         }
529
530         /// <summary>
531         ///     Demand which succeeds if either a set of special permissions or a permission set is granted
532         ///     to the call stack
533         /// </summary>
534         /// <param name="flags">set of flags to check (See PermissionType)</param>
535         /// <param name="grantSet">alternate permission set to check</param>
536         [System.Security.SecurityCritical]  // auto-generated
537         internal void DemandFlagsOrGrantSet(int flags, PermissionSet grantSet)
538         {
539             if (CheckFlags(flags))
540                 return;
541
542             CheckSetDemand(grantSet, RuntimeMethodHandleInternal.EmptyHandle);
543         }
544
545 #if FEATURE_COMPRESSEDSTACK
546         internal void GetZoneAndOrigin(ArrayList zoneList, ArrayList originList, PermissionToken zoneToken, PermissionToken originToken)
547         {
548             if (m_zoneList != null)
549                 zoneList.AddRange(m_zoneList);
550             if (m_originList != null)
551                 originList.AddRange(m_originList);
552         }
553 #endif
554     }
555
556 }