我正在尝试使用RFC 3244中的 Kerberos 密码协议,从 C++/CLI 库(将由另一个服务调用)对 ActiveDirectory 中的用户执行一些密码操作。
我使用 LogonUser 模拟了 C# 中的序列(这是我的首选语言)来模拟管理员,然后使用 DirectoryServices.AccountManagement 命名空间在用户条目上调用SetPassword 。SetPassword 使用三种方法来尝试更改 LDAPS、Kerberos 和 RPC。如果我查看 Wireshark 跟踪,我可以看到模拟管理员时的 Kerberos 握手,然后是 LDAP 尝试(由于缺少 SSL 而失败),然后是 kerberos 密码交换。
尝试复制这是 C++ LogonUser 不会启动 Kerberos 交换,因此当调用 SetPassword 时,该方法会通过 RPC(成功但不满足我们使用 Kerberos 的要求)。
有没有办法强制使用 Kerberos?
有没有更好的解决方案来与.net 中的 Kerberos 密码协议进行交互,而不是依赖于 SetPassword?
最小代码示例:
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");
这种方法成功地模拟了服务帐户,然后使用 KPASSWD over 464 执行 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,所以我猜这是 auth),但随后回退到使用 RPC。
如果我获取 C# 代码并从 C++/CLI 包装器中调用它,则行为会更改为代码在 C++ 中时显示的行为。