|
Fri
Apr 20 2007 |
Impersonate User |
/// <summary> /// Impersonate a user within the current thread. /// This class will automatically revert the user to the original user /// identity when this class is disposed. Use this class with the /// C# using or a try/catch block to ensure the user is reverted /// after an exception. /// /// Suggested usage: /// using (new ImpersonateHelper("domain", "joe", "password")) /// { /// ...code to run as joe /// } /// ...code to run as orignial user /// /// Note, this implementation is vulnerable to "exception filter" attacks /// as described below. Evaluate it against the risk of other attacks /// such as the credential store used to impersonate. /// http://blogs.msdn.com/shawnfa/archive/2005/03/22/400749.aspx /// </summary> public class ImpersonationHelper : IDisposable { IntPtr m_tokenHandle = new IntPtr(0); WindowsImpersonationContext m_impersonatedUser; #region Win32 API Declarations const int LOGON32_PROVIDER_DEFAULT = 0; const int LOGON32_LOGON_INTERACTIVE = 2; //This parameter causes LogonUser to create a primary token. [DllImport("advapi32.dll", SetLastError=true)] public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("kernel32.dll", CharSet=CharSet.Auto)] public extern static bool CloseHandle(IntPtr handle); [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle); #endregion /// <summary> /// Constructor. Impersonates the requested user. Impersonation lasts until /// the instance is disposed. /// </summary> public ImpersonationHelper(string domain, string user, string password) { // Call LogonUser to obtain a handle to an access token. bool returnValue = LogonUser(user, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref m_tokenHandle); if (false == returnValue) { int ret = Marshal.GetLastWin32Error(); throw new System.ComponentModel.Win32Exception(ret); } // Impersonate m_impersonatedUser = new WindowsIdentity(m_tokenHandle).Impersonate(); } #region IDisposable Pattern /// <summary> /// Revert to original user and cleanup. /// </summary> protected virtual void Dispose(bool disposing) { if (disposing) { // Revert to original user identity if (m_impersonatedUser != null) m_impersonatedUser.Undo(); } // Free the tokens. if (m_tokenHandle != IntPtr.Zero) CloseHandle(m_tokenHandle); } /// <summary> /// Explicit dispose. /// </summary> public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// <summary> /// Destructor /// </summary> ~ImpersonationHelper() { Dispose(false); } #endregion } |