option to control federating device display names

Signed-off-by: girlbossceo <june@girlboss.ceo>
This commit is contained in:
girlbossceo 2023-09-10 15:40:00 -04:00
parent 81e8df3102
commit 1b75d384d7
5 changed files with 47 additions and 10 deletions

View File

@ -63,4 +63,8 @@ allow_public_room_directory_over_federation = false
# Set this to true to allow your server's public room directory to be queried without client authentication (access token) through the Client APIs. # Set this to true to allow your server's public room directory to be queried without client authentication (access token) through the Client APIs.
# Set this to false to protect against /publicRooms spiders. # Set this to false to protect against /publicRooms spiders.
allow_public_room_directory_without_auth = false allow_public_room_directory_without_auth = false
# Set this to true to allow federating device display names / allow external users to see your device display name.
# If federation is disabled entirely (`allow_federation`), this is inherently false.
allow_device_name_federation = false

View File

@ -72,8 +72,13 @@ pub async fn upload_keys_route(
pub async fn get_keys_route(body: Ruma<get_keys::v3::Request>) -> Result<get_keys::v3::Response> { pub async fn get_keys_route(body: Ruma<get_keys::v3::Request>) -> Result<get_keys::v3::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let sender_user = body.sender_user.as_ref().expect("user is authenticated");
let response = let response = get_keys_helper(
get_keys_helper(Some(sender_user), &body.device_keys, |u| u == sender_user).await?; Some(sender_user),
&body.device_keys,
|u| u == sender_user,
true, // Always allow local users to see device names of other local users
)
.await?;
Ok(response) Ok(response)
} }
@ -259,6 +264,7 @@ pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
sender_user: Option<&UserId>, sender_user: Option<&UserId>,
device_keys_input: &BTreeMap<OwnedUserId, Vec<OwnedDeviceId>>, device_keys_input: &BTreeMap<OwnedUserId, Vec<OwnedDeviceId>>,
allowed_signatures: F, allowed_signatures: F,
include_display_names: bool,
) -> Result<get_keys::v3::Response> { ) -> Result<get_keys::v3::Response> {
let mut master_keys = BTreeMap::new(); let mut master_keys = BTreeMap::new();
let mut self_signing_keys = BTreeMap::new(); let mut self_signing_keys = BTreeMap::new();
@ -290,8 +296,9 @@ pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
Error::bad_database("all_device_keys contained nonexistent device.") Error::bad_database("all_device_keys contained nonexistent device.")
})?; })?;
add_unsigned_device_display_name(&mut keys, metadata) add_unsigned_device_display_name(&mut keys, metadata, include_display_names)
.map_err(|_| Error::bad_database("invalid device keys in database"))?; .map_err(|_| Error::bad_database("invalid device keys in database"))?;
container.insert(device_id, keys); container.insert(device_id, keys);
} }
} }
@ -308,7 +315,7 @@ pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
"Tried to get keys for nonexistent device.", "Tried to get keys for nonexistent device.",
))?; ))?;
add_unsigned_device_display_name(&mut keys, metadata) add_unsigned_device_display_name(&mut keys, metadata, include_display_names)
.map_err(|_| Error::bad_database("invalid device keys in database"))?; .map_err(|_| Error::bad_database("invalid device keys in database"))?;
container.insert(device_id.to_owned(), keys); container.insert(device_id.to_owned(), keys);
} }
@ -446,13 +453,21 @@ pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
fn add_unsigned_device_display_name( fn add_unsigned_device_display_name(
keys: &mut Raw<ruma::encryption::DeviceKeys>, keys: &mut Raw<ruma::encryption::DeviceKeys>,
metadata: ruma::api::client::device::Device, metadata: ruma::api::client::device::Device,
include_display_names: bool,
) -> serde_json::Result<()> { ) -> serde_json::Result<()> {
if let Some(display_name) = metadata.display_name { if let Some(display_name) = metadata.display_name {
let mut object = keys.deserialize_as::<serde_json::Map<String, serde_json::Value>>()?; let mut object = keys.deserialize_as::<serde_json::Map<String, serde_json::Value>>()?;
let unsigned = object.entry("unsigned").or_insert_with(|| json!({})); let unsigned = object.entry("unsigned").or_insert_with(|| json!({}));
if let serde_json::Value::Object(unsigned_object) = unsigned { if let serde_json::Value::Object(unsigned_object) = unsigned {
unsigned_object.insert("device_display_name".to_owned(), display_name.into()); if include_display_names {
unsigned_object.insert("device_display_name".to_owned(), display_name.into());
} else {
unsigned_object.insert(
"device_display_name".to_owned(),
Some(metadata.device_id.as_str().to_string()).into(),
);
}
} }
*keys = Raw::from_json(serde_json::value::to_raw_value(&object)?); *keys = Raw::from_json(serde_json::value::to_raw_value(&object)?);

View File

@ -1848,13 +1848,18 @@ pub async fn get_devices_route(
.all_devices_metadata(&body.user_id) .all_devices_metadata(&body.user_id)
.filter_map(|r| r.ok()) .filter_map(|r| r.ok())
.filter_map(|metadata| { .filter_map(|metadata| {
let device_id_string = metadata.device_id.as_str().to_string();
let device_display_name = match services().globals.allow_device_name_federation() {
true => Some(device_id_string.to_string()),
false => metadata.display_name,
};
Some(UserDevice { Some(UserDevice {
keys: services() keys: services()
.users .users
.get_device_keys(&body.user_id, &metadata.device_id) .get_device_keys(&body.user_id, &metadata.device_id)
.ok()??, .ok()??,
device_id: metadata.device_id, device_id: metadata.device_id,
device_display_name: metadata.display_name, device_display_name: device_display_name,
}) })
}) })
.collect(), .collect(),
@ -1940,9 +1945,12 @@ pub async fn get_keys_route(body: Ruma<get_keys::v1::Request>) -> Result<get_key
return Err(Error::bad_config("Federation is disabled.")); return Err(Error::bad_config("Federation is disabled."));
} }
let result = get_keys_helper(None, &body.device_keys, |u| { let result = get_keys_helper(
Some(u.server_name()) == body.sender_servername.as_deref() None,
}) &body.device_keys,
|u| Some(u.server_name()) == body.sender_servername.as_deref(),
services().globals.allow_device_name_federation(),
)
.await?; .await?;
Ok(get_keys::v1::Response { Ok(get_keys::v1::Response {

View File

@ -55,6 +55,8 @@ pub struct Config {
pub allow_public_room_directory_over_federation: bool, pub allow_public_room_directory_over_federation: bool,
#[serde(default = "false_fn")] #[serde(default = "false_fn")]
pub allow_public_room_directory_without_auth: bool, pub allow_public_room_directory_without_auth: bool,
#[serde(default = "false_fn")]
pub allow_device_name_federation: bool,
#[serde(default = "true_fn")] #[serde(default = "true_fn")]
pub allow_room_creation: bool, pub allow_room_creation: bool,
#[serde(default = "true_fn")] #[serde(default = "true_fn")]
@ -153,6 +155,10 @@ impl fmt::Display for Config {
), ),
("Allow encryption", &self.allow_encryption.to_string()), ("Allow encryption", &self.allow_encryption.to_string()),
("Allow federation", &self.allow_federation.to_string()), ("Allow federation", &self.allow_federation.to_string()),
(
"Allow device name federation",
&self.allow_device_name_federation.to_string(),
),
("Allow room creation", &self.allow_room_creation.to_string()), ("Allow room creation", &self.allow_room_creation.to_string()),
( (
"Allow public room directory over federation", "Allow public room directory over federation",

View File

@ -307,6 +307,10 @@ impl Service {
self.config.allow_public_room_directory_without_auth self.config.allow_public_room_directory_without_auth
} }
pub fn allow_device_name_federation(&self) -> bool {
self.config.allow_device_name_federation
}
pub fn allow_room_creation(&self) -> bool { pub fn allow_room_creation(&self) -> bool {
self.config.allow_room_creation self.config.allow_room_creation
} }