SASL使用带有ldap_sasl_bind_s函数的Kerberos凭证通过GSSAPI进行绑定 [英] SASL bind over GSSAPI using kerberos credentials with ldap_sasl_bind_s function

查看:154
本文介绍了SASL使用带有ldap_sasl_bind_s函数的Kerberos凭证通过GSSAPI进行绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用带有ldap_sasl_bind_s函数的kerberos凭据在GSSAPI上实现SASL绑定.我遵循

I am trying to implement SASL bind over GSSAPI using kerberos credentials with ldap_sasl_bind_s function. I follow to the steps described in ldap_sasl_bind_s(GSSAPI) - What should be provided in the credentials BERVAL structure chain

我获得了提到的链中描述的所有调用的期望返回值,直到对ldap_sasl_bind_s的最后(第三次)调用失败,并因LDAP_INVALID_CREDENTIALS错误而失败.我也看到Windows事件查看器中发生以下错误

I get expected return values for all calls described in the mentioned chain, until the last(third) call to ldap_sasl_bind_s, which fails with LDAP_INVALID_CREDENTIALS error. Also I see the following error occurs in the windows event viewer

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

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

Please note I have two applications, let us call them client and server, client is being run under some Active domain account,server application receives credentials from the client and tries to bind to ldap using tokens provided by the client. here are the steps I do. Client calls

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

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

After filling credhandle1 I pass it to the first call of InitializeSecurityContext again in the client side

  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.

I use one of the spn-s available in my active directory setup. This call returns SEC_I_CONTINUE_NEEDED, and fills sec_buffer_desc1 which is then passed to my server application to call ldap_sasl_bind_s with constructed token.

第一次调用ldap_sasl_bind_s返回LDAP_SUCCESS,并填充struct berval * servresp,这是调用

First call of ldap_sasl_bind_s returns LDAP_SUCCESS, and fills struct berval *servresp, here is the call

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

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

The token in servresp is passed to the client application which does the second call of InitializeSecurityContext as follows

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的服务器

InBuffDesc3 contains credentials returned from the server. This call returns SEC_E_OK, and produced empty output token in sec_buffer_desc3, This token is passed to the server which calls ldap_sasl_bind_s second time

rc1 = ldap_sasl_bind_s(ld1, "", "GSSAPI", &cred2, NULL, NULL, &servresp2);

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

This call again returns LDAP_SUCCESS and fills servresp2 with 32 byte long token which is then passed to the client. Last error message in the server is LDAP_SASL_BIND_IN_PROGRESS.

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

I pass to DecryptMessage NewContext2 (that was received in InitSecContext call) as a first argument. BuffDesc passed as second argument to DecryptMessage contains pointer to two SecBuffer objects, SecBuffer[0] has type SECBUFFER_STREAM and contains server response (token generated by the second call of ldap_sasl_bind_s) and SecBuffer[1] has type SECBUFFER_DATA.After DecryptMessage call SecBuffer[1] is being filled by some token(also it's size is being changed, so I think that it contains decrypted message). Third argument of DecryptMessage is 0 and the last one is being filled by SECQOP_WRAP_NO_ENCRYPT value after Decrypting the message. Here is the call

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

在传递给DecryptMessage的SECBUFFER_DATA缓冲区中,我收到4个字节长的令牌(似乎是输入SECBUFFER_STREAM缓冲区的最后4个字节). 解密的邮件(SecBuff [1] .pvBuffer)"的第一个字节为7,然后执行以下操作

In SECBUFFER_DATA buffer passed to DecryptMessage I receive 4 bytes long token (which seems to be the last 4 bytes of input SECBUFFER_STREAM buffer). The first byte of "decrypted message(SecBuff[1].pvBuffer)" is 7, then I do the following

    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称为

I am constructing the input SecBufferDesc object for EncryptMessage using three buffers, first one has type SECBUFFER_TOKEN which is filled after EncryptMEssage call(so I think it contains encrypted message after this call), the second one has SECBUFFER_DATA type and contains ptr I have constructed above, and the third buffer of type SECBUFFER_PADDING. I call EncryptMessage as follows

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

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

which returns SEC_E_OK, and produces 28 bytes long token in the buffer with type SECBUFFER_TOKEN, this output token is then passed to my server application which calls ldap_sasl_bind_s with this token as client credentials and fails with invalid credentials error.

我查看了帖子中提到的RFC,它也试图找到具有SASL和kerberos凭据的任何有效示例,但是无法处理此错误. 任何帮助将不胜感激,请您帮助我解决这个问题,或者提供一些工作代码示例,以便我看看.

I looked at RFC mentioned in the post also tried to find any working example with SASL and kerberos credentials, however was not able to deal with this error. Any help will be appreciated, could you please help me to get to the bottom of this issue, or provide some working code example so that I can take a look.

谢谢! -格里格(Grigor)

Thank you ! -Grigor

推荐答案

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

I ran into the exact same problem, and I think I found the solution:

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

The message you send in the third ldap_sasl_bind_s call should be the concatenation of all three buffers given to EncryptMessage (in the order TOKEN, DATA, PADDING)

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

When I do that, it works!

这篇关于SASL使用带有ldap_sasl_bind_s函数的Kerberos凭证通过GSSAPI进行绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆