如何解决ldap 与 sasl + gssapi 和 windows api 绑定
我确实看到有些人已经列出了步骤,例如
- SASL bind over GSSAPI using kerberos credentials with ldap_sasl_bind_s function
- ldap_sasl_bind_s(GSSAPI) - What should be provided in the credentials BERVAL structure
我的要求是仅使用令牌将 kerberos 与 sasl+ gssapi 绑定,无需密码或其他。我按照说明进行操作,这是我的示例代码:
bool ActiveDirectoryLoginWithoutPassword(std::string& aErrorTxt)
{
LDAP* ld = NULL;
int rc = 0;
const int version = LDAP_VERSION3;
SEC_WINNT_AUTH_IDENTITY wincreds;
struct berval* servresp = NULL;
SECURITY_STATUS res;
CredHandle credhandle;
CtxtHandle newhandle;
SecBufferDesc OutBuffDesc;
SecBuffer OutSecBuff;
SecBufferDesc InBuffDesc;
SecBuffer InSecBuff;
unsigned long contextattr;
ZeroMemory(&wincreds,sizeof(wincreds));
wincreds.Domain = (unsigned char*)domainName;
wincreds.DomainLength = strlen(domainName);
wincreds.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
TimeStamp tsExpiry;
res = AcquireCredentialsHandle(
NULL,"Kerberos",SECPKG_CRED_BOTH,NULL,&credhandle,&tsExpiry);
if (res != SEC_E_OK)
{
aErrorTxt = "AcquireCredentialsHandle failed";
return false;
}
OutBuffDesc.ulVersion = SECBUFFER_VERSION;
OutBuffDesc.cBuffers = 1;
OutBuffDesc.pBuffers = &OutSecBuff;
OutSecBuff.BufferType = SECBUFFER_TOKEN;
OutSecBuff.pvBuffer = NULL;
char domainName* = "Domian1";
ld = ldap_init(domainName,LDAP_PORT);
rc = ldap_set_option(ld,LDAP_OPT_SIGN,LDAP_OPT_ON);
rc = ldap_set_option(ld,LDAP_OPT_ENCRYPT,LDAP_OPT_PROTOCOL_VERSION,(void*)&version);
rc = ldap_connect(ld,NULL); //Connect befor SASL bind!
if (rc != LDAP_SUCCESS)
{
aErrorTxt = std::string("ldap_connect failed with error:") + ldap_err2string(rc) +
std::string(",domain:") + std::string(domainName);
ldap_unbind(ld);
return false;
}
const size_t bufferSize = 256;
TCHAR loginUserName[bufferSize];
memset(loginUserName,bufferSize);
DWORD size = bufferSize - 1;
if (!GetUserName(loginUserName,&size))
{
aErrorTxt = "Failed to get current user name";
return false;
}
unsigned long ulClientFlags = ISC_REQ_CONNECTION | ISC_REQ_MUTUAL_AUTH | ISC_REQ_DELEGATE;
res = InitializeSecurityContext(
&credhandle,"ldap/lccn-dc4.com@CHINA.COM",ulClientFlags,&newhandle,&OutBuffDesc,&contextattr,NULL);
struct berval cred;
cred.bv_len = OutSecBuff.cbBuffer;
cred.bv_val = (char*)OutSecBuff.pvBuffer;
rc = ldap_sasl_bind_s(
ld,"","GSSAPI",&cred,&servresp);
ldap_get_option(ld,LDAP_OPT_ERROR_NUMBER,&res);
if (rc != LDAP_SUCCESS) {
aErrorTxt = std::string("Bind failed with: ") + ldap_err2string(rc);
ldap_unbind(ld);
return false;
}
InBuffDesc.ulVersion = 0;
InBuffDesc.cBuffers = 1;
InBuffDesc.pBuffers = &InSecBuff;
InSecBuff.cbBuffer = servresp->bv_len;
InSecBuff.BufferType = SECBUFFER_TOKEN;
InSecBuff.pvBuffer = servresp->bv_val;
res = InitializeSecurityContext(
&credhandle,&InBuffDesc,NULL);
cred.bv_len = OutSecBuff.cbBuffer;
cred.bv_val = (char*)OutSecBuff.pvBuffer;
rc = ldap_sasl_bind_s(
ld,&res);
if (rc != LDAP_SUCCESS) {
aErrorTxt = std::string("Bind failed with: ") + ldap_err2string(rc);
ldap_unbind(ld);
return false;
}
SecBuffer InSecBuff2[2];
InBuffDesc.ulVersion = SECBUFFER_VERSION;
InBuffDesc.cBuffers = 2;
InBuffDesc.pBuffers = InSecBuff2;
InSecBuff2[0].cbBuffer = servresp->bv_len;
InSecBuff2[0].BufferType = SECBUFFER_STREAM;
InSecBuff2[0].pvBuffer = servresp->bv_val;
InSecBuff2[1].cbBuffer = 0;
InSecBuff2[1].BufferType = SECBUFFER_DATA;
InSecBuff2[1].pvBuffer = NULL;
ULONG ulQop;
res = DecryptMessage(&newhandle,&ulQop);
SecPkgContext_Sizes sizes;
res = QueryContextAttributes(&newhandle,SECPKG_ATTR_SIZES,&sizes);
if (res != SEC_E_OK) {
aErrorTxt = std::string("QueryContextAttributes failed ");
return false;
}
SIZE_T inbufSize = sizes.cbSecurityTrailer + 4 + sizes.cbBlockSize;
SEC_CHAR* inbuf = (SEC_CHAR*)malloc(inbufSize);
SecBuffer InSecBuff3[3];
InBuffDesc.ulVersion = SECBUFFER_VERSION;
InBuffDesc.cBuffers = 3;
InBuffDesc.pBuffers = InSecBuff3;
InSecBuff3[0].cbBuffer = sizes.cbSecurityTrailer;
InSecBuff3[0].BufferType = SECBUFFER_TOKEN;
InSecBuff3[0].pvBuffer = inbuf;
InSecBuff3[1].cbBuffer = InSecBuff2[1].cbBuffer;
InSecBuff3[1].BufferType = SECBUFFER_DATA;
InSecBuff3[1].pvBuffer = inbuf + sizes.cbSecurityTrailer;
memcpy(InSecBuff3[1].pvBuffer,InSecBuff2[1].pvBuffer,InSecBuff2[1].cbBuffer);
InSecBuff3[2].cbBuffer = sizes.cbBlockSize;
InSecBuff3[2].BufferType = SECBUFFER_PADDING;
InSecBuff3[2].pvBuffer = inbuf + sizes.cbSecurityTrailer + 4;
ULONG fQOP = SECQOP_WRAP_NO_ENCRYPT;
res = EncryptMessage(&newhandle,fQOP,0);
if (res != SEC_E_OK) {
aErrorTxt = std::string("EncryptMessage failed ");
return false;
}
cred.bv_len = inbufSize;
cred.bv_val = (char*)inbuf;
rc = ldap_sasl_bind_s(
ld,&servresp);
if (rc != LDAP_SUCCESS) {
aErrorTxt = std::string("Bind failed with: ") + ldap_err2string(rc);
ldap_unbind(ld);
return false;
}
ldap_get_option(ld,&res);
return true;
}
目前的问题是最后一个 ldap_sasl_bind_s 返回“Invalid Credentials”。请帮我检查错误在哪里。
非常感谢。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。