Я пытаюсь выполнить ряд операций с паролями для пользователя в ActiveDirectory из библиотеки C ++ / CLI (которая, в свою очередь, будет вызываться другой службой), используя протокол паролей Kerberos, как в RFC 3244.
Я смоделировал последовательность в C # (это мой предпочтительный язык), используя LogonUser для олицетворения администратора, а затем использовал пространство имен DirectoryServices.AccountManagement для вызова Установка пароля на записи пользователя. SetPassword использует три подхода для попытки изменения LDAPS, Kerberos и RPC. Если я посмотрю на трассировку Wireshark, то смогу увидеть рукопожатие Kerberos при олицетворении администратора, затем попытку LDAP (которая не удалась из-за отсутствия SSL), а затем обмен паролем Kerberos.
Попытка повторить это — C ++ LogonUser не инициирует обмен Kerberos, поэтому, когда вызывается SetPassword, метод переходит к RPC (что успешно, но не соответствует нашему требованию использования Kerberos).
Есть ли способ, которым я могу форсировать использование Kerberos?
Есть ли лучшее решение для взаимодействия с протоколом паролей Kerberos из .net, а не полагаться на 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");
Этот подход успешно олицетворяет служебную учетную запись, затем выполняет setpassword, используя KPASSWD через 464.
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 ++.
Наконец-то удалось проследить это на днях, пропустив вывод обратно через отражатель.
Свойства проекта для класса C ++ / CLI включали установку набора символов в Unicode. С этим набором вывод использует метод LogonUserW. Однако если этот параметр изменен на «Не установлено», то используется метод LogonUser, и путь аутентификации Kerberos для setPassword ведет себя как обычно.
Других решений пока нет …