Page 1 of 1

ImpersonateLoggedOnUser

Posted: Mon Apr 11, 2005 11:29 pm
by Droopy
I Logon / Impersonate successfully toto
but when Notepad is launched, the name of the user who launch Notepad
is not toto, it's my account !!

Code: Select all

Username.s="toto"
Domain.s="."
Password.s="passe"
Token.l

Debug logonuser_(@Username,@Domain,@Password,2,0,@Token)

Debug ImpersonateLoggedOnUser_(Token)

RunProgram("notepad.exe","","")

Posted: Tue Apr 12, 2005 12:11 am
by El_Choni
Do either of these work for you?:

Code: Select all

Procedure u(string$)
  sLen = Len(string$)
  uLen = (sLen<<1)+2
  *uBuffer = AllocateMemory(uLen)
  MultiByteToWideChar_(#CP_ACP, 0, string$, sLen, *uBuffer, uLen)
  ProcedureReturn *uBuffer
EndProcedure

!extrn _CreateProcessWithLogonW@44
Global *CreateProcessWithLogonW
!MOV dword [p_CreateProcessWithLogonW], _CreateProcessWithLogonW@44

Procedure Error(message$, hToken)
  wError = GetLastError_()
  If wError
    *ErrorBuffer = AllocateMemory(1024)
    If *ErrorBuffer
      FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM, 0, wError, 0, *ErrorBuffer, 1024, 0)
      message$+Chr(10)+PeekS(*ErrorBuffer)
      FreeMemory(*ErrorBuffer)
    EndIf
  EndIf
  If hToken:RevertToSelf_():CloseHandle_(hToken):EndIf
  MessageRequester("Error", message$)
  ProcedureReturn #FALSE
EndProcedure

Procedure RunAsUser(Program$, UserName$, Domain$, Password$)
  If LogonUser_(@Username$, @Domain$, @Password$, 2, 0, @hToken)=0:ProcedureReturn Error("LogonUser", 0):EndIf
  If ImpersonateLoggedOnUser_(hToken)=0:ProcedureReturn Error("ImpersonateLoggedOnUser", hToken):EndIf
  GetStartupInfo_(@si.STARTUPINFO)
  hProcess = CreateProcessAsUser_(hToken, Program$, "", #NULL, #NULL, #FALSE, #NORMAL_PRIORITY_CLASS, #NULL, #NULL, @si, @pi.PROCESS_INFORMATION)
  If hProcess=0:ProcedureReturn Error("CreateProcessAsUser", hToken):EndIf
  RevertToSelf_()
  CloseHandle_(hToken)
  ProcedureReturn hProcess
EndProcedure

#LOGON_WITH_PROFILE = 1
Procedure RunAsUser2(Program$, UserName$, Domain$, Password$)
  GetStartupInfo_(@si.STARTUPINFO)
  hProcess = CallFunctionFast(*CreateProcessWithLogonW, u(Username$), u(Domain$), u(Password$), #LOGON_WITH_PROFILE, u(Program$), "", #NULL, #NULL, #FALSE, @si, @pi.PROCESS_INFORMATION)
  If hProcess=0:ProcedureReturn Error("CreateProcessWithLogonW", 0):EndIf
  ProcedureReturn hProcess
EndProcedure

Username.s = "toto"
Domain.s = "."
Password.s = "passe"

Debug RunAsUser("notepad.exe", Username, Domain, Password)
Debug RunAsUser2("calc.exe", Username, Domain, Password)

Posted: Tue Apr 12, 2005 5:57 am
by Droopy
Thanks El_Choni
but I can't use this code
cause I want to impersonate the Thread ( as an local administrator)
for creating users / SetComputer name
without launching external program

Posted: Tue Apr 12, 2005 2:50 pm
by El_Choni
I thought you wanted to launch a program as another user, that's what your code tries to do anyway :?:

Posted: Tue Apr 12, 2005 3:46 pm
by Tommeh
On msdn, it says this code is part of the .net framework and needs the included header: mscoree.h

I think this may only be for .net ;)

Posted: Tue Apr 12, 2005 6:58 pm
by Droopy
I want my software launched by a user, was impersonated as an administrator

So the next command ( Purebasic code ) of this software was in an administrator security context .

So the next code work

Code: Select all

ComputerName.s="PPPPP"
If SetComputerName_(@ComputerName)

Without creating another exe and launch it with CreateProcessWithLogonW

Posted: Tue Apr 12, 2005 7:11 pm
by El_Choni
I don't Windows would let a limited user impersonate an administrator. Wouldn't make too much sense, would it?

Posted: Tue Apr 12, 2005 7:17 pm
by Droopy
With user right you can launch another exe as an administrator ( If you know the username / password )

I just want the same without launch external program

Posted: Tue Apr 12, 2005 11:18 pm
by Max.
Hopefully, I am not off, but actually, El Choni's example works well for me (thanks for that!).

Here a stripped down version and a description of the test (needs NTFS):

1. Logged on as user "A"
2. Created a directory "C:\ElChoni"
3. Changed security, so only the user "B" has write access, others only read
4. Started the program below, that attempts to create a file in that restricted dir

a) User "A" (before impersonation) tries: no success
b) Calling the impersonation routine, impersonating "B": success

Now let's check if it really is as it pretended to be:

- et voila, the file was created

Code: Select all

;Stripped down from sample by El Choni
;http://forums.purebasic.com/english/viewtopic.php?t=14727&highlight=


Username$ = "b"
Domain$ = "."
Password$ = "mypassword"



Procedure u(string$)
  sLen = Len(string$)
  uLen = (sLen<<1)+2
  *uBuffer = AllocateMemory(uLen)
  MultiByteToWideChar_(#CP_ACP, 0, string$, sLen, *uBuffer, uLen)
  ProcedureReturn *uBuffer
EndProcedure

Procedure Error(message$, hToken)
  wError = GetLastError_()
  If wError
    *ErrorBuffer = AllocateMemory(1024)
    If *ErrorBuffer
      FormatMessage_(#FORMAT_MESSAGE_FROM_SYSTEM, 0, wError, 0, *ErrorBuffer, 1024, 0)
      message$+Chr(10)+PeekS(*ErrorBuffer)
      FreeMemory(*ErrorBuffer)
    EndIf
  EndIf
  If hToken:RevertToSelf_():CloseHandle_(hToken):EndIf
  MessageRequester("Error", message$)
  ProcedureReturn #FALSE
EndProcedure 

!extrn _CreateProcessWithLogonW@44
Global *CreateProcessWithLogonW
!MOV dword [p_CreateProcessWithLogonW], _CreateProcessWithLogonW@44

Procedure ImpersonateUser(UserName$, Domain$, Password$)
  
  If LogonUser_(@Username$, @Domain$, @Password$, 2, 0, @hToken)=0
    ProcedureReturn Error("LogonUser", 0)
  EndIf
  
  If ImpersonateLoggedOnUser_(hToken)=0:
    ProcedureReturn Error("ImpersonateLoggedOnUser", hToken)
  EndIf
  
  GetStartupInfo_(@si.STARTUPINFO)
  
  ;After impersonation
  Result=CreateFile(0,"C:\ElChoni\UserB.txt")
  If Result
    Debug "Successful: impersonated user"
    CloseFile(0)
  Else
    Debug "Error: impersonated user"
  EndIf
  
  
  RevertToSelf_()
  CloseHandle_(hToken)
  ProcedureReturn hProcess
EndProcedure 

;Before impersonation
Result=CreateFile(0,"C:\ElChoni\UserA.txt")
If Result
  Debug "Successful: main user"
  CloseFile(0)
Else
  Debug "Error: main user"
EndIf

ImpersonateUser(Username$,Domain$,Password$)

;Now reverted to state "before impersonation"
Isn't that what you mean to do (just chose a random built in function to make it easier to test. API should work as well)?

But:

The user that impersonates (here: A) needs to have the privilege ImpersonateUser!

Posted: Wed Apr 13, 2005 6:58 pm
by Droopy
Thanks a lot :D , the code of El_Choni works well

but i don't understand 2 portions of code :(

Code: Select all

!extrn _CreateProcessWithLogonW@44 
Global *CreateProcessWithLogonW 
!MOV dword [p_CreateProcessWithLogonW], _CreateProcessWithLogonW@44 
and

Code: Select all

GetStartupInfo_(@si.STARTUPINFO)
is it possible to El_Choni to comment this piece of code :D

Posted: Wed Apr 13, 2005 10:26 pm
by Droopy
I retest the El Choni code and it doesn't work
The code of Max works well but the following code is no needed

Code: Select all

!extrn _CreateProcessWithLogonW@44 
Global *CreateProcessWithLogonW 
!MOV dword [p_CreateProcessWithLogonW], _CreateProcessWithLogonW@44 
and

Code: Select all

GetStartupInfo_(@si.STARTUPINFO)
My first code works well, the software is impersonated ( file creation / add user ) except for launching external program !!


Thanks a lot El Choni & Max

Posted: Thu Apr 14, 2005 12:07 am
by Max.
Droopy wrote:I retest the El Choni code and it doesn't work
The code of Max works well
"My" code is El Choni's code, where I just removed calling an external application. It is the same. And impersonation works until the RevertToSelf_ call. Just for clarification.

Posted: Thu Apr 14, 2005 8:31 am
by El_Choni
In the code posted by Max, these two pieces of code are not used, they were only needed for my example.

This:

Code: Select all

!extrn _CreateProcessWithLogonW@44
Global *CreateProcessWithLogonW
!MOV dword [p_CreateProcessWithLogonW], _CreateProcessWithLogonW@44
Enables calling to CreateProcessWithLogonW, as it's not natively included in PB, and AFAIK will only work in Windows 2000, XP and 2003. Using it this way speeds up things, but you won't be able to check if the function exists in the machine or not as if you used OpenLibrary & Co.

And this:

Code: Select all

GetStartupInfo_(@si.STARTUPINFO)
Is just to provide a valid argument to CreateProcessWithLogonW, I don't know if it's necessary or not.

I wasn't able to check any of the code in my machine, which only has 1 user. Right now I'm in a machine with several users, and the code doesn't work: the users don't have password, and I don't know how to tell that to LogonUser_()

Well, that's all about it. Regards,