ldap_sasl_bind_s(GSSAPI)-凭证结构中应该提供什么

ldap_sasl_bind_s(GSSAPI)-凭证结构中应该提供什么,ldap,sasl,gssapi,Ldap,Sasl,Gssapi,我正在尝试使用Microsoft LDAP C SDK中的方法,使用GSSAPI作为身份验证机制ldap_sasl_bind_s希望凭据是一个不透明的BERVAL结构 给定一个用户名(或DN)和密码,我如何到达要传递给ldap\u sasl\u bind\s的BERVAL结构 到目前为止我找到的例子 来自其他LDAP C SDK,而不是来自Microsoft的SDK 当需要简单身份验证时,请使用ldap\u sasl\u bind\s,但我需要使用GSSAPI 当需要其他sasl身份验证机制时

我正在尝试使用Microsoft LDAP C SDK中的方法,使用GSSAPI作为身份验证机制
ldap_sasl_bind_s
希望凭据是一个不透明的
BERVAL
结构

给定一个用户名(或DN)和密码,我如何到达要传递给
ldap\u sasl\u bind\s
BERVAL
结构

到目前为止我找到的例子

  • 来自其他LDAP C SDK,而不是来自Microsoft的SDK
  • 当需要简单身份验证时,请使用
    ldap\u sasl\u bind\s
    ,但我需要使用GSSAPI
  • 当需要其他sasl身份验证机制时,请使用
    ldap\u sasl\u interactive\u bind\s
    。但是,Microsoft SDK中没有
    ldap\u sasl\u interactive\u bind\s
作为补充说明,目标是能够通过SASL绑定到各种LDAP服务器;目前:ActiveDirectory和OpenLDAP

任何提示都将不胜感激。

来自和的文章。如果你能尝试创建一个示例程序,你可能会得到答案

伪码

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 );

我设法使用
LDAP\u SASL\u bind\u s
在GSSAPI上执行LDAP SASL绑定。对于那些感兴趣的人,这里有一些建议

对于客户端和服务器在GSSAPI SASL身份验证期间需要执行的操作的抽象描述,应阅读Kerberos V5(“GSSAPI”)简单身份验证和安全层(SASL)机制的RFC;具体来说,“身份验证协议交换的客户端”部分很有意思,因为它指示了我们需要执行的操作序列,以便通过Kerberos成功绑定到LDAP服务器

凭证
ldap\u sasl\u bind\u s
的形式和含义取决于实际使用的身份验证机制,在我们的例子中是Kerberos

在微软SDK中,Kerberos可以通过SSPI获得,SSPI大致是微软对GSSAPI的实现;与我们的特定情况相关的方法有:
AcquireCredentialsHandle
初始化安全上下文
解密消息
加密消息

Kerberos上的LDAP SASL绑定有3个阶段

第一阶段 调用
AcquireCredentialsHandle
InitializeSecurityContext

重要注意事项如下:

  • 传递给
    AcquireCredentialsHandle
    指向包含实际凭据(域、用户名、密码)的
    SEC\u WINNT\u AUTH\u标识的结构的指针,或者如果要使用当前线程的凭据,则传递给
    NULL
  • 目标名称应该是映射到运行LDAP服务器的帐户的SPN
  • 调用
    InitializeSecurityContext
    时,必须请求相互身份验证
如果所有重要参数都正确-有效凭证、有效SPN、
NULL
输入令牌-调用
InitializeSecurityContext
应返回
SEC\u CONTINUE\u NEEDED
并正确填充输出令牌。此输出令牌的内容应位于
BERVAL
结构中
ldap\u sasl\u bind\s
期望作为客户端凭据

使用
InitializeSecurityContext
中的输出令牌作为客户端凭据调用
ldap\u sasl\u bind\s
。如果所有参数都正确-空DN,GSSAPI作为机制名称-实际调用应返回
LDAP\u SUCCESS
,LDAP会话的最新LDAP错误应为
LDAP\u SASL\u BIND\u IN\u PROGRESS

作为补充说明,可以通过在会话上调用
LDAP\u get\u option
并将
LDAP\u OPT\u error\u NUMBER
作为选项来发现LDAP会话的最新LDAP错误

第二阶段 成功调用
ldap\u sasl\u bind\s
后,其最后一个参数指向包含服务器凭据的
BERVAL
结构。此
BERVAL
结构的内容现在应该用作第二次调用
InitializeSecurityContext
的输入标记

InitializeSecurityContext
的第二次调用应返回
SEC_OK
和一个空输出令牌

此空输出令牌应用作另一个对
ldap\u sasl\u bind\u s
调用的客户端凭据。对
ldap\u sasl\u bind\s
的第二次调用应返回
ldap\u SUCCESS
,ldap会话的最新ldap错误为
ldap\u sasl\u bind\u IN\u PROGRESS

第三阶段 第二次成功调用
ldap\u sasl\u bind\s
后,其最后一个参数指向包含服务器数据的
BERVAL
结构。此服务器数据应作为
DecryptMessage
的输入提供。正如前面提到的RFC中所指定的,解密的数据必须是4字节长

客户应根据同一RFC中的信息生成回复。
注意:就我而言,我忽略了RFC中提到的授权id。据我所知,空的授权id也会导致身份验证id被用于授权

然后,客户端生成的回复应作为输入传递给
EncryptMessage
。然后,
EncryptMessage
调用的输出应作为第三次也是最后一次调用
ldap\u sasl\u bind\s
的客户端凭据传递

注意:在Kerberos下使用
EncryptMessage
的MSDN文档似乎不完整。谷歌的代码搜索应该提供一个有用的例子。另外,对于上面描述的流程的工作示例,可以参考Samba的源代码。

我发现了问题

根据这个线程()的说法,ldap_sasl_bind_返回空的服务器证书时有一个bug