PrincipalContext со вставленной смарт-картой

Некоторое время мы использовали приложение, которое использует System.DirectoryServices.AccountManagement для связи с каталогом Active (контекст домена).

ContextOptions options = ContextOptions.Negotiate | 
ContextOptions.SecureSocketLayer;
Using(PrincipalContext adContext = new PrincipalContext(ContextType.Domain, "AD.DOMAIN", "DC=AD,DC=intranet", options)) 
{

//Do stuff

}

Это работает нормально, пока мы не вставим смарт-карту. Как только мы вставим смарт-карту с сертификатом пользователя, она запросит пин-код смарт-карты, как только попадет в конструктор PrincipalContext. При отмене приложение вылетает. При вводе правильного пин-кода он просто будет продолжать подсказывать снова и снова.

Кажется, это связано с сеансом TLS, который настроен в фоновом режиме. Проблема не существует, если мы не включаем шифрование. Но шифрование обязательно.

Кто-нибудь сталкивался с этой проблемой раньше? Ресурсы, похоже, ограничены. Ближайшее, что я смог найти, было:

https://connect.microsoft.com/VisualStudio/feedback/details/3100569/initializing-contextoptions-does-not-work-in-system-directoryservices-accountmanagement-principalcontext-constructor

заранее спасибо


person Azlec    schedule 07.11.2017    source источник


Ответы (1)


PrincipalContext использует внутренний класс CredentialValidator для аутентификации во время привязки LDAP.

private bool BindLdap(NetworkCredential creds, ContextOptions contextOptions)
{
  LdapConnection current = (LdapConnection) null;
  ...
  current = new LdapConnection(this.directoryIdent);
  ...
  try
  {
    current.SessionOptions.FastConcurrentBind();

Метод FastConcurrentBind находит сертификат и, поскольку SSL включен в параметрах подключения, запрашивает PIN-код.

если быстрая привязка не поддерживается, вызывается Bind и делает то же самое:

private void lockedLdapBind(
  LdapConnection current, 
  NetworkCredential creds, 
  ContextOptions contextOptions)
{
  current.AuthType = 
    (ContextOptions.SimpleBind & contextOptions) > (ContextOptions) 0 
      ? AuthType.Basic 
      : AuthType.Negotiate;
  current.SessionOptions.Signing = 
    (ContextOptions.Signing & contextOptions) > (ContextOptions) 0;
  current.SessionOptions.Sealing = 
    (ContextOptions.Sealing & contextOptions) > (ContextOptions) 0;

  if (creds.UserName == null && creds.Password == null)
    current.Bind();
  else
    current.Bind(creds);
}

Чтобы предотвратить это, параметры сеанса должны быть изменены следующим образом.

current.SessionOptions.QueryClientCertificate = 
  new QueryClientCertificateCallback((a,b) => null);

Проблема в том, что это нельзя сделать для внутреннего класса извне.

Это можно сделать только при создании объекта LdapConnection вручную.

person Daniel Fisher lennybacon    schedule 03.05.2018
comment
Спасибо огромное. Я играл с добавлением аутентификации смарт-карты в LDAP, и как только я вернулся к обычной аутентификации TLS без сертификатов, я столкнулся с проблемами, когда Windows постоянно просит меня вставить смарт-карту. Это сразу исправило. - person ChopperCharles; 08.03.2019
comment
Я рад помочь. Не могли бы вы отметить это как ответ? Проголосуйте за него, чтобы другие пользователи сразу увидели, что это правильно, пожалуйста. - person Daniel Fisher lennybacon; 13.03.2019