11590Srgrimes/*	$NetBSD$	*/
21590Srgrimes
31590Srgrimes/* OpenLDAP: pkg/ldap/libraries/libldap/test.c,v 1.55.2.5 2010/04/13 20:23:00 kurt Exp */
41590Srgrimes/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
51590Srgrimes *
61590Srgrimes * Copyright 1998-2010 The OpenLDAP Foundation.
71590Srgrimes * All rights reserved.
81590Srgrimes *
91590Srgrimes * Redistribution and use in source and binary forms, with or without
101590Srgrimes * modification, are permitted only as authorized by the OpenLDAP
111590Srgrimes * Public License.
121590Srgrimes *
131590Srgrimes * A copy of this license is available in the file LICENSE in the
141590Srgrimes * top-level directory of the distribution or, alternatively, at
151590Srgrimes * <http://www.OpenLDAP.org/license.html>.
161590Srgrimes */
171590Srgrimes
181590Srgrimes#include "portable.h"
191590Srgrimes
201590Srgrimes#include <stdio.h>
211590Srgrimes
221590Srgrimes#include <ac/stdlib.h>
231590Srgrimes
241590Srgrimes#include <ac/ctype.h>
251590Srgrimes#include <ac/socket.h>
261590Srgrimes#include <ac/string.h>
271590Srgrimes#include <ac/time.h>
281590Srgrimes#include <ac/unistd.h>
291590Srgrimes
301590Srgrimes#include <sys/stat.h>
311590Srgrimes
321590Srgrimes#ifdef HAVE_SYS_FILE_H
331590Srgrimes#include <sys/file.h>
341590Srgrimes#endif
3528202Scharnier#ifdef HAVE_IO_H
361590Srgrimes#include <io.h>
371590Srgrimes#endif
381590Srgrimes
391590Srgrimes#include <fcntl.h>
401590Srgrimes
4128202Scharnier/* including the "internal" defs is legit and nec. since this test routine has
421590Srgrimes * a-priori knowledge of libldap internal workings.
4328202Scharnier * hodges@stanford.edu 5-Feb-96
4428202Scharnier */
4540765Sdg#include "ldap-int.h"
461590Srgrimes
471590Srgrimes/* local functions */
481590Srgrimesstatic char *get_line LDAP_P(( char *line, int len, FILE *fp, const char *prompt ));
491590Srgrimesstatic char **get_list LDAP_P(( const char *prompt ));
501590Srgrimesstatic int file_read LDAP_P(( const char *path, struct berval *bv ));
511590Srgrimesstatic LDAPMod **get_modlist LDAP_P(( const char *prompt1,
521590Srgrimes	const char *prompt2, const char *prompt3 ));
5328202Scharnierstatic void handle_result LDAP_P(( LDAP *ld, LDAPMessage *lm ));
541590Srgrimesstatic void print_ldap_result LDAP_P(( LDAP *ld, LDAPMessage *lm,
551590Srgrimes	const char *s ));
561590Srgrimesstatic void print_search_entry LDAP_P(( LDAP *ld, LDAPMessage *res ));
5736792Simpstatic void free_list LDAP_P(( char **list ));
581590Srgrimes
591590Srgrimesstatic char *dnsuffix;
601590Srgrimes
611590Srgrimesstatic char *
621590Srgrimesget_line( char *line, int len, FILE *fp, const char *prompt )
631590Srgrimes{
6428202Scharnier	fputs(prompt, stdout);
651590Srgrimes
661590Srgrimes	if ( fgets( line, len, fp ) == NULL )
671590Srgrimes		return( NULL );
681590Srgrimes
691590Srgrimes	line[ strlen( line ) - 1 ] = '\0';
701590Srgrimes
711590Srgrimes	return( line );
721590Srgrimes}
731590Srgrimes
741590Srgrimesstatic char **
751590Srgrimesget_list( const char *prompt )
761590Srgrimes{
771590Srgrimes	static char	buf[256];
781590Srgrimes	int		num;
791590Srgrimes	char		**result;
801590Srgrimes
811590Srgrimes	num = 0;
821590Srgrimes	result = (char **) 0;
831590Srgrimes	while ( 1 ) {
841590Srgrimes		get_line( buf, sizeof(buf), stdin, prompt );
851590Srgrimes
861590Srgrimes		if ( *buf == '\0' )
871590Srgrimes			break;
881590Srgrimes
891590Srgrimes		if ( result == (char **) 0 )
901590Srgrimes			result = (char **) malloc( sizeof(char *) );
911590Srgrimes		else
921590Srgrimes			result = (char **) realloc( result,
931590Srgrimes			    sizeof(char *) * (num + 1) );
941590Srgrimes
951590Srgrimes		result[num++] = (char *) strdup( buf );
961590Srgrimes	}
971590Srgrimes	if ( result == (char **) 0 )
981590Srgrimes		return( NULL );
991590Srgrimes	result = (char **) realloc( result, sizeof(char *) * (num + 1) );
1001590Srgrimes	result[num] = NULL;
1011590Srgrimes
1021590Srgrimes	return( result );
1031590Srgrimes}
1041590Srgrimes
1051590Srgrimes
10618286Sbdestatic void
1071590Srgrimesfree_list( char **list )
1081590Srgrimes{
1091590Srgrimes	int	i;
1101590Srgrimes
1111590Srgrimes	if ( list != NULL ) {
1121590Srgrimes		for ( i = 0; list[ i ] != NULL; ++i ) {
1131590Srgrimes			free( list[ i ] );
1141590Srgrimes		}
1151590Srgrimes		free( (char *)list );
1161590Srgrimes	}
1171590Srgrimes}
1181590Srgrimes
1191590Srgrimes
1201590Srgrimesstatic int
1211590Srgrimesfile_read( const char *path, struct berval *bv )
1221590Srgrimes{
1231590Srgrimes	FILE		*fp;
1241590Srgrimes	ber_slen_t	rlen;
1251590Srgrimes	int		eof;
1261590Srgrimes
1271590Srgrimes	if (( fp = fopen( path, "r" )) == NULL ) {
1281590Srgrimes	    	perror( path );
1291590Srgrimes		return( -1 );
1301590Srgrimes	}
1311590Srgrimes
1321590Srgrimes	if ( fseek( fp, 0L, SEEK_END ) != 0 ) {
1331590Srgrimes		perror( path );
1341590Srgrimes		fclose( fp );
1351590Srgrimes		return( -1 );
1361590Srgrimes	}
1371590Srgrimes
1381590Srgrimes	bv->bv_len = ftell( fp );
1391590Srgrimes
1401590Srgrimes	if (( bv->bv_val = (char *)malloc( bv->bv_len )) == NULL ) {
1411590Srgrimes		perror( "malloc" );
1421590Srgrimes		fclose( fp );
1431590Srgrimes		return( -1 );
1441590Srgrimes	}
1451590Srgrimes
1461590Srgrimes	if ( fseek( fp, 0L, SEEK_SET ) != 0 ) {
1471590Srgrimes		perror( path );
1481590Srgrimes		fclose( fp );
1491590Srgrimes		return( -1 );
1501590Srgrimes	}
1511590Srgrimes
1521590Srgrimes	rlen = fread( bv->bv_val, 1, bv->bv_len, fp );
1531590Srgrimes	eof = feof( fp );
1541590Srgrimes	fclose( fp );
1551590Srgrimes
1561590Srgrimes	if ( (ber_len_t) rlen != bv->bv_len ) {
1571590Srgrimes		perror( path );
1581590Srgrimes		free( bv->bv_val );
1591590Srgrimes		return( -1 );
1601590Srgrimes	}
1611590Srgrimes
1621590Srgrimes	return( bv->bv_len );
16328202Scharnier}
16428202Scharnier
1651590Srgrimes
16628202Scharnierstatic LDAPMod **
16728202Scharnierget_modlist(
1681590Srgrimes	const char *prompt1,
1691590Srgrimes	const char *prompt2,
17028202Scharnier	const char *prompt3 )
17128202Scharnier{
1721590Srgrimes	static char	buf[256];
1731590Srgrimes	int		num;
1741590Srgrimes	LDAPMod		tmp = { 0 };
1751590Srgrimes	LDAPMod		**result;
1761590Srgrimes	struct berval	**bvals;
1771590Srgrimes
1781590Srgrimes	num = 0;
1791590Srgrimes	result = NULL;
1801590Srgrimes	while ( 1 ) {
1811590Srgrimes		if ( prompt1 ) {
1821590Srgrimes			get_line( buf, sizeof(buf), stdin, prompt1 );
1831590Srgrimes			tmp.mod_op = atoi( buf );
18428202Scharnier
1851590Srgrimes			if ( tmp.mod_op == -1 || buf[0] == '\0' )
1861590Srgrimes				break;
1871590Srgrimes		}
1881590Srgrimes
1891590Srgrimes		get_line( buf, sizeof(buf), stdin, prompt2 );
1901590Srgrimes		if ( buf[0] == '\0' )
1911590Srgrimes			break;
1921590Srgrimes		tmp.mod_type = strdup( buf );
1931590Srgrimes
1941590Srgrimes		tmp.mod_values = get_list( prompt3 );
1951590Srgrimes
19613068Sjoerg		if ( tmp.mod_values != NULL ) {
1971590Srgrimes			int	i;
1981590Srgrimes
1991590Srgrimes			for ( i = 0; tmp.mod_values[i] != NULL; ++i )
2001590Srgrimes				;
2011590Srgrimes			bvals = (struct berval **)calloc( i + 1,
2021590Srgrimes			    sizeof( struct berval *));
2031590Srgrimes			for ( i = 0; tmp.mod_values[i] != NULL; ++i ) {
2041590Srgrimes				bvals[i] = (struct berval *)malloc(
2051590Srgrimes				    sizeof( struct berval ));
2061590Srgrimes				if ( strncmp( tmp.mod_values[i], "{FILE}",
2071590Srgrimes				    6 ) == 0 ) {
20836792Simp					if ( file_read( tmp.mod_values[i] + 6,
20936792Simp					    bvals[i] ) < 0 ) {
21036792Simp						free( bvals );
2111590Srgrimes						for ( i = 0; i<num; i++ )
2121590Srgrimes							free( result[ i ] );
2131590Srgrimes						free( result );
2141590Srgrimes						return( NULL );
2151590Srgrimes					}
2161590Srgrimes				} else {
2171590Srgrimes					bvals[i]->bv_val = tmp.mod_values[i];
2181590Srgrimes					bvals[i]->bv_len =
21936792Simp					    strlen( tmp.mod_values[i] );
2201590Srgrimes				}
22136792Simp			}
2221590Srgrimes			tmp.mod_bvalues = bvals;
2231590Srgrimes			tmp.mod_op |= LDAP_MOD_BVALUES;
2241590Srgrimes		}
2251590Srgrimes
2261590Srgrimes		if ( result == NULL )
2271590Srgrimes			result = (LDAPMod **) malloc( sizeof(LDAPMod *) );
2281590Srgrimes		else
2291590Srgrimes			result = (LDAPMod **) realloc( result,
2301590Srgrimes			    sizeof(LDAPMod *) * (num + 1) );
2311590Srgrimes
2321590Srgrimes		result[num] = (LDAPMod *) malloc( sizeof(LDAPMod) );
2331590Srgrimes		*(result[num]) = tmp;	/* struct copy */
2341590Srgrimes		num++;
2351590Srgrimes	}
2361590Srgrimes	if ( result == NULL )
2371590Srgrimes		return( NULL );
2381590Srgrimes	result = (LDAPMod **) realloc( result, sizeof(LDAPMod *) * (num + 1) );
2391590Srgrimes	result[num] = NULL;
2401590Srgrimes
2411590Srgrimes	return( result );
2421590Srgrimes}
2431590Srgrimes
2441590Srgrimes
2451590Srgrimesstatic int
2461590Srgrimesbind_prompt( LDAP *ld,
2471590Srgrimes	LDAP_CONST char *url,
2481590Srgrimes	ber_tag_t request, ber_int_t msgid,
2491590Srgrimes	void *params )
2501590Srgrimes{
2511590Srgrimes	static char	dn[256], passwd[256];
2521590Srgrimes	int	authmethod;
2531590Srgrimes
2541590Srgrimes	printf("rebind for request=%ld msgid=%ld url=%s\n",
2551590Srgrimes		request, (long) msgid, url );
2561590Srgrimes
2571590Srgrimes	authmethod = LDAP_AUTH_SIMPLE;
2581590Srgrimes
2591590Srgrimes		get_line( dn, sizeof(dn), stdin, "re-bind dn? " );
2601590Srgrimes		strcat( dn, dnsuffix );
2611590Srgrimes
2621590Srgrimes	if ( authmethod == LDAP_AUTH_SIMPLE && dn[0] != '\0' ) {
2631590Srgrimes			get_line( passwd, sizeof(passwd), stdin,
2641590Srgrimes			    "re-bind password? " );
2651590Srgrimes		} else {
2661590Srgrimes			passwd[0] = '\0';
2671590Srgrimes		}
2681590Srgrimes
2691590Srgrimes	return ldap_bind_s( ld, dn, passwd, authmethod);
2701590Srgrimes}
2711590Srgrimes
2721590Srgrimes
2731590Srgrimesint
2741590Srgrimesmain( int argc, char **argv )
2751590Srgrimes{
2761590Srgrimes	LDAP		*ld = NULL;
2771590Srgrimes	int		i, c, port, errflg, method, id, msgtype;
2781590Srgrimes	char		line[256], command1, command2, command3;
2791590Srgrimes	char		passwd[64], dn[256], rdn[64], attr[64], value[256];
2801590Srgrimes	char		filter[256], *host, **types;
2811590Srgrimes	char		**exdn;
2821590Srgrimes	static const char usage[] =
2831590Srgrimes		"usage: %s [-u] [-h host] [-d level] [-s dnsuffix] [-p port] [-t file] [-T file]\n";
2841590Srgrimes	int		bound, all, scope, attrsonly;
2851590Srgrimes	LDAPMessage	*res;
2861590Srgrimes	LDAPMod		**mods, **attrs;
2878874Srgrimes	struct timeval	timeout;
2881590Srgrimes	char		*copyfname = NULL;
2891590Srgrimes	int		copyoptions = 0;
2901590Srgrimes	LDAPURLDesc	*ludp;
2911590Srgrimes
2921590Srgrimes	host = NULL;
2931590Srgrimes	port = LDAP_PORT;
2941590Srgrimes	dnsuffix = "";
2951590Srgrimes	errflg = 0;
2961590Srgrimes
2971590Srgrimes	while (( c = getopt( argc, argv, "h:d:s:p:t:T:" )) != -1 ) {
2981590Srgrimes		switch( c ) {
2991590Srgrimes		case 'd':
3001590Srgrimes#ifdef LDAP_DEBUG
3011590Srgrimes			ldap_debug = atoi( optarg );
3021590Srgrimes#ifdef LBER_DEBUG
3031590Srgrimes			if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
3041590Srgrimes				ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &ldap_debug );
3051590Srgrimes			}
3061590Srgrimes#endif
3071590Srgrimes#else
3081590Srgrimes			printf( "Compile with -DLDAP_DEBUG for debugging\n" );
3091590Srgrimes#endif
3101590Srgrimes			break;
3111590Srgrimes
3121590Srgrimes		case 'h':
3131590Srgrimes			host = optarg;
3141590Srgrimes			break;
3151590Srgrimes
3161590Srgrimes		case 's':
3171590Srgrimes			dnsuffix = optarg;
3181590Srgrimes			break;
3191590Srgrimes
3201590Srgrimes		case 'p':
3211590Srgrimes			port = atoi( optarg );
3221590Srgrimes			break;
3231590Srgrimes
3241590Srgrimes		case 't':	/* copy ber's to given file */
3251590Srgrimes			copyfname = strdup( optarg );
32613068Sjoerg/*			copyoptions = LBER_TO_FILE; */
3271590Srgrimes			break;
3281590Srgrimes
3291590Srgrimes		case 'T':	/* only output ber's to given file */
3301590Srgrimes			copyfname = strdup( optarg );
3311590Srgrimes/*			copyoptions = (LBER_TO_FILE | LBER_TO_FILE_ONLY); */
3321590Srgrimes			break;
3331590Srgrimes
3341590Srgrimes		default:
3351590Srgrimes		    ++errflg;
3361590Srgrimes		}
3371590Srgrimes	}
3381590Srgrimes
3391590Srgrimes	if ( host == NULL && optind == argc - 1 ) {
3401590Srgrimes		host = argv[ optind ];
3411590Srgrimes		++optind;
3421590Srgrimes	}
3431590Srgrimes
3441590Srgrimes	if ( errflg || optind < argc - 1 ) {
3451590Srgrimes		fprintf( stderr, usage, argv[ 0 ] );
3461590Srgrimes		exit( EXIT_FAILURE );
3471590Srgrimes	}
3481590Srgrimes
3491590Srgrimes	printf( "ldap_init( %s, %d )\n",
3501590Srgrimes		host == NULL ? "(null)" : host, port );
3511590Srgrimes
3521590Srgrimes	ld = ldap_init( host, port );
3531590Srgrimes
35436792Simp	if ( ld == NULL ) {
35536792Simp		perror( "ldap_init" );
3561590Srgrimes		exit( EXIT_FAILURE );
3571590Srgrimes	}
35836792Simp
35936792Simp	if ( copyfname != NULL ) {
3601590Srgrimes		if ( ( ld->ld_sb->sb_fd = open( copyfname, O_WRONLY|O_CREAT|O_EXCL,
3611590Srgrimes		    0600 ))  == -1 ) {
3621590Srgrimes			perror( copyfname );
3631590Srgrimes			exit ( EXIT_FAILURE );
3641590Srgrimes		}
3651590Srgrimes		ld->ld_sb->sb_options = copyoptions;
3661590Srgrimes	}
3671590Srgrimes
3681590Srgrimes	bound = 0;
36928202Scharnier	timeout.tv_sec = 0;
3701590Srgrimes	timeout.tv_usec = 0;
3711590Srgrimes
3721590Srgrimes	(void) memset( line, '\0', sizeof(line) );
3731590Srgrimes	while ( get_line( line, sizeof(line), stdin, "\ncommand? " ) != NULL ) {
3741590Srgrimes		command1 = line[0];
3751590Srgrimes		command2 = line[1];
37640765Sdg		command3 = line[2];
3771590Srgrimes
3781590Srgrimes		switch ( command1 ) {
3791590Srgrimes		case 'a':	/* add or abandon */
3801590Srgrimes			switch ( command2 ) {
3818874Srgrimes			case 'd':	/* add */
3821590Srgrimes				get_line( dn, sizeof(dn), stdin, "dn? " );
3831590Srgrimes				strcat( dn, dnsuffix );
3841590Srgrimes				if ( (attrs = get_modlist( NULL, "attr? ",
3851590Srgrimes				    "value? " )) == NULL )
3861590Srgrimes					break;
38728202Scharnier				if ( (id = ldap_add( ld, dn, attrs )) == -1 )
3881590Srgrimes					ldap_perror( ld, "ldap_add" );
3891590Srgrimes				else
3901590Srgrimes					printf( "Add initiated with id %d\n",
3911590Srgrimes					    id );
3921590Srgrimes				break;
3931590Srgrimes
39440765Sdg			case 'b':	/* abandon */
3951590Srgrimes				get_line( line, sizeof(line), stdin, "msgid? " );
3961590Srgrimes				id = atoi( line );
3971590Srgrimes				if ( ldap_abandon( ld, id ) != 0 )
3981590Srgrimes					ldap_perror( ld, "ldap_abandon" );
3991590Srgrimes				else
4001590Srgrimes					printf( "Abandon successful\n" );
4011590Srgrimes				break;
4021590Srgrimes			default:
4031590Srgrimes				printf( "Possibilities: [ad]d, [ab]ort\n" );
4041590Srgrimes			}
4051590Srgrimes			break;
4061590Srgrimes
4071590Srgrimes		case 'b':	/* asynch bind */
4081590Srgrimes			method = LDAP_AUTH_SIMPLE;
4091590Srgrimes			get_line( dn, sizeof(dn), stdin, "dn? " );
4101590Srgrimes			strcat( dn, dnsuffix );
4111590Srgrimes
4121590Srgrimes			if ( method == LDAP_AUTH_SIMPLE && dn[0] != '\0' )
4131590Srgrimes				get_line( passwd, sizeof(passwd), stdin,
4141590Srgrimes				    "password? " );
4151590Srgrimes			else
4161590Srgrimes				passwd[0] = '\0';
4171590Srgrimes
4181590Srgrimes			if ( ldap_bind( ld, dn, passwd, method ) == -1 ) {
4191590Srgrimes				fprintf( stderr, "ldap_bind failed\n" );
4201590Srgrimes				ldap_perror( ld, "ldap_bind" );
4211590Srgrimes			} else {
42213068Sjoerg				printf( "Bind initiated\n" );
4231590Srgrimes				bound = 1;
4241590Srgrimes			}
4251590Srgrimes			break;
4261590Srgrimes
4271590Srgrimes		case 'B':	/* synch bind */
4281590Srgrimes			method = LDAP_AUTH_SIMPLE;
4291590Srgrimes			get_line( dn, sizeof(dn), stdin, "dn? " );
4301590Srgrimes			strcat( dn, dnsuffix );
4311590Srgrimes
4321590Srgrimes			if ( dn[0] != '\0' )
4331590Srgrimes				get_line( passwd, sizeof(passwd), stdin,
4341590Srgrimes				    "password? " );
4351590Srgrimes			else
4361590Srgrimes				passwd[0] = '\0';
4371590Srgrimes
4381590Srgrimes			if ( ldap_bind_s( ld, dn, passwd, method ) !=
4391590Srgrimes			    LDAP_SUCCESS ) {
4401590Srgrimes				fprintf( stderr, "ldap_bind_s failed\n" );
4411590Srgrimes				ldap_perror( ld, "ldap_bind_s" );
4421590Srgrimes			} else {
4431590Srgrimes				printf( "Bind successful\n" );
4441590Srgrimes				bound = 1;
4451590Srgrimes			}
4461590Srgrimes			break;
4471590Srgrimes
4481590Srgrimes		case 'c':	/* compare */
4491590Srgrimes			get_line( dn, sizeof(dn), stdin, "dn? " );
4501590Srgrimes			strcat( dn, dnsuffix );
4511590Srgrimes			get_line( attr, sizeof(attr), stdin, "attr? " );
4521590Srgrimes			get_line( value, sizeof(value), stdin, "value? " );
45336792Simp
4541590Srgrimes			if ( (id = ldap_compare( ld, dn, attr, value )) == -1 )
4551590Srgrimes				ldap_perror( ld, "ldap_compare" );
45636792Simp			else
45736792Simp				printf( "Compare initiated with id %d\n", id );
4581590Srgrimes			break;
4591590Srgrimes
4601590Srgrimes		case 'd':	/* turn on debugging */
4611590Srgrimes#ifdef LDAP_DEBUG
4621590Srgrimes			get_line( line, sizeof(line), stdin, "debug level? " );
46328202Scharnier			ldap_debug = atoi( line );
4641590Srgrimes#ifdef LBER_DEBUG
4651590Srgrimes			if ( ldap_debug & LDAP_DEBUG_PACKETS ) {
4661590Srgrimes				ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &ldap_debug );
4671590Srgrimes			}
4681590Srgrimes#endif
4691590Srgrimes#else
4701590Srgrimes			printf( "Compile with -DLDAP_DEBUG for debugging\n" );
4711590Srgrimes#endif
4721590Srgrimes			break;
4731590Srgrimes
4741590Srgrimes		case 'E':	/* explode a dn */
4751590Srgrimes			get_line( line, sizeof(line), stdin, "dn? " );
47628202Scharnier			exdn = ldap_explode_dn( line, 0 );
4771590Srgrimes			for ( i = 0; exdn != NULL && exdn[i] != NULL; i++ ) {
4781590Srgrimes				printf( "\t%s\n", exdn[i] );
4791590Srgrimes			}
4801590Srgrimes			break;
4811590Srgrimes
4821590Srgrimes		case 'g':	/* set next msgid */
4831590Srgrimes			get_line( line, sizeof(line), stdin, "msgid? " );
4841590Srgrimes			ld->ld_msgid = atoi( line );
4851590Srgrimes			break;
4861590Srgrimes
4871590Srgrimes		case 'v':	/* set version number */
4881590Srgrimes			get_line( line, sizeof(line), stdin, "version? " );
4891590Srgrimes			ld->ld_version = atoi( line );
4901590Srgrimes			break;
4911590Srgrimes
4921590Srgrimes		case 'm':	/* modify or modifyrdn */
4931590Srgrimes			if ( strncmp( line, "modify", 4 ) == 0 ) {
4941590Srgrimes				get_line( dn, sizeof(dn), stdin, "dn? " );
4951590Srgrimes				strcat( dn, dnsuffix );
4961590Srgrimes				if ( (mods = get_modlist(
4971590Srgrimes				    "mod (0=>add, 1=>delete, 2=>replace -1=>done)? ",
4981590Srgrimes				    "attribute type? ", "attribute value? " ))
4991590Srgrimes				    == NULL )
5001590Srgrimes					break;
5011590Srgrimes				if ( (id = ldap_modify( ld, dn, mods )) == -1 )
5021590Srgrimes					ldap_perror( ld, "ldap_modify" );
5031590Srgrimes				else
5041590Srgrimes					printf( "Modify initiated with id %d\n",
5051590Srgrimes					    id );
5061590Srgrimes			} else if ( strncmp( line, "modrdn", 4 ) == 0 ) {
50713068Sjoerg				get_line( dn, sizeof(dn), stdin, "dn? " );
5081590Srgrimes				strcat( dn, dnsuffix );
5091590Srgrimes				get_line( rdn, sizeof(rdn), stdin, "newrdn? " );
5101590Srgrimes				if ( (id = ldap_modrdn( ld, dn, rdn )) == -1 )
5111590Srgrimes					ldap_perror( ld, "ldap_modrdn" );
5121590Srgrimes				else
5131590Srgrimes					printf( "Modrdn initiated with id %d\n",
5141590Srgrimes					    id );
5151590Srgrimes			} else {
5161590Srgrimes				printf( "Possibilities: [modi]fy, [modr]dn\n" );
5171590Srgrimes			}
5181590Srgrimes			break;
5191590Srgrimes
5201590Srgrimes		case 'q':	/* quit */
5211590Srgrimes			ldap_unbind( ld );
5221590Srgrimes			exit( EXIT_SUCCESS );
5231590Srgrimes			break;
5241590Srgrimes
5251590Srgrimes		case 'r':	/* result or remove */
5261590Srgrimes			switch ( command3 ) {
5271590Srgrimes			case 's':	/* result */
5281590Srgrimes				get_line( line, sizeof(line), stdin,
5291590Srgrimes				    "msgid (-1=>any)? " );
5301590Srgrimes				if ( line[0] == '\0' )
5311590Srgrimes					id = -1;
5321590Srgrimes				else
5331590Srgrimes					id = atoi( line );
5341590Srgrimes				get_line( line, sizeof(line), stdin,
53513068Sjoerg				    "all (0=>any, 1=>all)? " );
5361590Srgrimes				if ( line[0] == '\0' )
5371590Srgrimes					all = 1;
5381590Srgrimes				else
5391590Srgrimes					all = atoi( line );
5401590Srgrimes				if (( msgtype = ldap_result( ld, id, all,
5411590Srgrimes				    &timeout, &res )) < 1 ) {
5421590Srgrimes					ldap_perror( ld, "ldap_result" );
5431590Srgrimes					break;
5441590Srgrimes				}
5451590Srgrimes				printf( "\nresult: msgtype %d msgid %d\n",
5461590Srgrimes				    msgtype, res->lm_msgid );
5471590Srgrimes				handle_result( ld, res );
5481590Srgrimes				res = NULL;
5491590Srgrimes				break;
5501590Srgrimes
5511590Srgrimes			case 'm':	/* remove */
5521590Srgrimes				get_line( dn, sizeof(dn), stdin, "dn? " );
5531590Srgrimes				strcat( dn, dnsuffix );
5541590Srgrimes				if ( (id = ldap_delete( ld, dn )) == -1 )
5551590Srgrimes					ldap_perror( ld, "ldap_delete" );
5561590Srgrimes				else
5571590Srgrimes					printf( "Remove initiated with id %d\n",
5581590Srgrimes					    id );
5591590Srgrimes				break;
5601590Srgrimes
5611590Srgrimes			default:
5621590Srgrimes				printf( "Possibilities: [rem]ove, [res]ult\n" );
5631590Srgrimes				break;
5641590Srgrimes			}
5651590Srgrimes			break;
5661590Srgrimes
5671590Srgrimes		case 's':	/* search */
5681590Srgrimes			get_line( dn, sizeof(dn), stdin, "searchbase? " );
5691590Srgrimes			strcat( dn, dnsuffix );
5701590Srgrimes			get_line( line, sizeof(line), stdin,
5711590Srgrimes			    "scope (0=baseObject, 1=oneLevel, 2=subtree, 3=children)? " );
5721590Srgrimes			scope = atoi( line );
5731590Srgrimes			get_line( filter, sizeof(filter), stdin,
5741590Srgrimes			    "search filter (e.g. sn=jones)? " );
5751590Srgrimes			types = get_list( "attrs to return? " );
5761590Srgrimes			get_line( line, sizeof(line), stdin,
5771590Srgrimes			    "attrsonly (0=attrs&values, 1=attrs only)? " );
5781590Srgrimes			attrsonly = atoi( line );
5791590Srgrimes
5808874Srgrimes			    if (( id = ldap_search( ld, dn, scope, filter,
5811590Srgrimes				    types, attrsonly  )) == -1 ) {
5821590Srgrimes				ldap_perror( ld, "ldap_search" );
5831590Srgrimes			    } else {
5841590Srgrimes				printf( "Search initiated with id %d\n", id );
5851590Srgrimes			    }
5861590Srgrimes			free_list( types );
5871590Srgrimes			break;
5881590Srgrimes
5891590Srgrimes		case 't':	/* set timeout value */
5901590Srgrimes			get_line( line, sizeof(line), stdin, "timeout? " );
5911590Srgrimes			timeout.tv_sec = atoi( line );
5921590Srgrimes			break;
5931590Srgrimes
5941590Srgrimes		case 'p':	/* parse LDAP URL */
59518286Sbde			get_line( line, sizeof(line), stdin, "LDAP URL? " );
5961590Srgrimes			if (( i = ldap_url_parse( line, &ludp )) != 0 ) {
5971590Srgrimes			    fprintf( stderr, "ldap_url_parse: error %d\n", i );
5981590Srgrimes			} else {
59913068Sjoerg			    printf( "\t  host: " );
6001590Srgrimes			    if ( ludp->lud_host == NULL ) {
6011590Srgrimes				printf( "DEFAULT\n" );
6021590Srgrimes			    } else {
60313068Sjoerg				printf( "<%s>\n", ludp->lud_host );
6041590Srgrimes			    }
6051590Srgrimes			    printf( "\t  port: " );
6061590Srgrimes			    if ( ludp->lud_port == 0 ) {
6071590Srgrimes				printf( "DEFAULT\n" );
6081590Srgrimes			    } else {
6091590Srgrimes				printf( "%d\n", ludp->lud_port );
61013068Sjoerg			    }
61113068Sjoerg			    printf( "\t    dn: <%s>\n", ludp->lud_dn );
6121590Srgrimes			    printf( "\t attrs:" );
6131590Srgrimes			    if ( ludp->lud_attrs == NULL ) {
6141590Srgrimes				printf( " ALL" );
6151590Srgrimes			    } else {
6161590Srgrimes				for ( i = 0; ludp->lud_attrs[ i ] != NULL; ++i ) {
6171590Srgrimes				    printf( " <%s>", ludp->lud_attrs[ i ] );
6181590Srgrimes				}
6191590Srgrimes			    }
6201590Srgrimes			    printf( "\n\t scope: %s\n",
6211590Srgrimes					ludp->lud_scope == LDAP_SCOPE_BASE ? "baseObject"
6221590Srgrimes					: ludp->lud_scope == LDAP_SCOPE_ONELEVEL ? "oneLevel"
6231590Srgrimes					: ludp->lud_scope == LDAP_SCOPE_SUBTREE ? "subtree"
6241590Srgrimes#ifdef LDAP_SCOPE_SUBORDINATE
6251590Srgrimes					: ludp->lud_scope == LDAP_SCOPE_SUBORDINATE ? "children"
6261590Srgrimes#endif
6271590Srgrimes					: "**invalid**" );
6281590Srgrimes			    printf( "\tfilter: <%s>\n", ludp->lud_filter );
6291590Srgrimes			    ldap_free_urldesc( ludp );
6301590Srgrimes			}
6311590Srgrimes			    break;
6321590Srgrimes
6331590Srgrimes		case 'n':	/* set dn suffix, for convenience */
6341590Srgrimes			get_line( line, sizeof(line), stdin, "DN suffix? " );
6351590Srgrimes			strcpy( dnsuffix, line );
6361590Srgrimes			break;
6371590Srgrimes
6381590Srgrimes		case 'o':	/* set ldap options */
6391590Srgrimes			get_line( line, sizeof(line), stdin, "alias deref (0=never, 1=searching, 2=finding, 3=always)?" );
6401590Srgrimes			ld->ld_deref = atoi( line );
6411590Srgrimes			get_line( line, sizeof(line), stdin, "timelimit?" );
6421590Srgrimes			ld->ld_timelimit = atoi( line );
6431590Srgrimes			get_line( line, sizeof(line), stdin, "sizelimit?" );
6441590Srgrimes			ld->ld_sizelimit = atoi( line );
6451590Srgrimes
6461590Srgrimes			LDAP_BOOL_ZERO(&ld->ld_options);
6471590Srgrimes
6481590Srgrimes			get_line( line, sizeof(line), stdin,
6491590Srgrimes				"Recognize and chase referrals (0=no, 1=yes)?" );
6501590Srgrimes			if ( atoi( line ) != 0 ) {
6511590Srgrimes				LDAP_BOOL_SET(&ld->ld_options, LDAP_BOOL_REFERRALS);
6521590Srgrimes				get_line( line, sizeof(line), stdin,
6531590Srgrimes					"Prompt for bind credentials when chasing referrals (0=no, 1=yes)?" );
6541590Srgrimes				if ( atoi( line ) != 0 ) {
6551590Srgrimes					ldap_set_rebind_proc( ld, bind_prompt, NULL );
6561590Srgrimes				}
6571590Srgrimes			}
6581590Srgrimes			break;
6591590Srgrimes
6601590Srgrimes		case '?':	/* help */
6611590Srgrimes			printf(
6621590Srgrimes"Commands: [ad]d         [ab]andon         [b]ind\n"
6631590Srgrimes"          [B]ind async  [c]ompare\n"
6641590Srgrimes"          [modi]fy      [modr]dn          [rem]ove\n"
6651590Srgrimes"          [res]ult      [s]earch          [q]uit/unbind\n\n"
6661590Srgrimes"          [d]ebug       set ms[g]id\n"
6671590Srgrimes"          d[n]suffix    [t]imeout         [v]ersion\n"
6681590Srgrimes"          [?]help       [o]ptions"
66913068Sjoerg"          [E]xplode dn  [p]arse LDAP URL\n" );
67013068Sjoerg			break;
6711590Srgrimes
6721590Srgrimes		default:
6731590Srgrimes			printf( "Invalid command.  Type ? for help.\n" );
6741590Srgrimes			break;
6751590Srgrimes		}
6761590Srgrimes
6771590Srgrimes		(void) memset( line, '\0', sizeof(line) );
6781590Srgrimes	}
6791590Srgrimes
6801590Srgrimes	return( 0 );
6811590Srgrimes}
6821590Srgrimes
6831590Srgrimesstatic void
6841590Srgrimeshandle_result( LDAP *ld, LDAPMessage *lm )
6851590Srgrimes{
6861590Srgrimes	switch ( lm->lm_msgtype ) {
6871590Srgrimes	case LDAP_RES_COMPARE:
6881590Srgrimes		printf( "Compare result\n" );
6891590Srgrimes		print_ldap_result( ld, lm, "compare" );
6901590Srgrimes		break;
6911590Srgrimes
6921590Srgrimes	case LDAP_RES_SEARCH_RESULT:
6931590Srgrimes		printf( "Search result\n" );
6941590Srgrimes		print_ldap_result( ld, lm, "search" );
6951590Srgrimes		break;
6961590Srgrimes
6971590Srgrimes	case LDAP_RES_SEARCH_ENTRY:
6981590Srgrimes		printf( "Search entry\n" );
6991590Srgrimes		print_search_entry( ld, lm );
7001590Srgrimes		break;
7011590Srgrimes
7021590Srgrimes	case LDAP_RES_ADD:
7031590Srgrimes		printf( "Add result\n" );
7041590Srgrimes		print_ldap_result( ld, lm, "add" );
7051590Srgrimes		break;
7061590Srgrimes
7071590Srgrimes	case LDAP_RES_DELETE:
7081590Srgrimes		printf( "Delete result\n" );
7091590Srgrimes		print_ldap_result( ld, lm, "delete" );
7101590Srgrimes		break;
7111590Srgrimes
7121590Srgrimes	case LDAP_RES_MODRDN:
7131590Srgrimes		printf( "ModRDN result\n" );
7141590Srgrimes		print_ldap_result( ld, lm, "modrdn" );
7151590Srgrimes		break;
7161590Srgrimes
7171590Srgrimes	case LDAP_RES_BIND:
7181590Srgrimes		printf( "Bind result\n" );
7191590Srgrimes		print_ldap_result( ld, lm, "bind" );
7201590Srgrimes		break;
7211590Srgrimes
7221590Srgrimes	default:
7231590Srgrimes		printf( "Unknown result type 0x%lx\n",
7241590Srgrimes		        (unsigned long) lm->lm_msgtype );
7251590Srgrimes		print_ldap_result( ld, lm, "unknown" );
7261590Srgrimes	}
7271590Srgrimes}
7281590Srgrimes
7291590Srgrimesstatic void
7301590Srgrimesprint_ldap_result( LDAP *ld, LDAPMessage *lm, const char *s )
7311590Srgrimes{
7321590Srgrimes	ldap_result2error( ld, lm, 1 );
7331590Srgrimes	ldap_perror( ld, s );
7341590Srgrimes/*
7351590Srgrimes	if ( ld->ld_error != NULL && *ld->ld_error != '\0' )
7361590Srgrimes		fprintf( stderr, "Additional info: %s\n", ld->ld_error );
7371590Srgrimes	if ( LDAP_NAME_ERROR( ld->ld_errno ) && ld->ld_matched != NULL )
7381590Srgrimes		fprintf( stderr, "Matched DN: %s\n", ld->ld_matched );
7391590Srgrimes*/
7401590Srgrimes}
7411590Srgrimes
742static void
743print_search_entry( LDAP *ld, LDAPMessage *res )
744{
745	LDAPMessage	*e;
746
747	for ( e = ldap_first_entry( ld, res ); e != NULL;
748	    e = ldap_next_entry( ld, e ) )
749	{
750		BerElement	*ber = NULL;
751		char *a, *dn, *ufn;
752
753		if ( e->lm_msgtype == LDAP_RES_SEARCH_RESULT )
754			break;
755
756		dn = ldap_get_dn( ld, e );
757		printf( "\tDN: %s\n", dn );
758
759		ufn = ldap_dn2ufn( dn );
760		printf( "\tUFN: %s\n", ufn );
761
762		free( dn );
763		free( ufn );
764
765		for ( a = ldap_first_attribute( ld, e, &ber ); a != NULL;
766		    a = ldap_next_attribute( ld, e, ber ) )
767		{
768			struct berval	**vals;
769
770			printf( "\t\tATTR: %s\n", a );
771			if ( (vals = ldap_get_values_len( ld, e, a ))
772			    == NULL ) {
773				printf( "\t\t\t(no values)\n" );
774			} else {
775				int i;
776				for ( i = 0; vals[i] != NULL; i++ ) {
777					int	j, nonascii;
778
779					nonascii = 0;
780					for ( j = 0; (ber_len_t) j < vals[i]->bv_len; j++ )
781						if ( !isascii( vals[i]->bv_val[j] ) ) {
782							nonascii = 1;
783							break;
784						}
785
786					if ( nonascii ) {
787						printf( "\t\t\tlength (%ld) (not ascii)\n", vals[i]->bv_len );
788#ifdef BPRINT_NONASCII
789						ber_bprint( vals[i]->bv_val,
790						    vals[i]->bv_len );
791#endif /* BPRINT_NONASCII */
792						continue;
793					}
794					printf( "\t\t\tlength (%ld) %s\n",
795					    vals[i]->bv_len, vals[i]->bv_val );
796				}
797				ber_bvecfree( vals );
798			}
799		}
800
801		if(ber != NULL) {
802			ber_free( ber, 0 );
803		}
804	}
805
806	if ( res->lm_msgtype == LDAP_RES_SEARCH_RESULT
807	    || res->lm_chain != NULL )
808		print_ldap_result( ld, res, "search" );
809}
810