Reputation: 103
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
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