Skip to content
October 27, 2006 / Bob Black

You’re Just an Imposter!

[Warning: This is one of those technical articles where the writer (me) tries to be all witty and stuff instead of just getting to the point. Sorry. I couldn’t help myself.]

[Warning #2: WordPress is a pain in the patula oblongata about formatting. I spent waaay too much time trying to get the code snippets in this post looking good, only to have WordPress reformat everything the next time I saved. AAaaiiiiggh!! So if the code snippets look stanky, sorry… I tried!]

I mentioned in an earlier post that I was working on a little console utility to launch an application using a particular user’s credentials. That right there is what I like to call impersonation. Come to think of it, everyone else calls it impersonation too, but no matter. In this post I’ll show you, dear reader, the very innards of impersonation, and hopefully when you’re done reading this post you’ll be as excited about the subject as I am! Yeah! Go Team Go! And stuff!

The .Net Framework provides everything you need to get at useful tidbits like the currently logged on user, role membership and so forth, but to do full fledged impersonation you have to do a little Win32 api work. If you’re using Mono.Net on Linux, um… I’m sorry, you should stop reading now, ’cause this article won’t help you on a non-Windows platform. Sorry. But really, who uses Linux anyway? I mean, c’mon you guys, Linux is just sooo OS2. Just like the Macintosh. Yeah, nobody uses the Mac anymore either.

But anyway, where was I before I waxed controversial? Oh yeah, impersonation. If you need to know how to do impersonation (on Windows), look no further for the source of power! This post should provide everything you need to be well on your way to… uh, impostering. I mean impersonatering. Or something.

So let’s take a look at the problem from up around a thousand feet. Yeah, I speak management speak, too. I’m bilingual like that. But any way, from way up here in the stratosphere we can rest our chins on our hands and hypothesize that there are really two ways to approach impersonation…

  1. Impersonation when launching a new process – for example, when you want to run a program as a particular user.
  2. Impersonation when running a piece of code – for example, when you want to execute a method as a particular user.

At the end of this post I’ve provided, free of charge and limitations, the full source code to a C# class that makes it fairly easy to impersonate using either approach. Some of the methods are unsafe, so if you use the code in your own application you must compile using the /unsafe switch.

So let’s talk about the first approach, which is the simpler of the two. In a nutshell, it involves calling the CreateProcessWithLogonW API method, as shown in the below snippet taken from my Impersonator class. You’ll notice this method doesn’t allow you to specify a username and password because those are provided when you call the Impersonator class’s constructor, not shown (see the file download).

So to run another app as a particular user, you just create a new Impersonator object, and call the RunAs method, and off the new process goes on its merry way, running happily as another user (provided the username and password you supplied in the constructor are correct).

[PermissionSetAttribute(SecurityAction.Demand, Name = FullTrust)]
public unsafe bool RunAs(string ApplicationName, string CommandLine, string CurrentDirectory)
{
  StartupInfo si
= new StartupInfo();
  si.cb
= Marshal.SizeOf(typeof(StartupInfo));
  si.title
= m_strUsername; ProcessInfo pi = new ProcessInfo(); try
  {
 
if (CreateProcessWithLogonW(m_strUsername, m_strDomain, m_strPassword,
 
0, //LogonFlags.LOGON_WITH_PROFILE,
ApplicationName, CommandLine,
 
0, IntPtr.Zero, CurrentDirectory,
  ref si, out pi))
  {
  CloseHandle(pi.hProcess);
  CloseHandle(pi.hThread);
 
return true;
  }
 
else
  {
 
return false;
}
  }
 
catch
  {
 
return true;
  }
}

I’ve provided a handy dandy method called Validate() that will return true if the specified credentials are valid. The Validate() method returns the result of the LogonUser API method, and looks like this…
public bool Validate()
{
  IntPtr tokenHandle
= new IntPtr(0);
return LogonUser(m_strUsername, m_strDomain, m_strPassword,
  LogonFlags.LOGON32_LOGON_INTERACTIVE, LogonFlags.LOGON32_PROVIDER_DEFAULT,
 
ref tokenHandle);
}

And so finally, let’s talk about second way to perform impersonation, which is by executing a block of code as a particular user.This method of impersonation is performed in the Impersonate method. If you open up the Impersonator class and look at this method you’ll notice (or if not, I’ll tell you now, hehe), that the Impersonate function takes care of rolling back the impersonation context after impersonation is complete (or if an error occurs), which is good because you don’t want other code in your application suddenly running under a login context you didn’t expect. You’ll also notice that impersonation code must be executed before (to impersonate) and immediately after (to undo the impersonation) the code you want to execute. To make this work in a reusable code library (such as I have provided for you to download at the end of this article), the Impersonate method accepts as a parameter a delegate of type ImpersonateCallback, which is called if impersonation succeeds.

In my not so humble opinion, this little class takes a lot of the headache out of impersonation. Give it a try, and if you have any feedback or questions feel free to post a comment.

And here’s the link to Download Impersonator.cs

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: