From 4262f1d3b0e7682f51591166725e4ec47ba4e78f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Fri, 16 Oct 2020 15:54:50 +0200 Subject: [PATCH] crypto: Don't cache inbound group sessions in the sqlite store. --- matrix_sdk_crypto/src/store/sqlite.rs | 180 ++++++++++++++++++-------- 1 file changed, 124 insertions(+), 56 deletions(-) diff --git a/matrix_sdk_crypto/src/store/sqlite.rs b/matrix_sdk_crypto/src/store/sqlite.rs index e3aaa303..6bc710dc 100644 --- a/matrix_sdk_crypto/src/store/sqlite.rs +++ b/matrix_sdk_crypto/src/store/sqlite.rs @@ -34,7 +34,7 @@ use sqlx::{query, query_as, sqlite::SqliteConnectOptions, Connection, Executor, use zeroize::Zeroizing; use super::{ - caches::{DeviceStore, GroupSessionStore, ReadOnlyUserDevices, SessionStore}, + caches::{DeviceStore, ReadOnlyUserDevices, SessionStore}, CryptoStore, CryptoStoreError, Result, }; use crate::{ @@ -56,7 +56,6 @@ pub struct SqliteStore { path: Arc, sessions: SessionStore, - inbound_group_sessions: GroupSessionStore, devices: DeviceStore, tracked_users: Arc>, users_for_key_query: Arc>, @@ -150,7 +149,6 @@ impl SqliteStore { device_id: Arc::new(device_id.into()), account_info: Arc::new(SyncMutex::new(None)), sessions: SessionStore::new(), - inbound_group_sessions: GroupSessionStore::new(), devices: DeviceStore::new(), path: Arc::new(path), connection: Arc::new(Mutex::new(connection)), @@ -525,7 +523,113 @@ impl SqliteStore { .collect::>>()?) } - async fn load_inbound_group_sessions(&self) -> Result<()> { + async fn load_inbound_session_data( + &self, + connection: &mut SqliteConnection, + session_row_id: i64, + pickle: String, + sender_key: String, + room_id: RoomId, + imported: bool, + ) -> Result { + let key_rows: Vec<(String, String)> = + query_as("SELECT algorithm, key FROM group_session_claimed_keys WHERE session_id = ?") + .bind(session_row_id) + .fetch_all(&mut *connection) + .await?; + + let claimed_keys: BTreeMap = key_rows + .into_iter() + .filter_map(|row| { + let algorithm = row.0.parse::().ok()?; + let key = row.1; + + Some((algorithm, key)) + }) + .collect(); + + let mut chain_rows: Vec<(String,)> = + query_as("SELECT key, key FROM group_session_chains WHERE session_id = ?") + .bind(session_row_id) + .fetch_all(&mut *connection) + .await?; + + let chains: Vec = chain_rows.drain(..).map(|r| r.0).collect(); + + let chains = if chains.is_empty() { + None + } else { + Some(chains) + }; + + let pickle = PickledInboundGroupSession { + pickle: InboundGroupSessionPickle::from(pickle), + sender_key, + signing_key: claimed_keys, + room_id, + forwarding_chains: chains, + imported, + }; + + Ok(InboundGroupSession::from_pickle( + pickle, + self.get_pickle_mode(), + )?) + } + + async fn load_inbound_group_session_helper( + &self, + room_id: &RoomId, + sender_key: &str, + session_id: &str, + ) -> Result> { + let account_id = self.account_id().ok_or(CryptoStoreError::AccountUnset)?; + let mut connection = self.connection.lock().await; + + let row: Option<(i64, String, bool)> = query_as( + "SELECT id, pickle, imported + FROM inbound_group_sessions + WHERE ( + account_id = ? and + room_id = ? and + sender_key = ? and + session_id = ? + )", + ) + .bind(account_id) + .bind(room_id.as_str()) + .bind(sender_key) + .bind(session_id) + .fetch_optional(&mut *connection) + .await?; + + let row = if let Some(r) = row { + r + } else { + return Ok(None); + }; + + let session_row_id = row.0; + let pickle = row.1; + let imported = row.2; + + let session = self + .load_inbound_session_data( + &mut connection, + session_row_id, + pickle, + sender_key.to_owned(), + room_id.to_owned(), + imported, + ) + .await?; + + Ok(Some(session)) + } + + async fn load_inbound_group_sessions(&self) -> Result> { + let mut sessions = Vec::new(); + let account_id = self.account_id().ok_or(CryptoStoreError::AccountUnset)?; let mut connection = self.connection.lock().await; @@ -541,57 +645,24 @@ impl SqliteStore { let session_row_id = row.0; let pickle = row.1; let sender_key = row.2; - let room_id = row.3; + let room_id = RoomId::try_from(row.3)?; let imported = row.4; - let key_rows: Vec<(String, String)> = query_as( - "SELECT algorithm, key FROM group_session_claimed_keys WHERE session_id = ?", - ) - .bind(session_row_id) - .fetch_all(&mut *connection) - .await?; - - let claimed_keys: BTreeMap = key_rows - .into_iter() - .filter_map(|row| { - let algorithm = row.0.parse::().ok()?; - let key = row.1; - - Some((algorithm, key)) - }) - .collect(); - - let mut chain_rows: Vec<(String,)> = - query_as("SELECT key, key FROM group_session_chains WHERE session_id = ?") - .bind(session_row_id) - .fetch_all(&mut *connection) - .await?; - - let chains: Vec = chain_rows.drain(..).map(|r| r.0).collect(); - - let chains = if chains.is_empty() { - None - } else { - Some(chains) - }; - - let pickle = PickledInboundGroupSession { - pickle: InboundGroupSessionPickle::from(pickle), - sender_key, - signing_key: claimed_keys, - room_id: RoomId::try_from(room_id)?, - forwarding_chains: chains, - imported, - }; - - self.inbound_group_sessions - .add(InboundGroupSession::from_pickle( + let session = self + .load_inbound_session_data( + &mut connection, + session_row_id, pickle, - self.get_pickle_mode(), - )?); + sender_key, + room_id.to_owned(), + imported, + ) + .await?; + + sessions.push(session); } - Ok(()) + Ok(sessions) } async fn save_tracked_user(&self, user: &UserId, dirty: bool) -> Result<()> { @@ -1205,7 +1276,6 @@ impl CryptoStore for SqliteStore { drop(connection); - self.load_inbound_group_sessions().await?; self.load_devices().await?; self.load_tracked_users().await?; @@ -1300,7 +1370,6 @@ impl CryptoStore for SqliteStore { for session in sessions { self.save_inbound_group_session_helper(account_id, &mut transaction, session) .await?; - self.inbound_group_sessions.add(session.clone()); } transaction.commit().await?; @@ -1315,12 +1384,12 @@ impl CryptoStore for SqliteStore { session_id: &str, ) -> Result> { Ok(self - .inbound_group_sessions - .get(room_id, sender_key, session_id)) + .load_inbound_group_session_helper(room_id, sender_key, session_id) + .await?) } async fn get_inbound_group_sessions(&self) -> Result> { - Ok(self.inbound_group_sessions.get_all()) + Ok(self.load_inbound_group_sessions().await?) } fn is_user_tracked(&self, user_id: &UserId) -> bool { @@ -1768,7 +1837,6 @@ mod test { .expect("Can't create store"); store.load_account().await.unwrap(); - store.load_inbound_group_sessions().await.unwrap(); let loaded_session = store .get_inbound_group_session(&session.room_id, &session.sender_key, session.session_id())