I have a VB .net application. Have a module that contains the following code:
Imports System.Web
Imports System.Security.Principal
Imports System.Data.SqlClient
Module ImpersonateAdminLogin
Dim LOGON32_LOGON_INTERACTIVE As Integer = 2
Dim LOGON32_PROVIDER_DEFAULT As Integer = 0
Dim impersonationContext As WindowsImpersonationContext
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
Declare Auto Function DuplicateToken Lib "advapi32.dll" ( _
ByVal ExistingTokenHandle As IntPtr, _
ByVal ImpersonationLevel As Integer, _
ByRef DuplicateTokenHandle As IntPtr) As Integer
Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long
Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long
Private Function impersonateValidUser(ByVal userName As String, _
ByVal domain As String, ByVal password As String) As Boolean
Dim tempWindowsIdentity As WindowsIdentity
Dim token As IntPtr = IntPtr.Zero
Dim tokenDuplicate As IntPtr = IntPtr.Zero
impersonateValidUser = False
If RevertToSelf() <> 0 Then
If LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, token) <> 0 Then
If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then
tempWindowsIdentity = New WindowsIdentity(tokenDuplicate)
impersonationContext = tempWindowsIdentity.Impersonate()
If Not impersonationContext Is Nothing Then
impersonateValidUser = True
End If
End If
End If
End If
If Not tokenDuplicate.Equals(IntPtr.Zero) Then
CloseHandle(tokenDuplicate)
End If
If Not token.Equals(IntPtr.Zero) Then
CloseHandle(token)
End If
End Function
Private Sub undoImpersonation()
impersonationContext.Undo()
End Sub
Sub ImpersonateAdminUser()
If impersonateValidUser("exchange1", "SACRAMENTO", "uZT1q11") Then
'Insert your code that runs under the security context of a specific user here.
Dim c As New SqlConnection("server=sac_db5_srv;database=WCI_Global;integrated security=sspi")
c.Open()
Dim m As New SqlCommand("Select * from scan_login")
Dim r As SqlDataReader
r = m.ExecuteReader()
While r.Read
'Response.Write(r.Item(0).ToString())
End While
undoImpersonation()
Else
'Your impersonation failed. Therefore, include a fail-safe mechanism here.
End If
End Sub
End Module
so this basically defines the functions for impersonating (i copied this from somewhere on the Internet).
Then I have a form as follows:
Imports System.Web
Imports System.Security.Principal
Imports System.Data.SqlClient
Module ImpersonateAdminLogin
Dim LOGON32_LOGON_INTERACTIVE As Integer = 2
Dim LOGON32_PROVIDER_DEFAULT As Integer = 0
Dim impersonationContext As WindowsImpersonationContext
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
Declare Auto Function DuplicateToken Lib "advapi32.dll" ( _
ByVal ExistingTokenHandle As IntPtr, _
ByVal ImpersonationLevel As Integer, _
ByRef DuplicateTokenHandle As IntPtr) As Integer
Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long
Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long
Private Function impersonateValidUser(ByVal userName As String, _
ByVal domain As String, ByVal password As String) As Boolean
Dim tempWindowsIdentity As WindowsIdentity
Dim token As IntPtr = IntPtr.Zero
Dim tokenDuplicate As IntPtr = IntPtr.Zero
impersonateValidUser = False
If RevertToSelf() <> 0 Then
If LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, token) <> 0 Then
If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then
tempWindowsIdentity = New WindowsIdentity(tokenDuplicate)
impersonationContext = tempWindowsIdentity.Impersonate()
If Not impersonationContext Is Nothing Then
impersonateValidUser = True
End If
End If
End If
End If
If Not tokenDuplicate.Equals(IntPtr.Zero) Then
CloseHandle(tokenDuplicate)
End If
If Not token.Equals(IntPtr.Zero) Then
CloseHandle(token)
End If
End Function
Private Sub undoImpersonation()
impersonationContext.Undo()
End Sub
Sub ImpersonateAdminUser()
If impersonateValidUser("exchange1", "SACRAMENTO", "uZT1q11") Then
'Insert your code that runs under the security context of a specific user here.
Dim c As New SqlConnection("server=sac_db5_srv;database=WCI_Global;integrated security=sspi")
c.Open()
Dim m As New SqlCommand("Select * from scan_login")
Dim r As SqlDataReader
r = m.ExecuteReader()
While r.Read
'Response.Write(r.Item(0).ToString())
End While
undoImpersonation()
Else
'Your impersonation failed. Therefore, include a fail-safe mechanism here.
End If
End Sub
........
I've ommitted the Windows Form Designer generated code here
............
Then I have a button here - that's actually calling the functions to do the impersonation as follows:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btImpersonate.Click
Const LOGON32_PROVIDER_DEFAULT As Integer = 0
'This parameter causes LogonUser to create a primary token.
Const LOGON32_LOGON_INTERACTIVE As Integer = 2
Const SecurityImpersonation As Integer = 2
Dim bans As Boolean
Dim sErr As String
Dim tokenHandle As New IntPtr(0)
Dim dupeTokenHandle As New IntPtr(0)
Try
tokenHandle = IntPtr.Zero
dupeTokenHandle = IntPtr.Zero
' Call LogonUser to obtain a handle to an access token.
Dim returnValue As Boolean = LogonUser("theuser", "Sacramento", "thepassword", LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, tokenHandle)
'bans = SaveTextToFile("Logon User Called", "C:\ImpersonateTestLog\Log.txt", sErr)
MsgBox("Logon User Called.")
If False = returnValue Then
'Dim ret As Integer = Marshal.GetLastWin32Error()
'MsgBox("Error Code: " & ret)
'MsgBox("Error Message: " & GetErrorMessage(ret))
'bans = SaveTextToFile("LogonUser failed with error code : {0} Last Error Code = " & ret, "C:\ImpersonateTestLog\Log.txt", sErr)
'bans = SaveTextToFile(ControlChars.Cr & "Error: [{0}] {1}" & ControlChars.Cr & " ret =" & ret & "GetErrorMessage()=" & GetErrorMessage(ret), "C:\ImpersonateTestLog\Log.txt", sErr)
MsgBox("End of Failed.")
End If
Dim success As String
If returnValue Then
success = "Yes"
Else
success = "No"
End If
'bans = SaveTextToFile("Did Logon User succeed? " & success, "C:\ImpersonateTestLog\Log.txt", sErr)
MsgBox("Did Logon User succeed? " & success)
'bans = SaveTextToFile("Value of Windows NT Token? " & tokenHandle.ToString(), "C:\ImpersonateTestLog\Log.txt", sErr)
MsgBox("Value of Windows NT Token? " & tokenHandle.ToString())
' Check the identity.
'bans = SaveTextToFile("Before Impersonation: " & WindowsIdentity.GetCurrent().Name, "C:\ImpersonateTestLog\Log.txt", sErr)
MsgBox("Before Impersonation: " & WindowsIdentity.GetCurrent().Name)
MsgBox("Midway")
Dim retVal As Boolean = DuplicateToken(tokenHandle, SecurityImpersonation, dupeTokenHandle)
If False = retVal Then
'CloseHandle(tokenHandle)
'Console.WriteLine("Exception thrown in trying to duplicate token.")
MsgBox("Exception thrown in trying to duplicate token.")
End If
' TThe 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(dupeTokenHandle)
Dim impersonatedUser As WindowsImpersonationContext = newId.Impersonate()
' Check the identity.
'bans = SaveTextToFile("After impersonation: " & WindowsIdentity.GetCurrent().Name, "C:\ImpersonateTestLog\Log.txt", sErr)
MsgBox("After impersonation: " & WindowsIdentity.GetCurrent().Name)
'bans = SaveTextToFile("Before FillFileScan", "C:\ImpersonateTestLog\Log.txt", sErr)
'bans = SaveTextToFile("After FillFileScan", "C:\ImpersonateTestLog\Log.txt", sErr)
' Stop impersonating the user.
impersonatedUser.Undo()
' Check the identity.
MsgBox("AFter impersonateUnDo: " & WindowsIdentity.GetCurrent().Name)
' Free the tokens.
If Not System.IntPtr.op_Equality(tokenHandle, IntPtr.Zero) Then
CloseHandle(tokenHandle)
End If
If Not System.IntPtr.op_Equality(dupeTokenHandle, IntPtr.Zero) Then
CloseHandle(dupeTokenHandle)
End If
MsgBox("End of function")
Catch ex As Exception
Console.WriteLine(("Exception occurred. " + ex.Message))
End Try
End Sub
The code works fine when I run it in development mode - but when i create an executable and package it and install it on a machine -
it fails at the line:
Dim returnValue As Boolean = LogonUser("theuser", "Sacramento", "thepassword", LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, tokenHandle)
something fails in the LogonUser function - the returnValue evaluates to false - so it doesn't work beyond that point.
I'm going nuts over trying to figure out what's causing the problem. I even packaged advapi32.dll and kernel32.dll with the application but it still fails. Any ideas?
Imports System.Web
Imports System.Security.Principal
Imports System.Data.SqlClient
Module ImpersonateAdminLogin
Dim LOGON32_LOGON_INTERACTIVE As Integer = 2
Dim LOGON32_PROVIDER_DEFAULT As Integer = 0
Dim impersonationContext As WindowsImpersonationContext
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
Declare Auto Function DuplicateToken Lib "advapi32.dll" ( _
ByVal ExistingTokenHandle As IntPtr, _
ByVal ImpersonationLevel As Integer, _
ByRef DuplicateTokenHandle As IntPtr) As Integer
Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long
Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long
Private Function impersonateValidUser(ByVal userName As String, _
ByVal domain As String, ByVal password As String) As Boolean
Dim tempWindowsIdentity As WindowsIdentity
Dim token As IntPtr = IntPtr.Zero
Dim tokenDuplicate As IntPtr = IntPtr.Zero
impersonateValidUser = False
If RevertToSelf() <> 0 Then
If LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, token) <> 0 Then
If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then
tempWindowsIdentity = New WindowsIdentity(tokenDuplicate)
impersonationContext = tempWindowsIdentity.Impersonate()
If Not impersonationContext Is Nothing Then
impersonateValidUser = True
End If
End If
End If
End If
If Not tokenDuplicate.Equals(IntPtr.Zero) Then
CloseHandle(tokenDuplicate)
End If
If Not token.Equals(IntPtr.Zero) Then
CloseHandle(token)
End If
End Function
Private Sub undoImpersonation()
impersonationContext.Undo()
End Sub
Sub ImpersonateAdminUser()
If impersonateValidUser("exchange1", "SACRAMENTO", "uZT1q11") Then
'Insert your code that runs under the security context of a specific user here.
Dim c As New SqlConnection("server=sac_db5_srv;database=WCI_Global;integrated security=sspi")
c.Open()
Dim m As New SqlCommand("Select * from scan_login")
Dim r As SqlDataReader
r = m.ExecuteReader()
While r.Read
'Response.Write(r.Item(0).ToString())
End While
undoImpersonation()
Else
'Your impersonation failed. Therefore, include a fail-safe mechanism here.
End If
End Sub
End Module
so this basically defines the functions for impersonating (i copied this from somewhere on the Internet).
Then I have a form as follows:
Imports System.Web
Imports System.Security.Principal
Imports System.Data.SqlClient
Module ImpersonateAdminLogin
Dim LOGON32_LOGON_INTERACTIVE As Integer = 2
Dim LOGON32_PROVIDER_DEFAULT As Integer = 0
Dim impersonationContext As WindowsImpersonationContext
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
Declare Auto Function DuplicateToken Lib "advapi32.dll" ( _
ByVal ExistingTokenHandle As IntPtr, _
ByVal ImpersonationLevel As Integer, _
ByRef DuplicateTokenHandle As IntPtr) As Integer
Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long
Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long
Private Function impersonateValidUser(ByVal userName As String, _
ByVal domain As String, ByVal password As String) As Boolean
Dim tempWindowsIdentity As WindowsIdentity
Dim token As IntPtr = IntPtr.Zero
Dim tokenDuplicate As IntPtr = IntPtr.Zero
impersonateValidUser = False
If RevertToSelf() <> 0 Then
If LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, token) <> 0 Then
If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then
tempWindowsIdentity = New WindowsIdentity(tokenDuplicate)
impersonationContext = tempWindowsIdentity.Impersonate()
If Not impersonationContext Is Nothing Then
impersonateValidUser = True
End If
End If
End If
End If
If Not tokenDuplicate.Equals(IntPtr.Zero) Then
CloseHandle(tokenDuplicate)
End If
If Not token.Equals(IntPtr.Zero) Then
CloseHandle(token)
End If
End Function
Private Sub undoImpersonation()
impersonationContext.Undo()
End Sub
Sub ImpersonateAdminUser()
If impersonateValidUser("exchange1", "SACRAMENTO", "uZT1q11") Then
'Insert your code that runs under the security context of a specific user here.
Dim c As New SqlConnection("server=sac_db5_srv;database=WCI_Global;integrated security=sspi")
c.Open()
Dim m As New SqlCommand("Select * from scan_login")
Dim r As SqlDataReader
r = m.ExecuteReader()
While r.Read
'Response.Write(r.Item(0).ToString())
End While
undoImpersonation()
Else
'Your impersonation failed. Therefore, include a fail-safe mechanism here.
End If
End Sub
........
I've ommitted the Windows Form Designer generated code here
............
Then I have a button here - that's actually calling the functions to do the impersonation as follows:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btImpersonate.Click
Const LOGON32_PROVIDER_DEFAULT As Integer = 0
'This parameter causes LogonUser to create a primary token.
Const LOGON32_LOGON_INTERACTIVE As Integer = 2
Const SecurityImpersonation As Integer = 2
Dim bans As Boolean
Dim sErr As String
Dim tokenHandle As New IntPtr(0)
Dim dupeTokenHandle As New IntPtr(0)
Try
tokenHandle = IntPtr.Zero
dupeTokenHandle = IntPtr.Zero
' Call LogonUser to obtain a handle to an access token.
Dim returnValue As Boolean = LogonUser("theuser", "Sacramento", "thepassword", LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, tokenHandle)
'bans = SaveTextToFile("Logon User Called", "C:\ImpersonateTestLog\Log.txt", sErr)
MsgBox("Logon User Called.")
If False = returnValue Then
'Dim ret As Integer = Marshal.GetLastWin32Error()
'MsgBox("Error Code: " & ret)
'MsgBox("Error Message: " & GetErrorMessage(ret))
'bans = SaveTextToFile("LogonUser failed with error code : {0} Last Error Code = " & ret, "C:\ImpersonateTestLog\Log.txt", sErr)
'bans = SaveTextToFile(ControlChars.Cr & "Error: [{0}] {1}" & ControlChars.Cr & " ret =" & ret & "GetErrorMessage()=" & GetErrorMessage(ret), "C:\ImpersonateTestLog\Log.txt", sErr)
MsgBox("End of Failed.")
End If
Dim success As String
If returnValue Then
success = "Yes"
Else
success = "No"
End If
'bans = SaveTextToFile("Did Logon User succeed? " & success, "C:\ImpersonateTestLog\Log.txt", sErr)
MsgBox("Did Logon User succeed? " & success)
'bans = SaveTextToFile("Value of Windows NT Token? " & tokenHandle.ToString(), "C:\ImpersonateTestLog\Log.txt", sErr)
MsgBox("Value of Windows NT Token? " & tokenHandle.ToString())
' Check the identity.
'bans = SaveTextToFile("Before Impersonation: " & WindowsIdentity.GetCurrent().Name, "C:\ImpersonateTestLog\Log.txt", sErr)
MsgBox("Before Impersonation: " & WindowsIdentity.GetCurrent().Name)
MsgBox("Midway")
Dim retVal As Boolean = DuplicateToken(tokenHandle, SecurityImpersonation, dupeTokenHandle)
If False = retVal Then
'CloseHandle(tokenHandle)
'Console.WriteLine("Exception thrown in trying to duplicate token.")
MsgBox("Exception thrown in trying to duplicate token.")
End If
' TThe 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(dupeTokenHandle)
Dim impersonatedUser As WindowsImpersonationContext = newId.Impersonate()
' Check the identity.
'bans = SaveTextToFile("After impersonation: " & WindowsIdentity.GetCurrent().Name, "C:\ImpersonateTestLog\Log.txt", sErr)
MsgBox("After impersonation: " & WindowsIdentity.GetCurrent().Name)
'bans = SaveTextToFile("Before FillFileScan", "C:\ImpersonateTestLog\Log.txt", sErr)
'bans = SaveTextToFile("After FillFileScan", "C:\ImpersonateTestLog\Log.txt", sErr)
' Stop impersonating the user.
impersonatedUser.Undo()
' Check the identity.
MsgBox("AFter impersonateUnDo: " & WindowsIdentity.GetCurrent().Name)
' Free the tokens.
If Not System.IntPtr.op_Equality(tokenHandle, IntPtr.Zero) Then
CloseHandle(tokenHandle)
End If
If Not System.IntPtr.op_Equality(dupeTokenHandle, IntPtr.Zero) Then
CloseHandle(dupeTokenHandle)
End If
MsgBox("End of function")
Catch ex As Exception
Console.WriteLine(("Exception occurred. " + ex.Message))
End Try
End Sub
The code works fine when I run it in development mode - but when i create an executable and package it and install it on a machine -
it fails at the line:
Dim returnValue As Boolean = LogonUser("theuser", "Sacramento", "thepassword", LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, tokenHandle)
something fails in the LogonUser function - the returnValue evaluates to false - so it doesn't work beyond that point.
I'm going nuts over trying to figure out what's causing the problem. I even packaged advapi32.dll and kernel32.dll with the application but it still fails. Any ideas?