1
/* $OpenLDAP: pkg/ldap/servers/slapd/back-meta/search.c,v 1.146.2.11 2008/04/21 17:03:23 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 ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
1159
/* don't retry any more... */
1160
candidates[ i ].sr_type = REP_RESULT;
1165
rc = ldap_parse_reference( msc->msc_ld, msg,
1166
&references, &rs->sr_ctrls, 0 );
1168
if ( rc != LDAP_SUCCESS ) {
1172
if ( references == NULL ) {
1176
#ifdef ENABLE_REWRITE
1177
dc.ctx = "referralDN";
1178
#else /* ! ENABLE_REWRITE */
1181
#endif /* ! ENABLE_REWRITE */
1183
/* FIXME: merge all and return at the end */
1185
for ( cnt = 0; references[ cnt ]; cnt++ )
1188
rs->sr_ref = ch_calloc( sizeof( struct berval ), cnt + 1 );
1190
for ( cnt = 0; references[ cnt ]; cnt++ ) {
1191
ber_str2bv( references[ cnt ], 0, 1, &rs->sr_ref[ cnt ] );
1193
BER_BVZERO( &rs->sr_ref[ cnt ] );
1195
( void )ldap_back_referral_result_rewrite( &dc, rs->sr_ref );
1197
if ( rs->sr_ref != NULL && !BER_BVISNULL( &rs->sr_ref[ 0 ] ) ) {
1198
/* ignore return value by now */
1199
savepriv = op->o_private;
1200
op->o_private = (void *)i;
1201
( void )send_search_reference( op, rs );
1202
op->o_private = savepriv;
1204
ber_bvarray_free( rs->sr_ref );
1210
ber_memvfree( (void **)references );
1213
if ( rs->sr_ctrls ) {
1214
ldap_controls_free( rs->sr_ctrls );
1215
rs->sr_ctrls = NULL;
1218
} else if ( rc == LDAP_RES_SEARCH_RESULT ) {
1219
char buf[ SLAP_TEXT_BUFLEN ];
1220
char **references = NULL;
1222
if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
1223
/* don't retry any more... */
1224
candidates[ i ].sr_type = REP_RESULT;
1227
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
1229
/* NOTE: ignores response controls
1230
* (and intermediate response controls
1231
* as well, except for those with search
1232
* references); this may not be correct,
1233
* but if they're not ignored then
1234
* back-meta would need to merge them
1235
* consistently (think of pagedResults...)
1237
/* FIXME: response controls? */
1238
rs->sr_err = ldap_parse_result( msc->msc_ld,
1240
&candidates[ i ].sr_err,
1241
(char **)&candidates[ i ].sr_matched,
1242
NULL /* (char **)&candidates[ i ].sr_text */ ,
1244
NULL /* &candidates[ i ].sr_ctrls (unused) */ ,
1246
if ( rs->sr_err != LDAP_SUCCESS ) {
1247
sres = slap_map_api2result( &candidates[ i ] );
1248
candidates[ i ].sr_type = REP_RESULT;
1249
ldap_msgfree( res );
1254
rs->sr_err = candidates[ i ].sr_err;
1256
/* massage matchedDN if need be */
1257
if ( candidates[ i ].sr_matched != NULL ) {
1258
struct berval match, mmatch;
1260
ber_str2bv( candidates[ i ].sr_matched,
1262
candidates[ i ].sr_matched = NULL;
1264
dc.ctx = "matchedDN";
1265
dc.target = mi->mi_targets[ i ];
1266
if ( !ldap_back_dn_massage( &dc, &match, &mmatch ) ) {
1267
if ( mmatch.bv_val == match.bv_val ) {
1268
candidates[ i ].sr_matched
1269
= ch_strdup( mmatch.bv_val );
1272
candidates[ i ].sr_matched = mmatch.bv_val;
1277
ldap_memfree( match.bv_val );
1280
/* add references to array */
1281
/* RFC 4511: referrals can only appear
1282
* if result code is LDAP_REFERRAL */
1283
if ( references != NULL
1284
&& references[ 0 ] != NULL
1285
&& references[ 0 ][ 0 ] != '\0' )
1287
if ( rs->sr_err != LDAP_REFERRAL ) {
1288
Debug( LDAP_DEBUG_ANY,
1289
"%s meta_back_search[%ld]: "
1290
"got referrals with err=%d\n",
1298
for ( cnt = 0; references[ cnt ]; cnt++ )
1301
sr_ref = ch_calloc( sizeof( struct berval ), cnt + 1 );
1303
for ( cnt = 0; references[ cnt ]; cnt++ ) {
1304
ber_str2bv( references[ cnt ], 0, 1, &sr_ref[ cnt ] );
1306
BER_BVZERO( &sr_ref[ cnt ] );
1308
( void )ldap_back_referral_result_rewrite( &dc, sr_ref );
1310
if ( rs->sr_v2ref == NULL ) {
1311
rs->sr_v2ref = sr_ref;
1314
for ( cnt = 0; !BER_BVISNULL( &sr_ref[ cnt ] ); cnt++ ) {
1315
ber_bvarray_add( &rs->sr_v2ref, &sr_ref[ cnt ] );
1317
ber_memfree( sr_ref );
1321
} else if ( rs->sr_err == LDAP_REFERRAL ) {
1322
Debug( LDAP_DEBUG_ANY,
1323
"%s meta_back_search[%ld]: "
1324
"got err=%d with null "
1325
"or empty referrals\n",
1329
rs->sr_err = LDAP_NO_SUCH_OBJECT;
1333
ber_memvfree( (void **)references );
1335
sres = slap_map_api2result( rs );
1337
if ( LogTest( LDAP_DEBUG_TRACE | LDAP_DEBUG_ANY ) ) {
1338
snprintf( buf, sizeof( buf ),
1339
"%s meta_back_search[%ld] "
1340
"match=\"%s\" err=%ld",
1341
op->o_log_prefix, i,
1342
candidates[ i ].sr_matched ? candidates[ i ].sr_matched : "",
1343
(long) candidates[ i ].sr_err );
1344
if ( candidates[ i ].sr_err == LDAP_SUCCESS ) {
1345
Debug( LDAP_DEBUG_TRACE, "%s.\n", buf, 0, 0 );
1348
Debug( LDAP_DEBUG_ANY, "%s (%s).\n",
1349
buf, ldap_err2string( candidates[ i ].sr_err ), 0 );
1354
case LDAP_NO_SUCH_OBJECT:
1355
/* is_ok is touched any time a valid
1356
* (even intermediate) result is
1357
* returned; as a consequence, if
1358
* a candidate returns noSuchObject
1359
* it is ignored and the candidate
1360
* is simply demoted. */
1362
sres = LDAP_SUCCESS;
1371
case LDAP_SIZELIMIT_EXCEEDED:
1372
/* if a target returned sizelimitExceeded
1373
* and the entry count is equal to the
1374
* proxy's limit, the target would have
1375
* returned more, and the error must be
1376
* propagated to the client; otherwise,
1377
* the target enforced a limit lower
1378
* than what requested by the proxy;
1380
candidates[ i ].sr_err = rs->sr_err;
1381
if ( rs->sr_nentries == op->ors_slimit
1382
|| META_BACK_ONERR_STOP( mi ) )
1384
savepriv = op->o_private;
1385
op->o_private = (void *)i;
1386
send_ldap_result( op, rs );
1387
op->o_private = savepriv;
1388
ldap_msgfree( res );
1395
candidates[ i ].sr_err = rs->sr_err;
1396
if ( META_BACK_ONERR_STOP( mi ) ) {
1397
savepriv = op->o_private;
1398
op->o_private = (void *)i;
1399
send_ldap_result( op, rs );
1400
op->o_private = savepriv;
1401
ldap_msgfree( res );
1412
* When no candidates are left,
1413
* the outer cycle finishes
1415
assert( ncandidates > 0 );
1418
} else if ( rc == LDAP_RES_BIND ) {
1419
meta_search_candidate_t retcode;
1421
retcode = meta_search_dobind_result( op, rs, &mc, i, candidates, msg );
1422
if ( retcode == META_SEARCH_CANDIDATE ) {
1423
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
1424
retcode = meta_back_search_start( op, rs, &dc, &mc, i, candidates );
1427
switch ( retcode ) {
1428
case META_SEARCH_CANDIDATE:
1431
/* means that failed but onerr == continue */
1432
case META_SEARCH_NOT_CANDIDATE:
1433
case META_SEARCH_ERR:
1434
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
1435
assert( ncandidates > 0 );
1438
candidates[ i ].sr_err = rs->sr_err;
1439
if ( META_BACK_ONERR_STOP( mi ) ) {
1440
savepriv = op->o_private;
1441
op->o_private = (void *)i;
1442
send_ldap_result( op, rs );
1443
op->o_private = savepriv;
1444
ldap_msgfree( res );
1457
ldap_msgfree( res );
1464
ldap_msgfree( res );
1468
/* check for abandon */
1469
if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( mc ) ) {
1470
for ( i = 0; i < mi->mi_ntargets; i++ ) {
1471
if ( candidates[ i ].sr_msgid >= 0
1472
|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
1474
if ( META_IS_BINDING( &candidates[ i ] )
1475
|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
1477
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
1478
if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] )
1479
|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
1481
/* if still binding, destroy */
1484
char buf[ SLAP_TEXT_BUFLEN ];
1486
snprintf( buf, sizeof( buf), "%s meta_back_search(abandon) "
1487
"ldap_unbind_ext[%ld] mc=%p ld=%p",
1488
op->o_log_prefix, i, (void *)mc,
1489
(void *)mc->mc_conns[i].msc_ld );
1491
Debug( LDAP_DEBUG_ANY, "### %s\n", buf, 0, 0 );
1492
#endif /* DEBUG_205 */
1494
meta_clear_one_candidate( op, mc, i );
1496
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
1497
META_BINDING_CLEAR( &candidates[ i ] );
1500
(void)meta_back_cancel( mc, op, rs,
1501
candidates[ i ].sr_msgid, i,
1502
LDAP_BACK_DONTSEND );
1505
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
1506
assert( ncandidates > 0 );
1511
if ( op->o_abandon ) {
1515
/* let send_ldap_result play cleanup handlers (ITS#4645) */
1519
/* if no entry was found during this loop,
1520
* set a minimal timeout */
1521
if ( ncandidates > 0 && gotit == 0 ) {
1522
if ( save_tv.tv_sec == 0 && save_tv.tv_usec == 0 ) {
1523
save_tv.tv_usec = LDAP_BACK_RESULT_UTIMEOUT/initial_candidates;
1525
/* arbitrarily limit to something between 1 and 2 minutes */
1526
} else if ( ( stoptime == -1 && save_tv.tv_sec < 60 )
1527
|| save_tv.tv_sec < ( stoptime - slap_get_time() ) / ( 2 * ncandidates ) )
1529
/* double the timeout */
1530
lutil_timermul( &save_tv, 2, &save_tv );
1533
if ( alreadybound == 0 ) {
1535
(void)select( 0, NULL, NULL, NULL, &tv );
1538
ldap_pvt_thread_yield();
1545
* FIXME: need a better strategy to handle errors
1548
rc = meta_back_op_result( mc, op, rs, META_TARGET_NONE,
1549
-1, stoptime != -1 ? (stoptime - slap_get_time()) : 0,
1550
LDAP_BACK_SENDERR );
1558
* Rewrite the matched portion of the search base, if required
1560
* FIXME: only the last one gets caught!
1562
savepriv = op->o_private;
1563
op->o_private = (void *)(long)mi->mi_ntargets;
1564
if ( candidate_match > 0 ) {
1565
struct berval pmatched = BER_BVNULL;
1567
/* we use the first one */
1568
for ( i = 0; i < mi->mi_ntargets; i++ ) {
1569
if ( META_IS_CANDIDATE( &candidates[ i ] )
1570
&& candidates[ i ].sr_matched != NULL )
1572
struct berval bv, pbv;
1575
/* if we got success, and this target
1576
* returned noSuchObject, and its suffix
1577
* is a superior of the searchBase,
1578
* ignore the matchedDN */
1579
if ( sres == LDAP_SUCCESS
1580
&& candidates[ i ].sr_err == LDAP_NO_SUCH_OBJECT
1581
&& op->o_req_ndn.bv_len > mi->mi_targets[ i ]->mt_nsuffix.bv_len )
1583
free( (char *)candidates[ i ].sr_matched );
1584
candidates[ i ].sr_matched = NULL;
1588
ber_str2bv( candidates[ i ].sr_matched, 0, 0, &bv );
1589
rc = dnPretty( NULL, &bv, &pbv, op->o_tmpmemctx );
1591
if ( rc == LDAP_SUCCESS ) {
1593
/* NOTE: if they all are superiors
1594
* of the baseDN, the shorter is also
1595
* superior of the longer... */
1596
if ( pbv.bv_len > pmatched.bv_len ) {
1597
if ( !BER_BVISNULL( &pmatched ) ) {
1598
op->o_tmpfree( pmatched.bv_val, op->o_tmpmemctx );
1601
op->o_private = (void *)i;
1604
op->o_tmpfree( pbv.bv_val, op->o_tmpmemctx );
1608
if ( candidates[ i ].sr_matched != NULL ) {
1609
free( (char *)candidates[ i ].sr_matched );
1610
candidates[ i ].sr_matched = NULL;
1615
if ( !BER_BVISNULL( &pmatched ) ) {
1616
matched = pmatched.bv_val;
1619
} else if ( sres == LDAP_NO_SUCH_OBJECT ) {
1620
matched = op->o_bd->be_suffix[ 0 ].bv_val;
1624
* In case we returned at least one entry, we return LDAP_SUCCESS
1625
* otherwise, the latter error code we got
1628
if ( sres == LDAP_SUCCESS ) {
1629
if ( rs->sr_v2ref ) {
1630
sres = LDAP_REFERRAL;
1633
if ( META_BACK_ONERR_REPORT( mi ) ) {
1635
* Report errors, if any
1637
* FIXME: we should handle error codes and return the more
1638
* important/reasonable
1640
for ( i = 0; i < mi->mi_ntargets; i++ ) {
1641
if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) {
1645
if ( candidates[ i ].sr_err != LDAP_SUCCESS
1646
&& candidates[ i ].sr_err != LDAP_NO_SUCH_OBJECT )
1648
sres = candidates[ i ].sr_err;
1656
rs->sr_matched = matched;
1657
rs->sr_ref = ( sres == LDAP_REFERRAL ? rs->sr_v2ref : NULL );
1658
send_ldap_result( op, rs );
1659
op->o_private = savepriv;
1660
rs->sr_matched = NULL;
1664
if ( matched && matched != op->o_bd->be_suffix[ 0 ].bv_val ) {
1665
op->o_tmpfree( matched, op->o_tmpmemctx );
1668
if ( rs->sr_v2ref ) {
1669
ber_bvarray_free( rs->sr_v2ref );
1672
for ( i = 0; i < mi->mi_ntargets; i++ ) {
1673
if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) {
1678
if ( META_IS_BINDING( &candidates[ i ] )
1679
|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
1681
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
1682
if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] )
1683
|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING )
1685
assert( candidates[ i ].sr_msgid >= 0
1686
|| candidates[ i ].sr_msgid == META_MSGID_CONNECTING );
1687
assert( mc->mc_conns[ i ].msc_ld != NULL );
1690
Debug( LDAP_DEBUG_ANY, "### %s meta_back_search(cleanup) "
1691
"ldap_unbind_ext[%ld] ld=%p\n",
1692
op->o_log_prefix, i, (void *)mc->mc_conns[i].msc_ld );
1693
#endif /* DEBUG_205 */
1695
/* if still binding, destroy */
1696
meta_clear_one_candidate( op, mc, i );
1698
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
1699
META_BINDING_CLEAR( &candidates[ i ] );
1701
} else if ( candidates[ i ].sr_msgid >= 0 ) {
1702
(void)meta_back_cancel( mc, op, rs,
1703
candidates[ i ].sr_msgid, i,
1704
LDAP_BACK_DONTSEND );
1708
if ( candidates[ i ].sr_matched ) {
1709
free( (char *)candidates[ i ].sr_matched );
1710
candidates[ i ].sr_matched = NULL;
1713
if ( candidates[ i ].sr_text ) {
1714
ldap_memfree( (char *)candidates[ i ].sr_text );
1715
candidates[ i ].sr_text = NULL;
1718
if ( candidates[ i ].sr_ref ) {
1719
ber_bvarray_free( candidates[ i ].sr_ref );
1720
candidates[ i ].sr_ref = NULL;
1723
if ( candidates[ i ].sr_ctrls ) {
1724
ldap_controls_free( candidates[ i ].sr_ctrls );
1725
candidates[ i ].sr_ctrls = NULL;
1728
if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ i ] ) ) {
1729
meta_back_quarantine( op, &candidates[ i ], i );
1732
/* only in case of timelimit exceeded, if the timelimit exceeded because
1733
* one contacted target never responded, invalidate the connection
1734
* NOTE: should we quarantine the target as well? right now, the connection
1735
* is invalidated; the next time it will be recreated and the target
1736
* will be quarantined if it cannot be contacted */
1737
if ( mi->mi_idle_timeout != 0
1738
&& rs->sr_err == LDAP_TIMELIMIT_EXCEEDED
1739
&& op->o_time > mc->mc_conns[ i ].msc_time )
1741
/* don't let anyone else use this expired connection */
1742
LDAP_BACK_CONN_TAINTED_SET( mc );
1747
meta_back_release_conn( mi, mc );
1761
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
1762
struct berval a, mapped;
1763
int check_duplicate_attrs = 0;
1765
BerElement ber = *e->lm_ber;
1766
Attribute *attr, **attrp;
1773
if ( ber_scanf( &ber, "{m{", &bdn ) == LBER_ERROR ) {
1774
return LDAP_DECODING_ERROR;
1778
* Rewrite the dn of the result, if needed
1780
dc.target = mi->mi_targets[ target ];
1781
dc.conn = op->o_conn;
1783
dc.ctx = "searchResult";
1785
rs->sr_err = ldap_back_dn_massage( &dc, &bdn, &dn );
1786
if ( rs->sr_err != LDAP_SUCCESS) {
1791
* Note: this may fail if the target host(s) schema differs
1792
* from the one known to the meta, and a DN with unknown
1793
* attributes is returned.
1795
* FIXME: should we log anything, or delegate to dnNormalize?
1797
rc = dnPrettyNormal( NULL, &dn, &ent.e_name, &ent.e_nname,
1799
if ( dn.bv_val != bdn.bv_val ) {
1804
if ( rc != LDAP_SUCCESS ) {
1805
return LDAP_INVALID_DN_SYNTAX;
1811
if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED ) {
1812
( void )meta_dncache_update_entry( &mi->mi_cache,
1813
&ent.e_nname, target );
1816
attrp = &ent.e_attrs;
1818
dc.ctx = "searchAttrDN";
1819
while ( ber_scanf( &ber, "{m", &a ) != LBER_ERROR ) {
1821
slap_syntax_validate_func *validate;
1822
slap_syntax_transform_func *pretty;
1824
ldap_back_map( &mi->mi_targets[ target ]->mt_rwmap.rwm_at,
1825
&a, &mapped, BACKLDAP_REMAP );
1826
if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0' ) {
1827
( void )ber_scanf( &ber, "x" /* [W] */ );
1830
if ( mapped.bv_val != a.bv_val ) {
1831
/* will need to check for duplicate attrs */
1832
check_duplicate_attrs++;
1834
attr = attr_alloc( NULL );
1835
if ( attr == NULL ) {
1838
if ( slap_bv2ad( &mapped, &attr->a_desc, &text )
1840
if ( slap_bv2undef_ad( &mapped, &attr->a_desc, &text,
1841
SLAP_AD_PROXIED ) != LDAP_SUCCESS )
1843
char buf[ SLAP_TEXT_BUFLEN ];
1845
snprintf( buf, sizeof( buf ),
1846
"%s meta_send_entry(\"%s\"): "
1847
"slap_bv2undef_ad(%s): %s\n",
1848
op->o_log_prefix, ent.e_name.bv_val,
1849
mapped.bv_val, text );
1851
Debug( LDAP_DEBUG_ANY, "%s", buf, 0, 0 );
1857
/* no subschemaSubentry */
1858
if ( attr->a_desc == slap_schema.si_ad_subschemaSubentry
1859
|| attr->a_desc == slap_schema.si_ad_entryDN )
1863
* We eat target's subschemaSubentry because
1864
* a search for this value is likely not
1865
* to resolve to the appropriate backend;
1866
* later, the local subschemaSubentry is
1869
* We also eat entryDN because the frontend
1870
* will reattach it without checking if already
1873
( void )ber_scanf( &ber, "x" /* [W] */ );
1879
if ( ber_scanf( &ber, "[W]", &attr->a_vals ) == LBER_ERROR
1880
|| attr->a_vals == NULL )
1882
attr->a_vals = (struct berval *)&slap_dummy_bv;
1885
for ( last = 0; !BER_BVISNULL( &attr->a_vals[ last ] ); ++last )
1888
attr->a_numvals = last;
1890
validate = attr->a_desc->ad_type->sat_syntax->ssyn_validate;
1891
pretty = attr->a_desc->ad_type->sat_syntax->ssyn_pretty;
1893
if ( !validate && !pretty ) {
1898
if ( attr->a_desc == slap_schema.si_ad_objectClass
1899
|| attr->a_desc == slap_schema.si_ad_structuralObjectClass )
1903
for ( bv = attr->a_vals; !BER_BVISNULL( bv ); bv++ ) {
1904
ldap_back_map( &mi->mi_targets[ target ]->mt_rwmap.rwm_oc,
1905
bv, &mapped, BACKLDAP_REMAP );
1906
if ( BER_BVISNULL( &mapped ) || mapped.bv_val[0] == '\0') {
1913
*bv = attr->a_vals[ last ];
1914
BER_BVZERO( &attr->a_vals[ last ] );
1917
} else if ( mapped.bv_val != bv->bv_val ) {
1920
for ( i = 0; !BER_BVISNULL( &attr->a_vals[ i ] ); i++ ) {
1921
if ( &attr->a_vals[ i ] == bv ) {
1925
if ( ber_bvstrcasecmp( &mapped, &attr->a_vals[ i ] ) == 0 ) {
1930
if ( !BER_BVISNULL( &attr->a_vals[ i ] ) ) {
1934
ber_bvreplace( bv, &mapped );
1938
* It is necessary to try to rewrite attributes with
1939
* dn syntax because they might be used in ACLs as
1940
* members of groups; since ACLs are applied to the
1941
* rewritten stuff, no dn-based subecj clause could
1942
* be used at the ldap backend side (see
1943
* http://www.OpenLDAP.org/faq/data/cache/452.html)
1944
* The problem can be overcome by moving the dn-based
1945
* ACLs to the target directory server, and letting
1946
* everything pass thru the ldap backend.
1951
if ( attr->a_desc->ad_type->sat_syntax ==
1952
slap_schema.si_syn_distinguishedName )
1954
ldap_dnattr_result_rewrite( &dc, attr->a_vals );
1956
} else if ( attr->a_desc == slap_schema.si_ad_ref ) {
1957
ldap_back_referral_result_rewrite( &dc, attr->a_vals );
1961
for ( i = 0; i < last; i++ ) {
1966
rc = pretty( attr->a_desc->ad_type->sat_syntax,
1967
&attr->a_vals[i], &pval, NULL );
1970
rc = validate( attr->a_desc->ad_type->sat_syntax,
1975
LBER_FREE( attr->a_vals[i].bv_val );
1976
if ( --last == i ) {
1977
BER_BVZERO( &attr->a_vals[ i ] );
1980
attr->a_vals[i] = attr->a_vals[last];
1981
BER_BVZERO( &attr->a_vals[last] );
1987
LBER_FREE( attr->a_vals[i].bv_val );
1988
attr->a_vals[i] = pval;
1992
if ( last == 0 && attr->a_vals != &slap_dummy_bv ) {
1998
if ( last && attr->a_desc->ad_type->sat_equality &&
1999
attr->a_desc->ad_type->sat_equality->smr_normalize )
2003
attr->a_nvals = ch_malloc( ( last + 1 ) * sizeof( struct berval ) );
2004
for ( i = 0; i<last; i++ ) {
2005
attr->a_desc->ad_type->sat_equality->smr_normalize(
2006
SLAP_MR_VALUE_OF_ATTRIBUTE_SYNTAX,
2007
attr->a_desc->ad_type->sat_syntax,
2008
attr->a_desc->ad_type->sat_equality,
2009
&attr->a_vals[i], &attr->a_nvals[i],
2012
BER_BVZERO( &attr->a_nvals[i] );
2015
attr->a_nvals = attr->a_vals;
2019
attrp = &attr->a_next;
2023
/* only check if some mapping occurred */
2024
if ( check_duplicate_attrs ) {
2027
for ( ap = &ent.e_attrs; *ap != NULL; ap = &(*ap)->a_next ) {
2030
for ( tap = &(*ap)->a_next; *tap != NULL; ) {
2031
if ( (*tap)->a_desc == (*ap)->a_desc ) {
2033
Modification mod = { 0 };
2034
const char *text = NULL;
2035
char textbuf[ SLAP_TEXT_BUFLEN ];
2036
Attribute *next = (*tap)->a_next;
2038
BER_BVSTR( &e.e_name, "" );
2039
BER_BVSTR( &e.e_nname, "" );
2041
mod.sm_op = LDAP_MOD_ADD;
2042
mod.sm_desc = (*ap)->a_desc;
2043
mod.sm_type = mod.sm_desc->ad_cname;
2044
mod.sm_numvals = (*ap)->a_numvals;
2045
mod.sm_values = (*tap)->a_vals;
2046
if ( (*tap)->a_nvals != (*tap)->a_vals ) {
2047
mod.sm_nvalues = (*tap)->a_nvals;
2050
(void)modify_add_values( &e, &mod,
2052
&text, textbuf, sizeof( textbuf ) );
2054
/* should not insert new attrs! */
2055
assert( e.e_attrs == *ap );
2061
tap = &(*tap)->a_next;
2067
ldap_get_entry_controls( mc->mc_conns[target].msc_ld,
2069
rs->sr_entry = &ent;
2070
rs->sr_attrs = op->ors_attrs;
2071
rs->sr_operational_attrs = NULL;
2073
rs->sr_err = LDAP_SUCCESS;
2074
rc = send_search_entry( op, rs );
2076
case LDAP_UNAVAILABLE:
2080
rs->sr_entry = NULL;
2081
rs->sr_attrs = NULL;
2082
if ( rs->sr_ctrls != NULL ) {
2083
ldap_controls_free( rs->sr_ctrls );
2084
rs->sr_ctrls = NULL;
2086
if ( !BER_BVISNULL( &ent.e_name ) ) {
2087
free( ent.e_name.bv_val );
2088
BER_BVZERO( &ent.e_name );
2090
if ( !BER_BVISNULL( &ent.e_nname ) ) {
2091
free( ent.e_nname.bv_val );
2092
BER_BVZERO( &ent.e_nname );
2094
entry_clean( &ent );