⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 chain.c

📁 ldap服务器源码
💻 C
📖 第 1 页 / 共 4 页
字号:
				ldap_pvt_thread_mutex_unlock( &lc->lc_lai.lai_mutex );			} else {				temporary = 1;			}		}		lb->lb_op_f = op_f;		lb->lb_depth = depth + 1;		rc = op_f( op, &rs2 );		/* note the first error */		if ( first_rc == -1 ) {			first_rc = rc;		}cleanup:;		ldap_memfree( li.li_uri );		li.li_uri = NULL;		if ( temporary ) {			lip->li_uri = NULL;			lip->li_bvuri = NULL;			(void)ldap_chain_db_close_one( op->o_bd );			(void)ldap_chain_db_destroy_one( op->o_bd );		}further_cleanup:;		if ( !BER_BVISNULL( &pdn ) ) {			op->o_tmpfree( pdn.bv_val, op->o_tmpmemctx );		}		op->o_req_dn = save_req_dn;		if ( !BER_BVISNULL( &ndn ) ) {			op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx );		}		op->o_req_ndn = save_req_ndn;				if ( rc == LDAP_SUCCESS && rs2.sr_err == LDAP_SUCCESS ) {			*rs = rs2;			break;		}		rc = rs2.sr_err;	}#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR	(void)chaining_control_remove( op, &ctrls );#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */	if ( rc != LDAP_SUCCESS && first_rc > 0 ) {		rc = first_rc;	}	return rc;}static intldap_chain_search(	Operation	*op,	SlapReply	*rs,	BerVarray	ref,	int		depth ){	slap_overinst	*on = (slap_overinst *) op->o_bd->bd_info;	ldap_chain_cb_t	*lb = (ldap_chain_cb_t *)op->o_callback->sc_private;	ldap_chain_t	*lc = (ldap_chain_t *)on->on_bi.bi_private;	ldapinfo_t	li = { 0 }, *lip = NULL;	struct berval	bvuri[ 2 ] = { { 0 } };	struct berval	odn = op->o_req_dn,			ondn = op->o_req_ndn;	slap_response	*save_response = op->o_callback->sc_response;	int		rc = LDAP_OTHER,			first_rc = -1;#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR	LDAPControl	**ctrls = NULL;		(void)chaining_control_add( lc, op, &ctrls );#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */	rs->sr_type = REP_SEARCH;	op->o_callback->sc_response = ldap_chain_cb_search_response;	/* if we parse the URI then by no means 	 * we can cache stuff or reuse connections, 	 * because in back-ldap there's no caching	 * based on the URI value, which is supposed	 * to be set once for all (correct?) */	li.li_bvuri = bvuri;	for ( ; !BER_BVISNULL( &ref[0] ); ref++ ) {		SlapReply	rs2 = { 0 };		LDAPURLDesc	*srv;		struct berval	save_req_dn = op->o_req_dn,				save_req_ndn = op->o_req_ndn,				dn,				pdn = BER_BVNULL,				ndn = BER_BVNULL;		int		temporary = 0;		/* parse reference and use		 * proto://[host][:port]/ only */		rc = ldap_url_parse_ext( ref[0].bv_val, &srv );		if ( rc != LDAP_URL_SUCCESS ) {			/* try next */			rs->sr_err = LDAP_OTHER;			continue;		}		/* normalize DN */		ber_str2bv( srv->lud_dn, 0, 0, &dn );		rc = dnPrettyNormal( NULL, &dn, &pdn, &ndn, op->o_tmpmemctx );		if ( rc == LDAP_SUCCESS ) {			/* remove DN essentially because later on 			 * ldap_initialize() will parse the URL 			 * as a comma-separated URL list */			srv->lud_dn = "";			srv->lud_scope = LDAP_SCOPE_DEFAULT;			li.li_uri = ldap_url_desc2str( srv );			srv->lud_dn = dn.bv_val;		}		ldap_free_urldesc( srv );		if ( rc != LDAP_SUCCESS ) {			/* try next */			rc = LDAP_OTHER;			continue;		}		if ( li.li_uri == NULL ) {			/* try next */			rc = LDAP_OTHER;			goto further_cleanup;		}		op->o_req_dn = pdn;		op->o_req_ndn = ndn;		ber_str2bv( li.li_uri, 0, 0, &li.li_bvuri[ 0 ] );		/* Searches for a ldapinfo in the avl tree */		ldap_pvt_thread_mutex_lock( &lc->lc_lai.lai_mutex );		lip = (ldapinfo_t *)avl_find( lc->lc_lai.lai_tree, 			(caddr_t)&li, ldap_chain_uri_cmp );		ldap_pvt_thread_mutex_unlock( &lc->lc_lai.lai_mutex );		if ( lip != NULL ) {			op->o_bd->be_private = (void *)lip;		} else {			/* if none is found, create a temporary... */			rc = ldap_chain_db_init_one( op->o_bd );			if ( rc != 0 ) {				goto cleanup;			}			lip = (ldapinfo_t *)op->o_bd->be_private;			lip->li_uri = li.li_uri;			lip->li_bvuri = bvuri;			rc = ldap_chain_db_open_one( op->o_bd );			if ( rc != 0 ) {				lip->li_uri = NULL;				lip->li_bvuri = NULL;				(void)ldap_chain_db_destroy_one( op->o_bd );				goto cleanup;			}			if ( LDAP_CHAIN_CACHE_URI( lc ) ) {				ldap_pvt_thread_mutex_lock( &lc->lc_lai.lai_mutex );				if ( avl_insert( &lc->lc_lai.lai_tree,					(caddr_t)lip, ldap_chain_uri_cmp, ldap_chain_uri_dup ) )				{					/* someone just inserted another;					 * don't bother, use this and then					 * just free it */					temporary = 1;				}				ldap_pvt_thread_mutex_unlock( &lc->lc_lai.lai_mutex );			} else {				temporary = 1;			}		}		lb->lb_op_f = lback->bi_op_search;		lb->lb_depth = depth + 1;		/* FIXME: should we also copy filter and scope?		 * according to RFC3296, no */		rc = lback->bi_op_search( op, &rs2 );		if ( first_rc == -1 ) {			first_rc = rc;		}cleanup:;		ldap_memfree( li.li_uri );		li.li_uri = NULL;		op->o_tmpfree( op->o_req_dn.bv_val, op->o_tmpmemctx );		op->o_tmpfree( op->o_req_ndn.bv_val, op->o_tmpmemctx );		if ( temporary ) {			lip->li_uri = NULL;			lip->li_bvuri = NULL;			(void)ldap_chain_db_close_one( op->o_bd );			(void)ldap_chain_db_destroy_one( op->o_bd );		}		further_cleanup:;		if ( !BER_BVISNULL( &pdn ) ) {			op->o_tmpfree( pdn.bv_val, op->o_tmpmemctx );		}		op->o_req_dn = save_req_dn;		if ( !BER_BVISNULL( &ndn ) ) {			op->o_tmpfree( ndn.bv_val, op->o_tmpmemctx );		}		op->o_req_ndn = save_req_ndn;				if ( rc == LDAP_SUCCESS && rs2.sr_err == LDAP_SUCCESS ) {			*rs = rs2;			break;		}		rc = rs2.sr_err;	}#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR	(void)chaining_control_remove( op, &ctrls );#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */	op->o_req_dn = odn;	op->o_req_ndn = ondn;	op->o_callback->sc_response = save_response;	rs->sr_type = REP_SEARCHREF;	rs->sr_entry = NULL;	if ( rc != LDAP_SUCCESS ) {		/* couldn't chase any of the referrals */		if ( first_rc != -1 ) {			rc = first_rc;		} else {			rc = SLAP_CB_CONTINUE;		}	}	return rc;}static intldap_chain_response( Operation *op, SlapReply *rs ){	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;	ldap_chain_t	*lc = (ldap_chain_t *)on->on_bi.bi_private;	BackendDB	db, *bd = op->o_bd;	ldap_chain_cb_t	lb = { 0 };	slap_callback	*sc = op->o_callback,			sc2 = { 0 };	int		rc = 0;	char		*text = NULL;	const char	*matched;	BerVarray	ref;	struct berval	ndn = op->o_ndn;	int		sr_err = rs->sr_err;	slap_reply_t	sr_type = rs->sr_type;#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR	slap_mask_t	chain_mask = 0;	ber_len_t	chain_shift = 0;#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */	if ( rs->sr_err != LDAP_REFERRAL && rs->sr_type != REP_SEARCHREF ) {		return SLAP_CB_CONTINUE;	}#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR	if ( rs->sr_err == LDAP_REFERRAL && get_chaining( op ) > SLAP_CONTROL_IGNORED ) {		switch ( get_resolveBehavior( op ) ) {		case SLAP_CH_RESOLVE_REFERRALS_PREFERRED:		case SLAP_CH_RESOLVE_REFERRALS_REQUIRED:			return SLAP_CB_CONTINUE;		default:			chain_mask = SLAP_CH_RESOLVE_MASK;			chain_shift = SLAP_CH_RESOLVE_SHIFT;			break;		}	} else if ( rs->sr_type == REP_SEARCHREF && get_chaining( op ) > SLAP_CONTROL_IGNORED ) {		switch ( get_continuationBehavior( op ) ) {		case SLAP_CH_CONTINUATION_REFERRALS_PREFERRED:		case SLAP_CH_CONTINUATION_REFERRALS_REQUIRED:			return SLAP_CB_CONTINUE;		default:			chain_mask = SLAP_CH_CONTINUATION_MASK;			chain_shift = SLAP_CH_CONTINUATION_SHIFT;			break;		}	}#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */	/*	 * TODO: add checks on who/when chain operations; e.g.:	 *   a) what identities are authorized	 *   b) what request DN (e.g. only chain requests rooted at <DN>)	 *   c) what referral URIs	 *   d) what protocol scheme (e.g. only ldaps://)	 *   e) what ssf	 */	db = *op->o_bd;	op->o_bd = &db;	text = rs->sr_text;	rs->sr_text = NULL;	matched = rs->sr_matched;	rs->sr_matched = NULL;	ref = rs->sr_ref;	rs->sr_ref = NULL;	/* we need this to know if back-ldap returned any result */	lb.lb_lc = lc;	sc2.sc_private = &lb;	sc2.sc_response = ldap_chain_cb_response;	op->o_callback = &sc2;	/* Chaining can be performed by a privileged user on behalf	 * of normal users, using the ProxyAuthz control, by exploiting	 * the identity assertion feature of back-ldap; see idassert-*	 * directives in slapd-ldap(5).	 *	 * FIXME: the idassert-authcDN is one, will it be fine regardless	 * of the URI we obtain from the referral?	 */	switch ( op->o_tag ) {	case LDAP_REQ_BIND: {		struct berval	rndn = op->o_req_ndn;		Connection	*conn = op->o_conn;		/* FIXME: can we really get a referral for binds? */		op->o_req_ndn = slap_empty_bv;		op->o_conn = NULL;		rc = ldap_chain_op( op, rs, lback->bi_op_bind, ref, 0 );		op->o_req_ndn = rndn;		op->o_conn = conn;		}		break;	case LDAP_REQ_ADD:		rc = ldap_chain_op( op, rs, lback->bi_op_add, ref, 0 );		break;	case LDAP_REQ_DELETE:		rc = ldap_chain_op( op, rs, lback->bi_op_delete, ref, 0 );		break;	case LDAP_REQ_MODRDN:		rc = ldap_chain_op( op, rs, lback->bi_op_modrdn, ref, 0 );	    	break;	case LDAP_REQ_MODIFY:		rc = ldap_chain_op( op, rs, lback->bi_op_modify, ref, 0 );		break;	case LDAP_REQ_COMPARE:		rc = ldap_chain_op( op, rs, lback->bi_op_compare, ref, 0 );		if ( rs->sr_err == LDAP_COMPARE_TRUE || rs->sr_err == LDAP_COMPARE_FALSE ) {			rc = LDAP_SUCCESS;		}		break;	case LDAP_REQ_SEARCH:		if ( rs->sr_type == REP_SEARCHREF ) {			rc = ldap_chain_search( op, rs, ref, 0 );					} else {			/* we might get here before any database actually 			 * performed a search; in those cases, we need			 * to check limits, to make sure safe defaults			 * are in place */			if ( op->ors_limit != NULL || limits_check( op, rs ) == 0 ) {				rc = ldap_chain_op( op, rs, lback->bi_op_search, ref, 0 );			} else {				rc = SLAP_CB_CONTINUE;			}		}	    	break;	case LDAP_REQ_EXTENDED:		rc = ldap_chain_op( op, rs, lback->bi_extended, ref, 0 );		/* FIXME: ldap_back_extended() by design 		 * doesn't send result; frontend is expected		 * to send it... */		/* FIXME: what about chaining? */		if ( rc != SLAPD_ABANDON ) {			send_ldap_extended( op, rs );			rc = LDAP_SUCCESS;		}		lb.lb_status = LDAP_CH_RES;		break;	default:		rc = SLAP_CB_CONTINUE;		break;	}	switch ( rc ) {	case SLAPD_ABANDON:		goto dont_chain;	case LDAP_SUCCESS:	case LDAP_REFERRAL:		/* slapd-ldap sent response */		if ( !op->o_abandon && lb.lb_status != LDAP_CH_RES ) {			/* FIXME: should we send response? */			Debug( LDAP_DEBUG_ANY,				"%s: ldap_chain_response: "				"overlay should have sent result.\n",				op->o_log_prefix, 0, 0 );		}		break;	default:#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR		if ( lb.lb_status == LDAP_CH_ERR && rs->sr_err == LDAP_X_CANNOT_CHAIN ) {			goto cannot_chain;		}		switch ( ( get_chainingBehavior( op ) & chain_mask ) >> chain_shift ) {		case LDAP_CHAINING_REQUIRED:cannot_chain:;			op->o_callback = NULL;			send_ldap_error( op, rs, LDAP_X_CANNOT_CHAIN,				"operation cannot be completed without chaining" );			goto dont_chain;		default:#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */			if ( LDAP_CHAIN_RETURN_ERR( lc ) ) {				rs->sr_err = rc;				rs->sr_type = sr_type;			} else {				rc = SLAP_CB_CONTINUE;				rs->sr_err = sr_err;				rs->sr_type = sr_type;				rs->sr_text = text;				rs->sr_matched = matched;				rs->sr_ref = ref;			}#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR			break;		}#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR */	}	if ( lb.lb_status == LDAP_CH_NONE && rc != SLAPD_ABANDON ) {		op->o_callback = NULL;		rc = rs->sr_err = slap_map_api2result( rs );		send_ldap_result( op, rs );	}dont_chain:;	rs->sr_err = sr_err;	rs->sr_type = sr_type;	rs->sr_text = text;	rs->sr_matched = matched;	rs->sr_ref = ref;	op->o_bd = bd;	op->o_callback = sc;	op->o_ndn = ndn;	return rc;}#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIORstatic intldap_chain_parse_ctrl(	Operation	*op,	SlapReply	*rs,	LDAPControl	*ctrl );static intstr2chain( const char *s ){	if ( strcasecmp( s, "chainingPreferred" ) == 0 ) {		return LDAP_CHAINING_PREFERRED;			} else if ( strcasecmp( s, "chainingRequired" ) == 0 ) {		return LDAP_CHAINING_REQUIRED;	} else if ( strcasecmp( s, "referralsPreferred" ) == 0 ) {		return LDAP_REFERRALS_PREFERRED;			} else if ( strcasecmp( s, "referralsRequired" ) == 0 ) {		return LDAP_REFERRALS_REQUIRED;	}	return -1;}#endif /* LDAP_CONTROL_X_CHAINING_BEHAVIOR *//* * configuration... */enum {	CH_CHAINING = 1,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -