Visual Studio 无法在C++中将“ldap_bind_s”绑定到AD(0x31错误代码)

iyfjxgzm  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(100)

我试图连接到AD在Windows Server 2008根据these instructions from MSDN .直到调用ldap_bind_s一切正常,但后来我得到了错误0x31代码(The supplied credential is invalid).
账号和密码都是正确的,我已经检查了好几遍了。
使用C++ MSVS 2015。这里是我的代码示例。

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;

//[email protected]
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;
}

字符串
控制台输出:

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


在我看来,错误可能是由编码或域名引起的。但根据this answerSEC_WINNT_AUTH_IDENTITY结构中的域字段被忽略。我也试图设置secIdent.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;没有任何结果。

UPD。

下面是执行成功连接到同一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,'[email protected]','mypassword');

weylhg0b

weylhg0b1#

看完this example找到解决办法
我应该在ldap_bind_s()中使用LDAP_AUTH_SIMPLE身份验证方法而不是LDAP_AUTH_NEGOTIATE,或者简单地使用ldap_simple_bind_s()
工作代码段

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"[email protected]";
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;
}

字符串

cxfofazt

cxfofazt2#

Microsoft Docs在上面提到的链接使用LDAP_AUTH_NEGOTIATE你只需要传递第三个参数就足够了。我的程序工作正常下面是一个片段:

std::wstring username = L"Your user name ";
std::wstring password = L"Your password";
std::wstring domain = L"Your domain";

secIdentity.User = (unsigned short*) username.c_str(); // Replace with the username
secIdentity.UserLength = username.length();
secIdentity.Password = (unsigned short*) password.c_str(); // Replace with the username
secIdentity.PasswordLength = password.length();
secIdentity.Domain = (unsigned short*) domain.c_str(); // Replace with the domain
secIdentity.DomainLength = domain.length();
secIdentity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;

//ldapResult = ldap_simple_bind_sW(ldapConnection, (PWCHAR)username.c_str(), (PWCHAR)password.c_str()); // --> work as expected

ldapResult = ldap_bind_sW(ldapConnection, NULL, (PWCHAR)&secIdentity, LDAP_AUTH_NEGOTIATE);

字符串

相关问题