xref: /netbsd-src/external/bsd/openldap/dist/servers/slapd/back-meta/search.c (revision 549b59ed3ccf0d36d3097190a0db27b770f3a839)
1 /*	$NetBSD: search.c,v 1.3 2021/08/14 16:15:00 christos Exp $	*/
2 
3 /* $OpenLDAP$ */
4 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5  *
6  * Copyright 1999-2021 The OpenLDAP Foundation.
7  * Portions Copyright 2001-2003 Pierangelo Masarati.
8  * Portions Copyright 1999-2003 Howard Chu.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted only as authorized by the OpenLDAP
13  * Public License.
14  *
15  * A copy of this license is available in the file LICENSE in the
16  * top-level directory of the distribution or, alternatively, at
17  * <http://www.OpenLDAP.org/license.html>.
18  */
19 /* ACKNOWLEDGEMENTS:
20  * This work was initially developed by the Howard Chu for inclusion
21  * in OpenLDAP Software and subsequently enhanced by Pierangelo
22  * Masarati.
23  */
24 
25 #include <sys/cdefs.h>
26 __RCSID("$NetBSD: search.c,v 1.3 2021/08/14 16:15:00 christos Exp $");
27 
28 #include "portable.h"
29 
30 #include <stdio.h>
31 
32 #include <ac/socket.h>
33 #include <ac/string.h>
34 #include <ac/time.h>
35 
36 #include "lutil.h"
37 #include "slap.h"
38 #include "../back-ldap/back-ldap.h"
39 #include "back-meta.h"
40 #include "../../../libraries/liblber/lber-int.h"
41 
42 /* IGNORE means that target does not (no longer) participate
43  * in the search;
44  * NOTREADY means the search on that target has not been initialized yet
45  */
46 #define	META_MSGID_IGNORE	(-1)
47 #define	META_MSGID_NEED_BIND	(-2)
48 #define	META_MSGID_CONNECTING	(-3)
49 
50 static int
51 meta_send_entry(
52 	Operation 	*op,
53 	SlapReply	*rs,
54 	metaconn_t	*mc,
55 	int 		i,
56 	LDAPMessage 	*e );
57 
58 typedef enum meta_search_candidate_t {
59 	META_SEARCH_UNDEFINED = -2,
60 	META_SEARCH_ERR = -1,
61 	META_SEARCH_NOT_CANDIDATE,
62 	META_SEARCH_CANDIDATE,
63 	META_SEARCH_BINDING,
64 	META_SEARCH_NEED_BIND,
65 	META_SEARCH_CONNECTING
66 } meta_search_candidate_t;
67 
68 /*
69  * meta_search_dobind_init()
70  *
71  * initiates bind for a candidate target of a search.
72  */
73 static meta_search_candidate_t
meta_search_dobind_init(Operation * op,SlapReply * rs,metaconn_t ** mcp,int candidate,SlapReply * candidates)74 meta_search_dobind_init(
75 	Operation		*op,
76 	SlapReply		*rs,
77 	metaconn_t		**mcp,
78 	int			candidate,
79 	SlapReply		*candidates )
80 {
81 	metaconn_t		*mc = *mcp;
82 	metainfo_t		*mi = ( metainfo_t * )op->o_bd->be_private;
83 	metatarget_t		*mt = mi->mi_targets[ candidate ];
84 	metasingleconn_t	*msc = &mc->mc_conns[ candidate ];
85 
86 	struct berval		binddn = msc->msc_bound_ndn,
87 				cred = msc->msc_cred;
88 	int			method;
89 
90 	int			rc;
91 
92 	meta_search_candidate_t	retcode;
93 
94 	Debug( LDAP_DEBUG_TRACE, "%s >>> meta_search_dobind_init[%d]\n",
95 		op->o_log_prefix, candidate );
96 
97 	/*
98 	 * all the targets are already bound as pseudoroot
99 	 */
100 	if ( mc->mc_authz_target == META_BOUND_ALL ) {
101 		return META_SEARCH_CANDIDATE;
102 	}
103 
104 	retcode = META_SEARCH_BINDING;
105 	ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
106 	if ( LDAP_BACK_CONN_ISBOUND( msc ) || LDAP_BACK_CONN_ISANON( msc ) ) {
107 		/* already bound (or anonymous) */
108 
109 #ifdef DEBUG_205
110 		int	bound = 0;
111 
112 		if ( LDAP_BACK_CONN_ISBOUND( msc ) ) {
113 			bound = 1;
114 		}
115 
116 		Debug(LDAP_DEBUG_ANY,
117 		      "### %s meta_search_dobind_init[%d] mc=%p ld=%p%s DN=\"%s\"\n",
118 		      op->o_log_prefix, candidate, (void *)mc,
119 		      (void *)msc->msc_ld, bound ? " bound" : " anonymous",
120 		      bound == 0 ? "" : msc->msc_bound_ndn.bv_val );
121 #endif /* DEBUG_205 */
122 
123 		retcode = META_SEARCH_CANDIDATE;
124 
125 	} else if ( META_BACK_CONN_CREATING( msc ) || LDAP_BACK_CONN_BINDING( msc ) ) {
126 		/* another thread is binding the target for this conn; wait */
127 
128 #ifdef DEBUG_205
129 		Debug(LDAP_DEBUG_ANY,
130 		      "### %s meta_search_dobind_init[%d] mc=%p ld=%p needbind\n",
131 		      op->o_log_prefix, candidate, (void *)mc,
132 		      (void *)msc->msc_ld );
133 #endif /* DEBUG_205 */
134 
135 		candidates[ candidate ].sr_msgid = META_MSGID_NEED_BIND;
136 		retcode = META_SEARCH_NEED_BIND;
137 
138 	} else {
139 		/* we'll need to bind the target for this conn */
140 
141 #ifdef DEBUG_205
142 		Debug(LDAP_DEBUG_ANY,
143 		      "### %s meta_search_dobind_init[%d] mc=%p ld=%p binding\n",
144 		      op->o_log_prefix, candidate, (void *)mc,
145 		      (void *)msc->msc_ld );
146 #endif /* DEBUG_205 */
147 
148 		if ( msc->msc_ld == NULL ) {
149 			/* for some reason (e.g. because formerly in "binding"
150 			 * state, with eventual connection expiration or invalidation)
151 			 * it was not initialized as expected */
152 
153 			Debug( LDAP_DEBUG_ANY, "%s meta_search_dobind_init[%d] mc=%p ld=NULL\n",
154 				op->o_log_prefix, candidate, (void *)mc );
155 
156 			rc = meta_back_init_one_conn( op, rs, *mcp, candidate,
157 				LDAP_BACK_CONN_ISPRIV( *mcp ), LDAP_BACK_DONTSEND, 0 );
158 			switch ( rc ) {
159 			case LDAP_SUCCESS:
160 				assert( msc->msc_ld != NULL );
161 				break;
162 
163 			case LDAP_SERVER_DOWN:
164 			case LDAP_UNAVAILABLE:
165 				ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
166 				goto down;
167 
168 			default:
169 				ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
170 				goto other;
171 			}
172 		}
173 
174 		LDAP_BACK_CONN_BINDING_SET( msc );
175 	}
176 
177 	ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
178 
179 	if ( retcode != META_SEARCH_BINDING ) {
180 		return retcode;
181 	}
182 
183 	/* NOTE: this obsoletes pseudorootdn */
184 	if ( op->o_conn != NULL &&
185 		!op->o_do_not_cache &&
186 		( BER_BVISNULL( &msc->msc_bound_ndn ) ||
187 			BER_BVISEMPTY( &msc->msc_bound_ndn ) ||
188 			( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
189 	{
190 		rc = meta_back_proxy_authz_cred( mc, candidate, op, rs, LDAP_BACK_DONTSEND, &binddn, &cred, &method );
191 		switch ( rc ) {
192 		case LDAP_SUCCESS:
193 			break;
194 		case LDAP_UNAVAILABLE:
195 			goto down;
196 		default:
197 			goto other;
198 		}
199 
200 		/* NOTE: we copy things here, even if bind didn't succeed yet,
201 		 * because the connection is not shared until bind is over */
202 		if ( !BER_BVISNULL( &binddn ) ) {
203 			ber_bvreplace( &msc->msc_bound_ndn, &binddn );
204 			if ( META_BACK_TGT_SAVECRED( mt ) && !BER_BVISNULL( &cred ) ) {
205 				if ( !BER_BVISNULL( &msc->msc_cred ) ) {
206 					memset( msc->msc_cred.bv_val, 0,
207 						msc->msc_cred.bv_len );
208 				}
209 				ber_bvreplace( &msc->msc_cred, &cred );
210 			}
211 		}
212 
213 		if ( LDAP_BACK_CONN_ISBOUND( msc ) ) {
214 			/* apparently, idassert was configured with SASL bind,
215 			 * so bind occurred inside meta_back_proxy_authz_cred() */
216 			ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
217 			LDAP_BACK_CONN_BINDING_CLEAR( msc );
218 			ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
219 			return META_SEARCH_CANDIDATE;
220 		}
221 
222 		/* paranoid */
223 		switch ( method ) {
224 		case LDAP_AUTH_NONE:
225 		case LDAP_AUTH_SIMPLE:
226 			/* do a simple bind with binddn, cred */
227 			break;
228 
229 		default:
230 			assert( 0 );
231 			break;
232 		}
233 	}
234 
235 	assert( msc->msc_ld != NULL );
236 
237 	/* connect must be async only the first time... */
238 	ldap_set_option( msc->msc_ld, LDAP_OPT_CONNECT_ASYNC, LDAP_OPT_ON );
239 
240 retry:;
241 	if ( !BER_BVISEMPTY( &binddn ) && BER_BVISEMPTY( &cred ) ) {
242 		/* bind anonymously? */
243 		Debug( LDAP_DEBUG_ANY, "%s meta_search_dobind_init[%d] mc=%p: "
244 			"non-empty dn with empty cred; binding anonymously\n",
245 			op->o_log_prefix, candidate, (void *)mc );
246 		cred = slap_empty_bv;
247 
248 	} else if ( BER_BVISEMPTY( &binddn ) && !BER_BVISEMPTY( &cred ) ) {
249 		/* error */
250 		Debug( LDAP_DEBUG_ANY, "%s meta_search_dobind_init[%d] mc=%p: "
251 			"empty dn with non-empty cred: error\n",
252 			op->o_log_prefix, candidate, (void *)mc );
253 		rc = LDAP_OTHER;
254 		goto other;
255 	}
256 
257 	rc = ldap_sasl_bind( msc->msc_ld, binddn.bv_val, LDAP_SASL_SIMPLE, &cred,
258 			NULL, NULL, &candidates[ candidate ].sr_msgid );
259 
260 #ifdef DEBUG_205
261 	Debug(LDAP_DEBUG_ANY,
262 	      "### %s meta_search_dobind_init[%d] mc=%p ld=%p rc=%d\n",
263 	      op->o_log_prefix, candidate, (void *)mc,
264 	      (void *)mc->mc_conns[candidate].msc_ld, rc );
265 #endif /* DEBUG_205 */
266 
267 	switch ( rc ) {
268 	case LDAP_SUCCESS:
269 		assert( candidates[ candidate ].sr_msgid >= 0 );
270 		META_BINDING_SET( &candidates[ candidate ] );
271 		return META_SEARCH_BINDING;
272 
273 	case LDAP_X_CONNECTING:
274 		/* must retry, same conn */
275 		candidates[ candidate ].sr_msgid = META_MSGID_CONNECTING;
276 		ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
277 		LDAP_BACK_CONN_BINDING_CLEAR( msc );
278 		ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
279 		return META_SEARCH_CONNECTING;
280 
281 	case LDAP_SERVER_DOWN:
282 down:;
283 		/* This is the worst thing that could happen:
284 		 * the search will wait until the retry is over. */
285 		if ( !META_IS_RETRYING( &candidates[ candidate ] ) ) {
286 			META_RETRYING_SET( &candidates[ candidate ] );
287 
288 			ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
289 
290 			assert( mc->mc_refcnt > 0 );
291 			if ( LogTest( LDAP_DEBUG_ANY ) ) {
292 				/* this lock is required; however,
293 				 * it's invoked only when logging is on */
294 				ldap_pvt_thread_mutex_lock( &mt->mt_uri_mutex );
295 				Debug(LDAP_DEBUG_ANY,
296 				      "%s meta_search_dobind_init[%d]: retrying URI=\"%s\" DN=\"%s\".\n",
297 				      op->o_log_prefix, candidate, mt->mt_uri,
298 				      BER_BVISNULL(&msc->msc_bound_ndn) ? "" : msc->msc_bound_ndn.bv_val );
299 				ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex );
300 			}
301 
302 			meta_clear_one_candidate( op, mc, candidate );
303 			LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
304 
305 			( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn );
306 
307 			/* mc here must be the regular mc, reset and ready for init */
308 			rc = meta_back_init_one_conn( op, rs, mc, candidate,
309 				LDAP_BACK_CONN_ISPRIV( mc ), LDAP_BACK_DONTSEND, 0 );
310 
311 			if ( rc == LDAP_SUCCESS ) {
312 				LDAP_BACK_CONN_BINDING_SET( msc );
313 			}
314 
315 			ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
316 
317 			if ( rc == LDAP_SUCCESS ) {
318 				candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
319 				binddn = msc->msc_bound_ndn;
320 				cred = msc->msc_cred;
321 				goto retry;
322 			}
323 		}
324 
325 		if ( *mcp == NULL ) {
326 			retcode = META_SEARCH_ERR;
327 			rc = LDAP_UNAVAILABLE;
328 			candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
329 			break;
330 		}
331 		/* fall thru */
332 
333 	default:
334 other:;
335 		/* convert rc to the correct LDAP error and send it back to the client:
336 		   assign the error to rs, so we can use it as argument to slap_map_api2result
337 		   and then assign the output back to rs->sr_err */
338 		rs->sr_err = rc;
339 		rs->sr_err = slap_map_api2result( rs );
340 
341 		ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
342 		meta_clear_one_candidate( op, mc, candidate );
343 		candidates[ candidate ].sr_err = rs->sr_err;
344 		if ( META_BACK_ONERR_STOP( mi ) ) {
345 			LDAP_BACK_CONN_TAINTED_SET( mc );
346 			meta_back_release_conn_lock( mi, mc, 0 );
347 			*mcp = NULL;
348 
349 			retcode = META_SEARCH_ERR;
350 
351 		} else {
352 			retcode = META_SEARCH_NOT_CANDIDATE;
353 		}
354 		candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
355 		ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
356 		break;
357 	}
358 
359 	return retcode;
360 }
361 
362 static meta_search_candidate_t
meta_search_dobind_result(Operation * op,SlapReply * rs,metaconn_t ** mcp,int candidate,SlapReply * candidates,LDAPMessage * res)363 meta_search_dobind_result(
364 	Operation		*op,
365 	SlapReply		*rs,
366 	metaconn_t		**mcp,
367 	int			candidate,
368 	SlapReply		*candidates,
369 	LDAPMessage		*res )
370 {
371 	metainfo_t		*mi = ( metainfo_t * )op->o_bd->be_private;
372 	metatarget_t		*mt = mi->mi_targets[ candidate ];
373 	metaconn_t		*mc = *mcp;
374 	metasingleconn_t	*msc = &mc->mc_conns[ candidate ];
375 
376 	meta_search_candidate_t	retcode = META_SEARCH_NOT_CANDIDATE;
377 	int			rc;
378 
379 	assert( msc->msc_ld != NULL );
380 
381 	/* FIXME: matched? referrals? response controls? */
382 	rc = ldap_parse_result( msc->msc_ld, res,
383 		&candidates[ candidate ].sr_err,
384 		NULL, NULL, NULL, NULL, 0 );
385 	if ( rc != LDAP_SUCCESS ) {
386 		candidates[ candidate ].sr_err = rc;
387 	}
388 	rc = slap_map_api2result( &candidates[ candidate ] );
389 
390 	ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
391 	LDAP_BACK_CONN_BINDING_CLEAR( msc );
392 	if ( rc != LDAP_SUCCESS ) {
393 		meta_clear_one_candidate( op, mc, candidate );
394 		candidates[ candidate ].sr_err = rc;
395 		if ( META_BACK_ONERR_STOP( mi ) ) {
396 	        	LDAP_BACK_CONN_TAINTED_SET( mc );
397 			meta_back_release_conn_lock( mi, mc, 0 );
398 			*mcp = NULL;
399 			retcode = META_SEARCH_ERR;
400 			rs->sr_err = rc;
401 		}
402 
403 	} else {
404 		/* FIXME: check if bound as idassert authcDN! */
405 		if ( BER_BVISNULL( &msc->msc_bound_ndn )
406 			|| BER_BVISEMPTY( &msc->msc_bound_ndn ) )
407 		{
408 			LDAP_BACK_CONN_ISANON_SET( msc );
409 
410 		} else {
411 			if ( META_BACK_TGT_SAVECRED( mt ) &&
412 				!BER_BVISNULL( &msc->msc_cred ) &&
413 				!BER_BVISEMPTY( &msc->msc_cred ) )
414 			{
415 				ldap_set_rebind_proc( msc->msc_ld, mt->mt_rebind_f, msc );
416 			}
417 			LDAP_BACK_CONN_ISBOUND_SET( msc );
418 		}
419 		retcode = META_SEARCH_CANDIDATE;
420 
421 		/* connect must be async */
422 		ldap_set_option( msc->msc_ld, LDAP_OPT_CONNECT_ASYNC, LDAP_OPT_OFF );
423 	}
424 
425 	candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
426 	META_BINDING_CLEAR( &candidates[ candidate ] );
427 
428 	ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
429 
430 	return retcode;
431 }
432 
433 static meta_search_candidate_t
meta_back_search_start(Operation * op,SlapReply * rs,dncookie * dc,metaconn_t ** mcp,int candidate,SlapReply * candidates,struct berval * prcookie,ber_int_t prsize)434 meta_back_search_start(
435 	Operation		*op,
436 	SlapReply		*rs,
437 	dncookie		*dc,
438 	metaconn_t		**mcp,
439 	int			candidate,
440 	SlapReply		*candidates,
441 	struct berval		*prcookie,
442 	ber_int_t		prsize )
443 {
444 	metainfo_t		*mi = ( metainfo_t * )op->o_bd->be_private;
445 	metatarget_t		*mt = mi->mi_targets[ candidate ];
446 	metasingleconn_t	*msc = &(*mcp)->mc_conns[ candidate ];
447 	struct berval		realbase = op->o_req_dn;
448 	int			realscope = op->ors_scope;
449 	struct berval		mbase = BER_BVNULL;
450 	struct berval		mfilter = BER_BVNULL;
451 	char			**mapped_attrs = NULL;
452 	int			rc;
453 	meta_search_candidate_t	retcode;
454 	struct timeval		tv, *tvp = NULL;
455 	int			nretries = 1;
456 	LDAPControl		**ctrls = NULL;
457 #ifdef SLAPD_META_CLIENT_PR
458 	LDAPControl		**save_ctrls = NULL;
459 #endif /* SLAPD_META_CLIENT_PR */
460 
461 	/* this should not happen; just in case... */
462 	if ( msc->msc_ld == NULL ) {
463 		Debug( LDAP_DEBUG_ANY,
464 			"%s: meta_back_search_start candidate=%d ld=NULL%s.\n",
465 			op->o_log_prefix, candidate,
466 			META_BACK_ONERR_STOP( mi ) ? "" : " (ignored)" );
467 		candidates[ candidate ].sr_err = LDAP_OTHER;
468 		if ( META_BACK_ONERR_STOP( mi ) ) {
469 			return META_SEARCH_ERR;
470 		}
471 		candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
472 		return META_SEARCH_NOT_CANDIDATE;
473 	}
474 
475 	Debug( LDAP_DEBUG_TRACE, "%s >>> meta_back_search_start[%d]\n", op->o_log_prefix, candidate );
476 
477 	/*
478 	 * modifies the base according to the scope, if required
479 	 */
480 	if ( mt->mt_nsuffix.bv_len > op->o_req_ndn.bv_len ) {
481 		switch ( op->ors_scope ) {
482 		case LDAP_SCOPE_SUBTREE:
483 			/*
484 			 * make the target suffix the new base
485 			 * FIXME: this is very forgiving, because
486 			 * "illegal" searchBases may be turned
487 			 * into the suffix of the target; however,
488 			 * the requested searchBase already passed
489 			 * thru the candidate analyzer...
490 			 */
491 			if ( dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) ) {
492 				realbase = mt->mt_nsuffix;
493 				if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) {
494 					realscope = LDAP_SCOPE_SUBORDINATE;
495 				}
496 
497 			} else {
498 				/*
499 				 * this target is no longer candidate
500 				 */
501 				retcode = META_SEARCH_NOT_CANDIDATE;
502 				goto doreturn;
503 			}
504 			break;
505 
506 		case LDAP_SCOPE_SUBORDINATE:
507 		case LDAP_SCOPE_ONELEVEL:
508 		{
509 			struct berval	rdn = mt->mt_nsuffix;
510 			rdn.bv_len -= op->o_req_ndn.bv_len + STRLENOF( "," );
511 			if ( dnIsOneLevelRDN( &rdn )
512 					&& dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) )
513 			{
514 				/*
515 				 * if there is exactly one level,
516 				 * make the target suffix the new
517 				 * base, and make scope "base"
518 				 */
519 				realbase = mt->mt_nsuffix;
520 				if ( op->ors_scope == LDAP_SCOPE_SUBORDINATE ) {
521 					if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) {
522 						realscope = LDAP_SCOPE_SUBORDINATE;
523 					} else {
524 						realscope = LDAP_SCOPE_SUBTREE;
525 					}
526 				} else {
527 					realscope = LDAP_SCOPE_BASE;
528 				}
529 				break;
530 			} /* else continue with the next case */
531 		}
532 
533 		case LDAP_SCOPE_BASE:
534 			/*
535 			 * this target is no longer candidate
536 			 */
537 			retcode = META_SEARCH_NOT_CANDIDATE;
538 			goto doreturn;
539 		}
540 	}
541 
542 	/* check filter expression */
543 	if ( mt->mt_filter ) {
544 		metafilter_t *mf;
545 		for ( mf = mt->mt_filter; mf; mf = mf->mf_next ) {
546 			if ( regexec( &mf->mf_regex, op->ors_filterstr.bv_val, 0, NULL, 0 ) == 0 )
547 				break;
548 		}
549 		/* nothing matched, this target is no longer a candidate */
550 		if ( !mf ) {
551 			retcode = META_SEARCH_NOT_CANDIDATE;
552 			goto doreturn;
553 		}
554 	}
555 
556 	/* initiate dobind */
557 	retcode = meta_search_dobind_init( op, rs, mcp, candidate, candidates );
558 
559 	Debug( LDAP_DEBUG_TRACE, "%s <<< meta_search_dobind_init[%d]=%d\n", op->o_log_prefix, candidate, retcode );
560 
561 	if ( retcode != META_SEARCH_CANDIDATE ) {
562 		goto doreturn;
563 	}
564 
565 	/*
566 	 * Rewrite the search base, if required
567 	 */
568 	dc->target = mt;
569 	dc->ctx = "searchBase";
570 	switch ( ldap_back_dn_massage( dc, &realbase, &mbase ) ) {
571 	case LDAP_SUCCESS:
572 		break;
573 
574 	case LDAP_UNWILLING_TO_PERFORM:
575 		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
576 		rs->sr_text = "Operation not allowed";
577 		send_ldap_result( op, rs );
578 		retcode = META_SEARCH_ERR;
579 		goto doreturn;
580 
581 	default:
582 
583 		/*
584 		 * this target is no longer candidate
585 		 */
586 		retcode = META_SEARCH_NOT_CANDIDATE;
587 		goto doreturn;
588 	}
589 
590 	/*
591 	 * Maps filter
592 	 */
593 	rc = ldap_back_filter_map_rewrite( dc, op->ors_filter,
594 			&mfilter, BACKLDAP_MAP, op->o_tmpmemctx );
595 	switch ( rc ) {
596 	case LDAP_SUCCESS:
597 		break;
598 
599 	case LDAP_COMPARE_FALSE:
600 	default:
601 		/*
602 		 * this target is no longer candidate
603 		 */
604 		retcode = META_SEARCH_NOT_CANDIDATE;
605 		goto done;
606 	}
607 
608 	/*
609 	 * Maps required attributes
610 	 */
611 	rc = ldap_back_map_attrs( op, &mt->mt_rwmap.rwm_at,
612 			op->ors_attrs, BACKLDAP_MAP, &mapped_attrs );
613 	if ( rc != LDAP_SUCCESS ) {
614 		/*
615 		 * this target is no longer candidate
616 		 */
617 		retcode = META_SEARCH_NOT_CANDIDATE;
618 		goto done;
619 	}
620 
621 	if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
622 		tv.tv_sec = op->ors_tlimit > 0 ? op->ors_tlimit : 1;
623 		tv.tv_usec = 0;
624 		tvp = &tv;
625 	}
626 
627 #ifdef SLAPD_META_CLIENT_PR
628 	save_ctrls = op->o_ctrls;
629 	{
630 		LDAPControl *pr_c = NULL;
631 		int i = 0, nc = 0;
632 
633 		if ( save_ctrls ) {
634 			for ( ; save_ctrls[i] != NULL; i++ );
635 			nc = i;
636 			pr_c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, save_ctrls, NULL );
637 		}
638 
639 		if ( pr_c != NULL ) nc--;
640 		if ( mt->mt_ps > 0 || prcookie != NULL ) nc++;
641 
642 		if ( mt->mt_ps > 0 || prcookie != NULL || pr_c != NULL ) {
643 			int src = 0, dst = 0;
644 			BerElementBuffer berbuf;
645 			BerElement *ber = (BerElement *)&berbuf;
646 			struct berval val = BER_BVNULL;
647 			ber_len_t len;
648 
649 			len = sizeof( LDAPControl * )*( nc + 1 ) + sizeof( LDAPControl );
650 
651 			if ( mt->mt_ps > 0 || prcookie != NULL ) {
652 				struct berval nullcookie = BER_BVNULL;
653 				ber_tag_t tag;
654 
655 				if ( prsize == 0 && mt->mt_ps > 0 ) prsize = mt->mt_ps;
656 				if ( prcookie == NULL ) prcookie = &nullcookie;
657 
658 				ber_init2( ber, NULL, LBER_USE_DER );
659 				tag = ber_printf( ber, "{iO}", prsize, prcookie );
660 				if ( tag == LBER_ERROR ) {
661 					/* error */
662 					(void) ber_free_buf( ber );
663 					goto done_pr;
664 				}
665 
666 				tag = ber_flatten2( ber, &val, 0 );
667 				if ( tag == LBER_ERROR ) {
668 					/* error */
669 					(void) ber_free_buf( ber );
670 					goto done_pr;
671 				}
672 
673 				len += val.bv_len + 1;
674 			}
675 
676 			op->o_ctrls = op->o_tmpalloc( len, op->o_tmpmemctx );
677 			if ( save_ctrls ) {
678 				for ( ; save_ctrls[ src ] != NULL; src++ ) {
679 					if ( save_ctrls[ src ] != pr_c ) {
680 						op->o_ctrls[ dst ] = save_ctrls[ src ];
681 						dst++;
682 					}
683 				}
684 			}
685 
686 			if ( mt->mt_ps > 0 || prcookie != NULL ) {
687 				op->o_ctrls[ dst ] = (LDAPControl *)&op->o_ctrls[ nc + 1 ];
688 
689 				op->o_ctrls[ dst ]->ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
690 				op->o_ctrls[ dst ]->ldctl_iscritical = 1;
691 
692 				op->o_ctrls[ dst ]->ldctl_value.bv_val = (char *)&op->o_ctrls[ dst ][ 1 ];
693 				AC_MEMCPY( op->o_ctrls[ dst ]->ldctl_value.bv_val, val.bv_val, val.bv_len + 1 );
694 				op->o_ctrls[ dst ]->ldctl_value.bv_len = val.bv_len;
695 				dst++;
696 
697 				(void)ber_free_buf( ber );
698 			}
699 
700 			op->o_ctrls[ dst ] = NULL;
701 		}
702 done_pr:;
703 	}
704 #endif /* SLAPD_META_CLIENT_PR */
705 
706 retry:;
707 	ctrls = op->o_ctrls;
708 	if ( meta_back_controls_add( op, rs, *mcp, candidate, &ctrls )
709 		!= LDAP_SUCCESS )
710 	{
711 		candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
712 		retcode = META_SEARCH_NOT_CANDIDATE;
713 		goto done;
714 	}
715 
716 	/*
717 	 * Starts the search
718 	 */
719 	assert( msc->msc_ld != NULL );
720 	rc = ldap_pvt_search( msc->msc_ld,
721 			mbase.bv_val, realscope, mfilter.bv_val,
722 			mapped_attrs, op->ors_attrsonly,
723 			ctrls, NULL, tvp, op->ors_slimit, op->ors_deref,
724 			&candidates[ candidate ].sr_msgid );
725 	switch ( rc ) {
726 	case LDAP_SUCCESS:
727 		retcode = META_SEARCH_CANDIDATE;
728 		break;
729 
730 	case LDAP_SERVER_DOWN:
731 		if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
732 			nretries = 0;
733 			/* if the identity changed, there might be need to re-authz */
734 			(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
735 			goto retry;
736 		}
737 
738 		if ( *mcp == NULL ) {
739 			retcode = META_SEARCH_ERR;
740 			candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
741 			break;
742 		}
743 		/* fall thru */
744 
745 	default:
746 		candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
747 		retcode = META_SEARCH_NOT_CANDIDATE;
748 	}
749 
750 done:;
751 	(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
752 #ifdef SLAPD_META_CLIENT_PR
753 	if ( save_ctrls != op->o_ctrls ) {
754 		op->o_tmpfree( op->o_ctrls, op->o_tmpmemctx );
755 		op->o_ctrls = save_ctrls;
756 	}
757 #endif /* SLAPD_META_CLIENT_PR */
758 
759 	if ( mapped_attrs ) {
760 		ber_memfree_x( mapped_attrs, op->o_tmpmemctx );
761 	}
762 	if ( mfilter.bv_val != op->ors_filterstr.bv_val ) {
763 		ber_memfree_x( mfilter.bv_val, op->o_tmpmemctx );
764 	}
765 	if ( mbase.bv_val != realbase.bv_val ) {
766 		free( mbase.bv_val );
767 	}
768 
769 doreturn:;
770 	Debug( LDAP_DEBUG_TRACE, "%s <<< meta_back_search_start[%d]=%d\n", op->o_log_prefix, candidate, retcode );
771 
772 	return retcode;
773 }
774 
775 int
meta_back_search(Operation * op,SlapReply * rs)776 meta_back_search( Operation *op, SlapReply *rs )
777 {
778 	metainfo_t	*mi = ( metainfo_t * )op->o_bd->be_private;
779 	metaconn_t	*mc;
780 	struct timeval	save_tv = { 0, 0 },
781 			tv;
782 	time_t		stoptime = (time_t)(-1),
783 			lastres_time = slap_get_time(),
784 			timeout = 0;
785 	int		rc = 0, sres = LDAP_SUCCESS;
786 	char		*matched = NULL;
787 	int		last = 0, ncandidates = 0,
788 			initial_candidates = 0, candidate_match = 0,
789 			needbind = 0;
790 	ldap_back_send_t	sendok = LDAP_BACK_SENDERR;
791 	long		i;
792 	dncookie	dc;
793 	int		is_ok = 0;
794 	void		*savepriv;
795 	SlapReply	*candidates = NULL;
796 	int		do_taint = 0;
797 
798 	rs_assert_ready( rs );
799 	rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia, we can set rs = non-entry */
800 
801 	/*
802 	 * controls are set in ldap_back_dobind()
803 	 *
804 	 * FIXME: in case of values return filter, we might want
805 	 * to map attrs and maybe rewrite value
806 	 */
807 getconn:;
808 	mc = meta_back_getconn( op, rs, NULL, sendok );
809 	if ( !mc ) {
810 		return rs->sr_err;
811 	}
812 
813 	dc.conn = op->o_conn;
814 	dc.rs = rs;
815 
816 	if ( candidates == NULL ) candidates = meta_back_candidates_get( op );
817 	/*
818 	 * Inits searches
819 	 */
820 	for ( i = 0; i < mi->mi_ntargets; i++ ) {
821 		/* reset sr_msgid; it is used in most loops
822 		 * to check if that target is still to be considered */
823 		candidates[ i ].sr_msgid = META_MSGID_IGNORE;
824 
825 		/* a target is marked as candidate by meta_back_getconn();
826 		 * if for any reason (an error, it's over or so) it is
827 		 * no longer active, sr_msgid is set to META_MSGID_IGNORE
828 		 * but it remains candidate, which means it has been active
829 		 * at some point during the operation.  This allows to
830 		 * use its response code and more to compute the final
831 		 * response */
832 		if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) {
833 			continue;
834 		}
835 
836 		candidates[ i ].sr_matched = NULL;
837 		candidates[ i ].sr_text = NULL;
838 		candidates[ i ].sr_ref = NULL;
839 		candidates[ i ].sr_ctrls = NULL;
840 		candidates[ i ].sr_nentries = 0;
841 
842 		/* get largest timeout among candidates */
843 		if ( mi->mi_targets[ i ]->mt_timeout[ SLAP_OP_SEARCH ]
844 			&& mi->mi_targets[ i ]->mt_timeout[ SLAP_OP_SEARCH ] > timeout )
845 		{
846 			timeout = mi->mi_targets[ i ]->mt_timeout[ SLAP_OP_SEARCH ];
847 		}
848 	}
849 
850 	for ( i = 0; i < mi->mi_ntargets; i++ ) {
851 		if ( !META_IS_CANDIDATE( &candidates[ i ] )
852 			|| candidates[ i ].sr_err != LDAP_SUCCESS )
853 		{
854 			continue;
855 		}
856 
857 		switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates, NULL, 0 ) )
858 		{
859 		case META_SEARCH_NOT_CANDIDATE:
860 			candidates[ i ].sr_msgid = META_MSGID_IGNORE;
861 			break;
862 
863 		case META_SEARCH_NEED_BIND:
864 			++needbind;
865 			/* fallthru */
866 
867 		case META_SEARCH_CONNECTING:
868 		case META_SEARCH_CANDIDATE:
869 		case META_SEARCH_BINDING:
870 			candidates[ i ].sr_type = REP_INTERMEDIATE;
871 			++ncandidates;
872 			break;
873 
874 		case META_SEARCH_ERR:
875 			savepriv = op->o_private;
876 			op->o_private = (void *)i;
877 			send_ldap_result( op, rs );
878 			op->o_private = savepriv;
879 			rc = -1;
880 			goto finish;
881 
882 		default:
883 			assert( 0 );
884 			break;
885 		}
886 	}
887 
888 	if ( ncandidates > 0 && needbind == ncandidates ) {
889 		/*
890 		 * give up the second time...
891 		 *
892 		 * NOTE: this should not occur the second time, since a fresh
893 		 * connection has ben created; however, targets may also
894 		 * need bind because the bind timed out or so.
895 		 */
896 		if ( sendok & LDAP_BACK_BINDING ) {
897 			Debug( LDAP_DEBUG_ANY,
898 				"%s meta_back_search: unable to initialize conn\n",
899 				op->o_log_prefix );
900 			rs->sr_err = LDAP_UNAVAILABLE;
901 			rs->sr_text = "unable to initialize connection to remote targets";
902 			send_ldap_result( op, rs );
903 			rc = -1;
904 			goto finish;
905 		}
906 
907 		/* FIXME: better create a separate connection? */
908 		sendok |= LDAP_BACK_BINDING;
909 
910 #ifdef DEBUG_205
911 		Debug( LDAP_DEBUG_ANY, "*** %s drop mc=%p create new connection\n",
912 			op->o_log_prefix, (void *)mc );
913 #endif /* DEBUG_205 */
914 
915 		meta_back_release_conn( mi, mc );
916 		mc = NULL;
917 
918 		needbind = 0;
919 		ncandidates = 0;
920 
921 		goto getconn;
922 	}
923 
924 	initial_candidates = ncandidates;
925 
926 	if ( LogTest( LDAP_DEBUG_TRACE ) ) {
927 		char	cnd[ SLAP_TEXT_BUFLEN ];
928 		int	c;
929 
930 		for ( c = 0; c < mi->mi_ntargets; c++ ) {
931 			if ( META_IS_CANDIDATE( &candidates[ c ] ) ) {
932 				cnd[ c ] = '*';
933 			} else {
934 				cnd[ c ] = ' ';
935 			}
936 		}
937 		cnd[ c ] = '\0';
938 
939 		Debug( LDAP_DEBUG_TRACE, "%s meta_back_search: ncandidates=%d "
940 			"cnd=\"%s\"\n", op->o_log_prefix, ncandidates, cnd );
941 	}
942 
943 	if ( initial_candidates == 0 ) {
944 		/* NOTE: here we are not sending any matchedDN;
945 		 * this is intended, because if the back-meta
946 		 * is serving this search request, but no valid
947 		 * candidate could be looked up, it means that
948 		 * there is a hole in the mapping of the targets
949 		 * and thus no knowledge of any remote superior
950 		 * is available */
951 		Debug( LDAP_DEBUG_ANY, "%s meta_back_search: "
952 			"base=\"%s\" scope=%d: "
953 			"no candidate could be selected\n",
954 			op->o_log_prefix, op->o_req_dn.bv_val,
955 			op->ors_scope );
956 
957 		/* FIXME: we're sending the first error we encounter;
958 		 * maybe we should pick the worst... */
959 		rc = LDAP_NO_SUCH_OBJECT;
960 		for ( i = 0; i < mi->mi_ntargets; i++ ) {
961 			if ( META_IS_CANDIDATE( &candidates[ i ] )
962 				&& candidates[ i ].sr_err != LDAP_SUCCESS )
963 			{
964 				rc = candidates[ i ].sr_err;
965 				break;
966 			}
967 		}
968 
969 		send_ldap_error( op, rs, rc, NULL );
970 
971 		goto finish;
972 	}
973 
974 	/* We pull apart the ber result, stuff it into a slapd entry, and
975 	 * let send_search_entry stuff it back into ber format. Slow & ugly,
976 	 * but this is necessary for version matching, and for ACL processing.
977 	 */
978 
979 	if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
980 		stoptime = op->o_time + op->ors_tlimit;
981 	}
982 
983 	/*
984 	 * In case there are no candidates, no cycle takes place...
985 	 *
986 	 * FIXME: we might use a queue, to better balance the load
987 	 * among the candidates
988 	 */
989 	for ( rc = 0; ncandidates > 0; ) {
990 		int	gotit = 0,
991 			doabandon = 0,
992 			alreadybound = ncandidates;
993 
994 		/* check timeout */
995 		if ( timeout && lastres_time > 0
996 			&& ( slap_get_time() - lastres_time ) > timeout )
997 		{
998 			doabandon = 1;
999 			rs->sr_text = "Operation timed out";
1000 			rc = rs->sr_err = op->o_protocol >= LDAP_VERSION3 ?
1001 				LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER;
1002 			savepriv = op->o_private;
1003 			op->o_private = (void *)i;
1004 			send_ldap_result( op, rs );
1005 			op->o_private = savepriv;
1006 			goto finish;
1007 		}
1008 
1009 		/* check time limit */
1010 		if ( op->ors_tlimit != SLAP_NO_LIMIT
1011 				&& slap_get_time() > stoptime )
1012 		{
1013 			doabandon = 1;
1014 			rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED;
1015 			savepriv = op->o_private;
1016 			op->o_private = (void *)i;
1017 			send_ldap_result( op, rs );
1018 			op->o_private = savepriv;
1019 			goto finish;
1020 		}
1021 
1022 		for ( i = 0; i < mi->mi_ntargets; i++ ) {
1023 			meta_search_candidate_t	retcode = META_SEARCH_UNDEFINED;
1024 			metasingleconn_t	*msc = &mc->mc_conns[ i ];
1025 			LDAPMessage		*res = NULL, *msg;
1026 
1027 			/* if msgid is invalid, don't ldap_result() */
1028 			if ( candidates[ i ].sr_msgid == META_MSGID_IGNORE ) {
1029 				continue;
1030 			}
1031 
1032 			/* if target still needs bind, retry */
1033 			if ( candidates[ i ].sr_msgid == META_MSGID_NEED_BIND
1034 				|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
1035 			{
1036 				/* initiate dobind */
1037 				retcode = meta_search_dobind_init( op, rs, &mc, i, candidates );
1038 
1039 				Debug( LDAP_DEBUG_TRACE, "%s <<< meta_search_dobind_init[%ld]=%d\n",
1040 					op->o_log_prefix, i, retcode );
1041 
1042 				switch ( retcode ) {
1043 				case META_SEARCH_NEED_BIND:
1044 					alreadybound--;
1045 					/* fallthru */
1046 
1047 				case META_SEARCH_CONNECTING:
1048 				case META_SEARCH_BINDING:
1049 					break;
1050 
1051 				case META_SEARCH_ERR:
1052 					candidates[ i ].sr_err = rs->sr_err;
1053 					if ( META_BACK_ONERR_STOP( mi ) ) {
1054 						savepriv = op->o_private;
1055 						op->o_private = (void *)i;
1056 						send_ldap_result( op, rs );
1057 						op->o_private = savepriv;
1058 						goto finish;
1059 					}
1060 					/* fallthru */
1061 
1062 				case META_SEARCH_NOT_CANDIDATE:
1063 					/*
1064 					 * When no candidates are left,
1065 					 * the outer cycle finishes
1066 					 */
1067 					candidates[ i ].sr_msgid = META_MSGID_IGNORE;
1068 					assert( ncandidates > 0 );
1069 					--ncandidates;
1070 					break;
1071 
1072 				case META_SEARCH_CANDIDATE:
1073 					candidates[ i ].sr_msgid = META_MSGID_IGNORE;
1074 					switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates, NULL, 0 ) )
1075 					{
1076 					case META_SEARCH_CANDIDATE:
1077 						assert( candidates[ i ].sr_msgid >= 0 );
1078 						break;
1079 
1080 					case META_SEARCH_ERR:
1081 						candidates[ i ].sr_err = rs->sr_err;
1082 						if ( META_BACK_ONERR_STOP( mi ) ) {
1083 							savepriv = op->o_private;
1084 							op->o_private = (void *)i;
1085 							send_ldap_result( op, rs );
1086 							op->o_private = savepriv;
1087 							goto finish;
1088 						}
1089 						/* fallthru */
1090 
1091 					case META_SEARCH_NOT_CANDIDATE:
1092 						/* means that meta_back_search_start()
1093 						 * failed but onerr == continue */
1094 						candidates[ i ].sr_msgid = META_MSGID_IGNORE;
1095 						assert( ncandidates > 0 );
1096 						--ncandidates;
1097 						break;
1098 
1099 					default:
1100 						/* impossible */
1101 						assert( 0 );
1102 						break;
1103 					}
1104 					break;
1105 
1106 				default:
1107 					/* impossible */
1108 					assert( 0 );
1109 					break;
1110 				}
1111 				continue;
1112 			}
1113 
1114 			/* check for abandon */
1115 			if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( mc ) ) {
1116 				break;
1117 			}
1118 
1119 #ifdef DEBUG_205
1120 			if ( msc->msc_ld == NULL ) {
1121 				ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
1122 				Debug(LDAP_DEBUG_ANY,
1123 				      "!!! %s meta_back_search[%ld] mc=%p msgid=%d%s%s%s\n\n",
1124 				      op->o_log_prefix, (long)i, (void *)mc,
1125 				      candidates[i].sr_msgid,
1126 				      META_IS_BINDING(&candidates[i]) ? " binding" : "",
1127 				      LDAP_BACK_CONN_BINDING(&mc->mc_conns[i]) ? " connbinding" : "",
1128 				      META_BACK_CONN_CREATING(&mc->mc_conns[i]) ? " conncreating" : "" );
1129 				ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
1130 			}
1131 #endif /* DEBUG_205 */
1132 
1133 			/*
1134 			 * FIXME: handle time limit as well?
1135 			 * Note that target servers are likely
1136 			 * to handle it, so at some time we'll
1137 			 * get a LDAP_TIMELIMIT_EXCEEDED from
1138 			 * one of them ...
1139 			 */
1140 			tv = save_tv;
1141 			rc = ldap_result( msc->msc_ld, candidates[ i ].sr_msgid,
1142 					LDAP_MSG_RECEIVED, &tv, &res );
1143 			switch ( rc ) {
1144 			case 0:
1145 				/* FIXME: res should not need to be freed */
1146 				assert( res == NULL );
1147 				continue;
1148 
1149 			case -1:
1150 really_bad:;
1151 				/* something REALLY bad happened! */
1152 				if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
1153 					candidates[ i ].sr_type = REP_RESULT;
1154 
1155 					if ( meta_back_retry( op, rs, &mc, i, LDAP_BACK_DONTSEND ) ) {
1156 						candidates[ i ].sr_msgid = META_MSGID_IGNORE;
1157 						switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates, NULL, 0 ) )
1158 						{
1159 							/* means that failed but onerr == continue */
1160 						case META_SEARCH_NOT_CANDIDATE:
1161 							candidates[ i ].sr_msgid = META_MSGID_IGNORE;
1162 
1163 							assert( ncandidates > 0 );
1164 							--ncandidates;
1165 
1166 							candidates[ i ].sr_err = rs->sr_err;
1167 							if ( META_BACK_ONERR_STOP( mi ) ) {
1168 								savepriv = op->o_private;
1169 								op->o_private = (void *)i;
1170 								send_ldap_result( op, rs );
1171 								op->o_private = savepriv;
1172 								goto finish;
1173 							}
1174 							/* fall thru */
1175 
1176 						case META_SEARCH_CANDIDATE:
1177 							/* get back into business... */
1178 							continue;
1179 
1180 						case META_SEARCH_BINDING:
1181 						case META_SEARCH_CONNECTING:
1182 						case META_SEARCH_NEED_BIND:
1183 						case META_SEARCH_UNDEFINED:
1184 							assert( 0 );
1185 
1186 						default:
1187 							/* unrecoverable error */
1188 							candidates[ i ].sr_msgid = META_MSGID_IGNORE;
1189 							rc = rs->sr_err = LDAP_OTHER;
1190 							goto finish;
1191 						}
1192 					}
1193 
1194 					candidates[ i ].sr_err = rs->sr_err;
1195 					if ( META_BACK_ONERR_STOP( mi ) ) {
1196 						savepriv = op->o_private;
1197 						op->o_private = (void *)i;
1198 						send_ldap_result( op, rs );
1199 						op->o_private = savepriv;
1200 						goto finish;
1201 					}
1202 				}
1203 
1204 				/*
1205 				 * When no candidates are left,
1206 				 * the outer cycle finishes
1207 				 */
1208 				candidates[ i ].sr_msgid = META_MSGID_IGNORE;
1209 				assert( ncandidates > 0 );
1210 				--ncandidates;
1211 				rs->sr_err = candidates[ i ].sr_err;
1212 				continue;
1213 
1214 			default:
1215 				lastres_time = slap_get_time();
1216 
1217 				/* only touch when activity actually took place... */
1218 				if ( mi->mi_idle_timeout != 0 && msc->msc_time < lastres_time ) {
1219 					msc->msc_time = lastres_time;
1220 				}
1221 				break;
1222 			}
1223 
1224 			for ( msg = ldap_first_message( msc->msc_ld, res );
1225 				msg != NULL;
1226 				msg = ldap_next_message( msc->msc_ld, msg ) )
1227 			{
1228 				rc = ldap_msgtype( msg );
1229 				if ( rc == LDAP_RES_SEARCH_ENTRY ) {
1230 					LDAPMessage	*e;
1231 
1232 					if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
1233 						/* don't retry any more... */
1234 						candidates[ i ].sr_type = REP_RESULT;
1235 					}
1236 
1237 					/* count entries returned by target */
1238 					candidates[ i ].sr_nentries++;
1239 
1240 					is_ok++;
1241 
1242 					e = ldap_first_entry( msc->msc_ld, msg );
1243 					savepriv = op->o_private;
1244 					op->o_private = (void *)i;
1245 					rs->sr_err = meta_send_entry( op, rs, mc, i, e );
1246 
1247 					switch ( rs->sr_err ) {
1248 					case LDAP_SIZELIMIT_EXCEEDED:
1249 						savepriv = op->o_private;
1250 						op->o_private = (void *)i;
1251 						send_ldap_result( op, rs );
1252 						op->o_private = savepriv;
1253 						rs->sr_err = LDAP_SUCCESS;
1254 						ldap_msgfree( res );
1255 						res = NULL;
1256 						goto finish;
1257 
1258 					case LDAP_UNAVAILABLE:
1259 						rs->sr_err = LDAP_OTHER;
1260 						ldap_msgfree( res );
1261 						res = NULL;
1262 						goto finish;
1263 					}
1264 					op->o_private = savepriv;
1265 
1266 					/* don't wait any longer... */
1267 					gotit = 1;
1268 					save_tv.tv_sec = 0;
1269 					save_tv.tv_usec = 0;
1270 
1271 				} else if ( rc == LDAP_RES_SEARCH_REFERENCE ) {
1272 					char		**references = NULL;
1273 					int		cnt;
1274 
1275 					if ( META_BACK_TGT_NOREFS( mi->mi_targets[ i ] ) ) {
1276 						continue;
1277 					}
1278 
1279 					if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
1280 						/* don't retry any more... */
1281 						candidates[ i ].sr_type = REP_RESULT;
1282 					}
1283 
1284 					is_ok++;
1285 
1286 					rc = ldap_parse_reference( msc->msc_ld, msg,
1287 							&references, &rs->sr_ctrls, 0 );
1288 
1289 					if ( rc != LDAP_SUCCESS ) {
1290 						continue;
1291 					}
1292 
1293 					if ( references == NULL ) {
1294 						continue;
1295 					}
1296 
1297 					dc.ctx = "referralDN";
1298 
1299 					/* FIXME: merge all and return at the end */
1300 
1301 					for ( cnt = 0; references[ cnt ]; cnt++ )
1302 						;
1303 
1304 					rs->sr_ref = op->o_tmpalloc( sizeof( struct berval ) * ( cnt + 1 ),
1305 						op->o_tmpmemctx );
1306 
1307 					for ( cnt = 0; references[ cnt ]; cnt++ ) {
1308 						ber_str2bv_x( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ],
1309 						op->o_tmpmemctx );
1310 					}
1311 					BER_BVZERO( &rs->sr_ref[ cnt ] );
1312 
1313 					( void )ldap_back_referral_result_rewrite( &dc, rs->sr_ref,
1314 						op->o_tmpmemctx );
1315 
1316 					if ( rs->sr_ref != NULL && !BER_BVISNULL( &rs->sr_ref[ 0 ] ) ) {
1317 						/* ignore return value by now */
1318 						savepriv = op->o_private;
1319 						op->o_private = (void *)i;
1320 						( void )send_search_reference( op, rs );
1321 						op->o_private = savepriv;
1322 
1323 						ber_bvarray_free_x( rs->sr_ref, op->o_tmpmemctx );
1324 						rs->sr_ref = NULL;
1325 					}
1326 
1327 					/* cleanup */
1328 					if ( references ) {
1329 						ber_memvfree( (void **)references );
1330 					}
1331 
1332 					if ( rs->sr_ctrls ) {
1333 						ldap_controls_free( rs->sr_ctrls );
1334 						rs->sr_ctrls = NULL;
1335 					}
1336 
1337 				} else if ( rc == LDAP_RES_INTERMEDIATE ) {
1338 					if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
1339 						/* don't retry any more... */
1340 						candidates[ i ].sr_type = REP_RESULT;
1341 					}
1342 
1343 					/* FIXME: response controls
1344 					 * are passed without checks */
1345 					rs->sr_err = ldap_parse_intermediate( msc->msc_ld,
1346 						msg,
1347 						(char **)&rs->sr_rspoid,
1348 						&rs->sr_rspdata,
1349 						&rs->sr_ctrls,
1350 						0 );
1351 					if ( rs->sr_err != LDAP_SUCCESS ) {
1352 						candidates[ i ].sr_type = REP_RESULT;
1353 						ldap_msgfree( res );
1354 						res = NULL;
1355 						goto really_bad;
1356 					}
1357 
1358 					slap_send_ldap_intermediate( op, rs );
1359 
1360 					if ( rs->sr_rspoid != NULL ) {
1361 						ber_memfree( (char *)rs->sr_rspoid );
1362 						rs->sr_rspoid = NULL;
1363 					}
1364 
1365 					if ( rs->sr_rspdata != NULL ) {
1366 						ber_bvfree( rs->sr_rspdata );
1367 						rs->sr_rspdata = NULL;
1368 					}
1369 
1370 					if ( rs->sr_ctrls != NULL ) {
1371 						ldap_controls_free( rs->sr_ctrls );
1372 						rs->sr_ctrls = NULL;
1373 					}
1374 
1375 				} else if ( rc == LDAP_RES_SEARCH_RESULT ) {
1376 					char		**references = NULL;
1377 					LDAPControl	**ctrls = NULL;
1378 
1379 					if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
1380 						/* don't retry any more... */
1381 						candidates[ i ].sr_type = REP_RESULT;
1382 					}
1383 
1384 					candidates[ i ].sr_msgid = META_MSGID_IGNORE;
1385 
1386 					/* NOTE: ignores response controls
1387 					 * (and intermediate response controls
1388 					 * as well, except for those with search
1389 					 * references); this may not be correct,
1390 					 * but if they're not ignored then
1391 					 * back-meta would need to merge them
1392 					 * consistently (think of pagedResults...)
1393 					 */
1394 					/* FIXME: response controls? */
1395 					rs->sr_err = ldap_parse_result( msc->msc_ld,
1396 						msg,
1397 						&candidates[ i ].sr_err,
1398 						(char **)&candidates[ i ].sr_matched,
1399 						(char **)&candidates[ i ].sr_text,
1400 						&references,
1401 						&ctrls /* &candidates[ i ].sr_ctrls (unused) */ ,
1402 						0 );
1403 					if ( rs->sr_err != LDAP_SUCCESS ) {
1404 						candidates[ i ].sr_err = rs->sr_err;
1405 						sres = slap_map_api2result( &candidates[ i ] );
1406 						candidates[ i ].sr_type = REP_RESULT;
1407 						ldap_msgfree( res );
1408 						res = NULL;
1409 						goto really_bad;
1410 					}
1411 
1412 					rs->sr_err = candidates[ i ].sr_err;
1413 
1414 					/* massage matchedDN if need be */
1415 					if ( candidates[ i ].sr_matched != NULL ) {
1416 						struct berval	match, mmatch;
1417 
1418 						ber_str2bv( candidates[ i ].sr_matched,
1419 							0, 0, &match );
1420 						candidates[ i ].sr_matched = NULL;
1421 
1422 						dc.ctx = "matchedDN";
1423 						dc.target = mi->mi_targets[ i ];
1424 						if ( !ldap_back_dn_massage( &dc, &match, &mmatch ) ) {
1425 							if ( mmatch.bv_val == match.bv_val ) {
1426 								candidates[ i ].sr_matched
1427 									= ch_strdup( mmatch.bv_val );
1428 
1429 							} else {
1430 								candidates[ i ].sr_matched = mmatch.bv_val;
1431 							}
1432 
1433 							candidate_match++;
1434 						}
1435 						ldap_memfree( match.bv_val );
1436 					}
1437 
1438 					/* add references to array */
1439 					/* RFC 4511: referrals can only appear
1440 					 * if result code is LDAP_REFERRAL */
1441 					if ( references != NULL
1442 						&& references[ 0 ] != NULL
1443 						&& references[ 0 ][ 0 ] != '\0' )
1444 					{
1445 						if ( rs->sr_err != LDAP_REFERRAL ) {
1446 							Debug( LDAP_DEBUG_ANY,
1447 								"%s meta_back_search[%ld]: "
1448 								"got referrals with err=%d\n",
1449 								op->o_log_prefix,
1450 								i, rs->sr_err );
1451 
1452 						} else {
1453 							BerVarray	sr_ref;
1454 							int		cnt;
1455 
1456 							for ( cnt = 0; references[ cnt ]; cnt++ )
1457 								;
1458 
1459 							sr_ref = op->o_tmpalloc( sizeof( struct berval ) * ( cnt + 1 ),
1460 								op->o_tmpmemctx );
1461 
1462 							for ( cnt = 0; references[ cnt ]; cnt++ ) {
1463 								ber_str2bv_x( references[ cnt ], 0, 1, &sr_ref[ cnt ],
1464 									op->o_tmpmemctx );
1465 							}
1466 							BER_BVZERO( &sr_ref[ cnt ] );
1467 
1468 							( void )ldap_back_referral_result_rewrite( &dc, sr_ref,
1469 								op->o_tmpmemctx );
1470 
1471 							if ( rs->sr_v2ref == NULL ) {
1472 								rs->sr_v2ref = sr_ref;
1473 
1474 							} else {
1475 								for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) {
1476 									ber_bvarray_add_x( &rs->sr_v2ref, &sr_ref[ cnt ],
1477 										op->o_tmpmemctx );
1478 								}
1479 								ber_memfree_x( sr_ref, op->o_tmpmemctx );
1480 							}
1481 						}
1482 
1483 					} else if ( rs->sr_err == LDAP_REFERRAL ) {
1484 						Debug( LDAP_DEBUG_ANY,
1485 							"%s meta_back_search[%ld]: "
1486 							"got err=%d with null "
1487 							"or empty referrals\n",
1488 							op->o_log_prefix,
1489 							i, rs->sr_err );
1490 
1491 						rs->sr_err = LDAP_NO_SUCH_OBJECT;
1492 					}
1493 
1494 					/* cleanup */
1495 					ber_memvfree( (void **)references );
1496 
1497 					sres = slap_map_api2result( rs );
1498 
1499 					if ( LogTest( LDAP_DEBUG_TRACE | LDAP_DEBUG_ANY ) ) {
1500 						char buf[ SLAP_TEXT_BUFLEN ];
1501 						snprintf( buf, sizeof( buf ),
1502 							"%s meta_back_search[%ld] "
1503 							"match=\"%s\" err=%ld",
1504 							op->o_log_prefix, i,
1505 							candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "",
1506 							(long) candidates[ i ].sr_err );
1507 						if ( candidates[ i ].sr_err == LDAP_SUCCESS ) {
1508 							Debug( LDAP_DEBUG_TRACE, "%s.\n", buf );
1509 
1510 						} else {
1511 							Debug( LDAP_DEBUG_ANY, "%s (%s) text=\"%s\".\n",
1512 								buf, ldap_err2string( candidates[ i ].sr_err ),
1513 								candidates[ i ].sr_text ? candidates[i].sr_text : "" );
1514 						}
1515 					}
1516 
1517 					switch ( sres ) {
1518 					case LDAP_NO_SUCH_OBJECT:
1519 						/* is_ok is touched any time a valid
1520 						 * (even intermediate) result is
1521 						 * returned; as a consequence, if
1522 						 * a candidate returns noSuchObject
1523 						 * it is ignored and the candidate
1524 						 * is simply demoted. */
1525 						if ( is_ok ) {
1526 							sres = LDAP_SUCCESS;
1527 						}
1528 						break;
1529 
1530 					case LDAP_SUCCESS:
1531 						if ( ctrls != NULL && ctrls[0] != NULL ) {
1532 #ifdef SLAPD_META_CLIENT_PR
1533 							LDAPControl *pr_c;
1534 
1535 							pr_c = ldap_control_find( LDAP_CONTROL_PAGEDRESULTS, ctrls, NULL );
1536 							if ( pr_c != NULL ) {
1537 								BerElementBuffer berbuf;
1538 								BerElement *ber = (BerElement *)&berbuf;
1539 								ber_tag_t tag;
1540 								ber_int_t prsize;
1541 								struct berval prcookie;
1542 
1543 								/* unsolicited, do not accept */
1544 								if ( mi->mi_targets[i]->mt_ps == 0 ) {
1545 									rs->sr_err = LDAP_OTHER;
1546 									goto err_pr;
1547 								}
1548 
1549 								ber_init2( ber, &pr_c->ldctl_value, LBER_USE_DER );
1550 
1551 								tag = ber_scanf( ber, "{im}", &prsize, &prcookie );
1552 								if ( tag == LBER_ERROR ) {
1553 									rs->sr_err = LDAP_OTHER;
1554 									goto err_pr;
1555 								}
1556 
1557 								/* more pages? new search request */
1558 								if ( !BER_BVISNULL( &prcookie ) && !BER_BVISEMPTY( &prcookie ) ) {
1559 									if ( mi->mi_targets[i]->mt_ps > 0 ) {
1560 										/* ignore size if specified */
1561 										prsize = 0;
1562 
1563 									} else if ( prsize == 0 ) {
1564 										/* guess the page size from the entries returned so far */
1565 										prsize = candidates[ i ].sr_nentries;
1566 									}
1567 
1568 									candidates[ i ].sr_nentries = 0;
1569 									candidates[ i ].sr_msgid = META_MSGID_IGNORE;
1570 									candidates[ i ].sr_type = REP_INTERMEDIATE;
1571 
1572 									assert( candidates[ i ].sr_matched == NULL );
1573 									assert( candidates[ i ].sr_text == NULL );
1574 									assert( candidates[ i ].sr_ref == NULL );
1575 
1576 									switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates, &prcookie, prsize ) )
1577 									{
1578 									case META_SEARCH_CANDIDATE:
1579 										assert( candidates[ i ].sr_msgid >= 0 );
1580 										ldap_controls_free( ctrls );
1581 										goto free_message;
1582 
1583 									case META_SEARCH_ERR:
1584 err_pr:;
1585 										candidates[ i ].sr_err = rs->sr_err;
1586 										if ( META_BACK_ONERR_STOP( mi ) ) {
1587 											savepriv = op->o_private;
1588 											op->o_private = (void *)i;
1589 											send_ldap_result( op, rs );
1590 											op->o_private = savepriv;
1591 											ldap_controls_free( ctrls );
1592 											goto finish;
1593 										}
1594 										/* fallthru */
1595 
1596 									case META_SEARCH_NOT_CANDIDATE:
1597 										/* means that meta_back_search_start()
1598 										 * failed but onerr == continue */
1599 										candidates[ i ].sr_msgid = META_MSGID_IGNORE;
1600 										assert( ncandidates > 0 );
1601 										--ncandidates;
1602 										break;
1603 
1604 									default:
1605 										/* impossible */
1606 										assert( 0 );
1607 										break;
1608 									}
1609 									break;
1610 								}
1611 							}
1612 #endif /* SLAPD_META_CLIENT_PR */
1613 						}
1614 						/* fallthru */
1615 
1616 					case LDAP_REFERRAL:
1617 						is_ok++;
1618 						break;
1619 
1620 					case LDAP_SIZELIMIT_EXCEEDED:
1621 						/* if a target returned sizelimitExceeded
1622 						 * and the entry count is equal to the
1623 						 * proxy's limit, the target would have
1624 						 * returned more, and the error must be
1625 						 * propagated to the client; otherwise,
1626 						 * the target enforced a limit lower
1627 						 * than what requested by the proxy;
1628 						 * ignore it */
1629 						candidates[ i ].sr_err = rs->sr_err;
1630 						if ( rs->sr_nentries == op->ors_slimit
1631 							|| META_BACK_ONERR_STOP( mi ) )
1632 						{
1633 							const char *save_text;
1634 got_err:
1635 							save_text = rs->sr_text;
1636 							savepriv = op->o_private;
1637 							op->o_private = (void *)i;
1638 							rs->sr_text = candidates[ i ].sr_text;
1639 							send_ldap_result( op, rs );
1640 							rs->sr_text = save_text;
1641 							op->o_private = savepriv;
1642 							ldap_msgfree( res );
1643 							res = NULL;
1644 							ldap_controls_free( ctrls );
1645 							goto finish;
1646 						}
1647 						break;
1648 
1649 					default:
1650 						candidates[ i ].sr_err = rs->sr_err;
1651 						if ( META_BACK_ONERR_STOP( mi ) )
1652 							goto got_err;
1653 						break;
1654 					}
1655 
1656 					ldap_controls_free( ctrls );
1657 					last = i;
1658 					rc = 0;
1659 
1660 					/*
1661 					 * When no candidates are left,
1662 					 * the outer cycle finishes
1663 					 */
1664 					assert( ncandidates > 0 );
1665 					--ncandidates;
1666 
1667 				} else if ( rc == LDAP_RES_BIND ) {
1668 					meta_search_candidate_t	retcode;
1669 
1670 					retcode = meta_search_dobind_result( op, rs, &mc, i, candidates, msg );
1671 					if ( retcode == META_SEARCH_CANDIDATE ) {
1672 						candidates[ i ].sr_msgid = META_MSGID_IGNORE;
1673 						retcode = meta_back_search_start( op, rs, &dc, &mc, i, candidates, NULL, 0 );
1674 					}
1675 
1676 					switch ( retcode ) {
1677 					case META_SEARCH_CANDIDATE:
1678 						break;
1679 
1680 						/* means that failed but onerr == continue */
1681 					case META_SEARCH_NOT_CANDIDATE:
1682 					case META_SEARCH_ERR:
1683 						candidates[ i ].sr_msgid = META_MSGID_IGNORE;
1684 						assert( ncandidates > 0 );
1685 						--ncandidates;
1686 
1687 						candidates[ i ].sr_err = rs->sr_err;
1688 						if ( META_BACK_ONERR_STOP( mi ) ) {
1689 							savepriv = op->o_private;
1690 							op->o_private = (void *)i;
1691 							send_ldap_result( op, rs );
1692 							op->o_private = savepriv;
1693 							ldap_msgfree( res );
1694 							res = NULL;
1695 							goto finish;
1696 						}
1697 						goto free_message;
1698 
1699 					default:
1700 						assert( 0 );
1701 						break;
1702 					}
1703 
1704 				} else {
1705 					Debug( LDAP_DEBUG_ANY,
1706 						"%s meta_back_search[%ld]: "
1707 						"unrecognized response message tag=%d\n",
1708 						op->o_log_prefix,
1709 						i, rc );
1710 
1711 					ldap_msgfree( res );
1712 					res = NULL;
1713 					goto really_bad;
1714 				}
1715 			}
1716 
1717 free_message:;
1718 			ldap_msgfree( res );
1719 			res = NULL;
1720 		}
1721 
1722 		/* check for abandon */
1723 		if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( mc ) ) {
1724 			for ( i = 0; i < mi->mi_ntargets; i++ ) {
1725 				if ( candidates[ i ].sr_msgid >= 0
1726 					|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
1727 				{
1728 					if ( META_IS_BINDING( &candidates[ i ] )
1729 						|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
1730 					{
1731 						ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
1732 						if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] )
1733 							|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
1734 						{
1735 							/* if still binding, destroy */
1736 
1737 #ifdef DEBUG_205
1738 							Debug(LDAP_DEBUG_ANY,
1739 							      "### %s meta_back_search(abandon) " "ldap_unbind_ext[%ld] mc=%p ld=%p\n",
1740 							      op->o_log_prefix,
1741 							      i, (void *)mc,
1742 							      (void *)mc->mc_conns[i].msc_ld );
1743 #endif /* DEBUG_205 */
1744 
1745 							meta_clear_one_candidate( op, mc, i );
1746 						}
1747 						ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
1748 						META_BINDING_CLEAR( &candidates[ i ] );
1749 
1750 					} else {
1751 						(void)meta_back_cancel( mc, op, rs,
1752 							candidates[ i ].sr_msgid, i,
1753 							LDAP_BACK_DONTSEND );
1754 					}
1755 
1756 					candidates[ i ].sr_msgid = META_MSGID_IGNORE;
1757 					assert( ncandidates > 0 );
1758 					--ncandidates;
1759 				}
1760 			}
1761 
1762 			if ( op->o_abandon ) {
1763 				rc = SLAPD_ABANDON;
1764 			}
1765 
1766 			/* let send_ldap_result play cleanup handlers (ITS#4645) */
1767 			break;
1768 		}
1769 
1770 		/* if no entry was found during this loop,
1771 		 * set a minimal timeout */
1772 		if ( ncandidates > 0 && gotit == 0 ) {
1773 			if ( save_tv.tv_sec == 0 && save_tv.tv_usec == 0 ) {
1774 				save_tv.tv_usec = LDAP_BACK_RESULT_UTIMEOUT/initial_candidates;
1775 
1776 				/* arbitrarily limit to something between 1 and 2 minutes */
1777 			} else if ( ( stoptime == -1 && save_tv.tv_sec < 60 )
1778 				|| save_tv.tv_sec < ( stoptime - slap_get_time() ) / ( 2 * ncandidates ) )
1779 			{
1780 				/* double the timeout */
1781 				lutil_timermul( &save_tv, 2, &save_tv );
1782 			}
1783 
1784 			if ( alreadybound == 0 ) {
1785 				tv = save_tv;
1786 				(void)select( 0, NULL, NULL, NULL, &tv );
1787 
1788 			} else {
1789 				ldap_pvt_thread_yield();
1790 			}
1791 		}
1792 	}
1793 
1794 	if ( rc == -1 ) {
1795 		/*
1796 		 * FIXME: need a better strategy to handle errors
1797 		 */
1798 		if ( mc ) {
1799 			rc = meta_back_op_result( mc, op, rs, META_TARGET_NONE,
1800 				-1, stoptime != -1 ? (stoptime - slap_get_time()) : 0,
1801 				LDAP_BACK_SENDERR );
1802 		} else {
1803 			rc = rs->sr_err;
1804 		}
1805 		goto finish;
1806 	}
1807 
1808 	/*
1809 	 * Rewrite the matched portion of the search base, if required
1810 	 *
1811 	 * FIXME: only the last one gets caught!
1812 	 */
1813 	savepriv = op->o_private;
1814 	op->o_private = (void *)(long)mi->mi_ntargets;
1815 	if ( candidate_match > 0 ) {
1816 		struct berval	pmatched = BER_BVNULL;
1817 
1818 		/* we use the first one */
1819 		for ( i = 0; i < mi->mi_ntargets; i++ ) {
1820 			if ( META_IS_CANDIDATE( &candidates[ i ] )
1821 					&& candidates[ i ].sr_matched != NULL )
1822 			{
1823 				struct berval	bv, pbv;
1824 				int		rc;
1825 
1826 				/* if we got success, and this target
1827 				 * returned noSuchObject, and its suffix
1828 				 * is a superior of the searchBase,
1829 				 * ignore the matchedDN */
1830 				if ( sres == LDAP_SUCCESS
1831 					&& candidates[ i ].sr_err == LDAP_NO_SUCH_OBJECT
1832 					&& op->o_req_ndn.bv_len > mi->mi_targets[ i ]->mt_nsuffix.bv_len )
1833 				{
1834 					free( (char *)candidates[ i ].sr_matched );
1835 					candidates[ i ].sr_matched = NULL;
1836 					continue;
1837 				}
1838 
1839 				ber_str2bv( candidates[ i ].sr_matched, 0, 0, &bv );
1840 				rc = dnPretty( NULL, &bv, &pbv, op->o_tmpmemctx );
1841 
1842 				if ( rc == LDAP_SUCCESS ) {
1843 
1844 					/* NOTE: if they all are superiors
1845 					 * of the baseDN, the shorter is also
1846 					 * superior of the longer... */
1847 					if ( pbv.bv_len > pmatched.bv_len ) {
1848 						if ( !BER_BVISNULL( &pmatched ) ) {
1849 							op->o_tmpfree( pmatched.bv_val, op->o_tmpmemctx );
1850 						}
1851 						pmatched = pbv;
1852 						op->o_private = (void *)i;
1853 
1854 					} else {
1855 						op->o_tmpfree( pbv.bv_val, op->o_tmpmemctx );
1856 					}
1857 				}
1858 
1859 				if ( candidates[ i ].sr_matched != NULL ) {
1860 					free( (char *)candidates[ i ].sr_matched );
1861 					candidates[ i ].sr_matched = NULL;
1862 				}
1863 			}
1864 		}
1865 
1866 		if ( !BER_BVISNULL( &pmatched ) ) {
1867 			matched = pmatched.bv_val;
1868 		}
1869 
1870 	} else if ( sres == LDAP_NO_SUCH_OBJECT ) {
1871 		matched = op->o_bd->be_suffix[ 0 ].bv_val;
1872 	}
1873 
1874 	/*
1875 	 * In case we returned at least one entry, we return LDAP_SUCCESS
1876 	 * otherwise, the latter error code we got
1877 	 */
1878 
1879 	if ( sres == LDAP_SUCCESS ) {
1880 		if ( rs->sr_v2ref ) {
1881 			sres = LDAP_REFERRAL;
1882 		}
1883 
1884 		if ( META_BACK_ONERR_REPORT( mi ) ) {
1885 			/*
1886 			 * Report errors, if any
1887 			 *
1888 			 * FIXME: we should handle error codes and return the more
1889 			 * important/reasonable
1890 			 */
1891 			for ( i = 0; i < mi->mi_ntargets; i++ ) {
1892 				if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) {
1893 					continue;
1894 				}
1895 
1896 				if ( candidates[ i ].sr_err != LDAP_SUCCESS
1897 					&& candidates[ i ].sr_err != LDAP_NO_SUCH_OBJECT )
1898 				{
1899 					sres = candidates[ i ].sr_err;
1900 					break;
1901 				}
1902 			}
1903 		}
1904 	}
1905 
1906 	rs->sr_err = sres;
1907 	rs->sr_matched = ( sres == LDAP_SUCCESS ? NULL : matched );
1908 	rs->sr_ref = ( sres == LDAP_REFERRAL ? rs->sr_v2ref : NULL );
1909 	send_ldap_result( op, rs );
1910 	op->o_private = savepriv;
1911 	rs->sr_matched = NULL;
1912 	rs->sr_ref = NULL;
1913 
1914 finish:;
1915 	if ( matched && matched != op->o_bd->be_suffix[ 0 ].bv_val ) {
1916 		op->o_tmpfree( matched, op->o_tmpmemctx );
1917 	}
1918 
1919 	if ( rs->sr_v2ref ) {
1920 		ber_bvarray_free_x( rs->sr_v2ref, op->o_tmpmemctx );
1921 	}
1922 
1923 	for ( i = 0; i < mi->mi_ntargets; i++ ) {
1924 		if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) {
1925 			continue;
1926 		}
1927 
1928 		if ( mc ) {
1929 			if ( META_IS_BINDING( &candidates[ i ] )
1930 				|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
1931 			{
1932 				ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
1933 				if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] )
1934 					|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
1935 				{
1936 					assert( candidates[ i ].sr_msgid >= 0
1937 						|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING );
1938 					assert( mc->mc_conns[ i ].msc_ld != NULL );
1939 
1940 #ifdef DEBUG_205
1941 					Debug( LDAP_DEBUG_ANY, "### %s meta_back_search(cleanup) "
1942 						"ldap_unbind_ext[%ld] ld=%p\n",
1943 						op->o_log_prefix, i, (void *)mc->mc_conns[i].msc_ld );
1944 #endif /* DEBUG_205 */
1945 
1946 					/* if still binding, destroy */
1947 					meta_clear_one_candidate( op, mc, i );
1948 				}
1949 				ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
1950 				META_BINDING_CLEAR( &candidates[ i ] );
1951 
1952 			} else if ( candidates[ i ].sr_msgid >= 0 ) {
1953 				(void)meta_back_cancel( mc, op, rs,
1954 					candidates[ i ].sr_msgid, i,
1955 					LDAP_BACK_DONTSEND );
1956 			}
1957 		}
1958 
1959 		if ( candidates[ i ].sr_matched ) {
1960 			free( (char *)candidates[ i ].sr_matched );
1961 			candidates[ i ].sr_matched = NULL;
1962 		}
1963 
1964 		if ( candidates[ i ].sr_text ) {
1965 			ldap_memfree( (char *)candidates[ i ].sr_text );
1966 			candidates[ i ].sr_text = NULL;
1967 		}
1968 
1969 		if ( candidates[ i ].sr_ref ) {
1970 			ber_bvarray_free( candidates[ i ].sr_ref );
1971 			candidates[ i ].sr_ref = NULL;
1972 		}
1973 
1974 		if ( candidates[ i ].sr_ctrls ) {
1975 			ldap_controls_free( candidates[ i ].sr_ctrls );
1976 			candidates[ i ].sr_ctrls = NULL;
1977 		}
1978 
1979 		if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ i ] ) ) {
1980 			meta_back_quarantine( op, &candidates[ i ], i );
1981 		}
1982 
1983 		/* only in case of timelimit exceeded, if the timelimit exceeded because
1984 		 * one contacted target never responded, invalidate the connection
1985 		 * NOTE: should we quarantine the target as well?  right now, the connection
1986 		 * is invalidated; the next time it will be recreated and the target
1987 		 * will be quarantined if it cannot be contacted */
1988 		if ( mi->mi_idle_timeout != 0
1989 			&& rs->sr_err == LDAP_TIMELIMIT_EXCEEDED
1990 			&& op->o_time > mc->mc_conns[ i ].msc_time )
1991 		{
1992 			/* don't let anyone else use this expired connection */
1993 			do_taint++;
1994 		}
1995 	}
1996 
1997 	if ( mc ) {
1998 		ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
1999 		if ( do_taint ) {
2000 			LDAP_BACK_CONN_TAINTED_SET( mc );
2001 		}
2002 		meta_back_release_conn_lock( mi, mc, 0 );
2003 		ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
2004 	}
2005 
2006 	return rs->sr_err;
2007 }
2008 
2009 static int
meta_send_entry(Operation * op,SlapReply * rs,metaconn_t * mc,int target,LDAPMessage * e)2010 meta_send_entry(
2011 	Operation 	*op,
2012 	SlapReply	*rs,
2013 	metaconn_t	*mc,
2014 	int 		target,
2015 	LDAPMessage 	*e )
2016 {
2017 	metainfo_t 		*mi = ( metainfo_t * )op->o_bd->be_private;
2018 	struct berval		a, mapped;
2019 	int			check_duplicate_attrs = 0;
2020 	int			check_sorted_attrs = 0;
2021 	Entry 			ent = { 0 };
2022 	BerElement 		ber = *ldap_get_message_ber( e );
2023 	Attribute 		*attr, **attrp;
2024 	struct berval 		bdn,
2025 				dn = BER_BVNULL;
2026 	const char 		*text;
2027 	dncookie		dc;
2028 	ber_len_t		len;
2029 	int			rc;
2030 
2031 	if ( ber_scanf( &ber, "l{", &len ) == LBER_ERROR ) {
2032 		return LDAP_DECODING_ERROR;
2033 	}
2034 
2035 	if ( ber_set_option( &ber, LBER_OPT_REMAINING_BYTES, &len ) != LBER_OPT_SUCCESS ) {
2036 		return LDAP_OTHER;
2037 	}
2038 
2039 	if ( ber_scanf( &ber, "m{", &bdn ) == LBER_ERROR ) {
2040 		return LDAP_DECODING_ERROR;
2041 	}
2042 
2043 	/*
2044 	 * Rewrite the dn of the result, if needed
2045 	 */
2046 	dc.target = mi->mi_targets[ target ];
2047 	dc.conn = op->o_conn;
2048 	dc.rs = rs;
2049 	dc.ctx = "searchResult";
2050 
2051 	rs->sr_err = ldap_back_dn_massage( &dc, &bdn, &dn );
2052 	if ( rs->sr_err != LDAP_SUCCESS) {
2053 		return rs->sr_err;
2054 	}
2055 
2056 	/*
2057 	 * Note: this may fail if the target host(s) schema differs
2058 	 * from the one known to the meta, and a DN with unknown
2059 	 * attributes is returned.
2060 	 *
2061 	 * FIXME: should we log anything, or delegate to dnNormalize?
2062 	 */
2063 	rc = dnPrettyNormal( NULL, &dn, &ent.e_name, &ent.e_nname,
2064 		op->o_tmpmemctx );
2065 	if ( dn.bv_val != bdn.bv_val ) {
2066 		free( dn.bv_val );
2067 	}
2068 	BER_BVZERO( &dn );
2069 
2070 	if ( rc != LDAP_SUCCESS ) {
2071 		Debug( LDAP_DEBUG_ANY,
2072 			"%s meta_send_entry(\"%s\"): "
2073 			"invalid DN syntax\n",
2074 			op->o_log_prefix, ent.e_name.bv_val );
2075 		rc = LDAP_INVALID_DN_SYNTAX;
2076 		goto done;
2077 	}
2078 
2079 	/*
2080 	 * cache dn
2081 	 */
2082 	if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED ) {
2083 		( void )meta_dncache_update_entry( &mi->mi_cache,
2084 				&ent.e_nname, target );
2085 	}
2086 
2087 	attrp = &ent.e_attrs;
2088 
2089 	dc.ctx = "searchAttrDN";
2090 	while ( ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) {
2091 		int				last = 0;
2092 		slap_syntax_validate_func	*validate;
2093 		slap_syntax_transform_func	*pretty;
2094 
2095 		if ( ber_pvt_ber_remaining( &ber ) < 0 ) {
2096 			Debug( LDAP_DEBUG_ANY,
2097 				"%s meta_send_entry(\"%s\"): "
2098 				"unable to parse attr \"%s\".\n",
2099 				op->o_log_prefix, ent.e_name.bv_val, a.bv_val );
2100 
2101 			rc = LDAP_OTHER;
2102 			goto done;
2103 		}
2104 
2105 		if ( ber_pvt_ber_remaining( &ber ) == 0 ) {
2106 			break;
2107 		}
2108 
2109 		ldap_back_map( &mi->mi_targets[ target ]->mt_rwmap.rwm_at,
2110 				&a, &mapped, BACKLDAP_REMAP );
2111 		if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0' ) {
2112 			( void )ber_scanf( &ber, "x" /* [W] */ );
2113 			continue;
2114 		}
2115 		if ( mapped.bv_val != a.bv_val ) {
2116 			/* will need to check for duplicate attrs */
2117 			check_duplicate_attrs++;
2118 		}
2119 		attr = attr_alloc( NULL );
2120 		if ( attr == NULL ) {
2121 			rc = LDAP_OTHER;
2122 			goto done;
2123 		}
2124 		if ( slap_bv2ad( &mapped, &attr->a_desc, &text )
2125 				!= LDAP_SUCCESS) {
2126 			if ( slap_bv2undef_ad( &mapped, &attr->a_desc, &text,
2127 				SLAP_AD_PROXIED ) != LDAP_SUCCESS )
2128 			{
2129 				Debug(LDAP_DEBUG_ANY,
2130 				      "%s meta_send_entry(\"%s\"): " "slap_bv2undef_ad(%s): %s\n",
2131 				      op->o_log_prefix, ent.e_name.bv_val,
2132 				      mapped.bv_val, text );
2133 				( void )ber_scanf( &ber, "x" /* [W] */ );
2134 				attr_free( attr );
2135 				continue;
2136 			}
2137 		}
2138 
2139 		if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL )
2140 			check_sorted_attrs = 1;
2141 
2142 		/* no subschemaSubentry */
2143 		if ( attr->a_desc == slap_schema.si_ad_subschemaSubentry
2144 			|| attr->a_desc == slap_schema.si_ad_entryDN )
2145 		{
2146 
2147 			/*
2148 			 * We eat target's subschemaSubentry because
2149 			 * a search for this value is likely not
2150 			 * to resolve to the appropriate backend;
2151 			 * later, the local subschemaSubentry is
2152 			 * added.
2153 			 *
2154 			 * We also eat entryDN because the frontend
2155 			 * will reattach it without checking if already
2156 			 * present...
2157 			 */
2158 			( void )ber_scanf( &ber, "x" /* [W] */ );
2159 			attr_free(attr);
2160 			continue;
2161 		}
2162 
2163 		if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR
2164 				|| attr->a_vals == NULL )
2165 		{
2166 			attr->a_vals = (struct berval *)&slap_dummy_bv;
2167 
2168 		} else {
2169 			for ( last = 0; !BER_BVISNULL( &attr->a_vals[ last ] ); ++last )
2170 				;
2171 		}
2172 		attr->a_numvals = last;
2173 
2174 		validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate;
2175 		pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty;
2176 
2177 		if ( !validate && !pretty ) {
2178 			attr_free( attr );
2179 			goto next_attr;
2180 		}
2181 
2182 		if ( attr->a_desc == slap_schema.si_ad_objectClass
2183 				|| attr->a_desc == slap_schema.si_ad_structuralObjectClass )
2184 		{
2185 			struct berval 	*bv;
2186 
2187 			for ( bv = attr->a_vals; !BER_BVISNULL( bv ); bv++ ) {
2188 				ObjectClass *oc;
2189 
2190 				ldap_back_map( &mi->mi_targets[ target ]->mt_rwmap.rwm_oc,
2191 						bv, &mapped, BACKLDAP_REMAP );
2192 				if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0') {
2193 remove_oc:;
2194 					free( bv->bv_val );
2195 					BER_BVZERO( bv );
2196 					if ( --last < 0 ) {
2197 						break;
2198 					}
2199 					*bv = attr->a_vals[ last ];
2200 					BER_BVZERO( &attr->a_vals[ last ] );
2201 					bv--;
2202 
2203 				} else if ( mapped.bv_val != bv->bv_val ) {
2204 					int	i;
2205 
2206 					for ( i = 0; !BER_BVISNULL( &attr->a_vals[ i ] ); i++ ) {
2207 						if ( &attr->a_vals[ i ] == bv ) {
2208 							continue;
2209 						}
2210 
2211 						if ( ber_bvstrcasecmp( &mapped, &attr->a_vals[ i ] ) == 0 ) {
2212 							break;
2213 						}
2214 					}
2215 
2216 					if ( !BER_BVISNULL( &attr->a_vals[ i ] ) ) {
2217 						goto remove_oc;
2218 					}
2219 
2220 					ber_bvreplace( bv, &mapped );
2221 
2222 				} else if ( ( oc = oc_bvfind_undef( bv ) ) == NULL ) {
2223 					goto remove_oc;
2224 
2225 				} else {
2226 					ber_bvreplace( bv, &oc->soc_cname );
2227 				}
2228 			}
2229 		/*
2230 		 * It is necessary to try to rewrite attributes with
2231 		 * dn syntax because they might be used in ACLs as
2232 		 * members of groups; since ACLs are applied to the
2233 		 * rewritten stuff, no dn-based subecj clause could
2234 		 * be used at the ldap backend side (see
2235 		 * http://www.OpenLDAP.org/faq/data/cache/452.html)
2236 		 * The problem can be overcome by moving the dn-based
2237 		 * ACLs to the target directory server, and letting
2238 		 * everything pass thru the ldap backend.
2239 		 */
2240 		} else {
2241 			int	i;
2242 
2243 			if ( attr->a_desc->ad_type->sat_syntax ==
2244 				slap_schema.si_syn_distinguishedName )
2245 			{
2246 				ldap_dnattr_result_rewrite( &dc, attr->a_vals );
2247 
2248 			} else if ( attr->a_desc == slap_schema.si_ad_ref ) {
2249 				ldap_back_referral_result_rewrite( &dc, attr->a_vals, NULL );
2250 
2251 			}
2252 
2253 			for ( i = 0; i < last; i++ ) {
2254 				struct berval	pval;
2255 				int		rc;
2256 
2257 				if ( pretty ) {
2258 					rc = ordered_value_pretty( attr->a_desc,
2259 						&attr->a_vals[i], &pval, NULL );
2260 
2261 				} else {
2262 					rc = ordered_value_validate( attr->a_desc,
2263 						&attr->a_vals[i], 0 );
2264 				}
2265 
2266 				if ( rc ) {
2267 					ber_memfree( attr->a_vals[i].bv_val );
2268 					if ( --last == i ) {
2269 						BER_BVZERO( &attr->a_vals[ i ] );
2270 						break;
2271 					}
2272 					attr->a_vals[i] = attr->a_vals[last];
2273 					BER_BVZERO( &attr->a_vals[last] );
2274 					i--;
2275 					continue;
2276 				}
2277 
2278 				if ( pretty ) {
2279 					ber_memfree( attr->a_vals[i].bv_val );
2280 					attr->a_vals[i] = pval;
2281 				}
2282 			}
2283 
2284 			if ( last == 0 && attr->a_vals != &slap_dummy_bv ) {
2285 				attr_free( attr );
2286 				goto next_attr;
2287 			}
2288 		}
2289 
2290 		if ( last && attr->a_desc->ad_type->sat_equality &&
2291 			attr->a_desc->ad_type->sat_equality->smr_normalize )
2292 		{
2293 			int i;
2294 
2295 			attr->a_nvals = ch_malloc( ( last + 1 ) * sizeof( struct berval ) );
2296 			for ( i = 0; i<last; i++ ) {
2297 				/* if normalizer fails, drop this value */
2298 				if ( ordered_value_normalize(
2299 					SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
2300 					attr->a_desc,
2301 					attr->a_desc->ad_type->sat_equality,
2302 					&attr->a_vals[i], &attr->a_nvals[i],
2303 					NULL )) {
2304 					ber_memfree( attr->a_vals[i].bv_val );
2305 					if ( --last == i ) {
2306 						BER_BVZERO( &attr->a_vals[ i ] );
2307 						break;
2308 					}
2309 					attr->a_vals[i] = attr->a_vals[last];
2310 					BER_BVZERO( &attr->a_vals[last] );
2311 					i--;
2312 				}
2313 			}
2314 			BER_BVZERO( &attr->a_nvals[i] );
2315 			if ( last == 0 ) {
2316 				attr_free( attr );
2317 				goto next_attr;
2318 			}
2319 
2320 		} else {
2321 			attr->a_nvals = attr->a_vals;
2322 		}
2323 
2324 		attr->a_numvals = last;
2325 		*attrp = attr;
2326 		attrp = &attr->a_next;
2327 next_attr:;
2328 	}
2329 
2330 	/* only check if some mapping occurred */
2331 	if ( check_duplicate_attrs ) {
2332 		Attribute	**ap;
2333 
2334 		for ( ap = &ent.e_attrs; *ap != NULL; ap = &(*ap)->a_next ) {
2335 			Attribute	**tap;
2336 
2337 			for ( tap = &(*ap)->a_next; *tap != NULL; ) {
2338 				if ( (*tap)->a_desc == (*ap)->a_desc ) {
2339 					Entry		e = { 0 };
2340 					Modification	mod = { 0 };
2341 					const char	*text = NULL;
2342 					char		textbuf[ SLAP_TEXT_BUFLEN ];
2343 					Attribute	*next = (*tap)->a_next;
2344 
2345 					BER_BVSTR( &e.e_name, "" );
2346 					BER_BVSTR( &e.e_nname, "" );
2347 					e.e_attrs = *ap;
2348 					mod.sm_op = LDAP_MOD_ADD;
2349 					mod.sm_desc = (*ap)->a_desc;
2350 					mod.sm_type = mod.sm_desc->ad_cname;
2351 					mod.sm_numvals = (*ap)->a_numvals;
2352 					mod.sm_values = (*tap)->a_vals;
2353 					if ( (*tap)->a_nvals != (*tap)->a_vals ) {
2354 						mod.sm_nvalues = (*tap)->a_nvals;
2355 					}
2356 
2357 					(void)modify_add_values( &e, &mod,
2358 						/* permissive */ 1,
2359 						&text, textbuf, sizeof( textbuf ) );
2360 
2361 					/* should not insert new attrs! */
2362 					assert( e.e_attrs == *ap );
2363 
2364 					attr_free( *tap );
2365 					*tap = next;
2366 
2367 				} else {
2368 					tap = &(*tap)->a_next;
2369 				}
2370 			}
2371 		}
2372 	}
2373 
2374 	/* Check for sorted attributes */
2375 	if ( check_sorted_attrs ) {
2376 		for ( attr = ent.e_attrs; attr; attr = attr->a_next ) {
2377 			if ( attr->a_desc->ad_type->sat_flags & SLAP_AT_SORTED_VAL ) {
2378 				while ( attr->a_numvals > 1 ) {
2379 					int i;
2380 					int rc = slap_sort_vals( (Modifications *)attr, &text, &i, op->o_tmpmemctx );
2381 					if ( rc != LDAP_TYPE_OR_VALUE_EXISTS )
2382 						break;
2383 
2384 					/* Strip duplicate values */
2385 					if ( attr->a_nvals != attr->a_vals )
2386 						ber_memfree( attr->a_nvals[i].bv_val );
2387 					ber_memfree( attr->a_vals[i].bv_val );
2388 					attr->a_numvals--;
2389 					if ( (unsigned)i < attr->a_numvals ) {
2390 						attr->a_vals[i] = attr->a_vals[attr->a_numvals];
2391 						if ( attr->a_nvals != attr->a_vals )
2392 							attr->a_nvals[i] = attr->a_nvals[attr->a_numvals];
2393 					}
2394 					BER_BVZERO(&attr->a_vals[attr->a_numvals]);
2395 					if ( attr->a_nvals != attr->a_vals )
2396 						BER_BVZERO(&attr->a_nvals[attr->a_numvals]);
2397 				}
2398 				attr->a_flags |= SLAP_ATTR_SORTED_VALS;
2399 			}
2400 		}
2401 	}
2402 
2403 	ldap_get_entry_controls( mc->mc_conns[target].msc_ld,
2404 		e, &rs->sr_ctrls );
2405 	rs->sr_entry = &ent;
2406 	rs->sr_attrs = op->ors_attrs;
2407 	rs->sr_operational_attrs = NULL;
2408 	rs->sr_flags = mi->mi_targets[ target ]->mt_rep_flags;
2409 	rs->sr_err = LDAP_SUCCESS;
2410 	rc = send_search_entry( op, rs );
2411 	switch ( rc ) {
2412 	case LDAP_UNAVAILABLE:
2413 		rc = LDAP_OTHER;
2414 		break;
2415 	}
2416 
2417 done:;
2418 	rs->sr_entry = NULL;
2419 	rs->sr_attrs = NULL;
2420 	if ( rs->sr_ctrls != NULL ) {
2421 		ldap_controls_free( rs->sr_ctrls );
2422 		rs->sr_ctrls = NULL;
2423 	}
2424 	if ( !BER_BVISNULL( &ent.e_name ) ) {
2425 		free( ent.e_name.bv_val );
2426 		BER_BVZERO( &ent.e_name );
2427 	}
2428 	if ( !BER_BVISNULL( &ent.e_nname ) ) {
2429 		free( ent.e_nname.bv_val );
2430 		BER_BVZERO( &ent.e_nname );
2431 	}
2432 	entry_clean( &ent );
2433 
2434 	return rc;
2435 }
2436 
2437