Click here to Skip to main content
15,886,258 members
Articles / Programming Languages / C#

Windows Impersonation using C#

Rate me:
Please Sign up or sign in to vote.
4.77/5 (49 votes)
29 Apr 2003CPOL 722.1K   15.7K   149  
An article demonstrating how to use Windows impersonation in your C# code
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Runtime.InteropServices;  // DllImport
using System.Security.Principal; // WindowsImpersonationContext
using System.Security.Permissions; // PermissionSetAttribute

namespace Impersonate
{
	// group type enum
	public enum SECURITY_IMPERSONATION_LEVEL : int
	{
		SecurityAnonymous = 0,
		SecurityIdentification = 1,
		SecurityImpersonation = 2,
		SecurityDelegation = 3
	}
		
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class Form1 : System.Windows.Forms.Form
	{

		// obtains user token
		[DllImport("advapi32.dll", SetLastError=true)]
		public static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword, 
			int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

		// closes open handes returned by LogonUser
		[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
		public extern static bool CloseHandle(IntPtr handle);

		// creates duplicate token handle
		[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
		public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, 
			int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);

		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.Label lblCurrentUser;
		private System.Windows.Forms.TextBox textBoxUsername;
		private System.Windows.Forms.Label label2;
		private System.Windows.Forms.Label label3;
		private System.Windows.Forms.TextBox textBoxPassword;
		private System.Windows.Forms.Button buttonLogon;
		private System.Windows.Forms.Label label4;
		private System.Windows.Forms.TextBox textBoxDomain;
		private System.Security.Principal.WindowsImpersonationContext newUser;
		private System.Windows.Forms.Button buttonRevert;

		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public Form1()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			//
			// TODO: Add any constructor code after InitializeComponent call
			//

			// set logged on username
			lblCurrentUser.Text = System.Security.Principal.WindowsIdentity.GetCurrent().Name;

			// populate logon domain name
			string sTempUser = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
			if (sTempUser.IndexOf("\\") != -1)
			{
				string[] aryUser = new String[2];
				char[] splitter  = {'\\'};
				aryUser = sTempUser.Split(splitter);
				textBoxDomain.Text = aryUser[0];
			}
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.label1 = new System.Windows.Forms.Label();
			this.lblCurrentUser = new System.Windows.Forms.Label();
			this.textBoxUsername = new System.Windows.Forms.TextBox();
			this.label2 = new System.Windows.Forms.Label();
			this.label3 = new System.Windows.Forms.Label();
			this.textBoxPassword = new System.Windows.Forms.TextBox();
			this.buttonLogon = new System.Windows.Forms.Button();
			this.label4 = new System.Windows.Forms.Label();
			this.textBoxDomain = new System.Windows.Forms.TextBox();
			this.buttonRevert = new System.Windows.Forms.Button();
			this.SuspendLayout();
			// 
			// label1
			// 
			this.label1.Location = new System.Drawing.Point(16, 24);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(88, 16);
			this.label1.TabIndex = 0;
			this.label1.Text = "Running As:";
			this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
			// 
			// lblCurrentUser
			// 
			this.lblCurrentUser.Location = new System.Drawing.Point(112, 24);
			this.lblCurrentUser.Name = "lblCurrentUser";
			this.lblCurrentUser.Size = new System.Drawing.Size(200, 16);
			this.lblCurrentUser.TabIndex = 1;
			// 
			// textBoxUsername
			// 
			this.textBoxUsername.Location = new System.Drawing.Point(112, 80);
			this.textBoxUsername.Name = "textBoxUsername";
			this.textBoxUsername.Size = new System.Drawing.Size(144, 20);
			this.textBoxUsername.TabIndex = 2;
			this.textBoxUsername.Text = "";
			// 
			// label2
			// 
			this.label2.Location = new System.Drawing.Point(16, 80);
			this.label2.Name = "label2";
			this.label2.Size = new System.Drawing.Size(88, 16);
			this.label2.TabIndex = 3;
			this.label2.Text = "New Username:";
			this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
			// 
			// label3
			// 
			this.label3.Location = new System.Drawing.Point(16, 104);
			this.label3.Name = "label3";
			this.label3.Size = new System.Drawing.Size(88, 16);
			this.label3.TabIndex = 5;
			this.label3.Text = "New Password:";
			this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
			// 
			// textBoxPassword
			// 
			this.textBoxPassword.Location = new System.Drawing.Point(112, 104);
			this.textBoxPassword.Name = "textBoxPassword";
			this.textBoxPassword.PasswordChar = '*';
			this.textBoxPassword.Size = new System.Drawing.Size(144, 20);
			this.textBoxPassword.TabIndex = 4;
			this.textBoxPassword.Text = "";
			// 
			// buttonLogon
			// 
			this.buttonLogon.Location = new System.Drawing.Point(181, 136);
			this.buttonLogon.Name = "buttonLogon";
			this.buttonLogon.TabIndex = 6;
			this.buttonLogon.Text = "Logon";
			this.buttonLogon.Click += new System.EventHandler(this.buttonLogon_Click);
			// 
			// label4
			// 
			this.label4.Location = new System.Drawing.Point(16, 56);
			this.label4.Name = "label4";
			this.label4.Size = new System.Drawing.Size(88, 16);
			this.label4.TabIndex = 8;
			this.label4.Text = "Logon Domain:";
			this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
			// 
			// textBoxDomain
			// 
			this.textBoxDomain.Location = new System.Drawing.Point(112, 56);
			this.textBoxDomain.Name = "textBoxDomain";
			this.textBoxDomain.Size = new System.Drawing.Size(144, 20);
			this.textBoxDomain.TabIndex = 7;
			this.textBoxDomain.Text = "";
			// 
			// buttonRevert
			// 
			this.buttonRevert.Enabled = false;
			this.buttonRevert.Location = new System.Drawing.Point(104, 136);
			this.buttonRevert.Name = "buttonRevert";
			this.buttonRevert.TabIndex = 9;
			this.buttonRevert.Text = "Revert";
			this.buttonRevert.Click += new System.EventHandler(this.buttonRevert_Click);
			// 
			// Form1
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(312, 189);
			this.Controls.AddRange(new System.Windows.Forms.Control[] {
																		  this.buttonRevert,
																		  this.label4,
																		  this.textBoxDomain,
																		  this.buttonLogon,
																		  this.label3,
																		  this.textBoxPassword,
																		  this.label2,
																		  this.textBoxUsername,
																		  this.lblCurrentUser,
																		  this.label1});
			this.MaximizeBox = false;
			this.Name = "Form1";
			this.Text = "Impersonation Example";
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			Application.Run(new Form1());
		}

		private void buttonLogon_Click(object sender, System.EventArgs e)
		{
			if (textBoxUsername.Text != "" && textBoxPassword.Text != "")
			{
				try
				{
					// attempt to impersonate specified user
					newUser = this.ImpersonateUser(textBoxUsername.Text, textBoxDomain.Text, textBoxPassword.Text);
					// update the running as name
					lblCurrentUser.Text = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
					buttonRevert.Enabled = true;
					buttonLogon.Enabled = false;
				}
				catch (Exception ex)
				{
					// why did it fail?
					MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
				}
			}
			else
				MessageBox.Show(this, "Complete all the logon credentials", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
		}

		/// <summary>
		/// Revert back to previous user
		/// </summary>
		private void buttonRevert_Click(object sender, System.EventArgs e)
		{
			// revert to previous user
			newUser.Undo();
			buttonRevert.Enabled = false;
			buttonLogon.Enabled = true;
			// update the running as name
			lblCurrentUser.Text = System.Security.Principal.WindowsIdentity.GetCurrent().Name;			
		}

		/// <summary>
		/// Attempts to impersonate a user.  If successful, returns 
		/// a WindowsImpersonationContext of the new users identity.
		/// </summary>
		/// <param name="sUsername">Username you want to impersonate</param>
		/// <param name="sDomain">Logon domain</param>
		/// <param name="sPassword">User's password to logon with</param></param>
		/// <returns></returns>
		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();
					CloseHandle(pExistingTokenHandle); // close existing handle
					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);
			}
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

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


Written By
Zambia Zambia
Living abroad and loving life.

Comments and Discussions