windowsvb.netimpersonationcomobject

Is it possible to duplicate the following credential process in VB.NET?


Solution (kinda):

Turns out this impersonation with .NET's security only allows application-level access. Since the COM object is at the system level, the impersonated user still cannot instantiate it. I figured this out by right-clicking the executable and selecting "Run As...", the program functioned fine. I found out that launches the program with system access (assuming the user you are running it with has those credentials). Now I am in the process of creating an external program that will launch this application using this method.

Thanks for the tips :D


I have a windows XP installation on a virtual machine. It is part of my domain, but the logged in user is a local user only. Obviously, if I try to access a network share it will prompt for a user/password:

alt text

The program I am testing out on the virtual machine uses a COM object to interface with data from another program. If I do not impersonate, I get errors because I do not have the proper credentials.

I did some research into the matter and found a number of websites that had a decent amount of VB.NET information. The problem I am having with the code I wrote is I can access the network resources, but I cannot instantiate the COM object.

If I fill and submit the credential prompt (above) before attempting to instantiate it, it works fine. That leads me to believe there must be something that the WinXP credential prompt is doing that I am not. Below is the code I am using for Impersonation:

Public Sub BeginImpersonation()
    Const LOGON32_PROVIDER_DEFAULT As Integer = 0
    Const LOGON32_LOGON_INTERACTIVE As Integer = 2
    Const SecurityImpersonation As Integer = 2

    Dim win32ErrorNumber As Integer

    _tokenHandle = IntPtr.Zero
    _dupeTokenHandle = IntPtr.Zero

    If Not LogonUser(_username, _domainname, _password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, _tokenHandle) Then
        win32ErrorNumber = System.Runtime.InteropServices.Marshal.GetLastWin32Error()
        Throw New ImpersonationException(win32ErrorNumber, GetErrorMessage(win32ErrorNumber), _username, _domainname)
    End If

    If Not DuplicateToken(_tokenHandle, SecurityImpersonation, _dupeTokenHandle) Then
        win32ErrorNumber = System.Runtime.InteropServices.Marshal.GetLastWin32Error()

        CloseHandle(_tokenHandle)
        Throw New ImpersonationException(win32ErrorNumber, "Unable to duplicate token!", _username, _domainname)
    End If

    Dim newId As New System.Security.Principal.WindowsIdentity(_dupeTokenHandle)
    _impersonatedUser = newId.Impersonate()
    _impersonating = True
End Sub

I have also tried sending different flags to the impersonator method, but nothing seems to be working. Here are the different flags I found:

Enum LOGON32_LOGON
    INTERACTIVE = 2
    NETWORK = 3
    BATCH = 4
    SERVICE = 5
    UNLOCK = 7
    NETWORK_CLEARTEXT = 8
    NEW_CREDENTIALS = 9
End Enum
Enum LOGON32_PROVIDER
    [DEFAULT] = 0
    WINNT35 = 1
    WINNT40 = 2
    WINNT50 = 3
End Enum
Enum SECURITY_LEVEL
    Anonymous = 0
    Identification = 1
    Impersonation = 2
    Delegation = 3
End Enum

Solution

  • I have run into this before, and used two different soloution - the easiest was using a third party app: TqcRunas: http://www.quimeras.com/Products/products.asp which allows you to package the required creentials in an encrypted file. However is a pain if the password is forced to expire.

    The other solution that I have used is to call a new process with alternative credentials:

            Dim myProcessStartInfo As ProcessStartInfo = New ProcessStartInfo
    
        With myProcessStartInfo
    
            .FileName = "file path and name"
    
            .Domain = "domainname"
            .UserName = "username"
    
            'password needs to be a SerureString
            Using NewPassword As New Security.SecureString
                With NewPassword
                    For Each c As Char In "password".ToCharArray
                        .AppendChar(c)
                    Next c
                    .MakeReadOnly()
                End With
                .Password = NewPassword.Copy
            End Using
    
            'UseShellExecute must be false for impersonated process
            .UseShellExecute = False
    
        End With
    
        Using Process As New System.Diagnostics.Process
            With Process
                .StartInfo = myProcessStartInfo
                .Start()
            End With
        End Using