I'm trying to connect to AD in Windows Server 2008 according to these instructions from MSDN. Until calling ldap_bind_s
all is ok, but then I got error with 0x31 code(The supplied credential is invalid).
Username and password are correct, I've checked for several times.
Using C++ MSVS 2015. Here is my code sample.
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;
}
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. Also I tried to set secIdent.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
without any result.
Below is PHP code snippet that performs successful connection to same AD Server
$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');
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()
.
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"[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;
}