Ejemplo n.º 1
0
meta_search_candidate_t
asyncmeta_dobind_result(
	a_metaconn_t		*mc,
	int			candidate,
	SlapReply		*bind_result,
	LDAPMessage		*res )
{
	a_metainfo_t		*mi = mc->mc_info;
	a_metatarget_t		*mt = mi->mi_targets[ candidate ];
	a_metasingleconn_t	*msc = &mc->mc_conns[ candidate ];

	meta_search_candidate_t	retcode = META_SEARCH_NOT_CANDIDATE;
	int			rc;

	assert( msc->msc_ldr != NULL );

	if ( mi->mi_idle_timeout != 0 ) {
		asyncmeta_set_msc_time(msc);
	}

	if ( LogTest( asyncmeta_debug ) ) {
		char	time_buf[ SLAP_TEXT_BUFLEN ];
		asyncmeta_get_timestamp(time_buf);
		Debug( asyncmeta_debug, "[%x] [%s] asyncmeta_dobind_result msc: %p, "
		       "msc->msc_binding_time: %x, msc->msc_flags:%x\n ",
		       (unsigned int)slap_get_time(), time_buf, msc,
		       (unsigned int)msc->msc_binding_time, msc->msc_mscflags );
	}
	/* FIXME: matched? referrals? response controls? */
	rc = ldap_parse_result( msc->msc_ldr, res,
				&(bind_result->sr_err),
				(char **)&(bind_result->sr_matched),
				(char **)&(bind_result->sr_text),
				NULL, NULL, 0 );

	if ( LogTest( asyncmeta_debug ) ) {
		char	time_buf[ SLAP_TEXT_BUFLEN ];
		asyncmeta_get_timestamp(time_buf);
		Debug( asyncmeta_debug,
		       "[%s] asyncmeta_dobind_result error=%d msc: %p\n",
		       time_buf,bind_result->sr_err, msc );
	}

	if ( rc != LDAP_SUCCESS ) {
		bind_result->sr_err = rc;
	}
	rc = slap_map_api2result( bind_result );

	LDAP_BACK_CONN_BINDING_CLEAR( msc );
	if ( rc != LDAP_SUCCESS ) {
		bind_result->sr_err = rc;
	} else {
		/* FIXME: check if bound as idassert authcDN! */
		if ( BER_BVISNULL( &msc->msc_bound_ndn )
			|| BER_BVISEMPTY( &msc->msc_bound_ndn ) )
		{
			LDAP_BACK_CONN_ISANON_SET( msc );
			if ( LogTest( asyncmeta_debug ) ) {
				char	time_buf[ SLAP_TEXT_BUFLEN ];
				asyncmeta_get_timestamp(time_buf);
				Debug( asyncmeta_debug, "[%s] asyncmeta_dobind_result anonymous msc: %p\n",
				      time_buf, msc );
			}

		} else {
			if ( META_BACK_TGT_SAVECRED( mt ) &&
				!BER_BVISNULL( &msc->msc_cred ) &&
				!BER_BVISEMPTY( &msc->msc_cred ) )
			{
				ldap_set_rebind_proc( msc->msc_ldr, mt->mt_rebind_f, msc );
			}
			if ( LogTest( asyncmeta_debug ) ) {
				char	time_buf[ SLAP_TEXT_BUFLEN ];
				asyncmeta_get_timestamp(time_buf);
				Debug( asyncmeta_debug, "[%s] asyncmeta_dobind_result success msc: %p\n",
				      time_buf, msc );
			}
			LDAP_BACK_CONN_ISBOUND_SET( msc );
		}
		retcode = META_SEARCH_CANDIDATE;
	}
	return retcode;
}
Ejemplo n.º 2
0
/*
 * meta_back_dobind
 */
int
meta_back_dobind(
	Operation		*op,
	SlapReply		*rs,
	metaconn_t		*mc,
	ldap_back_send_t	sendok )
{
	metainfo_t		*mi = ( metainfo_t * )op->o_bd->be_private;

	int			bound = 0,
				i,
				isroot = 0;

	SlapReply		*candidates;

	if ( be_isroot( op ) ) {
		isroot = 1;
	}

	if ( LogTest( LDAP_DEBUG_TRACE ) ) {
		char buf[STRLENOF("4294967295U") + 1] = { 0 };
		mi->mi_ldap_extra->connid2str( &mc->mc_base, buf, sizeof(buf) );

		Debug( LDAP_DEBUG_TRACE,
			"%s meta_back_dobind: conn=%s%s\n",
			op->o_log_prefix, buf,
			isroot ? " (isroot)" : "" );
	}

	/*
	 * all the targets are bound as pseudoroot
	 */
	if ( mc->mc_authz_target == META_BOUND_ALL ) {
		bound = 1;
		goto done;
	}

	candidates = meta_back_candidates_get( op );

	for ( i = 0; i < mi->mi_ntargets; i++ ) {
		metatarget_t		*mt = mi->mi_targets[ i ];
		metasingleconn_t	*msc = &mc->mc_conns[ i ];
		int			rc;

		/*
		 * Not a candidate
		 */
		if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) {
			continue;
		}

		assert( msc->msc_ld != NULL );

		/*
		 * If the target is already bound it is skipped
		 */

retry_binding:;
		ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
		if ( LDAP_BACK_CONN_ISBOUND( msc )
			|| ( LDAP_BACK_CONN_ISANON( msc )
				&& mt->mt_idassert_authmethod == LDAP_AUTH_NONE ) )
		{
			ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
			++bound;
			continue;

		} else if ( META_BACK_CONN_CREATING( msc ) || LDAP_BACK_CONN_BINDING( msc ) )
		{
			ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
			ldap_pvt_thread_yield();
			goto retry_binding;

		}

		LDAP_BACK_CONN_BINDING_SET( msc );
		ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );

		rc = meta_back_single_dobind( op, rs, &mc, i,
			LDAP_BACK_DONTSEND, mt->mt_nretries, 1 );
		/*
		 * NOTE: meta_back_single_dobind() already retries;
		 * in case of failure, it resets mc...
		 */
		if ( rc != LDAP_SUCCESS ) {
			char		buf[ SLAP_TEXT_BUFLEN ];

			if ( mc == NULL ) {
				/* meta_back_single_dobind() already sent
				 * response and released connection */
				goto send_err;
			}


			if ( rc == LDAP_UNAVAILABLE ) {
				/* FIXME: meta_back_retry() already re-calls
				 * meta_back_single_dobind() */
				if ( meta_back_retry( op, rs, &mc, i, sendok ) ) {
					goto retry_ok;
				}

				if ( mc != NULL ) {
					ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
					LDAP_BACK_CONN_BINDING_CLEAR( msc );
					meta_back_release_conn_lock( mi, mc, 0 );
					ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
				}

				return 0;
			}

			ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
			LDAP_BACK_CONN_BINDING_CLEAR( msc );
			ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );

			snprintf( buf, sizeof( buf ),
				"meta_back_dobind[%d]: (%s) err=%d (%s).",
				i, isroot ? op->o_bd->be_rootdn.bv_val : "anonymous",
				rc, ldap_err2string( rc ) );
			Debug( LDAP_DEBUG_ANY,
				"%s %s\n",
				op->o_log_prefix, buf );

			/*
			 * null cred bind should always succeed
			 * as anonymous, so a failure means
			 * the target is no longer candidate possibly
			 * due to technical reasons (remote host down?)
			 * so better clear the handle
			 */
			/* leave the target candidate, but record the error for later use */
			candidates[ i ].sr_err = rc;
			if ( META_BACK_ONERR_STOP( mi ) ) {
				bound = 0;
				goto done;
			}

			continue;
		} /* else */

retry_ok:;
		Debug( LDAP_DEBUG_TRACE,
			"%s meta_back_dobind[%d]: "
			"(%s)\n",
			op->o_log_prefix, i,
			isroot ? op->o_bd->be_rootdn.bv_val : "anonymous" );

		ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
		LDAP_BACK_CONN_BINDING_CLEAR( msc );
		if ( isroot ) {
			LDAP_BACK_CONN_ISBOUND_SET( msc );
		} else {
			LDAP_BACK_CONN_ISANON_SET( msc );
		}
		ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
		++bound;
	}

done:;
	if ( LogTest( LDAP_DEBUG_TRACE ) ) {
		char buf[STRLENOF("4294967295U") + 1] = { 0 };
		mi->mi_ldap_extra->connid2str( &mc->mc_base, buf, sizeof(buf) );

		Debug( LDAP_DEBUG_TRACE,
			"%s meta_back_dobind: conn=%s bound=%d\n",
			op->o_log_prefix, buf, bound );
	}

	if ( bound == 0 ) {
		meta_back_release_conn( mi, mc );

send_err:;
		if ( sendok & LDAP_BACK_SENDERR ) {
			if ( rs->sr_err == LDAP_SUCCESS ) {
				rs->sr_err = LDAP_BUSY;
			}
			send_ldap_result( op, rs );
		}

		return 0;
	}

	return ( bound > 0 );
}
Ejemplo n.º 3
0
static int
meta_back_proxy_authz_bind(
	metaconn_t *mc,
	int candidate,
	Operation *op,
	SlapReply *rs,
	ldap_back_send_t sendok,
	int dolock )
{
	metainfo_t		*mi = (metainfo_t *)op->o_bd->be_private;
	metatarget_t		*mt = mi->mi_targets[ candidate ];
	metasingleconn_t	*msc = &mc->mc_conns[ candidate ];
	struct berval		binddn = BER_BVC( "" ),
				cred = BER_BVC( "" );
	int			method = LDAP_AUTH_NONE,
				rc;

	rc = meta_back_proxy_authz_cred( mc, candidate, op, rs, sendok, &binddn, &cred, &method );
	if ( rc == LDAP_SUCCESS && !LDAP_BACK_CONN_ISBOUND( msc ) ) {
		int	msgid;

		switch ( method ) {
		case LDAP_AUTH_NONE:
		case LDAP_AUTH_SIMPLE:

			if(!dolock) {
				ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
			}

			for (;;) {
				rs->sr_err = ldap_sasl_bind( msc->msc_ld,
					binddn.bv_val, LDAP_SASL_SIMPLE,
					&cred, NULL, NULL, &msgid );
				if ( rs->sr_err != LDAP_X_CONNECTING ) {
					break;
				}
				ldap_pvt_thread_yield();
			}

			if(!dolock) {
				ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
			}

			rc = meta_back_bind_op_result( op, rs, mc, candidate, msgid, sendok, dolock );
			if ( rc == LDAP_SUCCESS ) {
				/* set rebind stuff in case of successful proxyAuthz bind,
				 * so that referral chasing is attempted using the right
				 * identity */
				LDAP_BACK_CONN_ISBOUND_SET( msc );
				ber_bvreplace( &msc->msc_bound_ndn, &binddn );

				if ( META_BACK_TGT_SAVECRED( mt ) ) {
					if ( !BER_BVISNULL( &msc->msc_cred ) ) {
						memset( msc->msc_cred.bv_val, 0,
							msc->msc_cred.bv_len );
					}
					ber_bvreplace( &msc->msc_cred, &cred );
					ldap_set_rebind_proc( msc->msc_ld, mt->mt_rebind_f, msc );
				}
			}
			break;

		default:
			LDAP_BUG();
			break;
		}
	}

	return LDAP_BACK_CONN_ISBOUND( msc );
}
Ejemplo n.º 4
0
/*
 * meta_back_single_bind
 *
 * attempts to perform a bind with creds
 */
static int
meta_back_single_bind(
	Operation		*op,
	SlapReply		*rs,
	metaconn_t		*mc,
	int			candidate )
{
	metainfo_t		*mi = ( metainfo_t * )op->o_bd->be_private;
	metatarget_t		*mt = mi->mi_targets[ candidate ];
	struct berval		mdn = BER_BVNULL;
	metasingleconn_t	*msc = &mc->mc_conns[ candidate ];
	int			msgid;
	dncookie		dc;
	struct berval		save_o_dn;
	int			save_o_do_not_cache;
	LDAPControl		**ctrls = NULL;

	if ( !BER_BVISNULL( &msc->msc_bound_ndn ) ) {
		ch_free( msc->msc_bound_ndn.bv_val );
		BER_BVZERO( &msc->msc_bound_ndn );
	}

	if ( !BER_BVISNULL( &msc->msc_cred ) ) {
		/* destroy sensitive data */
		memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
		ch_free( msc->msc_cred.bv_val );
		BER_BVZERO( &msc->msc_cred );
	}

	/*
	 * Rewrite the bind dn if needed
	 */
	dc.target = mt;
	dc.conn = op->o_conn;
	dc.rs = rs;
	dc.ctx = "bindDN";

	if ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
		rs->sr_text = "DN rewrite error";
		rs->sr_err = LDAP_OTHER;
		return rs->sr_err;
	}

	/* don't add proxyAuthz; set the bindDN */
	save_o_dn = op->o_dn;
	save_o_do_not_cache = op->o_do_not_cache;
	op->o_do_not_cache = 1;
	op->o_dn = op->o_req_dn;

	ctrls = op->o_ctrls;
	rs->sr_err = meta_back_controls_add( op, rs, mc, candidate, &ctrls );
	op->o_dn = save_o_dn;
	op->o_do_not_cache = save_o_do_not_cache;
	if ( rs->sr_err != LDAP_SUCCESS ) {
		goto return_results;
	}

	/* FIXME: this fixes the bind problem right now; we need
	 * to use the asynchronous version to get the "matched"
	 * and more in case of failure ... */
	/* FIXME: should we check if at least some of the op->o_ctrls
	 * can/should be passed? */
	for (;;) {
		rs->sr_err = ldap_sasl_bind( msc->msc_ld, mdn.bv_val,
			LDAP_SASL_SIMPLE, &op->orb_cred,
			ctrls, NULL, &msgid );
		if ( rs->sr_err != LDAP_X_CONNECTING ) {
			break;
		}
		ldap_pvt_thread_yield();
	}

	mi->mi_ldap_extra->controls_free( op, rs, &ctrls );

	meta_back_bind_op_result( op, rs, mc, candidate, msgid, LDAP_BACK_DONTSEND, 1 );
	if ( rs->sr_err != LDAP_SUCCESS ) {
		goto return_results;
	}

	/* If defined, proxyAuthz will be used also when
	 * back-ldap is the authorizing backend; for this
	 * purpose, a successful bind is followed by a
	 * bind with the configured identity assertion */
	/* NOTE: use with care */
	if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) {
		meta_back_proxy_authz_bind( mc, candidate, op, rs, LDAP_BACK_SENDERR, 1 );
		if ( !LDAP_BACK_CONN_ISBOUND( msc ) ) {
			goto return_results;
		}
		goto cache_refresh;
	}

	ber_bvreplace( &msc->msc_bound_ndn, &op->o_req_ndn );
	LDAP_BACK_CONN_ISBOUND_SET( msc );
	mc->mc_authz_target = candidate;

	if ( META_BACK_TGT_SAVECRED( mt ) ) {
		if ( !BER_BVISNULL( &msc->msc_cred ) ) {
			memset( msc->msc_cred.bv_val, 0,
				msc->msc_cred.bv_len );
		}
		ber_bvreplace( &msc->msc_cred, &op->orb_cred );
		ldap_set_rebind_proc( msc->msc_ld, mt->mt_rebind_f, msc );
	}

cache_refresh:;
	if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED
			&& !BER_BVISEMPTY( &op->o_req_ndn ) )
	{
		( void )meta_dncache_update_entry( &mi->mi_cache,
				&op->o_req_ndn, candidate );
	}

return_results:;
	if ( mdn.bv_val != op->o_req_dn.bv_val ) {
		free( mdn.bv_val );
	}

	if ( META_BACK_TGT_QUARANTINE( mt ) ) {
		meta_back_quarantine( op, rs, candidate );
	}

	return rs->sr_err;
}
Ejemplo n.º 5
0
/*
 * meta_back_proxy_authz_cred()
 *
 * prepares credentials & method for meta_back_proxy_authz_bind();
 * or, if method is SASL, performs the SASL bind directly.
 */
int
meta_back_proxy_authz_cred(
	metaconn_t		*mc,
	int			candidate,
	Operation		*op,
	SlapReply		*rs,
	ldap_back_send_t	sendok,
	struct berval		*binddn,
	struct berval		*bindcred,
	int			*method )
{
	metainfo_t		*mi = (metainfo_t *)op->o_bd->be_private;
	metatarget_t		*mt = mi->mi_targets[ candidate ];
	metasingleconn_t	*msc = &mc->mc_conns[ candidate ];
	struct berval		ndn;
	int			dobind = 0;

	/* don't proxyAuthz if protocol is not LDAPv3 */
	switch ( mt->mt_version ) {
	case LDAP_VERSION3:
		break;

	case 0:
		if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) {
			break;
		}
		/* fall thru */

	default:
		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
		if ( sendok & LDAP_BACK_SENDERR ) {
			send_ldap_result( op, rs );
		}
		LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
		goto done;
	}

	if ( op->o_tag == LDAP_REQ_BIND ) {
		ndn = op->o_req_ndn;

	} else if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) {
		ndn = op->o_conn->c_ndn;

	} else {
		ndn = op->o_ndn;
	}
	rs->sr_err = LDAP_SUCCESS;

	/*
	 * FIXME: we need to let clients use proxyAuthz
	 * otherwise we cannot do symmetric pools of servers;
	 * we have to live with the fact that a user can
	 * authorize itself as any ID that is allowed
	 * by the authzTo directive of the "proxyauthzdn".
	 */
	/*
	 * NOTE: current Proxy Authorization specification
	 * and implementation do not allow proxy authorization
	 * control to be provided with Bind requests
	 */
	/*
	 * if no bind took place yet, but the connection is bound
	 * and the "proxyauthzdn" is set, then bind as
	 * "proxyauthzdn" and explicitly add the proxyAuthz
	 * control to every operation with the dn bound
	 * to the connection as control value.
	 */

	/* bind as proxyauthzdn only if no idassert mode
	 * is requested, or if the client's identity
	 * is authorized */
	switch ( mt->mt_idassert_mode ) {
	case LDAP_BACK_IDASSERT_LEGACY:
		if ( !BER_BVISNULL( &ndn ) && !BER_BVISEMPTY( &ndn ) ) {
			if ( !BER_BVISNULL( &mt->mt_idassert_authcDN ) && !BER_BVISEMPTY( &mt->mt_idassert_authcDN ) )
			{
				*binddn = mt->mt_idassert_authcDN;
				*bindcred = mt->mt_idassert_passwd;
				dobind = 1;
			}
		}
		break;

	default:
		/* NOTE: rootdn can always idassert */
		if ( BER_BVISNULL( &ndn )
			&& mt->mt_idassert_authz == NULL
			&& !( mt->mt_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) )
		{
			if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
				rs->sr_err = LDAP_INAPPROPRIATE_AUTH;
				if ( sendok & LDAP_BACK_SENDERR ) {
					send_ldap_result( op, rs );
				}
				LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
				goto done;

			}

			rs->sr_err = LDAP_SUCCESS;
			*binddn = slap_empty_bv;
			*bindcred = slap_empty_bv;
			break;

		} else if ( mt->mt_idassert_authz && !be_isroot( op ) ) {
			struct berval authcDN;

			if ( BER_BVISNULL( &ndn ) ) {
				authcDN = slap_empty_bv;

			} else {
				authcDN = ndn;
			}
			rs->sr_err = slap_sasl_matches( op, mt->mt_idassert_authz,
					&authcDN, &authcDN );
			if ( rs->sr_err != LDAP_SUCCESS ) {
				if ( mt->mt_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {
					if ( sendok & LDAP_BACK_SENDERR ) {
						send_ldap_result( op, rs );
					}
					LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
					goto done;
				}

				rs->sr_err = LDAP_SUCCESS;
				*binddn = slap_empty_bv;
				*bindcred = slap_empty_bv;
				break;
			}
		}

		*binddn = mt->mt_idassert_authcDN;
		*bindcred = mt->mt_idassert_passwd;
		dobind = 1;
		break;
	}

	if ( dobind && mt->mt_idassert_authmethod == LDAP_AUTH_SASL ) {
#ifdef HAVE_CYRUS_SASL
		void		*defaults = NULL;
		struct berval	authzID = BER_BVNULL;
		int		freeauthz = 0;

		/* if SASL supports native authz, prepare for it */
		if ( ( !op->o_do_not_cache || !op->o_is_auth_check ) &&
				( mt->mt_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) )
		{
			switch ( mt->mt_idassert_mode ) {
			case LDAP_BACK_IDASSERT_OTHERID:
			case LDAP_BACK_IDASSERT_OTHERDN:
				authzID = mt->mt_idassert_authzID;
				break;

			case LDAP_BACK_IDASSERT_ANONYMOUS:
				BER_BVSTR( &authzID, "dn:" );
				break;

			case LDAP_BACK_IDASSERT_SELF:
				if ( BER_BVISNULL( &ndn ) ) {
					/* connection is not authc'd, so don't idassert */
					BER_BVSTR( &authzID, "dn:" );
					break;
				}
				authzID.bv_len = STRLENOF( "dn:" ) + ndn.bv_len;
				authzID.bv_val = slap_sl_malloc( authzID.bv_len + 1, op->o_tmpmemctx );
				memcpy( authzID.bv_val, "dn:", STRLENOF( "dn:" ) );
				memcpy( authzID.bv_val + STRLENOF( "dn:" ),
						ndn.bv_val, ndn.bv_len + 1 );
				freeauthz = 1;
				break;

			default:
				break;
			}
		}

		if ( mt->mt_idassert_secprops != NULL ) {
			rs->sr_err = ldap_set_option( msc->msc_ld,
				LDAP_OPT_X_SASL_SECPROPS,
				(void *)mt->mt_idassert_secprops );

			if ( rs->sr_err != LDAP_OPT_SUCCESS ) {
				rs->sr_err = LDAP_OTHER;
				if ( sendok & LDAP_BACK_SENDERR ) {
					send_ldap_result( op, rs );
				}
				LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
				goto done;
			}
		}

		defaults = lutil_sasl_defaults( msc->msc_ld,
				mt->mt_idassert_sasl_mech.bv_val,
				mt->mt_idassert_sasl_realm.bv_val,
				mt->mt_idassert_authcID.bv_val,
				mt->mt_idassert_passwd.bv_val,
				authzID.bv_val );
		if ( defaults == NULL ) {
			rs->sr_err = LDAP_OTHER;
			LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
			if ( sendok & LDAP_BACK_SENDERR ) {
				send_ldap_result( op, rs );
			}
			goto done;
		}

		rs->sr_err = ldap_sasl_interactive_bind_s( msc->msc_ld, binddn->bv_val,
				mt->mt_idassert_sasl_mech.bv_val, NULL, NULL,
				LDAP_SASL_QUIET, lutil_sasl_interact,
				defaults );

		rs->sr_err = slap_map_api2result( rs );
		if ( rs->sr_err != LDAP_SUCCESS ) {
			LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
			if ( sendok & LDAP_BACK_SENDERR ) {
				send_ldap_result( op, rs );
			}

		} else {
			LDAP_BACK_CONN_ISBOUND_SET( msc );
		}

		lutil_sasl_freedefs( defaults );
		if ( freeauthz ) {
			slap_sl_free( authzID.bv_val, op->o_tmpmemctx );
		}

		goto done;
#endif /* HAVE_CYRUS_SASL */
	}

	*method = mt->mt_idassert_authmethod;
	switch ( mt->mt_idassert_authmethod ) {
	case LDAP_AUTH_NONE:
		BER_BVSTR( binddn, "" );
		BER_BVSTR( bindcred, "" );
		/* fallthru */

	case LDAP_AUTH_SIMPLE:
		break;

	default:
		/* unsupported! */
		LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
		rs->sr_err = LDAP_AUTH_METHOD_NOT_SUPPORTED;
		if ( sendok & LDAP_BACK_SENDERR ) {
			send_ldap_result( op, rs );
		}
		break;
	}

done:;

	if ( !BER_BVISEMPTY( binddn ) ) {
		LDAP_BACK_CONN_ISIDASSERT_SET( msc );
	}

	return rs->sr_err;
}