1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
Imports System.Security.Principal Imports System.Runtime.InteropServices Public Class Impersonation 'These constants are based on values in the Win32 API file WINBASE.H 'Refer to http://msdn.microsoft.com/en-us/library/aa378184(VS.85).aspx for their meanings Const LOGON32_LOGON_INTERACTIVE As Integer = 2 Const LOGON32_PROVIDER_DEFAULT As Integer = 0 Private Declare Function LogonUserA Lib "advapi32.dll" (ByVal lpszUsername As String, _ ByVal lpszDomain As String, _ ByVal lpszPassword As String, _ ByVal dwLogonType As Integer, _ ByVal dwLogonProvider As Integer, _ ByRef phToken As IntPtr) As Integer Private Declare Auto Function DuplicateToken Lib "advapi32.dll" ( _ ByVal ExistingTokenHandle As IntPtr, _ ByVal ImpersonationLevel As SECURITY_IMPERSONATION_LEVEL, _ ByRef DuplicateTokenHandle As IntPtr) As Integer Private Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long Private Enum SECURITY_IMPERSONATION_LEVEL As Integer SecurityAnonymous = 0 SecurityIdentification = 1 SecurityImpersonation = 2 SecurityDelegation = 3 End Enum Private m_oImpersonationContext As WindowsImpersonationContext Private m_bImpersonationActive As Boolean Public Sub New() End Sub Public ReadOnly Property ImpersonationActive() As Boolean Get Return m_bImpersonationActive End Get End Property Public Function StartImpersonation(ByVal sUserName As String, ByVal sDomain As String, ByVal sPassword As String) As Boolean Dim bResults As Boolean = False Dim sErrorMessage As String Dim oWindowsIdentity As WindowsIdentity Dim hPrimaryToken As IntPtr = IntPtr.Zero 'a Win32 handle to our authentication token Dim hImpersonationToken As IntPtr = IntPtr.Zero 'a Win32 handle to our impersonation token If String.IsNullOrEmpty(sUserName) Then Throw New ArgumentException("UserName may not be NULL or String.Empty") End If 'If no domain is given, assume the account is a local one If sDomain = String.Empty Then sDomain = Environment.MachineName End If Try 'Validate the provided userid, password and domain. If LogonUserA(sUserName, sDomain, sPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hPrimaryToken) <> 0 Then 'Convert our token to one whos handle has TOKEN_IMPERSONATE set If DuplicateToken(hPrimaryToken, SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, hImpersonationToken) <> 0 Then 'Create a new identity object based on our impersonation token oWindowsIdentity = New WindowsIdentity(hImpersonationToken) 'Switch to our new identity m_oImpersonationContext = oWindowsIdentity.Impersonate() If m_oImpersonationContext IsNot Nothing Then m_bImpersonationActive = True bResults = True End If Else sErrorMessage = String.Format("DuplicateToken failed (rc={0})", Runtime.InteropServices.Marshal.GetLastWin32Error) Throw New Security.Authentication.AuthenticationException(sErrorMessage) End If Else sErrorMessage = String.Format("LogonUser failed (rc={0})", Runtime.InteropServices.Marshal.GetLastWin32Error) Throw New Security.Authentication.AuthenticationException(sErrorMessage) End If Finally If Not hImpersonationToken.Equals(IntPtr.Zero) Then CloseHandle(hImpersonationToken) hImpersonationToken = IntPtr.Zero End If If Not hPrimaryToken.Equals(IntPtr.Zero) Then CloseHandle(hPrimaryToken) hPrimaryToken = IntPtr.Zero End If End Try Return bResults End Function Public Sub EndImpersonation() If m_oImpersonationContext IsNot Nothing AndAlso m_bImpersonationActive Then m_oImpersonationContext.Undo() m_oImpersonationContext.Dispose() m_oImpersonationContext = Nothing m_bImpersonationActive = False End If End Sub End Class |