Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

LogonUser failing in Impersonation

Status
Not open for further replies.

saadabc

Programmer
Aug 5, 2004
107
0
0
US
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?




 
I figured this out.

I had to change the Local Policy so that the user would have privilege to run processes that 'Act As Part of the Operating System.'

There's a lot in Windows that I still haven't learnt.

Thanks.

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top