From b482396beffe1166b7237aa62af3656f1bd891c6 Mon Sep 17 00:00:00 2001
From: Kurt Zeilenga <kurt@openldap.org>
Date: Thu, 17 Nov 2005 21:29:41 +0000
Subject: [PATCH] Sync with HEAD

---
 servers/slapd/add.c             |  2 ++
 servers/slapd/back-ldap/chain.c |  4 +++
 servers/slapd/back-sql/search.c |  9 ++++---
 servers/slapd/bconfig.c         | 45 +++++++++++++++++++++++----------
 servers/slapd/config.c          |  5 ++++
 servers/slapd/modify.c          |  1 +
 servers/slapd/repl.c            |  5 +---
 servers/slapd/slap.h            |  2 +-
 servers/slapd/syncrepl.c        | 27 ++++++++++----------
 tests/scripts/sql-test000-read  | 43 +++++++++++++++++++++++++++++++
 10 files changed, 108 insertions(+), 35 deletions(-)

diff --git a/servers/slapd/add.c b/servers/slapd/add.c
index 896eae65ea..c35cafc96f 100644
--- a/servers/slapd/add.c
+++ b/servers/slapd/add.c
@@ -470,6 +470,7 @@ slap_mods2entry(
 			snprintf( textbuf, textlen,
 				"attribute '%s' provided more than once",
 				mods->sml_desc->ad_cname.bv_val );
+			*text = textbuf;
 			return LDAP_TYPE_OR_VALUE_EXISTS;
 #endif
 		}
@@ -500,6 +501,7 @@ slap_mods2entry(
 						snprintf( textbuf, textlen,
 							"%s: value #%d provided more than once",
 							mods->sml_desc->ad_cname.bv_val, j );
+						*text = textbuf;
 						return LDAP_TYPE_OR_VALUE_EXISTS;
 
 					} else if ( rc != LDAP_SUCCESS ) {
diff --git a/servers/slapd/back-ldap/chain.c b/servers/slapd/back-ldap/chain.c
index a0dbb581c2..3a582883c3 100644
--- a/servers/slapd/back-ldap/chain.c
+++ b/servers/slapd/back-ldap/chain.c
@@ -368,6 +368,7 @@ ldap_chain_response( Operation *op, SlapReply *rs )
 			sc2 = { 0 };
 	int		rc = 0;
 	int		cache = op->o_do_not_cache;
+	char		*matched;
 	BerVarray	ref;
 	struct berval	ndn = op->o_ndn;
 
@@ -423,6 +424,8 @@ ldap_chain_response( Operation *op, SlapReply *rs )
 	 *   e) what ssf
 	 */
 
+	matched = rs->sr_matched;
+	rs->sr_matched = NULL;
 	ref = rs->sr_ref;
 	rs->sr_ref = NULL;
 
@@ -626,6 +629,7 @@ dont_chain:;
 	op->o_bd->be_private = private;
 	op->o_callback = sc;
 	op->o_ndn = ndn;
+	rs->sr_matched = matched;
 	rs->sr_ref = ref;
 
 	ldap_pvt_thread_mutex_unlock( &lc->lc_mutex );
diff --git a/servers/slapd/back-sql/search.c b/servers/slapd/back-sql/search.c
index dcd349ffa7..2fe00acb2c 100644
--- a/servers/slapd/back-sql/search.c
+++ b/servers/slapd/back-sql/search.c
@@ -2305,6 +2305,11 @@ backsql_search( Operation *op, SlapReply *rs )
 
 		if ( test_filter( op, e, op->ors_filter ) == LDAP_COMPARE_TRUE )
 		{
+			if ( --op->ors_slimit == -1 ) {
+				rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
+				goto send_results;
+			}
+
 			rs->sr_attrs = op->ors_attrs;
 			rs->sr_operational_attrs = NULL;
 			rs->sr_entry = e;
@@ -2334,10 +2339,6 @@ next_entry:;
 		}
 
 next_entry2:;
-		if ( --op->ors_slimit == -1 ) {
-			rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
-			goto send_results;
-		}
 	}
 
 end_of_search:;
diff --git a/servers/slapd/bconfig.c b/servers/slapd/bconfig.c
index a1545a1cb6..688d6e815b 100644
--- a/servers/slapd/bconfig.c
+++ b/servers/slapd/bconfig.c
@@ -1067,12 +1067,14 @@ config_generic(ConfigArgs *c) {
 			break;
 
 		case CFG_THREADS:
-			ldap_pvt_thread_pool_maxthreads(&connection_pool, c->value_int);
+			if ( slapMode & SLAP_SERVER_MODE )
+				ldap_pvt_thread_pool_maxthreads(&connection_pool, c->value_int);
 			connection_pool_max = c->value_int;	/* save for reference */
 			break;
 
 		case CFG_TTHREADS:
-			ldap_pvt_thread_pool_maxthreads(&connection_pool, c->value_int);
+			if ( slapMode & SLAP_TOOL_MODE )
+				ldap_pvt_thread_pool_maxthreads(&connection_pool, c->value_int);
 			slap_tool_thread_max = c->value_int;	/* save for reference */
 			break;
 
@@ -2337,6 +2339,8 @@ replica_unparse( struct slap_replica_info *ri, int i, struct berval *bv )
 	struct berval bc = BER_BVNULL;
 	char numbuf[32];
 
+	assert( !BER_BVISNULL( &ri->ri_bindconf.sb_uri ) );
+	
 	BER_BVZERO( bv );
 
 	len = snprintf(numbuf, sizeof( numbuf ), SLAP_X_ORDERED_FMT, i );
@@ -2345,14 +2349,13 @@ replica_unparse( struct slap_replica_info *ri, int i, struct berval *bv )
 		return;
 	}
 
-	len += strlen( ri->ri_uri ) + STRLENOF("uri=");
 	if ( ri->ri_nsuffix ) {
 		for (i=0; !BER_BVISNULL( &ri->ri_nsuffix[i] ); i++) {
 			len += ri->ri_nsuffix[i].bv_len + STRLENOF(" suffix=\"\"");
 		}
 	}
 	if ( ri->ri_attrs ) {
-		len += STRLENOF("attr");
+		len += STRLENOF(" attrs");
 		if ( ri->ri_exclude ) len++;
 		for (i=0; !BER_BVISNULL( &ri->ri_attrs[i].an_name ); i++) {
 			len += 1 + ri->ri_attrs[i].an_name.bv_len;
@@ -2365,8 +2368,13 @@ replica_unparse( struct slap_replica_info *ri, int i, struct berval *bv )
 	bv->bv_len = len;
 
 	ptr = lutil_strcopy( bv->bv_val, numbuf );
-	ptr = lutil_strcopy( ptr, "uri=" );
-	ptr = lutil_strcopy( ptr, ri->ri_uri );
+
+	/* start with URI from bindconf */
+	assert( !BER_BVISNULL( &bc ) );
+	if ( bc.bv_val ) {
+		strcpy( ptr, bc.bv_val );
+		ch_free( bc.bv_val );
+	}
 
 	if ( ri->ri_nsuffix ) {
 		for (i=0; !BER_BVISNULL( &ri->ri_nsuffix[i] ); i++) {
@@ -2376,15 +2384,11 @@ replica_unparse( struct slap_replica_info *ri, int i, struct berval *bv )
 		}
 	}
 	if ( ri->ri_attrs ) {
-		ptr = lutil_strcopy( ptr, "attr" );
+		ptr = lutil_strcopy( ptr, " attrs" );
 		if ( ri->ri_exclude ) *ptr++ = '!';
 		*ptr++ = '=';
 		ptr = anlist_unparse( ri->ri_attrs, ptr );
 	}
-	if ( bc.bv_val ) {
-		strcpy( ptr, bc.bv_val );
-		ch_free( bc.bv_val );
-	}
 }
 
 static int
@@ -2472,7 +2476,11 @@ config_replica(ConfigArgs *c) {
 		return(1);
 	} else {
 		for(i = 1; i < c->argc; i++) {
-			if(!strncasecmp(c->argv[i], "suffix=", STRLENOF( "suffix="))) {
+			if(!strncasecmp(c->argv[i], "uri=", STRLENOF("uri="))) {
+				/* dealt with separately; don't let it get to bindconf */
+				;
+
+			} else if(!strncasecmp(c->argv[i], "suffix=", STRLENOF( "suffix="))) {
 				switch(add_replica_suffix(c->be, nr, c->argv[i] + STRLENOF("suffix="))) {
 					case 1:
 						Debug( SLAPD_DEBUG_CONFIG_ERROR, "%s: "
@@ -2494,9 +2502,20 @@ config_replica(ConfigArgs *c) {
 						break;
 				}
 
-			} else if(!strncasecmp(c->argv[i], "attr", STRLENOF("attr"))) {
+			} else if (!strncasecmp(c->argv[i], "attr", STRLENOF("attr"))
+				|| !strncasecmp(c->argv[i], "attrs", STRLENOF("attrs")))
+			{
 				int exclude = 0;
 				char *arg = c->argv[i] + STRLENOF("attr");
+				if (arg[0] == 's') {
+					arg++;
+				} else {
+					Debug( LDAP_DEBUG_ANY,
+						"%s: \"attr\" "
+						"is deprecated (and undocumented); "
+						"use \"attrs\" instead.\n",
+						c->log, 0, 0 );
+				}
 				if(arg[0] == '!') {
 					arg++;
 					exclude = 1;
diff --git a/servers/slapd/config.c b/servers/slapd/config.c
index da85ee01ab..cbc9f21ec6 100644
--- a/servers/slapd/config.c
+++ b/servers/slapd/config.c
@@ -992,6 +992,7 @@ static slap_verbmasks methkey[] = {
 };
 
 static slap_cf_aux_table bindkey[] = {
+	{ BER_BVC("uri="), offsetof(slap_bindconf, sb_uri), 'b', 1, NULL },
 	{ BER_BVC("starttls="), offsetof(slap_bindconf, sb_tls), 'd', 0, tlskey },
 	{ BER_BVC("bindmethod="), offsetof(slap_bindconf, sb_method), 'd', 0, methkey },
 	{ BER_BVC("binddn="), offsetof(slap_bindconf, sb_binddn), 'b', 1, NULL },
@@ -1151,6 +1152,10 @@ bindconf_unparse( slap_bindconf *bc, struct berval *bv )
 }
 
 void bindconf_free( slap_bindconf *bc ) {
+	if ( !BER_BVISNULL( &bc->sb_uri ) ) {
+		ch_free( bc->sb_uri.bv_val );
+		BER_BVZERO( &bc->sb_uri );
+	}
 	if ( !BER_BVISNULL( &bc->sb_binddn ) ) {
 		ch_free( bc->sb_binddn.bv_val );
 		BER_BVZERO( &bc->sb_binddn );
diff --git a/servers/slapd/modify.c b/servers/slapd/modify.c
index c9c594474f..90c7d3c3a0 100644
--- a/servers/slapd/modify.c
+++ b/servers/slapd/modify.c
@@ -525,6 +525,7 @@ slap_mods_no_repl_user_mod_check(
 				snprintf( textbuf, textlen,
 					"attribute '%s' provided more than once",
 					mods->sml_desc->ad_cname.bv_val );
+				*text = textbuf;
 				return LDAP_TYPE_OR_VALUE_EXISTS;
 			}
 		}
diff --git a/servers/slapd/repl.c b/servers/slapd/repl.c
index 8931915219..73b3c8ca96 100644
--- a/servers/slapd/repl.c
+++ b/servers/slapd/repl.c
@@ -59,7 +59,7 @@ add_replica_info(
 
 	be->be_replica[ i ] 
 		= ch_calloc( sizeof( struct slap_replica_info ), 1 );
-	be->be_replica[ i ]->ri_uri = uri;
+	ber_str2bv( uri, 0, 0, &be->be_replica[ i ]->ri_bindconf.sb_uri );
 	be->be_replica[ i ]->ri_host = host;
 	be->be_replica[ i ]->ri_nsuffix = NULL;
 	be->be_replica[ i ]->ri_attrs = NULL;
@@ -81,9 +81,6 @@ destroy_replica_info(
 	}
 
 	for ( ; be->be_replica[ i ] != NULL; i++ ) {
-
-		ch_free( (char *)be->be_replica[ i ]->ri_uri );
-
 		ber_bvarray_free( be->be_replica[ i ]->ri_nsuffix );
 
 		if ( be->be_replica[ i ]->ri_attrs ) {
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index 1d81e8abaa..5f280d3663 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -1543,6 +1543,7 @@ LDAP_SLAPD_V (int) slapMode;
 #define SB_TLS_CRITICAL		2
 
 typedef struct slap_bindconf {
+	struct berval sb_uri;
 	int sb_tls;
 	int sb_method;
 	struct berval sb_binddn;
@@ -1555,7 +1556,6 @@ typedef struct slap_bindconf {
 } slap_bindconf;
 
 struct slap_replica_info {
-	const char *ri_uri;			/* supersedes be_replica */
 	const char *ri_host;		/* points to host part of uri */
 	BerVarray ri_nsuffix;		/* array of suffixes this replica accepts */
 	AttributeName *ri_attrs;	/* attrs to replicate, NULL=all */
diff --git a/servers/slapd/syncrepl.c b/servers/slapd/syncrepl.c
index b694ee2091..a801e54a7c 100644
--- a/servers/slapd/syncrepl.c
+++ b/servers/slapd/syncrepl.c
@@ -48,7 +48,6 @@ typedef struct syncinfo_s {
 	struct slap_backend_db *si_be;
 	struct re_s			*si_re;
 	long				si_rid;
-	struct berval		si_provideruri;
 	slap_bindconf		si_bindconf;
 	struct berval		si_base;
 	struct berval		si_logbase;
@@ -420,11 +419,11 @@ do_syncrep1(
 	psub = &si->si_be->be_nsuffix[0];
 
 	/* Init connection to master */
-	rc = ldap_initialize( &si->si_ld, si->si_provideruri.bv_val );
+	rc = ldap_initialize( &si->si_ld, si->si_bindconf.sb_uri.bv_val );
 	if ( rc != LDAP_SUCCESS ) {
 		Debug( LDAP_DEBUG_ANY,
 			"do_syncrep1: ldap_initialize failed (%s)\n",
-			si->si_provideruri.bv_val, 0, 0 );
+			si->si_bindconf.sb_uri.bv_val, 0, 0 );
 		return rc;
 	}
 
@@ -455,7 +454,7 @@ do_syncrep1(
 			if( rc != LDAP_OPT_SUCCESS ) {
 				Debug( LDAP_DEBUG_ANY, "Error: ldap_set_option "
 					"(%s,SECPROPS,\"%s\") failed!\n",
-					si->si_provideruri.bv_val, si->si_bindconf.sb_secprops, 0 );
+					si->si_bindconf.sb_uri.bv_val, si->si_bindconf.sb_secprops, 0 );
 				goto done;
 			}
 		}
@@ -2559,9 +2558,6 @@ void
 syncinfo_free( syncinfo_t *sie )
 {
  	ldap_pvt_thread_mutex_destroy( &sie->si_mutex );
-	if ( !BER_BVISNULL( &sie->si_provideruri ) ) {
-		ch_free( sie->si_provideruri.bv_val );
-	}
 
 	bindconf_free( &sie->si_bindconf );
 
@@ -2733,7 +2729,7 @@ parse_syncrepl_line(
 					STRLENOF( PROVIDERSTR "=" ) ) )
 		{
 			val = cargv[ i ] + STRLENOF( PROVIDERSTR "=" );
-			ber_str2bv( val, 0, 1, &si->si_provideruri );
+			ber_str2bv( val, 0, 1, &si->si_bindconf.sb_uri );
 			gots |= GOT_PROVIDER;
 		} else if ( !strncasecmp( cargv[ i ], SCHEMASTR "=",
 					STRLENOF( SCHEMASTR "=" ) ) )
@@ -3091,8 +3087,8 @@ add_syncrepl(
 	} else {
 		Debug( LDAP_DEBUG_CONFIG,
 			"Config: ** successfully added syncrepl \"%s\"\n",
-			BER_BVISNULL( &si->si_provideruri ) ?
-			"(null)" : si->si_provideruri.bv_val, 0, 0 );
+			BER_BVISNULL( &si->si_bindconf.sb_uri ) ?
+			"(null)" : si->si_bindconf.sb_uri.bv_val, 0, 0 );
 		if ( !si->si_schemachecking ) {
 			SLAP_DBFLAGS(be) |= SLAP_DBFLAG_NO_SCHEMA_CHECK;
 		}
@@ -3104,14 +3100,19 @@ add_syncrepl(
 static void
 syncrepl_unparse( syncinfo_t *si, struct berval *bv )
 {
-	struct berval bc;
+	struct berval bc, uri;
 	char buf[BUFSIZ*2], *ptr;
 	int i;
 
+	/* temporarily inhibit bindconf from printing URI */
+	uri = si->si_bindconf.sb_uri;
+	BER_BVZERO( &si->si_bindconf.sb_uri );
 	bindconf_unparse( &si->si_bindconf, &bc );
+	si->si_bindconf.sb_uri = uri;
+
 	ptr = buf;
-	ptr += sprintf( ptr, IDSTR "=%03ld " PROVIDERSTR "=%s",
-		si->si_rid, si->si_provideruri.bv_val );
+	ptr += snprintf( ptr, sizeof( buf ), IDSTR "=%03ld " PROVIDERSTR "=%s",
+		si->si_rid, si->si_bindconf.sb_uri.bv_val );
 	if ( !BER_BVISNULL( &bc )) {
 		ptr = lutil_strcopy( ptr, bc.bv_val );
 		free( bc.bv_val );
diff --git a/tests/scripts/sql-test000-read b/tests/scripts/sql-test000-read
index 4bad573eb4..ed1b40d15e 100755
--- a/tests/scripts/sql-test000-read
+++ b/tests/scripts/sql-test000-read
@@ -412,6 +412,49 @@ fi
 
 grep -v '^entryCSN:' $SEARCHFLT >> $SEARCHOUT 
 
+SIZELIMIT=4
+echo "Testing size limit..."
+$LDAPRSEARCH -h $LOCALHOST -p $PORT1 -b "$BASEDN" \
+	-z $SIZELIMIT -S "" '(objectClass=*)' >$SEARCHFLT 2>&1
+RC=$?
+COUNT=`awk '/^# numEntries:/ {print $3}' $SEARCHFLT`
+case $RC in
+	0)
+		if test x"$COUNT" != x ; then
+			if test "$COUNT" -gt "$SIZELIMIT" ; then
+				echo "...error: got $COUNT entries instead of the requested $SIZELIMIT"
+				test $KILLSERVERS != no && kill -HUP $KILLPIDS
+				exit 1
+			fi
+			echo "...didn't bump into the requested size limit ($SIZELIMIT; got $COUNT entries)"
+		else
+			echo "...error: did not expect ldapsearch success ($RC)!"
+			test $KILLSERVERS != no && kill -HUP $KILLPIDS
+			exit 1
+		fi
+	;;
+	4)
+		if test x"$COUNT" != x ; then
+			if test "$COUNT" = "$SIZELIMIT" ; then
+				echo "...bumped into requested size limit ($SIZELIMIT)"
+			else
+				echo "...error: got $COUNT entries with a requested sizelimit of $SIZELIMIT"
+				test $KILLSERVERS != no && kill -HUP $KILLPIDS
+				exit $RC
+			fi
+		else
+			echo "...error: bumped into server-side size limit, but got no entries!"
+                        test $KILLSERVERS != no && kill -HUP $KILLPIDS
+                        exit $RC
+		fi
+	;;
+	*)
+		echo "ldapsearch failed ($RC)!"
+		test $KILLSERVERS != no && kill -HUP $KILLPIDS
+		exit $RC
+	;;
+esac
+
 echo -n "Testing compare (should be TRUE)... "
 $LDAPCOMPARE -h $LOCALHOST -p $PORT1 "$BINDDN" \
 	 "sn:kovalev" >> $TESTOUT 2>&1
-- 
GitLab