static void retcode_item_destroy( retcode_item_t *rdi ) { ber_memfree( rdi->rdi_line.bv_val ); ber_memfree( rdi->rdi_dn.bv_val ); ber_memfree( rdi->rdi_ndn.bv_val ); if ( !BER_BVISNULL( &rdi->rdi_text ) ) { ber_memfree( rdi->rdi_text.bv_val ); } if ( !BER_BVISNULL( &rdi->rdi_matched ) ) { ber_memfree( rdi->rdi_matched.bv_val ); } if ( rdi->rdi_ref ) { ber_bvarray_free( rdi->rdi_ref ); } BER_BVZERO( &rdi->rdi_e.e_name ); BER_BVZERO( &rdi->rdi_e.e_nname ); entry_clean( &rdi->rdi_e ); if ( !BER_BVISNULL( &rdi->rdi_unsolicited_oid ) ) { ber_memfree( rdi->rdi_unsolicited_oid.bv_val ); if ( !BER_BVISNULL( &rdi->rdi_unsolicited_data ) ) ber_memfree( rdi->rdi_unsolicited_data.bv_val ); } ch_free( rdi ); }
void entry_free( Entry *e ) { entry_clean( e ); ldap_pvt_thread_mutex_lock( &entry_mutex ); e->e_private = entry_list; entry_list = e; ldap_pvt_thread_mutex_unlock( &entry_mutex ); }
int dnssrv_back_search( Operation *op, SlapReply *rs ) { int i; int rc; char *domain = NULL; char *hostlist = NULL; char **hosts = NULL; char *refdn; struct berval nrefdn = BER_BVNULL; BerVarray urls = NULL; int manageDSAit; rs->sr_ref = NULL; if ( BER_BVISEMPTY( &op->o_req_ndn ) ) { /* FIXME: need some means to determine whether the database * is a glue instance; if we got here with empty DN, then * we passed this same test in dnssrv_back_referrals() */ if ( !SLAP_GLUE_INSTANCE( op->o_bd ) ) { rs->sr_err = LDAP_UNWILLING_TO_PERFORM; rs->sr_text = "DNS SRV operation upon null (empty) DN disallowed"; } else { rs->sr_err = LDAP_SUCCESS; } goto done; } manageDSAit = get_manageDSAit( op ); /* * FIXME: we may return a referral if manageDSAit is not set */ if ( !manageDSAit ) { send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM, "manageDSAit must be set" ); goto done; } if( ldap_dn2domain( op->o_req_dn.bv_val, &domain ) || domain == NULL ) { rs->sr_err = LDAP_REFERRAL; rs->sr_ref = default_referral; send_ldap_result( op, rs ); rs->sr_ref = NULL; goto done; } Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" -> domain=\"%s\"\n", op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", domain ); if( ( rc = ldap_domain2hostlist( domain, &hostlist ) ) ) { Debug( LDAP_DEBUG_TRACE, "DNSSRV: domain2hostlist returned %d\n", rc ); send_ldap_error( op, rs, LDAP_NO_SUCH_OBJECT, "no DNS SRV RR available for DN" ); goto done; } hosts = ldap_str2charray( hostlist, " " ); if( hosts == NULL ) { Debug( LDAP_DEBUG_TRACE, "DNSSRV: str2charray error\n" ); send_ldap_error( op, rs, LDAP_OTHER, "problem processing DNS SRV records for DN" ); goto done; } for( i=0; hosts[i] != NULL; i++) { struct berval url; url.bv_len = STRLENOF( "ldap://" ) + strlen(hosts[i]); url.bv_val = ch_malloc( url.bv_len + 1 ); strcpy( url.bv_val, "ldap://" ); strcpy( &url.bv_val[STRLENOF( "ldap://" )], hosts[i] ); if( ber_bvarray_add( &urls, &url ) < 0 ) { free( url.bv_val ); send_ldap_error( op, rs, LDAP_OTHER, "problem processing DNS SRV records for DN" ); goto done; } } Debug( LDAP_DEBUG_STATS, "%s DNSSRV p=%d dn=\"%s\" url=\"%s\"\n", op->o_log_prefix, op->o_protocol, op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", urls[0].bv_val ); Debug( LDAP_DEBUG_TRACE, "DNSSRV: ManageDSAit scope=%d dn=\"%s\" -> url=\"%s\"\n", op->oq_search.rs_scope, op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", urls[0].bv_val ); rc = ldap_domain2dn(domain, &refdn); if( rc != LDAP_SUCCESS ) { send_ldap_error( op, rs, LDAP_OTHER, "DNS SRV problem processing manageDSAit control" ); goto done; } else { struct berval bv; bv.bv_val = refdn; bv.bv_len = strlen( refdn ); rc = dnNormalize( 0, NULL, NULL, &bv, &nrefdn, op->o_tmpmemctx ); if( rc != LDAP_SUCCESS ) { send_ldap_error( op, rs, LDAP_OTHER, "DNS SRV problem processing manageDSAit control" ); goto done; } } if( !dn_match( &nrefdn, &op->o_req_ndn ) ) { /* requested dn is subordinate */ Debug( LDAP_DEBUG_TRACE, "DNSSRV: dn=\"%s\" subordinate to refdn=\"%s\"\n", op->o_req_dn.bv_len ? op->o_req_dn.bv_val : "", refdn == NULL ? "" : refdn ); rs->sr_matched = refdn; rs->sr_err = LDAP_NO_SUCH_OBJECT; send_ldap_result( op, rs ); rs->sr_matched = NULL; } else if ( op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL ) { send_ldap_error( op, rs, LDAP_SUCCESS, NULL ); } else { Entry e = { 0 }; AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass; AttributeDescription *ad_ref = slap_schema.si_ad_ref; e.e_name.bv_val = ch_strdup( op->o_req_dn.bv_val ); e.e_name.bv_len = op->o_req_dn.bv_len; e.e_nname.bv_val = ch_strdup( op->o_req_ndn.bv_val ); e.e_nname.bv_len = op->o_req_ndn.bv_len; e.e_attrs = NULL; e.e_private = NULL; attr_merge_one( &e, ad_objectClass, &slap_schema.si_oc_referral->soc_cname, NULL ); attr_merge_one( &e, ad_objectClass, &slap_schema.si_oc_extensibleObject->soc_cname, NULL ); if ( ad_dc ) { char *p; struct berval bv; bv.bv_val = domain; p = strchr( bv.bv_val, '.' ); if ( p == bv.bv_val ) { bv.bv_len = 1; } else if ( p != NULL ) { bv.bv_len = p - bv.bv_val; } else { bv.bv_len = strlen( bv.bv_val ); } attr_merge_normalize_one( &e, ad_dc, &bv, NULL ); } if ( ad_associatedDomain ) { struct berval bv; ber_str2bv( domain, 0, 0, &bv ); attr_merge_normalize_one( &e, ad_associatedDomain, &bv, NULL ); } attr_merge_normalize_one( &e, ad_ref, urls, NULL ); rc = test_filter( op, &e, op->oq_search.rs_filter ); if( rc == LDAP_COMPARE_TRUE ) { rs->sr_entry = &e; rs->sr_attrs = op->oq_search.rs_attrs; rs->sr_flags = REP_ENTRY_MODIFIABLE; send_search_entry( op, rs ); rs->sr_entry = NULL; rs->sr_attrs = NULL; rs->sr_flags = 0; } entry_clean( &e ); rs->sr_err = LDAP_SUCCESS; send_ldap_result( op, rs ); } free( refdn ); if ( nrefdn.bv_val ) free( nrefdn.bv_val ); done: if( domain != NULL ) ch_free( domain ); if( hostlist != NULL ) ch_free( hostlist ); if( hosts != NULL ) ldap_charray_free( hosts ); if( urls != NULL ) ber_bvarray_free( urls ); return 0; }
int passwd_back_search( Operation *op, SlapReply *rs ) { struct passwd *pw; time_t stoptime = (time_t)-1; LDAPRDN rdn = NULL; struct berval parent = BER_BVNULL; AttributeDescription *ad_objectClass = slap_schema.si_ad_objectClass; if ( op->ors_tlimit != SLAP_NO_LIMIT ) { stoptime = op->o_time + op->ors_tlimit; } /* Handle a query for the base of this backend */ if ( be_issuffix( op->o_bd, &op->o_req_ndn ) ) { struct berval val; rs->sr_matched = op->o_req_dn.bv_val; if( op->ors_scope != LDAP_SCOPE_ONELEVEL ) { AttributeDescription *desc = NULL; char *next; Entry e = { 0 }; /* Create an entry corresponding to the base DN */ e.e_name.bv_val = ch_strdup( op->o_req_dn.bv_val ); e.e_name.bv_len = op->o_req_dn.bv_len; e.e_nname.bv_val = ch_strdup( op->o_req_ndn.bv_val ); e.e_nname.bv_len = op->o_req_ndn.bv_len; /* Use the first attribute of the DN * as an attribute within the entry itself. */ if( ldap_bv2rdn( &op->o_req_dn, &rdn, &next, LDAP_DN_FORMAT_LDAP ) ) { rs->sr_err = LDAP_INVALID_DN_SYNTAX; goto done; } if( slap_bv2ad( &rdn[0]->la_attr, &desc, &rs->sr_text )) { rs->sr_err = LDAP_NO_SUCH_OBJECT; ldap_rdnfree(rdn); goto done; } attr_merge_normalize_one( &e, desc, &rdn[0]->la_value, NULL ); ldap_rdnfree(rdn); rdn = NULL; /* Every entry needs an objectclass. We don't really * know if our hardcoded choice here agrees with the * DN that was configured for this backend, but it's * better than nothing. * * should be a configuratable item */ BER_BVSTR( &val, "organizationalUnit" ); attr_merge_one( &e, ad_objectClass, &val, NULL ); if ( test_filter( op, &e, op->ors_filter ) == LDAP_COMPARE_TRUE ) { rs->sr_entry = &e; rs->sr_attrs = op->ors_attrs; rs->sr_flags = REP_ENTRY_MODIFIABLE; send_search_entry( op, rs ); rs->sr_flags = 0; rs->sr_attrs = NULL; } entry_clean( &e ); } if ( op->ors_scope != LDAP_SCOPE_BASE ) { /* check all our "children" */ ldap_pvt_thread_mutex_lock( &passwd_mutex ); pw_start( op->o_bd ); for ( pw = getpwent(); pw != NULL; pw = getpwent() ) { Entry e = { 0 }; /* check for abandon */ if ( op->o_abandon ) { endpwent(); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); return( SLAPD_ABANDON ); } /* check time limit */ if ( op->ors_tlimit != SLAP_NO_LIMIT && slap_get_time() > stoptime ) { send_ldap_error( op, rs, LDAP_TIMELIMIT_EXCEEDED, NULL ); endpwent(); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); return( 0 ); } if ( pw2entry( op->o_bd, pw, &e ) ) { rs->sr_err = LDAP_OTHER; endpwent(); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); goto done; } if ( test_filter( op, &e, op->ors_filter ) == LDAP_COMPARE_TRUE ) { /* check size limit */ if ( --op->ors_slimit == -1 ) { send_ldap_error( op, rs, LDAP_SIZELIMIT_EXCEEDED, NULL ); endpwent(); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); return( 0 ); } rs->sr_entry = &e; rs->sr_attrs = op->ors_attrs; rs->sr_flags = REP_ENTRY_MODIFIABLE; send_search_entry( op, rs ); rs->sr_flags = 0; rs->sr_entry = NULL; } entry_clean( &e ); } endpwent(); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); } } else { char *next; Entry e = { 0 }; int rc; if (! be_issuffix( op->o_bd, &op->o_req_ndn ) ) { dnParent( &op->o_req_ndn, &parent ); } /* This backend is only one layer deep. Don't answer requests for * anything deeper than that. */ if( !be_issuffix( op->o_bd, &parent ) ) { int i; for( i=0; op->o_bd->be_nsuffix[i].bv_val != NULL; i++ ) { if( dnIsSuffix( &op->o_req_ndn, &op->o_bd->be_nsuffix[i] ) ) { rs->sr_matched = op->o_bd->be_suffix[i].bv_val; break; } } rs->sr_err = LDAP_NO_SUCH_OBJECT; goto done; } if( op->ors_scope == LDAP_SCOPE_ONELEVEL ) { goto done; } if ( ldap_bv2rdn( &op->o_req_dn, &rdn, &next, LDAP_DN_FORMAT_LDAP )) { rs->sr_err = LDAP_OTHER; goto done; } ldap_pvt_thread_mutex_lock( &passwd_mutex ); pw_start( op->o_bd ); pw = getpwnam( rdn[0]->la_value.bv_val ); if ( pw == NULL ) { rs->sr_matched = parent.bv_val; rs->sr_err = LDAP_NO_SUCH_OBJECT; ldap_pvt_thread_mutex_unlock( &passwd_mutex ); goto done; } rc = pw2entry( op->o_bd, pw, &e ); ldap_pvt_thread_mutex_unlock( &passwd_mutex ); if ( rc ) { rs->sr_err = LDAP_OTHER; goto done; } if ( test_filter( op, &e, op->ors_filter ) == LDAP_COMPARE_TRUE ) { rs->sr_entry = &e; rs->sr_attrs = op->ors_attrs; rs->sr_flags = REP_ENTRY_MODIFIABLE; send_search_entry( op, rs ); rs->sr_flags = 0; rs->sr_entry = NULL; rs->sr_attrs = NULL; } entry_clean( &e ); } done: if( rs->sr_err != LDAP_NO_SUCH_OBJECT ) rs->sr_matched = NULL; send_ldap_result( op, rs ); if( rdn != NULL ) ldap_rdnfree( rdn ); return( 0 ); }
int ldap_back_search( Operation *op, SlapReply *rs ) { ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private; ldapconn_t *lc = NULL; struct timeval tv; time_t stoptime = (time_t)(-1); LDAPMessage *res, *e; int rc = 0, msgid; struct berval match = BER_BVNULL, filter = BER_BVNULL; int i, x; char **attrs = NULL; int freetext = 0, filter_undef = 0; int do_retry = 1, dont_retry = 0; LDAPControl **ctrls = NULL; char **references = NULL; rs_assert_ready( rs ); rs->sr_flags &= ~REP_ENTRY_MASK; /* paranoia, we can set rs = non-entry */ if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) { return rs->sr_err; } /* * FIXME: in case of values return filter, we might want * to map attrs and maybe rewrite value */ if ( op->ors_tlimit != SLAP_NO_LIMIT ) { tv.tv_sec = op->ors_tlimit; tv.tv_usec = 0; stoptime = op->o_time + op->ors_tlimit; } else { LDAP_BACK_TV_SET( &tv ); } i = 0; if ( op->ors_attrs ) { for ( ; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++ ) /* just count attrs */ ; } x = 0; if ( op->o_bd->be_extra_anlist ) { for ( ; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++ ) /* just count attrs */ ; } if ( i > 0 || x > 0 ) { int j = 0; attrs = op->o_tmpalloc( ( i + x + 1 )*sizeof( char * ), op->o_tmpmemctx ); if ( attrs == NULL ) { rs->sr_err = LDAP_NO_MEMORY; rc = -1; goto finish; } if ( i > 0 ) { for ( i = 0; !BER_BVISNULL( &op->ors_attrs[i].an_name ); i++, j++ ) { attrs[ j ] = op->ors_attrs[i].an_name.bv_val; } } if ( x > 0 ) { for ( x = 0; !BER_BVISNULL( &op->o_bd->be_extra_anlist[x].an_name ); x++, j++ ) { if ( op->o_bd->be_extra_anlist[x].an_desc && ad_inlist( op->o_bd->be_extra_anlist[x].an_desc, op->ors_attrs ) ) { continue; } attrs[ j ] = op->o_bd->be_extra_anlist[x].an_name.bv_val; } } attrs[ j ] = NULL; } ctrls = op->o_ctrls; rc = ldap_back_controls_add( op, rs, lc, &ctrls ); if ( rc != LDAP_SUCCESS ) { goto finish; } /* deal with <draft-zeilenga-ldap-t-f> filters */ filter = op->ors_filterstr; retry: /* this goes after retry because ldap_back_munge_filter() * optionally replaces RFC 4526 T-F filters (&) (|) * if already computed, they will be re-installed * by filter2bv_undef_x() later */ if ( !LDAP_BACK_T_F( li ) ) { ldap_back_munge_filter( op, &filter ); } rs->sr_err = ldap_pvt_search( lc->lc_ld, op->o_req_dn.bv_val, op->ors_scope, filter.bv_val, attrs, op->ors_attrsonly, ctrls, NULL, tv.tv_sec ? &tv : NULL, op->ors_slimit, op->ors_deref, &msgid ); ldap_pvt_thread_mutex_lock( &li->li_counter_mutex ); ldap_pvt_mp_add( li->li_ops_completed[ SLAP_OP_SEARCH ], 1 ); ldap_pvt_thread_mutex_unlock( &li->li_counter_mutex ); if ( rs->sr_err != LDAP_SUCCESS ) { switch ( rs->sr_err ) { case LDAP_SERVER_DOWN: if ( do_retry ) { do_retry = 0; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_DONTSEND ) ) { goto retry; } } if ( lc == NULL ) { /* reset by ldap_back_retry ... */ rs->sr_err = slap_map_api2result( rs ); } else { rc = ldap_back_op_result( lc, op, rs, msgid, 0, LDAP_BACK_DONTSEND ); } goto finish; case LDAP_FILTER_ERROR: /* first try? */ if ( !filter_undef && strstr( filter.bv_val, "(?" ) && !LDAP_BACK_NOUNDEFFILTER( li ) ) { BER_BVZERO( &filter ); filter2bv_undef_x( op, op->ors_filter, 1, &filter ); filter_undef = 1; goto retry; } /* invalid filters return success with no data */ rs->sr_err = LDAP_SUCCESS; rs->sr_text = NULL; goto finish; default: rs->sr_err = slap_map_api2result( rs ); rs->sr_text = NULL; goto finish; } } /* if needed, initialize timeout */ if ( li->li_timeout[ SLAP_OP_SEARCH ] ) { if ( tv.tv_sec == 0 || tv.tv_sec > li->li_timeout[ SLAP_OP_SEARCH ] ) { tv.tv_sec = li->li_timeout[ SLAP_OP_SEARCH ]; tv.tv_usec = 0; } } /* We pull apart the ber result, stuff it into a slapd entry, and * let send_search_entry stuff it back into ber format. Slow & ugly, * but this is necessary for version matching, and for ACL processing. */ for ( rc = -2; rc != -1; rc = ldap_result( lc->lc_ld, msgid, LDAP_MSG_ONE, &tv, &res ) ) { /* check for abandon */ if ( op->o_abandon || LDAP_BACK_CONN_ABANDON( lc ) ) { if ( rc > 0 ) { ldap_msgfree( res ); } (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND ); rc = SLAPD_ABANDON; goto finish; } if ( rc == 0 || rc == -2 ) { ldap_pvt_thread_yield(); /* check timeout */ if ( li->li_timeout[ SLAP_OP_SEARCH ] ) { if ( rc == 0 ) { (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND ); rs->sr_text = "Operation timed out"; rc = rs->sr_err = op->o_protocol >= LDAP_VERSION3 ? LDAP_ADMINLIMIT_EXCEEDED : LDAP_OTHER; goto finish; } } else { LDAP_BACK_TV_SET( &tv ); } /* check time limit */ if ( op->ors_tlimit != SLAP_NO_LIMIT && slap_get_time() > stoptime ) { (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND ); rc = rs->sr_err = LDAP_TIMELIMIT_EXCEEDED; goto finish; } continue; } else { /* only touch when activity actually took place... */ if ( li->li_idle_timeout && lc ) { lc->lc_time = op->o_time; } /* don't retry any more */ dont_retry = 1; } if ( rc == LDAP_RES_SEARCH_ENTRY ) { Entry ent = { 0 }; struct berval bdn = BER_BVNULL; do_retry = 0; e = ldap_first_entry( lc->lc_ld, res ); rc = ldap_build_entry( op, e, &ent, &bdn ); if ( rc == LDAP_SUCCESS ) { ldap_get_entry_controls( lc->lc_ld, res, &rs->sr_ctrls ); rs->sr_entry = &ent; rs->sr_attrs = op->ors_attrs; rs->sr_operational_attrs = NULL; rs->sr_flags = 0; rs->sr_err = LDAP_SUCCESS; rc = rs->sr_err = send_search_entry( op, rs ); if ( rs->sr_ctrls ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } rs->sr_entry = NULL; rs->sr_flags = 0; if ( !BER_BVISNULL( &ent.e_name ) ) { assert( ent.e_name.bv_val != bdn.bv_val ); op->o_tmpfree( ent.e_name.bv_val, op->o_tmpmemctx ); BER_BVZERO( &ent.e_name ); } if ( !BER_BVISNULL( &ent.e_nname ) ) { op->o_tmpfree( ent.e_nname.bv_val, op->o_tmpmemctx ); BER_BVZERO( &ent.e_nname ); } entry_clean( &ent ); } ldap_msgfree( res ); switch ( rc ) { case LDAP_SUCCESS: case LDAP_INSUFFICIENT_ACCESS: break; default: if ( rc == LDAP_UNAVAILABLE ) { rc = rs->sr_err = LDAP_OTHER; } else { (void)ldap_back_cancel( lc, op, rs, msgid, LDAP_BACK_DONTSEND ); } goto finish; } } else if ( rc == LDAP_RES_SEARCH_REFERENCE ) { if ( LDAP_BACK_NOREFS( li ) ) { ldap_msgfree( res ); continue; } do_retry = 0; rc = ldap_parse_reference( lc->lc_ld, res, &references, &rs->sr_ctrls, 1 ); if ( rc != LDAP_SUCCESS ) { continue; } /* FIXME: there MUST be at least one */ if ( references && references[ 0 ] && references[ 0 ][ 0 ] ) { int cnt; for ( cnt = 0; references[ cnt ]; cnt++ ) /* NO OP */ ; /* FIXME: there MUST be at least one */ rs->sr_ref = op->o_tmpalloc( ( cnt + 1 ) * sizeof( struct berval ), op->o_tmpmemctx ); for ( cnt = 0; references[ cnt ]; cnt++ ) { ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] ); } BER_BVZERO( &rs->sr_ref[ cnt ] ); /* ignore return value by now */ RS_ASSERT( !(rs->sr_flags & REP_ENTRY_MASK) ); rs->sr_entry = NULL; ( void )send_search_reference( op, rs ); } else { Debug( LDAP_DEBUG_ANY, "%s ldap_back_search: " "got SEARCH_REFERENCE " "with no referrals\n", op->o_log_prefix, 0, 0 ); } /* cleanup */ if ( references ) { ber_memvfree( (void **)references ); op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx ); rs->sr_ref = NULL; references = NULL; } if ( rs->sr_ctrls ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } } else if ( rc == LDAP_RES_INTERMEDIATE ) { /* FIXME: response controls * are passed without checks */ rc = ldap_parse_intermediate( lc->lc_ld, res, (char **)&rs->sr_rspoid, &rs->sr_rspdata, &rs->sr_ctrls, 0 ); if ( rc != LDAP_SUCCESS ) { continue; } slap_send_ldap_intermediate( op, rs ); if ( rs->sr_rspoid != NULL ) { ber_memfree( (char *)rs->sr_rspoid ); rs->sr_rspoid = NULL; } if ( rs->sr_rspdata != NULL ) { ber_bvfree( rs->sr_rspdata ); rs->sr_rspdata = NULL; } if ( rs->sr_ctrls != NULL ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } } else { char *err = NULL; rc = ldap_parse_result( lc->lc_ld, res, &rs->sr_err, &match.bv_val, &err, &references, &rs->sr_ctrls, 1 ); if ( rc == LDAP_SUCCESS ) { if ( err ) { rs->sr_text = err; freetext = 1; } } else { rs->sr_err = rc; } rs->sr_err = slap_map_api2result( rs ); /* RFC 4511: referrals can only appear * if result code is LDAP_REFERRAL */ if ( references && references[ 0 ] && references[ 0 ][ 0 ] ) { if ( rs->sr_err != LDAP_REFERRAL ) { Debug( LDAP_DEBUG_ANY, "%s ldap_back_search: " "got referrals with err=%d\n", op->o_log_prefix, rs->sr_err, 0 ); } else { int cnt; for ( cnt = 0; references[ cnt ]; cnt++ ) /* NO OP */ ; rs->sr_ref = op->o_tmpalloc( ( cnt + 1 ) * sizeof( struct berval ), op->o_tmpmemctx ); for ( cnt = 0; references[ cnt ]; cnt++ ) { /* duplicating ...*/ ber_str2bv( references[ cnt ], 0, 0, &rs->sr_ref[ cnt ] ); } BER_BVZERO( &rs->sr_ref[ cnt ] ); } } else if ( rs->sr_err == LDAP_REFERRAL ) { Debug( LDAP_DEBUG_ANY, "%s ldap_back_search: " "got err=%d with null " "or empty referrals\n", op->o_log_prefix, rs->sr_err, 0 ); rs->sr_err = LDAP_NO_SUCH_OBJECT; } if ( match.bv_val != NULL ) { match.bv_len = strlen( match.bv_val ); } rc = 0; break; } /* if needed, restore timeout */ if ( li->li_timeout[ SLAP_OP_SEARCH ] ) { if ( tv.tv_sec == 0 || tv.tv_sec > li->li_timeout[ SLAP_OP_SEARCH ] ) { tv.tv_sec = li->li_timeout[ SLAP_OP_SEARCH ]; tv.tv_usec = 0; } } } if ( rc == -1 ) { if ( dont_retry == 0 ) { if ( do_retry ) { do_retry = 0; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_DONTSEND ) ) { goto retry; } } rs->sr_err = LDAP_SERVER_DOWN; rs->sr_err = slap_map_api2result( rs ); goto finish; } else if ( LDAP_BACK_ONERR_STOP( li ) ) { /* if onerr == STOP */ rs->sr_err = LDAP_SERVER_DOWN; rs->sr_err = slap_map_api2result( rs ); goto finish; } } /* * Rewrite the matched portion of the search base, if required */ if ( !BER_BVISNULL( &match ) && !BER_BVISEMPTY( &match ) ) { struct berval pmatch; if ( dnPretty( NULL, &match, &pmatch, op->o_tmpmemctx ) != LDAP_SUCCESS ) { pmatch.bv_val = match.bv_val; match.bv_val = NULL; } rs->sr_matched = pmatch.bv_val; rs->sr_flags |= REP_MATCHED_MUSTBEFREED; } finish:; if ( !BER_BVISNULL( &match ) ) { ber_memfree( match.bv_val ); } if ( rs->sr_v2ref ) { rs->sr_err = LDAP_REFERRAL; } if ( LDAP_BACK_QUARANTINE( li ) ) { ldap_back_quarantine( op, rs ); } if ( filter.bv_val != op->ors_filterstr.bv_val ) { op->o_tmpfree( filter.bv_val, op->o_tmpmemctx ); } #if 0 /* let send_ldap_result play cleanup handlers (ITS#4645) */ if ( rc != SLAPD_ABANDON ) #endif { send_ldap_result( op, rs ); } (void)ldap_back_controls_free( op, rs, &ctrls ); if ( rs->sr_ctrls ) { ldap_controls_free( rs->sr_ctrls ); rs->sr_ctrls = NULL; } if ( rs->sr_text ) { if ( freetext ) { ber_memfree( (char *)rs->sr_text ); } rs->sr_text = NULL; } if ( rs->sr_ref ) { op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx ); rs->sr_ref = NULL; } if ( references ) { ber_memvfree( (void **)references ); } if ( attrs ) { op->o_tmpfree( attrs, op->o_tmpmemctx ); } if ( lc != NULL ) { ldap_back_release_conn( li, lc ); } return rs->sr_err; }