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