Question

Current User Token

Asked by: dentab

I now have the code to impersonate a user using VB6:
http://www.experts-exchange.com/Programming/Languages/Visual_Basic/Q_24798823.html?cid=1575#a25548098

Since getting this code, I have been finding new uses for it.  One such use is inside a DLL called by IIS.  The problem is that IIS impersonates the remote user (ANON access is off) and so calling LogOff does not revert to the user that was running the page before LogOn, but rather it will change to NETWORK SERVICE

I would like to know how to get the current users token as returned in
Private Declare Function LogonUserW Lib "advapi32" (ByVal lpszUsername As Long, ByVal lpszDomain As Long, ByVal lpszPassword As Long, ByVal dwLogonType As Long, ByVal dwLogonProvider As Long, phToken As Long) As Long

I want the current users token, without specifying A password - they are already logged on.

This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2009-10-12 at 13:10:55ID24805816
Tags

VB6

,

Permissions

,

Security Tokens

,

User Impersonation

Topic

Visual Basic Programming

Participating Experts
1
Points
500
Comments
37

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. Thread token !!!
    I have a service application starting with LocalSystem account. In an other process using an IPC with this service, i would assign the service thread token (the thread with LocalSystem account) TO one of my process thread token in order to execute some restricted Win32 funct...
  2. String Tokenizer
    Hi there, i would like to know if anybody has a function or procedure which separates the words of a string in tokens i mean i have a string s:='a1,b34,c2345,d3,f3535' and need to separate a1, b34, c2345,... and set that values in an array :)- Thanks
  3. Hardware tokens
    Hello all, I'd like to know which of these you prefer and why - CryptoCard - Safeword - Secure-ID - Some brand I might have forgotten to mention Few restrictions: I am only looking for info about hardware tokens. So no USB, phoneintegrated, whatever kinda stuff. Cheers fo...
  4. token?
    pls explain what is token meaning from the following? char *strtok( char *s1, const char *s2 ); A sequence of calls to strtok breaks string s1 into tokenslogical pieces such as words in a line of textseparated by characters contained in string s2. The first call contains...

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: egl1044Posted on 2009-10-12 at 14:39:30ID: 25555312

Hi dentab,

I am not sure the problem here but (user token) can all be accessed by the following:
LogonUser, CreateRestrictedToken, DuplicateToken, OpenProcessToken, or OpenThreadToken function.

Option Explicit
 
Private Const TOKEN_IMPERSONATE = &H4&
Private Const TOKEN_QUERY = &H8&
 
Private Declare Function GetUserProfileDirectoryW Lib "userenv" (ByVal hToken As Long, ByVal lpProfileDir As Long, ByRef lpcchSize As Long) As Long
Private Declare Function OpenProcessToken Lib "advapi32" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, ByRef TokenHandle As Long) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
 
Private Function GetUserProfile(ByVal dwTokenHandle As Long) As String
  
  Dim Buffer() As Byte
  Dim dwSize As Long
  
  ReDim Buffer(4096) As Byte
  dwSize = 4096
  If GetUserProfileDirectoryW(dwTokenHandle, VarPtr(Buffer(0)), dwSize) Then
    ReDim Preserve Buffer(dwSize * 2 - 2) As Byte '// unicode bytes
    GetUserProfile = Buffer
  End If
  Erase Buffer
End Function
 
Public Sub UserToken()
  
  Dim hToken As Long
 
  If OpenProcessToken(GetCurrentProcess, TOKEN_QUERY Or TOKEN_IMPERSONATE, hToken) Then
    MsgBox GetUserProfile(hToken)
    CloseHandle hToken
  End If
 
End Sub
 
 
Private Sub Command1_Click()
UserToken
End Sub

                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:

Select allOpen in new window

 

by: dentabPosted on 2009-10-13 at 00:47:13ID: 25557735

Hi egl

IIS uses impersonate user, so when I write ASP thet uses it too, instead of reverting to the "remote user" on logoff, it reverts to NETWORK SERVICE.  To remedy this, I need to capture the current user token before using logonuser so that afterwards I can impersonate using the stored token instead of passing a username and password.

Hope that makes more sense, I will try your example shortly.

thanks again!

 

by: dentabPosted on 2009-10-13 at 00:52:26ID: 25557751

for clarity using what you have given me already it would be, using imaginary functions that I would like to have exist.

curUser = GetCurrentUserToken
newUser=GetNewUserToken("username", "password", "mydomain")
LogonWithToken newUser
DoStuff "Imaginary task done as impersonated user"
LogonWithToken curUser 'Return to user that was impersonated BEFORE my code run

 

by: dentabPosted on 2009-10-13 at 02:55:54ID: 25558283

Sorry egl, I do not seem to be able to do this with your code.

What I would want is something like
curUser = GetCurrentUserToken
newUser=GetNewUserToken("username", "password", "mydomain")
LogonWithToken newUser
DoStuff "Imaginary task done as impersonated user"
LogonWithToken curUser 'Return to user that was impersonated BEFORE my code run

I think LogonWithToken would look like the function below and I assumed GetCurrentUserToken from your coude would also be like the function I have listed below.

I hope this makes sense... esentially
  I need to switch from user A to B and back to A
User B I have the password for, but user A is a variable.  It is who will be running the process however.
I cannot use the RevertToSelf, because IIS is already impersonating a user and RevertToSelf will switch the current user to be NETWORK SERVICE.

I really appreciate your help on this, my Google powers fail me on this one.

Public Function LogOnWithToken(thisToken As Long)
  '// log off any previous impersonation.
  LogOff
  
  '// attempt to log on a a user
  hToken = thisToken
  
  If ImpersonateLoggedOnUser(hToken) Then
    impersonationactive = True
    '// the process should be granted the
    '// logged on token.
    LogOnWithToken = True      
  Else
    impersonationactive = False
    LogOnWithToken = False      
  End If
  '// cleanup token handle.
  CloseHandle hToken   
End Function
 
Function GetNewUserToken() As Long
  Call OpenProcessToken(GetCurrentProcess, TOKEN_QUERY Or TOKEN_IMPERSONATE, hToken)
  CurrentToken = hToken
End Function

                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:

Select allOpen in new window

 

by: egl1044Posted on 2009-10-13 at 05:44:22ID: 25559253

Unfortunately ImpersonateLoggedOnUser is used only in conjuction with LogOnUser from my understanding so that type of call won't work. You should however be able to something like this but using (SetThreadToken) instead.

Private Declare Function SetThreadToken Lib "advapi32" (ByVal Thread As Long, ByVal Token As Long) As Long
 
 SetThreadToken 0, hTokenUser

                                              
1:
2:
3:

Select allOpen in new window

 

by: dentabPosted on 2009-10-13 at 06:40:19ID: 25559733

it no work for me :(

I will have a play with it, but not having any joy so far.

 

by: egl1044Posted on 2009-10-13 at 06:43:21ID: 25559775

This should remove all impersonation. You might need to call DuplicateTokenEx on the token handle before you do this. I am still not sure about the problem RevertToSelf should work

SetThreadToken 0, 0

                                              
1:

Select allOpen in new window

 

by: dentabPosted on 2009-10-13 at 06:51:32ID: 25559887

thats the problem RevertToSelf DOES work....

I am writing in for IIS
IIS appears to use Impersonation too, so
Lets say NETWORK SERVICE is User A
Annon User or, a remote user is User B
and the impersonation user I want is User C


IIS loads under USER A
This is an intranet site with annon access off, so it gets my credentials
IIS Impersonates my user (USER B)
IIS runs my webpage (which calls my DLL)
I call Impersonate User, I get USER C
so far so good
I call RevertToSelf
I get USER A (NETWORK SERVICE)

 

by: dentabPosted on 2009-10-13 at 06:59:56ID: 25559995

now I know all this, my DLL needs to capture the token for User B and
when I have finished with User C
instead of revertingtoself I need to Impersonate User B

question is, how do I do this without asking for username and password.  I expect this is possible because it will be who I was running as at a particular point in time but how?

To give you an idea of whats happening, my DLL from my ASP page is using Impersonate User where I am logged on as DenTab and browsing to my web
The code below has the following effect:
DenTab
DenAdmin
NETWORK SERVICE
DenTab

Response.Write curWinUser '(linked to GetUserName Lib "advapi32.dll")
LogOn "DenAdmin", "password", "DenDomain"
Response.Write curWinUser 
LogOff
Response.Write curWinUser 

                                              
1:
2:
3:
4:
5:

Select allOpen in new window

 

by: dentabPosted on 2009-10-13 at 07:05:18ID: 25560050

woops, the output is

DenTab
DenAdmin
NETWORK SERVICE

I diddnt mean the extra DenTab

 

by: egl1044Posted on 2009-10-13 at 07:05:58ID: 25560059

What do you get after making this call:

SetThreadToken 0, 0

                                              
1:

Select allOpen in new window

 

by: dentabPosted on 2009-10-13 at 07:11:24ID: 25560112

Not sure if this applies:

https://forum.eviloctal.com/thread-22081-1-5.html

Then, when a service accepts a client, it creates a thread to do the work and associates the clients access token with the worker thread. Once associated in this way, the clients access token is an impersonation token that identifies the client, the clients groups, and the clients privileges. The impersonation tokens information is used during access checks when the thread requests access to resources on the clients behalf. When impersonation is over, the thread reverts to using the primary token and returns to operating in the services security context instead of the clients.

 

by: dentabPosted on 2009-10-13 at 07:29:06ID: 25560285

SetThreadToken 0, 0

has no effect

 

by: dentabPosted on 2009-10-13 at 07:31:51ID: 25560309

by no effect, I mean if I replace the reverttoself, I get

DenTab
DenAdmin
DenAdmin

So it is not changing the current user at all
(The desired output being)
DenTab
DenAdmin
DenTab

 

by: egl1044Posted on 2009-10-13 at 08:11:10ID: 25560819

I can't really debug this because I honestly know nothing about IIS.:(

Can you try this call in your DLL and see if it succeeds. I can't test it on my side.

  Private Const TOKEN_IMPERSONATE = &H4&
Private Const TOKEN_DUPLICATE = &H2&
Private Const TOKEN_QUERY = &H8&
Debug.Print OpenThreadToken(GetCurrentThread, TOKEN_QUERY Or TOKEN_DUPLICATE Or TOKEN_IMPERSONATE, 0, hTokenUser)
Debug.Print Err.LastDllError
CloseHandle hTokenUser

                                              
1:
2:
3:
4:
5:
6:

Select allOpen in new window

 

by: dentabPosted on 2009-10-13 at 08:23:12ID: 25560952

ok, I will

I could give you a test VB6 app that can "replicate" the problem, providing you have a user (besides yourself) to test with.

again, I do appreciate your help on this.

 

by: egl1044Posted on 2009-10-13 at 08:52:45ID: 25561257

Okay I got it to work with user token but only with a process I created with VB. The problem here is your DLL is loaded into IIS service from what I gather. But if you take a look at this example it changes the token back to the launched user.

I tested this by logging on a limited account(XP) I made a call to LogOn with administrator information. Then executed the example code which worked. The trick though is to make this work inside your DLL from which IIS is loading. This might give you some insight on how to make it work. I am afraid since I know little to nothign about IIS it's hard to come to a conclusion I would suspect you need to use OpenThreadToken() instead if IIS is creating a new thread but I can't be certain :(

Option Explicit
 
Private Const TOKEN_IMPERSONATE = &H4&
Private Const TOKEN_DUPLICATE = &H2&
Private Const TOKEN_QUERY = &H8&
 
Private Declare Function DuplicateTokenEx Lib "advapi32" (ByVal hExistingToken As Long, ByVal dwDesiredAccess As Long, ByVal lpTokenAttributes As Long, ByVal ImpersonationLevel As Long, ByVal TokenType As Long, ByRef phNewToken As Long) As Long
Private Declare Function SetThreadToken Lib "advapi32" (ByVal Thread As Long, ByVal Token As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function OpenProcessToken Lib "advapi32" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, ByRef TokenHandle As Long) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
 
Dim hTokenUserA As Long
 
Public Sub GetUserToken()
 
  Dim hTokenUser As Long
  If OpenProcessToken(GetCurrentProcess, TOKEN_QUERY Or TOKEN_DUPLICATE Or TOKEN_IMPERSONATE, hTokenUser) Then
    If DuplicateTokenEx(hTokenUser, 0, 0, 2, 2, hTokenUserA) Then
      MsgBox "Duplicate Success"
    End If
  CloseHandle hTokenUser
 End If
 
End Sub
 
Public Sub SetUserLaunchToken()
  SetThreadToken 0, hTokenUserA
  'CloseHandle hTokenUserA
End Sub
 
Private Sub Command1_Click()
  SetUserLaunchToken '//revert to user launch token
End Sub
 
Private Sub Form_Load()
 
  GetUserToken '// get user token on load
  
End Sub

                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:

Select allOpen in new window

 

by: dentabPosted on 2009-10-13 at 10:09:13ID: 25561984

That looks very promising...

I will demo soon (it might be in the morning), but I think we are on the same page now :)

 

by: dentabPosted on 2009-10-14 at 05:48:45ID: 25569831

I am testing it in VB...

GetCurrentProcess is returning -1

 

by: egl1044Posted on 2009-10-14 at 06:06:09ID: 25569976

That is what it should return it's a pseudo handle not a real handle. What are you testing?

 

by: dentabPosted on 2009-10-14 at 06:12:59ID: 25570029

ah... well

my test code is below

Private Sub Form_Load()
  oClear
    
  o "Proc: " & getCurrentProcess
  o
  oUser
  o
  
  o "Impersonating Admin"
  LogOn_Admin
  oUser
  o
  
  o "Storing Token"
  GetUserToken
  o
  
  o "Impersonating Standard User"
  LogOn_StandardUser
  oUser
  o
    
  o "Restoring Token"
  SetUserLaunchToken
  oUser
  o
    
  
  LogOff
  oUser
End Sub
 
 
Private Sub o(Optional ByVal strOutput As String = "-")
  If strOutput = "-" Then strOutput = "---------------------"
  List1.AddItem strOutput
End Sub
 
Private Sub oUser()
  o "Current User: " & getCurrentUser
End Sub
 
Private Sub oClear()
  List1.Clear
End Sub

                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:

Select allOpen in new window

 

by: dentabPosted on 2009-10-14 at 06:14:09ID: 25570043

and the module

Private Const LOGON32_LOGON_INTERACTIVE As Long = &H2&
Private Const LOGON32_PROVIDER_DEFAULT As Long = &H0&
Private Const TOKEN_IMPERSONATE = &H4&
Private Const TOKEN_DUPLICATE = &H2&
Private Const TOKEN_QUERY = &H8&
 
Private Declare Function DuplicateTokenEx Lib "advapi32" (ByVal hExistingToken As Long, ByVal dwDesiredAccess As Long, ByVal lpTokenAttributes As Long, ByVal ImpersonationLevel As Long, ByVal TokenType As Long, ByRef phNewToken As Long) As Long
Private Declare Function ImpersonateLoggedOnUser Lib "advapi32" (ByVal hToken As Long) As Long
Private Declare Function LogonUserW Lib "advapi32" (ByVal lpszUsername As Long, ByVal lpszDomain As Long, ByVal lpszPassword As Long, ByVal dwLogonType As Long, ByVal dwLogonProvider As Long, ByRef phToken As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function RevertToSelf Lib "advapi32" () As Long
Private Declare Function GetUserProfileDirectoryW Lib "userenv" (ByVal hToken As Long, ByVal lpProfileDir As Long, ByRef lpcchSize As Long) As Long
Private Declare Function OpenProcessToken Lib "advapi32" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, ByRef TokenHandle As Long) As Long
Public Declare Function getCurrentProcess Lib "kernel32" Alias "GetCurrentProcess" () As Long
Private Declare Function SetThreadToken Lib "advapi32" (ByRef Thread As Long, ByVal Token As Long) As Integer
Private Declare Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" (ByVal lpbuffer As String, nSize As Long) As Long
 
Private Const impersonation_ADMIN_User As String = "AppUser_Admin"
Private Const impersonation_ADMIN_Password As String = "password"
Private Const impersonation_ADMIN_Domain As String = "domain"
Private Const impersonation_STANDARD_User As String = "AppUser_Std"
Private Const impersonation_STANDARD_Password As String = "password"
Private Const impersonation_STANDARD_Domain As String = "domain"
Private hTokenUserA As Long
 
Dim hToken As Long
Dim success As Long
Public impersonationactive As Boolean
 
 
Public Sub GetUserToken()
 
  Dim hTokenUser As Long
  If OpenProcessToken(getCurrentProcess, TOKEN_QUERY Or TOKEN_DUPLICATE Or TOKEN_IMPERSONATE, hTokenUser) Then
    If DuplicateTokenEx(hTokenUser, 0, 0, 2, 2, hTokenUserA) Then
      MsgBox "Duplicate Success"
    Else
      MsgBox "Fail"
    End If
  CloseHandle hTokenUser
 Else
   Debug.Print "getCurrentProcess: " & CStr(getCurrentProcess)
 End If
 
End Sub
 
Public Sub SetUserLaunchToken()
  SetThreadToken 0, hTokenUserA
  'CloseHandle hTokenUserA
End Sub
 
' ********
 
'
'Private Sub Command1_Click()
'  SetUserLaunchToken '//revert to user launch token
'End Sub
'
'Private Sub Form_Load()
'
'  GetUserToken '// get user token on load
'
'End Sub
'
 
'*********
 
 
 
Public Sub LogOn_Admin()
  LogOn impersonation_ADMIN_User, impersonation_ADMIN_Password, impersonation_ADMIN_Domain
End Sub
 
Public Sub LogOn_StandardUser()
  LogOn impersonation_STANDARD_User, impersonation_STANDARD_Password, impersonation_STANDARD_Domain
End Sub
 
Public Function LogOn( _
  ByVal szUser As String, _
  ByVal szPassword As String, _
  ByVal szDomain As String) As Boolean
  
  '// log off any previous impersonation.
  LogOff
  
  '// attempt to log on a a user
  success = LogonUserW( _
    StrPtr(szUser), _
    StrPtr(szDomain), _
    StrPtr(szPassword), _
    LOGON32_LOGON_INTERACTIVE, _
    LOGON32_PROVIDER_DEFAULT, _
    hToken)
 
  If success Then
    If ImpersonateLoggedOnUser(hToken) Then
      impersonationactive = True
      '// the process should be granted the
      '// logged on token.
      LogOn = True
      
    Else
      impersonationactive = False
      LogOn = False
      
    End If
    '// cleanup token handle.
    CloseHandle hToken
  
  Else
  
    LogOn = False
    
  End If
  
End Function
 
 
Public Sub LogOff()
  
  '// logs off the impersonation.
'  SetThreadToken 0, 0
  RevertToSelf
 
  impersonationactive = False
End Sub
 
 
 
 
Private Function GetUserProfile(ByVal dwTokenHandle As Long) As String
  
  Dim Buffer() As Byte
  Dim dwSize As Long
  
  ReDim Buffer(4096) As Byte
  dwSize = 4096
  If GetUserProfileDirectoryW(dwTokenHandle, VarPtr(Buffer(0)), dwSize) Then
    ReDim Preserve Buffer(dwSize * 2 - 2) As Byte '// unicode bytes
    GetUserProfile = Buffer
  End If
  Erase Buffer
End Function
 
 
 
 
Public Function LogOnWithToken(thisToken As Long)
  '// log off any previous impersonation.
  LogOff
  '// attempt to log on a a user
  hToken = thisToken
  If ImpersonateLoggedOnUser(hToken) Then
    impersonationactive = True
    '// the process should be granted the
    '// logged on token.
    LogOnWithToken = True
  Else
    impersonationactive = False
    LogOnWithToken = False
  End If
  '// cleanup token handle.
  CloseHandle hToken
End Function
 
Public Function getCurrentUser() As String
  Dim sBuffer As String
  Dim lSize As Long
 
  sBuffer = Space$(255)
  lSize = Len(sBuffer)
  Call GetUserName(sBuffer, lSize)
  sBuffer = Trim$(Left$(sBuffer, lSize))
  lSize = InStr(sBuffer, vbNullChar)
  If lSize > 0 Then
    sBuffer = Left$(sBuffer, lSize - 1)
  End If
  getCurrentUser = sBuffer
End Function
 
 
Function CurrentToken() As Long
  Dim cUT As Long
  Call OpenProcessToken(getCurrentProcess, TOKEN_QUERY Or TOKEN_IMPERSONATE, cUT)
  CurrentToken = cUT
  CloseHandle hToken
End Function
                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:

Select allOpen in new window

 

by: dentabPosted on 2009-10-14 at 06:14:47ID: 25570050

should mention, the test form basicly just has a listbox

 

by: dentabPosted on 2009-10-14 at 06:16:27ID: 25570068

This line is failing
  If OpenProcessToken(getCurrentProcess, TOKEN_QUERY Or TOKEN_DUPLICATE Or TOKEN_IMPERSONATE, hTokenUser) Then

 

by: dentabPosted on 2009-10-14 at 06:22:16ID: 25570125

remove some of the junk I hed left in from the code module

Private Const LOGON32_LOGON_INTERACTIVE As Long = &H2&
Private Const LOGON32_PROVIDER_DEFAULT As Long = &H0&
Private Const TOKEN_IMPERSONATE = &H4&
Private Const TOKEN_DUPLICATE = &H2&
Private Const TOKEN_QUERY = &H8&
 
Private Declare Function DuplicateTokenEx Lib "advapi32" (ByVal hExistingToken As Long, ByVal dwDesiredAccess As Long, ByVal lpTokenAttributes As Long, ByVal ImpersonationLevel As Long, ByVal TokenType As Long, ByRef phNewToken As Long) As Long
Private Declare Function ImpersonateLoggedOnUser Lib "advapi32" (ByVal hToken As Long) As Long
Private Declare Function LogonUserW Lib "advapi32" (ByVal lpszUsername As Long, ByVal lpszDomain As Long, ByVal lpszPassword As Long, ByVal dwLogonType As Long, ByVal dwLogonProvider As Long, ByRef phToken As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function RevertToSelf Lib "advapi32" () As Long
Private Declare Function GetUserProfileDirectoryW Lib "userenv" (ByVal hToken As Long, ByVal lpProfileDir As Long, ByRef lpcchSize As Long) As Long
Private Declare Function OpenProcessToken Lib "advapi32" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, ByRef TokenHandle As Long) As Long
Public Declare Function getCurrentProcess Lib "kernel32" Alias "GetCurrentProcess" () As Long
Private Declare Function SetThreadToken Lib "advapi32" (ByRef Thread As Long, ByVal Token As Long) As Integer
Private Declare Function GetUserName Lib "advapi32.dll" Alias "GetUserNameA" (ByVal lpbuffer As String, nSize As Long) As Long
 
Private Const impersonation_ADMIN_User As String = "AppUser_Admin"
Private Const impersonation_ADMIN_Password As String = "PASSWORD1"
Private Const impersonation_ADMIN_Domain As String = "ADMIN"
Private Const impersonation_STANDARD_User As String = "AppUser_Std"
Private Const impersonation_STANDARD_Password As String = "PASSWORD2"
Private Const impersonation_STANDARD_Domain As String = "ADMIN"
Private hTokenUserA As Long
Private hToken As Long
 
Dim success As Long
Public impersonationactive As Boolean
 
 
Public Sub GetUserToken()
 
  Dim hTokenUser As Long
  If OpenProcessToken(getCurrentProcess, TOKEN_QUERY Or TOKEN_DUPLICATE Or TOKEN_IMPERSONATE, hTokenUser) Then
    If DuplicateTokenEx(hTokenUser, 0, 0, 2, 2, hTokenUserA) Then
      MsgBox "Duplicate Success"
    Else
      MsgBox "Fail"
    End If
  CloseHandle hTokenUser
 
 End If
 
End Sub
 
Public Sub SetUserLaunchToken()
  SetThreadToken 0, hTokenUserA
  CloseHandle hTokenUserA
End Sub
 
 
 
 
 
Public Sub LogOn_Admin()
  LogOn impersonation_ADMIN_User, impersonation_ADMIN_Password, impersonation_ADMIN_Domain
End Sub
 
Public Sub LogOn_StandardUser()
  LogOn impersonation_STANDARD_User, impersonation_STANDARD_Password, impersonation_STANDARD_Domain
End Sub
 
Public Function LogOn( _
  ByVal szUser As String, _
  ByVal szPassword As String, _
  ByVal szDomain As String) As Boolean
  
  '// log off any previous impersonation.
  LogOff
  
  '// attempt to log on a a user
  success = LogonUserW( _
    StrPtr(szUser), _
    StrPtr(szDomain), _
    StrPtr(szPassword), _
    LOGON32_LOGON_INTERACTIVE, _
    LOGON32_PROVIDER_DEFAULT, _
    hToken)
 
  If success Then
    If ImpersonateLoggedOnUser(hToken) Then
      impersonationactive = True
      '// the process should be granted the
      '// logged on token.
      LogOn = True
      
    Else
      impersonationactive = False
      LogOn = False
      
    End If
    '// cleanup token handle.
    CloseHandle hToken
  
  Else
  
    LogOn = False
    
  End If
  
End Function
 
 
Public Sub LogOff()
  
  '// logs off the impersonation.
'  SetThreadToken 0, 0
  RevertToSelf
 
  impersonationactive = False
End Sub
 
 
 
 
Private Function GetUserProfile(ByVal dwTokenHandle As Long) As String
  
  Dim Buffer() As Byte
  Dim dwSize As Long
  
  ReDim Buffer(4096) As Byte
  dwSize = 4096
  If GetUserProfileDirectoryW(dwTokenHandle, VarPtr(Buffer(0)), dwSize) Then
    ReDim Preserve Buffer(dwSize * 2 - 2) As Byte '// unicode bytes
    GetUserProfile = Buffer
  End If
  Erase Buffer
End Function
 
Public Function getCurrentUser() As String
  Dim sBuffer As String
  Dim lSize As Long
 
  sBuffer = Space$(255)
  lSize = Len(sBuffer)
  Call GetUserName(sBuffer, lSize)
  sBuffer = Trim$(Left$(sBuffer, lSize))
  lSize = InStr(sBuffer, vbNullChar)
  If lSize > 0 Then
    sBuffer = Left$(sBuffer, lSize - 1)
  End If
  getCurrentUser = sBuffer
End Function

                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:

Select allOpen in new window

 

by: egl1044Posted on 2009-10-14 at 06:23:26ID: 25570138

Yes the problem is that when I did my test I used my own executable. If your testing this from your IIS DLL it might fail. That is why I asked if you could test the OpenThreadToken() from your DLL to see if that fails. OpenProcessToken should work if from your executable context. The problem here is your DLL is being loaded by the IIS service from what you mentioned this means it would be running in the context of the IIS service.

 

by: dentabPosted on 2009-10-14 at 06:25:03ID: 25570148

I am not doing it from IIS, I am doing it from VB...

Once I have it working in a VB executable I will move it to IIS

 

by: dentabPosted on 2009-10-14 at 06:31:06ID: 25570215

I have attached my demo app, if you have a moment to look.

thank you.

 

by: egl1044Posted on 2009-10-14 at 06:33:21ID: 25570240

Okay. I'll post what I had if you want to just create a new project exactly like it.

I put 3 command buttons on a form. (log on) (username) (conver to launched user)


'//
'// Module1.bas
'//
 
Option Explicit
 
Private Const LOGON32_LOGON_INTERACTIVE As Long = &H2&
Private Const LOGON32_PROVIDER_DEFAULT As Long = &H0&
 
Private Declare Function ImpersonateLoggedOnUser Lib "advapi32" (ByVal hToken As Long) As Long
Private Declare Function LogonUserW Lib "advapi32" (ByVal lpszUsername As Long, ByVal lpszDomain As Long, ByVal lpszPassword As Long, ByVal dwLogonType As Long, ByVal dwLogonProvider As Long, phToken As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function RevertToSelf Lib "advapi32" () As Long
 
Dim hToken As Long
Dim Success As Long
 
Public Sub LogOn( _
  ByVal szUser As String, _
  ByVal szPassword As String, _
  ByVal szDomain As String)
  
  '// log off any previous impersonation.
  LogOff
  
  '// attempt to log on a a user
  Success = LogonUserW( _
    StrPtr(szUser), _
    StrPtr(szDomain), _
    StrPtr(szPassword), _
    LOGON32_LOGON_INTERACTIVE, _
    LOGON32_PROVIDER_DEFAULT, _
    hToken)
 
  If Success Then
  
    If ImpersonateLoggedOnUser(hToken) Then
      
      '// the process should be granted the
      '// logged on token.
      MsgBox "LogOn Success"
      
    Else
    
      MsgBox "ImpersonateLoggedOnUser failed."
      
    End If
    '// cleanup token handle.
    CloseHandle hToken
  
  Else
  
    MsgBox "LogonUserW failed."
    
  End If
  
End Sub
 
 
Public Sub LogOff()
  
  '// logs off the impersonation.
  RevertToSelf
 
End Sub
 
 
 
 
 
 
 
 
 
 
 
 
'//
'// Form1
'//
 
Option Explicit
 
Private Const TOKEN_IMPERSONATE = &H4&
Private Const TOKEN_DUPLICATE = &H2&
Private Const TOKEN_QUERY = &H8&
 
Private Declare Function DuplicateTokenEx Lib "advapi32" (ByVal hExistingToken As Long, ByVal dwDesiredAccess As Long, ByVal lpTokenAttributes As Long, ByVal ImpersonationLevel As Long, ByVal TokenType As Long, ByRef phNewToken As Long) As Long
Private Declare Function OpenThreadToken Lib "advapi32" (ByVal ThreadHandle As Long, ByVal DesiredAccess As Long, ByVal OpenAsSelf As Long, ByRef TokenHandle As Long) As Long
Private Declare Function SetThreadToken Lib "advapi32" (ByVal Thread As Long, ByVal Token As Long) As Long
Private Declare Function GetCurrentThread Lib "kernel32" () As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function OpenProcessToken Lib "advapi32" (ByVal ProcessHandle As Long, ByVal DesiredAccess As Long, ByRef TokenHandle As Long) As Long
Private Declare Function GetCurrentProcess Lib "kernel32" () As Long
 
Dim hTokenUserA As Long
 
Public Sub GetUserToken()
  Dim hTokenUser As Long
  If OpenProcessToken(GetCurrentProcess, TOKEN_QUERY Or TOKEN_DUPLICATE Or TOKEN_IMPERSONATE, hTokenUser) Then
  If DuplicateTokenEx(hTokenUser, 0, 0, 2, 2, hTokenUserA) Then
    MsgBox "Success"
  End If
  CloseHandle hTokenUser
End Sub
 
Public Sub SetUserToken()
  SetThreadToken 0, hTokenUserA
End Sub
 
Private Sub Command1_Click()
'// add admin info
  LogOn "user", "pass", vbNullString
End Sub
 
Private Sub Command2_Click()
'// username stuff
End Sub
 
Private Sub Command3_Click()
  SetUserToken
End Sub
 
Private Sub Form_Load()
  '// get token of user
  Call GetUserToken
 
End Sub

                                              
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:

Select allOpen in new window

 

by: dentabPosted on 2009-10-14 at 06:40:23ID: 25570307

Aghh...

Your demo seems to do the same as Logoff

It seems to work the same as reverttoself
To test reverting to a previous impersonation

Private Sub Form_Load()
  '// get token of user
  LogOn "SomeUser", "12345", "Domain"
  Call GetUserToken
 End Sub

 

by: dentabPosted on 2009-10-14 at 06:43:10ID: 25570339

It looks like its not feasible.
I thank you for all your help, way beyond the standard level I encounter on EE

If you want to post a message that you dont think it can be done - I will accept that as the answer.

 

by: egl1044Posted on 2009-10-14 at 07:02:03ID: 25570544

It's different that you would get the token before you log to admin so you can convert back to the token you had before calling admin ex..

DenUser ... opens process (this token)
DenAdmin logs on
Convert back to DenUser token

From your IIS DLL standpoint.

DenUser loads IIS (get the token DenUser)
DenUser calls LogOn() your now DenAdmin
DenAdmin calls  (SetUserToken)  to change the token back to DenUser instead of using RevertToSelf.

Because I don't know how IIS really works under the hood this may or may not work. The fact IIS creates a thread and does some other stuff you might have to try OpenThreadToken() as a replacment for OpenProcessToken(). I am not saying it can't be done but I don't know exactly if it can be done from an IIS standpoint. All we can do is try a couple of things that would seem feasible if they don't work then we can make the conclusion that it's not worth it. I have one question to ask yourself is NETWORK_USER much different from a DenUser() if the privilges are the same then it's probrably not even worth it to change the token back and just use RevertToSelf().

 

by: dentabPosted on 2009-10-14 at 07:28:35ID: 25570877

but IIS seems to impersonate is the point
so its already impersonating a user before my code is run.  so what happens is

NETWORK SERVICE runs IIS
IIS challanges remote user
IIS recieves DenUser Auth
IIS impersonates on one thread DenUser
IIS Runs ASP
ASP runs DLL
ASP impersonates DenAdmin
ASP logs of DenAdmin (which reverts all the way to NETWORK SERVICE

I will however try this in IIS, but I think it will be the same result

 

by: dentabPosted on 2009-10-19 at 00:37:28ID: 25603142

it didnt work egl

could you post a summary saying something like "It seems that you can not revert back to an already impersonated user" please.

I will accept that as the solution.

 

by: egl1044Posted on 2009-10-19 at 04:54:40ID: 25604300

@Dentab

NETWORK_SERVICE is the default owner of IIS/ASP so when you logoff/RevertToSelf you receive the default NETWORK_SERVICE token. It appears reverting back to a user from IIS doesn't work from the small testing done.

 

by: dentabPosted on 2009-10-19 at 05:54:17ID: 31640232

Thanks egl, I really appreciate the effort you put into this one.

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...