0

我正在尝试使用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++ 中时显示的行为。

4

1 回答 1

1

前几天终于设法通过反射器运行输出来追踪这一点。C++/CLI 类的项目属性包括将字符集设置为 unicode。使用此设置,输出使用 LogonUserW 方法。但是,如果此设置更改为“未设置”,则会使用 LogonUser 方法,并且 setPassword 的 Kerberos 身份验证路径将正常运行。

于 2013-01-29T09:55:19.030 回答