From 3a8321f9adcb575370fa2c606c2a212c1f6f03f3 Mon Sep 17 00:00:00 2001 From: AndSDev Date: Mon, 29 Aug 2022 14:09:08 +0000 Subject: [PATCH 1/7] feat(db/rooms): encryption is not allowed in the admins room --- src/service/rooms/timeline/mod.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 619dca28..32781f20 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -22,6 +22,7 @@ use ruma::{ }, push::{Action, Ruleset, Tweak}, state_res, + state_res::Event, state_res::RoomVersion, uint, CanonicalJsonObject, CanonicalJsonValue, EventId, OwnedEventId, OwnedRoomId, OwnedServerName, RoomAliasId, RoomId, UserId, @@ -683,6 +684,22 @@ impl Service { let (pdu, pdu_json) = self.create_hash_and_sign_event(pdu_builder, sender, room_id, state_lock)?; + let admin_room = services().rooms.alias.resolve_local_alias( + <&RoomAliasId>::try_from( + format!("#admins:{}", services().globals.server_name()).as_str(), + ) + .expect("#admins:server_name is a valid room alias"), + )?; + if admin_room.filter(|v| v == room_id).is_some() { + if pdu.event_type() == &RoomEventType::RoomEncryption { + warn!("Encryption is not allowed in the admins room"); + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "Encryption is not allowed in the admins room.", + )); + } + } + // 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. let statehashid = services().rooms.state.append_to_state(&pdu)?; From c67f95ebffd60a9efe222816c742b1522e06578e Mon Sep 17 00:00:00 2001 From: AndSDev Date: Wed, 31 Aug 2022 07:10:54 +0000 Subject: [PATCH 2/7] feat(db/rooms): disable leaving from admin room for conduit user --- src/service/rooms/timeline/mod.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 32781f20..2f56fead 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -698,6 +698,26 @@ impl Service { "Encryption is not allowed in the admins room.", )); } + if pdu.event_type() == &RoomEventType::RoomMember { + #[derive(Deserialize)] + struct ExtractMembership { + membership: MembershipState, + } + + let content = serde_json::from_str::(pdu.content.get()) + .map_err(|_| Error::bad_database("Invalid content in pdu."))?; + + if content.membership == MembershipState::Leave { + let server_user = format!("@conduit:{}", services().globals.server_name()); + if sender == &server_user { + warn!("Conduit user cannot leave from admins room"); + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "Conduit user cannot leave from admins room.", + )); + } + } + } } // We append to state before appending the pdu, so we don't have a moment in time with the From da2dbd2877d3b7b1edc2a05bb5593759d8072794 Mon Sep 17 00:00:00 2001 From: AndSDev Date: Wed, 31 Aug 2022 07:11:28 +0000 Subject: [PATCH 3/7] feat(db/rooms): disable leaving from admin room for last user --- src/service/rooms/timeline/mod.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 2f56fead..5d286283 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -716,6 +716,21 @@ impl Service { "Conduit user cannot leave from admins room.", )); } + + let count = services() + .rooms + .state_cache + .room_members(room_id) + .filter_map(|m| m.ok()) + .filter(|m| m.server_name() == services().globals.server_name()) + .count(); + if count < 3 { + warn!("Last admin cannot leave from admins room"); + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "Last admin cannot leave from admins room.", + )); + } } } } From 912491cb28f88fb0ed9cdd1aac4a76a307cbec03 Mon Sep 17 00:00:00 2001 From: AndSDev Date: Wed, 31 Aug 2022 08:22:45 +0000 Subject: [PATCH 4/7] style(db/rooms): refactor admin room pdu validating --- src/service/rooms/timeline/mod.rs | 73 ++++++++++++++++--------------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 5d286283..9ededd2b 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -691,47 +691,50 @@ impl Service { .expect("#admins:server_name is a valid room alias"), )?; if admin_room.filter(|v| v == room_id).is_some() { - if pdu.event_type() == &RoomEventType::RoomEncryption { - warn!("Encryption is not allowed in the admins room"); - return Err(Error::BadRequest( - ErrorKind::Forbidden, - "Encryption is not allowed in the admins room.", - )); - } - if pdu.event_type() == &RoomEventType::RoomMember { - #[derive(Deserialize)] - struct ExtractMembership { - membership: MembershipState, + match pdu.event_type() { + RoomEventType::RoomEncryption => { + warn!("Encryption is not allowed in the admins room"); + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "Encryption is not allowed in the admins room.", + )); } + RoomEventType::RoomMember => { + #[derive(Deserialize)] + struct ExtractMembership { + membership: MembershipState, + } - let content = serde_json::from_str::(pdu.content.get()) - .map_err(|_| Error::bad_database("Invalid content in pdu."))?; + let content = serde_json::from_str::(pdu.content.get()) + .map_err(|_| Error::bad_database("Invalid content in pdu."))?; - if content.membership == MembershipState::Leave { - let server_user = format!("@conduit:{}", services().globals.server_name()); - if sender == &server_user { - warn!("Conduit user cannot leave from admins room"); - return Err(Error::BadRequest( - ErrorKind::Forbidden, - "Conduit user cannot leave from admins room.", - )); - } + if content.membership == MembershipState::Leave { + let server_user = format!("@conduit:{}", services().globals.server_name()); + if sender == &server_user { + warn!("Conduit user cannot leave from admins room"); + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "Conduit user cannot leave from admins room.", + )); + } - let count = services() - .rooms - .state_cache - .room_members(room_id) - .filter_map(|m| m.ok()) - .filter(|m| m.server_name() == services().globals.server_name()) - .count(); - if count < 3 { - warn!("Last admin cannot leave from admins room"); - return Err(Error::BadRequest( - ErrorKind::Forbidden, - "Last admin cannot leave from admins room.", - )); + let count = services() + .rooms + .state_cache + .room_members(room_id) + .filter_map(|m| m.ok()) + .filter(|m| m.server_name() == services().globals.server_name()) + .count(); + if count < 3 { + warn!("Last admin cannot leave from admins room"); + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "Last admin cannot leave from admins room.", + )); + } } } + _ => {} } } From 76f81ac2010746c5cba1105a37187ce2e59d2ffe Mon Sep 17 00:00:00 2001 From: AndSDev Date: Tue, 6 Sep 2022 11:32:33 +0000 Subject: [PATCH 5/7] feat(db/rooms): disable banning for last user and conduit user in admins room --- src/service/rooms/timeline/mod.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 9ededd2b..66a81960 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -733,6 +733,32 @@ impl Service { )); } } + + if content.membership == MembershipState::Ban && pdu.state_key().is_some() { + let server_user = format!("@conduit:{}", services().globals.server_name()); + if pdu.state_key().as_ref().unwrap() == &server_user { + warn!("Conduit user cannot be banned in admins room"); + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "Conduit user cannot be banned in admins room.", + )); + } + + let count = services() + .rooms + .state_cache + .room_members(room_id) + .filter_map(|m| m.ok()) + .filter(|m| m.server_name() == services().globals.server_name()) + .count(); + if count < 3 { + warn!("Last admin cannot be banned in admins room"); + return Err(Error::BadRequest( + ErrorKind::Forbidden, + "Last admin cannot be banned in admins room.", + )); + } + } } _ => {} } From d755a96c2c3422849fdac8792e5d91141f837a18 Mon Sep 17 00:00:00 2001 From: AndSDev Date: Thu, 13 Oct 2022 11:19:51 +0000 Subject: [PATCH 6/7] refactor(service/rooms/timeline): add cache for server_name --- src/service/rooms/timeline/mod.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 66a81960..9494f67d 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -705,11 +705,12 @@ impl Service { membership: MembershipState, } + let server_name = services().globals.server_name(); let content = serde_json::from_str::(pdu.content.get()) .map_err(|_| Error::bad_database("Invalid content in pdu."))?; if content.membership == MembershipState::Leave { - let server_user = format!("@conduit:{}", services().globals.server_name()); + let server_user = format!("@conduit:{}", server_name); if sender == &server_user { warn!("Conduit user cannot leave from admins room"); return Err(Error::BadRequest( @@ -723,7 +724,7 @@ impl Service { .state_cache .room_members(room_id) .filter_map(|m| m.ok()) - .filter(|m| m.server_name() == services().globals.server_name()) + .filter(|m| m.server_name() == server_name) .count(); if count < 3 { warn!("Last admin cannot leave from admins room"); @@ -735,7 +736,7 @@ impl Service { } if content.membership == MembershipState::Ban && pdu.state_key().is_some() { - let server_user = format!("@conduit:{}", services().globals.server_name()); + let server_user = format!("@conduit:{}", server_name); if pdu.state_key().as_ref().unwrap() == &server_user { warn!("Conduit user cannot be banned in admins room"); return Err(Error::BadRequest( @@ -749,7 +750,7 @@ impl Service { .state_cache .room_members(room_id) .filter_map(|m| m.ok()) - .filter(|m| m.server_name() == services().globals.server_name()) + .filter(|m| m.server_name() == server_name) .count(); if count < 3 { warn!("Last admin cannot be banned in admins room"); From e923f63c4919a9eb65f074c8099fc7bc115925ee Mon Sep 17 00:00:00 2001 From: AndSDev Date: Fri, 14 Oct 2022 14:45:05 +0300 Subject: [PATCH 7/7] fix(service/rooms/timeline): fix validating for non-joined members --- src/service/rooms/timeline/mod.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/service/rooms/timeline/mod.rs b/src/service/rooms/timeline/mod.rs index 9494f67d..403b400d 100644 --- a/src/service/rooms/timeline/mod.rs +++ b/src/service/rooms/timeline/mod.rs @@ -705,13 +705,17 @@ impl Service { membership: MembershipState, } + let target = pdu + .state_key() + .filter(|v| v.starts_with("@")) + .unwrap_or(sender.as_str()); let server_name = services().globals.server_name(); + let server_user = format!("@conduit:{}", server_name); let content = serde_json::from_str::(pdu.content.get()) .map_err(|_| Error::bad_database("Invalid content in pdu."))?; if content.membership == MembershipState::Leave { - let server_user = format!("@conduit:{}", server_name); - if sender == &server_user { + if target == &server_user { warn!("Conduit user cannot leave from admins room"); return Err(Error::BadRequest( ErrorKind::Forbidden, @@ -725,8 +729,9 @@ impl Service { .room_members(room_id) .filter_map(|m| m.ok()) .filter(|m| m.server_name() == server_name) + .filter(|m| m != target) .count(); - if count < 3 { + if count < 2 { warn!("Last admin cannot leave from admins room"); return Err(Error::BadRequest( ErrorKind::Forbidden, @@ -736,8 +741,7 @@ impl Service { } if content.membership == MembershipState::Ban && pdu.state_key().is_some() { - let server_user = format!("@conduit:{}", server_name); - if pdu.state_key().as_ref().unwrap() == &server_user { + if target == &server_user { warn!("Conduit user cannot be banned in admins room"); return Err(Error::BadRequest( ErrorKind::Forbidden, @@ -751,8 +755,9 @@ impl Service { .room_members(room_id) .filter_map(|m| m.ok()) .filter(|m| m.server_name() == server_name) + .filter(|m| m != target) .count(); - if count < 3 { + if count < 2 { warn!("Last admin cannot be banned in admins room"); return Err(Error::BadRequest( ErrorKind::Forbidden,