1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 //
5 // ==--==
6 // <OWNER>Microsoft</OWNER>
7 //
8 
9 //
10 // WindowsImpersonationContext.cs
11 //
12 // Representation of an impersonation context.
13 //
14 
15 namespace System.Security.Principal
16 {
17     using Microsoft.Win32;
18     using Microsoft.Win32.SafeHandles;
19     using System.Runtime.InteropServices;
20 #if FEATURE_CORRUPTING_EXCEPTIONS
21     using System.Runtime.ExceptionServices;
22 #endif // FEATURE_CORRUPTING_EXCEPTIONS
23     using System.Security.Permissions;
24     using System.Runtime.ConstrainedExecution;
25     using System.Runtime.Versioning;
26     using System.Diagnostics.Contracts;
27 
28     [System.Runtime.InteropServices.ComVisible(true)]
29     public class WindowsImpersonationContext : IDisposable {
30         [System.Security.SecurityCritical] // auto-generated
31         private SafeAccessTokenHandle m_safeTokenHandle = SafeAccessTokenHandle.InvalidHandle;
32         private WindowsIdentity m_wi;
33         private FrameSecurityDescriptor m_fsd;
34 
35         [System.Security.SecurityCritical]  // auto-generated
WindowsImpersonationContext()36         private WindowsImpersonationContext () {}
37 
38         [System.Security.SecurityCritical]  // auto-generated
39         [ResourceExposure(ResourceScope.None)]
40         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
WindowsImpersonationContext(SafeAccessTokenHandle safeTokenHandle, WindowsIdentity wi, bool isImpersonating, FrameSecurityDescriptor fsd)41         internal WindowsImpersonationContext (SafeAccessTokenHandle safeTokenHandle, WindowsIdentity wi, bool isImpersonating, FrameSecurityDescriptor fsd) {
42             if (safeTokenHandle.IsInvalid)
43                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidImpersonationToken"));
44             Contract.EndContractBlock();
45 
46             if (isImpersonating) {
47                 if (!Win32Native.DuplicateHandle(Win32Native.GetCurrentProcess(),
48                                                  safeTokenHandle,
49                                                  Win32Native.GetCurrentProcess(),
50                                                  ref m_safeTokenHandle,
51                                                  0,
52                                                  true,
53                                                  Win32Native.DUPLICATE_SAME_ACCESS))
54                     throw new SecurityException(Win32Native.GetMessage(Marshal.GetLastWin32Error()));
55                 m_wi = wi;
56             }
57             m_fsd = fsd;
58         }
59 
60         // Revert to previous impersonation (the only public method).
61         [System.Security.SecuritySafeCritical]  // auto-generated
62         [ResourceExposure(ResourceScope.None)]
63         [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
Undo()64         public void Undo () {
65             int hr = 0;
66             if (m_safeTokenHandle.IsInvalid) { // the thread was not initially impersonating
67                 hr = Win32.RevertToSelf();
68                 if (hr < 0)
69                     Environment.FailFast(Win32Native.GetMessage(hr));
70             } else {
71                 hr = Win32.RevertToSelf();
72                 if (hr < 0)
73                     Environment.FailFast(Win32Native.GetMessage(hr));
74                 hr = Win32.ImpersonateLoggedOnUser(m_safeTokenHandle);
75                 if (hr < 0)
76                     throw new SecurityException(Win32Native.GetMessage(hr));
77             }
78             WindowsIdentity.UpdateThreadWI(m_wi);
79             if (m_fsd != null)
80                 m_fsd.SetTokenHandles(null, null);
81         }
82 
83         // Non-throwing version that does not new any exception objects. To be called when reliability matters
84         [System.Security.SecurityCritical]  // auto-generated
85         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
86         [ResourceExposure(ResourceScope.None)]
87         [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
88 #if FEATURE_CORRUPTING_EXCEPTIONS
89         [HandleProcessCorruptedStateExceptions] //
90 #endif // FEATURE_CORRUPTING_EXCEPTIONS
UndoNoThrow()91         internal bool UndoNoThrow()
92         {
93             bool bRet = false;
94             try{
95                 int hr = 0;
96                 if (m_safeTokenHandle.IsInvalid)
97                 { // the thread was not initially impersonating
98                     hr = Win32.RevertToSelf();
99                     if (hr < 0)
100                         Environment.FailFast(Win32Native.GetMessage(hr));
101                 }
102                 else
103                 {
104                     hr = Win32.RevertToSelf();
105                     if (hr >= 0)
106                     {
107                         hr = Win32.ImpersonateLoggedOnUser(m_safeTokenHandle);
108                     }
109                     else
110                     {
111                         Environment.FailFast(Win32Native.GetMessage(hr));
112                     }
113                 }
114                 bRet = (hr >= 0);
115                 if (m_fsd != null)
116                     m_fsd.SetTokenHandles(null,null);
117             }
118             catch
119             {
120                 bRet = false;
121             }
122             return bRet;
123         }
124 
125         //
126         // IDisposable interface.
127         //
128 
129         [System.Security.SecuritySafeCritical]  // auto-generated
130         [ComVisible(false)]
Dispose(bool disposing)131         protected virtual void Dispose(bool disposing) {
132             if (disposing) {
133                 if (m_safeTokenHandle != null && !m_safeTokenHandle.IsClosed) {
134                     Undo();
135                     m_safeTokenHandle.Dispose();
136                 }
137             }
138         }
139 
140         [ComVisible(false)]
Dispose()141         public void Dispose () {
142             Dispose(true);
143         }
144     }
145 }
146