1

I use Windows PowerShell to query and validate the user's Windows credentials during an installation process. That worked well until yesterday. Now the IT department in my company has changed some configuration of the domain controller and now I get the following exception.

Exception calling "ValidateCredentials" with "2" argument(s): "The server cannot
handle directory requests."
At line:32 char:5
+ if ($pc.ValidateCredentials($username, $credential.GetNetworkCredenti ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DirectoryOperationException

From my research I already found out that it has to do with the missing SSL connection. I have to add ContextOptions.SecureSocketLayer somewhere in the code. The question is: Where is the right place to put this parameter? I cannot find any examples for PowerShell.

Here's the script I used to check the credentials:

$credential = $Host.UI.PromptForCredential("Need credentials.", "For using Windows Integrated Authentication please provide the login information for the user that has access to the Microsoft SQL Server database.", "", "")
if (!$credential) {
    Write-Output "No credentials provided"
    return
}

[System.Reflection.Assembly]::LoadWithPartialName('System.DirectoryServices.AccountManagement')

$system = Get-WmiObject -Class Win32_ComputerSystem

if ($credential.GetNetworkCredential().Domain) {
    Write-Output "Credentials contain domain"
    if ($credential.GetNetworkCredential().Domain -eq $system.Name) {
        Write-Output "Domain is local system"
        $pc = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext 'Machine', $system.Name
    } else {
        Write-Output "Domain is network domain"
        $pc = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext 'Domain', $credential.GetNetworkCredential().Domain
    }
    $username = $credential.UserName
} elseif (0, 2 -contains $system.DomainRole) {
    $pc = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext 'Machine', $system.Name
    $username = $system.Name + '\' + $credential.GetNetworkCredential().UserName
} else {
    $pc = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext 'Domain', $system.Domain
    $username = $system.Domain + '\' + $credential.GetNetworkCredential().UserName
}

if ($pc.ValidateCredentials($username, $credential.GetNetworkCredential().Password)) {
    Write-Output "Validation successfull"
} else {
    Write-Output "Validation failed"
}
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
André
  • 464
  • 4
  • 17
  • 3
    you can add it to the `principalcontext` it seems....https://msdn.microsoft.com/en-us/library/bb339842(v=vs.110).aspx – Kiran Reddy Sep 12 '17 at 08:14

1 Answers1

2

As mentioned by Kiran in the comments, you can pass a ContextOptions value to the PrincipalContext constructor:

$DefaultNC = "DC=$($system.Domain -replace '\.',',DC=')"
# ...
$pc = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext 'Domain', $system.Domain, $DefaultNC, ([System.DirectoryServices.AccountManagement.ContextOptions]'SecureSocketLayer,Negotiate')

An authentication option (Negotiate or SimpleBind) must be specified, thus the 'SecureSocketLayer,Negotiate' value

Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • Thanks for your answer. The syntax is correct. But I still get the DirectoryOperationException when I call $pc.ValidateCredentials. So the missing SecureSocketLayer doesn't seem to be the cause of my problem. I have no idea what has changed. – André Sep 12 '17 at 11:24
  • 2
    had similar issue, `$pc.ValidateCredentials($username, $credential.GetNetworkCredential().Password)` was working fine for a long time and suddenly started throwing "The server cannot handle directory requests." exception. This was only happening when running this code under system account by the way. Passing context with negotiate fixed the problem `$pc.ValidateCredentials($username, $credential.GetNetworkCredential().Password,[System.DirectoryServices.AccountManagement.ContextOptions]'Negotiate')` – Aurimas Stands with Ukraine Jan 30 '19 at 07:08