Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / mscorlib / system / security / securitycontext.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 /*============================================================
6 **
7 ** Class:  SecurityContext
8 ** 
9 ** <OWNER>Microsoft</OWNER>
10 **
11 **
12 ** Purpose: Capture security  context for a thread
13 **
14 ** 
15 ===========================================================*/
16 namespace System.Security
17 {    
18     using Microsoft.Win32;
19     using Microsoft.Win32.SafeHandles;
20     using System.Threading;
21     using System.Runtime.Remoting;
22     using System.Security.Principal;
23     using System.Collections;
24     using System.Runtime.Serialization;
25     using System.Security.Permissions;
26     using System.Runtime.InteropServices;
27     using System.Runtime.CompilerServices;
28 #if FEATURE_CORRUPTING_EXCEPTIONS
29     using System.Runtime.ExceptionServices;
30 #endif // FEATURE_CORRUPTING_EXCEPTIONS
31     using System.Runtime.ConstrainedExecution;
32     using System.Runtime.Versioning;
33     using System.Diagnostics.Contracts;
34
35     // This enum must be kept in sync with the SecurityContextSource enum in the VM
36     public enum SecurityContextSource
37     {
38         CurrentAppDomain = 0,
39         CurrentAssembly
40     }
41
42     internal enum SecurityContextDisableFlow
43     {
44         Nothing = 0,
45         WI = 0x1,
46         All = 0x3FFF
47     }
48
49 #if !FEATURE_PAL && FEATURE_IMPERSONATION
50     internal enum WindowsImpersonationFlowMode { 
51     IMP_FASTFLOW = 0,
52        IMP_NOFLOW = 1,
53        IMP_ALWAYSFLOW = 2,
54        IMP_DEFAULT = IMP_FASTFLOW 
55     }
56 #endif
57
58 #if FEATURE_COMPRESSEDSTACK
59     internal struct SecurityContextSwitcher: IDisposable
60     {
61         internal SecurityContext.Reader prevSC; // prev SC that we restore on an Undo
62         internal SecurityContext currSC; //current SC  - SetSecurityContext that created the switcher set this on the Thread
63         internal ExecutionContext currEC; // current ExecutionContext on Thread
64         internal CompressedStackSwitcher cssw;
65 #if !FEATURE_PAL && FEATURE_IMPERSONATION
66         internal WindowsImpersonationContext wic;
67 #endif
68
69         [System.Security.SecuritySafeCritical] // overrides public transparent member
70         public void Dispose()
71         {
72             Undo();
73         }
74
75         [System.Security.SecurityCritical]  // auto-generated
76         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
77 #if FEATURE_CORRUPTING_EXCEPTIONS
78         [HandleProcessCorruptedStateExceptions] // 
79 #endif // FEATURE_CORRUPTING_EXCEPTIONS
80         internal bool UndoNoThrow()
81         {
82             try
83             {
84                 Undo();
85             }
86             catch
87             {
88                 return false;
89             }
90             return true;
91         }
92
93         [System.Security.SecurityCritical]  // auto-generated
94         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
95         [ResourceExposure(ResourceScope.None)]
96         [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]  // FailFast
97 #if FEATURE_CORRUPTING_EXCEPTIONS
98         [HandleProcessCorruptedStateExceptions] // 
99 #endif // FEATURE_CORRUPTING_EXCEPTIONS
100         public void Undo()
101         {        
102             if (currSC == null) 
103             {
104                 return; // mutiple Undo()s called on this switcher object
105             }  
106
107             if (currEC != null)
108             {
109                 Contract.Assert(currEC == Thread.CurrentThread.GetMutableExecutionContext(), "SecurityContextSwitcher used from another thread");
110                 Contract.Assert(currSC == currEC.SecurityContext, "SecurityContextSwitcher context mismatch");
111             
112                 // restore the saved security context 
113                 currEC.SecurityContext = prevSC.DangerousGetRawSecurityContext();
114             }
115             else
116             {
117                 // caller must have already restored the ExecutionContext
118                 Contract.Assert(Thread.CurrentThread.GetExecutionContextReader().SecurityContext.IsSame(prevSC));
119             }
120
121             currSC = null; // this will prevent the switcher object being used again        
122
123             bool bNoException = true;
124 #if !FEATURE_PAL && FEATURE_IMPERSONATION
125             try 
126             {
127                 if (wic != null)
128                     bNoException &= wic.UndoNoThrow();
129             }
130             catch
131             {
132                 // Failfast since we can't continue safely...
133                 bNoException &= cssw.UndoNoThrow();
134                 System.Environment.FailFast(Environment.GetResourceString("ExecutionContext_UndoFailed"));
135                 
136             }
137 #endif
138             bNoException &= cssw.UndoNoThrow();
139
140
141             if (!bNoException)
142             {
143                 // Failfast since we can't continue safely...
144                 System.Environment.FailFast(Environment.GetResourceString("ExecutionContext_UndoFailed"));                
145             }
146
147         }
148     }
149     
150
151     public sealed class SecurityContext : IDisposable 
152     {
153 #if !FEATURE_PAL && FEATURE_IMPERSONATION
154         // Note that only one of the following variables will be true. The way we set up the flow mode in the g_pConfig guarantees this.
155         static bool _LegacyImpersonationPolicy = (GetImpersonationFlowMode() == WindowsImpersonationFlowMode.IMP_NOFLOW);
156         static bool _alwaysFlowImpersonationPolicy = (GetImpersonationFlowMode() == WindowsImpersonationFlowMode.IMP_ALWAYSFLOW);
157 #endif
158         /*=========================================================================
159         ** Data accessed from managed code that needs to be defined in 
160         ** SecurityContextObject  to maintain alignment between the two classes.
161         ** DON'T CHANGE THESE UNLESS YOU MODIFY SecurityContextObject in vm\object.h
162         =========================================================================*/
163         
164         private ExecutionContext            _executionContext;
165 #if !FEATURE_PAL && FEATURE_IMPERSONATION
166         private volatile WindowsIdentity             _windowsIdentity;
167 #endif
168 #if FEATURE_COMPRESSEDSTACK
169         private volatile CompressedStack          _compressedStack;
170 #endif
171         static private volatile SecurityContext _fullTrustSC;
172         
173         internal volatile bool isNewCapture = false;
174         internal volatile SecurityContextDisableFlow _disableFlow = SecurityContextDisableFlow.Nothing;
175                 
176         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
177         internal SecurityContext()
178         {
179         }
180
181         internal struct Reader
182         {
183             SecurityContext m_sc;
184
185             public Reader(SecurityContext sc) { m_sc = sc; }
186
187             public SecurityContext DangerousGetRawSecurityContext() { return m_sc; }
188
189             public bool IsNull { get { return m_sc == null; } }
190             public bool IsSame(SecurityContext sc) { return m_sc == sc; }
191             public bool IsSame(SecurityContext.Reader sc) { return m_sc == sc.m_sc; }
192
193             [MethodImpl(MethodImplOptions.AggressiveInlining)]
194             public bool IsFlowSuppressed(SecurityContextDisableFlow flags)
195             {           
196                 return (m_sc == null) ? false : ((m_sc._disableFlow & flags) == flags);
197             }
198         
199             public CompressedStack CompressedStack { get { return IsNull ? null : m_sc.CompressedStack; } }
200
201             public WindowsIdentity WindowsIdentity 
202             { 
203                 [MethodImpl(MethodImplOptions.AggressiveInlining)]
204                 get { return IsNull ? null : m_sc.WindowsIdentity; } 
205             }
206         }
207         
208             
209         static internal SecurityContext FullTrustSecurityContext
210         {
211             [System.Security.SecurityCritical]  // auto-generated
212             get
213             {
214                 if (_fullTrustSC == null)
215                     _fullTrustSC = CreateFullTrustSecurityContext();
216                 return _fullTrustSC;
217             }
218         }
219
220         // link the security context to an ExecutionContext
221         internal ExecutionContext ExecutionContext
222         {
223             [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
224             set
225             {
226                 _executionContext = value;
227             }
228         }
229                 
230 #if !FEATURE_PAL && FEATURE_IMPERSONATION
231
232
233         internal WindowsIdentity WindowsIdentity 
234         {
235             get 
236             {
237                 return _windowsIdentity;
238             }
239             set
240             {
241                 // Note, we do not dispose of the existing windows identity, since some code such as remoting
242                 // relies on reusing that identity.  If you are not going to reuse the existing identity, then
243                 // you should dispose of the existing identity before resetting it.
244                     _windowsIdentity = value;
245             }
246         }
247 #endif // !FEATURE_PAL && FEATURE_IMPERSONATION
248
249               
250         internal CompressedStack CompressedStack
251         {
252             get
253             {
254                 return _compressedStack; 
255             }
256             [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
257             set
258             {
259                 _compressedStack =  value;                    
260             }
261         }
262
263         public void Dispose()
264         {
265 #if !FEATURE_PAL && FEATURE_IMPERSONATION
266             if (_windowsIdentity != null)
267                 _windowsIdentity.Dispose();
268 #endif // !FEATURE_PAL
269         }
270
271         [System.Security.SecurityCritical]  // auto-generated_required
272         public static AsyncFlowControl SuppressFlow()
273         {
274             return SuppressFlow(SecurityContextDisableFlow.All);
275         }
276         
277         [System.Security.SecurityCritical]  // auto-generated_required
278         public static AsyncFlowControl SuppressFlowWindowsIdentity()
279         {
280             return SuppressFlow(SecurityContextDisableFlow.WI);
281         }
282
283         [SecurityCritical]
284         internal static AsyncFlowControl SuppressFlow(SecurityContextDisableFlow flags)
285         {
286 #if MOBILE
287             throw new NotSupportedException ();
288 #else
289             if (IsFlowSuppressed(flags))
290             {
291                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotSupressFlowMultipleTimes"));
292             }
293
294             ExecutionContext ec = Thread.CurrentThread.GetMutableExecutionContext();
295             if (ec.SecurityContext == null)
296                 ec.SecurityContext = new SecurityContext();
297             AsyncFlowControl afc = new AsyncFlowControl();
298             afc.Setup(flags);
299             return afc;
300 #endif
301         }
302
303         [SecuritySafeCritical]
304         public static void RestoreFlow()
305         {
306 #if !MOBILE
307             SecurityContext sc = Thread.CurrentThread.GetMutableExecutionContext().SecurityContext;
308             if (sc == null || sc._disableFlow == SecurityContextDisableFlow.Nothing)
309             {
310                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotRestoreUnsupressedFlow"));
311             }
312             sc._disableFlow = SecurityContextDisableFlow.Nothing;        
313 #endif
314         }
315
316         public static bool IsFlowSuppressed()
317         {
318             return SecurityContext.IsFlowSuppressed(SecurityContextDisableFlow.All);
319         }
320 #if (!FEATURE_PAL && FEATURE_IMPERSONATION) || MONO
321         public static bool IsWindowsIdentityFlowSuppressed()
322         {
323             return (_LegacyImpersonationPolicy|| SecurityContext.IsFlowSuppressed(SecurityContextDisableFlow.WI));
324         }
325 #endif        
326         [SecuritySafeCritical]
327         internal static bool IsFlowSuppressed(SecurityContextDisableFlow flags)
328         {  
329 #if MOBILE
330             return false;
331 #else
332             return Thread.CurrentThread.GetExecutionContextReader().SecurityContext.IsFlowSuppressed(flags);
333 #endif
334         }
335
336         // This method is special from a security perspective - the VM will not allow a stack walk to
337         // continue past the call to SecurityContext.Run.  If you change the signature to this method, or
338         // provide an alternate way to do a SecurityContext.Run make sure to update
339         // SecurityStackWalk::IsSpecialRunFrame in the VM to search for the new method.
340         [System.Security.SecurityCritical]  // auto-generated_required
341         [DynamicSecurityMethodAttribute()]
342         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
343         public static void Run(SecurityContext securityContext, ContextCallback callback, Object state)
344         {
345             if (securityContext == null )
346             {
347                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NullContext"));
348             }
349             Contract.EndContractBlock();
350
351             StackCrawlMark stackMark = StackCrawlMark.LookForMe;
352
353             if (!securityContext.isNewCapture)
354             {
355                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotNewCaptureContext"));
356             }
357
358             securityContext.isNewCapture = false;
359 #if !MOBILE
360             ExecutionContext.Reader ec = Thread.CurrentThread.GetExecutionContextReader();
361             
362             // Optimization: do the callback directly if both the current and target contexts are equal to the
363             // default full-trust security context
364             if ( SecurityContext.CurrentlyInDefaultFTSecurityContext(ec)
365                 && securityContext.IsDefaultFTSecurityContext())
366             {
367                 callback(state);
368                 
369                 if (GetCurrentWI(Thread.CurrentThread.GetExecutionContextReader()) != null) 
370                 {
371                     // If we enter here it means the callback did an impersonation
372                     // that we need to revert.
373                     // We don't need to revert any other security state since it is stack-based 
374                     // and automatically goes away when the callback returns.
375                     WindowsIdentity.SafeRevertToSelf(ref stackMark);
376                     // Ensure we have reverted to the state we entered in.
377                     Contract.Assert(GetCurrentWI(Thread.CurrentThread.GetExecutionContextReader()) == null);
378                 }
379             }
380             else
381 #endif
382             {
383                 RunInternal(securityContext, callback, state);
384             }
385
386         }
387         [System.Security.SecurityCritical]  // auto-generated
388         internal static void RunInternal(SecurityContext securityContext, ContextCallback callBack, Object state)
389         {
390             if (cleanupCode == null)
391             {
392                 tryCode = new RuntimeHelpers.TryCode(runTryCode);
393                 cleanupCode = new RuntimeHelpers.CleanupCode(runFinallyCode);
394             }
395             SecurityContextRunData runData = new SecurityContextRunData(securityContext, callBack, state);
396             RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, runData);
397
398         }
399         
400         internal class SecurityContextRunData
401         {
402             internal SecurityContext sc;
403             internal ContextCallback callBack;
404             internal Object state;
405             internal SecurityContextSwitcher scsw;
406             internal SecurityContextRunData(SecurityContext securityContext, ContextCallback cb, Object state)
407             {
408                 this.sc = securityContext;
409                 this.callBack = cb;
410                 this.state = state;
411                 this.scsw = new SecurityContextSwitcher();
412             }
413         }
414
415         [System.Security.SecurityCritical]  // auto-generated
416         [ResourceExposure(ResourceScope.Process)]
417         [ResourceConsumption(ResourceScope.Process)]
418         static internal void runTryCode(Object userData)
419         {
420             SecurityContextRunData rData = (SecurityContextRunData) userData;
421             rData.scsw = SetSecurityContext(rData.sc, Thread.CurrentThread.GetExecutionContextReader().SecurityContext, modifyCurrentExecutionContext: true);
422             rData.callBack(rData.state);
423             
424         }
425
426         [System.Security.SecurityCritical]  // auto-generated
427         [PrePrepareMethod]
428         static internal void runFinallyCode(Object userData, bool exceptionThrown)
429         {
430             SecurityContextRunData rData = (SecurityContextRunData) userData;
431             rData.scsw.Undo();
432         }
433                     
434         static volatile internal RuntimeHelpers.TryCode tryCode;
435         static volatile internal RuntimeHelpers.CleanupCode cleanupCode;
436
437
438
439         // Internal API that gets called from public SetSecurityContext and from SetExecutionContext
440         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
441         [System.Security.SecurityCritical]  // auto-generated
442         [ResourceExposure(ResourceScope.Process)]
443         [ResourceConsumption(ResourceScope.Process)]
444         [DynamicSecurityMethodAttribute()]
445         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
446         internal static SecurityContextSwitcher SetSecurityContext(SecurityContext sc, SecurityContext.Reader prevSecurityContext, bool modifyCurrentExecutionContext)
447         {
448             StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
449             return SetSecurityContext(sc, prevSecurityContext, modifyCurrentExecutionContext, ref stackMark);
450         }
451
452         [System.Security.SecurityCritical]  // auto-generated
453 #if FEATURE_CORRUPTING_EXCEPTIONS
454         [HandleProcessCorruptedStateExceptions] // 
455 #endif // FEATURE_CORRUPTING_EXCEPTIONS
456         internal static SecurityContextSwitcher SetSecurityContext(SecurityContext sc, SecurityContext.Reader prevSecurityContext, bool modifyCurrentExecutionContext, ref StackCrawlMark stackMark)
457         {
458             // Save the flow state at capture and reset it in the SC.
459             SecurityContextDisableFlow _capturedFlowState = sc._disableFlow;
460             sc._disableFlow = SecurityContextDisableFlow.Nothing;
461             
462             //Set up the switcher object
463             SecurityContextSwitcher scsw = new SecurityContextSwitcher();
464             scsw.currSC = sc;   
465             scsw.prevSC = prevSecurityContext;
466
467             if (modifyCurrentExecutionContext)
468             {
469                 // save the current Execution Context
470                 ExecutionContext currEC = Thread.CurrentThread.GetMutableExecutionContext();
471                 scsw.currEC = currEC;
472                 currEC.SecurityContext = sc;
473             }
474
475             if (sc != null)
476             {
477                 RuntimeHelpers.PrepareConstrainedRegions();
478                 try
479                 {
480 #if !FEATURE_PAL && FEATURE_IMPERSONATION
481                     scsw.wic = null;
482                     if (!_LegacyImpersonationPolicy)
483                     {
484                         if (sc.WindowsIdentity != null)
485                         {
486                             scsw.wic = sc.WindowsIdentity.Impersonate(ref stackMark);
487                         }
488                         else if ( ((_capturedFlowState & SecurityContextDisableFlow.WI) == 0) 
489                             && prevSecurityContext.WindowsIdentity != null)
490                         {
491                             // revert impersonation if there was no WI flow supression at capture and we're currently impersonating
492                             scsw.wic = WindowsIdentity.SafeRevertToSelf(ref stackMark); 
493                         }
494                     }
495 #endif
496                     scsw.cssw = CompressedStack.SetCompressedStack(sc.CompressedStack, prevSecurityContext.CompressedStack);
497                 }
498                 catch 
499                 {
500                     scsw.UndoNoThrow();
501                     throw;
502                 }      
503             }
504             return scsw;
505         }
506
507         /// <internalonly/>
508         [System.Security.SecuritySafeCritical]  // auto-generated
509         public SecurityContext CreateCopy()
510         {
511             if (!isNewCapture)
512             {
513                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotNewCaptureContext"));
514             }                                
515
516             SecurityContext sc = new SecurityContext();
517             sc.isNewCapture = true;
518             sc._disableFlow = _disableFlow;
519
520 #if !FEATURE_PAL && FEATURE_IMPERSONATION
521             if (WindowsIdentity != null)
522                 sc._windowsIdentity = new WindowsIdentity(WindowsIdentity.AccessToken);
523 #endif //!FEATURE_PAL && FEATURE_IMPERSONATION
524
525             if (_compressedStack != null)
526                 sc._compressedStack = _compressedStack.CreateCopy();
527
528             return sc;
529         }
530
531         /// <internalonly/>
532         [System.Security.SecuritySafeCritical]  // auto-generated
533         internal SecurityContext CreateMutableCopy()
534         {
535             Contract.Assert(!this.isNewCapture);
536
537             SecurityContext sc = new SecurityContext();
538             sc._disableFlow = this._disableFlow;
539
540 #if !FEATURE_PAL && FEATURE_IMPERSONATION
541             if (this.WindowsIdentity != null)
542                 sc._windowsIdentity = new WindowsIdentity(this.WindowsIdentity.AccessToken);
543 #endif //!FEATURE_PAL && FEATURE_IMPERSONATION
544
545             // 
546             if (this._compressedStack != null)
547                 sc._compressedStack = this._compressedStack.CreateCopy();
548
549             return sc;
550         }
551
552         [System.Security.SecuritySafeCritical]  // auto-generated
553         [MethodImplAttribute(MethodImplOptions.NoInlining)] // Methods containing StackCrawlMark local var has to be marked non-inlineable
554         public static SecurityContext Capture( )
555         {
556             // check to see if Flow is suppressed
557             if (IsFlowSuppressed()) 
558                 return null;
559
560             StackCrawlMark stackMark= StackCrawlMark.LookForMyCaller;
561             SecurityContext sc = SecurityContext.Capture(Thread.CurrentThread.GetExecutionContextReader(), ref stackMark);
562             if (sc == null)
563                 sc = CreateFullTrustSecurityContext();
564             return sc;
565          }
566
567         // create a clone from a non-existing SecurityContext
568         [System.Security.SecurityCritical]  // auto-generated
569         [MethodImpl(MethodImplOptions.AggressiveInlining)]
570         static internal SecurityContext Capture(ExecutionContext.Reader currThreadEC, ref StackCrawlMark stackMark)
571         {
572             // check to see if Flow is suppressed
573             if (currThreadEC.SecurityContext.IsFlowSuppressed(SecurityContextDisableFlow.All)) 
574                 return null;
575         
576             // If we're in FT right now, return null
577             if (CurrentlyInDefaultFTSecurityContext(currThreadEC))
578                 return null;
579
580             return CaptureCore(currThreadEC, ref stackMark);
581         }
582
583         [System.Security.SecurityCritical]  // auto-generated
584         static private SecurityContext CaptureCore(ExecutionContext.Reader currThreadEC, ref StackCrawlMark stackMark)
585         {
586             SecurityContext sc = new SecurityContext();
587             sc.isNewCapture = true;
588
589     #if !FEATURE_PAL && FEATURE_IMPERSONATION
590                 // Force create WindowsIdentity
591             if (!IsWindowsIdentityFlowSuppressed())
592             {
593                 WindowsIdentity currentIdentity = GetCurrentWI(currThreadEC);
594                 if (currentIdentity != null)
595                     sc._windowsIdentity = new WindowsIdentity(currentIdentity.AccessToken);
596             }
597             else
598             {
599                 sc._disableFlow = SecurityContextDisableFlow.WI;
600             }
601     #endif // !FEATURE_PAL && FEATURE_IMPERSONATION
602
603             // Force create CompressedStack
604             sc.CompressedStack = CompressedStack.GetCompressedStack(ref stackMark);
605             return sc;
606         }
607         [System.Security.SecurityCritical]  // auto-generated
608         static internal SecurityContext CreateFullTrustSecurityContext()
609         {
610             SecurityContext sc = new SecurityContext();
611             sc.isNewCapture = true;
612         
613     #if !FEATURE_PAL && FEATURE_IMPERSONATION
614             if (IsWindowsIdentityFlowSuppressed())
615             {
616                 sc._disableFlow = SecurityContextDisableFlow.WI;
617             }
618     #endif // !FEATURE_PAL && FEATURE_IMPERSONATION
619         
620 #if FEATURE_COMPRESSEDSTACK
621             // Force create CompressedStack
622             sc.CompressedStack = new CompressedStack(null);
623 #endif
624             return sc;
625         }
626
627 #if !FEATURE_PAL && FEATURE_IMPERSONATION
628
629     static internal bool AlwaysFlowImpersonationPolicy { get { return _alwaysFlowImpersonationPolicy; } }
630
631         // Check to see if we have a WI on the thread and return if we do
632     [System.Security.SecurityCritical]  // auto-generated
633     [ResourceExposure(ResourceScope.None)]
634     [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
635     [MethodImpl(MethodImplOptions.AggressiveInlining)]
636     static internal WindowsIdentity GetCurrentWI(ExecutionContext.Reader threadEC)
637     {
638         return GetCurrentWI(threadEC, _alwaysFlowImpersonationPolicy);
639     }
640
641     [System.Security.SecurityCritical]  // auto-generated
642     [ResourceExposure(ResourceScope.None)]
643     [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
644     [MethodImpl(MethodImplOptions.AggressiveInlining)]
645     static internal WindowsIdentity GetCurrentWI(ExecutionContext.Reader threadEC, bool cachedAlwaysFlowImpersonationPolicy)
646     {
647         Contract.Assert(cachedAlwaysFlowImpersonationPolicy == _alwaysFlowImpersonationPolicy);
648         if (cachedAlwaysFlowImpersonationPolicy)
649         {
650             // Examine the threadtoken at the cost of a kernel call if the user has set the IMP_ALWAYSFLOW mode
651             return WindowsIdentity.GetCurrentInternal(TokenAccessLevels.MaximumAllowed, true);
652         }
653
654         return threadEC.SecurityContext.WindowsIdentity;
655     }
656
657     [System.Security.SecurityCritical]
658     [ResourceExposure(ResourceScope.None)]
659     [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
660     static internal void RestoreCurrentWI(ExecutionContext.Reader currentEC, ExecutionContext.Reader prevEC, WindowsIdentity targetWI, bool cachedAlwaysFlowImpersonationPolicy)
661     {
662         Contract.Assert(currentEC.IsSame(Thread.CurrentThread.GetExecutionContextReader()));
663         Contract.Assert(cachedAlwaysFlowImpersonationPolicy == _alwaysFlowImpersonationPolicy);
664
665         // NOTE: cachedAlwaysFlowImpersonationPolicy is a perf optimization to avoid always having to access a static variable here.
666         if (cachedAlwaysFlowImpersonationPolicy || prevEC.SecurityContext.WindowsIdentity != targetWI)
667         {
668             //
669             // Either we're always flowing, or the target WI was obtained from the current EC in the first place.
670             //
671             Contract.Assert(_alwaysFlowImpersonationPolicy || currentEC.SecurityContext.WindowsIdentity == targetWI);
672
673             RestoreCurrentWIInternal(targetWI);
674         }
675     }
676
677     [System.Security.SecurityCritical]
678     [ResourceExposure(ResourceScope.None)]
679     [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
680     static private void RestoreCurrentWIInternal(WindowsIdentity targetWI)
681     {
682         int hr = Win32.RevertToSelf();
683         if (hr < 0)
684             Environment.FailFast(Win32Native.GetMessage(hr));
685
686         if (targetWI != null)
687         {   
688             SafeAccessTokenHandle tokenHandle = targetWI.AccessToken;
689             if (tokenHandle != null && !tokenHandle.IsInvalid)
690             {
691                 hr = Win32.ImpersonateLoggedOnUser(tokenHandle);
692                 if (hr < 0)
693                     Environment.FailFast(Win32Native.GetMessage(hr));
694             }                
695         }
696     }
697
698     [System.Security.SecurityCritical]  // auto-generated
699     internal bool IsDefaultFTSecurityContext()
700     {
701         return (WindowsIdentity == null && (CompressedStack == null || CompressedStack.CompressedStackHandle == null));
702     }
703     [System.Security.SecurityCritical]  // auto-generated
704     [MethodImpl(MethodImplOptions.AggressiveInlining)]
705     static internal bool CurrentlyInDefaultFTSecurityContext(ExecutionContext.Reader threadEC)
706     {
707         return (IsDefaultThreadSecurityInfo() && GetCurrentWI(threadEC) == null);
708     }
709 #else
710         
711         internal bool IsDefaultFTSecurityContext()
712         {
713             return (CompressedStack == null || CompressedStack.CompressedStackHandle == null);
714         }
715         static internal bool CurrentlyInDefaultFTSecurityContext(ExecutionContext threadEC)
716         {
717             return (IsDefaultThreadSecurityInfo());
718         }
719 #endif
720 #if !FEATURE_PAL && FEATURE_IMPERSONATION
721         [System.Security.SecuritySafeCritical]  // auto-generated
722         [ResourceExposure(ResourceScope.None)]
723         [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
724         internal extern static WindowsImpersonationFlowMode GetImpersonationFlowMode();
725 #endif
726         [System.Security.SecurityCritical]  // auto-generated
727         [ResourceExposure(ResourceScope.None)]
728         [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
729         internal extern static bool IsDefaultThreadSecurityInfo();
730         
731     }
732 #endif // FEATURE_COMPRESSEDSTACK
733 }