SASL使用kerberos凭证与ldap_sasl_bind_s函数

时间:2015-09-13 22:00:32

标签: c++ active-directory ldap sspi gssapi

我正在尝试使用带有ldap_sasl_bind_s函数的kerberos凭据在GSSAPI上实现SASL绑定。我按照ldap_sasl_bind_s(GSSAPI) - What should be provided in the credentials BERVAL structure

中描述的步骤进行操作

我得到了上述链中描述的所有调用的预期返回值,直到对ldap_sasl_bind_s的最后一次(第三次)调用,该调用因LDAP_INVALID_CREDENTIALS错误而失败。此外,我看到Windows事件查看器中出现以下错误

Error value:
80090308: LdapErr: DSID-0C0904D1, comment: AcceptSecurityContext error, data 5, v1771

请注意我有两个应用程序,让我们称它们为客户端和服务器,客户端在某个Active域帐户下运行,服务器应用程序从客户端接收凭据并尝试使用客户端提供的令牌绑定到ldap。 这是我要做的步骤。客户来电

int res = AcquireCredentialsHandle(NULL, "Kerberos"  , SECPKG_CRED_BOTH,NULL, NULL, NULL, NULL, &credhandle1, &expry1); 

在填写credhandle1后,我再次在客户端将其传递给InitializeSecurityContext的第一次调用

  res = InitializeSecurityContext(&credhandle1,NULL,(SEC_CHAR*)(&spn1[0]),ISC_REQ_INTEGRITY|ISC_REQ_MUTUAL_AUTH|ISC_REQ_SEQUENCE_DETECT|ISC_REQ_CONFIDENTIALITY|ISC_REQ_DELEGATE,0,SECURITY_NATIVE_DREP ,NULL,0,&NewContext2,&sec_buffer_desc1,&contextattr2,&expry2);

我在我的活动目录设置中使用了一个spn-s。此调用返回SEC_I_CONTINUE_NEEDED,并填充sec_buffer_desc1,然后传递给我的服务器应用程序以使用构造的令牌调用ldap_sasl_bind_s。

首先调用ldap_sasl_bind_s返回LDAP_SUCCESS,并填充struct berval * servresp,这里是调用

rc1 = ldap_sasl_bind_s(ld1, "", "GSSAPI", &cred1, NULL, NULL, &servresp);

servresp中的令牌传递给客户端应用程序,该应用程序执行第二次InitializeSecurityContext调用,如下所示

res = InitializeSecurityContext(&credhandle1, &NewContext2, (SEC_CHAR*)(&spn1[0]),ISC_REQ_INTEGRITY|ISC_REQ_MUTUAL_AUTH|ISC_REQ_SEQUENCE_DETECT|ISC_REQ_CONFIDENTIALITY|ISC_REQ_DELEGATE,0, 0, &InBuffDesc3, 0, &NewContext3, &sec_buffer_desc3, &contextattr3, &expry3);

InBuffDesc3包含从服务器返回的凭据。 此调用返回SEC_E_OK,并在sec_buffer_desc3中生成空输出标记, 此令牌传递给第二次调用ldap_sasl_bind_s

的服务器
rc1 = ldap_sasl_bind_s(ld1, "", "GSSAPI", &cred2, NULL, NULL, &servresp2);

此调用再次返回LDAP_SUCCESS并使用32字节长令牌填充servresp2,然后将其传递给客户端。服务器中的上一条错误消息是LDAP_SASL_BIND_IN_PROGRESS。

我传递给DecryptMessage NewContext2(在InitSecContext调用中收到)作为第一个参数。作为DecryptMessage的第二个参数传递的BuffDesc包含指向两个SecBuffer对象的指针,SecBuffer [0]具有类型SECBUFFER_STREAM并且包含服务器响应(由第二次调用ldap_sasl_bind_s生成的令牌)和SecBuffer [1]具有类型SECBUFFER_DATA.After DecryptMessage调用SecBuffer [1正在被一些令牌填充(也正在改变它的大小,所以我认为它包含解密的消息)。解密消息后,DecryptMessage的第三个参数为0,最后一个参数由SECQOP_WRAP_NO_ENCRYPT值填充。这是电话

ULONG ulQop;
res = DecryptMessage( &NewContext2, &BuffDesc, 0, &ulQop); 

在传递给DecryptMessage的SECBUFFER_DATA缓冲区中,我收到4个字节长的令牌(这似乎是输入SECBUFFER_STREAM缓冲区的最后4个字节)。 "解密消息的第一个字节(SecBuff [1] .pvBuffer)"是7,然后我做以下

    unsigned char * ptr = (unsigned char *)SecBuff[1].pvBuffer;
    int maxsize = (ptr[1]<<16) | (ptr[2]<<8)| (ptr[3]);
    ptr = (unsigned char *) malloc(4);
    ptr[0]= 4;
    ptr[1]= maxsize>>16;
    ptr[2]= maxsize>>8;
    ptr[3]= maxsize; 

我正在为EncryptMessage使用构造输入SecBufferDesc对象 三个缓冲区,第一个具有SECBUFFER_TOKEN类型,在EncryptMEssage调用之后填充(所以我认为它在此调用后包含加密消息),第二个具有SECBUFFER_DATA类型并包含我在上面构造的ptr,以及第三个类型为SECBUFFER_PADDING的缓冲区。  我将EncryptMessage称为如下

err = EncryptMessage(&NewContext2,fQOP,&inSecBufDescSecond, 0);

返回SEC_E_OK,并在类型为SECBUFFER_TOKEN的缓冲区中生成28个字节长的令牌,然后将此输出令牌传递给我的服务器应用程序,该应用程序使用此令牌作为客户端凭据调用ldap_sasl_bind_s,并因无效凭据错误而失败。

我看了帖子中提到的RFC也试图找到SASL和kerberos凭证的任何工作示例,但是无法处理这个错误。 任何帮助将不胜感激,你能帮我解决这个问题的底部,或提供一些工作代码示例,以便我可以看看。

谢谢! -Grigor

1 个答案:

答案 0 :(得分:0)

我遇到了完全相同的问题,我想找到了解决方法:

您在第三个ldap_sasl_bind_s调用中发送的消息应该是分配给EncryptMessage的所有三个缓冲区的串联(顺序为TOKEN,DATA,PADDING)

当我这样做时,它会起作用!