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

📄 bind.c

📁 ldap服务器源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	*binddn = slap_empty_bv;	*bindcred = slap_empty_bv;	if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) {		ndn = op->o_conn->c_ndn;	} else {		ndn = op->o_ndn;	}	switch ( li->li_idassert_mode ) {	case LDAP_BACK_IDASSERT_LEGACY:		if ( !BER_BVISNULL( &ndn ) && !BER_BVISEMPTY( &ndn ) ) {			if ( !BER_BVISNULL( &li->li_idassert_authcDN ) && !BER_BVISEMPTY( &li->li_idassert_authcDN ) )			{				*binddn = li->li_idassert_authcDN;				*bindcred = li->li_idassert_passwd;				dobind = 1;			}		}		break;	default:		/* NOTE: rootdn can always idassert */		if ( BER_BVISNULL( &ndn )			&& li->li_idassert_authz == NULL			&& !( li->li_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) )		{			if ( li->li_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {				rs->sr_err = LDAP_INAPPROPRIATE_AUTH;				if ( sendok & LDAP_BACK_SENDERR ) {					send_ldap_result( op, rs );					dobind = -1;				}			} else {				rs->sr_err = LDAP_SUCCESS;				*binddn = slap_empty_bv;				*bindcred = slap_empty_bv;				break;			}			goto done;		} else if ( li->li_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, li->li_idassert_authz,					&authcDN, &authcDN );			if ( rs->sr_err != LDAP_SUCCESS ) {				if ( li->li_idassert_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {					if ( sendok & LDAP_BACK_SENDERR ) {						send_ldap_result( op, rs );						dobind = -1;					}				} else {					rs->sr_err = LDAP_SUCCESS;					*binddn = slap_empty_bv;					*bindcred = slap_empty_bv;					break;				}				goto done;			}		}		*binddn = li->li_idassert_authcDN;		*bindcred = li->li_idassert_passwd;		dobind = 1;		break;	}done:;	return dobind;}static intldap_back_proxy_authz_bind(	ldapconn_t		*lc,	Operation		*op,	SlapReply		*rs,	ldap_back_send_t	sendok,	struct berval		*binddn,	struct berval		*bindcred ){	ldapinfo_t	*li = (ldapinfo_t *)op->o_bd->be_private;	struct berval	ndn;	int		msgid;	int		rc;	if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) {		ndn = op->o_conn->c_ndn;	} else {		ndn = op->o_ndn;	}	if ( li->li_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 ) &&				( li->li_idassert_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) )		{			switch ( li->li_idassert_mode ) {			case LDAP_BACK_IDASSERT_OTHERID:			case LDAP_BACK_IDASSERT_OTHERDN:				authzID = li->li_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 );				AC_MEMCPY( authzID.bv_val, "dn:", STRLENOF( "dn:" ) );				AC_MEMCPY( authzID.bv_val + STRLENOF( "dn:" ),						ndn.bv_val, ndn.bv_len + 1 );				freeauthz = 1;				break;			default:				break;			}		}		if ( li->li_idassert_secprops != NULL ) {			rs->sr_err = ldap_set_option( lc->lc_ld,				LDAP_OPT_X_SASL_SECPROPS,				(void *)li->li_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( lc );				goto done;			}		}		defaults = lutil_sasl_defaults( lc->lc_ld,				li->li_idassert_sasl_mech.bv_val,				li->li_idassert_sasl_realm.bv_val,				li->li_idassert_authcID.bv_val,				li->li_idassert_passwd.bv_val,				authzID.bv_val );		rs->sr_err = ldap_sasl_interactive_bind_s( lc->lc_ld, binddn->bv_val,				li->li_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( lc );			if ( sendok & LDAP_BACK_SENDERR ) {				send_ldap_result( op, rs );			}		} else {			LDAP_BACK_CONN_ISBOUND_SET( lc );		}		lutil_sasl_freedefs( defaults );		if ( freeauthz ) {			slap_sl_free( authzID.bv_val, op->o_tmpmemctx );		}		goto done;#endif /* HAVE_CYRUS_SASL */	}	switch ( li->li_idassert_authmethod ) {	case LDAP_AUTH_NONE:		/* FIXME: do we really need this? */		BER_BVSTR( binddn, "" );		BER_BVSTR( bindcred, "" );		/* fallthru */	case LDAP_AUTH_SIMPLE:		rs->sr_err = ldap_sasl_bind( lc->lc_ld,				binddn->bv_val, LDAP_SASL_SIMPLE,				bindcred, NULL, NULL, &msgid );		rc = ldap_back_op_result( lc, op, rs, msgid,			-1, ( sendok | LDAP_BACK_BINDING ) );		break;	default:		/* unsupported! */		LDAP_BACK_CONN_ISBOUND_CLEAR( lc );		rs->sr_err = LDAP_AUTH_METHOD_NOT_SUPPORTED;		if ( sendok & LDAP_BACK_SENDERR ) {			send_ldap_result( op, rs );		}		goto done;	}	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( lc );		ber_bvreplace( &lc->lc_bound_ndn, binddn );		if ( !BER_BVISNULL( &lc->lc_cred ) ) {			memset( lc->lc_cred.bv_val, 0,					lc->lc_cred.bv_len );		}		if ( LDAP_BACK_SAVECRED( li ) ) {			ber_bvreplace( &lc->lc_cred, bindcred );			ldap_set_rebind_proc( lc->lc_ld, li->li_rebind_f, lc );		} else {			lc->lc_cred.bv_len = 0;		}	}done:;	return LDAP_BACK_CONN_ISBOUND( lc );}/* * ldap_back_proxy_authz_ctrl() prepends a proxyAuthz control * to existing server-side controls if required; if not, * the existing server-side controls are placed in *pctrls. * The caller, after using the controls in client API  * operations, if ( *pctrls != op->o_ctrls ), should * free( (*pctrls)[ 0 ] ) and free( *pctrls ). * The function returns success if the control could * be added if required, or if it did nothing; in the future, * it might return some error if it failed. *  * if no bind took place yet, but the connection is bound * and the "proxyauthzdn" is set, then bind as "proxyauthzdn"  * and explicitly add proxyAuthz the control to every operation * with the dn bound to the connection as control value. * * If no server-side controls are defined for the operation, * simply add the proxyAuthz control; otherwise, if the * proxyAuthz control is not already set, add it as * the first one * * FIXME: is controls order significant for security? * ANSWER: controls ordering and interoperability * must be indicated by the specs of each control; if none * is specified, the order is irrelevant. */intldap_back_proxy_authz_ctrl(		struct berval	*bound_ndn,		int		version,		slap_idassert_t	*si,		Operation	*op,		SlapReply	*rs,		LDAPControl	***pctrls ){	LDAPControl		**ctrls = NULL;	int			i = 0;	slap_idassert_mode_t	mode;	struct berval		assertedID,				ndn;	int			isroot = 0;	*pctrls = NULL;	rs->sr_err = LDAP_SUCCESS;	/* don't proxyAuthz if protocol is not LDAPv3 */	switch ( version ) {	case LDAP_VERSION3:		break;	case 0:		if ( op->o_protocol == 0 || op->o_protocol == LDAP_VERSION3 ) {			break;		}		/* fall thru */	default:		goto done;	}	/* FIXME: SASL/EXTERNAL over ldapi:// doesn't honor the authcID,	 * but if it is not set this test fails.  We need a different	 * means to detect if idassert is enabled */	if ( ( BER_BVISNULL( &si->si_bc.sb_authcId ) || BER_BVISEMPTY( &si->si_bc.sb_authcId ) )			&& ( BER_BVISNULL( &si->si_bc.sb_binddn ) || BER_BVISEMPTY( &si->si_bc.sb_binddn ) ) )	{		goto done;	}	if ( !op->o_conn || op->o_do_not_cache || ( isroot = be_isroot( op ) ) ) {		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;	}	if ( si->si_mode == LDAP_BACK_IDASSERT_LEGACY ) {		if ( op->o_proxy_authz ) {			/*			 * FIXME: we do not want to perform proxyAuthz			 * on behalf of the client, because this would			 * be performed with "proxyauthzdn" privileges.			 *			 * This might actually be too strict, since			 * the "proxyauthzdn" authzTo, and each entry's			 * authzFrom attributes may be crafted			 * to avoid unwanted proxyAuthz to take place.			 */#if 0			rs->sr_err = LDAP_UNWILLING_TO_PERFORM;			rs->sr_text = "proxyAuthz not allowed within namingContext";#endif			goto done;		}		if ( !BER_BVISNULL( bound_ndn ) ) {			goto done;		}		if ( BER_BVISNULL( &ndn ) ) {			goto done;		}		if ( BER_BVISNULL( &si->si_bc.sb_binddn ) ) {			goto done;		}	} else if ( si->si_bc.sb_method == LDAP_AUTH_SASL ) {		if ( ( si->si_flags & LDAP_BACK_AUTH_NATIVE_AUTHZ ) )		{			/* already asserted in SASL via native authz */			goto done;		}	} else if ( si->si_authz && !isroot ) {		int		rc;		struct berval authcDN;		if ( BER_BVISNULL( &ndn ) ) {			authcDN = slap_empty_bv;		} else {			authcDN = ndn;		}		rc = slap_sasl_matches( op, si->si_authz,				&authcDN, & authcDN );		if ( rc != LDAP_SUCCESS ) {			if ( si->si_flags & LDAP_BACK_AUTH_PRESCRIPTIVE ) {				/* ndn is not authorized				 * to use idassert */				rs->sr_err = rc;			}			goto done;		}	}	if ( op->o_proxy_authz ) {		/*		 * FIXME: we can:		 * 1) ignore the already set proxyAuthz control		 * 2) leave it in place, and don't set ours		 * 3) add both		 * 4) reject the operation		 *		 * option (4) is very drastic		 * option (3) will make the remote server reject		 * the operation, thus being equivalent to (4)		 * option (2) will likely break the idassert		 * assumptions, so we cannot accept it;		 * option (1) means that we are contradicting		 * the client's reques.		 *		 * I think (4) is the only correct choice.		 */		rs->sr_err = LDAP_UNWILLING_TO_PERFORM;		rs->sr_text = "proxyAuthz not allowed within namingContext";	}	if ( op->o_is_auth_check ) {		mode = LDAP_BACK_IDASSERT_NOASSERT;	} else {		mode = si->si_mode;	}	switch ( mode ) {	case LDAP_BACK_IDASSERT_LEGACY:		/* original behavior:		 * assert the client's identity */	case LDAP_BACK_IDASSERT_SELF:		assertedID = ndn;		break;	case LDAP_BACK_IDASSERT_ANONYMOUS:		/* assert "anonymous" */		assertedID = slap_empty_bv;		break;	case LDAP_BACK_IDASSERT_NOASSERT:		/* don't assert; bind as proxyauthzdn */		goto done;	case LDAP_BACK_IDASSERT_OTHERID:	case LDAP_BACK_IDASSERT_OTHERDN:		/* assert idassert DN */		assertedID = si->si_bc.sb_authzId;		break;	default:		assert( 0 );	}	/* if we got here, "" is allowed to proxyAuthz */	if ( BER_BVISNULL( &assertedID ) ) {		assertedID = slap_empty_bv;	}	/* don't idassert the bound DN (ITS#4497) */	if ( dn_match( &assertedID, bound_ndn ) ) {		goto done;	}	if ( op->o_ctrls ) {		for ( i = 0; op->o_ctrls[ i ]; i++ )			/* just count ctrls */ ;	}	ctrls = op->o_tmpalloc( sizeof( LDAPControl * ) * (i + 2) + sizeof( LDAPControl ),			op->o_tmpmemctx );	ctrls[ 0 ] = (LDAPControl *)&ctrls[ i + 2 ];		ctrls[ 0 ]->ldctl_oid = LDAP_CONTROL_PROXY_AUTHZ;	ctrls[ 0 ]->ldctl_iscritical = 1;	switch ( si->si_mode ) {	/* already in u:ID or dn:DN form */	case LDAP_BACK_IDASSERT_OTHERID:	case LDAP_BACK_IDASSERT_OTHERDN:		ber_dupbv_x( &ctrls[ 0 ]->ldctl_value, &assertedID, op->o_tmpmemctx );		break;	/* needs the dn: prefix */	default:		ctrls[ 0 ]->ldctl_value.bv_len = assertedID.bv_len + STRLENOF( "dn:" );		ctrls[ 0 ]->ldctl_value.bv_val = op->o_tmpalloc( ctrls[ 0 ]->ldctl_value.bv_len + 1,				op->o_tmpmemctx );		AC_MEMCPY( ctrls[ 0 ]->ldctl_value.bv_val, "dn:", STRLENOF( "dn:" ) );		AC_MEMCPY( &ctrls[ 0 ]->ldctl_value.bv_val[ STRLENOF( "dn:" ) ],				assertedID.bv_val, assertedID.bv_len + 1 );		break;	}	/* Older versions of <draft-weltman-ldapv3-proxy> required	 * to encode the value of the authzID (and called it proxyDN);	 * this hack provides compatibility with those DSAs that	 * implement it this way */	if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_ENCODING_WORKAROUND ) {		struct berval		authzID = ctrls[ 0 ]->ldctl_value;		BerElementBuffer	berbuf;		BerElement		*ber = (BerElement *)&berbuf;		ber_tag_t		tag;		ber_init2( ber, 0, LBER_USE_DER );		ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );		tag = ber_printf( ber, "O", &authzID );		if ( tag == LBER_ERROR ) {			rs->sr_err = LDAP_OTHER;			goto free_ber;		}		if ( ber_flatten2( ber, &ctrls[ 0 ]->ldctl_value, 1 ) == -1 ) {			rs->sr_err = LDAP_OTHER;			goto free_ber;		}free_ber:;		op->o_tmpfree( authzID.bv_val, op->o_tmpmemctx );		ber_free_buf( ber );		if ( rs->sr_err != LDAP_SUCCESS ) {			op->o_tmpfree( ctrls, op->o_tmpmemctx );			ctrls = NULL;			goto done;		}	} else if ( si->si_flags & LDAP_BACK_AUTH_OBSOLETE_PROXY_AUTHZ ) {		struct berval		authzID = ctrls[ 0 ]->ldctl_value,					tmp;		BerElementBuffer	berbuf;		BerElement		*ber = (BerElement *)&berbuf;		ber_tag_t		tag;		if ( strncasecmp( authzID.bv_val, "dn:", STRLENOF( "dn:" ) ) != 0 ) {			op->o_tmpfree( ctrls[ 0 ]->ldctl_value.bv_val, op->o_tmpmemctx );			op->o_tmpfree( ctrls, op->o_tmpmemctx );			ctrls = NULL;			rs->sr_err = LDAP_PROTOCOL_ERROR;			goto done;		}		tmp = authzID;		tmp.bv_val += STRLENOF( "dn:" );		tmp.bv_len -= STRLENOF( "dn:" );		ber_init2( ber, 0, LBER_USE_DER );		ber_set_option( ber, LBER_OPT_BER_MEMCTX, &op->o_tmpmemctx );		/* apparently, Mozilla API encodes this		 * as "SEQUENCE { LDAPDN }" */		tag = ber_printf( ber, "{O}", &tmp );		if ( tag == LBER_ERROR ) {			rs->sr_err = LDAP_OTHER;			goto free_ber2;		}		if ( ber_flatten2( ber, &ctrls[ 0 ]->ldctl_value, 1 ) == -1 ) {			rs->sr_err = LDAP_OTHER;			goto free_ber2;		}free_ber2:;		op->o_tmpfree( authzID.bv_val, op->o_tmpmemctx );		ber_free_buf( ber );		if ( rs->sr_err != LDAP_SUCCESS ) {			op->o_tmpfree( ctrls, op->o_tmpmemctx );			ctrls = NULL;			goto done;		}		ctrls[ 0 ]->ldctl_oid = LDAP_CONTROL_OBSOLETE_PROXY_AUTHZ;	}	if ( op->o_ctrls ) {		for ( i = 0; op->o_ctrls[ i ]; i++ ) {			ctrls[ i + 1 ] = op->o_ctrls[ i ];		}	}	ctrls[ i + 1 ] = NULL;done:;	if ( ctrls == NULL ) {		ctrls = op->o_ctrls;	}	*pctrls = ctrls;		return rs->sr_err;}intldap_back_proxy_authz_ctrl_free( Operation *op, LDAPControl ***pctrls ){	LDAPControl	**ctrls = *pctrls;	/* we assume that the first control is the proxyAuthz	 * added by back-ldap, so it's the only one we explicitly 	 * free */	if ( ctrls && ctrls != op->o_ctrls ) {		assert( ctrls[ 0 ] != NULL );		if ( !BER_BVISNULL( &ctrls[ 0 ]->ldctl_value ) ) {			op->o_tmpfree( ctrls[ 0 ]->ldctl_value.bv_val, op->o_tmpmemctx );		}		op->o_tmpfree( ctrls, op->o_tmpmemctx );	} 	*pctrls = NULL;	return 0;}

⌨️ 快捷键说明

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