Я пытаюсь использовать ldap_sasl_bind_s
метод от Microsoft LDAP C SDK, с GSSAPI как механизм аутентификации. ldap_sasl_bind_s
ожидает учетные данные как a BERVAL
структура, которая непрозрачна.
Учитывая имя пользователя (или DN) и пароль, как я добираюсь до BERVAL
структура, которой я, как предполагается, передаю ldap_sasl_bind_s
?
Примеры я нашел до сих пор
ldap_sasl_bind_s
когда Простая аутентификация желаема - но я должен использовать GSSAPIldap_sasl_interactive_bind_s
когда другие механизмы аутентификации SASL желаемы. Однако существует нет ldap_sasl_interactive_bind_s
в Microsoft SDK.Как примечание стороны, цель состоит в том, чтобы смочь обязать SASL ко множеству серверов LDAP; на данный момент: ActiveDirectory и OpenLDAP.
Любые указатели будут значительно цениться.
Мне удалось выполнить привязку LDAP SASL через GSSAPI, используя ldap_sasl_bind_s
. Для тех, кому интересно, вот несколько указателей.
Для абстрактного описания действий, которые клиент и сервер должны выполнять во время аутентификации GSSAPI SASL, «Механизм простой аутентификации и безопасности (SASL) Kerberos V5 (« GSSAPI »)» RFC должен быть прочитанным; В частности, раздел «Обмен протоколами аутентификации на стороне клиента» представляет интерес, поскольку он дает указание на последовательность действий, которые нам необходимо выполнить для успешного связывания с сервером LDAP по протоколу Kerberos.
Учетные данные ldap_sasl_bind_s
ожидаемые - их форма и их значение - зависят от фактического используемого механизма аутентификации, которым в нашем случае является Kerberos.
В Microsoft SDK Kerberos доступен через SSPI, что примерно представляет собой реализацию Microsoft GSSAPI; методы, которые актуальны для нашего конкретного случая: AcquireCredentialsHandle
, InitializeSecurityContext
, DecryptMessage
, EncryptMessage
Привязка LDAP SASL через Kerberos имеет 3 фазы.
Вызов AcquireCredentialsHandle
и InitializeSecurityContext
.
Важные примечания:
AcquireCredentialsHandle
указатель на структуру SEC_WINNT_AUTH_IDENTITY
, содержащую фактические учетные данные (область, имя пользователя, пароль) или NULL
, если должны использоваться учетные данные текущего потока 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
в качестве опции.
После успешного вызова 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
.
После второго успешного вызова ldap_sasl_bind_s
его последний аргумент указывает на структуру BERVAL
, содержащую данные сервера. Эти данные сервера должны быть введены в DecryptMessage
. Как указано в ранее упомянутом RFC, длина дешифрованных данных должна составлять 4 байта.
Клиент должен строить свой ответ в соответствии с информацией в том же RFC.
Примечание : В моем случае я пропустил идентификатор авторизации, упомянутый в RFC.Насколько я понимаю, пустой идентификатор авторизации приводит к тому, что идентификатор аутентификации также используется для авторизации.
Ответ, созданный клиентом, затем должен быть передан в качестве входных данных в EncryptMessage
. Затем результат вызова EncryptMessage
должен быть передан в качестве учетных данных клиента для третьего и последнего вызова ldap_sasl_bind_s
.
Примечание : документация MSDN по использованию EncryptMessage
под Kerberos кажется неполной. Поиск кода Google должен помочь с рабочим примером. Кроме того, для рабочего примера описанного выше потока можно обратиться к исходному коду Samba.
Статья из Sun и MSDN . Вероятно, если вы попытаетесь создать образец программы, вы получите ответы
PseudoCode
struct berval cred;
char mechanism[BUFSIZ];
getline( mechanism, sizeof(mechanism), stdin, "mechanism? " );
getline( passwd, sizeof(passwd), stdin,"credentials? " );
cred.bv_val = passwd;
cred.bv_len = strlen( passwd );
rc = ldap_sasl_bind_s( ld, dn, mechanism, &cred, NULL, NULL, NULL );