Sunday, August 17, 2008

Impersonation in VB6

Since VB6 is released around 1998 or earlier, and now we are on year 2008, this topic might be obsolete for some to discuss. Since supporting legacy system is inevitable, I have something simple but might useful to share, on impersonation.

(Sample source discussed can be downloaded here.)

When an application needs to perform any operation on a network folder, using UNC path, it's not like what we can simply do anything in our own drives. Let's say we try to do file copy with vb6 app using:

FileCopy App.Path & "\HelloWorld.txt", txtCurrNetworkPath.Text & "\HelloWorld.txt"

You will get this:

Some folders in the network only permit for certain personnel to access, to deal with it you must able to prove you are authorized to access it. By using LogonUser() API function, you can achieve it.

Visual Basic 6 provides an Win32 API viewer for you to invoke (copy-and-paste in source) it, it's normally located at: "Start">"All Programs">"Microsoft Visual Studio 6.0">"Microsoft Visual Studio 6.0 Tools">"API Text Viewer".

For the first-time user, you might need to load the look-up files or database before you can see the available API.

Type the API that you are looking for and the result will be filtered in real-time. Now you can get what you want, but beware the gotcha. It mentions you need to add reference with "Kernel32.lib":

From MSDN mentioned earlier, the actual library you need is "Advapi32.lib". OK, now you refer it using the correct library in the source with:

Private Declare Function LogonUser Lib "advapi32.dll" Alias _
"LogonUserA" _
(ByVal lpszUsername As String, _
ByVal lpszDomain As String, _
ByVal lpszPassword As String, _
ByVal dwLogonType As Long, _
ByVal dwLogonProvider As Long, _
phToken As Long) As Long

And we find a remote pc with a folder shared.

Let set "everybody" can access on it.


using this account in system account database, as shown in "Computer Management":

Next if you follow this tutorial (How to impersonate a user from Active Server Pages) or another tutorial (How to start a process as another user from Visual Basic), and apply it on a simple "Standard EXE".

You might use "LOGON32_LOGON_INTERACTIVE" as parameter "dwLogonType". Now you try to run it and you will get this error message:


What the heck?

Could it be this parameter "dwLogonType" that casue the error? So we browse to Win32 header file (usually at: C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Include) first and check the possible value for parameter "dwLogonType" since we know the domain/user/password are all correct. From "winbase.h", "9" represent another constant for "LOGON32_LOGON_NEW_CREDENTIALS".

Declaring it at our VB6 application:

Private Const LOGON32_LOGON_NEW_CREDENTIALS = 9

replaces "LOGON32_LOGON_INTERACTIVE" with it as parameter "dwLogonType" for LogonUser() function and eventually it works.

Note that in some pc, the impersonation might take long time.

Also, the allowed user for accessing the shared folder must be taken note as well. Previously we use PC name or IP address as our domain for a shared folder that can be accessed by "everyone"; if only a particular user in Active Directory (AD) can access a network folder, then you must provide AD account to impersonate, instead of account in system account database.

If you have logon-ed the remote shared folder from "Run" before, the previous example might be useless to prove its worth. Try reboot your pc before you try example above.

3 comments:

deepdraw said...

Hi, i spent ages trying to work out how to do this, can you email the code for this to parky_003 at hotmail.com
many thanks

Greg

Mathew Joseph said...

Thanks a lot.Very valuable

NightBiker said...

Hi, I am also interested in taking a look at your code .
can you send it to me? ruglor@gmail.com
Thank you.