RickInGarland
RickInGarland

Reputation: 103

Test-ADCredential fails on Windows 10 but works on 7

In no alternative reality can i be considered a sysadmin. To the contrary, i support an ERP system and use PowerShell as a programming language to do BI kinds of things because i don't have access to the language the ERP is written in. So, please overlook my ignorance on the subject of this question.

To keep our ERP in sync with an engineering system, i've created a suite of programs. The first one validates the AD account's password used to signon the PC and outputs it to a file for later use. The program works on the Windows 7 machine it was developed on. However, it gives this error when run on a Windows 10 machine. The function "Test-ADCredential" was stolen from the interned and is not mine.

Exception calling "ValidateCredentials" with "2" argument(s): "The server cannot handle directory requests."
At C:\GitRepo\PowerShellScripts\TeamCenter2M3AdCheck.ps1:20 char:9
+         $DS.ValidateCredentials($UserName, $Password)
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DirectoryOperationException

PowerShell on the development machine (Windows 7):

Name                           Value
----                           -----
PSVersion                      5.1.14409.1012
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.14409.1012
CLRVersion                     4.0.30319.34209
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

Version on Windows 10:

Name                           Value
----                           -----
PSVersion                      5.1.15063.786
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.15063.786
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

Here is the program:

# TeamCenter2M3AdCheck.ps1  Verify the password for current user and pass the user/id for MDI update
#  02/05/2018

param ([string]$IniFile)

Import-Module "C:\GitRepo\PowerShellScripts\TeamCenter2M3Setup.psm1" -Force

function Test-ADCredential {
  [CmdletBinding()]
    Param ([string]$UserName,
           [string]$Password)
    if (!($UserName) -or !($Password)) {
        Write-Warning 'Test-ADCredential: Please specify both user name and password'
    } else {
        Add-Type -AssemblyName System.DirectoryServices.AccountManagement
        $DS = New-Object System.DirectoryServices.AccountManagement.PrincipalContext('domain')
        $DS.ValidateCredentials($UserName, $Password)
    }
}  # function Test-ADCredential

# Initilize globlal variables from the INI file
IniParameters -IniFile $IniFile

$PasswordFile = $TC2M3Dir + "TeamCenterPassword.csv"
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null
[Byte[]] $Key = (1..16)

$UserId = $env:USERNAME
Do {  #loop until password is okay
    # Request the account's password
    $SecurePassword = Read-Host -AsSecureString  -Prompt "Enter password for $UserId"
    $UnsecurePassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword))
    $Okay = Test-ADCredential -UserName $UserId -Password $UnsecurePassword

    If ($Okay) {
      $PasswordString = ConvertFrom-SecureString -SecureString $SecurePassword -Key $Key
     $CsvText = "AdAccount,Password`n$UserId,$PasswordString"
     Out-File -FilePath $PasswordFile -InputObject $CsvText -Encoding ascii
   }
   else {
        Write-Host "Password failed.  Please try again or press Ctrl+c" -ForegroundColor Red
    }
} Until ($Okay)

Thanks in advance for your help.

Upvotes: 0

Views: 726

Answers (1)

HAL9256
HAL9256

Reputation: 13483

Change:

$DS.ValidateCredentials($UserName, $Password)

To:

$DS.ValidateCredentials($UserName, $Password, [DirectoryServices.AccountManagement.ContextOptions]::Negotiate -bor [DirectoryServices.AccountManagement.ContextOptions]::Sealing)

Essentially, on the new machine, it is likely falling back to trying to use Basic Authentication, and not using "Negotiate" (i.e. Use Kerberos or NTLM to encrypt connection to AD) to do the validation. By explicitly setting the Context option to force Negotiate or Sealing (another encryption variant), this should fix the issue.

I confirmed that I was able to have the code work on Windows 10.

References:

Upvotes: 1

Related Questions