简体   繁体   English

无法将ldap_bind_s转换为C ++中的AD(0x31错误代码)

[英]Can not “ldap_bind_s” to AD in C++ (0x31 error code)

I'm trying to connect to AD in Windows Server 2008 according to these instructions from MSDN . 我正在尝试根据MSDN的这些说明连接到Windows Server 2008中的AD。 Until calling ldap_bind_s all is ok, but then I got error with 0x31 code( The supplied credential is invalid ). 直到调用ldap_bind_s都可以,但是随后我收到了0x31代码的错误( 提供的凭据无效 )。

Username and password are correct, I've checked for several times. 用户名和密码正确,我已经检查了好几次了。

Using C++ MSVS 2015. Here is my code sample. 使用C ++ MSVS2015。这是我的代码示例。

PWSTR host_name = L"ad.server.ip.address";

LDAP* pLdapConnection = NULL;
pLdapConnection = ldap_init(host_name, LDAP_PORT);

if (pLdapConnection == NULL)
{
    printf("ldap_init failed with 0x%x.\n", LdapGetLastError());
    ldap_unbind(pLdapConnection);
    return -1;
}
else
    printf("ldap_init succeeded \n");

ULONG version = LDAP_VERSION3;
ULONG lRtn = 0;

lRtn = ldap_set_option(
    pLdapConnection,          
    LDAP_OPT_PROTOCOL_VERSION, 
    (void*)&version);         

if (lRtn == LDAP_SUCCESS)
    printf("ldap version set to 3.0 \n");
else
{
    printf("SetOption Error:%0lX\n", lRtn);
    ldap_unbind(pLdapConnection);
    return hr;
}

lRtn = ldap_connect(pLdapConnection, NULL);

if (lRtn == LDAP_SUCCESS)
    printf("ldap_connect succeeded \n");
else
{
    printf("ldap_connect failed with 0x%lx.\n", lRtn);
    ldap_unbind(pLdapConnection);
    return -1;
}

PWSTR pMyDN = L"DC=ad,DC=domain,DC=name";
SEC_WINNT_AUTH_IDENTITY secIdent;

//adm@ad.domain.name
unsigned short login[18] = { 'a', 'd', 'm', '@', 'a', 'd', '.', 'd', 'o', 'm', 'a', 'i', 'n', '.', 'n', 'a', 'm', 'e' }; //18
secIdent.User = login;
secIdent.UserLength = 18;

//mypassword
unsigned short password[10] = { 'm', 'y', 'p', 'a', 's', 's', 'w', 'o', 'r', 'd' }; //10
secIdent.Password = password;
secIdent.PasswordLength = 10;

//ad.domain.name
unsigned short domain[14] = { 'a', 'd', '.', 'd', 'o', 'm', 'a', 'i', 'n', '.', 'n', 'a', 'm', 'e' }; //14
secIdent.Domain = dmn;
secIdent.DomainLength = 14;
secIdent.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;

lRtn = ldap_bind_s(
    pLdapConnection,      // Session Handle
    pMyDN,                // Domain DN
    (PWCHAR)&secIdent,     // Credential structure
    LDAP_AUTH_NEGOTIATE); // Auth mode
if (lRtn == LDAP_SUCCESS)
{
    printf("ldap_bind_s succeeded \n");
    secIdent.Password = NULL; // Remove password pointer
    pPassword = NULL;         // Remove password pointer
}
else
{
    printf("ldap_bind_s failed with 0x%lx.\n", lRtn);
    ldap_unbind(pLdapConnection);
    return -1;
}

Console output: 控制台输出:

ldap_init succeeded
ldap version set to 3.0
ldap_connect succeeded
ldap_bind_s failed with 0x31.
Cannot execute query. Cannot bind to LDAP

It seems to me that the error can be occured by encoding or domain name. 在我看来,该错误可能是由于编码或域名引起的。 But according to this answer , domain field in SEC_WINNT_AUTH_IDENTITY structure is ignored. 但是根据此答案SEC_WINNT_AUTH_IDENTITY结构中的域字段SEC_WINNT_AUTH_IDENTITY被忽略。 Also I tried to set secIdent.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; 我也试图设置secIdent.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; without any result. 没有任何结果。


UPD. UPD。

Below is PHP code snippet that performs successful connection to same AD Server 以下是可成功连接到同一AD服务器的PHP代码段

$this->c = ldap_connect("ad.server.ip.address");
ldap_set_option($this->c, LDAP_OPT_PROTOCOL_VERSION, 3);
$r = ldap_bind($this->c,'adm@ad.domain.name','mypassword');

Just found a solution after watching this example 看完这个例子才 找到解决方案

I should use LDAP_AUTH_SIMPLE authentication method instead of LDAP_AUTH_NEGOTIATE in ldap_bind_s() or simply use ldap_simple_bind_s() . 我应该在ldap_bind_s()使用LDAP_AUTH_SIMPLE身份验证方法,而不是LDAP_AUTH_NEGOTIATE ,或者仅使用ldap_bind_s() ldap_simple_bind_s()

Working code snippet 工作代码段

PWSTR host_name = L"ad.server.ip.address";

LDAP* pLdapConnection = NULL;
pLdapConnection = ldap_init(host_name, LDAP_PORT);
if (pLdapConnection == NULL)
{
    printf("ldap_init failed with 0x%x.\n", LdapGetLastError());
    ldap_unbind(pLdapConnection);
    return -1;
}
else
    printf("ldap_init succeeded \n");

ULONG version = LDAP_VERSION3;
ULONG lRtn = 0;

lRtn = ldap_set_option(
    pLdapConnection,           // Session handle
    LDAP_OPT_PROTOCOL_VERSION, // Option
    (void*)&version);         // Option value

if (lRtn == LDAP_SUCCESS)
    printf("ldap version set to 3.0 \n");
else
{
    printf("SetOption Error:%0lX\n", lRtn);
    ldap_unbind(pLdapConnection);
    return 0;
}


lRtn = ldap_connect(pLdapConnection, NULL);

if (lRtn == LDAP_SUCCESS)
    printf("ldap_connect succeeded \n");
else
{
    printf("ldap_connect failed with 0x%lx.\n", lRtn);
    ldap_unbind(pLdapConnection);
    return -1;
}


PWCHAR user_name = L"adm@ad.domain.name";
PWCHAR password = L"mypassword";

lRtn = ldap_simple_bind_s(pLdapConnection, user_name, password);
if (lRtn == LDAP_SUCCESS)
{
    printf("ldap_simple_bind_s succeeded \n");
}
else
{
    printf("ldap_simple_bind_s failed with 0x%lx.\n", lRtn);
    ldap_unbind(pLdapConnection);
    return -1;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM