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