From 1c4ae8d268dc58829b5114ac2f0441c6f72e499d Mon Sep 17 00:00:00 2001 From: Matthias Ahouansou Date: Wed, 24 Apr 2024 09:28:16 +0100 Subject: [PATCH] fix(redaction): use content.redacts when checking v11 events --- src/service/rooms/event_handler/mod.rs | 60 ++++++++++++++++++----- src/service/rooms/timeline/mod.rs | 68 ++++++++++++++++++++------ 2 files changed, 102 insertions(+), 26 deletions(-) diff --git a/src/service/rooms/event_handler/mod.rs b/src/service/rooms/event_handler/mod.rs index ada289fb..b7817e50 100644 --- a/src/service/rooms/event_handler/mod.rs +++ b/src/service/rooms/event_handler/mod.rs @@ -23,7 +23,10 @@ use ruma::{ }, }, events::{ - room::{create::RoomCreateEventContent, server_acl::RoomServerAclEventContent}, + room::{ + create::RoomCreateEventContent, redaction::RoomRedactionEventContent, + server_acl::RoomServerAclEventContent, + }, StateEventType, TimelineEventType, }, int, @@ -797,17 +800,50 @@ impl Service { |k, s| auth_events.get(&(k.clone(), s.to_owned())), ) .map_err(|_e| Error::BadRequest(ErrorKind::InvalidParam, "Auth check failed."))? - || if let Some(redact_id) = &incoming_pdu.redacts { - incoming_pdu.kind == TimelineEventType::RoomRedaction - && !services().rooms.state_accessor.user_can_redact( - redact_id, - &incoming_pdu.sender, - &incoming_pdu.room_id, - true, - )? - } else { - false - }; + || incoming_pdu.kind == TimelineEventType::RoomRedaction + && match room_version_id { + RoomVersionId::V1 + | RoomVersionId::V2 + | RoomVersionId::V3 + | RoomVersionId::V4 + | RoomVersionId::V5 + | RoomVersionId::V6 + | RoomVersionId::V7 + | RoomVersionId::V8 + | RoomVersionId::V9 + | RoomVersionId::V10 => { + if let Some(redact_id) = &incoming_pdu.redacts { + !services().rooms.state_accessor.user_can_redact( + redact_id, + &incoming_pdu.sender, + &incoming_pdu.room_id, + true, + )? + } else { + false + } + } + RoomVersionId::V11 => { + let content = serde_json::from_str::( + incoming_pdu.content.get(), + ) + .map_err(|_| Error::bad_database("Invalid content in redaction pdu."))?; + + if let Some(redact_id) = &content.redacts { + !services().rooms.state_accessor.user_can_redact( + redact_id, + &incoming_pdu.sender, + &incoming_pdu.room_id, + true, + )? + } else { + false + } + } + _ => { + unreachable!("Validity of room version already checked") + } + }; // 13. Use state resolution to find new room state diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 2752abe4..acb00d01 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -900,21 +900,61 @@ impl Service { } // If redaction event is not authorized, do not append it to the timeline - if let Some(redact_id) = &pdu.redacts { - if pdu.kind == TimelineEventType::RoomRedaction - && !services().rooms.state_accessor.user_can_redact( - redact_id, - &pdu.sender, - &pdu.room_id, - false, - )? - { - return Err(Error::BadRequest( - ErrorKind::Forbidden, - "User cannot redact this event.", - )); + if pdu.kind == TimelineEventType::RoomRedaction { + match services().rooms.state.get_room_version(&pdu.room_id)? { + RoomVersionId::V1 + | RoomVersionId::V2 + | RoomVersionId::V3 + | RoomVersionId::V4 + | RoomVersionId::V5 + | RoomVersionId::V6 + | RoomVersionId::V7 + | RoomVersionId::V8 + | RoomVersionId::V9 + | RoomVersionId::V10 => { + if let Some(redact_id) = &pdu.redacts { + if !services().rooms.state_accessor.user_can_redact( + redact_id, + &pdu.sender, + &pdu.room_id, + false, + )? { + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "User cannot redact this event.", + )); + } + }; + } + RoomVersionId::V11 => { + let content = + serde_json::from_str::(pdu.content.get()) + .map_err(|_| { + Error::bad_database("Invalid content in redaction pdu.") + })?; + + if let Some(redact_id) = &content.redacts { + if !services().rooms.state_accessor.user_can_redact( + redact_id, + &pdu.sender, + &pdu.room_id, + false, + )? { + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "User cannot redact this event.", + )); + } + } + } + _ => { + return Err(Error::BadRequest( + ErrorKind::UnsupportedRoomVersion, + "Unsupported room version", + )); + } } - }; + } // We append to state before appending the pdu, so we don't have a moment in time with the // pdu without it's state. This is okay because append_pdu can't fail.