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