I am trying to search Active Directory for all attributes of a computer account. All of the the attributes get listed completely in PowerShell, but when I use ldap-search and open ldap in C++, I get only partial results even though the value is populated in the directory.
Many of the posts suggested to check if you are bound to port 3268 which is the global catalog and change it to port 389 which is the ldap port. But I am bound to the ldap port and I have also tried specifically listing the required attribute. But still I don't obtain the attribute.
This is the search query I used for ldap search
ldapsearch -x -h example.com -D "CN=Administrator,CN=Users,DC=example,DC=com" -w "passw"
-b "DC=example,DC=com" "(objectclass=computer)" '*'
This is the c++ code which i have used from oracle docs:
#include <stdio.h>
#include "ldap.h"
/* Change these as needed. */
#define HOSTNAME "localhost"
#define PORTNUMBER LDAP_PORT
#define BASEDN "dc=example,dc=com"
#define SCOPE LDAP_SCOPE_SUBTREE
#define FILTER "(objectclass=computer)"
int main( int argc, char **argv )
{
LDAP *ld;
LDAPMessage *res, *msg;
LDAPControl **serverctrls;
BerElement *ber;
char *a, *dn, *matched_msg = NULL, *error_msg = NULL;
char **vals, **referrals;
int version, i, rc, parse_rc, msgtype, num_entries = 0,
num_refs = 0;
/* Get a handle to an LDAP connection. */
if ( (ld = ldap_init( HOSTNAME, PORTNUMBER )) == NULL ) {
perror( "ldap_init" );
return( 1 );
}
version = LDAP_VERSION3;
if ( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) !=
LDAP_SUCCESS ) {
rc = ldap_get_lderrno( ld, NULL, NULL );
fprintf( stderr, "ldap_set_option: %s\n", ldap_err2string( rc ) );
ldap_unbind( ld );
return( 1 );
}
/* Bind to the server anonymously. */
rc = ldap_simple_bind_s( ld,"cn=Administrator,cn=users,dc=example,dc=net", "passw" );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_simple_bind_s: %s\n", ldap_err2string( rc ) );
ldap_get_lderrno( ld, &matched_msg, &error_msg );
if ( error_msg != NULL && *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL && *matched_msg != '\0' ) {
fprintf( stderr, "Part of the DN that matches an existing entry: %s\n", matched_msg );
}
ldap_unbind_s( ld );
return( 1 );
}
/* Perform the search operation. */
rc = ldap_search_ext_s( ld, BASEDN, SCOPE, FILTER, NULL, 0, NULL, NULL, NULL, LDAP_NO_LIMIT, &res );
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_search_ext_s: %s\n", ldap_err2string( rc ) );
if ( error_msg != NULL && *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL && *matched_msg != '\0' ) {
fprintf( stderr, "Part of the DN that matches an existing entry: %s\n", matched_msg );
}
ldap_unbind_s( ld );
return( 1 );
}
num_entries = ldap_count_entries( ld, res );
num_refs = ldap_count_references( ld, res );
/* Iterate through the results. An LDAPMessage structure sent back from
a search operation can contain either an entry found by the search,
a search reference, or the final result of the search operation. */
for ( msg = ldap_first_message( ld, res ); msg != NULL; msg = ldap_next_message( ld, msg ) ) {
/* Determine what type of message was sent from the server. */
msgtype = ldap_msgtype( msg );
switch( msgtype ) {
/* If the result was an entry found by the search, get and print the
attributes and values of the entry. */
case LDAP_RES_SEARCH_ENTRY:
/* Get and print the DN of the entry. */
if (( dn = ldap_get_dn( ld, res )) != NULL ) {
printf( "dn: %s\n", dn );
ldap_memfree( dn );
}
/* Iterate through each attribute in the entry. */
for ( a = ldap_first_attribute( ld, res, &ber );
a != NULL; a = ldap_next_attribute( ld, res, ber ) ) {
/* Get and print all values for each attribute. */
if (( vals = ldap_get_values( ld, res, a )) != NULL ) {
for ( i = 0; vals[ i ] != NULL; i++ ) {
printf( "%s: %s\n", a, vals[ i ] );
}
ldap_value_free( vals );
}
ldap_memfree( a );
}
if ( ber != NULL ) {
ber_free( ber, 0 );
}
printf( "\n" );
break;
case LDAP_RES_SEARCH_REFERENCE:
/* The server sent a search reference encountered during the
search operation. */
/* Parse the result and print the search references.
Ideally, rather than print them out, you would follow the
references. */
parse_rc = ldap_parse_reference( ld, msg, &referrals, NULL, 0 );
if ( parse_rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_parse_result: %s\n", ldap_err2string( parse_rc ) );
ldap_unbind( ld );
return( 1 );
}
if ( referrals != NULL ) {
for ( i = 0; referrals[ i ] != NULL; i++ ) {
printf( "Search reference: %s\n\n", referrals[ i ] );
}
ldap_value_free( referrals );
}
break;
case LDAP_RES_SEARCH_RESULT:
/* Parse the final result received from the server. Note the last
argument is a non-zero value, which indicates that the
LDAPMessage structure will be freed when done. (No need
to call ldap_msgfree().) */
parse_rc = ldap_parse_result( ld, msg, &rc, &matched_msg, &error_msg, NULL, &serverctrls, 0 );
if ( parse_rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_parse_result: %s\n", ldap_err2string( parse_rc ) );
ldap_unbind( ld );
return( 1 );
}
/* Check the results of the LDAP search operation. */
if ( rc != LDAP_SUCCESS ) {
fprintf( stderr, "ldap_search_ext: %s\n", ldap_err2string( rc ) );
if ( error_msg != NULL & *error_msg != '\0' ) {
fprintf( stderr, "%s\n", error_msg );
}
if ( matched_msg != NULL && *matched_msg != '\0' ) {
fprintf( stderr, "Part of the DN that matches an existing entry: %s\n", matched_msg );
}
} else {
printf( "Search completed successfully.\n"
"Entries found: %d\n"
"Search references returned: %d\n",
num_entries, num_refs );
}
break;
default:
break;
}
}
/* Disconnect when done. */
ldap_unbind( ld );
return( 0 );
}
ldapsearch
command line that works? – user207421ldapsearch
case you asked for*
, which means all non-operational attributes; in the C++ case you provided NULL, which means the same thing. If you want the operational attributes as well, you have to specify*,+
in both cases. – user207421