Мне удалось выполнить связывание LDAP SASL через GSSAPI, используя ldap_sasl_bind_s
.Для тех, кто заинтересован, вот несколько указателей.
Для абстрактного описания действий, которые клиент и сервер должны выполнить во время аутентификации SASL GSSAPI, "Простая аутентификация Kerberos V5 (" GSSAPI ") иМеханизм уровня безопасности (SASL) " Следует прочитать RFC;В частности, интерес представляет раздел «Клиентская сторона Exchange по протоколу аутентификации», поскольку в нем указывается последовательность действий, которые нам необходимо выполнить для успешного связывания с сервером LDAP через Kerberos.
Учетные данные ldap_sasl_bind_s
ожидает - их форма и их значение - зависят от фактического используемого механизма аутентификации, который в нашем случае - Kerberos.
В Microsoft SDK Kerberos доступен через SSPI - что примерно соответствует реализации GSSAPI от Microsoft.;методы, которые относятся к нашему конкретному случаю: AcquireCredentialsHandle
, InitializeSecurityContext
, DecryptMessage
, EncryptMessage
Связывание LDAP SASL с Kerberos имеет 3 фазы.
Фаза 1
Вызов AcquireCredentialsHandle
и InitializeSecurityContext
.
Важные примечания:
- передача
AcquireCredentialsHandle
указателя на структуру SEC_WINNT_AUTH_IDENTITY
, содержащую фактические учетные данные (область), имя пользователя, пароль) или NULL
, если должны использоваться учетные данные текущего потока - целевое имя должно быть именем участника-службы, сопоставленным с учетной записью, под которой работает сервер LDAP
- при вызове
InitializeSecurityContext
необходимо запросить взаимную аутентификацию.
Если все важные аргументы верны - действительные учетные данные, действительный SPN, NULL
входной токен - вызов InitializeSecurityContext
должен вернуть SEC_I_CONTINUE_NEEDED
и правильно заполнить выходной токен.Содержимое этого выходного токена должно быть в структуре BERVAL
, которую ldap_sasl_bind_s
ожидает в качестве учетных данных клиента.
Вызовите ldap_sasl_bind_s
с токеном вывода из InitializeSecurityContext
в качестве учетных данных клиента.Если все аргументы верны - пустой DN, GSSAPI в качестве имени механизма - реальный вызов должен вернуть LDAP_SUCCESS
, а самая последняя ошибка LDAP для сеанса LDAP должна быть LDAP_SASL_BIND_IN_PROGRESS
.
В качестве примечания, самую последнюю ошибку LDAP для сеанса LDAP можно обнаружить, вызвав ldap_get_option
в сеансе с LDAP_OPT_ERROR_NUMBER
в качестве опции.
Этап 2
После успешного вызова ldap_sasl_bind_s
его последний аргумент указывает на структуру BERVAL
, содержащую учетные данные сервера.Содержимое этой структуры BERVAL
теперь должно использоваться в качестве входного токена для второго вызова InitializeSecurityContext
.
Этот второй вызов InitializeSecurityContext
должен вернуть SEC_OK
и пустой токен вывода.
Этот пустой выходной токен следует использовать в качестве учетных данных клиента для другого вызова ldap_sasl_bind_s
.Этот второй вызов ldap_sasl_bind_s
должен вернуть LDAP_SUCCESS
, причем самой последней ошибкой LDAP для сеанса LDAP будет LDAP_SASL_BIND_IN_PROGRESS
.
Этап 3
После второго успешного вызова ldap_sasl_bind_s
, его последний аргумент указывает на структуру BERVAL
, содержащую данные сервера.Эти данные сервера должны быть введены как DecryptMessage
.Как указано в ранее упомянутом RFC, расшифрованные данные должны иметь длину 4 байта.
Клиент должен построить свой ответ в соответствии с информацией в том же RFC.
Примечание : В моем случае я пропустил идентификатор авторизации, упомянутый в RFC.Насколько я понимаю, пустой идентификатор авторизации приводит к тому, что идентификатор авторизации также используется для авторизации.
Ответ, созданный клиентом, должен быть передан в качестве ввода в EncryptMessage
.Выходные данные вызова EncryptMessage
должны затем передаваться как учетные данные клиента для третьего и последнего вызова в ldap_sasl_bind_s
.
Примечание : документация MSDN для использования EncryptMessage
вKerberos кажется неполным.Поиск кода Google должен помочь с рабочим примером.Также, для рабочего примера описанного выше потока, можно обратиться к исходному коду Samba.