While working on our new product SSW Exchange Reporter, the need to impersonate users (mostly for debugging purposes) arose. The reason being that unlike most of the other OLE providers you can’t provide login details with the connection string when trying to connect to Exchange with the ExOLEDB provider. For example an SQL connection string you can have “user=sa; password=xxx; ….” but you can’t for an ExOLE connection string. Therefore the ExOLE provider will not do any impersonation for you, it will always run under who ever is executing your application code. That is, whoever your service runs under or whoever is logged on and runs your .exe or whoever you run the .exe as using the ‘Run As…’ context menu item. Additionally the user we run under needed read permissions to all mailboxes.
Use some of the following code to do some impersonation.
Firstly make use of the windows LogonUser() function in advapi32.dll. Note that username and passwords are passed as plain text…
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_LOGON_SERVICE = 3;
public const int LOGON32_PROVIDER_DEFAULT = 0;
[DllImport(“advapi32.dll”, CharSet = CharSet.Auto)]
public static extern bool LogonUser(String lpszUserName, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
Then you can call this method to get the handle (the last parameter) for the user and use this to create a WindowsIdentity (in the System.Security.Principle namespace) and then begin impersonation with this handle.
IntPtr userHandle = new IntPtr(0); bool returnValue = LogonUser(name, machine, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref userHandle); if (! returnValue) throw new Exception("Invalid Username"); WindowsIdentity newId = new WindowsIdentity(userHandle); WindowsImpersonationContext impersonatedUser = newId.Impersonate();
You would probably wrap all this code, along with some additional verification code into a function called “BeginImpersonate“ or similar that would return both the user handle (so that you can free it later) and the impersonatedUser object so that you can end impersonation later via and “EndImpersonate“ function… End impersonation with the following code.
Free the userHandle with a call to another windows function.
[DllImport("kernel32.dll", CharSet = CharSet.Auto)] public extern static bool CloseHandle(IntPtr handle);
Better examples can be found on the MS .NET documentation on WindowsIdentity.Impersonate method, but I hope this helped a little… In this document they actually duplicate user handles that they use for impersonation, though I don’t exactly understand why… You duplicate your handles via:
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);