Поиск Ldap возвращает не все атрибуты учетной записи в Active Directory

#active-directory #ldap #openldap

#active-directory #ldap #openldap

Вопрос:

Я пытаюсь выполнить поиск в Active Directory по всем атрибутам учетной записи компьютера. Все атрибуты полностью перечислены в PowerShell, но когда я использую ldap-search и открываю ldap на C , я получаю только частичные результаты, даже если значение заполнено в каталоге.

Во многих сообщениях предлагалось проверить, привязаны ли вы к порту 3268, который является глобальным каталогом, и изменить его на порт 389, который является портом ldap. Но я привязан к порту ldap, и я также попытался специально указать требуемый атрибут. Но я все равно не получаю атрибут.

Это поисковый запрос, который я использовал для поиска ldap

 ldapsearch -x -h example.com -D "CN=Administrator,CN=Users,DC=example,DC=com" -w "passw" 
           -b "DC=example,DC=com" "(objectclass=computer)" '*'
 

Это код c , который я использовал из 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, amp;version ) !=
            LDAP_SUCCESS ) {
        rc = ldap_get_lderrno( ld, NULL, NULL );
        fprintf( stderr, "ldap_set_option: %sn", 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: %sn", ldap_err2string( rc ) );
        ldap_get_lderrno( ld, amp;matched_msg, amp;error_msg );
        if ( error_msg != NULL amp;amp; *error_msg != '' ) {
            fprintf( stderr, "%sn", error_msg );
        }
        if ( matched_msg != NULL amp;amp; *matched_msg != '' ) {
            fprintf( stderr, "Part of the DN that matches an existing entry: %sn", 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, amp;res );
    if ( rc != LDAP_SUCCESS ) {
        fprintf( stderr, "ldap_search_ext_s: %sn", ldap_err2string( rc ) );
        if ( error_msg != NULL amp;amp; *error_msg != '' ) {
            fprintf( stderr, "%sn", error_msg );
        }
        if ( matched_msg != NULL amp;amp; *matched_msg != '' ) {
            fprintf( stderr, "Part of the DN that matches an existing entry: %sn", 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: %sn", dn );
                ldap_memfree( dn );
            }
            /* Iterate through each attribute in the entry. */
            for ( a = ldap_first_attribute( ld, res, amp;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: %sn", 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, amp;referrals, NULL, 0 );
            if ( parse_rc != LDAP_SUCCESS ) {
                fprintf( stderr, "ldap_parse_result: %sn", ldap_err2string( parse_rc ) );
                ldap_unbind( ld );
                return( 1 );
            }
            if ( referrals != NULL ) {
                for ( i = 0; referrals[ i ] != NULL; i   ) {
                    printf( "Search reference: %snn", 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, amp;rc, amp;matched_msg, amp;error_msg, NULL, amp;serverctrls, 0 );
            if ( parse_rc != LDAP_SUCCESS ) {
                fprintf( stderr, "ldap_parse_result: %sn", 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: %sn", ldap_err2string( rc ) );
                if ( error_msg != NULL amp; *error_msg != '' ) {
                    fprintf( stderr, "%sn", error_msg );
                }
                if ( matched_msg != NULL amp;amp; *matched_msg != '' ) {
                    fprintf( stderr, "Part of the DN that matches an existing entry: %sn", matched_msg );
                }
            } else {
                printf( "Search completed successfully.n"
                        "Entries found: %dn"
                        "Search references returned: %dn",
                        num_entries, num_refs );
            }
            break;
        default:
            break;
        }
    }
    /* Disconnect when done. */
    ldap_unbind( ld );
    return( 0 );
}
 

Комментарии:

1. ОС этот вопрос об использовании инструмента командной строки или о C ? Сделайте это одним или другим. В первом случае вы должны указать точную версию инструмента. В последнем случае покажите код на C и точную версию библиотек, которые вы используете.

2. Если ваш вопрос касается вашего кода на C , почему вы опубликовали только ту ldapsearch командную строку, которая работает?

3. @Tomalak Я пробовал использовать как c , так и инструмент cmd, но оба метода возвращают не все атрибуты. я использую ldap версии 3. И просто для того, чтобы уточнить, имеет ли это какое-либо отношение к типу операции привязки?

4. Это связано с тем, какие атрибуты вы запрашиваете. В ldapsearch случае, который вы запросили * , это означает все нерабочие атрибуты; в случае C вы указали NULL , что означает то же самое. Если вам также нужны операционные атрибуты, вы должны указать *, их в обоих случаях.

5. @user207421 привет, я пытался использовать этот запрос, но он не перечисляет все атрибуты. ldapsearch -x -h example.net -p 389 -D «CN = Администратор, CN = Пользователи, DC = пример, DC = сеть» -W «passw» -b «CN = Компьютеры, DC = пример, DC = сеть» «(objectclass=компьютер)» «*, «. Правильный ли этот запрос?

Ответ №1:

В вашем коде вы выполняете a simple_bind_s с NULL параметрами, что означает, что вы выполняете анонимную привязку, и поэтому у клиента нет разрешения на чтение всех атрибутов. Если вы должны были пройти аутентификацию с тем же пользователем, что и в ldapsearch, вы, вероятно, получите тот же результат.

Комментарии:

1. да, сожалею об этом. Я забыл обновить код. я использую учетную запись администратора для привязки. Имеет ли это какое-либо отношение к типу привязки?

2. Так не должно быть. Я считаю, что обе привязки эквивалентны.

3. Мне было интересно, требуется ли для этого какое-то безопасное соединение, такое как sasl_bind

4. sasl_bind не устанавливает безопасное соединение по умолчанию. И -x в ldapsearch использует простую привязку.

Ответ №2:

 ldapsearch -o ldif-wrap=no -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)" '*' ' '
 
  • -o ldif-wrap=no // Удалить разрыв строки по умолчанию из 79 символов
  • ' ' // для возврата ТОЛЬКО рабочих атрибутов в ldapsearch
  • '*' // для возврата ТОЛЬКО нерабочих (пользовательских) атрибутов в ldapsearch (поведение по умолчанию)
  • '*' ' ' // для возврата пользовательских операционных атрибутов !