7

ドメイン コントローラーに対して一連の資格情報を検証したいと考えています。例えば:

Username: joel
Password: splotchy
Domain:   STACKOVERFLOW

.NET 3.5 以降では、PrincipalContext.ValidateCredentials(username, password) .

そうでなければ、あなたは困っています。

Microsoft ナレッジ ベースの記事How to validate user credentials on Microsoft operating systemsのコードに従って、次のように呼び出します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

更新 2Negotiate : 優先プロバイダーと、Windows NT4 の従来の "NTLM" プロバイダーの両方を試しました。

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
4

1 に答える 1

1

これは、投稿した別の質問と同じ問題を解決することだと思います。

あなたが今何をしようとしているのか、なんとなくわかります。別の投稿で書いたことを要約させてください。

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. ローカル ユーザーを認証する

最初の 2 つのケースは、ドメイン コントローラーと適切な SSPI ハンドシェイクを行うことで実現できます。別の質問で参照している KB 記事は、ループバック SSPI ハンドシェイクを行っています。クライアント マシンが認証先のドメインを信頼していないため、ケース 1 では機能しません。それがあなたが見ている理由ですSEC_E_NO_AUTHENTICATING_AUTHORITY

要するに、あなたがまったく同じことをしたいのであれば

PrincipalContext.ValidateCredentials(username, password);

ドメイン ユーザーとは異なる方法でローカル ユーザーを処理する必要があります。ドメイン ユーザーの場合、ldap_bind_sを呼び出して、指定された資格情報を使用してドメイン コントローラーにバインドする必要があります。ローカル ユーザーの場合、 ADsOpenObject を使用して、指定された資格情報を使用してWinnT://YourComputerNameバインドする必要があります。これは、リフレクターで読んだことから何をしているのかです。PrincipalContext.ValidateCredentials

同じことを行う同等の単一のネイティブ API はありません。

于 2012-03-26T06:03:06.480 に答える