3 // Copyright (c) Microsoft Corporation. All rights reserved.
6 /*=============================================================================
8 ** Class: PermissionListSet.cs
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
;
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;
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
);
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
112 bool fHalt
= Update2(currentTriple
, fsd
, false);
116 fHalt
= Update2(currentTriple
, fsd
, true);
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
)
136 PermissionSet deniedPset
= fsd
.GetDenials(fDeclarative
);
137 if (deniedPset
!= null)
139 currentTriple
.UpdateRefused(deniedPset
);
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
));
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
);
182 PermissionSetTriple retTriple
= currentTriple
.UpdateAssert(assertPset
);
183 if (retTriple
!= null)
185 EnsureTriplesListCreated();
186 m_permSetTriples
.Add(retTriple
);
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
)
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
)
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
);
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
))
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
);
263 // pls can be null only outside the loop in CreateCompressedState
264 UpdateTripleListAndCreateNewTriple(currentTriple
, null);
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
);
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
)
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
)
314 if (m_zoneList
== null)
315 m_zoneList
= new ArrayList();
316 z
.AppendZones(m_zoneList
);
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
);
346 continue; // we hit a FT Domain
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.
362 innerCS
.CompleteConstruction(null);
363 tmp_pls
= innerCS
.PLS
;
365 pls
.Terminate(currentTriple
, tmp_pls
);
369 pls
.Terminate(currentTriple
);
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
;
389 if (DomainCompressedStack
.GetDescriptorInfo(unmanagedDCS
, i
, out tmp_g
, out tmp_r
, out assembly
, out fsd
))
392 bHaltConstruction
= pls
.Update(currentTriple
, fsd
);
396 pls
.Update(currentTriple
, tmp_g
, tmp_r
);
400 if (!bHaltConstruction
)
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
416 [System
.Security
.SecurityCritical
] // auto-generated
417 static internal PermissionListSet
CreateCompressedState_HG()
419 PermissionListSet pls
= new PermissionListSet();
420 CompressedStack
.GetHomogeneousPLS(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;
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
);
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
);
505 /// Check to see if the PLS satisfies a demand for the special permissions encoded in flags
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");
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
);
531 /// Demand which succeeds if either a set of special permissions or a permission set is granted
532 /// to the call stack
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
))
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
);