Как проверить учетные данные домена (из нативного кода)? - PullRequest
6 голосов
/ 15 марта 2012

Я хочу проверить набор учетных данных на контроллере домена. e.g.:

Username: joel
Password: splotchy
Domain:   STACKOVERFLOW

В .NET 3.5 и новее вы можете использовать PrincipalContext.ValidateCredentials(username, password).

В противном случае у вас проблемы.

Следуя коду в статье базы знаний Майкрософт Как проверить учетные данные пользователя в операционных системах Microsoft , я дошел до того, что позвонил AcceptSecurityContext:

ss = AcceptSecurityContext(
      @pAS._hcred,           //[in]CredHandle structure
      phContext,             //[in,out]CtxtHandle structure
      @InBuffDesc,           //[in]SecBufferDesc structure 
      0,                     //[in]context requirement flags
      SECURITY_NATIVE_DREP,  //[in]target data representation
      @pAS._hctxt,           //[in,out]CtxtHandle strcture
      @OutBuffDesc,          //[in,out]SecBufferDesc structure
      ContextAttributes,     //[out]Context attribute flags
      @Lifetime);            //[out]Timestamp struture

за исключением того, что функция завершается с:

SEC_E_NO_AUTHENTICATING_AUTHORITY (0x80090311)

Функция не выполнена. Никакие полномочия не могли связаться для аутентификации. Это может быть связано со следующими условиями:

  • Неверное имя домена аутентифицирующей стороны.
  • Домен недоступен.
  • Не удалось установить доверительные отношения.

Это было бы полезной ошибкой, за исключением того, что я могу проверить те же учетные данные из .NET 3.5, используя:

using (PrincipalContext context = new PrincipalContext(ContextType.Domain, domain))
{
    valid = context.ValidateCredentials(username, password);                
}

Что может происходить, что позволяет .NET проверять набор учетных данных, а собственный код не может?


Обновление : LogonUser также не удается:

LogonUser("joel@stackoverflow.com", null, "splotchy", 
      LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_WINNT50, out token);

с

1311 - There are currently no logon servers available to service the logon request

Обновление два : я попробовал как предпочитаемого Negotiate поставщика, так и устаревшего поставщика NTLM для Windows NT4

String package = "Negotiate"; //"NTLM"

QuerySecurityPackageInfo(package, [out] packageInfo);
...
AcquireCredentialsHandle(
      null,                 //[in] principle
      package,              //[in] package
      SECPKG_CRED_OUTBOUND, //[in] credential use
      null,                 //[in] LogonID
      pAuthIdentity,        //[in] authData
      null,                 //[in] GetKeyFn, not used and should be null
      null,                 //[in] GetKeyArgument, not used and should be null
      credHandle,           //[out] CredHandle structure
      expires);             //[out] expiration TimeStamp structure

1 Ответ

0 голосов
/ 26 марта 2012

Я предполагаю, что это должно решить ту же проблему, что и другой вопрос , который вы отправили.

Я вроде понимаю, что вы пытаетесь сделать сейчас.Позвольте мне напомнить, что вы написали в другом посте.

Username  Password  Domain             Machine on domain?  Validate as
========  ========  =================  ==================  ============== 
iboyd     pass1     .                  No                  Local account 
iboyd     pass1     (empty)            No                  Local account
iboyd     pass1     stackoverflow.com  No                  Domain account
iboyd     pass1     .                  Yes                 Local account
iboyd     pass1     (empty)            Yes                 Domain account
iboyd     pass1     stackoverflow.com  Yes                 Domain account

Вы хотите

  1. Аутентифицировать пользователя из домена, которому ваша машина не доверяет
  2. Аутентифицировать пользователя из домена, которому доверяет ваша машина
  3. Аутентификация локального пользователя

Первые два случая можно выполнить, выполнив правильное подтверждение связи SSPI с контроллером домена.В статье базы знаний, на которую вы ссылаетесь в другом вопросе, выполняется установление обратной связи SSPI.Это не сработает в случае номер один, потому что клиентский компьютер не доверяет домену, к которому вы аутентифицируетесь.Вот почему вы видите SEC_E_NO_AUTHENTICATING_AUTHORITY.

Короче говоря, если вы хотите сделать то же самое, что и

PrincipalContext.ValidateCredentials(username, password);

, вам нужно обрабатывать локального пользователя иначе, чемпользователь домена.Пользователю домена необходимо вызвать ldap_bind_s , чтобы выполнить привязку к контроллеру домена с использованием указанных учетных данных.Для локального пользователя вам нужно использовать ADsOpenObject для привязки к WinnT: // YourComputerName с использованием указанных учетных данных.Это то, что PrincipalContext.ValidateCredentials делает из того, что я прочитал в Reflector.

Я не вижу ни одного эквивалентного единственного нативного API, делающего то же самое для вас.

...