1 /* $OpenLDAP: pkg/ldap/servers/slapd/back-meta/search.c,v 1.146.2.12 2008/07/10 00:28:39 quanah Exp $ */
2 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4 * Copyright 1999-2008 The OpenLDAP Foundation.
5 * Portions Copyright 2001-2003 Pierangelo Masarati.
6 * Portions Copyright 1999-2003 Howard Chu.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
18 * This work was initially developed by the Howard Chu for inclusion
19 * in OpenLDAP Software and subsequently enhanced by Pierangelo
27 #include <ac/socket.h>
28 #include <ac/string.h>
33 #include "../back-ldap/back-ldap.h"
34 #include "back-meta.h"
35 #undef ldap_debug /* silence a warning in ldap-int.h */
37 #include "../../../libraries/libldap/ldap-int.h"
39 /* IGNORE means that target does not (no longer) participate
41 * NOTREADY means the search on that target has not been initialized yet
43 #define META_MSGID_IGNORE (-1)
44 #define META_MSGID_NEED_BIND (-2)
45 #define META_MSGID_CONNECTING (-3)
55 typedef enum meta_search_candidate_t
{
56 META_SEARCH_UNDEFINED
= -2,
58 META_SEARCH_NOT_CANDIDATE
,
59 META_SEARCH_CANDIDATE
,
61 META_SEARCH_NEED_BIND
,
62 META_SEARCH_CONNECTING
63 } meta_search_candidate_t
;
66 * meta_search_dobind_init()
68 * initiates bind for a candidate target of a search.
70 static meta_search_candidate_t
71 meta_search_dobind_init(
76 SlapReply
*candidates
)
78 metaconn_t
*mc
= *mcp
;
79 metainfo_t
*mi
= ( metainfo_t
* )op
->o_bd
->be_private
;
80 metatarget_t
*mt
= mi
->mi_targets
[ candidate
];
81 metasingleconn_t
*msc
= &mc
->mc_conns
[ candidate
];
83 struct berval binddn
= msc
->msc_bound_ndn
,
89 meta_search_candidate_t retcode
;
91 Debug( LDAP_DEBUG_TRACE
, "%s >>> meta_search_dobind_init[%d]\n",
92 op
->o_log_prefix
, candidate
, 0 );
95 * all the targets are already bound as pseudoroot
97 if ( mc
->mc_authz_target
== META_BOUND_ALL
) {
98 return META_SEARCH_CANDIDATE
;
101 retcode
= META_SEARCH_BINDING
;
102 ldap_pvt_thread_mutex_lock( &mi
->mi_conninfo
.lai_mutex
);
103 if ( LDAP_BACK_CONN_ISBOUND( msc
) || LDAP_BACK_CONN_ISANON( msc
) ) {
104 /* already bound (or anonymous) */
107 char buf
[ SLAP_TEXT_BUFLEN
] = { '\0' };
110 if ( LDAP_BACK_CONN_ISBOUND( msc
) ) {
114 snprintf( buf
, sizeof( buf
), " mc=%p ld=%p%s DN=\"%s\"",
115 (void *)mc
, (void *)msc
->msc_ld
,
116 bound
? " bound" : " anonymous",
117 bound
== 0 ? "" : msc
->msc_bound_ndn
.bv_val
);
118 Debug( LDAP_DEBUG_ANY
, "### %s meta_search_dobind_init[%d]%s\n",
119 op
->o_log_prefix
, candidate
, buf
);
120 #endif /* DEBUG_205 */
122 retcode
= META_SEARCH_CANDIDATE
;
124 } else if ( META_BACK_CONN_CREATING( msc
) || LDAP_BACK_CONN_BINDING( msc
) ) {
125 /* another thread is binding the target for this conn; wait */
128 char buf
[ SLAP_TEXT_BUFLEN
] = { '\0' };
130 snprintf( buf
, sizeof( buf
), " mc=%p ld=%p needbind",
131 (void *)mc
, (void *)msc
->msc_ld
);
132 Debug( LDAP_DEBUG_ANY
, "### %s meta_search_dobind_init[%d]%s\n",
133 op
->o_log_prefix
, candidate
, buf
);
134 #endif /* DEBUG_205 */
136 candidates
[ candidate
].sr_msgid
= META_MSGID_NEED_BIND
;
137 retcode
= META_SEARCH_NEED_BIND
;
140 /* we'll need to bind the target for this conn */
143 char buf
[ SLAP_TEXT_BUFLEN
];
145 snprintf( buf
, sizeof( buf
), " mc=%p ld=%p binding",
146 (void *)mc
, (void *)msc
->msc_ld
);
147 Debug( LDAP_DEBUG_ANY
, "### %s meta_search_dobind_init[%d]%s\n",
148 op
->o_log_prefix
, candidate
, buf
);
149 #endif /* DEBUG_205 */
151 if ( msc
->msc_ld
== NULL
) {
152 /* for some reason (e.g. because formerly in "binding"
153 * state, with eventual connection expiration or invalidation)
154 * it was not initialized as expected */
156 Debug( LDAP_DEBUG_ANY
, "%s meta_search_dobind_init[%d] mc=%p ld=NULL\n",
157 op
->o_log_prefix
, candidate
, (void *)mc
);
159 rc
= meta_back_init_one_conn( op
, rs
, *mcp
, candidate
,
160 LDAP_BACK_CONN_ISPRIV( *mcp
), LDAP_BACK_DONTSEND
, 0 );
163 assert( msc
->msc_ld
!= NULL
);
166 case LDAP_SERVER_DOWN
:
167 case LDAP_UNAVAILABLE
:
168 ldap_pvt_thread_mutex_unlock( &mi
->mi_conninfo
.lai_mutex
);
172 ldap_pvt_thread_mutex_unlock( &mi
->mi_conninfo
.lai_mutex
);
177 LDAP_BACK_CONN_BINDING_SET( msc
);
180 ldap_pvt_thread_mutex_unlock( &mi
->mi_conninfo
.lai_mutex
);
182 if ( retcode
!= META_SEARCH_BINDING
) {
186 /* NOTE: this obsoletes pseudorootdn */
187 if ( op
->o_conn
!= NULL
&&
188 !op
->o_do_not_cache
&&
189 ( BER_BVISNULL( &msc
->msc_bound_ndn
) ||
190 BER_BVISEMPTY( &msc
->msc_bound_ndn
) ||
191 ( mt
->mt_idassert_flags
& LDAP_BACK_AUTH_OVERRIDE
) ) )
193 rc
= meta_back_proxy_authz_cred( mc
, candidate
, op
, rs
, LDAP_BACK_DONTSEND
, &binddn
, &cred
, &method
);
194 if ( rc
!= LDAP_SUCCESS
) {
198 /* NOTE: we copy things here, even if bind didn't succeed yet,
199 * because the connection is not shared until bind is over */
200 if ( !BER_BVISNULL( &binddn
) ) {
201 ber_bvreplace( &msc
->msc_bound_ndn
, &binddn
);
202 if ( LDAP_BACK_SAVECRED( mi
) && !BER_BVISNULL( &cred
) ) {
203 if ( !BER_BVISNULL( &msc
->msc_cred
) ) {
204 memset( msc
->msc_cred
.bv_val
, 0,
205 msc
->msc_cred
.bv_len
);
207 ber_bvreplace( &msc
->msc_cred
, &cred
);
211 if ( LDAP_BACK_CONN_ISBOUND( msc
) ) {
212 /* apparently, idassert was configured with SASL bind,
213 * so bind occurred inside meta_back_proxy_authz_cred() */
214 ldap_pvt_thread_mutex_lock( &mi
->mi_conninfo
.lai_mutex
);
215 LDAP_BACK_CONN_BINDING_CLEAR( msc
);
216 ldap_pvt_thread_mutex_unlock( &mi
->mi_conninfo
.lai_mutex
);
217 return META_SEARCH_CANDIDATE
;
223 case LDAP_AUTH_SIMPLE
:
224 /* do a simple bind with binddn, cred */
233 assert( msc
->msc_ld
!= NULL
);
235 /* connect must be async only the first time... */
236 ldap_set_option( msc
->msc_ld
, LDAP_OPT_CONNECT_ASYNC
, LDAP_OPT_ON
);
239 rc
= ldap_sasl_bind( msc
->msc_ld
, binddn
.bv_val
, LDAP_SASL_SIMPLE
, &cred
,
240 NULL
, NULL
, &candidates
[ candidate
].sr_msgid
);
244 char buf
[ SLAP_TEXT_BUFLEN
];
246 snprintf( buf
, sizeof( buf
), "meta_search_dobind_init[%d] mc=%p ld=%p rc=%d",
247 candidate
, (void *)mc
, (void *)mc
->mc_conns
[ candidate
].msc_ld
, rc
);
248 Debug( LDAP_DEBUG_ANY
, "### %s %s\n",
249 op
->o_log_prefix
, buf
, 0 );
251 #endif /* DEBUG_205 */
255 assert( candidates
[ candidate
].sr_msgid
>= 0 );
256 META_BINDING_SET( &candidates
[ candidate
] );
257 return META_SEARCH_BINDING
;
259 case LDAP_X_CONNECTING
:
260 /* must retry, same conn */
261 candidates
[ candidate
].sr_msgid
= META_MSGID_CONNECTING
;
262 ldap_pvt_thread_mutex_lock( &mi
->mi_conninfo
.lai_mutex
);
263 LDAP_BACK_CONN_BINDING_CLEAR( msc
);
264 ldap_pvt_thread_mutex_unlock( &mi
->mi_conninfo
.lai_mutex
);
265 return META_SEARCH_CONNECTING
;
267 case LDAP_SERVER_DOWN
:
269 /* This is the worst thing that could happen:
270 * the search will wait until the retry is over. */
271 if ( !META_IS_RETRYING( &candidates
[ candidate
] ) ) {
272 META_RETRYING_SET( &candidates
[ candidate
] );
274 ldap_pvt_thread_mutex_lock( &mi
->mi_conninfo
.lai_mutex
);
276 assert( mc
->mc_refcnt
> 0 );
277 if ( LogTest( LDAP_DEBUG_ANY
) ) {
278 char buf
[ SLAP_TEXT_BUFLEN
];
280 /* this lock is required; however,
281 * it's invoked only when logging is on */
282 ldap_pvt_thread_mutex_lock( &mt
->mt_uri_mutex
);
283 snprintf( buf
, sizeof( buf
),
284 "retrying URI=\"%s\" DN=\"%s\"",
286 BER_BVISNULL( &msc
->msc_bound_ndn
) ?
287 "" : msc
->msc_bound_ndn
.bv_val
);
288 ldap_pvt_thread_mutex_unlock( &mt
->mt_uri_mutex
);
290 Debug( LDAP_DEBUG_ANY
,
291 "%s meta_search_dobind_init[%d]: %s.\n",
292 op
->o_log_prefix
, candidate
, buf
);
295 meta_clear_one_candidate( op
, mc
, candidate
);
296 LDAP_BACK_CONN_ISBOUND_CLEAR( msc
);
298 ( void )rewrite_session_delete( mt
->mt_rwmap
.rwm_rw
, op
->o_conn
);
300 /* mc here must be the regular mc, reset and ready for init */
301 rc
= meta_back_init_one_conn( op
, rs
, mc
, candidate
,
302 LDAP_BACK_CONN_ISPRIV( mc
), LDAP_BACK_DONTSEND
, 0 );
304 if ( rc
== LDAP_SUCCESS
) {
305 LDAP_BACK_CONN_BINDING_SET( msc
);
308 ldap_pvt_thread_mutex_unlock( &mi
->mi_conninfo
.lai_mutex
);
310 if ( rc
== LDAP_SUCCESS
) {
311 candidates
[ candidate
].sr_msgid
= META_MSGID_IGNORE
;
316 if ( *mcp
== NULL
) {
317 retcode
= META_SEARCH_ERR
;
318 rs
->sr_err
= LDAP_UNAVAILABLE
;
319 candidates
[ candidate
].sr_msgid
= META_MSGID_IGNORE
;
327 rc
= slap_map_api2result( rs
);
329 ldap_pvt_thread_mutex_lock( &mi
->mi_conninfo
.lai_mutex
);
330 meta_clear_one_candidate( op
, mc
, candidate
);
331 candidates
[ candidate
].sr_err
= rc
;
332 if ( META_BACK_ONERR_STOP( mi
) ) {
333 LDAP_BACK_CONN_TAINTED_SET( mc
);
334 meta_back_release_conn_lock( mi
, mc
, 0 );
338 retcode
= META_SEARCH_ERR
;
341 retcode
= META_SEARCH_NOT_CANDIDATE
;
343 candidates
[ candidate
].sr_msgid
= META_MSGID_IGNORE
;
344 ldap_pvt_thread_mutex_unlock( &mi
->mi_conninfo
.lai_mutex
);
351 static meta_search_candidate_t
352 meta_search_dobind_result(
357 SlapReply
*candidates
,
360 metainfo_t
*mi
= ( metainfo_t
* )op
->o_bd
->be_private
;
361 metaconn_t
*mc
= *mcp
;
362 metasingleconn_t
*msc
= &mc
->mc_conns
[ candidate
];
364 meta_search_candidate_t retcode
= META_SEARCH_NOT_CANDIDATE
;
367 assert( msc
->msc_ld
!= NULL
);
369 /* FIXME: matched? referrals? response controls? */
370 rc
= ldap_parse_result( msc
->msc_ld
, res
,
371 &candidates
[ candidate
].sr_err
,
372 NULL
, NULL
, NULL
, NULL
, 0 );
373 if ( rc
!= LDAP_SUCCESS
) {
374 candidates
[ candidate
].sr_err
= rc
;
377 rc
= slap_map_api2result( &candidates
[ candidate
] );
380 ldap_pvt_thread_mutex_lock( &mi
->mi_conninfo
.lai_mutex
);
381 LDAP_BACK_CONN_BINDING_CLEAR( msc
);
382 if ( rc
!= LDAP_SUCCESS
) {
383 meta_clear_one_candidate( op
, mc
, candidate
);
384 candidates
[ candidate
].sr_err
= rc
;
385 if ( META_BACK_ONERR_STOP( mi
) ) {
386 LDAP_BACK_CONN_TAINTED_SET( mc
);
387 meta_back_release_conn_lock( mi
, mc
, 0 );
389 retcode
= META_SEARCH_ERR
;
394 /* FIXME: check if bound as idassert authcDN! */
395 if ( BER_BVISNULL( &msc
->msc_bound_ndn
)
396 || BER_BVISEMPTY( &msc
->msc_bound_ndn
) )
398 LDAP_BACK_CONN_ISANON_SET( msc
);
401 LDAP_BACK_CONN_ISBOUND_SET( msc
);
403 retcode
= META_SEARCH_CANDIDATE
;
405 /* connect must be async */
406 ldap_set_option( msc
->msc_ld
, LDAP_OPT_CONNECT_ASYNC
, LDAP_OPT_OFF
);
409 candidates
[ candidate
].sr_msgid
= META_MSGID_IGNORE
;
410 META_BINDING_CLEAR( &candidates
[ candidate
] );
412 ldap_pvt_thread_mutex_unlock( &mi
->mi_conninfo
.lai_mutex
);
417 static meta_search_candidate_t
418 meta_back_search_start(
424 SlapReply
*candidates
)
426 metainfo_t
*mi
= ( metainfo_t
* )op
->o_bd
->be_private
;
427 metatarget_t
*mt
= mi
->mi_targets
[ candidate
];
428 metasingleconn_t
*msc
= &(*mcp
)->mc_conns
[ candidate
];
429 struct berval realbase
= op
->o_req_dn
;
430 int realscope
= op
->ors_scope
;
431 struct berval mbase
= BER_BVNULL
;
432 struct berval mfilter
= BER_BVNULL
;
433 char **mapped_attrs
= NULL
;
435 meta_search_candidate_t retcode
;
436 struct timeval tv
, *tvp
= NULL
;
438 LDAPControl
**ctrls
= NULL
;
440 /* this should not happen; just in case... */
441 if ( msc
->msc_ld
== NULL
) {
442 Debug( LDAP_DEBUG_ANY
,
443 "%s: meta_back_search_start candidate=%d ld=NULL%s.\n",
444 op
->o_log_prefix
, candidate
,
445 META_BACK_ONERR_STOP( mi
) ? "" : " (ignored)" );
446 candidates
[ candidate
].sr_err
= LDAP_OTHER
;
447 if ( META_BACK_ONERR_STOP( mi
) ) {
448 return META_SEARCH_ERR
;
450 candidates
[ candidate
].sr_msgid
= META_MSGID_IGNORE
;
451 return META_SEARCH_NOT_CANDIDATE
;
454 Debug( LDAP_DEBUG_TRACE
, "%s >>> meta_back_search_start[%d]\n", op
->o_log_prefix
, candidate
, 0 );
457 * modifies the base according to the scope, if required
459 if ( mt
->mt_nsuffix
.bv_len
> op
->o_req_ndn
.bv_len
) {
460 switch ( op
->ors_scope
) {
461 case LDAP_SCOPE_SUBTREE
:
463 * make the target suffix the new base
464 * FIXME: this is very forgiving, because
465 * "illegal" searchBases may be turned
466 * into the suffix of the target; however,
467 * the requested searchBase already passed
468 * thru the candidate analyzer...
470 if ( dnIsSuffix( &mt
->mt_nsuffix
, &op
->o_req_ndn
) ) {
471 realbase
= mt
->mt_nsuffix
;
472 if ( mt
->mt_scope
== LDAP_SCOPE_SUBORDINATE
) {
473 realscope
= LDAP_SCOPE_SUBORDINATE
;
478 * this target is no longer candidate
480 retcode
= META_SEARCH_NOT_CANDIDATE
;
485 case LDAP_SCOPE_SUBORDINATE
:
486 case LDAP_SCOPE_ONELEVEL
:
488 struct berval rdn
= mt
->mt_nsuffix
;
489 rdn
.bv_len
-= op
->o_req_ndn
.bv_len
+ STRLENOF( "," );
490 if ( dnIsOneLevelRDN( &rdn
)
491 && dnIsSuffix( &mt
->mt_nsuffix
, &op
->o_req_ndn
) )
494 * if there is exactly one level,
495 * make the target suffix the new
496 * base, and make scope "base"
498 realbase
= mt
->mt_nsuffix
;
499 if ( op
->ors_scope
== LDAP_SCOPE_SUBORDINATE
) {
500 if ( mt
->mt_scope
== LDAP_SCOPE_SUBORDINATE
) {
501 realscope
= LDAP_SCOPE_SUBORDINATE
;
503 realscope
= LDAP_SCOPE_SUBTREE
;
506 realscope
= LDAP_SCOPE_BASE
;
509 } /* else continue with the next case */
512 case LDAP_SCOPE_BASE
:
514 * this target is no longer candidate
516 retcode
= META_SEARCH_NOT_CANDIDATE
;
521 /* initiate dobind */
522 retcode
= meta_search_dobind_init( op
, rs
, mcp
, candidate
, candidates
);
524 Debug( LDAP_DEBUG_TRACE
, "%s <<< meta_search_dobind_init[%d]=%d\n", op
->o_log_prefix
, candidate
, retcode
);
526 if ( retcode
!= META_SEARCH_CANDIDATE
) {
531 * Rewrite the search base, if required
534 dc
->ctx
= "searchBase";
535 switch ( ldap_back_dn_massage( dc
, &realbase
, &mbase
) ) {
539 case LDAP_UNWILLING_TO_PERFORM
:
540 rs
->sr_err
= LDAP_UNWILLING_TO_PERFORM
;
541 rs
->sr_text
= "Operation not allowed";
542 send_ldap_result( op
, rs
);
543 retcode
= META_SEARCH_ERR
;
549 * this target is no longer candidate
551 retcode
= META_SEARCH_NOT_CANDIDATE
;
558 rc
= ldap_back_filter_map_rewrite( dc
, op
->ors_filter
,
559 &mfilter
, BACKLDAP_MAP
);
564 case LDAP_COMPARE_FALSE
:
567 * this target is no longer candidate
569 retcode
= META_SEARCH_NOT_CANDIDATE
;
574 * Maps required attributes
576 rc
= ldap_back_map_attrs( &mt
->mt_rwmap
.rwm_at
,
577 op
->ors_attrs
, BACKLDAP_MAP
, &mapped_attrs
);
578 if ( rc
!= LDAP_SUCCESS
) {
580 * this target is no longer candidate
582 retcode
= META_SEARCH_NOT_CANDIDATE
;
586 /* should we check return values? */
587 if ( op
->ors_deref
!= -1 ) {
588 assert( msc
->msc_ld
!= NULL
);
589 (void)ldap_set_option( msc
->msc_ld
, LDAP_OPT_DEREF
,
590 ( void * )&op
->ors_deref
);
593 if ( op
->ors_tlimit
!= SLAP_NO_LIMIT
) {
594 tv
.tv_sec
= op
->ors_tlimit
> 0 ? op
->ors_tlimit
: 1;
601 if ( meta_back_controls_add( op
, rs
, *mcp
, candidate
, &ctrls
)
604 candidates
[ candidate
].sr_msgid
= META_MSGID_IGNORE
;
605 retcode
= META_SEARCH_NOT_CANDIDATE
;
612 assert( msc
->msc_ld
!= NULL
);
613 rc
= ldap_search_ext( msc
->msc_ld
,
614 mbase
.bv_val
, realscope
, mfilter
.bv_val
,
615 mapped_attrs
, op
->ors_attrsonly
,
616 ctrls
, NULL
, tvp
, op
->ors_slimit
,
617 &candidates
[ candidate
].sr_msgid
);
620 retcode
= META_SEARCH_CANDIDATE
;
623 case LDAP_SERVER_DOWN
:
624 if ( nretries
&& meta_back_retry( op
, rs
, mcp
, candidate
, LDAP_BACK_DONTSEND
) ) {
626 /* if the identity changed, there might be need to re-authz */
627 (void)mi
->mi_ldap_extra
->controls_free( op
, rs
, &ctrls
);
631 if ( *mcp
== NULL
) {
632 retcode
= META_SEARCH_ERR
;
633 candidates
[ candidate
].sr_msgid
= META_MSGID_IGNORE
;
639 candidates
[ candidate
].sr_msgid
= META_MSGID_IGNORE
;
640 retcode
= META_SEARCH_NOT_CANDIDATE
;
644 (void)mi
->mi_ldap_extra
->controls_free( op
, rs
, &ctrls
);
646 if ( mapped_attrs
) {
647 free( mapped_attrs
);
649 if ( mfilter
.bv_val
!= op
->ors_filterstr
.bv_val
) {
650 free( mfilter
.bv_val
);
652 if ( mbase
.bv_val
!= realbase
.bv_val
) {
653 free( mbase
.bv_val
);
657 Debug( LDAP_DEBUG_TRACE
, "%s <<< meta_back_search_start[%d]=%d\n", op
->o_log_prefix
, candidate
, retcode
);
663 meta_back_search( Operation
*op
, SlapReply
*rs
)
665 metainfo_t
*mi
= ( metainfo_t
* )op
->o_bd
->be_private
;
667 struct timeval save_tv
= { 0, 0 },
669 time_t stoptime
= (time_t)(-1),
670 lastres_time
= slap_get_time(),
672 int rc
= 0, sres
= LDAP_SUCCESS
;
673 char *matched
= NULL
;
674 int last
= 0, ncandidates
= 0,
675 initial_candidates
= 0, candidate_match
= 0,
677 ldap_back_send_t sendok
= LDAP_BACK_SENDERR
;
682 SlapReply
*candidates
= NULL
;
685 * controls are set in ldap_back_dobind()
687 * FIXME: in case of values return filter, we might want
688 * to map attrs and maybe rewrite value
691 mc
= meta_back_getconn( op
, rs
, NULL
, sendok
);
696 dc
.conn
= op
->o_conn
;
699 if ( candidates
== NULL
) candidates
= meta_back_candidates_get( op
);
703 for ( i
= 0; i
< mi
->mi_ntargets
; i
++ ) {
704 /* reset sr_msgid; it is used in most loops
705 * to check if that target is still to be considered */
706 candidates
[ i
].sr_msgid
= META_MSGID_IGNORE
;
708 /* a target is marked as candidate by meta_back_getconn();
709 * if for any reason (an error, it's over or so) it is
710 * no longer active, sr_msgid is set to META_MSGID_IGNORE
711 * but it remains candidate, which means it has been active
712 * at some point during the operation. This allows to
713 * use its response code and more to compute the final
715 if ( !META_IS_CANDIDATE( &candidates
[ i
] ) ) {
719 candidates
[ i
].sr_matched
= NULL
;
720 candidates
[ i
].sr_text
= NULL
;
721 candidates
[ i
].sr_ref
= NULL
;
722 candidates
[ i
].sr_ctrls
= NULL
;
724 /* get largest timeout among candidates */
725 if ( mi
->mi_targets
[ i
]->mt_timeout
[ SLAP_OP_SEARCH
]
726 && mi
->mi_targets
[ i
]->mt_timeout
[ SLAP_OP_SEARCH
] > timeout
)
728 timeout
= mi
->mi_targets
[ i
]->mt_timeout
[ SLAP_OP_SEARCH
];
732 for ( i
= 0; i
< mi
->mi_ntargets
; i
++ ) {
733 if ( !META_IS_CANDIDATE( &candidates
[ i
] )
734 || candidates
[ i
].sr_err
!= LDAP_SUCCESS
)
739 switch ( meta_back_search_start( op
, rs
, &dc
, &mc
, i
, candidates
) )
741 case META_SEARCH_NOT_CANDIDATE
:
742 candidates
[ i
].sr_msgid
= META_MSGID_IGNORE
;
745 case META_SEARCH_NEED_BIND
:
749 case META_SEARCH_CONNECTING
:
750 case META_SEARCH_CANDIDATE
:
751 case META_SEARCH_BINDING
:
752 candidates
[ i
].sr_type
= REP_INTERMEDIATE
;
756 case META_SEARCH_ERR
:
757 savepriv
= op
->o_private
;
758 op
->o_private
= (void *)i
;
759 send_ldap_result( op
, rs
);
760 op
->o_private
= savepriv
;
770 if ( ncandidates
> 0 && needbind
== ncandidates
) {
772 * give up the second time...
774 * NOTE: this should not occur the second time, since a fresh
775 * connection has ben created; however, targets may also
776 * need bind because the bind timed out or so.
778 if ( sendok
& LDAP_BACK_BINDING
) {
779 Debug( LDAP_DEBUG_ANY
,
780 "%s meta_back_search: unable to initialize conn\n",
781 op
->o_log_prefix
, 0, 0 );
782 rs
->sr_err
= LDAP_UNAVAILABLE
;
783 rs
->sr_text
= "unable to initialize connection to remote targets";
784 send_ldap_result( op
, rs
);
789 /* FIXME: better create a separate connection? */
790 sendok
|= LDAP_BACK_BINDING
;
793 Debug( LDAP_DEBUG_ANY
, "*** %s drop mc=%p create new connection\n",
794 op
->o_log_prefix
, (void *)mc
, 0 );
795 #endif /* DEBUG_205 */
797 meta_back_release_conn( mi
, mc
);
806 initial_candidates
= ncandidates
;
808 if ( LogTest( LDAP_DEBUG_TRACE
) ) {
809 char cnd
[ SLAP_TEXT_BUFLEN
];
812 for ( c
= 0; c
< mi
->mi_ntargets
; c
++ ) {
813 if ( META_IS_CANDIDATE( &candidates
[ c
] ) ) {
821 Debug( LDAP_DEBUG_TRACE
, "%s meta_back_search: ncandidates=%d "
822 "cnd=\"%s\"\n", op
->o_log_prefix
, ncandidates
, cnd
);
825 if ( initial_candidates
== 0 ) {
826 /* NOTE: here we are not sending any matchedDN;
827 * this is intended, because if the back-meta
828 * is serving this search request, but no valid
829 * candidate could be looked up, it means that
830 * there is a hole in the mapping of the targets
831 * and thus no knowledge of any remote superior
833 Debug( LDAP_DEBUG_ANY
, "%s meta_back_search: "
834 "base=\"%s\" scope=%d: "
835 "no candidate could be selected\n",
836 op
->o_log_prefix
, op
->o_req_dn
.bv_val
,
839 /* FIXME: we're sending the first error we encounter;
840 * maybe we should pick the worst... */
841 rc
= LDAP_NO_SUCH_OBJECT
;
842 for ( i
= 0; i
< mi
->mi_ntargets
; i
++ ) {
843 if ( META_IS_CANDIDATE( &candidates
[ i
] )
844 && candidates
[ i
].sr_err
!= LDAP_SUCCESS
)
846 rc
= candidates
[ i
].sr_err
;
851 send_ldap_error( op
, rs
, rc
, NULL
);
856 /* We pull apart the ber result, stuff it into a slapd entry, and
857 * let send_search_entry stuff it back into ber format. Slow & ugly,
858 * but this is necessary for version matching, and for ACL processing.
861 if ( op
->ors_tlimit
!= SLAP_NO_LIMIT
) {
862 stoptime
= op
->o_time
+ op
->ors_tlimit
;
866 * In case there are no candidates, no cycle takes place...
868 * FIXME: we might use a queue, to better balance the load
869 * among the candidates
871 for ( rc
= 0; ncandidates
> 0; ) {
874 alreadybound
= ncandidates
;
877 if ( timeout
&& lastres_time
> 0
878 && ( slap_get_time() - lastres_time
) > timeout
)
881 rs
->sr_text
= "Operation timed out";
882 rc
= rs
->sr_err
= op
->o_protocol
>= LDAP_VERSION3
?
883 LDAP_ADMINLIMIT_EXCEEDED
: LDAP_OTHER
;
884 savepriv
= op
->o_private
;
885 op
->o_private
= (void *)i
;
886 send_ldap_result( op
, rs
);
887 op
->o_private
= savepriv
;
891 /* check time limit */
892 if ( op
->ors_tlimit
!= SLAP_NO_LIMIT
893 && slap_get_time() > stoptime
)
896 rc
= rs
->sr_err
= LDAP_TIMELIMIT_EXCEEDED
;
897 savepriv
= op
->o_private
;
898 op
->o_private
= (void *)i
;
899 send_ldap_result( op
, rs
);
900 op
->o_private
= savepriv
;
904 for ( i
= 0; i
< mi
->mi_ntargets
; i
++ ) {
905 meta_search_candidate_t retcode
= META_SEARCH_UNDEFINED
;
906 metasingleconn_t
*msc
= &mc
->mc_conns
[ i
];
907 LDAPMessage
*res
= NULL
, *msg
;
909 /* if msgid is invalid, don't ldap_result() */
910 if ( candidates
[ i
].sr_msgid
== META_MSGID_IGNORE
) {
914 /* if target still needs bind, retry */
915 if ( candidates
[ i
].sr_msgid
== META_MSGID_NEED_BIND
916 || candidates
[ i
].sr_msgid
== META_MSGID_CONNECTING
)
918 /* initiate dobind */
919 retcode
= meta_search_dobind_init( op
, rs
, &mc
, i
, candidates
);
921 Debug( LDAP_DEBUG_TRACE
, "%s <<< meta_search_dobind_init[%ld]=%d\n",
922 op
->o_log_prefix
, i
, retcode
);
925 case META_SEARCH_NEED_BIND
:
929 case META_SEARCH_CONNECTING
:
930 case META_SEARCH_BINDING
:
933 case META_SEARCH_ERR
:
934 candidates
[ i
].sr_err
= rs
->sr_err
;
935 if ( META_BACK_ONERR_STOP( mi
) ) {
936 savepriv
= op
->o_private
;
937 op
->o_private
= (void *)i
;
938 send_ldap_result( op
, rs
);
939 op
->o_private
= savepriv
;
944 case META_SEARCH_NOT_CANDIDATE
:
946 * When no candidates are left,
947 * the outer cycle finishes
949 candidates
[ i
].sr_msgid
= META_MSGID_IGNORE
;
950 assert( ncandidates
> 0 );
954 case META_SEARCH_CANDIDATE
:
955 candidates
[ i
].sr_msgid
= META_MSGID_IGNORE
;
956 switch ( meta_back_search_start( op
, rs
, &dc
, &mc
, i
, candidates
) )
958 case META_SEARCH_CANDIDATE
:
959 assert( candidates
[ i
].sr_msgid
>= 0 );
962 case META_SEARCH_ERR
:
963 candidates
[ i
].sr_err
= rs
->sr_err
;
964 if ( META_BACK_ONERR_STOP( mi
) ) {
965 savepriv
= op
->o_private
;
966 op
->o_private
= (void *)i
;
967 send_ldap_result( op
, rs
);
968 op
->o_private
= savepriv
;
973 case META_SEARCH_NOT_CANDIDATE
:
974 /* means that meta_back_search_start()
975 * failed but onerr == continue */
976 candidates
[ i
].sr_msgid
= META_MSGID_IGNORE
;
977 assert( ncandidates
> 0 );
996 /* check for abandon */
997 if ( op
->o_abandon
|| LDAP_BACK_CONN_ABANDON( mc
) ) {
1002 if ( msc
->msc_ld
== NULL
) {
1003 char buf
[ SLAP_TEXT_BUFLEN
];
1005 ldap_pvt_thread_mutex_lock( &mi
->mi_conninfo
.lai_mutex
);
1006 snprintf( buf
, sizeof( buf
),
1007 "%s meta_back_search[%ld] mc=%p msgid=%d%s%s%s\n",
1008 op
->o_log_prefix
, (long)i
, (void *)mc
,
1009 candidates
[ i
].sr_msgid
,
1010 META_IS_BINDING( &candidates
[ i
] ) ? " binding" : "",
1011 LDAP_BACK_CONN_BINDING( &mc
->mc_conns
[ i
] ) ? " connbinding" : "",
1012 META_BACK_CONN_CREATING( &mc
->mc_conns
[ i
] ) ? " conncreating" : "" );
1013 ldap_pvt_thread_mutex_unlock( &mi
->mi_conninfo
.lai_mutex
);
1015 Debug( LDAP_DEBUG_ANY
, "!!! %s\n", buf
, 0, 0 );
1017 #endif /* DEBUG_205 */
1020 * FIXME: handle time limit as well?
1021 * Note that target servers are likely
1022 * to handle it, so at some time we'll
1023 * get a LDAP_TIMELIMIT_EXCEEDED from
1027 rc
= ldap_result( msc
->msc_ld
, candidates
[ i
].sr_msgid
,
1028 LDAP_MSG_RECEIVED
, &tv
, &res
);
1031 /* FIXME: res should not need to be freed */
1032 assert( res
== NULL
);
1037 /* something REALLY bad happened! */
1038 if ( candidates
[ i
].sr_type
== REP_INTERMEDIATE
) {
1039 candidates
[ i
].sr_type
= REP_RESULT
;
1041 if ( meta_back_retry( op
, rs
, &mc
, i
, LDAP_BACK_DONTSEND
) ) {
1042 candidates
[ i
].sr_msgid
= META_MSGID_IGNORE
;
1043 switch ( meta_back_search_start( op
, rs
, &dc
, &mc
, i
, candidates
) )
1045 /* means that failed but onerr == continue */
1046 case META_SEARCH_NOT_CANDIDATE
:
1047 candidates
[ i
].sr_msgid
= META_MSGID_IGNORE
;
1049 assert( ncandidates
> 0 );
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
;
1062 case META_SEARCH_CANDIDATE
:
1063 /* get back into business... */
1066 case META_SEARCH_BINDING
:
1067 case META_SEARCH_CONNECTING
:
1068 case META_SEARCH_NEED_BIND
:
1069 case META_SEARCH_UNDEFINED
:
1073 /* unrecoverable error */
1074 candidates
[ i
].sr_msgid
= META_MSGID_IGNORE
;
1075 rc
= rs
->sr_err
= LDAP_OTHER
;
1080 candidates
[ i
].sr_err
= rs
->sr_err
;
1081 if ( META_BACK_ONERR_STOP( mi
) ) {
1082 savepriv
= op
->o_private
;
1083 op
->o_private
= (void *)i
;
1084 send_ldap_result( op
, rs
);
1085 op
->o_private
= savepriv
;
1091 * When no candidates are left,
1092 * the outer cycle finishes
1094 candidates
[ i
].sr_msgid
= META_MSGID_IGNORE
;
1095 assert( ncandidates
> 0 );
1097 rs
->sr_err
= candidates
[ i
].sr_err
;
1101 lastres_time
= slap_get_time();
1103 /* only touch when activity actually took place... */
1104 if ( mi
->mi_idle_timeout
!= 0 && msc
->msc_time
< lastres_time
) {
1105 msc
->msc_time
= lastres_time
;
1110 for ( msg
= ldap_first_message( msc
->msc_ld
, res
);
1112 msg
= ldap_next_message( msc
->msc_ld
, msg
) )
1114 rc
= ldap_msgtype( msg
);
1115 if ( rc
== LDAP_RES_SEARCH_ENTRY
) {
1118 if ( candidates
[ i
].sr_type
== REP_INTERMEDIATE
) {
1119 /* don't retry any more... */
1120 candidates
[ i
].sr_type
= REP_RESULT
;
1125 e
= ldap_first_entry( msc
->msc_ld
, msg
);
1126 savepriv
= op
->o_private
;
1127 op
->o_private
= (void *)i
;
1128 rs
->sr_err
= meta_send_entry( op
, rs
, mc
, i
, e
);
1130 switch ( rs
->sr_err
) {
1131 case LDAP_SIZELIMIT_EXCEEDED
:
1132 savepriv
= op
->o_private
;
1133 op
->o_private
= (void *)i
;
1134 send_ldap_result( op
, rs
);
1135 op
->o_private
= savepriv
;
1136 rs
->sr_err
= LDAP_SUCCESS
;
1137 ldap_msgfree( res
);
1141 case LDAP_UNAVAILABLE
:
1142 rs
->sr_err
= LDAP_OTHER
;
1143 ldap_msgfree( res
);
1147 op
->o_private
= savepriv
;
1149 /* don't wait any longer... */
1152 save_tv
.tv_usec
= 0;
1154 } else if ( rc
== LDAP_RES_SEARCH_REFERENCE
) {
1155 char **references
= NULL
;
1158 if ( META_BACK_TGT_NOREFS( mi
->mi_targets
[ i
] ) ) {
1162 if ( candidates
[ i
].sr_type
== REP_INTERMEDIATE
) {
1163 /* don't retry any more... */
1164 candidates
[ i
].sr_type
= REP_RESULT
;
1169 rc
= ldap_parse_reference( msc
->msc_ld
, msg
,
1170 &references
, &rs
->sr_ctrls
, 0 );
1172 if ( rc
!= LDAP_SUCCESS
) {
1176 if ( references
== NULL
) {
1180 #ifdef ENABLE_REWRITE
1181 dc
.ctx
= "referralDN";
1182 #else /* ! ENABLE_REWRITE */
1185 #endif /* ! ENABLE_REWRITE */
1187 /* FIXME: merge all and return at the end */
1189 for ( cnt
= 0; references
[ cnt
]; cnt
++ )
1192 rs
->sr_ref
= ch_calloc( sizeof( struct berval
), cnt
+ 1 );
1194 for ( cnt
= 0; references
[ cnt
]; cnt
++ ) {
1195 ber_str2bv( references
[ cnt
], 0, 1, &rs
->sr_ref
[ cnt
] );
1197 BER_BVZERO( &rs
->sr_ref
[ cnt
] );
1199 ( void )ldap_back_referral_result_rewrite( &dc
, rs
->sr_ref
);
1201 if ( rs
->sr_ref
!= NULL
&& !BER_BVISNULL( &rs
->sr_ref
[ 0 ] ) ) {
1202 /* ignore return value by now */
1203 savepriv
= op
->o_private
;
1204 op
->o_private
= (void *)i
;
1205 ( void )send_search_reference( op
, rs
);
1206 op
->o_private
= savepriv
;
1208 ber_bvarray_free( rs
->sr_ref
);
1214 ber_memvfree( (void **)references
);
1217 if ( rs
->sr_ctrls
) {
1218 ldap_controls_free( rs
->sr_ctrls
);
1219 rs
->sr_ctrls
= NULL
;
1222 } else if ( rc
== LDAP_RES_SEARCH_RESULT
) {
1223 char buf
[ SLAP_TEXT_BUFLEN
];
1224 char **references
= NULL
;
1226 if ( candidates
[ i
].sr_type
== REP_INTERMEDIATE
) {
1227 /* don't retry any more... */
1228 candidates
[ i
].sr_type
= REP_RESULT
;
1231 candidates
[ i
].sr_msgid
= META_MSGID_IGNORE
;
1233 /* NOTE: ignores response controls
1234 * (and intermediate response controls
1235 * as well, except for those with search
1236 * references); this may not be correct,
1237 * but if they're not ignored then
1238 * back-meta would need to merge them
1239 * consistently (think of pagedResults...)
1241 /* FIXME: response controls? */
1242 rs
->sr_err
= ldap_parse_result( msc
->msc_ld
,
1244 &candidates
[ i
].sr_err
,
1245 (char **)&candidates
[ i
].sr_matched
,
1246 NULL
/* (char **)&candidates[ i ].sr_text */ ,
1248 NULL
/* &candidates[ i ].sr_ctrls (unused) */ ,
1250 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
1251 sres
= slap_map_api2result( &candidates
[ i
] );
1252 candidates
[ i
].sr_type
= REP_RESULT
;
1253 ldap_msgfree( res
);
1258 rs
->sr_err
= candidates
[ i
].sr_err
;
1260 /* massage matchedDN if need be */
1261 if ( candidates
[ i
].sr_matched
!= NULL
) {
1262 struct berval match
, mmatch
;
1264 ber_str2bv( candidates
[ i
].sr_matched
,
1266 candidates
[ i
].sr_matched
= NULL
;
1268 dc
.ctx
= "matchedDN";
1269 dc
.target
= mi
->mi_targets
[ i
];
1270 if ( !ldap_back_dn_massage( &dc
, &match
, &mmatch
) ) {
1271 if ( mmatch
.bv_val
== match
.bv_val
) {
1272 candidates
[ i
].sr_matched
1273 = ch_strdup( mmatch
.bv_val
);
1276 candidates
[ i
].sr_matched
= mmatch
.bv_val
;
1281 ldap_memfree( match
.bv_val
);
1284 /* add references to array */
1285 /* RFC 4511: referrals can only appear
1286 * if result code is LDAP_REFERRAL */
1287 if ( references
!= NULL
1288 && references
[ 0 ] != NULL
1289 && references
[ 0 ][ 0 ] != '\0' )
1291 if ( rs
->sr_err
!= LDAP_REFERRAL
) {
1292 Debug( LDAP_DEBUG_ANY
,
1293 "%s meta_back_search[%ld]: "
1294 "got referrals with err=%d\n",
1302 for ( cnt
= 0; references
[ cnt
]; cnt
++ )
1305 sr_ref
= ch_calloc( sizeof( struct berval
), cnt
+ 1 );
1307 for ( cnt
= 0; references
[ cnt
]; cnt
++ ) {
1308 ber_str2bv( references
[ cnt
], 0, 1, &sr_ref
[ cnt
] );
1310 BER_BVZERO( &sr_ref
[ cnt
] );
1312 ( void )ldap_back_referral_result_rewrite( &dc
, sr_ref
);
1314 if ( rs
->sr_v2ref
== NULL
) {
1315 rs
->sr_v2ref
= sr_ref
;
1318 for ( cnt
= 0; !BER_BVISNULL( &sr_ref
[ cnt
] ); cnt
++ ) {
1319 ber_bvarray_add( &rs
->sr_v2ref
, &sr_ref
[ cnt
] );
1321 ber_memfree( sr_ref
);
1325 } else if ( rs
->sr_err
== LDAP_REFERRAL
) {
1326 Debug( LDAP_DEBUG_ANY
,
1327 "%s meta_back_search[%ld]: "
1328 "got err=%d with null "
1329 "or empty referrals\n",
1333 rs
->sr_err
= LDAP_NO_SUCH_OBJECT
;
1337 ber_memvfree( (void **)references
);
1339 sres
= slap_map_api2result( rs
);
1341 if ( LogTest( LDAP_DEBUG_TRACE
| LDAP_DEBUG_ANY
) ) {
1342 snprintf( buf
, sizeof( buf
),
1343 "%s meta_back_search[%ld] "
1344 "match=\"%s\" err=%ld",
1345 op
->o_log_prefix
, i
,
1346 candidates
[ i
].sr_matched
? candidates
[ i
].sr_matched
: "",
1347 (long) candidates
[ i
].sr_err
);
1348 if ( candidates
[ i
].sr_err
== LDAP_SUCCESS
) {
1349 Debug( LDAP_DEBUG_TRACE
, "%s.\n", buf
, 0, 0 );
1352 Debug( LDAP_DEBUG_ANY
, "%s (%s).\n",
1353 buf
, ldap_err2string( candidates
[ i
].sr_err
), 0 );
1358 case LDAP_NO_SUCH_OBJECT
:
1359 /* is_ok is touched any time a valid
1360 * (even intermediate) result is
1361 * returned; as a consequence, if
1362 * a candidate returns noSuchObject
1363 * it is ignored and the candidate
1364 * is simply demoted. */
1366 sres
= LDAP_SUCCESS
;
1375 case LDAP_SIZELIMIT_EXCEEDED
:
1376 /* if a target returned sizelimitExceeded
1377 * and the entry count is equal to the
1378 * proxy's limit, the target would have
1379 * returned more, and the error must be
1380 * propagated to the client; otherwise,
1381 * the target enforced a limit lower
1382 * than what requested by the proxy;
1384 candidates
[ i
].sr_err
= rs
->sr_err
;
1385 if ( rs
->sr_nentries
== op
->ors_slimit
1386 || META_BACK_ONERR_STOP( mi
) )
1388 savepriv
= op
->o_private
;
1389 op
->o_private
= (void *)i
;
1390 send_ldap_result( op
, rs
);
1391 op
->o_private
= savepriv
;
1392 ldap_msgfree( res
);
1399 candidates
[ i
].sr_err
= rs
->sr_err
;
1400 if ( META_BACK_ONERR_STOP( mi
) ) {
1401 savepriv
= op
->o_private
;
1402 op
->o_private
= (void *)i
;
1403 send_ldap_result( op
, rs
);
1404 op
->o_private
= savepriv
;
1405 ldap_msgfree( res
);
1416 * When no candidates are left,
1417 * the outer cycle finishes
1419 assert( ncandidates
> 0 );
1422 } else if ( rc
== LDAP_RES_BIND
) {
1423 meta_search_candidate_t retcode
;
1425 retcode
= meta_search_dobind_result( op
, rs
, &mc
, i
, candidates
, msg
);
1426 if ( retcode
== META_SEARCH_CANDIDATE
) {
1427 candidates
[ i
].sr_msgid
= META_MSGID_IGNORE
;
1428 retcode
= meta_back_search_start( op
, rs
, &dc
, &mc
, i
, candidates
);
1431 switch ( retcode
) {
1432 case META_SEARCH_CANDIDATE
:
1435 /* means that failed but onerr == continue */
1436 case META_SEARCH_NOT_CANDIDATE
:
1437 case META_SEARCH_ERR
:
1438 candidates
[ i
].sr_msgid
= META_MSGID_IGNORE
;
1439 assert( ncandidates
> 0 );
1442 candidates
[ i
].sr_err
= rs
->sr_err
;
1443 if ( META_BACK_ONERR_STOP( mi
) ) {
1444 savepriv
= op
->o_private
;
1445 op
->o_private
= (void *)i
;
1446 send_ldap_result( op
, rs
);
1447 op
->o_private
= savepriv
;
1448 ldap_msgfree( res
);
1461 ldap_msgfree( res
);
1468 ldap_msgfree( res
);
1472 /* check for abandon */
1473 if ( op
->o_abandon
|| LDAP_BACK_CONN_ABANDON( mc
) ) {
1474 for ( i
= 0; i
< mi
->mi_ntargets
; i
++ ) {
1475 if ( candidates
[ i
].sr_msgid
>= 0
1476 || candidates
[ i
].sr_msgid
== META_MSGID_CONNECTING
)
1478 if ( META_IS_BINDING( &candidates
[ i
] )
1479 || candidates
[ i
].sr_msgid
== META_MSGID_CONNECTING
)
1481 ldap_pvt_thread_mutex_lock( &mi
->mi_conninfo
.lai_mutex
);
1482 if ( LDAP_BACK_CONN_BINDING( &mc
->mc_conns
[ i
] )
1483 || candidates
[ i
].sr_msgid
== META_MSGID_CONNECTING
)
1485 /* if still binding, destroy */
1488 char buf
[ SLAP_TEXT_BUFLEN
];
1490 snprintf( buf
, sizeof( buf
), "%s meta_back_search(abandon) "
1491 "ldap_unbind_ext[%ld] mc=%p ld=%p",
1492 op
->o_log_prefix
, i
, (void *)mc
,
1493 (void *)mc
->mc_conns
[i
].msc_ld
);
1495 Debug( LDAP_DEBUG_ANY
, "### %s\n", buf
, 0, 0 );
1496 #endif /* DEBUG_205 */
1498 meta_clear_one_candidate( op
, mc
, i
);
1500 ldap_pvt_thread_mutex_unlock( &mi
->mi_conninfo
.lai_mutex
);
1501 META_BINDING_CLEAR( &candidates
[ i
] );
1504 (void)meta_back_cancel( mc
, op
, rs
,
1505 candidates
[ i
].sr_msgid
, i
,
1506 LDAP_BACK_DONTSEND
);
1509 candidates
[ i
].sr_msgid
= META_MSGID_IGNORE
;
1510 assert( ncandidates
> 0 );
1515 if ( op
->o_abandon
) {
1519 /* let send_ldap_result play cleanup handlers (ITS#4645) */
1523 /* if no entry was found during this loop,
1524 * set a minimal timeout */
1525 if ( ncandidates
> 0 && gotit
== 0 ) {
1526 if ( save_tv
.tv_sec
== 0 && save_tv
.tv_usec
== 0 ) {
1527 save_tv
.tv_usec
= LDAP_BACK_RESULT_UTIMEOUT
/initial_candidates
;
1529 /* arbitrarily limit to something between 1 and 2 minutes */
1530 } else if ( ( stoptime
== -1 && save_tv
.tv_sec
< 60 )
1531 || save_tv
.tv_sec
< ( stoptime
- slap_get_time() ) / ( 2 * ncandidates
) )
1533 /* double the timeout */
1534 lutil_timermul( &save_tv
, 2, &save_tv
);
1537 if ( alreadybound
== 0 ) {
1539 (void)select( 0, NULL
, NULL
, NULL
, &tv
);
1542 ldap_pvt_thread_yield();
1549 * FIXME: need a better strategy to handle errors
1552 rc
= meta_back_op_result( mc
, op
, rs
, META_TARGET_NONE
,
1553 -1, stoptime
!= -1 ? (stoptime
- slap_get_time()) : 0,
1554 LDAP_BACK_SENDERR
);
1562 * Rewrite the matched portion of the search base, if required
1564 * FIXME: only the last one gets caught!
1566 savepriv
= op
->o_private
;
1567 op
->o_private
= (void *)(long)mi
->mi_ntargets
;
1568 if ( candidate_match
> 0 ) {
1569 struct berval pmatched
= BER_BVNULL
;
1571 /* we use the first one */
1572 for ( i
= 0; i
< mi
->mi_ntargets
; i
++ ) {
1573 if ( META_IS_CANDIDATE( &candidates
[ i
] )
1574 && candidates
[ i
].sr_matched
!= NULL
)
1576 struct berval bv
, pbv
;
1579 /* if we got success, and this target
1580 * returned noSuchObject, and its suffix
1581 * is a superior of the searchBase,
1582 * ignore the matchedDN */
1583 if ( sres
== LDAP_SUCCESS
1584 && candidates
[ i
].sr_err
== LDAP_NO_SUCH_OBJECT
1585 && op
->o_req_ndn
.bv_len
> mi
->mi_targets
[ i
]->mt_nsuffix
.bv_len
)
1587 free( (char *)candidates
[ i
].sr_matched
);
1588 candidates
[ i
].sr_matched
= NULL
;
1592 ber_str2bv( candidates
[ i
].sr_matched
, 0, 0, &bv
);
1593 rc
= dnPretty( NULL
, &bv
, &pbv
, op
->o_tmpmemctx
);
1595 if ( rc
== LDAP_SUCCESS
) {
1597 /* NOTE: if they all are superiors
1598 * of the baseDN, the shorter is also
1599 * superior of the longer... */
1600 if ( pbv
.bv_len
> pmatched
.bv_len
) {
1601 if ( !BER_BVISNULL( &pmatched
) ) {
1602 op
->o_tmpfree( pmatched
.bv_val
, op
->o_tmpmemctx
);
1605 op
->o_private
= (void *)i
;
1608 op
->o_tmpfree( pbv
.bv_val
, op
->o_tmpmemctx
);
1612 if ( candidates
[ i
].sr_matched
!= NULL
) {
1613 free( (char *)candidates
[ i
].sr_matched
);
1614 candidates
[ i
].sr_matched
= NULL
;
1619 if ( !BER_BVISNULL( &pmatched
) ) {
1620 matched
= pmatched
.bv_val
;
1623 } else if ( sres
== LDAP_NO_SUCH_OBJECT
) {
1624 matched
= op
->o_bd
->be_suffix
[ 0 ].bv_val
;
1628 * In case we returned at least one entry, we return LDAP_SUCCESS
1629 * otherwise, the latter error code we got
1632 if ( sres
== LDAP_SUCCESS
) {
1633 if ( rs
->sr_v2ref
) {
1634 sres
= LDAP_REFERRAL
;
1637 if ( META_BACK_ONERR_REPORT( mi
) ) {
1639 * Report errors, if any
1641 * FIXME: we should handle error codes and return the more
1642 * important/reasonable
1644 for ( i
= 0; i
< mi
->mi_ntargets
; i
++ ) {
1645 if ( !META_IS_CANDIDATE( &candidates
[ i
] ) ) {
1649 if ( candidates
[ i
].sr_err
!= LDAP_SUCCESS
1650 && candidates
[ i
].sr_err
!= LDAP_NO_SUCH_OBJECT
)
1652 sres
= candidates
[ i
].sr_err
;
1660 rs
->sr_matched
= matched
;
1661 rs
->sr_ref
= ( sres
== LDAP_REFERRAL
? rs
->sr_v2ref
: NULL
);
1662 send_ldap_result( op
, rs
);
1663 op
->o_private
= savepriv
;
1664 rs
->sr_matched
= NULL
;
1668 if ( matched
&& matched
!= op
->o_bd
->be_suffix
[ 0 ].bv_val
) {
1669 op
->o_tmpfree( matched
, op
->o_tmpmemctx
);
1672 if ( rs
->sr_v2ref
) {
1673 ber_bvarray_free( rs
->sr_v2ref
);
1676 for ( i
= 0; i
< mi
->mi_ntargets
; i
++ ) {
1677 if ( !META_IS_CANDIDATE( &candidates
[ i
] ) ) {
1682 if ( META_IS_BINDING( &candidates
[ i
] )
1683 || candidates
[ i
].sr_msgid
== META_MSGID_CONNECTING
)
1685 ldap_pvt_thread_mutex_lock( &mi
->mi_conninfo
.lai_mutex
);
1686 if ( LDAP_BACK_CONN_BINDING( &mc
->mc_conns
[ i
] )
1687 || candidates
[ i
].sr_msgid
== META_MSGID_CONNECTING
)
1689 assert( candidates
[ i
].sr_msgid
>= 0
1690 || candidates
[ i
].sr_msgid
== META_MSGID_CONNECTING
);
1691 assert( mc
->mc_conns
[ i
].msc_ld
!= NULL
);
1694 Debug( LDAP_DEBUG_ANY
, "### %s meta_back_search(cleanup) "
1695 "ldap_unbind_ext[%ld] ld=%p\n",
1696 op
->o_log_prefix
, i
, (void *)mc
->mc_conns
[i
].msc_ld
);
1697 #endif /* DEBUG_205 */
1699 /* if still binding, destroy */
1700 meta_clear_one_candidate( op
, mc
, i
);
1702 ldap_pvt_thread_mutex_unlock( &mi
->mi_conninfo
.lai_mutex
);
1703 META_BINDING_CLEAR( &candidates
[ i
] );
1705 } else if ( candidates
[ i
].sr_msgid
>= 0 ) {
1706 (void)meta_back_cancel( mc
, op
, rs
,
1707 candidates
[ i
].sr_msgid
, i
,
1708 LDAP_BACK_DONTSEND
);
1712 if ( candidates
[ i
].sr_matched
) {
1713 free( (char *)candidates
[ i
].sr_matched
);
1714 candidates
[ i
].sr_matched
= NULL
;
1717 if ( candidates
[ i
].sr_text
) {
1718 ldap_memfree( (char *)candidates
[ i
].sr_text
);
1719 candidates
[ i
].sr_text
= NULL
;
1722 if ( candidates
[ i
].sr_ref
) {
1723 ber_bvarray_free( candidates
[ i
].sr_ref
);
1724 candidates
[ i
].sr_ref
= NULL
;
1727 if ( candidates
[ i
].sr_ctrls
) {
1728 ldap_controls_free( candidates
[ i
].sr_ctrls
);
1729 candidates
[ i
].sr_ctrls
= NULL
;
1732 if ( META_BACK_TGT_QUARANTINE( mi
->mi_targets
[ i
] ) ) {
1733 meta_back_quarantine( op
, &candidates
[ i
], i
);
1736 /* only in case of timelimit exceeded, if the timelimit exceeded because
1737 * one contacted target never responded, invalidate the connection
1738 * NOTE: should we quarantine the target as well? right now, the connection
1739 * is invalidated; the next time it will be recreated and the target
1740 * will be quarantined if it cannot be contacted */
1741 if ( mi
->mi_idle_timeout
!= 0
1742 && rs
->sr_err
== LDAP_TIMELIMIT_EXCEEDED
1743 && op
->o_time
> mc
->mc_conns
[ i
].msc_time
)
1745 /* don't let anyone else use this expired connection */
1746 LDAP_BACK_CONN_TAINTED_SET( mc
);
1751 meta_back_release_conn( mi
, mc
);
1765 metainfo_t
*mi
= ( metainfo_t
* )op
->o_bd
->be_private
;
1766 struct berval a
, mapped
;
1767 int check_duplicate_attrs
= 0;
1769 BerElement ber
= *e
->lm_ber
;
1770 Attribute
*attr
, **attrp
;
1777 if ( ber_scanf( &ber
, "{m{", &bdn
) == LBER_ERROR
) {
1778 return LDAP_DECODING_ERROR
;
1782 * Rewrite the dn of the result, if needed
1784 dc
.target
= mi
->mi_targets
[ target
];
1785 dc
.conn
= op
->o_conn
;
1787 dc
.ctx
= "searchResult";
1789 rs
->sr_err
= ldap_back_dn_massage( &dc
, &bdn
, &dn
);
1790 if ( rs
->sr_err
!= LDAP_SUCCESS
) {
1795 * Note: this may fail if the target host(s) schema differs
1796 * from the one known to the meta, and a DN with unknown
1797 * attributes is returned.
1799 * FIXME: should we log anything, or delegate to dnNormalize?
1801 rc
= dnPrettyNormal( NULL
, &dn
, &ent
.e_name
, &ent
.e_nname
,
1803 if ( dn
.bv_val
!= bdn
.bv_val
) {
1808 if ( rc
!= LDAP_SUCCESS
) {
1809 return LDAP_INVALID_DN_SYNTAX
;
1815 if ( mi
->mi_cache
.ttl
!= META_DNCACHE_DISABLED
) {
1816 ( void )meta_dncache_update_entry( &mi
->mi_cache
,
1817 &ent
.e_nname
, target
);
1820 attrp
= &ent
.e_attrs
;
1822 dc
.ctx
= "searchAttrDN";
1823 while ( ber_scanf( &ber
, "{m", &a
) != LBER_ERROR
) {
1825 slap_syntax_validate_func
*validate
;
1826 slap_syntax_transform_func
*pretty
;
1828 ldap_back_map( &mi
->mi_targets
[ target
]->mt_rwmap
.rwm_at
,
1829 &a
, &mapped
, BACKLDAP_REMAP
);
1830 if ( BER_BVISNULL( &mapped
) || mapped
.bv_val
[0] == '\0' ) {
1831 ( void )ber_scanf( &ber
, "x" /* [W] */ );
1834 if ( mapped
.bv_val
!= a
.bv_val
) {
1835 /* will need to check for duplicate attrs */
1836 check_duplicate_attrs
++;
1838 attr
= attr_alloc( NULL
);
1839 if ( attr
== NULL
) {
1842 if ( slap_bv2ad( &mapped
, &attr
->a_desc
, &text
)
1844 if ( slap_bv2undef_ad( &mapped
, &attr
->a_desc
, &text
,
1845 SLAP_AD_PROXIED
) != LDAP_SUCCESS
)
1847 char buf
[ SLAP_TEXT_BUFLEN
];
1849 snprintf( buf
, sizeof( buf
),
1850 "%s meta_send_entry(\"%s\"): "
1851 "slap_bv2undef_ad(%s): %s\n",
1852 op
->o_log_prefix
, ent
.e_name
.bv_val
,
1853 mapped
.bv_val
, text
);
1855 Debug( LDAP_DEBUG_ANY
, "%s", buf
, 0, 0 );
1861 /* no subschemaSubentry */
1862 if ( attr
->a_desc
== slap_schema
.si_ad_subschemaSubentry
1863 || attr
->a_desc
== slap_schema
.si_ad_entryDN
)
1867 * We eat target's subschemaSubentry because
1868 * a search for this value is likely not
1869 * to resolve to the appropriate backend;
1870 * later, the local subschemaSubentry is
1873 * We also eat entryDN because the frontend
1874 * will reattach it without checking if already
1877 ( void )ber_scanf( &ber
, "x" /* [W] */ );
1883 if ( ber_scanf( &ber
, "[W]", &attr
->a_vals
) == LBER_ERROR
1884 || attr
->a_vals
== NULL
)
1886 attr
->a_vals
= (struct berval
*)&slap_dummy_bv
;
1889 for ( last
= 0; !BER_BVISNULL( &attr
->a_vals
[ last
] ); ++last
)
1892 attr
->a_numvals
= last
;
1894 validate
= attr
->a_desc
->ad_type
->sat_syntax
->ssyn_validate
;
1895 pretty
= attr
->a_desc
->ad_type
->sat_syntax
->ssyn_pretty
;
1897 if ( !validate
&& !pretty
) {
1902 if ( attr
->a_desc
== slap_schema
.si_ad_objectClass
1903 || attr
->a_desc
== slap_schema
.si_ad_structuralObjectClass
)
1907 for ( bv
= attr
->a_vals
; !BER_BVISNULL( bv
); bv
++ ) {
1908 ldap_back_map( &mi
->mi_targets
[ target
]->mt_rwmap
.rwm_oc
,
1909 bv
, &mapped
, BACKLDAP_REMAP
);
1910 if ( BER_BVISNULL( &mapped
) || mapped
.bv_val
[0] == '\0') {
1917 *bv
= attr
->a_vals
[ last
];
1918 BER_BVZERO( &attr
->a_vals
[ last
] );
1921 } else if ( mapped
.bv_val
!= bv
->bv_val
) {
1924 for ( i
= 0; !BER_BVISNULL( &attr
->a_vals
[ i
] ); i
++ ) {
1925 if ( &attr
->a_vals
[ i
] == bv
) {
1929 if ( ber_bvstrcasecmp( &mapped
, &attr
->a_vals
[ i
] ) == 0 ) {
1934 if ( !BER_BVISNULL( &attr
->a_vals
[ i
] ) ) {
1938 ber_bvreplace( bv
, &mapped
);
1942 * It is necessary to try to rewrite attributes with
1943 * dn syntax because they might be used in ACLs as
1944 * members of groups; since ACLs are applied to the
1945 * rewritten stuff, no dn-based subecj clause could
1946 * be used at the ldap backend side (see
1947 * http://www.OpenLDAP.org/faq/data/cache/452.html)
1948 * The problem can be overcome by moving the dn-based
1949 * ACLs to the target directory server, and letting
1950 * everything pass thru the ldap backend.
1955 if ( attr
->a_desc
->ad_type
->sat_syntax
==
1956 slap_schema
.si_syn_distinguishedName
)
1958 ldap_dnattr_result_rewrite( &dc
, attr
->a_vals
);
1960 } else if ( attr
->a_desc
== slap_schema
.si_ad_ref
) {
1961 ldap_back_referral_result_rewrite( &dc
, attr
->a_vals
);
1965 for ( i
= 0; i
< last
; i
++ ) {
1970 rc
= pretty( attr
->a_desc
->ad_type
->sat_syntax
,
1971 &attr
->a_vals
[i
], &pval
, NULL
);
1974 rc
= validate( attr
->a_desc
->ad_type
->sat_syntax
,
1979 LBER_FREE( attr
->a_vals
[i
].bv_val
);
1980 if ( --last
== i
) {
1981 BER_BVZERO( &attr
->a_vals
[ i
] );
1984 attr
->a_vals
[i
] = attr
->a_vals
[last
];
1985 BER_BVZERO( &attr
->a_vals
[last
] );
1991 LBER_FREE( attr
->a_vals
[i
].bv_val
);
1992 attr
->a_vals
[i
] = pval
;
1996 if ( last
== 0 && attr
->a_vals
!= &slap_dummy_bv
) {
2002 if ( last
&& attr
->a_desc
->ad_type
->sat_equality
&&
2003 attr
->a_desc
->ad_type
->sat_equality
->smr_normalize
)
2007 attr
->a_nvals
= ch_malloc( ( last
+ 1 ) * sizeof( struct berval
) );
2008 for ( i
= 0; i
<last
; i
++ ) {
2009 attr
->a_desc
->ad_type
->sat_equality
->smr_normalize(
2010 SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX
,
2011 attr
->a_desc
->ad_type
->sat_syntax
,
2012 attr
->a_desc
->ad_type
->sat_equality
,
2013 &attr
->a_vals
[i
], &attr
->a_nvals
[i
],
2016 BER_BVZERO( &attr
->a_nvals
[i
] );
2019 attr
->a_nvals
= attr
->a_vals
;
2023 attrp
= &attr
->a_next
;
2027 /* only check if some mapping occurred */
2028 if ( check_duplicate_attrs
) {
2031 for ( ap
= &ent
.e_attrs
; *ap
!= NULL
; ap
= &(*ap
)->a_next
) {
2034 for ( tap
= &(*ap
)->a_next
; *tap
!= NULL
; ) {
2035 if ( (*tap
)->a_desc
== (*ap
)->a_desc
) {
2037 Modification mod
= { 0 };
2038 const char *text
= NULL
;
2039 char textbuf
[ SLAP_TEXT_BUFLEN
];
2040 Attribute
*next
= (*tap
)->a_next
;
2042 BER_BVSTR( &e
.e_name
, "" );
2043 BER_BVSTR( &e
.e_nname
, "" );
2045 mod
.sm_op
= LDAP_MOD_ADD
;
2046 mod
.sm_desc
= (*ap
)->a_desc
;
2047 mod
.sm_type
= mod
.sm_desc
->ad_cname
;
2048 mod
.sm_numvals
= (*ap
)->a_numvals
;
2049 mod
.sm_values
= (*tap
)->a_vals
;
2050 if ( (*tap
)->a_nvals
!= (*tap
)->a_vals
) {
2051 mod
.sm_nvalues
= (*tap
)->a_nvals
;
2054 (void)modify_add_values( &e
, &mod
,
2056 &text
, textbuf
, sizeof( textbuf
) );
2058 /* should not insert new attrs! */
2059 assert( e
.e_attrs
== *ap
);
2065 tap
= &(*tap
)->a_next
;
2071 ldap_get_entry_controls( mc
->mc_conns
[target
].msc_ld
,
2073 rs
->sr_entry
= &ent
;
2074 rs
->sr_attrs
= op
->ors_attrs
;
2075 rs
->sr_operational_attrs
= NULL
;
2077 rs
->sr_err
= LDAP_SUCCESS
;
2078 rc
= send_search_entry( op
, rs
);
2080 case LDAP_UNAVAILABLE
:
2084 rs
->sr_entry
= NULL
;
2085 rs
->sr_attrs
= NULL
;
2086 if ( rs
->sr_ctrls
!= NULL
) {
2087 ldap_controls_free( rs
->sr_ctrls
);
2088 rs
->sr_ctrls
= NULL
;
2090 if ( !BER_BVISNULL( &ent
.e_name
) ) {
2091 free( ent
.e_name
.bv_val
);
2092 BER_BVZERO( &ent
.e_name
);
2094 if ( !BER_BVISNULL( &ent
.e_nname
) ) {
2095 free( ent
.e_nname
.bv_val
);
2096 BER_BVZERO( &ent
.e_nname
);
2098 entry_clean( &ent
);