summaryrefslogtreecommitdiffstats
path: root/ldap/c-sdk/libraries/libldap/test.c
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2019-11-03 00:17:46 -0400
committerMatt A. Tobin <email@mattatobin.com>2019-11-03 00:17:46 -0400
commit302bf1b523012e11b60425d6eee1221ebc2724eb (patch)
treeb191a895f8716efcbe42f454f37597a545a6f421 /ldap/c-sdk/libraries/libldap/test.c
parent21b3f6247403c06f85e1f45d219f87549862198f (diff)
downloadUXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.gz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.lz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.xz
UXP-302bf1b523012e11b60425d6eee1221ebc2724eb.zip
Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1
Diffstat (limited to 'ldap/c-sdk/libraries/libldap/test.c')
-rw-r--r--ldap/c-sdk/libraries/libldap/test.c1898
1 files changed, 1898 insertions, 0 deletions
diff --git a/ldap/c-sdk/libraries/libldap/test.c b/ldap/c-sdk/libraries/libldap/test.c
new file mode 100644
index 000000000..fa984f343
--- /dev/null
+++ b/ldap/c-sdk/libraries/libldap/test.c
@@ -0,0 +1,1898 @@
+/* ***** 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 <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef MACOS
+#ifdef THINK_C
+#include <console.h>
+#include <unix.h>
+#include <fcntl.h>
+#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 <windows.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+//#include "console.h"
+#else /* _WINDOWS */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#ifndef VMS
+#include <fcntl.h>
+#include <unistd.h>
+#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 <nss.h>
+#include <ldap_ssl.h>
+#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 );
+}