RFC 3244のように Kerberos パスワード プロトコルを使用して、C++/CLI ライブラリ (別のサービスによって呼び出される) から ActiveDirectory 内のユーザーに対して多くのパスワード操作を実行しようとしています。
LogonUser を使用して管理者になりすまし、DirectoryServices.AccountManagement 名前空間を使用して、ユーザーのエントリでSetPasswordを呼び出す C# (私の好みの言語) でシーケンスをモックアップしました。SetPassword は、LDAPS、Kerberos、および RPC の変更を試みるために 3 つのアプローチを使用します。Wireshark トレースを見ると、管理者が偽装されたときに Kerberos ハンドシェイクが行われ、次に LDAP が試行され (SSL がないために失敗)、次に kerberos パスワードが交換されていることがわかります。
これを再現しようとしているのは、C++ の LogonUser が Kerberos 交換を開始しないため、SetPassword が呼び出されると、メソッドは RPC に移行します (これは成功しますが、Kerberos を使用するという要件を満たしていません)。
Kerberos の使用を強制する方法はありますか?
SetPassword に依存するのではなく、.net から Kerberos パスワード プロトコルと対話するためのより良いソリューションはありますか?
最小限のコード例:
C#
SafeTokenHandle handle;
LogonUser("serviceAccount", "Test", "aPassw0rd", 2, 0, out handle);
WindowsIdentity.Impersonate(handle.DangerousGetHandle());
DirectoryEntry usr = new DirectoryEntry();
usr.Path = "LDAP://"+"dctest.test.com/"+"CN=testuser,CN=Users,DC=test,DC=com";
usr.AuthenticationType = AuthenticationTypes.Sealing | AuthenticationTypes.Secure;
object ret = usr.Invoke("SetPassword", "aPassw0rd");
usr.CommitChanges();
usr.Close();
Console.WriteLine("Completed");
このアプローチは、サービス アカウントの偽装に成功し、464 を介して KPASSWD を使用して setpassword を実行します。
C++/CLI
HANDLE _handle;
LogonUser(L"serviceAccount",L"Test",L"aPassw0rd",LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,&_handle)
ImpersonateLoggedOnUser(_handle);
DirectoryEntry^ usr = gcnew DirectoryEntry();
usr->Path = "LDAP://"+"dctest.test.com/"+"CN=testuser,CN=Users,DC=test,DC=com";
usr->AuthenticationType = AuthenticationTypes::Sealing | AuthenticationTypes::Secure;
Object^ ret = usr->Invoke("SetPassword", "aPassw0rd");
usr->CommitChanges();
usr->Close();
Console::WriteLine("Completed");
このアプローチは管理者アカウントを偽装し、パスワードの設定が呼び出されると、kerberos 交換 (88 を超えるため、これは認証であると推測しています) を行いますが、RPC の使用にフォールバックします。
C# コードを取得して C++/CLI ラッパーから呼び出すと、コードが C++ の場合と同じように動作が変わります。