feat(appservice): ensure users/aliases outside of namespaces are not accessed

This commit is contained in:
Matthias Ahouansou 2024-04-16 15:53:38 +01:00
parent 53d3f9ae89
commit 3086271139
No known key found for this signature in database
7 changed files with 202 additions and 39 deletions

View file

@ -6,7 +6,10 @@ pub use data::Data;
use futures_util::Future;
use regex::RegexSet;
use ruma::api::appservice::{Namespace, Registration};
use ruma::{
api::appservice::{Namespace, Registration},
RoomAliasId, RoomId, UserId,
};
use tokio::sync::RwLock;
use crate::{services, Result};
@ -83,6 +86,18 @@ pub struct RegistrationInfo {
pub rooms: NamespaceRegex,
}
impl RegistrationInfo {
pub fn is_user_match(&self, user_id: &UserId) -> bool {
self.users.is_match(user_id.as_str())
|| self.registration.sender_localpart == user_id.localpart()
}
pub fn is_exclusive_user_match(&self, user_id: &UserId) -> bool {
self.users.is_exclusive_match(user_id.as_str())
|| self.registration.sender_localpart == user_id.localpart()
}
}
impl TryFrom<Registration> for RegistrationInfo {
fn try_from(value: Registration) -> Result<RegistrationInfo, regex::Error> {
Ok(RegistrationInfo {
@ -122,6 +137,7 @@ impl Service {
}
/// Registers an appservice and returns the ID to the caller.
pub async fn register_appservice(&self, yaml: Registration) -> Result<String> {
//TODO: Check for collisions between exclusive appservice namespaces
services()
.appservice
.registration_info
@ -175,6 +191,30 @@ impl Service {
.cloned()
}
// Checks if a given user id matches any exclusive appservice regex
pub async fn is_exclusive_user_id(&self, user_id: &UserId) -> bool {
self.read()
.await
.values()
.any(|info| info.is_exclusive_user_match(user_id))
}
// Checks if a given room alias matches any exclusive appservice regex
pub async fn is_exclusive_alias(&self, alias: &RoomAliasId) -> bool {
self.read()
.await
.values()
.any(|info| info.aliases.is_exclusive_match(alias.as_str()))
}
// Checks if a given room id matches any exclusive appservice regex
pub async fn is_exclusive_room_id(&self, room_id: &RoomId) -> bool {
self.read()
.await
.values()
.any(|info| info.rooms.is_exclusive_match(room_id.as_str()))
}
pub fn read(
&self,
) -> impl Future<Output = tokio::sync::RwLockReadGuard<'_, BTreeMap<String, RegistrationInfo>>>