Jump to content

LogonUser question, advapi32.dll


Recommended Posts

Code seems ok, but it won't report user existence for correct user account

#NoTrayIcon
#RequireAdmin
#include <Array.au3>
#include <WinAPI.au3>

Global $aRet = _LogonUser("user","user")
$Ret = _WinAPI_GetLastErrorMessage()
MsgBox(64, "Debug", $Ret)
_ArrayDisplay($aRet, "Debug")

Func _LogonUser($sUsername, $sPassword, $sServer = '.')
    
    $stToken     =  DllStructCreate("int")

    Local $aRet = DllCall("advapi32.dll", "int", "LogonUser", _
            "wstr", $sUsername, "wstr", $sServer, "wstr", $sPassword, "dword", 3, "dword", 2, "ptr", DllStructGetPtr($stToken))
  ;If $aRet[0] Then Return SetError(1, $aRet[0], False)
    
    $hToken = DllStructGetData($stToken, 1)


    Return $aRet
EndFunc ;_LogonUser

Some ideas to correct this problem would be welcomed.

Edited by Ghost1987
Link to comment
Share on other sites

I may have found a solution for you.

I played with your code for ages and couldn't get it to work.

Then I did a search for "advapi32.dll" LogonUser and found http://www.autoitscript.com/forum/index.php?showtopic=14710

Try this out and see if it works for you.

#include <WinAPI.au3>

$test = _checkUserCredentials("user", "password")

MsgBox(64, "Username/password Valid", $test)

Func _checkUserCredentials($sUserName, $sPassword, $sServer = '.')

    $stToken = DllStructCreate("int")

    Local $aRet = DllCall("advapi32.dll", "int", "LogonUser", _
            "str", $sUserName, _
            "str", $sServer, _
            "str", $sPassword, _
            "dword", 2, _
            "dword", 0, _
            "ptr", DllStructGetPtr($stToken))

    If Not @error And $aRet[0] <> 0 Then
        Return True
    EndIf
    
    Return False
EndFunc   ;==>_checkUserCredentials

Keep on coding

John Morrison

Link to comment
Share on other sites

Hmm... tnx storme, I've actually searched for LogonUser implementation before I've tried to write my own code, but couldn't find any examples, but today I had searched again and fount a thread you was talking about.

I can see that I've missed data types "wstr" in my code should have been "str".

This was a main reason for the problem.

For better performance the above code should be modified, dwLogonType set to LOGON32_LOGON_NETWORK and not to LOGON32_LOGON_INTERACTIVE

So modified code would be like this

#NoTrayIcon

Global $Ret = _LogonUser("user","user")
MsgBox(64, "Debug", $Ret)

Func _LogonUser($sUsername, $sPassword, $sServer = '.'); Returns True if user exists 
    
    $stToken     =  DllStructCreate("int")

    Local $aRet = DllCall("advapi32.dll", "int", "LogonUser", _
            "str", $sUsername, "str", $sServer, "str", $sPassword, "dword", 3, "dword", 0, "ptr", DllStructGetPtr($stToken))
    
   ;$hToken = DllStructGetData($stToken, 1)
    
    If Not @error And $aRet[0] <> 0 Then
        Return True
    EndIf
   
    Return False
    
EndFunc   ;_LogonUser
Edited by Ghost1987
Link to comment
Share on other sites

I've been looking for a piece of code to check user credentials for a while now.

I was using this bit of code.

Func checkUserCredentials($username, $userPassword = "", $LogonDomain = @ComputerName)
    RunAs($username, $LogonDomain, $userPassword, 0, @ComSpec & " /c  echo test", @TempDir, @SW_HIDE)
    If @error Then
        $userPassword = ""
        Return False
    EndIf
    Return True
EndFunc   ;==>checkUserCredentials

But for some reason it couldn't handle blank passwords and I still don't know why. :-(

The new one appears to work fine. Though I haven't had a chance to test it on other computers yet.

BTW the only reason I found that one other tread was your post.

Thanks for the help

John Morrison

Link to comment
Share on other sites

I've been looking for a piece of code to check user credentials for a while now.

I was using this bit of code.

Func checkUserCredentials($username, $userPassword = "", $LogonDomain = @ComputerName)
    RunAs($username, $LogonDomain, $userPassword, 0, @ComSpec & " /c  echo test", @TempDir, @SW_HIDE)
    If @error Then
        $userPassword = ""
        Return False
    EndIf
    Return True
EndFunc   ;==>checkUserCredentials

But for some reason it couldn't handle blank passwords and I still don't know why. :-(

The new one appears to work fine. Though I haven't had a chance to test it on other computers yet.

BTW the only reason I found that one other tread was your post.

Thanks for the help

John Morrison

By default Windows RunAs command and corresponding winapi can't be used with blank passwords it's a security feature so this is why the code above didn't validate user credentials with blank passwords.

I am glad that I've helped someone ;-)

I even didn't knew that LogonUser validates user accounts with blank passwords, if it actually does this is very good thing.

By the way LogonUser approach of user account validation won't work on W2k, more info is on msdn

Link to comment
Share on other sites

  • 1 month later...

By default Windows RunAs command and corresponding winapi can't be used with blank passwords it's a security feature so this is why the code above didn't validate user credentials with blank passwords.

I am glad that I've helped someone ;-)

I even didn't knew that LogonUser validates user accounts with blank passwords, if it actually does this is very good thing.

By the way LogonUser approach of user account validation won't work on W2k, more info is on msdn

Thanks Ghost1987 I figured it was something like that.... BUT... that is always a BUT.... :-)

I've tried the scripts with "no password" on my computer and they both work (IE validate with no password). BUT on a new computer with "no password" they don't work. VERY inconsistant.

Does anyone know of a method of checking that a user has no password. I could add it to the function to handle all situations.

What I'm aiming for is a function I can add to an other script I'm working on that needs to restart the computer and relogon to the same user. At the moment I'm getting around it by making a temproary password and then using it to validate. But this is hardly the best way when I hand it to unsupervised users.

Thanks for the help

John Morrison

Link to comment
Share on other sites

Does anyone know of a method of checking that a user has no password. I could add it to the function to handle all situations.

This is based on the Scripting Guy article linked in the function.

It can either test a specific account, or return a list of all accounts with blank passwords.

It tries to reset an account's password from a blank to a blank.

Obviously if it succeeds, then that account has a blank password.

It is set to test only the local computer right now, and obviously if there are lots of accounts and you are doing the whole list, it can take a while.

Enjoy!

#include <array.au3>

$aBlanks = _WinPasswordIsBlank()
_ArrayDisplay($aBlanks, "Accounts With Blank Passwords")

$user = "Administrator"
If _WinPasswordIsBlank($user) Then MsgBox(0, "", "What??? " & $user & " has a blank Password")

Func _WinPasswordIsBlank($sUserName = "")
;http://www.microsoft.com/technet/scriptcenter/resources/qanda/oct05/hey1006.mspx
;if called with no parameter, returns an array of all user accounts with no/blank password
;   otherwise, call with a username and it will return TRUE if password is blank/not set
;
;Note: will not return an account with a blank password where "User cannot change password" has been set
;               Also, no checking to see if a specified Account exists
;
    Global $oMyError = ObjEvent("AutoIt.Error", "ComError")
    Local $sUserList = "", $aUserList, $colAccounts, $aFilter, $objUser
    $colAccounts = ObjGet("WinNT://" & @ComputerName)
    Dim $aFilter[2] = ["user"]
    $colAccounts.Filter = $aFilter
    For $objUser In $colAccounts
        If $sUserName And $objUser.Name <> $sUserName Then
            ContinueLoop
        Else
            $objUser.ChangePassword("", "")
        EndIf

        If @error = 0 Or @error = -2147023569 Then; user is using a blank password
            If $sUserList = "" Then
                $sUserList &= $objUser.Name
            Else
                $sUserList &= "|" & $objUser.Name
            EndIf
        EndIf
        SetError(0)
    Next

    $colAccounts = ""
    $objUser = ""

    If $sUserName And $sUserList = $sUserName Then
        Return True
    ElseIf $sUserName Then
        Return False
    Else
        $aUserList = StringSplit($sUserList, "|", 2)
        Return $aUserList
    EndIf
EndFunc ;==>_WinPasswordIsBlank

Func ComError()
    If IsObj($oMyError) Then
        SetError($oMyError.number)
    Else
        SetError(1)
    EndIf
    Return 0
EndFunc ;==>ComError

Edit: Also see Jos's work on user validation here http://www.autoitscript.com/forum/index.ph...st&p=543969

Should give you some useful ideas.

Edited by ResNullius
Link to comment
Share on other sites

This is based on the Scripting Guy article linked in the function.

It can either test a specific account, or return a list of all accounts with blank passwords.

It tries to reset an account's password from a blank to a blank.

Obviously if it succeeds, then that account has a blank password.

It is set to test only the local computer right now, and obviously if there are lots of accounts and you are doing the whole list, it can take a while.

Enjoy!

THANKS ResNullius that is what I was looking for!

John Morrison

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...