Skip to main content
Email Password   helpLost your password?

Impersonation

Introduction

I've been a member of the CodeProject for over 3 years now, and still haven't contributed any articles - until now.

While designing a Windows Forms-based application, to administrate containers in our Active Directory, I needed a way to allow binding to the AD using alternate credentials. Windows impersonation was the answer. This sample app demonstrates how to use unmanaged code by calling LogonUser() contained within the advapi32.dll, and pass a token handle back to your .NET application using WindowsImpersonationContext.

One of the downfalls to the LogonUser()function is that the password get passed in clear-text.

Partial Source Code

using System.Runtime.InteropServices; // DllImport

using System.Security.Principal; // WindowsImpersonationContext

using System.Security.Permissions; // PermissionSetAttribute

...

public WindowsImpersonationContext 
    ImpersonateUser(string sUsername, string sDomain, string sPassword)
{
    // initialize tokens

    IntPtr pExistingTokenHandle = new IntPtr(0);
    IntPtr pDuplicateTokenHandle = new IntPtr(0);
    pExistingTokenHandle = IntPtr.Zero;
    pDuplicateTokenHandle = IntPtr.Zero;
    
    // if domain name was blank, assume local machine

    if (sDomain == "")
        sDomain = System.Environment.MachineName;

    try
    {
        string sResult = null;

        const int LOGON32_PROVIDER_DEFAULT = 0;

        // create token

        const int LOGON32_LOGON_INTERACTIVE = 2;
        //const int SecurityImpersonation = 2;


        // get handle to token

        bool bImpersonated = LogonUser(sUsername, sDomain, sPassword, 
            LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, 
                ref pExistingTokenHandle);

        // did impersonation fail?

        if (false == bImpersonated)
        {
            int nErrorCode = Marshal.GetLastWin32Error();
            sResult = "LogonUser() failed with error code: " + 
                nErrorCode + "\r\n";

            // show the reason why LogonUser failed

            MessageBox.Show(this, sResult, "Error", 
                MessageBoxButtons.OK, MessageBoxIcon.Error);
        }

        // Get identity before impersonation

        sResult += "Before impersonation: " + 
            WindowsIdentity.GetCurrent().Name + "\r\n";

        bool bRetVal = DuplicateToken(pExistingTokenHandle, 
            (int)SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, 
                ref pDuplicateTokenHandle);

        // did DuplicateToken fail?

        if (false == bRetVal)
        {
            int nErrorCode = Marshal.GetLastWin32Error();
            // close existing handle

            CloseHandle(pExistingTokenHandle); 
            sResult += "DuplicateToken() failed with error code: " 
                + nErrorCode + "\r\n";

            // show the reason why DuplicateToken failed

            MessageBox.Show(this, sResult, "Error", 
                MessageBoxButtons.OK, MessageBoxIcon.Error);
            return null;
        }
        else
        {
            // create new identity using new primary token

            WindowsIdentity newId = new WindowsIdentity
                                        (pDuplicateTokenHandle);
            WindowsImpersonationContext impersonatedUser = 
                                        newId.Impersonate();

            // check the identity after impersonation

            sResult += "After impersonation: " + 
                WindowsIdentity.GetCurrent().Name + "\r\n";
            
            MessageBox.Show(this, sResult, "Success", 
                MessageBoxButtons.OK, MessageBoxIcon.Information);
            return impersonatedUser;
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
    finally
    {
        // close handle(s)

        if (pExistingTokenHandle != IntPtr.Zero)
            CloseHandle(pExistingTokenHandle);
        if (pDuplicateTokenHandle != IntPtr.Zero) 
            CloseHandle(pDuplicateTokenHandle);
    }
}

Points of Interest

This code won't work on Windows 98 or ME because they do not utilize user tokens. Code was built and run using Visual Studio.NET 2002 on Windows XP Service Pack 1.

One of the other uses for this code I've found is, for instantiating COM components that must run in an alternate security context to that of the logged-on user.

If anyone has a more secure method of achieving the same thing, please let me know.

History

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralWindows 2008 server Pin
smithafebinkal
19:45 3 Dec '08  
GeneralThis process not working with a WPF application!!! Pin
Arshad Kunnath
2:36 31 Jul '08  
GeneralRe: This process not working with a WPF application!!! Pin
Marc Merritt
3:59 31 Jul '08  
QuestionIt may be.... Pin
Willian.BR
9:55 15 May '08  
GeneralWindows CE .net Pin
questions_c
3:28 1 Oct '07  
GeneralRe: Windows CE .net Pin
Marc Merritt
16:18 1 Oct '07  
GeneralRe: Windows CE .net Pin
Pram_Singh41
5:22 20 Jul '09  
GeneralError Code 1326 [modified] Pin
collapo
1:56 21 Aug '07  
GeneralRe: Error Code 1326 Pin
mirh
2:59 10 Oct '07  
GeneralError 1314 Pin
m.aldegheri
7:28 3 Aug '06  
GeneralRe: Error 1314 Pin
m.aldegheri
23:23 3 Aug '06  
GeneralRe: Error 1314 Pin
MunkieFish
8:49 11 Apr '07  
AnswerRe: Error 1314 Pin
uppals
14:06 12 Apr '07  
GeneralHelp needed Windows 2000 SP4 still getting 1314! -- Re: Error 1314 Pin
devvvy
21:41 21 Feb '08  
GeneralRe: Help needed Windows 2000 SP4 still getting 1314! -- Re: Error 1314 Pin
Marc Merritt
4:02 26 Feb '08  
Generalhow to use this in case of a local account? Pin
yossof elnaggar
21:29 27 Jun '06  
GeneralRe: how to use this in case of a local account? Pin
hk11
20:04 12 Jul '07  
GeneralFirst call takes too long Pin
schweeneh
7:04 4 Apr '06  
GeneralRe: First call takes too long Pin
Marc Merritt
3:24 12 Jun '06  
GeneralA similar article Pin
Uwe Keim
0:59 24 Apr '05  
GeneralRe: A similar article Pin
craigg75
6:57 3 Nov '06  
GeneralRe: A similar article Pin
Uwe Keim
7:14 3 Nov '06  
GeneralImpersonation Pin
chriskoiak
6:13 16 Mar '04  
QuestionRe: Impersonation Pin
tee_jay
23:08 10 Apr '06  
AnswerRe: Impersonation Pin
hk11
20:01 12 Jul '07  


Last Updated 29 Apr 2003 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2009