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`.
This commit is contained in:
Charles Hall 2024-06-12 17:02:35 -07:00
parent 273ab33809
commit c7e03a06f7
No known key found for this signature in database
GPG key ID: 7B8E0645816E07CF
4 changed files with 56 additions and 11 deletions

View file

@ -19,6 +19,9 @@ use crate::{services, Ar, Error, Ra, Result};
pub(crate) async fn create_alias_route( pub(crate) async fn create_alias_route(
body: Ar<create_alias::v3::Request>, body: Ar<create_alias::v3::Request>,
) -> Result<Ra<create_alias::v3::Response>> { ) -> Result<Ra<create_alias::v3::Response>> {
let sender_user =
body.sender_user.as_deref().expect("user is authenticated");
if body.room_alias.server_name() != services().globals.server_name() { if body.room_alias.server_name() != services().globals.server_name() {
return Err(Error::BadRequest( return Err(Error::BadRequest(
ErrorKind::InvalidParam, ErrorKind::InvalidParam,
@ -44,7 +47,11 @@ pub(crate) async fn create_alias_route(
return Err(Error::Conflict("Alias already exists.")); 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())) 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( pub(crate) async fn delete_alias_route(
body: Ar<delete_alias::v3::Request>, body: Ar<delete_alias::v3::Request>,
) -> Result<Ra<delete_alias::v3::Response>> { ) -> Result<Ra<delete_alias::v3::Response>> {
let sender_user =
body.sender_user.as_deref().expect("user is authenticated");
if body.room_alias.server_name() != services().globals.server_name() { if body.room_alias.server_name() != services().globals.server_name() {
return Err(Error::BadRequest( return Err(Error::BadRequest(
ErrorKind::InvalidParam, 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? // TODO: update alt_aliases?

View file

@ -56,7 +56,8 @@ pub(crate) async fn create_room_route(
) -> Result<Ra<create_room::v3::Response>> { ) -> Result<Ra<create_room::v3::Response>> {
use create_room::v3::RoomPreset; 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()); let room_id = RoomId::new(services().globals.server_name());
@ -194,7 +195,7 @@ pub(crate) async fn create_room_route(
| RoomVersionId::V8 | RoomVersionId::V8
| RoomVersionId::V9 | RoomVersionId::V9
| RoomVersionId::V10 => { | RoomVersionId::V10 => {
RoomCreateEventContent::new_v1(sender_user.clone()) RoomCreateEventContent::new_v1(sender_user.to_owned())
} }
RoomVersionId::V11 => RoomCreateEventContent::new_v11(), RoomVersionId::V11 => RoomCreateEventContent::new_v11(),
_ => unreachable!("Validity of room version already checked"), _ => unreachable!("Validity of room version already checked"),
@ -292,7 +293,7 @@ pub(crate) async fn create_room_route(
}); });
let mut users = BTreeMap::new(); let mut users = BTreeMap::new();
users.insert(sender_user.clone(), int!(100)); users.insert(sender_user.to_owned(), int!(100));
if preset == RoomPreset::TrustedPrivateChat { if preset == RoomPreset::TrustedPrivateChat {
for invite_ in &body.invite { for invite_ in &body.invite {
@ -529,7 +530,7 @@ pub(crate) async fn create_room_route(
// Homeserver specific stuff // Homeserver specific stuff
if let Some(alias) = alias { 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 { if body.visibility == room::Visibility::Public {
@ -860,7 +861,11 @@ pub(crate) async fn upgrade_room_route(
.local_aliases_for_room(&body.room_id) .local_aliases_for_room(&body.room_id)
.filter_map(Result::ok) .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 // Get the old room power levels

View file

@ -1427,7 +1427,11 @@ impl Service {
) )
.await?; .await?;
services().rooms.alias.set_alias(alias, &room_id)?; services().rooms.alias.set_alias(
alias,
&room_id,
&services().globals.admin_bot_user_id,
)?;
Ok(()) Ok(())
} }

View file

@ -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; mod data;
@ -25,12 +28,35 @@ impl Service {
&self, &self,
alias: &RoomAliasId, alias: &RoomAliasId,
room_id: &RoomId, room_id: &RoomId,
user_id: &UserId,
) -> Result<()> { ) -> 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) self.db.set_alias(alias, room_id)
} }
/// Forgets about an alias. Returns an error if the alias did not exist. /// 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) self.db.remove_alias(alias)
} }