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