My application had a WindowsIdentity crisis
Posted
by Brian Donahue
on Simple Talk
See other posts from Simple Talk
or by Brian Donahue
Published on Thu, 17 Mar 2011 17:20:00 GMT
Indexed on
2011/03/18
0:16 UTC
Read the original article
Hit count: 229
Filed under:
The project I have been working on this week to test computer environments needs to do various actions as a user other than the one running the application. For instance, it looks up an installed Windows Service, finds out who the startup user is, and tries to connect to a database as that Windows user.
Later on, it will need to access a file in the context of the currently logged-in user.
With ASP .NET, this is super-easy: just go into Web.Config and set up the "identity impersonate" node, which can either impersonate a named user or the one who had logged into the website if authentication was enabled. With Windows applications, this is not so straightforward.
There may be something I am overlooking, but the limitation seems to be that you can only change the security context on the current thread: any threads spawned by the impersonated thread also inherit the impersonated credentials. Impersonation is easy enough to do, once you figure out how.
Here is my code for impersonating a user on the current thread:
- using System;
- using System.ComponentModel;
- using System.Runtime.InteropServices;
- using System.Security.Principal;
- public class ImpersonateUser
- {
- IntPtr userHandle;
- [DllImport("advapi32.dll", SetLastError = true)]
- static extern bool LogonUser(
- string lpszUsername,
- string lpszDomain,
- string lpszPassword,
- LogonType dwLogonType,
- LogonProvider dwLogonProvider,
- out IntPtr phToken
- );
- [DllImport("kernel32.dll", SetLastError = true)]
- static extern bool CloseHandle(IntPtr hHandle);
- enum LogonType : int
- {
- Interactive = 2,
- Network = 3,
- Batch = 4,
- Service = 5,
- NetworkCleartext = 8,
- NewCredentials = 9,
- }
- enum LogonProvider : int
- {
- Default = 0,
- }
- public static WindowsImpersonationContext Impersonate(string user, string domain, string password)
- {
- IntPtr userHandle = IntPtr.Zero;
- bool loggedOn = LogonUser(
- user,
- domain,
- password,
- LogonType.Interactive,
- LogonProvider.Default,
- out userHandle);
- if (!loggedOn)
- throw new Win32Exception(Marshal.GetLastWin32Error());
- WindowsIdentity identity = new WindowsIdentity(userHandle);
- WindowsPrincipal principal = new WindowsPrincipal(identity);
- System.Threading.Thread.CurrentPrincipal = principal;
- return identity.Impersonate();
- }
- }
- /* Call impersonation */
- ImpersonateUser.Impersonate("UserName","DomainName","Password");
- /* When you want to go back to the original user */
- WindowsIdentity.Impersonate(IntPtr.Zero);
© Simple Talk or respective owner