diff --git a/src/client_server/account.rs b/src/client_server/account.rs index 24b04d5912bcb3c253731943034046d2077a15eb..0cf30a079d8152bdf8016a90217f370b537665e2 100644 --- a/src/client_server/account.rs +++ b/src/client_server/account.rs @@ -179,12 +179,11 @@ pub async fn register_route( let password = if is_guest { None } else { - body.password.clone() - } - .unwrap_or_default(); + body.password.as_deref() + }; // Create user - db.users.create(&user_id, &password)?; + db.users.create(&user_id, password)?; // Initial data db.account_data.update( @@ -233,7 +232,7 @@ pub async fn register_route( let conduit_user = UserId::parse_with_server_name("conduit", db.globals.server_name()) .expect("@conduit:server_name is valid"); - db.users.create(&conduit_user, "")?; + db.users.create(&conduit_user, None)?; let room_id = RoomId::new(db.globals.server_name()); @@ -547,7 +546,8 @@ pub async fn change_password_route( return Err(Error::Uiaa(uiaainfo)); } - db.users.set_password(&sender_user, &body.new_password)?; + db.users + .set_password(&sender_user, Some(&body.new_password))?; if body.logout_devices { // Logout all devices except the current one diff --git a/src/client_server/media.rs b/src/client_server/media.rs index f9350e0f715225dd9545c9c584bded3e231bbefa..74ca6c842ce168dba04409a3c5cc6e01b30f1592 100644 --- a/src/client_server/media.rs +++ b/src/client_server/media.rs @@ -38,7 +38,11 @@ pub async fn create_content_route( ); db.media.create( mxc.clone(), - &body.filename.as_deref(), + &body + .filename + .as_ref() + .map(|filename| "inline; filename=".to_owned() + filename) + .as_deref(), &body.content_type.as_deref(), &body.file, )?; @@ -64,7 +68,7 @@ pub async fn get_content_route( let mxc = format!("mxc://{}/{}", body.server_name, body.media_id); if let Some(FileMeta { - filename, + content_disposition, content_type, file, }) = db.media.get(&mxc)? @@ -72,7 +76,7 @@ pub async fn get_content_route( Ok(get_content::Response { file, content_type, - content_disposition: filename, + content_disposition, } .into()) } else if &*body.server_name != db.globals.server_name() && body.allow_remote { diff --git a/src/database.rs b/src/database.rs index 561b56123e4f6e6d30c02d5d10f5acd7303edf54..7a55b030e412513d767424887319aa500f872824 100644 --- a/src/database.rs +++ b/src/database.rs @@ -11,7 +11,7 @@ pub mod uiaa; pub mod users; -use crate::{Error, Result}; +use crate::{utils, Error, Result}; use directories::ProjectDirs; use futures::StreamExt; use log::{error, info}; @@ -246,6 +246,25 @@ pub async fn load_or_create(config: Config) -> Result<Self> { info!("Migration: 0 -> 1 finished"); } + if db.globals.database_version()? < 2 { + // We accidentally inserted hashed versions of "" into the db instead of just "" + for userid_password in db.users.userid_password.iter() { + let (userid, password) = userid_password?; + + let password = utils::string_from_bytes(&password); + + if password.map_or(false, |password| { + argon2::verify_encoded(&password, b"").unwrap_or(false) + }) { + db.users.userid_password.insert(userid, b"")?; + } + } + + db.globals.bump_database_version(2)?; + + info!("Migration: 1 -> 2 finished"); + } + // This data is probably outdated db.rooms.edus.presenceid_presence.clear()?; diff --git a/src/database/media.rs b/src/database/media.rs index 37fcb741163d37cfcbe3ac756c44fc0876d7671b..28ef88a2ef2fac6b2f7760265aaf60da776b634e 100644 --- a/src/database/media.rs +++ b/src/database/media.rs @@ -4,14 +4,14 @@ use std::mem; pub struct FileMeta { - pub filename: Option<String>, + pub content_disposition: Option<String>, pub content_type: Option<String>, pub file: Vec<u8>, } #[derive(Clone)] pub struct Media { - pub(super) mediaid_file: sled::Tree, // MediaId = MXC + WidthHeight + Filename + ContentType + pub(super) mediaid_file: sled::Tree, // MediaId = MXC + WidthHeight + ContentDisposition + ContentType } impl Media { @@ -19,7 +19,7 @@ impl Media { pub fn create( &self, mxc: String, - filename: &Option<&str>, + content_disposition: &Option<&str>, content_type: &Option<&str>, file: &[u8], ) -> Result<()> { @@ -28,7 +28,12 @@ pub fn create( key.extend_from_slice(&0_u32.to_be_bytes()); // Width = 0 if it's not a thumbnail key.extend_from_slice(&0_u32.to_be_bytes()); // Height = 0 if it's not a thumbnail key.push(0xff); - key.extend_from_slice(filename.as_ref().map(|f| f.as_bytes()).unwrap_or_default()); + key.extend_from_slice( + content_disposition + .as_ref() + .map(|f| f.as_bytes()) + .unwrap_or_default(), + ); key.push(0xff); key.extend_from_slice( content_type @@ -46,7 +51,7 @@ pub fn create( pub fn upload_thumbnail( &self, mxc: String, - filename: &Option<String>, + content_disposition: &Option<String>, content_type: &Option<String>, width: u32, height: u32, @@ -57,7 +62,12 @@ pub fn upload_thumbnail( key.extend_from_slice(&width.to_be_bytes()); key.extend_from_slice(&height.to_be_bytes()); key.push(0xff); - key.extend_from_slice(filename.as_ref().map(|f| f.as_bytes()).unwrap_or_default()); + key.extend_from_slice( + content_disposition + .as_ref() + .map(|f| f.as_bytes()) + .unwrap_or_default(), + ); key.push(0xff); key.extend_from_slice( content_type @@ -92,20 +102,24 @@ pub fn get(&self, mxc: &str) -> Result<Option<FileMeta>> { }) .transpose()?; - let filename_bytes = parts + let content_disposition_bytes = parts .next() .ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?; - let filename = if filename_bytes.is_empty() { + let content_disposition = if content_disposition_bytes.is_empty() { None } else { - Some(utils::string_from_bytes(filename_bytes).map_err(|_| { - Error::bad_database("Filename in mediaid_file is invalid unicode.") - })?) + Some( + utils::string_from_bytes(content_disposition_bytes).map_err(|_| { + Error::bad_database( + "Content Disposition in mediaid_file is invalid unicode.", + ) + })?, + ) }; Ok(Some(FileMeta { - filename, + content_disposition, content_type, file: file.to_vec(), })) @@ -169,21 +183,22 @@ pub fn get_thumbnail(&self, mxc: String, width: u32, height: u32) -> Result<Opti }) .transpose()?; - let filename_bytes = parts + let content_disposition_bytes = parts .next() .ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?; - let filename = if filename_bytes.is_empty() { + let content_disposition = if content_disposition_bytes.is_empty() { None } else { Some( - utils::string_from_bytes(filename_bytes) - .map_err(|_| Error::bad_database("Filename in db is invalid."))?, + utils::string_from_bytes(content_disposition_bytes).map_err(|_| { + Error::bad_database("Content Disposition in db is invalid.") + })?, ) }; Ok(Some(FileMeta { - filename, + content_disposition, content_type, file: file.to_vec(), })) @@ -202,16 +217,20 @@ pub fn get_thumbnail(&self, mxc: String, width: u32, height: u32) -> Result<Opti }) .transpose()?; - let filename_bytes = parts + let content_disposition_bytes = parts .next() .ok_or_else(|| Error::bad_database("Media ID in db is invalid."))?; - let filename = if filename_bytes.is_empty() { + let content_disposition = if content_disposition_bytes.is_empty() { None } else { - Some(utils::string_from_bytes(filename_bytes).map_err(|_| { - Error::bad_database("Filename in mediaid_file is invalid unicode.") - })?) + Some( + utils::string_from_bytes(content_disposition_bytes).map_err(|_| { + Error::bad_database( + "Content Disposition in mediaid_file is invalid unicode.", + ) + })?, + ) }; if let Ok(image) = image::load_from_memory(&file) { @@ -219,7 +238,7 @@ pub fn get_thumbnail(&self, mxc: String, width: u32, height: u32) -> Result<Opti let original_height = image.height(); if width > original_width || height > original_height { return Ok(Some(FileMeta { - filename, + content_disposition, content_type, file: file.to_vec(), })); @@ -286,14 +305,14 @@ pub fn get_thumbnail(&self, mxc: String, width: u32, height: u32) -> Result<Opti self.mediaid_file.insert(thumbnail_key, &*thumbnail_bytes)?; Ok(Some(FileMeta { - filename, + content_disposition, content_type, file: thumbnail_bytes.to_vec(), })) } else { // Couldn't parse file to generate thumbnail, send original Ok(Some(FileMeta { - filename, + content_disposition, content_type, file: file.to_vec(), })) diff --git a/src/database/rooms.rs b/src/database/rooms.rs index 6b17f3989f4d2ec01b7f2275cac3d64bb3537004..703314e68e2220434563f6dccc119f7fd6f5257c 100644 --- a/src/database/rooms.rs +++ b/src/database/rooms.rs @@ -725,8 +725,9 @@ pub fn append_pdu( .users .iter() .filter_map(|r| r.ok()) - .filter(|user_id| self.is_joined(&user_id, &pdu.room_id).unwrap_or(false)) + .filter(|user_id| user_id.server_name() == db.globals.server_name()) .filter(|user_id| !db.users.is_deactivated(user_id).unwrap_or(false)) + .filter(|user_id| self.is_joined(&user_id, &pdu.room_id).unwrap_or(false)) { // Don't notify the user of their own events if user == pdu.sender { diff --git a/src/database/users.rs b/src/database/users.rs index a5b877540aea76ebd5029da8f0a30469821a2bb0..52e6e33bdd86fb6e4e319a019ea9cb7dda943d13 100644 --- a/src/database/users.rs +++ b/src/database/users.rs @@ -49,7 +49,7 @@ pub fn is_deactivated(&self, user_id: &UserId) -> Result<bool> { } /// Create a new user account on this homeserver. - pub fn create(&self, user_id: &UserId, password: &str) -> Result<()> { + pub fn create(&self, user_id: &UserId, password: Option<&str>) -> Result<()> { self.set_password(user_id, password)?; Ok(()) } @@ -110,15 +110,20 @@ pub fn password_hash(&self, user_id: &UserId) -> Result<Option<String>> { } /// Hash and set the user's password to the Argon2 hash - pub fn set_password(&self, user_id: &UserId, password: &str) -> Result<()> { - if let Ok(hash) = utils::calculate_hash(&password) { - self.userid_password.insert(user_id.to_string(), &*hash)?; - Ok(()) + pub fn set_password(&self, user_id: &UserId, password: Option<&str>) -> Result<()> { + if let Some(password) = password { + if let Ok(hash) = utils::calculate_hash(&password) { + self.userid_password.insert(user_id.to_string(), &*hash)?; + Ok(()) + } else { + Err(Error::BadRequest( + ErrorKind::InvalidParam, + "Password does not meet the requirements.", + )) + } } else { - Err(Error::BadRequest( - ErrorKind::InvalidParam, - "Password does not meet the requirements.", - )) + self.userid_password.insert(user_id.to_string(), "")?; + Ok(()) } }