Last active
July 12, 2021 02:29
-
-
Save iamandycohen/5020348 to your computer and use it in GitHub Desktop.
Impersonation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.ComponentModel; | |
using System.Runtime.InteropServices; | |
using System.Security.Permissions; | |
using System.Security.Principal; | |
public class UserImpersonator : IDisposable | |
{ | |
[DllImport("advapi32.dll", SetLastError = true)] | |
private static extern int LogonUser( | |
string lpszUserName, | |
string lpszDomain, | |
string lpszPassword, | |
int dwLogonType, | |
int dwLogonProvider, | |
ref IntPtr phToken); | |
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] | |
private static extern int DuplicateToken( | |
IntPtr hToken, | |
int impersonationLevel, | |
ref IntPtr hNewToken); | |
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] | |
private static extern bool RevertToSelf(); | |
[DllImport("kernel32.dll", CharSet = CharSet.Auto)] | |
private static extern bool CloseHandle( | |
IntPtr handle); | |
private const int LOGON32_LOGON_INTERACTIVE = 2; | |
private const int LOGON32_PROVIDER_DEFAULT = 0; | |
enum LogonType | |
{ | |
Interactive = 2, | |
Network = 3, | |
Batch = 4, | |
Service = 5, | |
Unlock = 7, | |
NetworkClearText = 8, | |
NewCredentials = 9 | |
} | |
enum LogonProvider | |
{ | |
Default = 0, | |
WinNT35 = 1, | |
WinNT40 = 2, | |
WinNT50 = 3 | |
} | |
// If you incorporate this code into a DLL, be sure to demand that it | |
// runs with FullTrust. | |
public UserImpersonator(string userPrincipalName, string password) | |
{ | |
var spn = userPrincipalName.Split('@'); | |
string userName = spn[0]; | |
string domainName = spn[1]; | |
Impersonate(domainName, userName, password); | |
} | |
public UserImpersonator(string domainName, string userName, string password) | |
{ | |
Impersonate(domainName, userName, password); | |
} | |
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")] | |
public void Impersonate(string domainName, string userName, string password) | |
{ | |
WindowsIdentity tempWindowsIdentity = null; | |
IntPtr token = IntPtr.Zero; | |
IntPtr tokenDuplicate = IntPtr.Zero; | |
try | |
{ | |
if (RevertToSelf()) | |
{ | |
if (LogonUser( | |
userName, | |
domainName, | |
password, | |
//(int)LogonType.NewCredentials, | |
//(int)LogonProvider.WinNT50, | |
(int)LogonType.Interactive, | |
(int)LogonProvider.Default, | |
//LOGON32_LOGON_INTERACTIVE, | |
//LOGON32_PROVIDER_DEFAULT, | |
ref token) != 0) | |
{ | |
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0) | |
{ | |
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate); | |
impersonationContext = tempWindowsIdentity.Impersonate(); | |
} | |
else | |
{ | |
throw new Win32Exception(Marshal.GetLastWin32Error()); | |
} | |
} | |
else | |
{ | |
throw new Win32Exception(Marshal.GetLastWin32Error()); | |
} | |
} | |
else | |
{ | |
throw new Win32Exception(Marshal.GetLastWin32Error()); | |
} | |
} | |
finally | |
{ | |
if (token != IntPtr.Zero) | |
{ | |
CloseHandle(token); | |
} | |
if (tokenDuplicate != IntPtr.Zero) | |
{ | |
CloseHandle(tokenDuplicate); | |
} | |
} | |
} | |
/// | |
/// Reverts the impersonation. | |
/// | |
private void UndoImpersonation() | |
{ | |
if (impersonationContext != null) | |
{ | |
impersonationContext.Undo(); | |
} | |
} | |
private WindowsImpersonationContext impersonationContext = null; | |
// Stops impersonation | |
public void Dispose() | |
{ | |
UndoImpersonation(); | |
} | |
} | |
public interface IElevatedUser : IDisposable | |
{ | |
IElevatedUser Impersonate(); | |
IElevatedUser Impersonate(string account, string password); | |
string Account | |
{ | |
get; | |
set; | |
} | |
string Password | |
{ | |
get; | |
set; | |
} | |
} | |
public class ElevatedUser : IElevatedUser | |
{ | |
private UserImpersonator impersonator; | |
public ElevatedUser() | |
{ | |
} | |
public IElevatedUser Impersonate() | |
{ | |
return Impersonate(Account, Password); | |
} | |
public IElevatedUser Impersonate(string account, string password) | |
{ | |
if (account == null) | |
{ | |
throw new ArgumentNullException("account", "Account not set."); | |
} | |
if (password == null) | |
{ | |
throw new ArgumentNullException("password", "Password not set."); | |
} | |
this.impersonator = new UserImpersonator(account, password); | |
return this; | |
} | |
public void Dispose() | |
{ | |
impersonator.Dispose(); | |
} | |
public string Account | |
{ | |
get; | |
set; | |
} | |
public string Password | |
{ | |
get; | |
set; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment