Application EventsIntroduction To XML Comments

Impersonation Class

May 18th, 2007

Impersonation allows an user or a process temporary access to secured resourcesIn today’s business environment more and more companies are securing the PC’s of many employees to prevent damage to their systems via malware downloaded over the Internet or user mistakes. On web servers running publicly available web services, administrators wisely don’t want to expose resources to just anyone. However, as we develop software we may find it necessary to access forbidden resources like certain areas of the registry or a file store on a network server. How can we do this and still keep the application and the system secure? Fortunately, we can use impersonation to solve this problem.

The code below is a simple class I wrote for this purpose. The class is declared as a Friend class rather than Public to avoid any accidential exposure to outside processes. The New method is overloaded so that an unintialized instance can be created as well as one that has credentials passed into it. The empty new method also allows easy subclassing so that other methods for initialization could be added as desired. Impersonation is started in the StartImpersonation method. EndImpersonation ends the session and the Finalize method helps insure that impersonation is ended when the instance is destroyed. The current state of impersonation can be checked in the ImpersonationActive read-only property.

This method is not without risks. First of all, the complete user login credentials have to be passed in as clear text. This means that you will need to use some type of encryption to protect this information at the very least. To protect these credentials further you may want to look into using secure strings.

ยป Click here to download VB.NET source code for this article or view it below.

Imports Microsoft.VisualBasic
Imports System.Web
Imports System.Web.Security
Imports System.Security.Principal
Imports System.Runtime.InteropServices

''' <summary>
''' Provides impersonation to allow access to resources
''' </summary>
''' <remarks></remarks>
Friend Class Impersonate
    Private LOGON32_LOGON_INTERACTIVE As Integer = 2
    Private LOGON32_PROVIDER_DEFAULT As Integer = 0

    Private impersonationContext As WindowsImpersonationContext

    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 Integer, _
                            ByRef DuplicateTokenHandle As IntPtr) As Integer

    Private Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long
    Private Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long

    Private _impersonationActive As Boolean

    ''' <summary>
    ''' Allows creation of a new instance without starting impersonation
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub New()

    End Sub

    ''' <summary>
    ''' starts impersonation with specified parameters
    ''' </summary>
    ''' <param name="userName">username to impersonate</param>
    ''' <param name="domain">domain for user</param>
    ''' <param name="password">password for user</param>
    ''' <remarks></remarks>
    Public Sub New(ByVal userName As String, ByVal domain As String, ByVal password As String)
        StartImpersonation(userName, domain, password)
    End Sub

    ''' <summary>
    ''' starts impersonation with specified parameters
    ''' </summary>
    ''' <param name="userName">username to impersonate</param>
    ''' <param name="domain">domain for user</param>
    ''' <param name="password">password for user</param>
    ''' <remarks></remarks>
    Public Function StartImpersonation(ByVal userName As String, ByVal domain As String, ByVal password As String) As Boolean
        Dim ReturnValue As Boolean = False
        Dim tempWindowsIdentity As WindowsIdentity
        Dim token As IntPtr = IntPtr.Zero
        Dim tokenDuplicate As IntPtr = IntPtr.Zero

            StartImpersonation = False

            If CBool(RevertToSelf()) 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
                            ReturnValue = True
                            _impersonationActive = 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
        Return ReturnValue
    End Function

    ''' <summary>
    ''' Ends impersonation session and returns thread back to original user
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub EndImpersonation()
        impersonationContext.Undo()
        _impersonationActive = False
    End Sub

    Protected Overrides Sub Finalize()
        If _impersonationActive Then
            impersonationContext.Undo()
            _impersonationActive = False
        End If
        MyBase.Finalize()
    End Sub

    Public ReadOnly Property ImpersonationActive() As Boolean
        Get
            Return _impersonationActive
        End Get
    End Property
End Class
Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

Entry Filed under: Code Examples


Rate This Article:

Not That GoodCould Be BetterOKGoodGreat (4 votes, average: 5 out of 5)
Loading ... Loading ...

1 Comment Add your own

  • 1. John  |  April 24th, 2009 at 5:35 pm

    Thank you, thank you, thank you. This class solved a problem I’ve been working on for days.

Leave a Comment

Required

Required, hidden

Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Trackback this post  |  Subscribe to the comments via RSS Feed


Visit Me At My New Site, Programming In C#

Most Popular Articles

Highest Rated Articles

Categories

Most Recent Articles

Feeds

 Subscribe in a reader

To subscribe by e-mail
Enter your address here

Delivered by FeedBurner

VB Opportunities

Archives