Use the RoomVersion struct in event_auth

This commit is contained in:
Devin Ragotzy 2021-04-29 12:06:50 -04:00 committed by Devin Ragotzy
parent c20893e536
commit 138ecd4f35
4 changed files with 48 additions and 31 deletions

View File

@ -1,5 +1,3 @@
use std::num::ParseIntError;
use serde_json::Error as JsonError;
use thiserror::Error;
@ -13,19 +11,19 @@ pub enum Error {
#[error(transparent)]
SerdeJson(#[from] JsonError),
/// An error that occurs when converting from JSON numbers to rust.
#[error(transparent)]
IntParseError(#[from] ParseIntError),
/// The given option or version is unsupported.
#[error("Unsupported room version: {0}")]
Unsupported(String),
/// The given event was not found.
#[error("Not found error: {0}")]
NotFound(String),
/// Invalid fields in the given PDU.
#[error("Invalid PDU: {0}")]
InvalidPdu(String),
#[error("Conversion failed: {0}")]
ConversionError(String),
/// A custom error.
#[error("{0}")]
Custom(Box<dyn std::error::Error>),
}

View File

@ -15,7 +15,7 @@ use ruma::{
RoomVersionId, UserId,
};
use crate::{Error, Event, Result, StateMap};
use crate::{room_version::RoomVersion, Error, Event, Result, StateMap};
/// For the given event `kind` what are the relevant auth events
/// that are needed to authenticate this `content`.
@ -82,7 +82,7 @@ pub fn auth_types_for_event(
/// ## Returns
/// This returns an `Error` only when serialization fails or some other fatal outcome.
pub fn auth_check<E: Event>(
room_version: &RoomVersionId,
room_version: &RoomVersion,
incoming_event: &Arc<E>,
prev_event: Option<Arc<E>>,
auth_events: &StateMap<Arc<E>>,
@ -180,7 +180,7 @@ pub fn auth_check<E: Event>(
// [synapse] checks for federation here
// 4. if type is m.room.aliases
if incoming_event.kind() == EventType::RoomAliases && room_version < &RoomVersionId::Version6 {
if incoming_event.kind() == EventType::RoomAliases && room_version.special_case_aliases_auth {
log::info!("starting m.room.aliases check");
// If sender's domain doesn't matches state_key, reject
@ -280,7 +280,7 @@ pub fn auth_check<E: Event>(
// Servers should only apply redaction's to events where the sender's domains match,
// or the sender of the redaction has the appropriate permissions per the power levels.
if room_version >= &RoomVersionId::Version3
if room_version.extra_redaction_checks
&& incoming_event.kind() == EventType::RoomRedaction
&& !check_redaction(room_version, incoming_event, &auth_events)?
{
@ -320,7 +320,7 @@ pub fn valid_membership_change<E: Event>(
.map(|t| serde_json::from_value::<room::member::ThirdPartyInvite>(t.clone()));
let target_user_id =
UserId::try_from(state_key).map_err(|e| Error::ConversionError(format!("{}", e)))?;
UserId::try_from(state_key).map_err(|e| Error::InvalidPdu(format!("{}", e)))?;
let key = (EventType::RoomMember, user_sender.to_string());
let sender = auth_events.get(&key);
@ -538,7 +538,7 @@ pub fn can_send_event<E: Event>(event: &Arc<E>, auth_events: &StateMap<Arc<E>>)
/// Confirm that the event sender has the required power levels.
pub fn check_power_levels<E: Event>(
room_version: &RoomVersionId,
room_version: &RoomVersion,
power_event: &Arc<E>,
auth_events: &StateMap<Arc<E>>,
) -> Option<bool> {
@ -639,7 +639,7 @@ pub fn check_power_levels<E: Event>(
}
// Notifications, currently there is only @room
if room_version >= &RoomVersionId::Version6 {
if room_version.limit_notifications_power_levels {
let old_level = old_state.notifications.room;
let new_level = new_state.notifications.room;
if old_level != new_level {
@ -693,7 +693,7 @@ fn get_deserialize_levels(
/// Does the event redacting come from a user with enough power to redact the given event.
pub fn check_redaction<E: Event>(
_room_version: &RoomVersionId,
_room_version: &RoomVersion,
redaction_event: &Arc<E>,
auth_events: &StateMap<Arc<E>>,
) -> Result<bool> {
@ -705,7 +705,8 @@ pub fn check_redaction<E: Event>(
return Ok(true);
}
// If the domain of the event_id of the event being redacted is the same as the domain of the event_id of the m.room.redaction, allow
// If the domain of the event_id of the event being redacted is the same as the
// domain of the event_id of the m.room.redaction, allow
if redaction_event.event_id().server_name()
== redaction_event
.redacts()

View File

@ -6,6 +6,7 @@ use std::{
};
use maplit::btreeset;
use room_version::RoomVersion;
use ruma::{
events::{
room::{
@ -21,12 +22,10 @@ mod error;
pub mod event_auth;
pub mod room_version;
mod state_event;
mod state_store;
pub use error::{Error, Result};
pub use event_auth::{auth_check, auth_types_for_event};
pub use state_event::Event;
pub use state_store::StateStore;
/// A mapping of event type and state_key to some value `T`, usually an `EventId`.
pub type StateMap<T> = BTreeMap<(EventType, String), T>;
@ -111,10 +110,11 @@ impl StateResolution {
log::debug!("SRTD {:?}", sorted_control_levels);
let room_version = RoomVersion::new(room_version)?;
// sequentially auth check each control event.
let resolved_control = StateResolution::iterative_auth_check(
room_id,
room_version,
&room_version,
&sorted_control_levels,
&clean,
event_map,
@ -166,7 +166,7 @@ impl StateResolution {
let mut resolved_state = StateResolution::iterative_auth_check(
room_id,
room_version,
&room_version,
&sorted_left_events,
&resolved_control, // The control events are added to the final resolved state
event_map,
@ -436,7 +436,7 @@ impl StateResolution {
/// function.
pub fn iterative_auth_check<E: Event>(
room_id: &RoomId,
room_version: &RoomVersionId,
room_version: &RoomVersion,
events_to_check: &[EventId],
unconflicted_state: &StateMap<EventId>,
event_map: &mut EventMap<Arc<E>>,

View File

@ -1,5 +1,7 @@
use ruma::RoomVersionId;
use crate::{Error, Result};
pub enum RoomDisposition {
/// A room version that has a stable specification.
Stable,
@ -36,29 +38,39 @@ pub struct RoomVersion {
/// not sure
pub enforce_key_validity: bool,
// bool: before MSC2261/MSC2432, m.room.aliases had special auth rules and redaction rules
// bool: before MSC2261/MSC2432,
/// `m.room.aliases` had special auth rules and redaction rules
/// before room version 6.
pub special_case_aliases_auth: bool,
// Strictly enforce canonicaljson, do not allow:
// * Integers outside the range of [-2 ^ 53 + 1, 2 ^ 53 - 1]
// * Floats
// * NaN, Infinity, -Infinity
/// Strictly enforce canonicaljson, do not allow:
/// * Integers outside the range of [-2 ^ 53 + 1, 2 ^ 53 - 1]
/// * Floats
/// * NaN, Infinity, -Infinity
pub strict_canonicaljson: bool,
// bool: MSC2209: Check 'notifications' key while verifying
// m.room.power_levels auth rules.
/// Verify notifications key while checking m.room.power_levels.
pub limit_notifications_power_levels: bool,
/// Extra rules when verifying redaction events.
pub extra_redaction_checks: bool,
}
impl RoomVersion {
pub fn new(version: &RoomVersionId) -> Self {
match version {
pub fn new(version: &RoomVersionId) -> Result<Self> {
Ok(match version {
RoomVersionId::Version1 => Self::version_1(),
RoomVersionId::Version2 => Self::version_2(),
RoomVersionId::Version3 => Self::version_3(),
RoomVersionId::Version4 => Self::version_4(),
RoomVersionId::Version5 => Self::version_5(),
RoomVersionId::Version6 => Self::version_6(),
_ => panic!("unspec'ed room version"),
}
ver => {
return Err(Error::Unsupported(format!(
"found version `{}`",
ver.as_str()
)))
}
})
}
fn version_1() -> Self {
@ -71,6 +83,7 @@ impl RoomVersion {
special_case_aliases_auth: true,
strict_canonicaljson: false,
limit_notifications_power_levels: false,
extra_redaction_checks: false,
}
}
@ -84,6 +97,7 @@ impl RoomVersion {
special_case_aliases_auth: true,
strict_canonicaljson: false,
limit_notifications_power_levels: false,
extra_redaction_checks: false,
}
}
@ -97,6 +111,7 @@ impl RoomVersion {
special_case_aliases_auth: true,
strict_canonicaljson: false,
limit_notifications_power_levels: false,
extra_redaction_checks: true,
}
}
@ -110,6 +125,7 @@ impl RoomVersion {
special_case_aliases_auth: true,
strict_canonicaljson: false,
limit_notifications_power_levels: false,
extra_redaction_checks: true,
}
}
@ -123,6 +139,7 @@ impl RoomVersion {
special_case_aliases_auth: true,
strict_canonicaljson: false,
limit_notifications_power_levels: false,
extra_redaction_checks: true,
}
}
@ -136,6 +153,7 @@ impl RoomVersion {
special_case_aliases_auth: false,
strict_canonicaljson: true,
limit_notifications_power_levels: true,
extra_redaction_checks: true,
}
}
}