Skip to content

Commit

Permalink
Add SecureString password support
Browse files Browse the repository at this point in the history
Add SecureString password support for Impersonation call
  • Loading branch information
michael-wanke committed Dec 4, 2015
1 parent 38be733 commit 78d9a34
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 5 deletions.
42 changes: 37 additions & 5 deletions SimpleImpersonation/Impersonation.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;

Expand All @@ -8,28 +9,59 @@ namespace SimpleImpersonation
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public sealed class Impersonation : IDisposable
{
private readonly SafeTokenHandle _handle;
private readonly WindowsImpersonationContext _context;
private SafeTokenHandle _handle;
private WindowsImpersonationContext _context;

public static Impersonation LogonUser(string domain, string username, string password, LogonType logonType)
{
return new Impersonation(domain, username, password, logonType);
}

private Impersonation(string domain, string username, string password, LogonType logonType)
public static Impersonation LogonUser(string domain, string username, SecureString password, LogonType logonType)
{
return new Impersonation(domain, username, password, logonType);
}

private void CompleteImpersonation(bool ok, IntPtr handle)
{
IntPtr handle;
var ok = NativeMethods.LogonUser(username, domain, password, (int)logonType, 0, out handle);
if (!ok)
{
var errorCode = Marshal.GetLastWin32Error();

if (handle != IntPtr.Zero)
NativeMethods.CloseHandle(handle);

throw new ApplicationException(string.Format("Could not impersonate the elevated user. LogonUser returned error code {0}.", errorCode));
}

_handle = new SafeTokenHandle(handle);
_context = WindowsIdentity.Impersonate(_handle.DangerousGetHandle());
}

private Impersonation(string domain, string username, SecureString password, LogonType logonType)
{
IntPtr handle;
var passPtr = Marshal.SecureStringToGlobalAllocUnicode(password);
bool ok;
try
{
ok = NativeMethods.LogonUser(username, domain, passPtr, (int)logonType, 0, out handle);
}
finally
{
Marshal.ZeroFreeGlobalAllocUnicode(passPtr);
}

CompleteImpersonation(ok, handle);
}

private Impersonation(string domain, string username, string password, LogonType logonType)
{
IntPtr handle;
var ok = NativeMethods.LogonUser(username, domain, password, (int)logonType, 0, out handle);
CompleteImpersonation(ok, handle);
}

public void Dispose()
{
_context.Dispose();
Expand Down
3 changes: 3 additions & 0 deletions SimpleImpersonation/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ internal class NativeMethods
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool LogonUser(String lpszUsername, String lpszDomain, IntPtr phPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);

[DllImport("kernel32.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
Expand Down

0 comments on commit 78d9a34

Please sign in to comment.