Вопрос по .net, directoryservices, ldap, c#, active-directory – Как проверить достоверность кредитов Active Directory через LDAP + SSL?

15

Я пытаюсь использовать .NET 3.5System.DirectoryServices.AccountManagement пространство имен для проверки учетных данных пользователя на нашем LDAP-сервере Active Directoryover an SSL encrypted LDAP connection, Вот пример кода:

using (var pc = new PrincipalContext(ContextType.Domain, "sd.example.com:389", "DC=sd,DC=example,DC=com", ContextOptions.Negotiate))
{
    return pc.ValidateCredentials(_username, _password);
}

Этот код отлично работает с незащищенным LDAP (порт 389), однако я не буду передавать комбинацию пользователь / пароль в виде открытого текста. Но когда я перехожу на LDAP + SSL (порт 636), я получаю следующее исключение:

System.DirectoryServices.Protocols.DirectoryOperationException: The server cannot handle directory requests.
  at System.DirectoryServices.Protocols.ErrorChecking.CheckAndSetLdapError(Int32 error)
  at System.DirectoryServices.Protocols.LdapSessionOptions.FastConcurrentBind()
  at System.DirectoryServices.AccountManagement.CredentialValidator.BindLdap(NetworkCredential creds, ContextOptions contextOptions)
  at System.DirectoryServices.AccountManagement.CredentialValidator.Validate(String userName, String password)
  at System.DirectoryServices.AccountManagement.PrincipalContext.ValidateCredentials(String userName, String password)
  at (my code)

Порт 636 работает для других операций, таких как поиск информации, не связанной с паролем, для этой записи LDAP / AD ...

UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, _username)

... так что я знаю, что это не настройка SSL моего сервера LDAP, так как он работает через SSL для других поисков.

Кто-нибудь получилValidateCredentials(...) призывать работать по SSL? Можете ли вы объяснить, как? Или есть другой / лучший способ безопасной проверки учетных данных AD / LDAP?

Пароли должны передаваться открытым текстом, а не хэшироваться, по защищенному соединению с сервером, который поддерживает проверки качества паролей и применение истории паролей, если только клиент LDAP не обеспечивает проверки качества паролей и истории, иначе сервер не сможет обеспечить качество и история. Terry Gardner
Вот статья MSDN для устранения неполадок LDAP через SSL:support.microsoft.com/kb/938703 CAbbott
Спасибо за ссылку. Но опять же, я могу общаться через LDAPS (порт 636) просто отлично для всех других запросов LDAP, которые я выполнял. Кажется, что-то необычное вValidateCredentials(), Впрочем, я рассмотрю статью более подробно. Nate Sauber

Ваш Ответ

4   ответа
0

Для меня метод ValidateCredentials работает просто отлично. Я обнаружил, что проблема заключалась в том, что сервер размещал AD (я использую AD LDS). Вам нужно было связать сертификат сервера с экземпляром AD. Так что, если ваш экземпляр назывался «MyAD»; (или ActiveDirectoryWebService), вам нужно было открыть MMC, привязать «Сертификаты»; выберите «Сервисная учетная запись». и затем выберите «MyAD»; из списка. Оттуда вы можете добавить сертификат SSL в «MyAD». Персональный магазин. Это, наконец, положило начало обработке SSL.

Я подозреваю, из того, что я знаю оLdapConnection метод и тот факт, что вы пропустили функцию обратного вызова, что вы не проверяете сертификат сервера. Это грязная работа иValidateCredentials делает это бесплатно. Вероятно, не имеет большого значения, но дыра в безопасности тем не менее.

14

Мне удалось проверить учетные данные, используяSystem.DirectoryServices.Protocols Пространство имен, благодаря сотруднику. Вот код:

// See http://support.microsoft.com/kb/218185 for full list of LDAP error codes
const int ldapErrorInvalidCredentials = 0x31;

const string server = "sd.example.com:636";
const string domain = "sd.example.com";

try
{
    using (var ldapConnection = new LdapConnection(server))
    {
        var networkCredential = new NetworkCredential(_username, _password, domain);
        ldapConnection.SessionOptions.SecureSocketLayer = true;
        ldapConnection.AuthType = AuthType.Negotiate;
        ldapConnection.Bind(networkCredential);
    }

    // If the bind succeeds, the credentials are valid
    return true;
}
catch (LdapException ldapException)
{
    // Invalid credentials throw an exception with a specific error code
    if (ldapException.ErrorCode.Equals(ldapErrorInvalidCredentials))
    {
        return false;
    }

    throw;
}

Я не в восторге от использования блока try / catch для управления логикой принятия решений, но это то, что работает. : /

3

Может быть, это другой способ. В проверке учетных данных нет ничего необычного. ContextOptions должен быть установлен правильно.

Значение по умолчанию:

ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing

Добавить Ssl:

ContextOptions.Negotiate | ContextOptions.Signing | ContextOptions.Sealing | ContextOptions.SecureSocketLayer

ContextOptions.Negotiate или ContextOptions.SimpleBind требуется. Или все, что нужно вашему серверу для аутентификации. ContextOptions поддерживает только OR побитно.

Вы также можете попытаться установить ContextOptions напрямую таким способом в методе ValidateCredentials.

using (var pc = new PrincipalContext(ContextType.Domain, "sd.example.com:636", "DC=sd,DC=example,DC=com", ContextOptions.Negotiate | ContextOptions.SecureSocketLayer))
{
    return pc.ValidateCredentials(_username, _password);
}

Или же

using (var pc = new PrincipalContext(ContextType.Domain, "sd.example.com:636", "DC=sd,DC=example,DC=com", ContextOptions.Negotiate))
{
    return pc.ValidateCredentials(_username, _password, ContextOptions.Negotiate | ContextOptions.SecureSocketLayer);
}
Я вижу, вы говорите & quot; Или все, что требуется вашему серверу для аутентификации. & Quot ;. Как узнать, что нужно серверу для аутентификации? Я работаю на сервере, который ранее был настроен с некоторыми опциями, но я не знаю, каковы они сейчас. Могу я их как-нибудь проверить?
0

Я знаю, что это старо, но для любого, кто сталкивается с этим снова:

PrincipalContext.ValidateCredentials(...)по умолчанию пытается открыть соединение SSL (ldap_init(NULL, 636)) с последующей настройкой параметраLDAP_OPT_FAST_CONCURRENT_BIND.

Если (доверенный?)client certificate присутствует, однако соединение LDAP неявно связано, и быстрое связывание больше не может быть включено. PrincipalContext не рассматривает этот случай и завершается с неожиданнымDirectoryOperationException.

Workaround: Для поддержки SSL, где это возможно, но есть запасной вариант, позвонитеValidateCredentials(...) сначала с параметрами по умолчанию (т.е. без параметров). Если это не удается сDirectoryOperationExceptionпопробуйте еще раз, указавContextOptions (Договориться | Печать | Подписание), что к чемуValidateCredentials внутренне делает для ожидаемогоLdapException тем не мение.

Похожие вопросы