int ldap_back_compare( Operation *op, SlapReply *rs ) { ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; ldapconn_t *lc = NULL; ber_int_t msgid; ldap_back_send_t retrying = LDAP_BACK_RETRYING; LDAPControl **ctrls = NULL; int rc = LDAP_SUCCESS; if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) { lc = NULL; goto cleanup; } retry: ctrls = op->o_ctrls; rc = ldap_back_controls_add( op, rs, lc, &ctrls ); if ( rc != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; } rs->sr_err = ldap_compare_ext( lc->lc_ld, op->o_req_dn.bv_val, op->orc_ava->aa_desc->ad_cname.bv_val, &op->orc_ava->aa_value, ctrls, NULL, &msgid ); rc = ldap_back_op_result( lc, op, rs, msgid, li->li_timeout[ SLAP_OP_COMPARE ], ( LDAP_BACK_SENDRESULT | retrying ) ); if ( rc == LDAP_UNAVAILABLE && retrying ) { retrying &= ~LDAP_BACK_RETRYING; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { /* if the identity changed, there might be need to re-authz */ (void)ldap_back_controls_free( op, rs, &ctrls ); goto retry; } } ldap_pvt_thread_mutex_lock( &li->li_counter_mutex ); ldap_pvt_mp_add( li->li_ops_completed[ SLAP_OP_COMPARE ], 1 ); ldap_pvt_thread_mutex_unlock( &li->li_counter_mutex ); cleanup: (void)ldap_back_controls_free( op, rs, &ctrls ); if ( lc != NULL ) { ldap_back_release_conn( li, lc ); } return rs->sr_err; }
int ldap_back_delete( Operation *op, SlapReply *rs ) { ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; ldapconn_t *lc = NULL; ber_int_t msgid; LDAPControl **ctrls = NULL; ldap_back_send_t retrying = LDAP_BACK_RETRYING; int rc = LDAP_SUCCESS; if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) { return rs->sr_err; } retry: ctrls = op->o_ctrls; rc = ldap_back_controls_add( op, rs, lc, &ctrls ); if ( rc != LDAP_SUCCESS ) { send_ldap_result( op, rs ); rc = rs->sr_err; goto cleanup; } rs->sr_err = ldap_delete_ext( lc->lc_ld, op->o_req_dn.bv_val, ctrls, NULL, &msgid ); rc = ldap_back_op_result( lc, op, rs, msgid, li->li_timeout[ SLAP_OP_DELETE ], ( LDAP_BACK_SENDRESULT | retrying ) ); if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) { retrying &= ~LDAP_BACK_RETRYING; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { /* if the identity changed, there might be need to re-authz */ (void)ldap_back_controls_free( op, rs, &ctrls ); goto retry; } } cleanup: (void)ldap_back_controls_free( op, rs, &ctrls ); if ( lc != NULL ) { ldap_back_release_conn( li, lc ); } return rc; }
static int ldap_back_extended_one( Operation *op, SlapReply *rs, ldap_back_exop_f exop ) { ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private; ldapconn_t *lc = NULL; LDAPControl **ctrls = NULL, **oldctrls = NULL; int rc; /* FIXME: this needs to be called here, so it is * called twice; maybe we could avoid the * ldap_back_dobind() call inside each extended() * call ... */ if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) { return -1; } ctrls = op->o_ctrls; if ( ldap_back_controls_add( op, rs, lc, &ctrls ) ) { op->o_ctrls = oldctrls; send_ldap_extended( op, rs ); rs->sr_text = NULL; /* otherwise frontend resends result */ rc = rs->sr_err = SLAPD_ABANDON; goto done; } op->o_ctrls = ctrls; rc = exop( op, rs, &lc ); op->o_ctrls = oldctrls; (void)ldap_back_controls_free( op, rs, &ctrls ); done:; if ( lc != NULL ) { ldap_back_release_conn( li, lc ); } return rc; }
int ldap_back_modify( Operation *op, SlapReply *rs ) { ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; ldapconn_t *lc = NULL; LDAPMod **modv = NULL, *mods = NULL; Modifications *ml; int i, j, rc; ber_int_t msgid; int isupdate; ldap_back_send_t retrying = LDAP_BACK_RETRYING; LDAPControl **ctrls = NULL; if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) { return rs->sr_err; } for ( i = 0, ml = op->orm_modlist; ml; i++, ml = ml->sml_next ) /* just count mods */ ; modv = (LDAPMod **)ch_malloc( ( i + 1 )*sizeof( LDAPMod * ) + i*sizeof( LDAPMod ) ); if ( modv == NULL ) { rc = LDAP_NO_MEMORY; goto cleanup; } mods = (LDAPMod *)&modv[ i + 1 ]; isupdate = be_shadow_update( op ); for ( i = 0, ml = op->orm_modlist; ml; ml = ml->sml_next ) { if ( !isupdate && !get_relax( op ) && ml->sml_desc->ad_type->sat_no_user_mod ) { continue; } modv[ i ] = &mods[ i ]; mods[ i ].mod_op = ( ml->sml_op | LDAP_MOD_BVALUES ); mods[ i ].mod_type = ml->sml_desc->ad_cname.bv_val; if ( ml->sml_values != NULL ) { if ( ml->sml_values == NULL ) { continue; } for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) /* just count mods */ ; mods[ i ].mod_bvalues = (struct berval **)ch_malloc( ( j + 1 )*sizeof( struct berval * ) ); for ( j = 0; !BER_BVISNULL( &ml->sml_values[ j ] ); j++ ) { mods[ i ].mod_bvalues[ j ] = &ml->sml_values[ j ]; } mods[ i ].mod_bvalues[ j ] = NULL; } else { mods[ i ].mod_bvalues = NULL; } i++; } modv[ i ] = 0; retry:; ctrls = op->o_ctrls; rc = ldap_back_controls_add( op, rs, lc, &ctrls ); if ( rc != LDAP_SUCCESS ) { send_ldap_result( op, rs ); rc = -1; goto cleanup; } rs->sr_err = ldap_modify_ext( lc->lc_ld, op->o_req_dn.bv_val, modv, ctrls, NULL, &msgid ); rc = ldap_back_op_result( lc, op, rs, msgid, li->li_timeout[ SLAP_OP_MODIFY ], ( LDAP_BACK_SENDRESULT | retrying ) ); if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) { retrying &= ~LDAP_BACK_RETRYING; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { /* if the identity changed, there might be need to re-authz */ (void)ldap_back_controls_free( op, rs, &ctrls ); goto retry; } } cleanup:; (void)ldap_back_controls_free( op, rs, &ctrls ); for ( i = 0; modv[ i ]; i++ ) { ch_free( modv[ i ]->mod_bvalues ); } ch_free( modv ); if ( lc != NULL ) { ldap_back_release_conn( li, lc ); } return rc; }
int ldap_back_add( Operation *op, SlapReply *rs ) { ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; ldapconn_t *lc = NULL; int i = 0, j = 0; Attribute *a; LDAPMod **attrs = NULL, *attrs2 = NULL; ber_int_t msgid; int isupdate; ldap_back_send_t retrying = LDAP_BACK_RETRYING; LDAPControl **ctrls = NULL; rs->sr_err = LDAP_SUCCESS; Debug( LDAP_DEBUG_ARGS, "==> ldap_back_add(\"%s\")\n", op->o_req_dn.bv_val, 0, 0 ); if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) { lc = NULL; goto cleanup; } /* Count number of attributes in entry */ for ( i = 1, a = op->oq_add.rs_e->e_attrs; a; i++, a = a->a_next ) /* just count attrs */ ; /* Create array of LDAPMods for ldap_add() */ attrs = (LDAPMod **)ch_malloc( sizeof( LDAPMod * )*i + sizeof( LDAPMod )*( i - 1 ) ); attrs2 = ( LDAPMod * )&attrs[ i ]; isupdate = be_shadow_update( op ); for ( i = 0, a = op->oq_add.rs_e->e_attrs; a; a = a->a_next ) { if ( !isupdate && !get_relax( op ) && a->a_desc->ad_type->sat_no_user_mod ) { continue; } attrs[ i ] = &attrs2[ i ]; attrs[ i ]->mod_op = LDAP_MOD_BVALUES; attrs[ i ]->mod_type = a->a_desc->ad_cname.bv_val; for ( j = 0; a->a_vals[ j ].bv_val; j++ ) /* just count vals */ ; attrs[i]->mod_vals.modv_bvals = ch_malloc( ( j + 1 )*sizeof( struct berval * ) ); for ( j = 0; a->a_vals[ j ].bv_val; j++ ) { attrs[ i ]->mod_vals.modv_bvals[ j ] = &a->a_vals[ j ]; } attrs[ i ]->mod_vals.modv_bvals[ j ] = NULL; i++; } attrs[ i ] = NULL; retry: ctrls = op->o_ctrls; rs->sr_err = ldap_back_controls_add( op, rs, lc, &ctrls ); if ( rs->sr_err != LDAP_SUCCESS ) { send_ldap_result( op, rs ); goto cleanup; } rs->sr_err = ldap_add_ext( lc->lc_ld, op->o_req_dn.bv_val, attrs, ctrls, NULL, &msgid ); rs->sr_err = ldap_back_op_result( lc, op, rs, msgid, li->li_timeout[ SLAP_OP_ADD ], ( LDAP_BACK_SENDRESULT | retrying ) ); if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) { retrying &= ~LDAP_BACK_RETRYING; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { /* if the identity changed, there might be need to re-authz */ (void)ldap_back_controls_free( op, rs, &ctrls ); goto retry; } } ldap_pvt_thread_mutex_lock( &li->li_counter_mutex ); ldap_pvt_mp_add( li->li_ops_completed[ SLAP_OP_ADD ], 1 ); ldap_pvt_thread_mutex_unlock( &li->li_counter_mutex ); cleanup: (void)ldap_back_controls_free( op, rs, &ctrls ); if ( attrs ) { for ( --i; i >= 0; --i ) { ch_free( attrs[ i ]->mod_vals.modv_bvals ); } ch_free( attrs ); } if ( lc ) { ldap_back_release_conn( li, lc ); } Debug( LDAP_DEBUG_ARGS, "<== ldap_back_add(\"%s\"): %d\n", op->o_req_dn.bv_val, rs->sr_err, 0 ); return rs->sr_err; }
int ldap_back_modrdn( Operation *op, SlapReply *rs ) { ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private; ldapconn_t *lc = NULL; ber_int_t msgid; LDAPControl **ctrls = NULL; ldap_back_send_t retrying = LDAP_BACK_RETRYING; int rc = LDAP_SUCCESS; char *newSup = NULL; struct berval newrdn = BER_BVNULL; if ( !ldap_back_dobind( &lc, op, rs, LDAP_BACK_SENDERR ) ) { return rs->sr_err; } if ( op->orr_newSup ) { /* needs LDAPv3 */ switch ( li->li_version ) { case LDAP_VERSION3: break; case 0: if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) { break; } /* fall thru */ default: /* op->o_protocol cannot be anything but LDAPv3, * otherwise wouldn't be here */ rs->sr_err = LDAP_UNWILLING_TO_PERFORM; send_ldap_result( op, rs ); goto cleanup; } newSup = op->orr_newSup->bv_val; } /* NOTE: we need to copy the newRDN in case it was formed * from a DN by simply changing the length (ITS#5397) */ newrdn = op->orr_newrdn; if ( newrdn.bv_val[ newrdn.bv_len ] != '\0' ) { ber_dupbv_x( &newrdn, &op->orr_newrdn, op->o_tmpmemctx ); } retry: ctrls = op->o_ctrls; rc = ldap_back_controls_add( op, rs, lc, &ctrls ); if ( rc != LDAP_SUCCESS ) { send_ldap_result( op, rs ); rc = -1; goto cleanup; } rs->sr_err = ldap_rename( lc->lc_ld, op->o_req_dn.bv_val, newrdn.bv_val, newSup, op->orr_deleteoldrdn, ctrls, NULL, &msgid ); rc = ldap_back_op_result( lc, op, rs, msgid, li->li_timeout[ SLAP_OP_MODRDN ], ( LDAP_BACK_SENDRESULT | retrying ) ); if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) { retrying &= ~LDAP_BACK_RETRYING; if ( ldap_back_retry( &lc, op, rs, LDAP_BACK_SENDERR ) ) { /* if the identity changed, there might be need to re-authz */ (void)ldap_back_controls_free( op, rs, &ctrls ); goto retry; } } cleanup: (void)ldap_back_controls_free( op, rs, &ctrls ); if ( newrdn.bv_val != op->orr_newrdn.bv_val ) { op->o_tmpfree( newrdn.bv_val, op->o_tmpmemctx ); } if ( lc != NULL ) { ldap_back_release_conn( li, lc ); } return rc; }
/* return 0 IFF we can retrieve the entry with ndn */ int ldap_back_entry_get( Operation *op, struct berval *ndn, ObjectClass *oc, AttributeDescription *at, int rw, Entry **ent ) { ldapinfo_t *li = (ldapinfo_t *) op->o_bd->be_private; ldapconn_t *lc = NULL; int rc, do_not_cache; ber_tag_t tag; struct berval bdn; LDAPMessage *result = NULL, *e = NULL; char *attr[3], **attrp = NULL; char *filter = NULL; SlapReply rs; int do_retry = 1; LDAPControl **ctrls = NULL; *ent = NULL; /* Tell getconn this is a privileged op */ do_not_cache = op->o_do_not_cache; tag = op->o_tag; /* do not cache */ op->o_do_not_cache = 1; /* ldap_back_entry_get() is an entry lookup, so it does not need * to know what the entry is being looked up for */ op->o_tag = LDAP_REQ_SEARCH; rc = ldap_back_dobind( &lc, op, &rs, LDAP_BACK_DONTSEND ); op->o_do_not_cache = do_not_cache; op->o_tag = tag; if ( !rc ) { return rs.sr_err; } if ( at ) { attrp = attr; if ( oc && at != slap_schema.si_ad_objectClass ) { attr[0] = slap_schema.si_ad_objectClass->ad_cname.bv_val; attr[1] = at->ad_cname.bv_val; attr[2] = NULL; } else { attr[0] = at->ad_cname.bv_val; attr[1] = NULL; } } if ( oc ) { char *ptr; filter = op->o_tmpalloc( STRLENOF( "(objectClass=" ")" ) + oc->soc_cname.bv_len + 1, op->o_tmpmemctx ); ptr = lutil_strcopy( filter, "(objectClass=" ); ptr = lutil_strcopy( ptr, oc->soc_cname.bv_val ); *ptr++ = ')'; *ptr++ = '\0'; } retry: ctrls = op->o_ctrls; rc = ldap_back_controls_add( op, &rs, lc, &ctrls ); if ( rc != LDAP_SUCCESS ) { goto cleanup; } /* TODO: timeout? */ rc = ldap_pvt_search_s( lc->lc_ld, ndn->bv_val, LDAP_SCOPE_BASE, filter, attrp, LDAP_DEREF_NEVER, ctrls, NULL, NULL, LDAP_NO_LIMIT, 0, &result ); if ( rc != LDAP_SUCCESS ) { if ( rc == LDAP_SERVER_DOWN && do_retry ) { do_retry = 0; if ( ldap_back_retry( &lc, op, &rs, LDAP_BACK_DONTSEND ) ) { /* if the identity changed, there might be need to re-authz */ (void)ldap_back_controls_free( op, &rs, &ctrls ); goto retry; } } goto cleanup; } e = ldap_first_entry( lc->lc_ld, result ); if ( e == NULL ) { /* the entry exists, but it doesn't match the filter? */ goto cleanup; } *ent = entry_alloc(); if ( *ent == NULL ) { rc = LDAP_NO_MEMORY; goto cleanup; } rc = ldap_build_entry( op, e, *ent, &bdn ); if ( rc != LDAP_SUCCESS ) { entry_free( *ent ); *ent = NULL; } cleanup: (void)ldap_back_controls_free( op, &rs, &ctrls ); if ( result ) { ldap_msgfree( result ); } if ( filter ) { op->o_tmpfree( filter, op->o_tmpmemctx ); } if ( lc != NULL ) { ldap_back_release_conn( li, lc ); } return rc; }
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; }