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