bind.c

来自「ldap服务器源码」· C语言 代码 · 共 1,440 行 · 第 1/3 页

C
1,440
字号
				rc = ldap_parse_result( msc->msc_ld, res, &rs->sr_err,						&matched, &text, &refs, &ctrls, 1 );				res = NULL;				rs->sr_text = text;				if ( rc != LDAP_SUCCESS ) {					rs->sr_err = rc;				}				if ( refs != NULL ) {					int	i;						for ( i = 0; refs[ i ] != NULL; i++ )						/* count */ ;					rs->sr_ref = op->o_tmpalloc( sizeof( struct berval ) * ( i + 1 ),						op->o_tmpmemctx );					for ( i = 0; refs[ i ] != NULL; i++ ) {						ber_str2bv( refs[ i ], 0, 0, &rs->sr_ref[ i ] );					}					BER_BVZERO( &rs->sr_ref[ i ] );				}				if ( ctrls != NULL ) {					rs->sr_ctrls = ctrls;				}			}			assert( res == NULL );		}		/* if the error in the reply structure is not		 * LDAP_SUCCESS, try to map it from client 		 * to server error */		if ( !ERR_OK( rs->sr_err ) ) {			rs->sr_err = slap_map_api2result( rs );			/* internal ops ( op->o_conn == NULL ) 			 * must not reply to client */			if ( op->o_conn && !op->o_do_not_cache && matched ) {				/* record the (massaged) matched				 * DN into the reply structure */				rs->sr_matched = matched;			}		}		if ( META_BACK_TGT_QUARANTINE( mt ) ) {			meta_back_quarantine( op, rs, candidate );		}	} else {		int	i,			err = rs->sr_err;		for ( i = 0; i < mi->mi_ntargets; i++ ) {			metasingleconn_t	*msc = &mc->mc_conns[ i ];			char			*xtext = NULL;			char			*xmatched = NULL;			rs->sr_err = LDAP_SUCCESS;			ldap_get_option( msc->msc_ld, LDAP_OPT_ERROR_NUMBER, &rs->sr_err );			if ( rs->sr_err != LDAP_SUCCESS ) {				/*				 * better check the type of error. In some cases				 * (search ?) it might be better to return a				 * success if at least one of the targets gave				 * positive result ...				 */				ldap_get_option( msc->msc_ld,						LDAP_OPT_ERROR_STRING, &xtext );				if ( xtext != NULL && xtext [ 0 ] == '\0' ) {					ldap_memfree( xtext );					xtext = NULL;				}				ldap_get_option( msc->msc_ld,						LDAP_OPT_MATCHED_DN, &xmatched );				if ( xmatched != NULL && xmatched[ 0 ] == '\0' ) {					ldap_memfree( xmatched );					xmatched = NULL;				}				rs->sr_err = slap_map_api2result( rs );					if ( StatslogTest( LDAP_DEBUG_ANY ) ) {					char	buf[ SLAP_TEXT_BUFLEN ];					snprintf( buf, sizeof( buf ),						"meta_back_op_result[%d] "						"err=%d text=\"%s\" matched=\"%s\"", 						i, rs->sr_err,						( xtext ? xtext : "" ),						( xmatched ? xmatched : "" ) );					Debug( LDAP_DEBUG_ANY, "%s %s.\n",						op->o_log_prefix, buf, 0 );				}				/*				 * FIXME: need to rewrite "match" (need rwinfo)				 */				switch ( rs->sr_err ) {				default:					err = rs->sr_err;					if ( xtext != NULL ) {						if ( text ) {							ldap_memfree( text );						}						text = xtext;						xtext = NULL;					}					if ( xmatched != NULL ) {						if ( matched ) {							ldap_memfree( matched );						}						matched = xmatched;						xmatched = NULL;					}					break;				}				if ( xtext ) {					ldap_memfree( xtext );				}					if ( xmatched ) {					ldap_memfree( xmatched );				}			}			if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ i ] ) ) {				meta_back_quarantine( op, rs, i );			}		}		if ( err != LDAP_SUCCESS ) {			rs->sr_err = err;		}	}	if ( matched != NULL ) {		struct berval	dn, pdn;		ber_str2bv( matched, 0, 0, &dn );		if ( dnPretty( NULL, &dn, &pdn, op->o_tmpmemctx ) == LDAP_SUCCESS ) {			ldap_memfree( matched );			matched_ctx = op->o_tmpmemctx;			matched = pdn.bv_val;		}		rs->sr_matched = matched;	}	if ( op->o_conn &&		( ( sendok & LDAP_BACK_SENDOK ) 			|| ( ( sendok & LDAP_BACK_SENDERR ) && rs->sr_err != LDAP_SUCCESS ) ) )	{		send_ldap_result( op, rs );	}	if ( matched ) {		op->o_tmpfree( (char *)rs->sr_matched, matched_ctx );	}	if ( text ) {		ldap_memfree( text );	}	if ( rs->sr_ref ) {		assert( refs != NULL );		ber_memvfree( (void **)refs );		op->o_tmpfree( rs->sr_ref, op->o_tmpmemctx );	}	if ( ctrls ) {		assert( rs->sr_ctrls != NULL );		ldap_controls_free( ctrls );	}	rs->sr_text = save_text;	rs->sr_matched = save_matched;	rs->sr_ref = save_ref;	rs->sr_ctrls = save_ctrls;	return( ERR_OK( rs->sr_err ) ? LDAP_SUCCESS : rs->sr_err );}/* * meta_back_proxy_authz_cred() * * prepares credentials & method for meta_back_proxy_authz_bind(); * or, if method is SASL, performs the SASL bind directly. */intmeta_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;	}	/*	 * 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 );				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 ( 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 );		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:;	return rs->sr_err;}static intmeta_back_proxy_authz_bind( metaconn_t *mc, int candidate, Operation *op, SlapReply *rs, ldap_back_send_t sendok ){	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:			rs->sr_err = ldap_sasl_bind( msc->msc_ld,					binddn.bv_val, LDAP_SASL_SIMPLE,					&cred, NULL, NULL, &msgid );			rc = meta_back_bind_op_result( op, rs, mc, candidate, msgid, sendok );			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 ( LDAP_BACK_SAVECRED( mi ) ) {					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:			assert( 0 );			break;		}	}	return LDAP_BACK_CONN_ISBOUND( msc );}

⌨️ 快捷键说明

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