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