if using code like the following to impersonate another user,
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool
LogonUser(string lpszUsername, string lpszDomain,
string lpszPassword, int dwLogonType,
int dwLogonProvider, ref IntPtr phToken);
var handle = IntPtr.Zero;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_PROVIDER_DEFAULT = 0;
const int SecurityImpersonation = 2;
LogonUser(username, domain,
password, LOGON32_LOGON_NETWORK,
LOGON32_PROVIDER_DEFAULT, ref handle))
on two different concurrent threads, will they interfere with one another? I.e., is the currently logged-on user associated with the thread, or with the host process ??
EDIT: Addition...
I am using the logon handle to create a WindowsImpersonationContext object, as a private state field in an instance of a type I named "Impersonator" (code below). So, since this WindowsImpersonationContext object is a local provate field in an imnstance of thos type, and a new instance of this type is created each time I wanto impersonate some set of credentials, I can assume that this WindowsImpersonationContext is what is being used to perform all ACL validations during execution of code within a block such as
using (Impersonator.Impersonate(userId, domain, password))
{
// code I want to execute using supplied credentials
}
What has me concerned is the statement on the msdn page WindowsImpersonationContext that says: "Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe."
Impersonator
class:
public class Impersonator: IDisposable
{
#region Declarations
private readonly string username;
private readonly string password;
private readonly string domain;
// this will hold the security context
// for reverting back to the client after
// impersonation operations are complete
private WindowsImpersonationContext impersonationContext;
#endregion Declarations
#region Constructors
public Impersonator(string UserName,
string Domain, string Password)
{
username = UserName;
domain = Domain;
password = Password;
}
#endregion Constructors
#region Public Methods
public static Impersonator Impersonate(
string userName, string domain, string password)
{
var imp = new Impersonator(userName, domain, password);
imp.Impersonate();
return imp;
}
public void Impersonate()
{ impersonationContext = Logon().Impersonate(); }
public void Undo() { impersonationContext.Undo(); }
#endregion Public Methods
#region Private Methods
private WindowsIdentity Logon()
{
var handle = IntPtr.Zero;
const int LOGON32_LOGON_NETWORK = 3;
const int LOGON32_PROVIDER_DEFAULT = 0;
const int SecurityImpersonation = 2;
// attempt to authenticate domain user account
try
{
if (!LogonUser(username, domain,
password, LOGON32_LOGON_NETWORK,
LOGON32_PROVIDER_DEFAULT, ref handle))
throw new LogonException(
"User logon failed. Error Number: " +
Marshal.GetLastWin32Error());
// ----------------------------------
var dupHandle = IntPtr.Zero;
if (!DuplicateToken(handle,
SecurityImpersonation,
ref dupHandle))
throw new LogonException(
"Logon failed attemting to duplicate handle");
// Logon Succeeded ! return new WindowsIdentity instance
return (new WindowsIdentity(handle));
}
// close the open handle to the authenticated account
finally { CloseHandle(handle); }
}
#region external Win32 API functions
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool
LogonUser(string lpszUsername, string lpszDomain,
string lpszPassword, int dwLogonType,
int dwLogonProvider, ref IntPtr phToken);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle);
// --------------------------------------------
[DllImport("advapi32.dll", CharSet = CharSet.Auto,
SetLastError = true)]
public static extern bool DuplicateToken(
IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL,
ref IntPtr DuplicateTokenHandle);
// --------------------------------------------
#endregion external Win32 API functions
#endregion Private Methods
#region IDisposable
private bool disposed;
public void Dispose() { Dispose(true); }
public void Dispose(bool isDisposing)
{
if (disposed) return;
if (isDisposing) Undo();
// -----------------
disposed = true;
GC.SuppressFinalize(this);
}
~Impersonator() { Dispose(false); }
#endregion IDisposable
}