0
votes

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 );
}
1
Os this question about the use of a command line tool or about C++? Make it the one or the other. In the former case, you should state the exact version of the tool. In the latter case, show C++ code and the exact version of the libraries you're using.Tomalak
If your question is about your C++ code, why did you only post the ldapsearch command line that works?user207421
@Tomalak I have tried using both c++ and cmd tool but both of the methods does not return all the attributes. i am using ldap version 3. And just to clarify , does this have anything to do with the type of bind operation?sham
It has to do with what attributes you ask for. In the ldapsearch 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
@user207421 hey, i tried using this query , but it does not list all attributes. ldapsearch -x -h example.net -p 389 -D "CN=Administrator,CN=Users,DC=example,DC=net" -W "passw" -b "CN=Computers,DC=example,DC=net" "(objectclass=computer)" "*,+" .Is this query right?sham

1 Answers

0
votes

In your code, you do a simple_bind_s with NULL parameters, which means that you are doing an Anonymous bind and as such the client doesn't have the permission to read all attributes. If you were to authenticate with the same user as in ldapsearch, you will probably get the same result.