using System; using System.Runtime.InteropServices; using System.Security.Principal; namespace Core.Security { /// /// Impersonates a windows user within the context of a disposable pattern: /// /// using(ImpersonationContext context = ImpersonationContext.ImpersonateUser("Joe","MyDomain","MyPasswrd")) { /// //Do stuff under impersonated user credentials /// } /// /// public class ImpersonationContext:IDisposable { public static ImpersonationContext ImpersonateUser(String userName,String domain,String password) { var context = new ImpersonationContext(); if(context.ImpersonateValidUser(userName,domain,password)) { return context; } return null; } WindowsImpersonationContext _impersonationContext; bool _impersonating; ImpersonationContext() { } const int LOGON32_LOGON_INTERACTIVE = 2; const int LOGON32_PROVIDER_DEFAULT = 0; [DllImport("advapi32.dll")] static extern int LogonUserA(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("advapi32.dll",CharSet = CharSet.Auto,SetLastError = true)] static extern int DuplicateToken(IntPtr hToken, int impersonationLevel, ref IntPtr hNewToken); [DllImport("advapi32.dll",CharSet = CharSet.Auto,SetLastError = true)] static extern bool RevertToSelf(); [DllImport("kernel32.dll",CharSet = CharSet.Auto)] static extern bool CloseHandle(IntPtr handle); bool ImpersonateValidUser(String userName,String domain,String password) { _impersonating = false; WindowsIdentity tempWindowsIdentity; IntPtr token = IntPtr.Zero; IntPtr tokenDuplicate = IntPtr.Zero; if(RevertToSelf()) { if(LogonUserA(userName,domain,password,LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,ref token) != 0) { if(DuplicateToken(token,2,ref tokenDuplicate) != 0) { tempWindowsIdentity = new WindowsIdentity(tokenDuplicate); _impersonationContext = tempWindowsIdentity.Impersonate(); if(_impersonationContext != null) { CloseHandle(token); CloseHandle(tokenDuplicate); _impersonating = true; return true; } } } } if(token != IntPtr.Zero) CloseHandle(token); if(tokenDuplicate != IntPtr.Zero) CloseHandle(tokenDuplicate); return false; } void UndoImpersonation() { if(_impersonationContext == null) return; _impersonationContext.Undo(); } #region IDisposable Pattern protected bool IsDisposed { get; private set; } protected void EnsureNotDisposed() { if(IsDisposed) throw new ObjectDisposedException(GetType().Name); } public virtual void Dispose() { if(IsDisposed) throw new ObjectDisposedException(this.GetType().Name); try { this.Dispose(true); } finally { GC.SuppressFinalize(this); } } protected virtual void Dispose(bool disposing) { if(disposing) { try { if(!IsDisposed) { if(_impersonating) UndoImpersonation(); } } finally { IsDisposed = true; } } } //Only add Finalizer in you need to dispose of resources with out call Dispose() directly ~ImpersonationContext() { Dispose(!IsDisposed); } #endregion } }