fix: wrong soft fail check, too many events in /sync state response
This commit is contained in:
		
							parent
							
								
									9f8c45c763
								
							
						
					
					
						commit
						9152b877a7
					
				
					 4 changed files with 51 additions and 36 deletions
				
			
		|  | @ -246,31 +246,13 @@ async fn sync_helper( | ||||||
|             .current_shortstatehash(&room_id)? |             .current_shortstatehash(&room_id)? | ||||||
|             .expect("All rooms have state"); |             .expect("All rooms have state"); | ||||||
| 
 | 
 | ||||||
|         let first_pdu_before_since = db |  | ||||||
|             .rooms |  | ||||||
|             .pdus_until(&sender_user, &room_id, since)? |  | ||||||
|             .next() |  | ||||||
|             .transpose()?; |  | ||||||
| 
 |  | ||||||
|         let pdus_after_since = db |         let pdus_after_since = db | ||||||
|             .rooms |             .rooms | ||||||
|             .pdus_after(&sender_user, &room_id, since)? |             .pdus_after(&sender_user, &room_id, since)? | ||||||
|             .next() |             .next() | ||||||
|             .is_some(); |             .is_some(); | ||||||
| 
 | 
 | ||||||
|         let since_shortstatehash = first_pdu_before_since |         let since_shortstatehash = db.rooms.get_token_shortstatehash(&room_id, since)?; | ||||||
|             .as_ref() |  | ||||||
|             .map(|pdu| { |  | ||||||
|                 db.rooms |  | ||||||
|                     .pdu_shortstatehash(&pdu.1.event_id) |  | ||||||
|                     .transpose() |  | ||||||
|                     .ok_or_else(|| { |  | ||||||
|                         warn!("PDU without state: {}", pdu.1.event_id); |  | ||||||
|                         Error::bad_database("Found PDU without state") |  | ||||||
|                     }) |  | ||||||
|             }) |  | ||||||
|             .transpose()? |  | ||||||
|             .transpose()?; |  | ||||||
| 
 | 
 | ||||||
|         // Calculates joined_member_count, invited_member_count and heroes
 |         // Calculates joined_member_count, invited_member_count and heroes
 | ||||||
|         let calculate_counts = || { |         let calculate_counts = || { | ||||||
|  | @ -359,7 +341,7 @@ async fn sync_helper( | ||||||
|                 true, |                 true, | ||||||
|                 state_events, |                 state_events, | ||||||
|             ) |             ) | ||||||
|         } else if !pdus_after_since || since_shortstatehash == Some(current_shortstatehash) { |         } else if !pdus_after_since && since_shortstatehash == Some(current_shortstatehash) { | ||||||
|             // No state changes
 |             // No state changes
 | ||||||
|             (Vec::new(), None, None, false, Vec::new()) |             (Vec::new(), None, None, false, Vec::new()) | ||||||
|         } else { |         } else { | ||||||
|  | @ -400,11 +382,6 @@ async fn sync_helper( | ||||||
|                 current_state_ids |                 current_state_ids | ||||||
|                     .iter() |                     .iter() | ||||||
|                     .filter(|(key, id)| since_state_ids.get(key) != Some(id)) |                     .filter(|(key, id)| since_state_ids.get(key) != Some(id)) | ||||||
|                     .filter(|(_, id)| { |  | ||||||
|                         !timeline_pdus |  | ||||||
|                             .iter() |  | ||||||
|                             .any(|(_, timeline_pdu)| timeline_pdu.event_id == **id) |  | ||||||
|                     }) |  | ||||||
|                     .map(|(_, id)| db.rooms.get_pdu(id)) |                     .map(|(_, id)| db.rooms.get_pdu(id)) | ||||||
|                     .filter_map(|r| r.ok().flatten()) |                     .filter_map(|r| r.ok().flatten()) | ||||||
|                     .collect() |                     .collect() | ||||||
|  | @ -585,6 +562,9 @@ async fn sync_helper( | ||||||
|             ); |             ); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         // Save the state after this sync so we can send the correct state diff next sync
 | ||||||
|  |         db.rooms.associate_token_shortstatehash(&room_id, next_batch, current_shortstatehash)?; | ||||||
|  | 
 | ||||||
|         let joined_room = sync_events::JoinedRoom { |         let joined_room = sync_events::JoinedRoom { | ||||||
|             account_data: sync_events::RoomAccountData { |             account_data: sync_events::RoomAccountData { | ||||||
|                 events: db |                 events: db | ||||||
|  |  | ||||||
|  | @ -271,6 +271,7 @@ impl Database { | ||||||
|                 shorteventid_eventid: builder.open_tree("shorteventid_eventid")?, |                 shorteventid_eventid: builder.open_tree("shorteventid_eventid")?, | ||||||
|                 shorteventid_shortstatehash: builder.open_tree("shorteventid_shortstatehash")?, |                 shorteventid_shortstatehash: builder.open_tree("shorteventid_shortstatehash")?, | ||||||
|                 roomid_shortstatehash: builder.open_tree("roomid_shortstatehash")?, |                 roomid_shortstatehash: builder.open_tree("roomid_shortstatehash")?, | ||||||
|  |                 roomsynctoken_shortstatehash: builder.open_tree("roomsynctoken_shortstatehash")?, | ||||||
|                 statehash_shortstatehash: builder.open_tree("statehash_shortstatehash")?, |                 statehash_shortstatehash: builder.open_tree("statehash_shortstatehash")?, | ||||||
| 
 | 
 | ||||||
|                 eventid_outlierpdu: builder.open_tree("eventid_outlierpdu")?, |                 eventid_outlierpdu: builder.open_tree("eventid_outlierpdu")?, | ||||||
|  |  | ||||||
|  | @ -69,6 +69,7 @@ pub struct Rooms { | ||||||
| 
 | 
 | ||||||
|     /// Remember the current state hash of a room.
 |     /// Remember the current state hash of a room.
 | ||||||
|     pub(super) roomid_shortstatehash: Arc<dyn Tree>, |     pub(super) roomid_shortstatehash: Arc<dyn Tree>, | ||||||
|  |     pub(super) roomsynctoken_shortstatehash: Arc<dyn Tree>, | ||||||
|     /// Remember the state hash at events in the past.
 |     /// Remember the state hash at events in the past.
 | ||||||
|     pub(super) shorteventid_shortstatehash: Arc<dyn Tree>, |     pub(super) shorteventid_shortstatehash: Arc<dyn Tree>, | ||||||
|     /// StateKey = EventType + StateKey, ShortStateKey = Count
 |     /// StateKey = EventType + StateKey, ShortStateKey = Count
 | ||||||
|  | @ -1800,6 +1801,38 @@ impl Rooms { | ||||||
|         Ok(()) |         Ok(()) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     pub fn associate_token_shortstatehash( | ||||||
|  |         &self, | ||||||
|  |         room_id: &RoomId, | ||||||
|  |         token: u64, | ||||||
|  |         shortstatehash: u64, | ||||||
|  |     ) -> Result<()> { | ||||||
|  |         let shortroomid = self.get_shortroomid(room_id)?.expect("room exists"); | ||||||
|  | 
 | ||||||
|  |         let mut key = shortroomid.to_be_bytes().to_vec(); | ||||||
|  |         key.extend_from_slice(&token.to_be_bytes()); | ||||||
|  | 
 | ||||||
|  |         self.roomsynctoken_shortstatehash | ||||||
|  |             .insert(&key, &shortstatehash.to_be_bytes()) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn get_token_shortstatehash(&self, room_id: &RoomId, token: u64) -> Result<Option<u64>> { | ||||||
|  |         let shortroomid = self.get_shortroomid(room_id)?.expect("room exists"); | ||||||
|  | 
 | ||||||
|  |         let mut key = shortroomid.to_be_bytes().to_vec(); | ||||||
|  |         key.extend_from_slice(&token.to_be_bytes()); | ||||||
|  | 
 | ||||||
|  |         Ok(self | ||||||
|  |             .roomsynctoken_shortstatehash | ||||||
|  |             .get(&key)? | ||||||
|  |             .map(|bytes| { | ||||||
|  |                 utils::u64_from_bytes(&bytes).map_err(|_| { | ||||||
|  |                     Error::bad_database("Invalid shortstatehash in roomsynctoken_shortstatehash") | ||||||
|  |                 }) | ||||||
|  |             }) | ||||||
|  |             .transpose()?) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /// Creates a new persisted data unit and adds it to a room.
 |     /// Creates a new persisted data unit and adds it to a room.
 | ||||||
|     #[tracing::instrument(skip(self, db, _mutex_lock))] |     #[tracing::instrument(skip(self, db, _mutex_lock))] | ||||||
|     pub fn build_and_append_pdu( |     pub fn build_and_append_pdu( | ||||||
|  |  | ||||||
|  | @ -1387,6 +1387,17 @@ async fn upgrade_outlier_to_timeline_pdu( | ||||||
|         .state_full_ids(current_sstatehash) |         .state_full_ids(current_sstatehash) | ||||||
|         .map_err(|_| "Failed to load room state.")?; |         .map_err(|_| "Failed to load room state.")?; | ||||||
| 
 | 
 | ||||||
|  |     let auth_events = db | ||||||
|  |         .rooms | ||||||
|  |         .get_auth_events( | ||||||
|  |             &room_id, | ||||||
|  |             &incoming_pdu.kind, | ||||||
|  |             &incoming_pdu.sender, | ||||||
|  |             incoming_pdu.state_key.as_deref(), | ||||||
|  |             &incoming_pdu.content, | ||||||
|  |         ) | ||||||
|  |         .map_err(|_| "Failed to get_auth_events.".to_owned())?; | ||||||
|  | 
 | ||||||
|     if incoming_pdu.state_key.is_some() { |     if incoming_pdu.state_key.is_some() { | ||||||
|         let mut extremity_sstatehashes = HashMap::new(); |         let mut extremity_sstatehashes = HashMap::new(); | ||||||
| 
 | 
 | ||||||
|  | @ -1541,18 +1552,8 @@ async fn upgrade_outlier_to_timeline_pdu( | ||||||
| 
 | 
 | ||||||
|     extremities.insert(incoming_pdu.event_id.clone()); |     extremities.insert(incoming_pdu.event_id.clone()); | ||||||
| 
 | 
 | ||||||
|     debug!("starting soft fail auth check"); |  | ||||||
|     // 13. Check if the event passes auth based on the "current state" of the room, if not "soft fail" it
 |     // 13. Check if the event passes auth based on the "current state" of the room, if not "soft fail" it
 | ||||||
|     let auth_events = db |     debug!("starting soft fail auth check"); | ||||||
|         .rooms |  | ||||||
|         .get_auth_events( |  | ||||||
|             &room_id, |  | ||||||
|             &incoming_pdu.kind, |  | ||||||
|             &incoming_pdu.sender, |  | ||||||
|             incoming_pdu.state_key.as_deref(), |  | ||||||
|             &incoming_pdu.content, |  | ||||||
|         ) |  | ||||||
|         .map_err(|_| "Failed to get_auth_events.".to_owned())?; |  | ||||||
| 
 | 
 | ||||||
|     let soft_fail = !state_res::event_auth::auth_check( |     let soft_fail = !state_res::event_auth::auth_check( | ||||||
|         &room_version, |         &room_version, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue