From c7e03a06f7924e9ee551228f32492d059c8cb561 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Wed, 12 Jun 2024 17:02:35 -0700 Subject: [PATCH] refuse admin room alias changes unless admin bot I.e. don't allow the `#admins:example.com` alias to be set or unset by any user other than `@grapevine:example.com`. --- src/api/client_server/alias.rs | 14 ++++++++++++-- src/api/client_server/room.rs | 15 ++++++++++----- src/service/admin.rs | 6 +++++- src/service/rooms/alias.rs | 32 +++++++++++++++++++++++++++++--- 4 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/api/client_server/alias.rs b/src/api/client_server/alias.rs index fb46dc55..c885d5e2 100644 --- a/src/api/client_server/alias.rs +++ b/src/api/client_server/alias.rs @@ -19,6 +19,9 @@ use crate::{services, Ar, Error, Ra, Result}; pub(crate) async fn create_alias_route( body: Ar, ) -> Result> { + let sender_user = + body.sender_user.as_deref().expect("user is authenticated"); + if body.room_alias.server_name() != services().globals.server_name() { return Err(Error::BadRequest( ErrorKind::InvalidParam, @@ -44,7 +47,11 @@ pub(crate) async fn create_alias_route( return Err(Error::Conflict("Alias already exists.")); } - services().rooms.alias.set_alias(&body.room_alias, &body.room_id)?; + services().rooms.alias.set_alias( + &body.room_alias, + &body.room_id, + sender_user, + )?; Ok(Ra(create_alias::v3::Response::new())) } @@ -58,6 +65,9 @@ pub(crate) async fn create_alias_route( pub(crate) async fn delete_alias_route( body: Ar, ) -> Result> { + let sender_user = + body.sender_user.as_deref().expect("user is authenticated"); + if body.room_alias.server_name() != services().globals.server_name() { return Err(Error::BadRequest( ErrorKind::InvalidParam, @@ -79,7 +89,7 @@ pub(crate) async fn delete_alias_route( )); } - services().rooms.alias.remove_alias(&body.room_alias)?; + services().rooms.alias.remove_alias(&body.room_alias, sender_user)?; // TODO: update alt_aliases? diff --git a/src/api/client_server/room.rs b/src/api/client_server/room.rs index 7c4dda90..843d9aea 100644 --- a/src/api/client_server/room.rs +++ b/src/api/client_server/room.rs @@ -56,7 +56,8 @@ pub(crate) async fn create_room_route( ) -> Result> { use create_room::v3::RoomPreset; - let sender_user = body.sender_user.as_ref().expect("user is authenticated"); + let sender_user = + body.sender_user.as_deref().expect("user is authenticated"); let room_id = RoomId::new(services().globals.server_name()); @@ -194,7 +195,7 @@ pub(crate) async fn create_room_route( | RoomVersionId::V8 | RoomVersionId::V9 | RoomVersionId::V10 => { - RoomCreateEventContent::new_v1(sender_user.clone()) + RoomCreateEventContent::new_v1(sender_user.to_owned()) } RoomVersionId::V11 => RoomCreateEventContent::new_v11(), _ => unreachable!("Validity of room version already checked"), @@ -292,7 +293,7 @@ pub(crate) async fn create_room_route( }); let mut users = BTreeMap::new(); - users.insert(sender_user.clone(), int!(100)); + users.insert(sender_user.to_owned(), int!(100)); if preset == RoomPreset::TrustedPrivateChat { for invite_ in &body.invite { @@ -529,7 +530,7 @@ pub(crate) async fn create_room_route( // Homeserver specific stuff if let Some(alias) = alias { - services().rooms.alias.set_alias(&alias, &room_id)?; + services().rooms.alias.set_alias(&alias, &room_id, sender_user)?; } if body.visibility == room::Visibility::Public { @@ -860,7 +861,11 @@ pub(crate) async fn upgrade_room_route( .local_aliases_for_room(&body.room_id) .filter_map(Result::ok) { - services().rooms.alias.set_alias(&alias, &replacement_room)?; + services().rooms.alias.set_alias( + &alias, + &replacement_room, + sender_user, + )?; } // Get the old room power levels diff --git a/src/service/admin.rs b/src/service/admin.rs index c825b579..e3576576 100644 --- a/src/service/admin.rs +++ b/src/service/admin.rs @@ -1427,7 +1427,11 @@ impl Service { ) .await?; - services().rooms.alias.set_alias(alias, &room_id)?; + services().rooms.alias.set_alias( + alias, + &room_id, + &services().globals.admin_bot_user_id, + )?; Ok(()) } diff --git a/src/service/rooms/alias.rs b/src/service/rooms/alias.rs index 3fc2d134..0b934fe7 100644 --- a/src/service/rooms/alias.rs +++ b/src/service/rooms/alias.rs @@ -1,6 +1,9 @@ -use ruma::{OwnedRoomAliasId, OwnedRoomId, RoomAliasId, RoomId}; +use ruma::{ + api::client::error::ErrorKind, OwnedRoomAliasId, OwnedRoomId, RoomAliasId, + RoomId, UserId, +}; -use crate::Result; +use crate::{services, Error, Result}; mod data; @@ -25,12 +28,35 @@ impl Service { &self, alias: &RoomAliasId, room_id: &RoomId, + user_id: &UserId, ) -> Result<()> { + if alias == services().globals.admin_bot_room_alias_id + && user_id != services().globals.admin_bot_user_id + { + return Err(Error::BadRequest( + ErrorKind::forbidden(), + "Only the admin bot can modify this alias", + )); + } + self.db.set_alias(alias, room_id) } /// Forgets about an alias. Returns an error if the alias did not exist. - pub(crate) fn remove_alias(&self, alias: &RoomAliasId) -> Result<()> { + pub(crate) fn remove_alias( + &self, + alias: &RoomAliasId, + user_id: &UserId, + ) -> Result<()> { + if alias == services().globals.admin_bot_room_alias_id + && user_id != services().globals.admin_bot_user_id + { + return Err(Error::BadRequest( + ErrorKind::forbidden(), + "Only the admin bot can modify this alias", + )); + } + self.db.remove_alias(alias) }