예제 #1
0
int
monitor_back_compare( Operation *op, SlapReply *rs )
{
	monitor_info_t	*mi = ( monitor_info_t * ) op->o_bd->be_private;
	Entry           *e, *matched = NULL;
	int		rc;

	/* get entry with reader lock */
	monitor_cache_dn2entry( op, rs, &op->o_req_ndn, &e, &matched );
	if ( e == NULL ) {
		rs->sr_err = LDAP_NO_SUCH_OBJECT;
		if ( matched ) {
			if ( !access_allowed_mask( op, matched,
					slap_schema.si_ad_entry,
					NULL, ACL_DISCLOSE, NULL, NULL ) )
			{
				/* do nothing */ ;
			} else {
				rs->sr_matched = matched->e_dn;
			}
		}
		send_ldap_result( op, rs );
		if ( matched ) {
			monitor_cache_release( mi, matched );
			rs->sr_matched = NULL;
		}

		return rs->sr_err;
	}

	monitor_entry_update( op, rs, e );
	rs->sr_err = slap_compare_entry( op, e, op->orc_ava );
	rc = rs->sr_err;
	switch ( rc ) {
	case LDAP_COMPARE_FALSE:
	case LDAP_COMPARE_TRUE:
		rc = LDAP_SUCCESS;
		break;
	}

	send_ldap_result( op, rs );
	rs->sr_err = rc;

	monitor_cache_release( mi, e );

	return rs->sr_err;
}
예제 #2
0
int
wt_compare( Operation *op, SlapReply *rs )
{
    struct wt_info *wi = (struct wt_info *) op->o_bd->be_private;
	Entry *e = NULL;
	int manageDSAit = get_manageDSAit( op );
	int rc;
	wt_ctx *wc = NULL;

	Debug( LDAP_DEBUG_ARGS, "==> " LDAP_XSTRING(wt_compare) ": %s\n",
		   op->o_req_dn.bv_val, 0, 0 );

	wc = wt_ctx_get(op, wi);
	if( !wc ){
		Debug( LDAP_DEBUG_ANY,
			   LDAP_XSTRING(wt_compare)
			   ": wt_ctx_get failed\n",
			   0, 0, 0 );
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
        send_ldap_result( op, rs );
        return rs->sr_err;
	}

	rs->sr_err = wt_dn2entry(op->o_bd, wc, &op->o_req_ndn, &e);
	switch( rs->sr_err ) {
	case 0:
	case WT_NOTFOUND:
		break;
	default:
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}

	if ( rs->sr_err == WT_NOTFOUND ) {
		if ( e != NULL ) {
			/* return referral only if "disclose" is granted on the object */
			if ( ! access_allowed( op, e, slap_schema.si_ad_entry,
								   NULL, ACL_DISCLOSE, NULL ) )
			{
				rs->sr_err = LDAP_NO_SUCH_OBJECT;
			} else {
				rs->sr_matched = ch_strdup( e->e_dn );
				if ( is_entry_referral( e )) {
					BerVarray ref = get_entry_referrals( op, e );
					rs->sr_ref = referral_rewrite( ref,
												   &e->e_name,
												   &op->o_req_dn,
												   LDAP_SCOPE_DEFAULT );
					ber_bvarray_free( ref );
				} else {
					rs->sr_ref = NULL;
				}
				rs->sr_err = LDAP_REFERRAL;
			}
			wt_entry_return( e );
			e = NULL;
		} else {
			rs->sr_ref = referral_rewrite( default_referral,
										   NULL,
										   &op->o_req_dn,
										   LDAP_SCOPE_DEFAULT );
			rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT;
		}

		rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
		send_ldap_result( op, rs );
		goto done;
	}

	if (!manageDSAit && is_entry_referral( e ) ) {
		/* return referral only if "disclose" is granted on the object */
		if ( !access_allowed( op, e, slap_schema.si_ad_entry,
							  NULL, ACL_DISCLOSE, NULL ) )
		{
			rs->sr_err = LDAP_NO_SUCH_OBJECT;
		} else {
			/* entry is a referral, don't allow compare */
			rs->sr_ref = get_entry_referrals( op, e );
			rs->sr_err = LDAP_REFERRAL;
			rs->sr_matched = e->e_name.bv_val;
		}

		Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 );

		send_ldap_result( op, rs );

		ber_bvarray_free( rs->sr_ref );
		rs->sr_ref = NULL;
		rs->sr_matched = NULL;
		goto done;
	}

	rs->sr_err = slap_compare_entry( op, e, op->orc_ava );

return_results:
	send_ldap_result( op, rs );

	switch ( rs->sr_err ) {
	case LDAP_COMPARE_FALSE:
	case LDAP_COMPARE_TRUE:
		rs->sr_err = LDAP_SUCCESS;
		break;
	}

done:
	if ( e != NULL ) {
		wt_entry_return( e );
	}
    return rs->sr_err;
}
예제 #3
0
파일: compare.c 프로젝트: benegon/openldap
int
bdb_compare( Operation *op, SlapReply *rs )
{
	struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
	Entry		*e = NULL;
	EntryInfo	*ei;
	int		manageDSAit = get_manageDSAit( op );

	DB_TXN		*rtxn;
	DB_LOCK		lock;

	rs->sr_err = bdb_reader_get(op, bdb->bi_dbenv, &rtxn);
	switch(rs->sr_err) {
	case 0:
		break;
	default:
		send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
		return rs->sr_err;
	}

dn2entry_retry:
	/* get entry */
	rs->sr_err = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1,
		&lock );

	switch( rs->sr_err ) {
	case DB_NOTFOUND:
	case 0:
		break;
	case LDAP_BUSY:
		rs->sr_text = "ldap server busy";
		goto return_results;
	case DB_LOCK_DEADLOCK:
	case DB_LOCK_NOTGRANTED:
		goto dn2entry_retry;
	default:
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}

	e = ei->bei_e;
	if ( rs->sr_err == DB_NOTFOUND ) {
		if ( e != NULL ) {
			/* return referral only if "disclose" is granted on the object */
			if ( ! access_allowed( op, e, slap_schema.si_ad_entry,
				NULL, ACL_DISCLOSE, NULL ) )
			{
				rs->sr_err = LDAP_NO_SUCH_OBJECT;

			} else {
				rs->sr_matched = ch_strdup( e->e_dn );
				rs->sr_ref = is_entry_referral( e )
					? get_entry_referrals( op, e )
					: NULL;
				rs->sr_err = LDAP_REFERRAL;
			}

			bdb_cache_return_entry_r( bdb, e, &lock );
			e = NULL;

		} else {
			rs->sr_ref = referral_rewrite( default_referral,
				NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
			rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT;
		}

		send_ldap_result( op, rs );

		ber_bvarray_free( rs->sr_ref );
		free( (char *)rs->sr_matched );
		rs->sr_ref = NULL;
		rs->sr_matched = NULL;

		goto done;
	}

	if (!manageDSAit && is_entry_referral( e ) ) {
		/* return referral only if "disclose" is granted on the object */
		if ( !access_allowed( op, e, slap_schema.si_ad_entry,
			NULL, ACL_DISCLOSE, NULL ) )
		{
			rs->sr_err = LDAP_NO_SUCH_OBJECT;
		} else {
			/* entry is a referral, don't allow compare */
			rs->sr_ref = get_entry_referrals( op, e );
			rs->sr_err = LDAP_REFERRAL;
			rs->sr_matched = e->e_name.bv_val;
		}

		Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 );

		send_ldap_result( op, rs );

		ber_bvarray_free( rs->sr_ref );
		rs->sr_ref = NULL;
		rs->sr_matched = NULL;
		goto done;
	}

	rs->sr_err = slap_compare_entry( op, e, op->orc_ava );

return_results:
	send_ldap_result( op, rs );

	switch ( rs->sr_err ) {
	case LDAP_COMPARE_FALSE:
	case LDAP_COMPARE_TRUE:
		rs->sr_err = LDAP_SUCCESS;
		break;
	}

done:
	/* free entry */
	if ( e != NULL ) {
		bdb_cache_return_entry_r( bdb, e, &lock );
	}

	return rs->sr_err;
}
예제 #4
0
파일: compare.c 프로젝트: Joywar/openldap
int
fe_op_compare( Operation *op, SlapReply *rs )
{
	Entry			*entry = NULL;
	AttributeAssertion	*ava = op->orc_ava;
	BackendDB		*bd = op->o_bd;

	if( strcasecmp( op->o_req_ndn.bv_val, LDAP_ROOT_DSE ) == 0 ) {
		if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
			send_ldap_result( op, rs );
			goto cleanup;
		}

		rs->sr_err = root_dse_info( op->o_conn, &entry, &rs->sr_text );
		if( rs->sr_err != LDAP_SUCCESS ) {
			send_ldap_result( op, rs );
			goto cleanup;
		}

	} else if ( bvmatch( &op->o_req_ndn, &frontendDB->be_schemandn ) ) {
		if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
			send_ldap_result( op, rs );
			rs->sr_err = 0;
			goto cleanup;
		}

		rs->sr_err = schema_info( &entry, &rs->sr_text );
		if( rs->sr_err != LDAP_SUCCESS ) {
			send_ldap_result( op, rs );
			rs->sr_err = 0;
			goto cleanup;
		}
	}

	if( entry ) {
		rs->sr_err = slap_compare_entry( op, entry, ava );
		entry_free( entry );

		send_ldap_result( op, rs );

		if( rs->sr_err == LDAP_COMPARE_TRUE ||
			rs->sr_err == LDAP_COMPARE_FALSE )
		{
			rs->sr_err = LDAP_SUCCESS;
		}

		goto cleanup;
	}

	/*
	 * We could be serving multiple database backends.  Select the
	 * appropriate one, or send a referral to our "referral server"
	 * if we don't hold it.
	 */
	op->o_bd = select_backend( &op->o_req_ndn, 0 );
	if ( op->o_bd == NULL ) {
		rs->sr_ref = referral_rewrite( default_referral,
			NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );

		rs->sr_err = LDAP_REFERRAL;
		if (!rs->sr_ref) rs->sr_ref = default_referral;
		op->o_bd = bd;
		send_ldap_result( op, rs );

		if (rs->sr_ref != default_referral) ber_bvarray_free( rs->sr_ref );
		rs->sr_err = 0;
		goto cleanup;
	}

	/* check restrictions */
	if( backend_check_restrictions( op, rs, NULL ) != LDAP_SUCCESS ) {
		send_ldap_result( op, rs );
		goto cleanup;
	}

	/* check for referrals */
	if( backend_check_referrals( op, rs ) != LDAP_SUCCESS ) {
		goto cleanup;
	}

	if ( SLAP_SHADOW(op->o_bd) && get_dontUseCopy(op) ) {
		/* don't use shadow copy */
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"copy not used" );

	} else if ( ava->aa_desc == slap_schema.si_ad_entryDN ) {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"entryDN compare not supported" );

	} else if ( ava->aa_desc == slap_schema.si_ad_subschemaSubentry ) {
		send_ldap_error( op, rs, LDAP_UNWILLING_TO_PERFORM,
			"subschemaSubentry compare not supported" );

#ifndef SLAP_COMPARE_IN_FRONTEND
	} else if ( ava->aa_desc == slap_schema.si_ad_hasSubordinates
		&& op->o_bd->be_has_subordinates )
	{
		int	rc, hasSubordinates = LDAP_SUCCESS;

		rc = be_entry_get_rw( op, &op->o_req_ndn, NULL, NULL, 0, &entry );
		if ( rc == 0 && entry ) {
			if ( ! access_allowed( op, entry,
				ava->aa_desc, &ava->aa_value, ACL_COMPARE, NULL ) )
			{	
				rc = rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
				
			} else {
				rc = rs->sr_err = op->o_bd->be_has_subordinates( op,
						entry, &hasSubordinates );
				be_entry_release_r( op, entry );
			}
		}

		if ( rc == 0 ) {
			int	asserted;

			asserted = bvmatch( &ava->aa_value, &slap_true_bv )
				? LDAP_COMPARE_TRUE : LDAP_COMPARE_FALSE;
			if ( hasSubordinates == asserted ) {
				rs->sr_err = LDAP_COMPARE_TRUE;

			} else {
				rs->sr_err = LDAP_COMPARE_FALSE;
			}

		} else {
			/* return error only if "disclose"
			 * is granted on the object */
			if ( backend_access( op, NULL, &op->o_req_ndn,
					slap_schema.si_ad_entry,
					NULL, ACL_DISCLOSE, NULL ) == LDAP_INSUFFICIENT_ACCESS )
			{
				rs->sr_err = LDAP_NO_SUCH_OBJECT;
			}
		}

		send_ldap_result( op, rs );

		if ( rc == 0 ) {
			rs->sr_err = LDAP_SUCCESS;
		}

	} else if ( op->o_bd->be_compare ) {
		rs->sr_err = op->o_bd->be_compare( op, rs );

#endif /* ! SLAP_COMPARE_IN_FRONTEND */
	} else {
		rs->sr_err = SLAP_CB_CONTINUE;
	}

	if ( rs->sr_err == SLAP_CB_CONTINUE ) {
		/* do our best to compare that AVA
		 * 
		 * NOTE: this code is used only
		 * if SLAP_COMPARE_IN_FRONTEND 
		 * is #define'd (it's not by default)
		 * or if op->o_bd->be_compare is NULL.
		 * 
		 * FIXME: one potential issue is that
		 * if SLAP_COMPARE_IN_FRONTEND overlays
		 * are not executed for compare. */
		BerVarray	vals = NULL;
		int		rc = LDAP_OTHER;

		rs->sr_err = backend_attribute( op, NULL, &op->o_req_ndn,
				ava->aa_desc, &vals, ACL_COMPARE );
		switch ( rs->sr_err ) {
		default:
			/* return error only if "disclose"
			 * is granted on the object */
			if ( backend_access( op, NULL, &op->o_req_ndn,
					slap_schema.si_ad_entry,
					NULL, ACL_DISCLOSE, NULL )
					== LDAP_INSUFFICIENT_ACCESS )
			{
				rs->sr_err = LDAP_NO_SUCH_OBJECT;
			}
			break;

		case LDAP_SUCCESS:
			if ( value_find_ex( op->oq_compare.rs_ava->aa_desc,
				SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
					SLAP_MR_ASSERTED_VALUE_NORMALIZED_MATCH,
				vals, &ava->aa_value, op->o_tmpmemctx ) == 0 )
			{
				rs->sr_err = LDAP_COMPARE_TRUE;
				break;

			} else {
				rs->sr_err = LDAP_COMPARE_FALSE;
			}
			rc = LDAP_SUCCESS;
			break;
		}

		send_ldap_result( op, rs );

		if ( rc == 0 ) {
			rs->sr_err = LDAP_SUCCESS;
		}
		
		if ( vals ) {
			ber_bvarray_free_x( vals, op->o_tmpmemctx );
		}
	}

cleanup:;
	op->o_bd = bd;
	return rs->sr_err;
}
예제 #5
0
int
mdb_compare( Operation *op, SlapReply *rs )
{
	struct mdb_info *mdb = (struct mdb_info *) op->o_bd->be_private;
	Entry		*e = NULL;
	int		manageDSAit = get_manageDSAit( op );

	MDB_txn		*rtxn;
	mdb_op_info	opinfo = {{{0}}}, *moi = &opinfo;

	rs->sr_err = mdb_opinfo_get(op, mdb, 1, &moi);
	switch(rs->sr_err) {
	case 0:
		break;
	default:
		send_ldap_error( op, rs, LDAP_OTHER, "internal error" );
		return rs->sr_err;
	}

	rtxn = moi->moi_txn;

	/* get entry */
	rs->sr_err = mdb_dn2entry( op, rtxn, NULL, &op->o_req_ndn, &e, NULL, 1 );
	switch( rs->sr_err ) {
	case MDB_NOTFOUND:
	case 0:
		break;
	case LDAP_BUSY:
		rs->sr_text = "ldap server busy";
		goto return_results;
	default:
		rs->sr_err = LDAP_OTHER;
		rs->sr_text = "internal error";
		goto return_results;
	}

	if ( rs->sr_err == MDB_NOTFOUND ) {
		if ( e != NULL ) {
			/* return referral only if "disclose" is granted on the object */
			if ( ! access_allowed( op, e, slap_schema.si_ad_entry,
				NULL, ACL_DISCLOSE, NULL ) )
			{
				rs->sr_err = LDAP_NO_SUCH_OBJECT;

			} else {
				rs->sr_matched = ch_strdup( e->e_dn );
				if ( is_entry_referral( e )) {
					BerVarray ref = get_entry_referrals( op, e );
					rs->sr_ref = referral_rewrite( ref, &e->e_name,
						&op->o_req_dn, LDAP_SCOPE_DEFAULT );
					ber_bvarray_free( ref );
				} else {
					rs->sr_ref = NULL;
				}
				rs->sr_err = LDAP_REFERRAL;
			}
			mdb_entry_return( op, e );
			e = NULL;

		} else {
			rs->sr_ref = referral_rewrite( default_referral,
				NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
			rs->sr_err = rs->sr_ref ? LDAP_REFERRAL : LDAP_NO_SUCH_OBJECT;
		}

		rs->sr_flags = REP_MATCHED_MUSTBEFREED | REP_REF_MUSTBEFREED;
		send_ldap_result( op, rs );
		goto done;
	}

	if (!manageDSAit && is_entry_referral( e ) ) {
		/* return referral only if "disclose" is granted on the object */
		if ( !access_allowed( op, e, slap_schema.si_ad_entry,
			NULL, ACL_DISCLOSE, NULL ) )
		{
			rs->sr_err = LDAP_NO_SUCH_OBJECT;
		} else {
			/* entry is a referral, don't allow compare */
			rs->sr_ref = get_entry_referrals( op, e );
			rs->sr_err = LDAP_REFERRAL;
			rs->sr_matched = e->e_name.bv_val;
		}

		Debug( LDAP_DEBUG_TRACE, "entry is referral\n", 0, 0, 0 );

		send_ldap_result( op, rs );

		ber_bvarray_free( rs->sr_ref );
		rs->sr_ref = NULL;
		rs->sr_matched = NULL;
		goto done;
	}

	rs->sr_err = slap_compare_entry( op, e, op->orc_ava );

return_results:
	send_ldap_result( op, rs );

	switch ( rs->sr_err ) {
	case LDAP_COMPARE_FALSE:
	case LDAP_COMPARE_TRUE:
		rs->sr_err = LDAP_SUCCESS;
		break;
	}

done:
	if ( moi == &opinfo ) {
		mdb_txn_reset( moi->moi_txn );
		LDAP_SLIST_REMOVE( &op->o_extra, &moi->moi_oe, OpExtra, oe_next );
	} else {
		moi->moi_ref--;
	}
	/* free entry */
	if ( e != NULL ) {
		mdb_entry_return( op, e );
	}

	return rs->sr_err;
}