Kerberos密码更改协议

时间:2012-12-13 09:12:00

标签: c++ .net active-directory kerberos

我正在尝试使用Kerberos密码协议(例如RFC 3244)从C ++ / CLI库(其将由另一个服务调用)对ActiveDirectory中的用户执行许多密码操作。 / p>

我在C#中模拟了一个序列(是我的首选语言),使用LogonUser来模拟管理员,然后使用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超过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 ++中时的行为。

1 个答案:

答案 0 :(得分:1)

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