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");
}
I am doing something realy similar. I have got it to work, buts its not realy production ready yet. Can you send me the
Be.Timvw.Framework.Sec
urity.Principal.WindowsIdentityHelper class to compare?
You can download the code from here.
Thanks for this sample of how to use a SafeHandle. Unfortunately, there’s not a lot of information on this out there!