Powershell function LogonUser return different Error code when using Schedule Task

0

I'm using function below in my script to ensure that user are not using specific list of passwords for local account. The function works fine and return "True" with correct username and password and return "False" with correct Error "The user name or password is incorrect" when tested against a username with wrong password. The issue is when I run my script using Task Scheduler with SYSTEM account, it still return correct validation, but the Error code for username with wrong password is "0" : The operation completed successfully. Does anyone knows why the GetLastWin32Error() return code 0 instead of 0x0000052E when using Task Scheduler?

Function Test-LocalCredential{
    <#
    Test credential/password for local account.
    #>
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$True)][String]$UserName,
        [Parameter(Mandatory=$True)][String]$Password
    )
    
  
    IF (!($UserName) -or !($Password)) {
        Write-Warning 'Username and password not provided'
        Return
    }

    [Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null
    [Reflection.Assembly]::LoadWithPartialName("System.Runtime.InteropServices") | Out-Null


$logonUserSignature =
@'
[DllImport( "advapi32.dll", SetLastError = true )]
public static extern bool LogonUser( String lpszUserName,
                                     String lpszDomain,
                                     String lpszPassword,
                                     int dwLogonType,
                                     int dwLogonProvider,
                                     ref IntPtr phToken );

'@

$closeHandleSignature =
@'

[DllImport( "kernel32.dll", CharSet = CharSet.Auto, SetLastError = true )]
public static extern bool CloseHandle( IntPtr handle );

'@

    $AdvApi32 = Add-Type -MemberDefinition $logonUserSignature -Name "AdvApi32" -Namespace "PsInvoke.NativeMethods" -PassThru
    $Kernel32 = Add-Type -MemberDefinition $closeHandleSignature -Name "Kernel32" -Namespace "PsInvoke.NativeMethods" -PassThru

    <#
        LOGON32_PROVIDER_DEFAULT = 0
        LOGON32_PROVIDER_WINNT35 = 1
        LOGON32_PROVIDER_WINNT40 = 2
        LOGON32_PROVIDER_WINNT50 = 3
    #>
    $Logon32Provider = 0

    <#
        LOGON32_LOGON_INTERACTIVE = 2
        LOGON32_LOGON_NETWORK = 3
        LOGON32_LOGON_BATCH = 4
        LOGON32_LOGON_SERVICE = 5
        LOGON32_LOGON_UNLOCK = 7
        LOGON32_LOGON_NETWORK_CLEARTEXT = 8
        LOGON32_LOGON_NEW_CREDENTIALS = 9
    #>
    $Logon32Type = 3

    $tokenHandle = [IntPtr]::Zero       
    $TestLogon = $False

    <# 
       Unless $userName is supplied using UPN format (e.g administrator@servername or administrator@domain) domain name should not be of null value as it would 
       default the logon provider authentication to NTLM
    #>
    $DomainName = $env:COMPUTERNAME
    $TestLogon = $AdvApi32::LogonUser($UserName, $DomainName, $Password, $Logon32Type, $Logon32Provider, [Ref]$tokenHandle)     

    $success_codes = @(
                0x0000052F,  # ERROR_ACCOUNT_RESTRICTION
                0x00000530,  # ERROR_INVALID_LOGON_HOURS
                0x00000531,  # ERROR_INVALID_WORKSTATION
                0x00000569  # ERROR_LOGON_TYPE_GRANTED
    )
     
    if (!$TestLogon){
        $err_code = $Null
        $err_code = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error()
        $Msg = $(([ComponentModel.Win32Exception] $err_code).Message)
        Write-Verbose $Msg
        
        if ($err_code -eq 0x0000052E) {
            # ERROR_LOGON_FAILURE - the user or pass was incorrect
            $valid_credentials = $false
        } elseif ($err_code -in $success_codes) {
            $valid_credentials = $true
        } else {
            # an unknown failure, raise an Exception for this
            $win32_exp = New-Object -TypeName System.ComponentModel.Win32Exception -ArgumentList $err_code
            $err_msg = "LogonUser failed: $($win32_exp.Message) (Win32ErrorCode: $err_code) ($Password)"
            Write-Verbose $err_msg
            throw New-Object -TypeName System.ComponentModel.Win32Exception -ArgumentList $err_code, $err_msg
            $valid_credentials = $false
        }

    } else {
        $Kernel32::CloseHandle($tokenHandle) | Out-Null
        $valid_credentials = $True
    }
    Return $valid_credentials
}
windows
powershell
asked on Stack Overflow Feb 2, 2021 by Azwan

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0