我设法通过 GSSAPI 执行 LDAP SASL 绑定,使用ldap_sasl_bind_s
. 对于那些感兴趣的人,这里有一些指示。
对于客户端和服务器在 GSSAPI SASL 身份验证期间需要执行的操作的抽象描述,应阅读“Kerberos V5(“GSSAPI”)简单身份验证和安全层(SASL)机制” RFC;具体来说,“身份验证协议交换的客户端”部分很有趣,因为它指示了我们需要执行的操作序列,以通过 Kerberos 成功绑定到 LDAP 服务器。
凭证的ldap_sasl_bind_s
期望——它们的形式和意义——取决于所使用的实际身份验证机制,在我们的例子中是 Kerberos。
在微软 SDK 中,Kerberos 是通过 SSPI 提供的——大致是微软对 GSSAPI 的实现;与我们的特定案例相关的方法是:AcquireCredentialsHandle
, InitializeSecurityContext
, DecryptMessage
,EncryptMessage
基于 Kerberos 的 LDAP SASL 绑定有 3 个阶段。
阶段1
呼叫AcquireCredentialsHandle
和InitializeSecurityContext
。
这里的重要说明:
- 传递到
AcquireCredentialsHandle
指向SEC_WINNT_AUTH_IDENTITY
包含实际凭据(领域、用户名、密码)的结构的指针,或者NULL
是否要使用当前线程的凭据
- 目标名称应该是映射到运行 LDAP 服务器的帐户的 SPN
- 调用时
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
。
第三阶段
在第二次成功调用 之后ldap_sasl_bind_s
,它的最后一个参数指向一个BERVAL
包含服务器数据的结构。该服务器数据应作为输入提供给DecryptMessage
. 正如前面提到的 RFC 中所规定的,解密后的数据必须是 4 个字节长。
客户端应根据同一 RFC 中的信息构建其回复。
注意:就我而言,我省略了 RFC 中提到的授权 ID。据我了解,一个空的授权 id 会导致身份验证 id 也被用于授权。
然后,客户端构建的回复应作为输入传递给EncryptMessage
. EncryptMessage
然后应将调用的输出作为第三次也是最后一次调用的客户端凭据传递给ldap_sasl_bind_s
.
注意:在 Kerberos 下使用的 MSDN 文档EncryptMessage
似乎不完整。谷歌的代码搜索应该有助于提供一个工作示例。此外,对于上述流程的工作示例,可以查阅 Samba 的源代码。