xref: /netbsd-src/external/bsd/openldap/dist/tests/progs/slapd-common.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1*549b59edSchristos /*	$NetBSD: slapd-common.c,v 1.3 2021/08/14 16:15:03 christos Exp $	*/
24e6df137Slukem 
3d11b170bStron /* $OpenLDAP$ */
42de962bdSlukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
52de962bdSlukem  *
6*549b59edSchristos  * Copyright 1999-2021 The OpenLDAP Foundation.
72de962bdSlukem  * All rights reserved.
82de962bdSlukem  *
92de962bdSlukem  * Redistribution and use in source and binary forms, with or without
102de962bdSlukem  * modification, are permitted only as authorized by the OpenLDAP
112de962bdSlukem  * Public License.
122de962bdSlukem  *
132de962bdSlukem  * A copy of this license is available in file LICENSE in the
142de962bdSlukem  * top-level directory of the distribution or, alternatively, at
152de962bdSlukem  * <http://www.OpenLDAP.org/license.html>.
162de962bdSlukem  */
172de962bdSlukem /* ACKNOWLEDGEMENTS:
182de962bdSlukem  * This work was initially developed by Howard Chu for inclusion
192de962bdSlukem  * in OpenLDAP Software.
202de962bdSlukem  */
212de962bdSlukem 
22376af7d7Schristos #include <sys/cdefs.h>
23*549b59edSchristos __RCSID("$NetBSD: slapd-common.c,v 1.3 2021/08/14 16:15:03 christos Exp $");
24376af7d7Schristos 
252de962bdSlukem #include "portable.h"
262de962bdSlukem 
272de962bdSlukem #include <stdio.h>
282de962bdSlukem 
292de962bdSlukem #include "ac/stdlib.h"
302de962bdSlukem #include "ac/unistd.h"
312de962bdSlukem #include "ac/string.h"
322de962bdSlukem #include "ac/errno.h"
332de962bdSlukem 
342de962bdSlukem #include "ldap.h"
352de962bdSlukem 
36*549b59edSchristos #include "lutil.h"
37*549b59edSchristos #include "lutil_ldap.h"
382de962bdSlukem #include "ldap_pvt.h"
392de962bdSlukem #include "slapd-common.h"
402de962bdSlukem 
412de962bdSlukem /* global vars */
422de962bdSlukem pid_t pid;
43*549b59edSchristos int debug;
442de962bdSlukem 
452de962bdSlukem /* static vars */
462de962bdSlukem static char progname[ BUFSIZ ];
472de962bdSlukem tester_t progtype;
482de962bdSlukem 
494e6df137Slukem /*
504e6df137Slukem  * ignore_count[] is indexed by result code:
514e6df137Slukem  * negative for OpenLDAP client-side errors, positive for protocol codes.
524e6df137Slukem  */
534e6df137Slukem #define	TESTER_CLIENT_FIRST	LDAP_REFERRAL_LIMIT_EXCEEDED /* negative */
544e6df137Slukem #define	TESTER_SERVER_LAST	LDAP_OTHER
554e6df137Slukem static int ignore_base	[ -TESTER_CLIENT_FIRST + TESTER_SERVER_LAST + 1 ];
564e6df137Slukem #define    ignore_count	(ignore_base - TESTER_CLIENT_FIRST)
572de962bdSlukem 
584e6df137Slukem static const struct {
594e6df137Slukem 	const char *name;
602de962bdSlukem 	int	err;
612de962bdSlukem } ignore_str2err[] = {
622de962bdSlukem 	{ "OPERATIONS_ERROR",		LDAP_OPERATIONS_ERROR },
632de962bdSlukem 	{ "PROTOCOL_ERROR",		LDAP_PROTOCOL_ERROR },
642de962bdSlukem 	{ "TIMELIMIT_EXCEEDED",		LDAP_TIMELIMIT_EXCEEDED },
652de962bdSlukem 	{ "SIZELIMIT_EXCEEDED",		LDAP_SIZELIMIT_EXCEEDED },
662de962bdSlukem 	{ "COMPARE_FALSE",		LDAP_COMPARE_FALSE },
672de962bdSlukem 	{ "COMPARE_TRUE",		LDAP_COMPARE_TRUE },
682de962bdSlukem 	{ "AUTH_METHOD_NOT_SUPPORTED",	LDAP_AUTH_METHOD_NOT_SUPPORTED },
692de962bdSlukem 	{ "STRONG_AUTH_NOT_SUPPORTED",	LDAP_STRONG_AUTH_NOT_SUPPORTED },
702de962bdSlukem 	{ "STRONG_AUTH_REQUIRED",	LDAP_STRONG_AUTH_REQUIRED },
712de962bdSlukem 	{ "STRONGER_AUTH_REQUIRED",	LDAP_STRONGER_AUTH_REQUIRED },
722de962bdSlukem 	{ "PARTIAL_RESULTS",		LDAP_PARTIAL_RESULTS },
732de962bdSlukem 
742de962bdSlukem 	{ "REFERRAL",			LDAP_REFERRAL },
752de962bdSlukem 	{ "ADMINLIMIT_EXCEEDED",	LDAP_ADMINLIMIT_EXCEEDED },
762de962bdSlukem 	{ "UNAVAILABLE_CRITICAL_EXTENSION", LDAP_UNAVAILABLE_CRITICAL_EXTENSION },
772de962bdSlukem 	{ "CONFIDENTIALITY_REQUIRED",	LDAP_CONFIDENTIALITY_REQUIRED },
782de962bdSlukem 	{ "SASL_BIND_IN_PROGRESS",	LDAP_SASL_BIND_IN_PROGRESS },
792de962bdSlukem 
802de962bdSlukem 	{ "NO_SUCH_ATTRIBUTE",		LDAP_NO_SUCH_ATTRIBUTE },
812de962bdSlukem 	{ "UNDEFINED_TYPE",		LDAP_UNDEFINED_TYPE },
822de962bdSlukem 	{ "INAPPROPRIATE_MATCHING",	LDAP_INAPPROPRIATE_MATCHING },
832de962bdSlukem 	{ "CONSTRAINT_VIOLATION",	LDAP_CONSTRAINT_VIOLATION },
842de962bdSlukem 	{ "TYPE_OR_VALUE_EXISTS",	LDAP_TYPE_OR_VALUE_EXISTS },
852de962bdSlukem 	{ "INVALID_SYNTAX",		LDAP_INVALID_SYNTAX },
862de962bdSlukem 
872de962bdSlukem 	{ "NO_SUCH_OBJECT",		LDAP_NO_SUCH_OBJECT },
882de962bdSlukem 	{ "ALIAS_PROBLEM",		LDAP_ALIAS_PROBLEM },
892de962bdSlukem 	{ "INVALID_DN_SYNTAX",		LDAP_INVALID_DN_SYNTAX },
902de962bdSlukem 	{ "IS_LEAF",			LDAP_IS_LEAF },
912de962bdSlukem 	{ "ALIAS_DEREF_PROBLEM",	LDAP_ALIAS_DEREF_PROBLEM },
922de962bdSlukem 
932de962bdSlukem 	/* obsolete */
942de962bdSlukem 	{ "PROXY_AUTHZ_FAILURE",	LDAP_X_PROXY_AUTHZ_FAILURE },
952de962bdSlukem 	{ "INAPPROPRIATE_AUTH",		LDAP_INAPPROPRIATE_AUTH },
962de962bdSlukem 	{ "INVALID_CREDENTIALS",	LDAP_INVALID_CREDENTIALS },
972de962bdSlukem 	{ "INSUFFICIENT_ACCESS",	LDAP_INSUFFICIENT_ACCESS },
982de962bdSlukem 
992de962bdSlukem 	{ "BUSY",			LDAP_BUSY },
1002de962bdSlukem 	{ "UNAVAILABLE",		LDAP_UNAVAILABLE },
1012de962bdSlukem 	{ "UNWILLING_TO_PERFORM",	LDAP_UNWILLING_TO_PERFORM },
1022de962bdSlukem 	{ "LOOP_DETECT",		LDAP_LOOP_DETECT },
1032de962bdSlukem 
1042de962bdSlukem 	{ "NAMING_VIOLATION",		LDAP_NAMING_VIOLATION },
1052de962bdSlukem 	{ "OBJECT_CLASS_VIOLATION",	LDAP_OBJECT_CLASS_VIOLATION },
1062de962bdSlukem 	{ "NOT_ALLOWED_ON_NONLEAF",	LDAP_NOT_ALLOWED_ON_NONLEAF },
1072de962bdSlukem 	{ "NOT_ALLOWED_ON_RDN",		LDAP_NOT_ALLOWED_ON_RDN },
1082de962bdSlukem 	{ "ALREADY_EXISTS",		LDAP_ALREADY_EXISTS },
1092de962bdSlukem 	{ "NO_OBJECT_CLASS_MODS",	LDAP_NO_OBJECT_CLASS_MODS },
1102de962bdSlukem 	{ "RESULTS_TOO_LARGE",		LDAP_RESULTS_TOO_LARGE },
1112de962bdSlukem 	{ "AFFECTS_MULTIPLE_DSAS",	LDAP_AFFECTS_MULTIPLE_DSAS },
1122de962bdSlukem 
1132de962bdSlukem 	{ "OTHER",			LDAP_OTHER },
1142de962bdSlukem 
1152de962bdSlukem 	{ "SERVER_DOWN",		LDAP_SERVER_DOWN },
1162de962bdSlukem 	{ "LOCAL_ERROR",		LDAP_LOCAL_ERROR },
1172de962bdSlukem 	{ "ENCODING_ERROR",		LDAP_ENCODING_ERROR },
1182de962bdSlukem 	{ "DECODING_ERROR",		LDAP_DECODING_ERROR },
1192de962bdSlukem 	{ "TIMEOUT",			LDAP_TIMEOUT },
1202de962bdSlukem 	{ "AUTH_UNKNOWN",		LDAP_AUTH_UNKNOWN },
1212de962bdSlukem 	{ "FILTER_ERROR",		LDAP_FILTER_ERROR },
1222de962bdSlukem 	{ "USER_CANCELLED",		LDAP_USER_CANCELLED },
1232de962bdSlukem 	{ "PARAM_ERROR",		LDAP_PARAM_ERROR },
1242de962bdSlukem 	{ "NO_MEMORY",			LDAP_NO_MEMORY },
1252de962bdSlukem 	{ "CONNECT_ERROR",		LDAP_CONNECT_ERROR },
1262de962bdSlukem 	{ "NOT_SUPPORTED",		LDAP_NOT_SUPPORTED },
1272de962bdSlukem 	{ "CONTROL_NOT_FOUND",		LDAP_CONTROL_NOT_FOUND },
1282de962bdSlukem 	{ "NO_RESULTS_RETURNED",	LDAP_NO_RESULTS_RETURNED },
1292de962bdSlukem 	{ "MORE_RESULTS_TO_RETURN",	LDAP_MORE_RESULTS_TO_RETURN },
1302de962bdSlukem 	{ "CLIENT_LOOP",		LDAP_CLIENT_LOOP },
1312de962bdSlukem 	{ "REFERRAL_LIMIT_EXCEEDED", 	LDAP_REFERRAL_LIMIT_EXCEEDED },
1322de962bdSlukem 
1332de962bdSlukem 	{ NULL }
1342de962bdSlukem };
1352de962bdSlukem 
1362de962bdSlukem #define UNKNOWN_ERR	(1234567890)
1372de962bdSlukem 
138*549b59edSchristos #define RETRIES 0
139*549b59edSchristos #define LOOPS	100
140*549b59edSchristos 
1412de962bdSlukem static int
tester_ignore_str2err(const char * err)1422de962bdSlukem tester_ignore_str2err( const char *err )
1432de962bdSlukem {
1444e6df137Slukem 	int		i, ignore = 1;
1452de962bdSlukem 
1462de962bdSlukem 	if ( strcmp( err, "ALL" ) == 0 ) {
1472de962bdSlukem 		for ( i = 0; ignore_str2err[ i ].name != NULL; i++ ) {
1484e6df137Slukem 			ignore_count[ ignore_str2err[ i ].err ] = 1;
1492de962bdSlukem 		}
1504e6df137Slukem 		ignore_count[ LDAP_SUCCESS ] = 0;
1512de962bdSlukem 
1522de962bdSlukem 		return 0;
1532de962bdSlukem 	}
1542de962bdSlukem 
1552de962bdSlukem 	if ( err[ 0 ] == '!' ) {
1562de962bdSlukem 		ignore = 0;
1572de962bdSlukem 		err++;
1584e6df137Slukem 
1594e6df137Slukem 	} else if ( err[ 0 ] == '*' ) {
1604e6df137Slukem 		ignore = -1;
1614e6df137Slukem 		err++;
1622de962bdSlukem 	}
1632de962bdSlukem 
1642de962bdSlukem 	for ( i = 0; ignore_str2err[ i ].name != NULL; i++ ) {
1652de962bdSlukem 		if ( strcmp( err, ignore_str2err[ i ].name ) == 0 ) {
1662de962bdSlukem 			int	err = ignore_str2err[ i ].err;
1672de962bdSlukem 
1684e6df137Slukem 			if ( err != LDAP_SUCCESS ) {
1694e6df137Slukem 				ignore_count[ err ] = ignore;
1702de962bdSlukem 			}
1712de962bdSlukem 
1722de962bdSlukem 			return err;
1732de962bdSlukem 		}
1742de962bdSlukem 	}
1752de962bdSlukem 
1762de962bdSlukem 	return UNKNOWN_ERR;
1772de962bdSlukem }
1782de962bdSlukem 
1792de962bdSlukem int
tester_ignore_str2errlist(const char * err)1802de962bdSlukem tester_ignore_str2errlist( const char *err )
1812de962bdSlukem {
1822de962bdSlukem 	int	i;
1832de962bdSlukem 	char	**errs = ldap_str2charray( err, "," );
1842de962bdSlukem 
1852de962bdSlukem 	for ( i = 0; errs[ i ] != NULL; i++ ) {
1862de962bdSlukem 		/* TODO: allow <err>:<prog> to ignore <err> only when <prog> */
1872de962bdSlukem 		(void)tester_ignore_str2err( errs[ i ] );
1882de962bdSlukem 	}
1892de962bdSlukem 
1902de962bdSlukem 	ldap_charray_free( errs );
1912de962bdSlukem 
1922de962bdSlukem 	return 0;
1932de962bdSlukem }
1942de962bdSlukem 
1954e6df137Slukem int
tester_ignore_err(int err)1962de962bdSlukem tester_ignore_err( int err )
1972de962bdSlukem {
1984e6df137Slukem 	int rc = 1;
1992de962bdSlukem 
2004e6df137Slukem 	if ( err && TESTER_CLIENT_FIRST <= err && err <= TESTER_SERVER_LAST ) {
2014e6df137Slukem 		rc = ignore_count[ err ];
2024e6df137Slukem 		if ( rc != 0 ) {
2034e6df137Slukem 			ignore_count[ err ] = rc + (rc > 0 ? 1 : -1);
2042de962bdSlukem 		}
2052de962bdSlukem 	}
2062de962bdSlukem 
2072de962bdSlukem 	/* SUCCESS is always "ignored" */
2082de962bdSlukem 	return rc;
2092de962bdSlukem }
2102de962bdSlukem 
211*549b59edSchristos struct tester_conn_args *
tester_init(const char * pname,tester_t ptype)2122de962bdSlukem tester_init( const char *pname, tester_t ptype )
2132de962bdSlukem {
214*549b59edSchristos 	static struct tester_conn_args config = {
215*549b59edSchristos 		.authmethod = -1,
216*549b59edSchristos 		.retries = RETRIES,
217*549b59edSchristos 		.loops = LOOPS,
218*549b59edSchristos 		.outerloops = 1,
219*549b59edSchristos 
220*549b59edSchristos 		.uri = NULL,
221*549b59edSchristos 	};
222*549b59edSchristos 
2232de962bdSlukem 	pid = getpid();
2242de962bdSlukem 	srand( pid );
2252de962bdSlukem 	snprintf( progname, sizeof( progname ), "%s PID=%d", pname, pid );
2262de962bdSlukem 	progtype = ptype;
2272de962bdSlukem 
228*549b59edSchristos 	return &config;
2292de962bdSlukem }
2302de962bdSlukem 
2312de962bdSlukem void
tester_ldap_error(LDAP * ld,const char * fname,const char * msg)2322de962bdSlukem tester_ldap_error( LDAP *ld, const char *fname, const char *msg )
2332de962bdSlukem {
2342de962bdSlukem 	int		err;
2352de962bdSlukem 	char		*text = NULL;
2362de962bdSlukem 	LDAPControl	**ctrls = NULL;
2372de962bdSlukem 
2382de962bdSlukem 	ldap_get_option( ld, LDAP_OPT_RESULT_CODE, (void *)&err );
2392de962bdSlukem 	if ( err != LDAP_SUCCESS ) {
2402de962bdSlukem 		ldap_get_option( ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void *)&text );
2412de962bdSlukem 	}
2422de962bdSlukem 
2432de962bdSlukem 	fprintf( stderr, "%s: %s: %s (%d) %s %s\n",
2442de962bdSlukem 		progname, fname, ldap_err2string( err ), err,
2452de962bdSlukem 		text == NULL ? "" : text,
2462de962bdSlukem 		msg ? msg : "" );
2472de962bdSlukem 
2482de962bdSlukem 	if ( text ) {
2492de962bdSlukem 		ldap_memfree( text );
2502de962bdSlukem 		text = NULL;
2512de962bdSlukem 	}
2522de962bdSlukem 
2532de962bdSlukem 	ldap_get_option( ld, LDAP_OPT_MATCHED_DN, (void *)&text );
2542de962bdSlukem 	if ( text != NULL ) {
2552de962bdSlukem 		if ( text[ 0 ] != '\0' ) {
2562de962bdSlukem 			fprintf( stderr, "\tmatched: %s\n", text );
2572de962bdSlukem 		}
2582de962bdSlukem 		ldap_memfree( text );
2592de962bdSlukem 		text = NULL;
2602de962bdSlukem 	}
2612de962bdSlukem 
2622de962bdSlukem 	ldap_get_option( ld, LDAP_OPT_SERVER_CONTROLS, (void *)&ctrls );
2632de962bdSlukem 	if ( ctrls != NULL ) {
2642de962bdSlukem 		int	i;
2652de962bdSlukem 
2662de962bdSlukem 		fprintf( stderr, "\tcontrols:\n" );
2672de962bdSlukem 		for ( i = 0; ctrls[ i ] != NULL; i++ ) {
2682de962bdSlukem 			fprintf( stderr, "\t\t%s\n", ctrls[ i ]->ldctl_oid );
2692de962bdSlukem 		}
2702de962bdSlukem 		ldap_controls_free( ctrls );
2712de962bdSlukem 		ctrls = NULL;
2722de962bdSlukem 	}
2732de962bdSlukem 
2742de962bdSlukem 	if ( err == LDAP_REFERRAL ) {
2752de962bdSlukem 		char **refs = NULL;
2762de962bdSlukem 
2772de962bdSlukem 		ldap_get_option( ld, LDAP_OPT_REFERRAL_URLS, (void *)&refs );
2782de962bdSlukem 
2792de962bdSlukem 		if ( refs ) {
2802de962bdSlukem 			int	i;
2812de962bdSlukem 
2822de962bdSlukem 			fprintf( stderr, "\treferral:\n" );
2832de962bdSlukem 			for ( i = 0; refs[ i ] != NULL; i++ ) {
2842de962bdSlukem 				fprintf( stderr, "\t\t%s\n", refs[ i ] );
2852de962bdSlukem 			}
2862de962bdSlukem 
2872de962bdSlukem 			ber_memvfree( (void **)refs );
2882de962bdSlukem 		}
2892de962bdSlukem 	}
2902de962bdSlukem }
2912de962bdSlukem 
2922de962bdSlukem void
tester_perror(const char * fname,const char * msg)2932de962bdSlukem tester_perror( const char *fname, const char *msg )
2942de962bdSlukem {
2952de962bdSlukem 	int	save_errno = errno;
2962de962bdSlukem 	char	buf[ BUFSIZ ];
2972de962bdSlukem 
2982de962bdSlukem 	fprintf( stderr, "%s: %s: (%d) %s %s\n",
2992de962bdSlukem 			progname, fname, save_errno,
3002de962bdSlukem 			AC_STRERROR_R( save_errno, buf, sizeof( buf ) ),
3012de962bdSlukem 			msg ? msg : "" );
3022de962bdSlukem }
3032de962bdSlukem 
304*549b59edSchristos int
tester_config_opt(struct tester_conn_args * config,char opt,char * optarg)305*549b59edSchristos tester_config_opt( struct tester_conn_args *config, char opt, char *optarg )
306*549b59edSchristos {
307*549b59edSchristos 	switch ( opt ) {
308*549b59edSchristos 		case 'C':
309*549b59edSchristos 			config->chaserefs++;
310*549b59edSchristos 			break;
311*549b59edSchristos 
312*549b59edSchristos 		case 'D':
313*549b59edSchristos 			config->binddn = optarg;
314*549b59edSchristos 			break;
315*549b59edSchristos 
316*549b59edSchristos 		case 'd':
317*549b59edSchristos 			{
318*549b59edSchristos 				if ( lutil_atoi( &debug, optarg ) != 0 ) {
319*549b59edSchristos 					return -1;
320*549b59edSchristos 				}
321*549b59edSchristos 
322*549b59edSchristos 				if ( ber_set_option( NULL, LBER_OPT_DEBUG_LEVEL, &debug )
323*549b59edSchristos 					!= LBER_OPT_SUCCESS )
324*549b59edSchristos 				{
325*549b59edSchristos 					fprintf( stderr,
326*549b59edSchristos 						"Could not set LBER_OPT_DEBUG_LEVEL %d\n", debug );
327*549b59edSchristos 				}
328*549b59edSchristos 
329*549b59edSchristos 				if ( ldap_set_option( NULL, LDAP_OPT_DEBUG_LEVEL, &debug )
330*549b59edSchristos 					!= LDAP_OPT_SUCCESS )
331*549b59edSchristos 				{
332*549b59edSchristos 					fprintf( stderr,
333*549b59edSchristos 						"Could not set LDAP_OPT_DEBUG_LEVEL %d\n", debug );
334*549b59edSchristos 				}
335*549b59edSchristos 				break;
336*549b59edSchristos 			}
337*549b59edSchristos 
338*549b59edSchristos 		case 'H':
339*549b59edSchristos 			config->uri = optarg;
340*549b59edSchristos 			break;
341*549b59edSchristos 
342*549b59edSchristos 		case 'i':
343*549b59edSchristos 			tester_ignore_str2errlist( optarg );
344*549b59edSchristos 			break;
345*549b59edSchristos 
346*549b59edSchristos 		case 'L':
347*549b59edSchristos 			if ( lutil_atoi( &config->outerloops, optarg ) != 0 ) {
348*549b59edSchristos 				return -1;
349*549b59edSchristos 			}
350*549b59edSchristos 			break;
351*549b59edSchristos 
352*549b59edSchristos 		case 'l':
353*549b59edSchristos 			if ( lutil_atoi( &config->loops, optarg ) != 0 ) {
354*549b59edSchristos 				return -1;
355*549b59edSchristos 			}
356*549b59edSchristos 			break;
357*549b59edSchristos 
358*549b59edSchristos #ifdef HAVE_CYRUS_SASL
359*549b59edSchristos 		case 'O':
360*549b59edSchristos 			if ( config->secprops != NULL ) {
361*549b59edSchristos 				return -1;
362*549b59edSchristos 			}
363*549b59edSchristos 			if ( config->authmethod != -1 && config->authmethod != LDAP_AUTH_SASL ) {
364*549b59edSchristos 				return -1;
365*549b59edSchristos 			}
366*549b59edSchristos 			config->authmethod = LDAP_AUTH_SASL;
367*549b59edSchristos 			config->secprops = optarg;
368*549b59edSchristos 			break;
369*549b59edSchristos 
370*549b59edSchristos 		case 'R':
371*549b59edSchristos 			if ( config->realm != NULL ) {
372*549b59edSchristos 				return -1;
373*549b59edSchristos 			}
374*549b59edSchristos 			if ( config->authmethod != -1 && config->authmethod != LDAP_AUTH_SASL ) {
375*549b59edSchristos 				return -1;
376*549b59edSchristos 			}
377*549b59edSchristos 			config->authmethod = LDAP_AUTH_SASL;
378*549b59edSchristos 			config->realm = optarg;
379*549b59edSchristos 			break;
380*549b59edSchristos 
381*549b59edSchristos 		case 'U':
382*549b59edSchristos 			if ( config->authc_id != NULL ) {
383*549b59edSchristos 				return -1;
384*549b59edSchristos 			}
385*549b59edSchristos 			if ( config->authmethod != -1 && config->authmethod != LDAP_AUTH_SASL ) {
386*549b59edSchristos 				return -1;
387*549b59edSchristos 			}
388*549b59edSchristos 			config->authmethod = LDAP_AUTH_SASL;
389*549b59edSchristos 			config->authc_id = optarg;
390*549b59edSchristos 			break;
391*549b59edSchristos 
392*549b59edSchristos 		case 'X':
393*549b59edSchristos 			if ( config->authz_id != NULL ) {
394*549b59edSchristos 				return -1;
395*549b59edSchristos 			}
396*549b59edSchristos 			if ( config->authmethod != -1 && config->authmethod != LDAP_AUTH_SASL ) {
397*549b59edSchristos 				return -1;
398*549b59edSchristos 			}
399*549b59edSchristos 			config->authmethod = LDAP_AUTH_SASL;
400*549b59edSchristos 			config->authz_id = optarg;
401*549b59edSchristos 			break;
402*549b59edSchristos 
403*549b59edSchristos 		case 'Y':
404*549b59edSchristos 			if ( config->mech != NULL ) {
405*549b59edSchristos 				return -1;
406*549b59edSchristos 			}
407*549b59edSchristos 			if ( config->authmethod != -1 && config->authmethod != LDAP_AUTH_SASL ) {
408*549b59edSchristos 				return -1;
409*549b59edSchristos 			}
410*549b59edSchristos 			config->authmethod = LDAP_AUTH_SASL;
411*549b59edSchristos 			config->mech = optarg;
412*549b59edSchristos 			break;
413*549b59edSchristos #endif
414*549b59edSchristos 
415*549b59edSchristos 		case 'r':
416*549b59edSchristos 			if ( lutil_atoi( &config->retries, optarg ) != 0 ) {
417*549b59edSchristos 				return -1;
418*549b59edSchristos 			}
419*549b59edSchristos 			break;
420*549b59edSchristos 
421*549b59edSchristos 		case 't':
422*549b59edSchristos 			if ( lutil_atoi( &config->delay, optarg ) != 0 ) {
423*549b59edSchristos 				return -1;
424*549b59edSchristos 			}
425*549b59edSchristos 			break;
426*549b59edSchristos 
427*549b59edSchristos 		case 'w':
428*549b59edSchristos 			config->pass.bv_val = strdup( optarg );
429*549b59edSchristos 			config->pass.bv_len = strlen( optarg );
430*549b59edSchristos 			memset( optarg, '*', config->pass.bv_len );
431*549b59edSchristos 			break;
432*549b59edSchristos 
433*549b59edSchristos 		case 'x':
434*549b59edSchristos 			if ( config->authmethod != -1 && config->authmethod != LDAP_AUTH_SIMPLE ) {
435*549b59edSchristos 				return -1;
436*549b59edSchristos 			}
437*549b59edSchristos 			config->authmethod = LDAP_AUTH_SIMPLE;
438*549b59edSchristos 			break;
439*549b59edSchristos 
440*549b59edSchristos 		default:
441*549b59edSchristos 			return -1;
442*549b59edSchristos 	}
443*549b59edSchristos 
444*549b59edSchristos 	return LDAP_SUCCESS;
445*549b59edSchristos }
446*549b59edSchristos 
447*549b59edSchristos void
tester_config_finish(struct tester_conn_args * config)448*549b59edSchristos tester_config_finish( struct tester_conn_args *config )
449*549b59edSchristos {
450*549b59edSchristos 	if ( config->authmethod == -1 ) {
451*549b59edSchristos #ifdef HAVE_CYRUS_SASL
452*549b59edSchristos 		if ( config->binddn != NULL ) {
453*549b59edSchristos 			config->authmethod = LDAP_AUTH_SIMPLE;
454*549b59edSchristos 		} else {
455*549b59edSchristos 			config->authmethod = LDAP_AUTH_SASL;
456*549b59edSchristos 		}
457*549b59edSchristos #else
458*549b59edSchristos 		config->authmethod = LDAP_AUTH_SIMPLE;
459*549b59edSchristos #endif
460*549b59edSchristos 	}
461*549b59edSchristos 
462*549b59edSchristos #ifdef HAVE_CYRUS_SASL
463*549b59edSchristos 	if ( config->authmethod == LDAP_AUTH_SASL ) {
464*549b59edSchristos 		config->defaults = lutil_sasl_defaults( NULL,
465*549b59edSchristos 			config->mech,
466*549b59edSchristos 			config->realm,
467*549b59edSchristos 			config->authc_id,
468*549b59edSchristos 			config->pass.bv_val,
469*549b59edSchristos 			config->authz_id );
470*549b59edSchristos 
471*549b59edSchristos 		if ( config->defaults == NULL ) {
472*549b59edSchristos 			tester_error( "unable to prepare SASL defaults" );
473*549b59edSchristos 			exit( EXIT_FAILURE );
474*549b59edSchristos 		}
475*549b59edSchristos 	}
476*549b59edSchristos #endif
477*549b59edSchristos }
478*549b59edSchristos 
479*549b59edSchristos void
tester_init_ld(LDAP ** ldp,struct tester_conn_args * config,int flags)480*549b59edSchristos tester_init_ld( LDAP **ldp, struct tester_conn_args *config, int flags )
481*549b59edSchristos {
482*549b59edSchristos 	LDAP *ld;
483*549b59edSchristos 	int rc, do_retry = config->retries;
484*549b59edSchristos 	int version = LDAP_VERSION3;
485*549b59edSchristos 
486*549b59edSchristos retry:;
487*549b59edSchristos 	ldap_initialize( &ld, config->uri );
488*549b59edSchristos 	if ( ld == NULL ) {
489*549b59edSchristos 		tester_perror( "ldap_initialize", NULL );
490*549b59edSchristos 		exit( EXIT_FAILURE );
491*549b59edSchristos 	}
492*549b59edSchristos 
493*549b59edSchristos 	(void) ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );
494*549b59edSchristos 	(void) ldap_set_option( ld, LDAP_OPT_REFERRALS,
495*549b59edSchristos 		config->chaserefs ? LDAP_OPT_ON: LDAP_OPT_OFF );
496*549b59edSchristos 
497*549b59edSchristos 	if ( !( flags & TESTER_INIT_ONLY ) ) {
498*549b59edSchristos 		if ( config->authmethod == LDAP_AUTH_SASL ) {
499*549b59edSchristos #ifdef HAVE_CYRUS_SASL
500*549b59edSchristos 			if ( config->secprops != NULL ) {
501*549b59edSchristos 				rc = ldap_set_option( ld,
502*549b59edSchristos 						LDAP_OPT_X_SASL_SECPROPS, config->secprops );
503*549b59edSchristos 
504*549b59edSchristos 				if ( rc != LDAP_OPT_SUCCESS ) {
505*549b59edSchristos 					tester_ldap_error( ld, "ldap_set_option(SECPROPS)", NULL );
506*549b59edSchristos 					ldap_unbind_ext( ld, NULL, NULL );
507*549b59edSchristos 					exit( EXIT_FAILURE );
508*549b59edSchristos 				}
509*549b59edSchristos 			}
510*549b59edSchristos 
511*549b59edSchristos 			rc = ldap_sasl_interactive_bind_s( ld,
512*549b59edSchristos 					config->binddn,
513*549b59edSchristos 					config->mech,
514*549b59edSchristos 					NULL, NULL,
515*549b59edSchristos 					LDAP_SASL_QUIET,
516*549b59edSchristos 					lutil_sasl_interact,
517*549b59edSchristos 					config->defaults );
518*549b59edSchristos #else /* HAVE_CYRUS_SASL */
519*549b59edSchristos 			/* caller shouldn't have allowed this */
520*549b59edSchristos 			assert(0);
521*549b59edSchristos #endif
522*549b59edSchristos 		} else if ( config->authmethod == LDAP_AUTH_SIMPLE ) {
523*549b59edSchristos 			rc = ldap_sasl_bind_s( ld,
524*549b59edSchristos 					config->binddn, LDAP_SASL_SIMPLE,
525*549b59edSchristos 					&config->pass, NULL, NULL, NULL );
526*549b59edSchristos 		}
527*549b59edSchristos 
528*549b59edSchristos 		if ( rc != LDAP_SUCCESS ) {
529*549b59edSchristos 			tester_ldap_error( ld, "ldap_sasl_bind_s", NULL );
530*549b59edSchristos 			switch ( rc ) {
531*549b59edSchristos 				case LDAP_BUSY:
532*549b59edSchristos 				case LDAP_UNAVAILABLE:
533*549b59edSchristos 					if ( do_retry > 0 ) {
534*549b59edSchristos 						do_retry--;
535*549b59edSchristos 						if ( config->delay > 0 ) {
536*549b59edSchristos 							sleep( config->delay );
537*549b59edSchristos 						}
538*549b59edSchristos 						goto retry;
539*549b59edSchristos 					}
540*549b59edSchristos 			}
541*549b59edSchristos 			ldap_unbind_ext( ld, NULL, NULL );
542*549b59edSchristos 			ld = NULL;
543*549b59edSchristos 			if ( !( flags & TESTER_INIT_NOEXIT ))
544*549b59edSchristos 				exit( EXIT_FAILURE );
545*549b59edSchristos 		}
546*549b59edSchristos 	}
547*549b59edSchristos 
548*549b59edSchristos 	*ldp = ld;
549*549b59edSchristos }
550*549b59edSchristos 
5512de962bdSlukem void
tester_error(const char * msg)5522de962bdSlukem tester_error( const char *msg )
5532de962bdSlukem {
5542de962bdSlukem 	fprintf( stderr, "%s: %s\n", progname, msg );
5552de962bdSlukem }
556