Use the RoomVersion struct in event_auth
This commit is contained in:
parent
c20893e536
commit
138ecd4f35
14
src/error.rs
14
src/error.rs
@ -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>),
|
||||
}
|
||||
|
@ -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()
|
||||
|
10
src/lib.rs
10
src/lib.rs
@ -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>>,
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user