I'm trying to test an ASP.NET MVC4 web application connecting with different users at the same time using impersonation. So, the idea for the test was to execute several instances of the driver each with a different impersonated user. It sounds conceptually easy...
However, if after calling LogonUser with a different user from the current, you run the IEDriverServer, an application fault dialog is displayed when it is starting. This is the information registered in the EventLog:
Faulting application name: IEDriverServer.exe, version: 2.44.0.0, time stamp: 0x54496690
Faulting module name: IED7543.tmp, version: 0.0.0.0, time stamp: 0x5449668c
Exception code: 0xc0000005
Fault offset: 0x000000000009d609
Faulting process id: 0x760
Faulting application start time: 0x01d00e3d12f93475
Faulting application path: ...\bin\IEDriverServer.exe
Faulting module path: C:\Users\user\AppData\Local\Temp\IED7543.tmp
Report Id: 5383a54d-7a30-11e4-b39c-000c29b46927
Here is the code I'm using for impersonation. It is based in all the examples I have found, so I there are not surprises... We also tried to used the SimpleImpersonation packege with the same result:
public class ImpersonationHelper
{
public enum LogonType
{
Interactive = 2,
Network = 3,
Batch = 4,
Service = 5,
Unlock = 7,
Cleartext = 8, // Win2K or higher
NewCredentials = 9 // Win2K or higher
};
public enum LogonProvider
{
Default = 0,
Winnt35 = 1,
Winnt40 = 2,
Winnt50 = 3
};
public enum ImpersonationLevel
{
SecurityAnonymous = 0,
SecurityIdentification = 1,
SecurityImpersonation = 2,
SecurityDelegation = 3
}
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, out IntPtr phToken);
[DllImport("kernel32.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr handle);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel, ref IntPtr hNewToken);
public sealed class Impersonator : IDisposable
{
public string Domain { get; private set; }
public string User { get; private set; }
public string Password { get; private set; }
public LogonType Type { get; private set; }
public LogonProvider Provider { get; private set; }
private WindowsImpersonationContext _context;
private IntPtr _token;
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public Impersonator(string domain, string user, string password,
LogonType type = LogonType.Interactive,
LogonProvider provider = LogonProvider.Default)
{
Domain = domain;
User = user;
Password = password;
Type = type;
Provider = provider;
_token = IntPtr.Zero;
Logon();
}
public void Dispose()
{
Undo();
}
private void Logon()
{
try
{
if (!LogonUser(User, Domain, Password, (int)Type, (int)Provider, out _token))
{
int ret = Marshal.GetLastWin32Error();
throw new Exception(String.Format("LogonUser failed with error code : {0}", ret));
}
_context = WindowsIdentity.Impersonate(_token);
}
catch (Exception exception)
{
var message = exception.Message;
Undo();
}
}
private void Undo()
{
try
{
if (_token != IntPtr.Zero)
{
CloseHandle(_token);
_token = IntPtr.Zero; // Clean _token so Undo() could be called several times
}
if (_context != null)
{
_context.Undo();
_context = null; // Clean _context so Undo() could be called several times
}
}
catch (Exception exception)
{
var message = exception.Message;
// Releasing resources failed...
}
}
}
}
The code that raises the exception is:
using (new ImpersonationHelper.Impersonator("WIN-NKLTTMMUEPD", "tester", "tester"))
{
using (IWebDriver driver = new InternetExplorerDriver())
{
driver.Url = _appAddress;
return null;
}
}
Does anybody know how can I prevent this error from appearing? Thank you very much in advance.