Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / mscorlib / system / security / permissionlistset.cs
blob27cf6cd5aa0630add7a285ee84ab8a677b55f1a6
1 // ==++==
2 //
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 //
5 // ==--==
6 /*=============================================================================
7 **
8 ** Class: PermissionListSet.cs
9 **
10 ** <OWNER>Microsoft</OWNER>
11 ** <OWNER>Microsoft</OWNER>
13 ** Purpose: Holds state about A/G/R permissionsets in a callstack or appdomain
14 ** (Replacement for PermissionListSet)
16 =============================================================================*/
18 namespace System.Security
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;
30 [Serializable]
31 sealed internal class PermissionListSet
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
42 internal PermissionListSet() {}
44 private void EnsureTriplesListCreated()
46 if (m_permSetTriples == null)
48 m_permSetTriples = new ArrayList();
49 if (m_firstPermSetTriple != null)
51 m_permSetTriples.Add(m_firstPermSetTriple);
52 m_firstPermSetTriple = null;
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);
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();
70 // update the grant and denied sets
71 m_firstPermSetTriple.UpdateGrant(grantSet);
72 m_firstPermSetTriple.UpdateRefused(deniedSet);
74 #endif // FEATURE_PLS
76 private void Terminate(PermissionSetTriple currentTriple)
78 UpdateTripleListAndCreateNewTriple(currentTriple, null);
81 [System.Security.SecurityCritical] // auto-generated
82 private void Terminate(PermissionSetTriple currentTriple, PermissionListSet pls)
84 #if FEATURE_COMPRESSEDSTACK
85 this.UpdateZoneAndOrigin(pls);
86 #endif // FEATURE_COMPRESSEDSTACK
87 this.UpdatePermissions(currentTriple, pls);
88 this.UpdateTripleListAndCreateNewTriple(currentTriple, null);
91 [System.Security.SecurityCritical] // auto-generated
92 private bool Update(PermissionSetTriple currentTriple, PermissionListSet pls)
94 #if FEATURE_COMPRESSEDSTACK
95 this.UpdateZoneAndOrigin(pls);
96 #endif // FEATURE_COMPRESSEDSTACK
97 return this.UpdatePermissions(currentTriple, pls);
100 [System.Security.SecurityCritical] // auto-generated
101 private bool Update(PermissionSetTriple currentTriple, FrameSecurityDescriptor fsd)
103 #if FEATURE_COMPRESSEDSTACK
104 FrameSecurityDescriptorWithResolver fsdWithResolver = fsd as FrameSecurityDescriptorWithResolver;
105 if (fsdWithResolver != null)
107 return Update2(currentTriple, fsdWithResolver);
109 #endif // FEATURE_COMPRESSEDSTACK
111 // check imperative
112 bool fHalt = Update2(currentTriple, fsd, false);
113 if (!fHalt)
115 // then declarative
116 fHalt = Update2(currentTriple, fsd, true);
118 return fHalt;
121 #if FEATURE_COMPRESSEDSTACK
122 [System.Security.SecurityCritical]
123 private bool Update2(PermissionSetTriple currentTriple, FrameSecurityDescriptorWithResolver fsdWithResolver)
125 System.Reflection.Emit.DynamicResolver resolver = fsdWithResolver.Resolver;
126 CompressedStack dynamicCompressedStack = resolver.GetSecurityContext();
127 dynamicCompressedStack.CompleteConstruction(null);
128 return this.Update(currentTriple, dynamicCompressedStack.PLS);
130 #endif // FEATURE_COMPRESSEDSTACK
132 [System.Security.SecurityCritical] // auto-generated
133 private bool Update2(PermissionSetTriple currentTriple, FrameSecurityDescriptor fsd, bool fDeclarative)
135 // Deny
136 PermissionSet deniedPset = fsd.GetDenials(fDeclarative);
137 if (deniedPset != null)
139 currentTriple.UpdateRefused(deniedPset);
142 // permit only
143 PermissionSet permitOnlyPset = fsd.GetPermitOnly(fDeclarative);
144 if (permitOnlyPset != null)
146 currentTriple.UpdateGrant(permitOnlyPset);
149 // Assert all possible
150 if (fsd.GetAssertAllPossible())
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;
158 UpdateTripleListAndCreateNewTriple(currentTriple, m_permSetTriples);
159 currentTriple.GrantSet = PermissionSet.s_fullTrust;
160 currentTriple.UpdateAssert(fsd.GetAssertions(fDeclarative));
161 return true;
164 // Assert
165 PermissionSet assertPset = fsd.GetAssertions(fDeclarative);
166 if (assertPset != null)
168 if (assertPset.IsUnrestricted())
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;
176 UpdateTripleListAndCreateNewTriple(currentTriple, m_permSetTriples);
177 currentTriple.GrantSet = PermissionSet.s_fullTrust;
178 currentTriple.UpdateAssert(assertPset);
179 return true;
182 PermissionSetTriple retTriple = currentTriple.UpdateAssert(assertPset);
183 if (retTriple != null)
185 EnsureTriplesListCreated();
186 m_permSetTriples.Add(retTriple);
190 return false;
192 [System.Security.SecurityCritical] // auto-generated
193 private void Update(PermissionSetTriple currentTriple, PermissionSet in_g, PermissionSet in_r)
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
207 // Called from the VM for HG CS construction
208 [System.Security.SecurityCritical] // auto-generated
209 private void Update(PermissionSet in_g)
211 if (m_firstPermSetTriple == null)
212 m_firstPermSetTriple = new PermissionSetTriple();
213 Update(m_firstPermSetTriple, in_g, null);
216 #if FEATURE_COMPRESSEDSTACK
217 private void UpdateZoneAndOrigin(PermissionListSet pls)
219 if (pls != null)
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);
229 #endif // FEATURE_COMPRESSEDSTACK
231 [System.Security.SecurityCritical] // auto-generated
232 private bool UpdatePermissions(PermissionSetTriple currentTriple, PermissionListSet pls)
234 if (pls != null)
236 if (pls.m_permSetTriples != null)
238 // DCS has an AGR List. So we need to add the AGR List
239 UpdateTripleListAndCreateNewTriple(currentTriple,pls.m_permSetTriples);
241 else
243 // Common case: One AGR set
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)
255 EnsureTriplesListCreated();
256 // we just created a new triple...add the previous one (returned) to the list
257 m_permSetTriples.Add(retTriple);
261 else
263 // pls can be null only outside the loop in CreateCompressedState
264 UpdateTripleListAndCreateNewTriple(currentTriple, null);
268 return false;
273 private void UpdateTripleListAndCreateNewTriple(PermissionSetTriple currentTriple, ArrayList tripleList)
275 if (!currentTriple.IsEmpty())
277 if (m_firstPermSetTriple == null && m_permSetTriples == null)
279 m_firstPermSetTriple = new PermissionSetTriple(currentTriple);
281 else
283 EnsureTriplesListCreated();
284 m_permSetTriples.Add(new PermissionSetTriple(currentTriple));
286 currentTriple.Reset();
288 if (tripleList != null)
290 EnsureTriplesListCreated();
291 m_permSetTriples.AddRange(tripleList);
295 private static void UpdateArrayList(ArrayList current, ArrayList newList)
297 if (newList == null)
298 return;
300 for(int i=0;i < newList.Count; i++)
302 if (!current.Contains(newList[i]))
303 current.Add(newList[i]);
308 #if FEATURE_COMPRESSEDSTACK
309 private void AppendZoneOrigin(ZoneIdentityPermission z, UrlIdentityPermission u)
312 if (z != null)
314 if (m_zoneList == null)
315 m_zoneList = new ArrayList();
316 z.AppendZones(m_zoneList);
319 if (u != null)
321 if (m_originList == null)
322 m_originList = new ArrayList();
323 u.AppendOrigin(m_originList);
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)
333 // function that completes the construction of the compressed stack if not done so already (bottom half for demand evaluation)
335 bool bHaltConstruction = false;
336 if (cs.CompressedStackHandle == null)
337 return null; // FT case or Security off
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--)
344 DomainCompressedStack dcs = CompressedStack.GetDomainCompressedStack(cs.CompressedStackHandle, i);
345 if (dcs == null)
346 continue; // we hit a FT Domain
347 if (dcs.PLS == null)
349 // We failed on some DCS
350 throw new SecurityException(String.Format(CultureInfo.InvariantCulture, Environment.GetResourceString("Security_Generic")));
352 pls.UpdateZoneAndOrigin(dcs.PLS);
353 pls.Update(currentTriple, dcs.PLS);
354 bHaltConstruction = dcs.ConstructionHalted;
356 if (!bHaltConstruction)
358 PermissionListSet tmp_pls = null;
359 // Construction did not halt.
360 if (innerCS != null)
362 innerCS.CompleteConstruction(null);
363 tmp_pls = innerCS.PLS;
365 pls.Terminate(currentTriple, tmp_pls);
367 else
369 pls.Terminate(currentTriple);
372 return pls;
375 [System.Security.SecurityCritical] // auto-generated
376 static internal PermissionListSet CreateCompressedState(IntPtr unmanagedDCS, out bool bHaltConstruction)
378 PermissionListSet pls = new PermissionListSet();
379 PermissionSetTriple currentTriple = new PermissionSetTriple();
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++)
387 FrameSecurityDescriptor fsd;
388 Assembly assembly;
389 if (DomainCompressedStack.GetDescriptorInfo(unmanagedDCS, i, out tmp_g, out tmp_r, out assembly, out fsd))
391 // Got an FSD
392 bHaltConstruction = pls.Update(currentTriple, fsd);
394 else
396 pls.Update(currentTriple, tmp_g, tmp_r);
400 if (!bHaltConstruction)
402 // domain
403 if (!DomainCompressedStack.IgnoreDomain(unmanagedDCS))
405 DomainCompressedStack.GetDomainPermissionSets(unmanagedDCS, out tmp_g, out tmp_r);
406 pls.Update(currentTriple, tmp_g, tmp_r);
409 pls.Terminate(currentTriple);
412 // return the created object
413 return pls;
416 [System.Security.SecurityCritical] // auto-generated
417 static internal PermissionListSet CreateCompressedState_HG()
419 PermissionListSet pls = new PermissionListSet();
420 CompressedStack.GetHomogeneousPLS(pls);
421 return pls;
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)
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");
433 PermissionToken permToken = null;
434 if (demand != null)
435 permToken = PermissionToken.GetToken(demand);
437 return m_firstPermSetTriple.CheckDemandNoThrow(demand, permToken);
441 [System.Security.SecurityCritical] // auto-generated
442 internal bool CheckSetDemandNoThrow(PermissionSet pSet)
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");
448 return m_firstPermSetTriple.CheckSetDemandNoThrow(pSet);
451 // Demand evauation functions
452 [System.Security.SecurityCritical] // auto-generated
453 internal bool CheckDemand(CodeAccessPermission demand, PermissionToken permToken, RuntimeMethodHandleInternal rmh)
455 bool bRet = SecurityRuntime.StackContinue;
456 if (m_permSetTriples != null)
458 for (int i=0; (i < m_permSetTriples.Count && bRet != SecurityRuntime.StackHalt) ; i++)
460 PermissionSetTriple psTriple = (PermissionSetTriple)m_permSetTriples[i];
461 bRet = psTriple.CheckDemand(demand, permToken, rmh);
464 else if (m_firstPermSetTriple != null)
466 bRet = m_firstPermSetTriple.CheckDemand(demand, permToken, rmh);
469 return bRet;
472 [System.Security.SecurityCritical] // auto-generated
473 internal bool CheckSetDemand(PermissionSet pset , RuntimeMethodHandleInternal rmh)
475 PermissionSet unused;
476 CheckSetDemandWithModification(pset, out unused, rmh);
477 return SecurityRuntime.StackHalt; // CS demand check always terminates the stackwalk
480 [System.Security.SecurityCritical]
481 internal bool CheckSetDemandWithModification(PermissionSet pset, out PermissionSet alteredDemandSet, RuntimeMethodHandleInternal rmh)
483 bool bRet = SecurityRuntime.StackContinue;
484 PermissionSet demandSet = pset;
485 alteredDemandSet = null;
486 if (m_permSetTriples != null)
488 for (int i=0; (i < m_permSetTriples.Count && bRet != SecurityRuntime.StackHalt) ; i++)
490 PermissionSetTriple psTriple = (PermissionSetTriple)m_permSetTriples[i];
491 bRet = psTriple.CheckSetDemand(demandSet, out alteredDemandSet, rmh);
492 if (alteredDemandSet != null)
493 demandSet = alteredDemandSet;
496 else if (m_firstPermSetTriple != null)
498 bRet = m_firstPermSetTriple.CheckSetDemand(demandSet, out alteredDemandSet, rmh);
501 return bRet;
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)
511 Contract.Assert(flags != 0, "Invalid permission flag demand");
513 bool check = true;
515 if (m_permSetTriples != null)
517 for (int i = 0; i < m_permSetTriples.Count && check && flags != 0; i++)
519 check &= ((PermissionSetTriple)m_permSetTriples[i]).CheckFlags(ref flags);
522 else if (m_firstPermSetTriple != null)
524 check = m_firstPermSetTriple.CheckFlags(ref flags);
527 return check;
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)
539 if (CheckFlags(flags))
540 return;
542 CheckSetDemand(grantSet, RuntimeMethodHandleInternal.EmptyHandle);
545 #if FEATURE_COMPRESSEDSTACK
546 internal void GetZoneAndOrigin(ArrayList zoneList, ArrayList originList, PermissionToken zoneToken, PermissionToken originToken)
548 if (m_zoneList != null)
549 zoneList.AddRange(m_zoneList);
550 if (m_originList != null)
551 originList.AddRange(m_originList);
553 #endif