Imports System
Imports System.Diagnostics
Imports System.Runtime.InteropServices
Imports System.Security
Imports System.Security.Principal
Imports System.Text
Module ImpersonationExample
' PInvoke into the Win32 API to provide access to the
' LogonUser and CloseHandle functions.
<DllImport("advapi32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)> Function LogonUser(ByVal username As String, ByVal domain As String, ByVal password As IntPtr, ByVal logonType As Integer, ByVal logonProvider As Integer, ByRef token As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", CharSet:=CharSet.Auto)> Function CloseHandle(ByVal handle As IntPtr) As Boolean
End Function
' Define the required LogonUser enumerations.
Const LOGON32_PROVIDER_DEFAULT As Integer = 0
Const LOGON32_LOGON_INTERACTIVE As Integer = 2
Sub Main(ByVal args() As String)
Try
' Display the current user before impersonation.
Console.WriteLine("Before impersonation: " + WindowsIdentity.GetCurrent().Name)
' Ask the user for a network domain.
Console.Write("Please enter your domain:")
Dim domain As String = Console.ReadLine()
' Ask the user for a user name.
Console.Write("Please enter your user name:")
Dim username As String = Console.ReadLine()
' Ask the user for a password.
Console.Write("Please enter your password:")
Dim passWord As SecureString = GetPassword()
' Impersonate the account provided by the user.
Dim userContext As WindowsImpersonationContext = ImpersonateUser(passWord, username, domain)
' Display the current user after impersonation.
Console.WriteLine("After impersonation: " + WindowsIdentity.GetCurrent().Name)
Catch e As Exception
Console.WriteLine(e.Message)
End Try
Console.ReadLine()
End Sub
Function GetPassword() As SecureString
Dim password As New SecureString()
' get the first character of the password
Dim nextKey As ConsoleKeyInfo = Console.ReadKey(True)
While nextKey.Key <> ConsoleKey.Enter
If nextKey.Key = ConsoleKey.BackSpace Then
If password.Length > 0 Then
password.RemoveAt(password.Length - 1)
' erase the last * as well
Console.Write(nextKey.KeyChar)
Console.Write(" ")
Console.Write(nextKey.KeyChar)
End If
Else
password.AppendChar(nextKey.KeyChar)
Console.Write("*")
End If
nextKey = Console.ReadKey(True)
End While
Console.WriteLine()
' lock the password down
password.MakeReadOnly()
Return password
End Function
Function ImpersonateUser(ByVal password As SecureString, ByVal userName As String, ByVal domainName As String) As WindowsImpersonationContext
Dim tokenHandle As IntPtr = IntPtr.Zero
Dim passwordPtr As IntPtr = IntPtr.Zero
Dim returnValue As Boolean = False
Try
' Marshal the SecureString to unmanaged memory.
passwordPtr = Marshal.SecureStringToGlobalAllocUnicode(password)
' Call LogonUser, passing the unmanaged (and decrypted) copy of
' the SecureString password.
returnValue = LogonUser(userName, domainName, passwordPtr, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, tokenHandle)
Finally
' Zero-out and free the unmanaged string reference.
Marshal.ZeroFreeGlobalAllocUnicode(passwordPtr)
' Close the token handle.
CloseHandle(tokenHandle)
End Try
' Get the Last win32 Error and throw an exception.
If Not returnValue AndAlso tokenHandle = IntPtr.Zero Then
Dim [error] As Integer = Marshal.GetLastWin32Error()
Throw New System.ComponentModel.Win32Exception([error])
End If
' The token that is passed to the following constructor must
' be a primary token in order to use it for impersonation.
Dim newId As New WindowsIdentity(tokenHandle)
Return newId.Impersonate()
End Function
End Module