Esempio n. 1
0
static int
slapi_op_func( Operation *op, SlapReply *rs )
{
	Slapi_PBlock		*pb;
	slap_operation_t	which;
	struct slapi_op_info	*opinfo;
	int			rc;
	slap_overinfo		*oi;
	slap_overinst		*on;
	slap_callback		cb;
	int			internal_op;
	int			preop_type, postop_type;
	BackendDB		*be;

	if ( !slapi_plugins_used )
		return SLAP_CB_CONTINUE;

	/*
	 * Find the SLAPI operation information for this LDAP
	 * operation; this will contain the preop and postop
	 * plugin types, as well as optional callbacks for
	 * setting up the SLAPI environment.
	 */
	which = slapi_tag2op( op->o_tag );
	if ( which >= op_last ) {
		/* invalid operation, but let someone else deal with it */
		return SLAP_CB_CONTINUE;
	}

	opinfo = &slapi_op_dispatch_table[which];
	if ( opinfo == NULL ) {
		/* no SLAPI plugin types for this operation */
		return SLAP_CB_CONTINUE;
	}

	internal_op = slapi_op_internal_p( op, rs, &cb );

	if ( internal_op ) {
		preop_type = opinfo->soi_internal_preop;
		postop_type = opinfo->soi_internal_postop;
	} else {
		preop_type = opinfo->soi_preop;
		postop_type = opinfo->soi_postop;
	}

	if ( preop_type == 0 ) {
		/* no SLAPI plugin types for this operation */
		pb = NULL;
		rc = SLAP_CB_CONTINUE;
		goto cleanup;
	}

	pb = SLAPI_OPERATION_PBLOCK( op );

	/* cache backend so we call correct postop plugins */
	be = pb->pb_op->o_bd;

	rc = slapi_int_call_plugins( be, preop_type, pb );

	/*
	 * soi_callback is responsible for examining the result code
	 * of the preoperation plugin and determining whether to
	 * abort. This is needed because of special SLAPI behaviour
	 e with bind preoperation plugins.
	 *
	 * The soi_callback function is also used to reset any values
	 * returned from the preoperation plugin before calling the
	 * backend (for the success case).
	 */
	if ( opinfo->soi_callback == NULL ) {
		/* default behaviour is preop plugin can abort operation */
		if ( rc < 0 ) {
			rc = rs->sr_err;
			goto cleanup;
		}
	} else {
		rc = (opinfo->soi_callback)( op, rs, rc );
		if ( rc )
			goto cleanup;
	}

	/*
	 * Call actual backend (or next overlay in stack). We need to
	 * do this rather than returning SLAP_CB_CONTINUE and calling
	 * postoperation plugins in a response handler to match the
	 * behaviour of SLAPI in OpenLDAP 2.2, where postoperation
	 * plugins are called after the backend has completely
	 * finished processing the operation.
	 */
	on = (slap_overinst *)op->o_bd->bd_info;
	oi = on->on_info;

	rc = overlay_op_walk( op, rs, which, oi, on->on_next );

	/*
	 * Call postoperation plugins
	 */
	slapi_int_call_plugins( be, postop_type, pb );

cleanup:
	if ( !internal_op ) {
		slapi_pblock_destroy(pb);
		cb.sc_private = NULL;
	}

	op->o_callback = cb.sc_next;

	return rc;
}
Esempio n. 2
0
static int translucent_search(Operation *op, SlapReply *rs) {
	slap_overinst *on = (slap_overinst *) op->o_bd->bd_info;
	translucent_info *ov = on->on_bi.bi_private;
	slap_callback cb = { NULL, NULL, NULL, NULL };
	trans_ctx tc;
	Filter *fl, *fr;
	struct berval fbv;
	int rc = 0;

	if ( op->o_managedsait > SLAP_CONTROL_IGNORED )
		return SLAP_CB_CONTINUE;

	Debug(LDAP_DEBUG_TRACE, "==> translucent_search: <%s> %s\n",
		op->o_req_dn.bv_val, op->ors_filterstr.bv_val, 0);

	if(ov->defer_db_open) {
		send_ldap_error(op, rs, LDAP_UNAVAILABLE,
			"remote DB not available");
		return(rs->sr_err);
	}

	fr = ov->remote ? trans_filter_dup( op, op->ors_filter, ov->remote ) : NULL;
	fl = ov->local ? trans_filter_dup( op, op->ors_filter, ov->local ) : NULL;
	cb.sc_response = (slap_response *) translucent_search_cb;
	cb.sc_private = &tc;
	cb.sc_next = op->o_callback;

	ov->db.be_acl = op->o_bd->be_acl;
	tc.db = op->o_bd;
	tc.on = on;
	tc.orig = op->ors_filter;
	tc.list = NULL;
	tc.step = 0;
	tc.slimit = op->ors_slimit;
	tc.attrs = NULL;
	fbv = op->ors_filterstr;

	op->o_callback = &cb;

	if ( fr || !fl ) {
		tc.attrs = op->ors_attrs;
		op->ors_slimit = SLAP_NO_LIMIT;
		op->ors_attrs = slap_anlist_all_attributes;
		op->o_bd = &ov->db;
		tc.step |= RMT_SIDE;
		if ( fl ) {
			tc.step |= USE_LIST;
			op->ors_filter = fr;
			filter2bv_x( op, fr, &op->ors_filterstr );
		}
		rc = ov->db.bd_info->bi_op_search(op, rs);
		if ( op->ors_attrs == slap_anlist_all_attributes )
			op->ors_attrs = tc.attrs;
		op->o_bd = tc.db;
		if ( fl ) {
			op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
		}
	}
	if ( fl && !rc ) {
		tc.step |= LCL_SIDE;
		op->ors_filter = fl;
		filter2bv_x( op, fl, &op->ors_filterstr );
		rc = overlay_op_walk( op, rs, op_search, on->on_info, on->on_next );
		op->o_tmpfree( op->ors_filterstr.bv_val, op->o_tmpmemctx );
	}
	op->ors_filterstr = fbv;
	op->ors_filter = tc.orig;
	op->o_callback = cb.sc_next;
	rs->sr_attrs = op->ors_attrs;
	rs->sr_attr_flags = slap_attr_flags( rs->sr_attrs );

	/* Send out anything remaining on the list and finish */
	if ( tc.step & USE_LIST ) {
		if ( tc.list ) {
			Avlnode *av;

			av = tavl_end( tc.list, TAVL_DIR_LEFT );
			while ( av ) {
				rs->sr_entry = av->avl_data;
				if ( rc == LDAP_SUCCESS && LDAP_COMPARE_TRUE ==
					test_filter( op, rs->sr_entry, op->ors_filter ))
				{
					rs->sr_flags = REP_ENTRY_MUSTBEFREED;
					rc = send_search_entry( op, rs );
				} else {
					entry_free( rs->sr_entry );
				}
				av = tavl_next( av, TAVL_DIR_RIGHT );
			}
			tavl_free( tc.list, NULL );
			rs->sr_flags = 0;
			rs->sr_entry = NULL;
		}
		send_ldap_result( op, rs );
	}

	op->ors_slimit = tc.slimit;

	/* Free in reverse order */
	if ( fl )
		trans_filter_free( op, fl );
	if ( fr )
		trans_filter_free( op, fr );

	return rc;
}