/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ /* test.c - a simple test harness. */ #include #include #include #include #ifdef MACOS #ifdef THINK_C #include #include #include #endif /* THINK_C */ #include "macos.h" #else /* MACOS */ #if defined( DOS ) #include "msdos.h" #if defined( WINSOCK ) #include "console.h" #endif /* WINSOCK */ #else /* DOS */ #ifdef _WINDOWS #include #include #include #include //#include "console.h" #else /* _WINDOWS */ #include #include #include #include #include #ifndef VMS #include #include #endif /* VMS */ #endif /* _WINDOWS */ #endif /* DOS */ #endif /* MACOS */ #include "ldap.h" #include "disptmpl.h" #include "ldaplog.h" #include "portable.h" #ifndef NO_LIBLCACHE #include "lcache.h" #endif /* !NO_LIBLCACHE */ #undef NET_SSL #if defined(NET_SSL) #include #include #endif #if !defined( PCNFS ) && !defined( WINSOCK ) && !defined( MACOS ) #define MOD_USE_BVALS #endif /* !PCNFS && !WINSOCK && !MACOS */ static void handle_result( LDAP *ld, LDAPMessage *lm, int onlyone ); static void print_ldap_result( LDAP *ld, LDAPMessage *lm, char *s ); static void print_controls( LDAPControl **ctrls, int freeit ); static void print_referrals( char **refs, int freeit ); static void print_search_entry( LDAP *ld, LDAPMessage *res, int onlyone ); static char *changetype_num2string( ber_int_t chgtype ); static void print_search_reference( LDAP *ld, LDAPMessage *res, int onlyone ); static void free_list( char **list ); static int entry2textwrite( void *fp, char *buf, int len ); static void bprint( char *data, int len ); static char **string2words( char *str, char *delims ); static const char * url_parse_err2string( int e ); char *dnsuffix; #ifndef WINSOCK static char * getline( char *line, int len, FILE *fp, char *prompt ) { printf(prompt); if ( fgets( line, len, fp ) == NULL ) return( NULL ); line[ strlen( line ) - 1 ] = '\0'; return( line ); } #endif /* WINSOCK */ static char ** get_list( char *prompt ) { static char buf[256]; int num; char **result; num = 0; result = (char **) 0; while ( 1 ) { getline( buf, sizeof(buf), stdin, prompt ); if ( *buf == '\0' ) break; if ( result == (char **) 0 ) result = (char **) malloc( sizeof(char *) ); else result = (char **) realloc( result, sizeof(char *) * (num + 1) ); result[num++] = (char *) strdup( buf ); } if ( result == (char **) 0 ) return( NULL ); result = (char **) realloc( result, sizeof(char *) * (num + 1) ); result[num] = NULL; return( result ); } static void free_list( char **list ) { int i; if ( list != NULL ) { for ( i = 0; list[ i ] != NULL; ++i ) { free( list[ i ] ); } free( (char *)list ); } } #ifdef MOD_USE_BVALS static int file_read( char *path, struct berval *bv ) { FILE *fp; long rlen; int eof; if (( fp = NSLDAPI_FOPEN( path, "r" )) == NULL ) { perror( path ); return( -1 ); } if ( fseek( fp, 0L, SEEK_END ) != 0 ) { perror( path ); fclose( fp ); return( -1 ); } bv->bv_len = ftell( fp ); if (( bv->bv_val = (char *)malloc( bv->bv_len )) == NULL ) { perror( "malloc" ); fclose( fp ); return( -1 ); } if ( fseek( fp, 0L, SEEK_SET ) != 0 ) { perror( path ); fclose( fp ); return( -1 ); } rlen = fread( bv->bv_val, 1, bv->bv_len, fp ); eof = feof( fp ); fclose( fp ); if ( (unsigned long)rlen != bv->bv_len ) { perror( path ); free( bv->bv_val ); return( -1 ); } return( bv->bv_len ); } #endif /* MOD_USE_BVALS */ static LDAPMod ** get_modlist( char *prompt1, char *prompt2, char *prompt3 ) { static char buf[256]; int num; LDAPMod tmp; LDAPMod **result; #ifdef MOD_USE_BVALS struct berval **bvals; #endif /* MOD_USE_BVALS */ num = 0; result = NULL; while ( 1 ) { if ( prompt1 ) { getline( buf, sizeof(buf), stdin, prompt1 ); tmp.mod_op = atoi( buf ); if ( tmp.mod_op == -1 || buf[0] == '\0' ) break; } else { tmp.mod_op = 0; } getline( buf, sizeof(buf), stdin, prompt2 ); if ( buf[0] == '\0' ) break; tmp.mod_type = strdup( buf ); tmp.mod_values = get_list( prompt3 ); #ifdef MOD_USE_BVALS if ( tmp.mod_values != NULL ) { int i; for ( i = 0; tmp.mod_values[i] != NULL; ++i ) ; bvals = (struct berval **)calloc( i + 1, sizeof( struct berval *)); for ( i = 0; tmp.mod_values[i] != NULL; ++i ) { bvals[i] = (struct berval *)malloc( sizeof( struct berval )); if ( strncmp( tmp.mod_values[i], "{FILE}", 6 ) == 0 ) { if ( file_read( tmp.mod_values[i] + 6, bvals[i] ) < 0 ) { return( NULL ); } } else { bvals[i]->bv_val = tmp.mod_values[i]; bvals[i]->bv_len = strlen( tmp.mod_values[i] ); } } tmp.mod_bvalues = bvals; tmp.mod_op |= LDAP_MOD_BVALUES; } #endif /* MOD_USE_BVALS */ if ( result == NULL ) result = (LDAPMod **) malloc( sizeof(LDAPMod *) ); else result = (LDAPMod **) realloc( result, sizeof(LDAPMod *) * (num + 1) ); result[num] = (LDAPMod *) malloc( sizeof(LDAPMod) ); *(result[num]) = tmp; /* struct copy */ num++; } if ( result == NULL ) return( NULL ); result = (LDAPMod **) realloc( result, sizeof(LDAPMod *) * (num + 1) ); result[num] = NULL; return( result ); } int LDAP_CALL LDAP_CALLBACK bind_prompt( LDAP *ld, char **dnp, char **passwdp, int *authmethodp, int freeit, void *dummy ) { static char dn[256], passwd[256]; if ( !freeit ) { #ifdef KERBEROS getline( dn, sizeof(dn), stdin, "re-bind method (0->simple, 1->krbv41, 2->krbv42, 3->krbv41&2)? " ); if (( *authmethodp = atoi( dn )) == 3 ) { *authmethodp = LDAP_AUTH_KRBV4; } else { *authmethodp |= 0x80; } #else /* KERBEROS */ *authmethodp = LDAP_AUTH_SIMPLE; #endif /* KERBEROS */ getline( dn, sizeof(dn), stdin, "re-bind dn? " ); strcat( dn, dnsuffix ); *dnp = dn; if ( *authmethodp == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) { getline( passwd, sizeof(passwd), stdin, "re-bind password? " ); } else { passwd[0] = '\0'; } *passwdp = passwd; } return( LDAP_SUCCESS ); } #define HEX2BIN( h ) ( (h) >= '0' && (h) <='9' ? (h) - '0' : (h) - 'A' + 10 ) void berval_from_hex( struct berval *bvp, char *hexstr ) { char *src, *dst, c; unsigned char abyte; dst = bvp->bv_val; bvp->bv_len = 0; src = hexstr; while ( *src != '\0' ) { c = *src; if ( isupper( c )) { c = tolower( c ); } abyte = HEX2BIN( c ) << 4; ++src; c = *src; if ( isupper( c )) { c = tolower( c ); } abyte |= HEX2BIN( c ); ++src; *dst++ = abyte; ++bvp->bv_len; } } static void add_control( LDAPControl ***ctrlsp, LDAPControl *newctrl ) { int i; if ( *ctrlsp == NULL ) { *ctrlsp = (LDAPControl **) calloc( 2, sizeof(LDAPControl *) ); i = 0; } else { for ( i = 0; (*ctrlsp)[i] != NULL; i++ ) { ; /* NULL */ } *ctrlsp = (LDAPControl **) realloc( *ctrlsp, (i + 2) * sizeof(LDAPControl *) ); } (*ctrlsp)[i] = newctrl; (*ctrlsp)[i+1] = NULL; } #ifdef TEST_CUSTOM_MALLOC typedef struct my_malloc_info { long mmi_magic; size_t mmi_actualsize; } MyMallocInfo; #define MY_MALLOC_MAGIC_NUMBER 0x19940618 #define MY_MALLOC_CHECK_MAGIC( p ) if ( ((MyMallocInfo *)( (p) - sizeof() void * my_malloc( size_t size ) { void *p; MyMallocInfo *mmip; if (( p = malloc( size + sizeof( struct my_malloc_info ))) != NULL ) { mmip = (MyMallocInfo *)p; mmip->mmi_magic = MY_MALLOC_MAGIC_NUMBER; mmip->mmi_actualsize = size; } fprintf( stderr, "my_malloc: allocated ptr 0x%x, size %ld\n", p, mmip->mmi_actualsize ); return( (char *)p + sizeof( MyMallocInfo )); } void * my_calloc( size_t nelem, size_t elsize ) { void *p; if (( p = my_malloc( nelem * elsize )) != NULL ) { memset( p, 0, nelem * elsize ); } return( p ); } void my_free( void *ptr ) { char *p; MyMallocInfo *mmip; p = (char *)ptr; p -= sizeof( MyMallocInfo ); mmip = (MyMallocInfo *)p; if ( mmip->mmi_magic != MY_MALLOC_MAGIC_NUMBER ) { fprintf( stderr, "my_malloc_check_magic: ptr 0x%x bad magic number\n", ptr ); exit( 1 ); } fprintf( stderr, "my_free: freeing ptr 0x%x, size %ld\n", p, mmip->mmi_actualsize ); memset( p, 0, mmip->mmi_actualsize + sizeof( MyMallocInfo )); free( p ); } void * my_realloc( void *ptr, size_t size ) { void *p; MyMallocInfo *mmip; if ( ptr == NULL ) { return( my_malloc( size )); } mmip = (MyMallocInfo *)( (char *)ptr - sizeof( MyMallocInfo )); if ( mmip->mmi_magic != MY_MALLOC_MAGIC_NUMBER ) { fprintf( stderr, "my_malloc_check_magic: ptr 0x%x bad magic number\n", ptr ); exit( 1 ); } if ( size <= mmip->mmi_actualsize ) { /* current block big enough? */ return( ptr ); } if (( p = my_malloc( size )) != NULL ) { memcpy( p, ptr, mmip->mmi_actualsize ); my_free( ptr ); } return( p ); } #endif /* TEST_CUSTOM_MALLOC */ int #ifdef WINSOCK ldapmain( #else /* WINSOCK */ main( #endif /* WINSOCK */ int argc, char **argv ) { LDAP *ld; int rc, i, c, port, cldapflg, errflg, method, id, msgtype; int version; char line[256], command1, command2, command3; char passwd[64], dn[256], rdn[64], attr[64], value[256]; char filter[256], *host, **types; char **exdn, *fnname; int bound, all, scope, attrsonly, optval, ldapversion; LDAPMessage *res; LDAPMod **mods, **attrs; struct timeval timeout, *tvp; char *copyfname = NULL; int copyoptions = 0; LDAPURLDesc *ludp; struct ldap_disptmpl *tmpllist = NULL; int changetypes, changesonly, return_echg_ctls; LDAPControl **tmpctrls, *newctrl, **controls = NULL; char *usage = "usage: %s [-u] [-h host] [-d level] [-s dnsuffix] [-p port] [-t file] [-T file] [-V protocolversion]\n"; extern char *optarg; extern int optind; #ifdef MACOS if (( argv = get_list( "cmd line arg?" )) == NULL ) { exit( 1 ); } for ( argc = 0; argv[ argc ] != NULL; ++argc ) { ; } #endif /* MACOS */ #ifdef TEST_CUSTOM_MALLOC { struct ldap_memalloc_fns memalloc_fns; memalloc_fns.ldapmem_malloc = my_malloc; memalloc_fns.ldapmem_calloc = my_calloc; memalloc_fns.ldapmem_realloc = my_realloc; memalloc_fns.ldapmem_free = my_free; if ( ldap_set_option( NULL, LDAP_OPT_MEMALLOC_FN_PTRS, &memalloc_fns ) != 0 ) { fputs( "ldap_set_option failed\n", stderr ); exit( 1 ); } } #endif /* TEST_CUSTOM_MALLOC */ host = NULL; port = LDAP_PORT; dnsuffix = ""; cldapflg = errflg = 0; ldapversion = 0; /* use default */ #ifndef _WIN32 #ifdef LDAP_DEBUG ldap_debug = LDAP_DEBUG_ANY; #endif #endif while (( c = getopt( argc, argv, "uh:d:s:p:t:T:V:" )) != -1 ) { switch( c ) { case 'u': #ifdef CLDAP cldapflg++; #else /* CLDAP */ printf( "Compile with -DCLDAP for UDP support\n" ); #endif /* CLDAP */ break; case 'd': #ifndef _WIN32 #ifdef LDAP_DEBUG ldap_debug = atoi( optarg ) | LDAP_DEBUG_ANY; if ( ldap_debug & LDAP_DEBUG_PACKETS ) { ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &ldap_debug ); } #else printf( "Compile with -DLDAP_DEBUG for debugging\n" ); #endif #endif break; case 'h': host = optarg; break; case 's': dnsuffix = optarg; break; case 'p': port = atoi( optarg ); break; #if !defined(MACOS) && !defined(DOS) case 't': /* copy ber's to given file */ copyfname = strdup( optarg ); copyoptions = LBER_SOCKBUF_OPT_TO_FILE; break; case 'T': /* only output ber's to given file */ copyfname = strdup( optarg ); copyoptions = (LBER_SOCKBUF_OPT_TO_FILE | LBER_SOCKBUF_OPT_TO_FILE_ONLY); break; #endif case 'V': /* LDAP protocol version */ ldapversion = atoi( optarg ); break; default: ++errflg; } } if ( host == NULL && optind == argc - 1 ) { host = argv[ optind ]; ++optind; } if ( errflg || optind < argc - 1 ) { fprintf( stderr, usage, argv[ 0 ] ); exit( 1 ); } printf( "%sldap_init( %s, %d )\n", cldapflg ? "c" : "", host == NULL ? "(null)" : host, port ); if ( cldapflg ) { #ifdef CLDAP ld = cldap_open( host, port ); #endif /* CLDAP */ } else { ld = ldap_init( host, port ); } if ( ld == NULL ) { perror( "ldap_init" ); exit(1); } if ( ldapversion != 0 && ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, (void *)&ldapversion ) != 0 ) { ldap_perror( ld, "ldap_set_option (protocol version)" ); exit(1); } #ifdef notdef #if !defined(MACOS) && !defined(DOS) if ( copyfname != NULL ) { int fd; Sockbuf *sb; if ( (fd = open( copyfname, O_WRONLY | O_CREAT, 0600 )) == -1 ) { perror( copyfname ); exit ( 1 ); } ldap_get_option( ld, LDAP_OPT_SOCKBUF, &sb ); ber_sockbuf_set_option( sb, LBER_SOCKBUF_OPT_COPYDESC, (void *) &fd ); ber_sockbuf_set_option( sb, copyoptions, LBER_OPT_ON ); } #endif #endif bound = 0; timeout.tv_sec = 0; timeout.tv_usec = 0; tvp = &timeout; (void) memset( line, '\0', sizeof(line) ); while ( getline( line, sizeof(line), stdin, "\ncommand? " ) != NULL ) { command1 = line[0]; command2 = line[1]; command3 = line[2]; switch ( command1 ) { case 'a': /* add or abandon */ switch ( command2 ) { case 'd': /* add */ getline( dn, sizeof(dn), stdin, "dn? " ); strcat( dn, dnsuffix ); if ( (attrs = get_modlist( NULL, "attr? ", "value? " )) == NULL ) break; if ( (id = ldap_add( ld, dn, attrs )) == -1 ) ldap_perror( ld, "ldap_add" ); else printf( "Add initiated with id %d\n", id ); break; case 'b': /* abandon */ getline( line, sizeof(line), stdin, "msgid? " ); id = atoi( line ); if ( ldap_abandon( ld, id ) != 0 ) ldap_perror( ld, "ldap_abandon" ); else printf( "Abandon successful\n" ); break; default: printf( "Possibilities: [ad]d, [ab]ort\n" ); } break; case 'v': /* ldap protocol version */ getline( line, sizeof(line), stdin, "ldap version? " ); version = atoi( line ); if ( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, (void *) &version ) != 0 ) { ldap_perror( ld, "ldap_set_option" ); } break; case 'b': /* asynch bind */ getline( line, sizeof(line), stdin, "method 0->simple 3->sasl? " ); method = atoi( line ); if ( method == 0 ) { method = LDAP_AUTH_SIMPLE; } else if ( method == 3 ) { method = LDAP_AUTH_SASL; } getline( dn, sizeof(dn), stdin, "dn? " ); strcat( dn, dnsuffix ); if ( method == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) { } else { passwd[0] = '\0'; } if ( method == LDAP_AUTH_SIMPLE ) { if ( dn[0] != '\0' ) { getline( passwd, sizeof(passwd), stdin, "password? " ); } else { passwd[0] = '\0'; } rc = ldap_simple_bind( ld, dn, passwd ); } else { struct berval cred; char mechanism[BUFSIZ]; getline( mechanism, sizeof(mechanism), stdin, "mechanism? " ); getline( passwd, sizeof(passwd), stdin, "credentials? " ); cred.bv_val = passwd; cred.bv_len = strlen( passwd ); if ( ldap_sasl_bind( ld, dn, mechanism, &cred, NULL, NULL, &rc ) != LDAP_SUCCESS ) { rc = -1; } } if ( rc == -1 ) { fprintf( stderr, "ldap_bind failed\n" ); ldap_perror( ld, "ldap_bind" ); } else { printf( "Bind initiated\n" ); bound = 1; } break; case 'B': /* synch bind */ getline( line, sizeof(line), stdin, "method 0->simple 3->sasl? " ); method = atoi( line ); if ( method == 0 ) { method = LDAP_AUTH_SIMPLE; } else if ( method == 3 ) { method = LDAP_AUTH_SASL; } getline( dn, sizeof(dn), stdin, "dn? " ); strcat( dn, dnsuffix ); if ( method == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) { } else { passwd[0] = '\0'; } if ( method == LDAP_AUTH_SIMPLE ) { if ( dn[0] != '\0' ) { getline( passwd, sizeof(passwd), stdin, "password? " ); } else { passwd[0] = '\0'; } rc = ldap_simple_bind_s( ld, dn, passwd ); fnname = "ldap_simple_bind_s"; } else { struct berval cred; char mechanism[BUFSIZ]; getline( mechanism, sizeof(mechanism), stdin, "mechanism? " ); getline( passwd, sizeof(passwd), stdin, "credentials? " ); cred.bv_val = passwd; cred.bv_len = strlen( passwd ); rc = ldap_sasl_bind_s( ld, dn, mechanism, &cred, NULL, NULL, NULL ); fnname = "ldap_sasl_bind_s"; } if ( rc != LDAP_SUCCESS ) { fprintf( stderr, "%s failed\n", fnname ); ldap_perror( ld, fnname ); } else { printf( "Bind successful\n" ); bound = 1; } break; case 'c': /* compare */ getline( dn, sizeof(dn), stdin, "dn? " ); strcat( dn, dnsuffix ); getline( attr, sizeof(attr), stdin, "attr? " ); getline( value, sizeof(value), stdin, "value? " ); if ( (id = ldap_compare( ld, dn, attr, value )) == -1 ) ldap_perror( ld, "ldap_compare" ); else printf( "Compare initiated with id %d\n", id ); break; case 'x': /* extended operation */ { char oid[100]; struct berval val; getline( oid, sizeof(oid), stdin, "oid? " ); getline( value, sizeof(value), stdin, "value? " ); if ( strncmp( value, "0x", 2 ) == 0 ) { val.bv_val = (char *)malloc( strlen( value ) / 2 ); berval_from_hex( &val, value + 2 ); } else { val.bv_val = strdup( value ); val.bv_len = strlen( value ); } if ( ldap_extended_operation( ld, oid, &val, NULL, NULL, &id ) != LDAP_SUCCESS ) { ldap_perror( ld, "ldap_extended_operation" ); } else { printf( "Extended op initiated with id %d\n", id ); } free( val.bv_val ); } break; case 'C': /* set cache parameters */ #ifdef NO_LIBLCACHE getline( line, sizeof(line), stdin, "cache init (memcache 0)? " ); #else getline( line, sizeof(line), stdin, "cache init (memcache 0, lcache 1)? " ); #endif i = atoi( line ); if ( i == 0 ) { /* memcache */ unsigned long ttl, size; char **basedns, *dnarray[2]; LDAPMemCache *mc; getline( line, sizeof(line), stdin, "memcache ttl? " ); ttl = atoi( line ); getline( line, sizeof(line), stdin, "memcache size? " ); size = atoi( line ); getline( line, sizeof(line), stdin, "memcache baseDN? " ); if ( *line == '\0' ) { basedns = NULL; } else { dnarray[0] = line; dnarray[1] = NULL; basedns = dnarray; } if (( rc = ldap_memcache_init( ttl, size, basedns, NULL, &mc )) != LDAP_SUCCESS ) { fprintf( stderr, "ldap_memcache_init: %s\n", ldap_err2string( rc )); } else if (( rc = ldap_memcache_set( ld, mc )) != LDAP_SUCCESS ) { fprintf( stderr, "ldap_memcache_set: %s\n", ldap_err2string( rc )); } #ifndef NO_LIBLCACHE } else if ( i == 1 ) { getline( line, sizeof(line), stdin, "cache config file? " ); if ( line[0] != '\0' ) { if ( lcache_init( ld, line ) != 0 ) { perror( "ldap_cache_init" ); break; } } getline( line, sizeof(line), stdin, "cache on/off (on 1, off 0)? " ); if ( line[0] != '\0' ) { i = atoi( line ); if ( ldap_set_option( ld, LDAP_OPT_CACHE_ENABLE, &i ) != 0 ) { ldap_perror( ld, "ldap_cache_enable" ); break; } } getline( line, sizeof(line), stdin, "cache strategy (check 0, populate 1, localdb 2)? " ); if ( line[0] != '\0' ) { i = atoi( line ); if ( ldap_set_option( ld, LDAP_OPT_CACHE_STRATEGY, &i ) != 0 ) { ldap_perror(ld, "ldap_cache_strategy"); break; } } #endif /* !NO_LIBLCACHE */ } else { fprintf( stderr, "unknown cachetype %d\n", i ); } break; case 'd': /* turn on debugging */ #ifndef _WIN32 #ifdef LDAP_DEBUG getline( line, sizeof(line), stdin, "debug level? " ); ldap_debug = atoi( line ) | LDAP_DEBUG_ANY; if ( ldap_debug & LDAP_DEBUG_PACKETS ) { ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &ldap_debug ); } #else printf( "Compile with -DLDAP_DEBUG for debugging\n" ); #endif #endif break; case 'E': /* explode a dn */ getline( line, sizeof(line), stdin, "dn? " ); exdn = ldap_explode_dn( line, 0 ); for ( i = 0; exdn != NULL && exdn[i] != NULL; i++ ) { printf( "\t\"%s\"\n", exdn[i] ); } break; case 'R': /* explode an rdn */ getline( line, sizeof(line), stdin, "rdn? " ); exdn = ldap_explode_rdn( line, 0 ); for ( i = 0; exdn != NULL && exdn[i] != NULL; i++ ) { printf( "\t\"%s\"\n", exdn[i] ); } break; case 'm': /* modify or modifyrdn */ if ( strncmp( line, "modify", 4 ) == 0 ) { getline( dn, sizeof(dn), stdin, "dn? " ); strcat( dn, dnsuffix ); if ( (mods = get_modlist( "mod (0=>add, 1=>delete, 2=>replace -1=>done)? ", "attribute type? ", "attribute value? " )) == NULL ) break; if ( (id = ldap_modify( ld, dn, mods )) == -1 ) ldap_perror( ld, "ldap_modify" ); else printf( "Modify initiated with id %d\n", id ); } else if ( strncmp( line, "modrdn", 4 ) == 0 ) { getline( dn, sizeof(dn), stdin, "dn? " ); strcat( dn, dnsuffix ); getline( rdn, sizeof(rdn), stdin, "newrdn? " ); getline( line, sizeof(line), stdin, "deleteoldrdn? " ); if ( (id = ldap_modrdn2( ld, dn, rdn, atoi(line) )) == -1 ) ldap_perror( ld, "ldap_modrdn" ); else printf( "Modrdn initiated with id %d\n", id ); } else { printf( "Possibilities: [modi]fy, [modr]dn\n" ); } break; case 'q': /* quit */ #ifdef CLDAP if ( cldapflg ) cldap_close( ld ); #endif /* CLDAP */ if ( !cldapflg ) ldap_unbind( ld ); exit( 0 ); break; case 'r': /* result or remove */ switch ( command3 ) { case 's': /* result */ getline( line, sizeof(line), stdin, "msgid (-1=>any)? " ); if ( line[0] == '\0' ) id = -1; else id = atoi( line ); getline( line, sizeof(line), stdin, "all (0=>any, 1=>all)? " ); if ( line[0] == '\0' ) all = 1; else all = atoi( line ); if (( msgtype = ldap_result( ld, id, all, tvp, &res )) < 1 ) { ldap_perror( ld, "ldap_result" ); break; } printf( "\nresult: msgtype %d msgid %d\n", msgtype, ldap_msgid( res ) ); handle_result( ld, res, 0 ); res = NULL; break; case 'm': /* remove */ getline( dn, sizeof(dn), stdin, "dn? " ); strcat( dn, dnsuffix ); if ( (id = ldap_delete( ld, dn )) == -1 ) ldap_perror( ld, "ldap_delete" ); else printf( "Remove initiated with id %d\n", id ); break; default: printf( "Possibilities: [rem]ove, [res]ult\n" ); break; } break; case 's': /* search */ getline( dn, sizeof(dn), stdin, "searchbase? " ); strcat( dn, dnsuffix ); getline( line, sizeof(line), stdin, "scope (0=Base, 1=One Level, 2=Subtree)? " ); scope = atoi( line ); getline( filter, sizeof(filter), stdin, "search filter (e.g. sn=jones)? " ); types = get_list( "attrs to return? " ); getline( line, sizeof(line), stdin, "attrsonly (0=attrs&values, 1=attrs only)? " ); attrsonly = atoi( line ); if ( cldapflg ) { #ifdef CLDAP getline( line, sizeof(line), stdin, "Requestor DN (for logging)? " ); if ( cldap_search_s( ld, dn, scope, filter, types, attrsonly, &res, line ) != 0 ) { ldap_perror( ld, "cldap_search_s" ); } else { printf( "\nresult: msgid %d\n", res->lm_msgid ); handle_result( ld, res, 0 ); res = NULL; } #endif /* CLDAP */ } else { if (( id = ldap_search( ld, dn, scope, filter, types, attrsonly )) == -1 ) { ldap_perror( ld, "ldap_search" ); } else { printf( "Search initiated with id %d\n", id ); } } free_list( types ); break; case 't': /* set timeout value */ getline( line, sizeof(line), stdin, "timeout (-1=infinite)? " ); timeout.tv_sec = atoi( line ); if ( timeout.tv_sec < 0 ) { tvp = NULL; } else { tvp = &timeout; } break; case 'U': /* set ufn search prefix */ getline( line, sizeof(line), stdin, "ufn prefix? " ); ldap_ufn_setprefix( ld, line ); break; case 'u': /* user friendly search w/optional timeout */ getline( dn, sizeof(dn), stdin, "ufn? " ); strcat( dn, dnsuffix ); types = get_list( "attrs to return? " ); getline( line, sizeof(line), stdin, "attrsonly (0=attrs&values, 1=attrs only)? " ); attrsonly = atoi( line ); if ( command2 == 't' ) { id = ldap_ufn_search_c( ld, dn, types, attrsonly, &res, ldap_ufn_timeout, &timeout ); } else { id = ldap_ufn_search_s( ld, dn, types, attrsonly, &res ); } if ( res == NULL ) ldap_perror( ld, "ldap_ufn_search" ); else { printf( "\nresult: err %d\n", id ); handle_result( ld, res, 0 ); res = NULL; } free_list( types ); break; case 'l': /* URL search */ getline( line, sizeof(line), stdin, "attrsonly (0=attrs&values, 1=attrs only)? " ); attrsonly = atoi( line ); getline( line, sizeof(line), stdin, "LDAP URL? " ); if (( id = ldap_url_search( ld, line, attrsonly )) == -1 ) { ldap_perror( ld, "ldap_url_search" ); } else { printf( "URL search initiated with id %d\n", id ); } break; case 'p': /* parse LDAP URL */ getline( line, sizeof(line), stdin, "LDAP URL? " ); if (( i = ldap_url_parse( line, &ludp )) != 0 ) { fprintf( stderr, "ldap_url_parse: error %d (%s)\n", i, url_parse_err2string( i )); } else { printf( "\t host: " ); if ( ludp->lud_host == NULL ) { printf( "DEFAULT\n" ); } else { printf( "<%s>\n", ludp->lud_host ); } printf( "\t port: " ); if ( ludp->lud_port == 0 ) { printf( "DEFAULT\n" ); } else { printf( "%d\n", ludp->lud_port ); } printf( "\tsecure: %s\n", ( ludp->lud_options & LDAP_URL_OPT_SECURE ) != 0 ? "Yes" : "No" ); printf( "\t dn: " ); if ( ludp->lud_dn == NULL ) { printf( "ROOT\n" ); } else { printf( "%s\n", ludp->lud_dn ); } printf( "\t attrs:" ); if ( ludp->lud_attrs == NULL ) { printf( " ALL" ); } else { for ( i = 0; ludp->lud_attrs[ i ] != NULL; ++i ) { printf( " <%s>", ludp->lud_attrs[ i ] ); } } printf( "\n\t scope: %s\n", ludp->lud_scope == LDAP_SCOPE_ONELEVEL ? "ONE" : ludp->lud_scope == LDAP_SCOPE_BASE ? "BASE" : ludp->lud_scope == LDAP_SCOPE_SUBTREE ? "SUB" : "**invalid**" ); printf( "\tfilter: <%s>\n", ludp->lud_filter ); ldap_free_urldesc( ludp ); } break; case 'n': /* set dn suffix, for convenience */ getline( line, sizeof(line), stdin, "DN suffix? " ); strcpy( dnsuffix, line ); break; case 'N': /* add an LDAPv3 control */ getline( line, sizeof(line), stdin, "Control oid (. to clear list)? " ); if ( *line == '.' && *(line+1) == '\0' ) { controls = NULL; } else { newctrl = (LDAPControl *) malloc( sizeof(LDAPControl) ); newctrl->ldctl_oid = strdup( line ); getline( line, sizeof(line), stdin, "Control value? " ); if ( strncmp( line, "0x", 2 ) == 0 ) { newctrl->ldctl_value.bv_val = (char *)malloc( strlen( line ) / 2 ); berval_from_hex( &(newctrl->ldctl_value), line + 2 ); } else { newctrl->ldctl_value.bv_val = strdup( line ); } newctrl->ldctl_value.bv_len = strlen( line ); getline( line, sizeof(line), stdin, "Critical (0=no, 1=yes)? " ); newctrl->ldctl_iscritical = atoi( line ); add_control( &controls, newctrl ); } ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, controls ); ldap_get_option( ld, LDAP_OPT_SERVER_CONTROLS, &tmpctrls ); print_controls( tmpctrls, 0 ); break; case 'P': /* add a persistent search control */ getline( line, sizeof(line), stdin, "Changetypes to " " return (additive - add (1), delete (2), " "modify (4), modDN (8))? " ); changetypes = atoi(line); getline( line, sizeof(line), stdin, "Return changes only (0=no, 1=yes)? " ); changesonly = atoi(line); getline( line, sizeof(line), stdin, "Return entry " "change controls (0=no, 1=yes)? " ); return_echg_ctls = atoi(line); getline( line, sizeof(line), stdin, "Critical (0=no, 1=yes)? " ); if ( ldap_create_persistentsearch_control( ld, changetypes, changesonly, return_echg_ctls, (char)atoi(line), &newctrl ) != LDAP_SUCCESS ) { ldap_perror( ld, "ldap_create_persistent" "search_control" ); } else { add_control( &controls, newctrl ); ldap_set_option( ld, LDAP_OPT_SERVER_CONTROLS, controls ); ldap_get_option( ld, LDAP_OPT_SERVER_CONTROLS, &tmpctrls ); print_controls( tmpctrls, 0 ); } break; case 'o': /* set ldap options */ getline( line, sizeof(line), stdin, "alias deref (0=never, 1=searching, 2=finding, 3=always)?" ); i = atoi( line ); ldap_set_option( ld, LDAP_OPT_DEREF, &i ); getline( line, sizeof(line), stdin, "timelimit?" ); i = atoi( line ); ldap_set_option( ld, LDAP_OPT_TIMELIMIT, &i ); getline( line, sizeof(line), stdin, "sizelimit?" ); i = atoi( line ); ldap_set_option( ld, LDAP_OPT_SIZELIMIT, &i ); #ifdef STR_TRANSLATION getline( line, sizeof(line), stdin, "Automatic translation of T.61 strings (0=no, 1=yes)?" ); if ( atoi( line ) == 0 ) { ld->ld_lberoptions &= ~LBER_OPT_TRANSLATE_STRINGS; } else { ld->ld_lberoptions |= LBER_OPT_TRANSLATE_STRINGS; #ifdef LDAP_CHARSET_8859 getline( line, sizeof(line), stdin, "Translate to/from ISO-8859 (0=no, 1=yes?" ); if ( atoi( line ) != 0 ) { ldap_set_string_translators( ld, ldap_8859_to_t61, ldap_t61_to_8859 ); } #endif /* LDAP_CHARSET_8859 */ } #endif /* STR_TRANSLATION */ #ifdef LDAP_DNS getline( line, sizeof(line), stdin, "Use DN & DNS to determine where to send requests (0=no, 1=yes)?" ); optval = ( atoi( line ) != 0 ); ldap_set_option( ld, LDAP_OPT_DNS, (void *) optval ); #endif /* LDAP_DNS */ getline( line, sizeof(line), stdin, "Recognize and chase referrals (0=no, 1=yes)?" ); optval = ( atoi( line ) != 0 ); ldap_set_option( ld, LDAP_OPT_REFERRALS, (void *) optval ); if ( optval ) { getline( line, sizeof(line), stdin, "Prompt for bind credentials when chasing referrals (0=no, 1=yes)?" ); if ( atoi( line ) != 0 ) { ldap_set_rebind_proc( ld, bind_prompt, NULL ); } } #ifdef NET_SSL getline( line, sizeof(line), stdin, "Use Secure Sockets Layer - SSL (0=no, 1=yes)?" ); optval = ( atoi( line ) != 0 ); if ( optval ) { getline( line, sizeof(line), stdin, "security DB path?" ); if ( ldapssl_client_init( (*line == '\0') ? NULL : line, NULL ) < 0 ) { perror( "ldapssl_client_init" ); optval = 0; /* SSL not avail. */ } else if ( ldapssl_install_routines( ld ) < 0 ) { ldap_perror( ld, "ldapssl_install_routines" ); optval = 0; /* SSL not avail. */ } } ldap_set_option( ld, LDAP_OPT_SSL, optval ? LDAP_OPT_ON : LDAP_OPT_OFF ); getline( line, sizeof(line), stdin, "Set SSL options (0=no, 1=yes)?" ); optval = ( atoi( line ) != 0 ); while ( 1 ) { PRInt32 sslopt; PRBool on; getline( line, sizeof(line), stdin, "Option to set (0 if done)?" ); sslopt = atoi(line); if ( sslopt == 0 ) { break; } getline( line, sizeof(line), stdin, "On=1, Off=0?" ); on = ( atoi( line ) != 0 ); if ( ldapssl_set_option( ld, sslopt, on ) != 0 ) { ldap_perror( ld, "ldapssl_set_option" ); } } #endif getline( line, sizeof(line), stdin, "Reconnect?" ); ldap_set_option( ld, LDAP_OPT_RECONNECT, ( atoi( line ) == 0 ) ? LDAP_OPT_OFF : LDAP_OPT_ON ); getline( line, sizeof(line), stdin, "Async I/O?" ); ldap_set_option( ld, LDAP_OPT_ASYNC_CONNECT, ( atoi( line ) == 0 ) ? LDAP_OPT_OFF : LDAP_OPT_ON ); break; case 'I': /* initialize display templates */ getline( line, sizeof(line), stdin, "Template file [ldaptemplates.conf]?" ); if (( i = ldap_init_templates( *line == '\0' ? "ldaptemplates.conf" : line, &tmpllist )) != 0 ) { fprintf( stderr, "ldap_init_templates: %s\n", ldap_tmplerr2string( i )); } break; case 'T': /* read & display using template */ getline( dn, sizeof(dn), stdin, "entry DN? " ); strcat( dn, dnsuffix ); if (( i = ldap_entry2text_search( ld, dn, NULL, NULL, tmpllist, NULL, NULL, entry2textwrite, stdout, "\n", 0, 0 )) != LDAP_SUCCESS ) { fprintf( stderr, "ldap_entry2text_search: %s\n", ldap_err2string( i )); } break; case 'L': /* set preferred language */ getline( line, sizeof(line), stdin, "Preferred language? " ); if ( *line == '\0' ) { ldap_set_option( ld, LDAP_OPT_PREFERRED_LANGUAGE, NULL ); } else { ldap_set_option( ld, LDAP_OPT_PREFERRED_LANGUAGE, line ); } break; case 'F': /* create filter */ { char filtbuf[ 512 ], pattern[ 512 ]; char prefix[ 512 ], suffix[ 512 ]; char attr[ 512 ], value[ 512 ]; char *dupvalue, **words; getline( pattern, sizeof(pattern), stdin, "pattern? " ); getline( prefix, sizeof(prefix), stdin, "prefix? " ); getline( suffix, sizeof(suffix), stdin, "suffix? " ); getline( attr, sizeof(attr), stdin, "attribute? " ); getline( value, sizeof(value), stdin, "value? " ); if (( dupvalue = strdup( value )) != NULL ) { words = string2words( value, " " ); } else { words = NULL; } if ( ldap_create_filter( filtbuf, sizeof(filtbuf), pattern, prefix, suffix, attr, value, words) != 0 ) { fprintf( stderr, "ldap_create_filter failed\n" ); } else { printf( "filter is \"%s\"\n", filtbuf ); } if ( dupvalue != NULL ) free( dupvalue ); if ( words != NULL ) free( words ); } break; case '?': /* help */ case '\0': /* help */ printf( "Commands: [ad]d [ab]andon [b]ind\n" ); printf( " synch [B]ind [c]ompare [l]URL search\n" ); printf( " [modi]fy [modr]dn [rem]ove\n" ); printf( " [res]ult [s]earch [q]uit/unbind\n\n" ); printf( " [u]fn search [ut]fn search with timeout\n" ); printf( " [d]ebug [C]set cache parms[g]set msgid\n" ); printf( " d[n]suffix [t]imeout [v]ersion\n" ); printf( " [U]fn prefix [?]help [o]ptions\n" ); printf( " [E]xplode dn [p]arse LDAP URL [R]explode RDN\n" ); printf( " e[x]tended op [F]ilter create\n" ); printf( " set co[N]trols set preferred [L]anguage\n" ); printf( " add a [P]ersistent search control\n" ); printf( " [I]nitialize display templates\n" ); printf( " [T]read entry and display using template\n" ); break; default: printf( "Invalid command. Type ? for help.\n" ); break; } (void) memset( line, '\0', sizeof(line) ); } return( 0 ); } static void handle_result( LDAP *ld, LDAPMessage *lm, int onlyone ) { int msgtype; switch ( (msgtype = ldap_msgtype( lm )) ) { case LDAP_RES_COMPARE: printf( "Compare result\n" ); print_ldap_result( ld, lm, "compare" ); break; case LDAP_RES_SEARCH_RESULT: printf( "Search result\n" ); print_ldap_result( ld, lm, "search" ); break; case LDAP_RES_SEARCH_ENTRY: printf( "Search entry\n" ); print_search_entry( ld, lm, onlyone ); break; case LDAP_RES_SEARCH_REFERENCE: printf( "Search reference\n" ); print_search_reference( ld, lm, onlyone ); break; case LDAP_RES_ADD: printf( "Add result\n" ); print_ldap_result( ld, lm, "add" ); break; case LDAP_RES_DELETE: printf( "Delete result\n" ); print_ldap_result( ld, lm, "delete" ); break; case LDAP_RES_MODIFY: printf( "Modify result\n" ); print_ldap_result( ld, lm, "modify" ); break; case LDAP_RES_MODRDN: printf( "ModRDN result\n" ); print_ldap_result( ld, lm, "modrdn" ); break; case LDAP_RES_BIND: printf( "Bind result\n" ); print_ldap_result( ld, lm, "bind" ); break; case LDAP_RES_EXTENDED: if ( ldap_msgid( lm ) == LDAP_RES_UNSOLICITED ) { printf( "Unsolicited result\n" ); print_ldap_result( ld, lm, "unsolicited" ); } else { printf( "ExtendedOp result\n" ); print_ldap_result( ld, lm, "extendedop" ); } break; default: printf( "Unknown result type 0x%x\n", msgtype ); print_ldap_result( ld, lm, "unknown" ); } if ( !onlyone ) { ldap_msgfree( lm ); } } static void print_ldap_result( LDAP *ld, LDAPMessage *lm, char *s ) { int lderr; char *matcheddn, *errmsg, *oid, **refs; LDAPControl **ctrls; struct berval *servercred, *data; if ( ldap_parse_result( ld, lm, &lderr, &matcheddn, &errmsg, &refs, &ctrls, 0 ) != LDAP_SUCCESS ) { ldap_perror( ld, "ldap_parse_result" ); } else { fprintf( stderr, "%s: %s", s, ldap_err2string( lderr )); if ( lderr == LDAP_CONNECT_ERROR ) { perror( " - " ); } else { fputc( '\n', stderr ); } if ( errmsg != NULL ) { if ( *errmsg != '\0' ) { fprintf( stderr, "Additional info: %s\n", errmsg ); } ldap_memfree( errmsg ); } if ( matcheddn != NULL ) { if ( NAME_ERROR( lderr )) { fprintf( stderr, "Matched DN: %s\n", matcheddn ); } ldap_memfree( matcheddn ); } print_referrals( refs, 1 ); print_controls( ctrls, 1 ); } /* if SASL bind response, get and show server credentials */ if ( ldap_msgtype( lm ) == LDAP_RES_BIND && ldap_parse_sasl_bind_result( ld, lm, &servercred, 0 ) == LDAP_SUCCESS && servercred != NULL ) { fputs( "\tSASL server credentials:\n", stderr ); bprint( servercred->bv_val, servercred->bv_len ); ber_bvfree( servercred ); } /* if ExtendedOp response, get and show oid plus data */ if ( ldap_msgtype( lm ) == LDAP_RES_EXTENDED && ldap_parse_extended_result( ld, lm, &oid, &data, 0 ) == LDAP_SUCCESS ) { if ( oid != NULL ) { if ( strcmp ( oid, LDAP_NOTICE_OF_DISCONNECTION ) == 0 ) { printf( "\t%s Notice of Disconnection (OID: %s)\n", s, oid ); } else { printf( "\t%s OID: %s\n", s, oid ); } ldap_memfree( oid ); } if ( data != NULL ) { printf( "\t%s data:\n", s ); bprint( data->bv_val, data->bv_len ); ber_bvfree( data ); } } } static void print_search_entry( LDAP *ld, LDAPMessage *res, int onlyone ) { BerElement *ber; char *a, *dn, *ufn; struct berval **vals; int i, count; LDAPMessage *e, *msg; LDAPControl **ectrls; count = 0; for ( msg = ldap_first_message( ld, res ); msg != NULL && ( !onlyone || count == 0 ); msg = ldap_next_message( ld, msg ), ++count ) { if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_ENTRY ) { handle_result( ld, msg, 1 ); /* something else */ continue; } e = msg; dn = ldap_get_dn( ld, e ); printf( "\tDN: %s\n", dn ); ufn = ldap_dn2ufn( dn ); printf( "\tUFN: %s\n", ufn ); #ifdef WINSOCK ldap_memfree( dn ); ldap_memfree( ufn ); #else /* WINSOCK */ free( dn ); free( ufn ); #endif /* WINSOCK */ for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL; a = ldap_next_attribute( ld, e, ber ) ) { printf( "\t\tATTR: %s\n", a ); if ( (vals = ldap_get_values_len( ld, e, a )) == NULL ) { printf( "\t\t\t(no values)\n" ); } else { for ( i = 0; vals[i] != NULL; i++ ) { int nonascii = 0; unsigned long j; for ( j = 0; j < vals[i]->bv_len; j++ ) if ( !isascii( vals[i]->bv_val[j] ) ) { nonascii = 1; break; } if ( nonascii ) { printf( "\t\t\tlength (%ld) (not ascii)\n", vals[i]->bv_len ); #ifdef BPRINT_NONASCII bprint( vals[i]->bv_val, vals[i]->bv_len ); #endif /* BPRINT_NONASCII */ continue; } printf( "\t\t\tlength (%ld) %s\n", vals[i]->bv_len, vals[i]->bv_val ); } ber_bvecfree( vals ); } ldap_memfree( a ); } if ( ldap_get_lderrno( ld, NULL, NULL ) != LDAP_SUCCESS ) { ldap_perror( ld, "ldap_first_attribute/ldap_next_attribute" ); } if ( ber != NULL ) { ber_free( ber, 0 ); } if ( ldap_get_entry_controls( ld, e, &ectrls ) != LDAP_SUCCESS ) { ldap_perror( ld, "ldap_get_entry_controls" ); } else { int changenumpresent; ber_int_t changetype; char *prevdn; ber_int_t changenum; if ( ldap_parse_entrychange_control( ld, ectrls, &changetype, &prevdn, &changenumpresent, &changenum ) == LDAP_SUCCESS ) { fprintf( stderr, "EntryChangeNotification\n" "\tchangeType: %s\n", changetype_num2string( changetype )); if ( prevdn != NULL ) { fprintf( stderr, "\tpreviousDN: \"%s\"\n", prevdn ); } if ( changenumpresent ) { fprintf( stderr, "\tchangeNumber: %d\n", changenum ); } if ( prevdn != NULL ) { free( prevdn ); } } print_controls( ectrls, 1 ); } } } static char * changetype_num2string( ber_int_t chgtype ) { static char buf[ 25 ]; char *s; switch( chgtype ) { case LDAP_CHANGETYPE_ADD: s = "add"; break; case LDAP_CHANGETYPE_DELETE: s = "delete"; break; case LDAP_CHANGETYPE_MODIFY: s = "modify"; break; case LDAP_CHANGETYPE_MODDN: s = "moddn"; break; default: s = buf; sprintf( s, "unknown (%d)", chgtype ); } return( s ); } static void print_search_reference( LDAP *ld, LDAPMessage *res, int onlyone ) { LDAPMessage *msg; LDAPControl **ctrls; char **refs; int count; count = 0; for ( msg = ldap_first_message( ld, res ); msg != NULL && ( !onlyone || count == 0 ); msg = ldap_next_message( ld, msg ), ++count ) { if ( ldap_msgtype( msg ) != LDAP_RES_SEARCH_REFERENCE ) { handle_result( ld, msg, 1 ); /* something else */ continue; } if ( ldap_parse_reference( ld, msg, &refs, &ctrls, 0 ) != LDAP_SUCCESS ) { ldap_perror( ld, "ldap_parse_reference" ); } else { print_referrals( refs, 1 ); print_controls( ctrls, 1 ); } } } static void print_referrals( char **refs, int freeit ) { int i; if ( refs == NULL ) { return; } fprintf( stderr, "Referrals:\n" ); for ( i = 0; refs[ i ] != NULL; ++i ) { fprintf( stderr, "\t%s\n", refs[ i ] ); } if ( freeit ) { ldap_value_free( refs ); } } static void print_controls( LDAPControl **ctrls, int freeit ) { int i; if ( ctrls == NULL ) { return; } fprintf( stderr, "Controls:\n" ); for ( i = 0; ctrls[ i ] != NULL; ++i ) { if ( i > 0 ) { fputs( "\t-----------\n", stderr ); } fprintf( stderr, "\toid: %s\n", ctrls[ i ]->ldctl_oid ); fprintf( stderr, "\tcritical: %s\n", ctrls[ i ]->ldctl_iscritical ? "YES" : "NO" ); fputs( "\tvalue:\n", stderr ); bprint( ctrls[ i ]->ldctl_value.bv_val, ctrls[ i ]->ldctl_value.bv_len ); } if ( freeit ) { ldap_controls_free( ctrls ); } } static int entry2textwrite( void *fp, char *buf, int len ) { return( fwrite( buf, len, 1, (FILE *)fp ) == 0 ? -1 : len ); } /* similar to getfilter.c:break_into_words() */ static char ** string2words( char *str, char *delims ) { char *word, **words; int count; char *lasts; if (( words = (char **)calloc( 1, sizeof( char * ))) == NULL ) { return( NULL ); } count = 0; words[ count ] = NULL; word = ldap_utf8strtok_r( str, delims, &lasts ); while ( word != NULL ) { if (( words = (char **)realloc( words, ( count + 2 ) * sizeof( char * ))) == NULL ) { free( words ); return( NULL ); } words[ count ] = word; words[ ++count ] = NULL; word = ldap_utf8strtok_r( NULL, delims, &lasts ); } return( words ); } static const char * url_parse_err2string( int e ) { const char *s = "unknown"; switch( e ) { case LDAP_URL_ERR_NOTLDAP: s = "URL doesn't begin with \"ldap://\""; break; case LDAP_URL_ERR_NODN: s = "URL has no DN (required)"; break; case LDAP_URL_ERR_BADSCOPE: s = "URL scope string is invalid"; break; case LDAP_URL_ERR_MEM: s = "can't allocate memory space"; break; case LDAP_URL_ERR_PARAM: s = "bad parameter to an URL function"; break; case LDAP_URL_UNRECOGNIZED_CRITICAL_EXTENSION: s = "unrecognized critical URL extension"; break; } return( s ); } /* * Print arbitrary stuff, for debugging. */ #define BPLEN 48 static void bprint( char *data, int len ) { static char hexdig[] = "0123456789abcdef"; char out[ BPLEN ]; int i = 0; memset( out, 0, BPLEN ); for ( ;; ) { if ( len < 1 ) { fprintf( stderr, "\t%s\n", ( i == 0 ) ? "(end)" : out ); break; } #ifndef HEX if ( isgraph( (unsigned char)*data )) { out[ i ] = ' '; out[ i+1 ] = *data; } else { #endif out[ i ] = hexdig[ ( *data & 0xf0 ) >> 4 ]; out[ i+1 ] = hexdig[ *data & 0x0f ]; #ifndef HEX } #endif i += 2; len--; data++; if ( i > BPLEN - 2 ) { fprintf( stderr, "\t%s\n", out ); memset( out, 0, BPLEN ); i = 0; continue; } out[ i++ ] = ' '; } fflush( stderr ); }