10

I have found some sample code on codeproject that allows for user impersonation.

This code works by importing the following unmanaged Win32 API functions:

[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);

These functions are used to impersonate the target user, then perform some operations, then revert the impersonation context. Impersonating the user is achieved like so:

if ( LogonUser(userName, domainName, password, LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT, ref token ) != 0 )
{
    if ( DuplicateToken( token, 2, ref tokenDuplicate ) != 0 )
    {
        tempWindowsIdentity = new WindowsIdentity( tokenDuplicate );
        impersonationContext = tempWindowsIdentity.Impersonate();
    }
}

I'm trying to understand why this code first gets the required token using LogonUser, then duplicates that token, before performing the impersonation on the duplicated token. Why not just impersonate using the token that you get from the LogonUser method.

Obviously the person that wrote this article understands this better than I do so it would appear that I am missing something. Could I please get an explanation of why the seemingly redundant token duplication step of this process is required?

joce
  • 9,624
  • 19
  • 56
  • 74
Sean Hunter
  • 1,041
  • 8
  • 19

1 Answers1

9

As far as I know, token, passed to WindowsIdentity ctor should be an impersonation token. So, the author of that code using

DuplicateToken( token, 2, ref tokenDuplicate )

to create an impersonation token from primary token, returned by LogonUser(). That '2' magic number stands for SecurityImpersonation member of SECURITY_IMPERSONATION_LEVEL enum.

Links:

http://msdn.microsoft.com/en-us/library/aa378184%28v=vs.85%29.aspx

http://msdn.microsoft.com/en-us/library/aa379572%28v=vs.85%29.aspx

http://msdn.microsoft.com/en-us/library/aa446616%28v=vs.85%29.aspx

torvin
  • 6,515
  • 1
  • 37
  • 52
  • Hi Torvin, thanks for the response. That does make sense and I was thinking along those lines as well until I read this information in the "LogonUser" method documentation. "You can then use this token handle to impersonate the specified user or, in most cases, to create a process that runs in the context of the specified user." The reference for this is here http://msdn.microsoft.com/en-us/library/aa378184%28VS.85%29.aspx. So if this already allows for the impersonation, why would the duplication part be required? – Sean Hunter May 15 '11 at 07:10
  • Hmm, good question :) That code is buggy anyway: it never disposes created WindowsIdentity nor calls CloseHandle() on obtained tokens, thus leaking kernel handles. – torvin May 15 '11 at 08:07
  • Thanks Torvin, I do realize that though. The code I provided is only the relevant snippet from the article :D. Appreciate your thoughts and have voted you up. – Sean Hunter May 15 '11 at 09:12
  • I also found this piece of [code](http://msdn.microsoft.com/en-us/library/w070t6ka.aspx). It basically does the same, but without `DuplicateHandle`, so I guess it's not needed. – torvin May 18 '11 at 09:35
  • Thanks torvin, I guess I can safely mark that part down as redundant then. -- Cheers – Sean Hunter May 18 '11 at 12:17