Created
January 24, 2020 20:28
-
-
Save jasonrush/5ab7f9b6a743ef95431bd1edcb6d0dc5 to your computer and use it in GitHub Desktop.
Test credentials for local computer (update arg 2 on line 40 from $null to domain name for domain auth). Slightly modified from Ansible.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Function Test-Credential { | |
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingUserNameAndPassWordParams", "", Justification="We need to use the plaintext pass in the Win32 call, also the source isn't a secure string to using that is just a waste of time/code")] | |
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "", Justification="See above")] | |
param([String]$Username, [String]$Password) | |
$platform_util = @' | |
using System; | |
using System.Runtime.InteropServices; | |
namespace TempNamespace | |
{ | |
public class WinUserPInvoke | |
{ | |
[DllImport("advapi32.dll", SetLastError = true)] | |
public static extern bool LogonUser( | |
string lpszUsername, | |
string lpszDomain, | |
string lpszPassword, | |
UInt32 dwLogonType, | |
UInt32 dwLogonProvider, | |
out IntPtr phToken); | |
[DllImport("kernel32.dll", SetLastError = true)] | |
public static extern bool CloseHandle( | |
IntPtr hObject); | |
} | |
} | |
'@ | |
$original_tmp = $env:TMP | |
$original_temp = $env:TEMP | |
$env:TMP = $_remote_tmp | |
$env:TEMP = $_remote_tmp | |
Add-Type -TypeDefinition $platform_util | |
$env:TMP = $original_tmp | |
$env:TEMP = $original_temp | |
$Logon32LogonInteractive = 2 | |
$LOGON32_PROVIDER_DEFAULT = 0 | |
$handle = [IntPtr]::Zero | |
$logon_res = [TempNamespace.WinUserPInvoke]::LogonUser($Username, $null, $Password, | |
$Logon32LogonInteractive, $LOGON32_PROVIDER_DEFAULT, [Ref]$handle) | |
if ($logon_res) { | |
$valid_credentials = $true | |
[TempNamespace.WinUserPInvoke]::CloseHandle($handle) > $null | |
} else { | |
$err_code = [System.Runtime.InteropServices.Marshal]::GetLastWin32Error() | |
# following errors indicate the creds are correct but the user was | |
# unable to log on for other reasons, which we don't care about | |
$success_codes = @( | |
0x0000052F, # ERROR_ACCOUNT_RESTRICTION | |
0x00000530, # ERROR_INVALID_LOGON_HOURS | |
0x00000531, # ERROR_INVALID_WORKSTATION | |
0x00000569 # ERROR_LOGON_TYPE_GRANTED | |
) | |
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 = "LogonUserW failed: $($win32_exp.Message) (Win32ErrorCode: $err_code)" | |
throw New-Object -TypeName System.ComponentModel.Win32Exception -ArgumentList $err_code, $err_msg | |
} | |
} | |
return $valid_credentials | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment