Tim Van Wassenhove

Passionate geek, interested in Technology. Proud father of two

06 Sep 2008

Presenting WindowsIdentityHelper

One of the difficulties of using the WindowsIdentity class is the fact that it requires a handle (IntPtr) to a Windows Security Token. Using the LogonUser functionality we can get a hold of such a handle

[DllImport(Advapi32File, CharSet = DefaultCharSet, SetLastError = DefaultSetLastError)]
public static extern bool LogonUser( /* other parameters */, out IntPtr userTokenHandle);

The easiest way to avoid memory leaks is to implement a custom SafeHandle

public class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
	protected internal SafeTokenHandle()
	: base(true)
	{
	}

	protected override bool ReleaseHandle()
	{
		if(!this.IsInvalid)
		{
			return NativeMethods.CloseHandle(this.handle);
		}

		return true;
	}
}

With that SafeHandle in place we can change the signature to

[DllImport(Advapi32File, CharSet = DefaultCharSet, SetLastError = DefaultSetLastError)]
public static extern bool LogonUser( /* other parameters */, out SafeTokenHandle userTokenHandle);

With the Be.Timvw.Framework.Security.Principal.WindowsIdentityHelper we can now easily obtain a WindowsIdentity and use it to do some impersonation

using(WindowsIdentityHelper windowsIdentityHelper = new WindowsIdentityHelper(username, domain, password))
using(windowsIdentityHelper.GetWindowsIdentity().Impersonate())
{
	File.WriteAllText(@"c:\temp\blah.txt", "hello there");
}