Guillermo recently started blogging about some Whidbey enhancements around impersonation. However, figuring out how to impersonate in the first place can be a little less than obvious.
WindowsIdentity contains an Impersonate method, but it doesn't accept any parameters. That means that we'll need to supply the user and password through some other means. The constructor for WindowsIdentity that takes a string looks promising, however there doesn't seem to be any way to get a password in. Instead we'll have to use the constructor that takes a token (as an IntPtr). If we intend to go that route, then we might as well just use the static WindowsIdentity.Impersonate overload that takes a token directly.
OK, so how do we get that token? Well, we can P/Invoke to LogonUser. LogonUser takes a user name, domain, and password, and returns us a token that we can use with WindowsIdentity. In addition to these parameters, LogonUser wants to know which logon provider to use (the default should suffice for most cases), and a logon type Selecting a logon type can be a tricky, so lets take a look at our options.
One important thing to note is that in order to use WindowsIdentity.Impersonate(), we need a primary token, so if we go with LOGON32_LOGON_NETWORK, we'll need to use DuplicateHandle in order to get at the primary token. Since I like to avoid extra work like that, it looks like LOGON32_LOGON_BATCH or LOGON32_LOGON_INTERACTIVE would both be more appropriate choices. Selecting between them will depend on the rights that the account we're trying to logon has.
Once your call to LogonUser has gotten you a user token for the user you'd like to impersonate, you can then call WindowsIdentity.Impersonate() and have your thread take over the identity of the Windows user you just logged on. The code might look something like this:
However this code has a very subtle security issue that's just waiting to bite you. Before I fix the problem tomorrow, any guesses as to what might be wrong with the code?
Update 4:35 PM: Corrected an issue that wasn't the bug I'm referring to above.