-
2
- #1
Having chased around for a clear working example of impersonation in .net I came up with A RunAs_Impersonator class to simplify things. Here is an example of how you would use the class:
I found a couple of examples from postings and examples in the WindowsImpersonationContext help and re-worked these to split the impersonation into separate start and stop methods - hopefully this makes the usage clearer.
So far it seems to work, but I note that this method has some limitations for instance it doesn't work for win9x or 2000 operating systems. Also (noted from thread796-1129322) the local policy has to allow users to 'Act As Part of the Operating System.'
Here is the code for the class:
Hope this is helpful. Please feel free to add any comments, corrections or improvements.
Code:
Dim imp As New RunAs_Impersonator
Try
imp.ImpersonateStart(DomainName, UserName, Password) [green] 'creates new context using token for user[/green]
[i]Add code to run as UserName here[/i] [green] 'everything between ImpersonateStart and ImpersonateStop will be run as the impersonated user[/green]
imp.ImpersonateStop()
Catch ex As Exception [green] 'make sure impersonation is stopped whether code succeeds or not[/green]
MsgBox(ex.Message)
imp.ImpersonateStop()
End Try
I found a couple of examples from postings and examples in the WindowsImpersonationContext help and re-worked these to split the impersonation into separate start and stop methods - hopefully this makes the usage clearer.
So far it seems to work, but I note that this method has some limitations for instance it doesn't work for win9x or 2000 operating systems. Also (noted from thread796-1129322) the local policy has to allow users to 'Act As Part of the Operating System.'
Here is the code for the class:
Code:
Imports System
Imports System.Runtime.InteropServices
Imports System.Security.Principal
Imports System.Security.Permissions
Imports Microsoft.VisualBasic
<Assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, UnmanagedCode:=True), _
Assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Name:="FullTrust")>
Public Class RunAs_Impersonator
#Region "Private Variables and Enum Constants"
Private tokenHandle As New IntPtr(0)
Private dupeTokenHandle As New IntPtr(0)
Private impersonatedUser As WindowsImpersonationContext
#End Region
#Region "Properties"
#End Region
#Region "Public Methods"
Public Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Boolean
Public Declare Auto Function DuplicateToken Lib "advapi32.dll" (ByVal ExistingTokenHandle As IntPtr, _
ByVal SECURITY_IMPERSONATION_LEVEL As Integer, _
ByRef DuplicateTokenHandle As IntPtr) As Boolean
' Test harness.
' If you incorporate this code into a DLL, be sure to demand FullTrust.
<PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")> _
Public Sub ImpersonateStart(ByVal Domain As String, ByVal userName As String, ByVal Password As String)
Try
tokenHandle = IntPtr.Zero
' Call LogonUser to obtain a handle to an access token.
Dim returnValue As Boolean = LogonUser(userName, Domain, Password, 2, 0, tokenHandle)
'check if logon successful
If returnValue = False Then
Dim ret As Integer = Marshal.GetLastWin32Error()
Console.WriteLine("LogonUser failed with error code : {0}", ret)
Throw New System.ComponentModel.Win32Exception(ret)
Exit Sub
End If
'Logon succeeded
' Use the token handle returned by LogonUser.
Dim newId As New WindowsIdentity(tokenHandle)
impersonatedUser = newId.Impersonate()
Catch ex As Exception
Throw ex
Exit Sub
End Try
MsgBox("running as " & impersonatedUser.ToString & " -- " & WindowsIdentity.GetCurrent.Name)
End Sub
<PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")> _
Public Sub ImpersonateStop()
' Stop impersonating the user.
impersonatedUser.Undo()
' Free the tokens.
If Not System.IntPtr.op_Equality(tokenHandle, IntPtr.Zero) Then
CloseHandle(tokenHandle)
End If
MsgBox("running as " & Environment.UserName)
End Sub
#End Region
#Region "Private Methods"
Private Declare Auto Function LogonUser 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 Boolean
<DllImport("kernel32.dll")> _
Public Shared Function FormatMessage(ByVal dwFlags As Integer, ByRef lpSource As IntPtr, _
ByVal dwMessageId As Integer, ByVal dwLanguageId As Integer, ByRef lpBuffer As [String], _
ByVal nSize As Integer, ByRef Arguments As IntPtr) As Integer
End Function
#End Region
End Class