mscorlib(4.0.0.0) API with additions
SecurityContext.cs
1 using Microsoft.Win32;
2 using Microsoft.Win32.SafeHandles;
7 using System.Threading;
8 
9 namespace System.Security
10 {
12  public sealed class SecurityContext : IDisposable
13  {
14  internal struct Reader
15  {
16  private SecurityContext m_sc;
17 
18  public bool IsNull => m_sc == null;
19 
21  {
22  get
23  {
24  if (!IsNull)
25  {
26  return m_sc.CompressedStack;
27  }
28  return null;
29  }
30  }
31 
33  {
34  [MethodImpl(MethodImplOptions.AggressiveInlining)]
35  get
36  {
37  if (!IsNull)
38  {
39  return m_sc.WindowsIdentity;
40  }
41  return null;
42  }
43  }
44 
45  public Reader(SecurityContext sc)
46  {
47  m_sc = sc;
48  }
49 
50  public SecurityContext DangerousGetRawSecurityContext()
51  {
52  return m_sc;
53  }
54 
55  public bool IsSame(SecurityContext sc)
56  {
57  return m_sc == sc;
58  }
59 
60  public bool IsSame(Reader sc)
61  {
62  return m_sc == sc.m_sc;
63  }
64 
65  [MethodImpl(MethodImplOptions.AggressiveInlining)]
66  public bool IsFlowSuppressed(SecurityContextDisableFlow flags)
67  {
68  if (m_sc != null)
69  {
70  return (m_sc._disableFlow & flags) == flags;
71  }
72  return false;
73  }
74  }
75 
76  internal class SecurityContextRunData
77  {
78  internal SecurityContext sc;
79 
80  internal ContextCallback callBack;
81 
82  internal object state;
83 
84  internal SecurityContextSwitcher scsw;
85 
86  internal SecurityContextRunData(SecurityContext securityContext, ContextCallback cb, object state)
87  {
88  sc = securityContext;
89  callBack = cb;
90  this.state = state;
91  scsw = default(SecurityContextSwitcher);
92  }
93  }
94 
95  private static bool _LegacyImpersonationPolicy = GetImpersonationFlowMode() == WindowsImpersonationFlowMode.IMP_NOFLOW;
96 
97  private static bool _alwaysFlowImpersonationPolicy = GetImpersonationFlowMode() == WindowsImpersonationFlowMode.IMP_ALWAYSFLOW;
98 
99  private ExecutionContext _executionContext;
100 
101  private volatile WindowsIdentity _windowsIdentity;
102 
103  private volatile CompressedStack _compressedStack;
104 
105  private static volatile SecurityContext _fullTrustSC;
106 
107  internal volatile bool isNewCapture;
108 
109  internal volatile SecurityContextDisableFlow _disableFlow;
110 
111  internal static volatile RuntimeHelpers.TryCode tryCode;
112 
113  internal static volatile RuntimeHelpers.CleanupCode cleanupCode;
114 
115  internal static SecurityContext FullTrustSecurityContext
116  {
117  [SecurityCritical]
118  get
119  {
120  if (_fullTrustSC == null)
121  {
122  _fullTrustSC = CreateFullTrustSecurityContext();
123  }
124  return _fullTrustSC;
125  }
126  }
127 
129  {
130  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
131  set
132  {
133  _executionContext = value;
134  }
135  }
136 
138  {
139  get
140  {
141  return _windowsIdentity;
142  }
143  set
144  {
145  _windowsIdentity = value;
146  }
147  }
148 
150  {
151  get
152  {
153  return _compressedStack;
154  }
155  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
156  set
157  {
158  _compressedStack = value;
159  }
160  }
161 
162  internal static bool AlwaysFlowImpersonationPolicy => _alwaysFlowImpersonationPolicy;
163 
164  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
165  internal SecurityContext()
166  {
167  }
168 
170  public void Dispose()
171  {
172  if (_windowsIdentity != null)
173  {
174  _windowsIdentity.Dispose();
175  }
176  }
177 
180  [SecurityCritical]
182  {
183  return SuppressFlow(SecurityContextDisableFlow.All);
184  }
185 
188  [SecurityCritical]
190  {
191  return SuppressFlow(SecurityContextDisableFlow.WI);
192  }
193 
194  [SecurityCritical]
195  internal static AsyncFlowControl SuppressFlow(SecurityContextDisableFlow flags)
196  {
197  if (IsFlowSuppressed(flags))
198  {
199  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotSupressFlowMultipleTimes"));
200  }
201  ExecutionContext mutableExecutionContext = Thread.CurrentThread.GetMutableExecutionContext();
202  if (mutableExecutionContext.SecurityContext == null)
203  {
204  mutableExecutionContext.SecurityContext = new SecurityContext();
205  }
206  AsyncFlowControl result = default(AsyncFlowControl);
207  result.Setup(flags);
208  return result;
209  }
210 
213  [SecuritySafeCritical]
214  public static void RestoreFlow()
215  {
216  SecurityContext securityContext = Thread.CurrentThread.GetMutableExecutionContext().SecurityContext;
217  if (securityContext == null || securityContext._disableFlow == SecurityContextDisableFlow.Nothing)
218  {
219  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_CannotRestoreUnsupressedFlow"));
220  }
221  securityContext._disableFlow = SecurityContextDisableFlow.Nothing;
222  }
223 
227  public static bool IsFlowSuppressed()
228  {
229  return IsFlowSuppressed(SecurityContextDisableFlow.All);
230  }
231 
235  public static bool IsWindowsIdentityFlowSuppressed()
236  {
237  if (!_LegacyImpersonationPolicy)
238  {
239  return IsFlowSuppressed(SecurityContextDisableFlow.WI);
240  }
241  return true;
242  }
243 
244  [SecuritySafeCritical]
245  internal static bool IsFlowSuppressed(SecurityContextDisableFlow flags)
246  {
247  return Thread.CurrentThread.GetExecutionContextReader().SecurityContext.IsFlowSuppressed(flags);
248  }
249 
258  [MethodImpl(MethodImplOptions.NoInlining)]
259  [SecurityCritical]
260  public static void Run(SecurityContext securityContext, ContextCallback callback, object state)
261  {
262  if (securityContext == null)
263  {
264  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NullContext"));
265  }
266  StackCrawlMark stackMark = StackCrawlMark.LookForMe;
267  if (!securityContext.isNewCapture)
268  {
269  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotNewCaptureContext"));
270  }
271  securityContext.isNewCapture = false;
272  ExecutionContext.Reader executionContextReader = Thread.CurrentThread.GetExecutionContextReader();
273  if (CurrentlyInDefaultFTSecurityContext(executionContextReader) && securityContext.IsDefaultFTSecurityContext())
274  {
275  callback(state);
276  if (GetCurrentWI(Thread.CurrentThread.GetExecutionContextReader()) != null)
277  {
278  WindowsIdentity.SafeRevertToSelf(ref stackMark);
279  }
280  }
281  else
282  {
283  RunInternal(securityContext, callback, state);
284  }
285  }
286 
287  [SecurityCritical]
288  internal static void RunInternal(SecurityContext securityContext, ContextCallback callBack, object state)
289  {
290  if (cleanupCode == null)
291  {
292  tryCode = runTryCode;
293  cleanupCode = runFinallyCode;
294  }
295  SecurityContextRunData userData = new SecurityContextRunData(securityContext, callBack, state);
296  RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(tryCode, cleanupCode, userData);
297  }
298 
299  [SecurityCritical]
300  internal static void runTryCode(object userData)
301  {
302  SecurityContextRunData securityContextRunData = (SecurityContextRunData)userData;
303  securityContextRunData.scsw = SetSecurityContext(securityContextRunData.sc, Thread.CurrentThread.GetExecutionContextReader().SecurityContext, modifyCurrentExecutionContext: true);
304  securityContextRunData.callBack(securityContextRunData.state);
305  }
306 
307  [SecurityCritical]
308  [PrePrepareMethod]
309  internal static void runFinallyCode(object userData, bool exceptionThrown)
310  {
311  SecurityContextRunData securityContextRunData = (SecurityContextRunData)userData;
312  securityContextRunData.scsw.Undo();
313  }
314 
315  [MethodImpl(MethodImplOptions.NoInlining)]
316  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
317  [SecurityCritical]
318  internal static SecurityContextSwitcher SetSecurityContext(SecurityContext sc, Reader prevSecurityContext, bool modifyCurrentExecutionContext)
319  {
320  StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
321  return SetSecurityContext(sc, prevSecurityContext, modifyCurrentExecutionContext, ref stackMark);
322  }
323 
324  [SecurityCritical]
325  [HandleProcessCorruptedStateExceptions]
326  internal static SecurityContextSwitcher SetSecurityContext(SecurityContext sc, Reader prevSecurityContext, bool modifyCurrentExecutionContext, ref StackCrawlMark stackMark)
327  {
328  SecurityContextDisableFlow disableFlow = sc._disableFlow;
329  sc._disableFlow = SecurityContextDisableFlow.Nothing;
330  SecurityContextSwitcher result = default(SecurityContextSwitcher);
331  result.currSC = sc;
332  result.prevSC = prevSecurityContext;
333  if (modifyCurrentExecutionContext)
334  {
335  (result.currEC = Thread.CurrentThread.GetMutableExecutionContext()).SecurityContext = sc;
336  }
337  if (sc != null)
338  {
340  try
341  {
342  result.wic = null;
343  if (!_LegacyImpersonationPolicy)
344  {
345  if (sc.WindowsIdentity != null)
346  {
347  result.wic = sc.WindowsIdentity.Impersonate(ref stackMark);
348  }
349  else if ((disableFlow & SecurityContextDisableFlow.WI) == SecurityContextDisableFlow.Nothing && prevSecurityContext.WindowsIdentity != null)
350  {
351  result.wic = WindowsIdentity.SafeRevertToSelf(ref stackMark);
352  }
353  }
354  result.cssw = CompressedStack.SetCompressedStack(sc.CompressedStack, prevSecurityContext.CompressedStack);
355  return result;
356  }
357  catch
358  {
359  result.UndoNoThrow();
360  throw;
361  }
362  }
363  return result;
364  }
365 
369  [SecuritySafeCritical]
371  {
372  if (!isNewCapture)
373  {
374  throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotNewCaptureContext"));
375  }
376  SecurityContext securityContext = new SecurityContext();
377  securityContext.isNewCapture = true;
378  securityContext._disableFlow = _disableFlow;
379  if (WindowsIdentity != null)
380  {
381  securityContext._windowsIdentity = new WindowsIdentity(WindowsIdentity.AccessToken);
382  }
383  if (_compressedStack != null)
384  {
385  securityContext._compressedStack = _compressedStack.CreateCopy();
386  }
387  return securityContext;
388  }
389 
390  [SecuritySafeCritical]
391  internal SecurityContext CreateMutableCopy()
392  {
393  SecurityContext securityContext = new SecurityContext();
394  securityContext._disableFlow = _disableFlow;
395  if (WindowsIdentity != null)
396  {
397  securityContext._windowsIdentity = new WindowsIdentity(WindowsIdentity.AccessToken);
398  }
399  if (_compressedStack != null)
400  {
401  securityContext._compressedStack = _compressedStack.CreateCopy();
402  }
403  return securityContext;
404  }
405 
408  [MethodImpl(MethodImplOptions.NoInlining)]
409  [SecuritySafeCritical]
410  public static SecurityContext Capture()
411  {
412  if (IsFlowSuppressed())
413  {
414  return null;
415  }
416  StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller;
417  SecurityContext securityContext = Capture(Thread.CurrentThread.GetExecutionContextReader(), ref stackMark);
418  if (securityContext == null)
419  {
420  securityContext = CreateFullTrustSecurityContext();
421  }
422  return securityContext;
423  }
424 
425  [MethodImpl(MethodImplOptions.AggressiveInlining)]
426  [SecurityCritical]
427  internal static SecurityContext Capture(ExecutionContext.Reader currThreadEC, ref StackCrawlMark stackMark)
428  {
429  if (currThreadEC.SecurityContext.IsFlowSuppressed(SecurityContextDisableFlow.All))
430  {
431  return null;
432  }
433  if (CurrentlyInDefaultFTSecurityContext(currThreadEC))
434  {
435  return null;
436  }
437  return CaptureCore(currThreadEC, ref stackMark);
438  }
439 
440  [SecurityCritical]
441  private static SecurityContext CaptureCore(ExecutionContext.Reader currThreadEC, ref StackCrawlMark stackMark)
442  {
443  SecurityContext securityContext = new SecurityContext();
444  securityContext.isNewCapture = true;
446  {
447  WindowsIdentity currentWI = GetCurrentWI(currThreadEC);
448  if (currentWI != null)
449  {
450  securityContext._windowsIdentity = new WindowsIdentity(currentWI.AccessToken);
451  }
452  }
453  else
454  {
455  securityContext._disableFlow = SecurityContextDisableFlow.WI;
456  }
457  securityContext.CompressedStack = CompressedStack.GetCompressedStack(ref stackMark);
458  return securityContext;
459  }
460 
461  [SecurityCritical]
462  internal static SecurityContext CreateFullTrustSecurityContext()
463  {
464  SecurityContext securityContext = new SecurityContext();
465  securityContext.isNewCapture = true;
467  {
468  securityContext._disableFlow = SecurityContextDisableFlow.WI;
469  }
470  securityContext.CompressedStack = new CompressedStack(null);
471  return securityContext;
472  }
473 
474  [MethodImpl(MethodImplOptions.AggressiveInlining)]
475  [SecurityCritical]
476  internal static WindowsIdentity GetCurrentWI(ExecutionContext.Reader threadEC)
477  {
478  return GetCurrentWI(threadEC, _alwaysFlowImpersonationPolicy);
479  }
480 
481  [MethodImpl(MethodImplOptions.AggressiveInlining)]
482  [SecurityCritical]
483  internal static WindowsIdentity GetCurrentWI(ExecutionContext.Reader threadEC, bool cachedAlwaysFlowImpersonationPolicy)
484  {
485  if (cachedAlwaysFlowImpersonationPolicy)
486  {
487  return WindowsIdentity.GetCurrentInternal(TokenAccessLevels.MaximumAllowed, threadOnly: true);
488  }
489  return threadEC.SecurityContext.WindowsIdentity;
490  }
491 
492  [SecurityCritical]
493  internal static void RestoreCurrentWI(ExecutionContext.Reader currentEC, ExecutionContext.Reader prevEC, WindowsIdentity targetWI, bool cachedAlwaysFlowImpersonationPolicy)
494  {
495  if (cachedAlwaysFlowImpersonationPolicy || prevEC.SecurityContext.WindowsIdentity != targetWI)
496  {
497  RestoreCurrentWIInternal(targetWI);
498  }
499  }
500 
501  [SecurityCritical]
502  private static void RestoreCurrentWIInternal(WindowsIdentity targetWI)
503  {
504  int num = Win32.RevertToSelf();
505  if (num < 0)
506  {
507  Environment.FailFast(Win32Native.GetMessage(num));
508  }
509  if (targetWI == null)
510  {
511  return;
512  }
513  SafeAccessTokenHandle accessToken = targetWI.AccessToken;
514  if (accessToken != null && !accessToken.IsInvalid)
515  {
516  num = Win32.ImpersonateLoggedOnUser(accessToken);
517  if (num < 0)
518  {
519  Environment.FailFast(Win32Native.GetMessage(num));
520  }
521  }
522  }
523 
524  [SecurityCritical]
525  internal bool IsDefaultFTSecurityContext()
526  {
527  if (WindowsIdentity == null)
528  {
529  if (CompressedStack != null)
530  {
531  return CompressedStack.CompressedStackHandle == null;
532  }
533  return true;
534  }
535  return false;
536  }
537 
538  [MethodImpl(MethodImplOptions.AggressiveInlining)]
539  [SecurityCritical]
540  internal static bool CurrentlyInDefaultFTSecurityContext(ExecutionContext.Reader threadEC)
541  {
542  if (IsDefaultThreadSecurityInfo())
543  {
544  return GetCurrentWI(threadEC) == null;
545  }
546  return false;
547  }
548 
549  [MethodImpl(MethodImplOptions.InternalCall)]
550  [SecuritySafeCritical]
551  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
552  internal static extern WindowsImpersonationFlowMode GetImpersonationFlowMode();
553 
554  [MethodImpl(MethodImplOptions.InternalCall)]
555  [SecurityCritical]
556  [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
557  internal static extern bool IsDefaultThreadSecurityInfo();
558  }
559 }
static Thread CurrentThread
Gets the currently running thread.
Definition: Thread.cs:134
static void RestoreFlow()
Restores the flow of the security context across asynchronous threads.
delegate void TryCode(object userData)
Represents a delegate to code that should be run in a try block..
static bool IsWindowsIdentityFlowSuppressed()
Determines whether the flow of the Windows identity portion of the current security context has been ...
delegate void ContextCallback(object state)
Represents a method to be called within a new context.
static void ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, object userData)
Executes code using a T:System.Delegate while using another T:System.Delegate to execute additional c...
Provides a mechanism for releasing unmanaged resources.To browse the .NET Framework source code for t...
Definition: IDisposable.cs:8
Definition: __Canon.cs:3
static AsyncFlowControl SuppressFlow()
Suppresses the flow of the security context across asynchronous threads.
Encapsulates and propagates all security-related data for execution contexts transferred across threa...
static AsyncFlowControl SuppressFlowWindowsIdentity()
Suppresses the flow of the Windows identity portion of the current security context across asynchrono...
Provides the functionality to restore the migration, or flow, of the execution context between thread...
Cer
Specifies a method's behavior when called within a constrained execution region.
Definition: Cer.cs:5
SecurityContext CreateCopy()
Creates a copy of the current security context.
static CompressedStack GetCompressedStack()
Gets the compressed stack for the current thread.
Provides information about, and means to manipulate, the current environment and platform....
Definition: Environment.cs:21
Manages the execution context for the current thread. This class cannot be inherited.
static SecurityContext Capture()
Captures the security context for the current thread.
static void PrepareConstrainedRegions()
Designates a body of code as a constrained execution region (CER).
static bool IsFlowSuppressed()
Determines whether the flow of the security context has been suppressed.
SafeAccessTokenHandle AccessToken
Gets this T:Microsoft.Win32.SafeHandles.SafeAccessTokenHandle for this T:System.Security....
MethodImplOptions
Defines the details of how a method is implemented.
static void Run(SecurityContext securityContext, ContextCallback callback, object state)
Runs the specified method in the specified security context on the current thread.
delegate void CleanupCode(object userData, bool exceptionThrown)
Represents a method to run when an exception occurs.
Provides methods for setting and capturing the compressed stack on the current thread....
The exception that is thrown when a method call is invalid for the object's current state.
Consistency
Specifies a reliability contract.
Definition: Consistency.cs:5
void Dispose()
Releases all resources used by the current instance of the T:System.Security.SecurityContext class.
TokenAccessLevels
Defines the privileges of the user account associated with the access token.
virtual void Dispose(bool disposing)
Releases the unmanaged resources used by the T:System.Security.Principal.WindowsIdentity and optional...
CompressedStack CreateCopy()
Creates a copy of the current compressed stack.
Provides a set of static methods and properties that provide support for compilers....
Creates and controls a thread, sets its priority, and gets its status.
Definition: Thread.cs:18