Click here to Skip to main content
12,445,470 members (59,870 online)
Click here to Skip to main content
Add your own
alternative version

Stats

545.9K views
13.2K downloads
142 bookmarked
Posted

Windows Impersonation using C#

, 29 Apr 2003 CPOL
Rate this:
Please Sign up or sign in to vote.
An article demonstrating how to use Windows impersonation in your C# code

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

  • Version 1.0 - 04.25.03 - First release version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Marc Merritt
Architect
United States United States
I live in beautiful Arizona, USA.

You may also be interested in...

Pro
Pro

Comments and Discussions

 
QuestionSame user name before and after impersonation Pin
phoenicyan8-Oct-15 12:39
memberphoenicyan8-Oct-15 12:39 
AnswerRe: Same user name before and after impersonation Pin
Marc Merritt19-Oct-15 11:30
memberMarc Merritt19-Oct-15 11:30 
GeneralMy vote of 5 Pin
srilekhamenon1-Sep-14 2:25
membersrilekhamenon1-Sep-14 2:25 
QuestionThanks a lot, you saved 2 hrs. Pin
Member 103845676-Nov-13 8:23
memberMember 103845676-Nov-13 8:23 
AnswerRe: Thanks a lot, you saved 2 hrs. Pin
Marc Merritt12-Nov-13 8:34
memberMarc Merritt12-Nov-13 8:34 
GeneralRe: Thanks a lot, you saved 2 hrs. Pin
Oded Arbel20-Mar-14 3:04
memberOded Arbel20-Mar-14 3:04 
GeneralRe: Thanks a lot, you saved 2 hrs. Pin
Marc Merritt20-Mar-14 3:10
memberMarc Merritt20-Mar-14 3:10 
GeneralRe: Thanks a lot, you saved 2 hrs. Pin
Guss7720-Mar-14 9:47
memberGuss7720-Mar-14 9:47 
Questionsource code help Pin
Pyakaa17-Dec-12 1:43
memberPyakaa17-Dec-12 1:43 
GeneralMy vote of 5 Pin
kerkenez20004-Apr-12 23:35
memberkerkenez20004-Apr-12 23:35 
QuestionCall LogonUser Pin
Member 822764117-Sep-11 13:40
memberMember 822764117-Sep-11 13:40 
QuestionPlease I need a Help Pin
kaiserssosse11-Aug-11 1:41
memberkaiserssosse11-Aug-11 1:41 
AnswerRe: Please I need a Help Pin
diialer21-Aug-11 7:36
memberdiialer21-Aug-11 7:36 
GeneralRe: Please I need a Help Pin
kaiserssosse21-Aug-11 21:03
memberkaiserssosse21-Aug-11 21:03 
GeneralIs Windows Impersionation Thread or Process Level ? Pin
Thomas Haller27-May-11 2:42
memberThomas Haller27-May-11 2:42 
GeneralThanks Pin
olivier gg14-Feb-11 8:43
memberolivier gg14-Feb-11 8:43 
GeneralWIndows 7 Pin
moralam13-Jul-10 7:58
membermoralam13-Jul-10 7:58 
GeneralRe: WIndows 7 Pin
Marc Merritt28-Jan-13 5:25
memberMarc Merritt28-Jan-13 5:25 
QuestionCross domain impersonation Pin
atulsureka18-Apr-10 2:25
memberatulsureka18-Apr-10 2:25 
AnswerRe: Cross domain impersonation Pin
deadwood8827-Sep-10 2:00
memberdeadwood8827-Sep-10 2:00 
GeneralRe: Cross domain impersonation Pin
Cstruter26-Oct-10 21:38
memberCstruter26-Oct-10 21:38 
GeneralRe: Cross domain impersonation Pin
sabh2125-Jan-13 1:32
membersabh2125-Jan-13 1:32 
GeneralCreate a folder on a remote computer Pin
Shlomo6-Jan-10 1:52
memberShlomo6-Jan-10 1:52 
GeneralWindows 2008 server Pin
smithafebinkal3-Dec-08 18:45
membersmithafebinkal3-Dec-08 18:45 
GeneralRe: Windows 2008 server Pin
omar_chavez1-Dec-15 15:08
memberomar_chavez1-Dec-15 15:08 
GeneralThis process not working with a WPF application!!! Pin
Arshad Kunnath31-Jul-08 1:36
memberArshad Kunnath31-Jul-08 1:36 
GeneralRe: This process not working with a WPF application!!! Pin
Marc Merritt31-Jul-08 2:59
memberMarc Merritt31-Jul-08 2:59 
GeneralRe: This process not working with a WPF application!!! Pin
Matei Focseneanu12-May-10 5:15
memberMatei Focseneanu12-May-10 5:15 
GeneralRe: This process not working with a WPF application!!! Pin
Jason Jakob20-Jun-13 5:09
memberJason Jakob20-Jun-13 5:09 
QuestionIt may be.... Pin
Willian.BR15-May-08 8:55
memberWillian.BR15-May-08 8:55 
GeneralWindows CE .net Pin
questions_c1-Oct-07 2:28
memberquestions_c1-Oct-07 2:28 
GeneralRe: Windows CE .net Pin
Marc Merritt1-Oct-07 15:18
memberMarc Merritt1-Oct-07 15:18 
GeneralRe: Windows CE .net Pin
Pram_Singh4120-Jul-09 4:22
memberPram_Singh4120-Jul-09 4:22 
GeneralError Code 1326 [modified] Pin
collapo21-Aug-07 0:56
membercollapo21-Aug-07 0:56 
Hi,

I've tried to use your code, or at least some of it in my project, and I've encountered the following problem:

The code runs, impersonates finely on local computer, but when I try to impersonate a user on an other computer (e.g. "Comp" , "User", "") I get error code 1326, the domain IS "Comp", username IS "User" and there is no password on it. So I don't know the solution for my problem.
I've tried your sample application, which encountered the same.
Could you provide me some information about this?

OK, I know that if there is no passwd on the share I needn't use this code, but the use of it should not end in the result written above, or is it?

After trying I noticed, that this program impersonates on local computer, because when I've tried to impersonate an admin user on an other computer, which has the same name and passwd as the admin of the local computer, it impersonated on the local computer. Is it possible or I'm missunderstanding something?


thanks in advance: collapo


-- modified at 7:13 Tuesday 21st August, 2007

Thx in advance:
Collapo
GeneralRe: Error Code 1326 Pin
mirh10-Oct-07 1:59
membermirh10-Oct-07 1:59 
GeneralRe: Error Code 1326 Pin
mustiy9-Feb-10 23:17
membermustiy9-Feb-10 23:17 
GeneralError 1314 Pin
m.aldegheri3-Aug-06 6:28
memberm.aldegheri3-Aug-06 6:28 
GeneralRe: Error 1314 Pin
m.aldegheri3-Aug-06 22:23
memberm.aldegheri3-Aug-06 22:23 
GeneralRe: Error 1314 Pin
MunkieFish11-Apr-07 7:49
memberMunkieFish11-Apr-07 7:49 
AnswerRe: Error 1314 Pin
uppals12-Apr-07 13:06
memberuppals12-Apr-07 13:06 
GeneralHelp needed Windows 2000 SP4 still getting 1314! -- Re: Error 1314 Pin
devvvy21-Feb-08 20:41
memberdevvvy21-Feb-08 20:41 
GeneralRe: Help needed Windows 2000 SP4 still getting 1314! -- Re: Error 1314 Pin
Marc Merritt26-Feb-08 3:02
memberMarc Merritt26-Feb-08 3:02 
Questionhow to use this in case of a local account? Pin
yossof elnaggar27-Jun-06 20:29
memberyossof elnaggar27-Jun-06 20:29 
AnswerRe: how to use this in case of a local account? Pin
hk1112-Jul-07 19:04
memberhk1112-Jul-07 19:04 
GeneralRe: how to use this in case of a local account? Pin
appalanaidu Aug20118-Feb-12 20:54
memberappalanaidu Aug20118-Feb-12 20:54 
GeneralFirst call takes too long Pin
schweeneh4-Apr-06 6:04
memberschweeneh4-Apr-06 6:04 
GeneralRe: First call takes too long Pin
Marc Merritt12-Jun-06 2:24
memberMarc Merritt12-Jun-06 2:24 
GeneralA similar article Pin
Uwe Keim23-Apr-05 23:59
sitebuilderUwe Keim23-Apr-05 23:59 
GeneralRe: A similar article Pin
craigg753-Nov-06 5:57
membercraigg753-Nov-06 5:57 
GeneralRe: A similar article Pin
Uwe Keim3-Nov-06 6:14
sitebuilderUwe Keim3-Nov-06 6:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.160811.3 | Last Updated 30 Apr 2003
Article Copyright 2003 by Marc Merritt
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid