crypto: Return a deserialized ToDevice struct when we receive a sync

master
Damir Jelić 2021-01-19 12:59:31 +01:00
parent 6a30514d40
commit 17f3dbb0a0
5 changed files with 53 additions and 32 deletions

View File

@ -27,6 +27,7 @@ use std::{
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
use dashmap::DashMap; use dashmap::DashMap;
#[cfg(feature = "encryption")]
use futures::TryStreamExt; use futures::TryStreamExt;
use futures_timer::Delay as sleep; use futures_timer::Delay as sleep;
use http::HeaderValue; use http::HeaderValue;
@ -121,7 +122,6 @@ use matrix_sdk_common::{
use crate::{ use crate::{
http_client::{client_with_config, HttpClient, HttpSend}, http_client::{client_with_config, HttpClient, HttpSend},
verification_request::VerificationRequest,
Error, OutgoingRequest, Result, Error, OutgoingRequest, Result,
}; };
@ -130,6 +130,7 @@ use crate::{
device::{Device, UserDevices}, device::{Device, UserDevices},
identifiers::DeviceId, identifiers::DeviceId,
sas::Sas, sas::Sas,
verification_request::VerificationRequest,
}; };
const DEFAULT_SYNC_TIMEOUT: Duration = Duration::from_secs(30); const DEFAULT_SYNC_TIMEOUT: Duration = Duration::from_secs(30);
@ -1176,6 +1177,7 @@ impl Client {
Ok(()) Ok(())
} }
#[cfg(feature = "encryption")]
pub(crate) async fn room_send_helper( pub(crate) async fn room_send_helper(
&self, &self,
request: &RoomMessageRequest, request: &RoomMessageRequest,
@ -1270,6 +1272,7 @@ impl Client {
.unwrap_or(false) .unwrap_or(false)
} }
#[cfg(feature = "encryption")]
async fn are_members_synced(&self, room_id: &RoomId) -> bool { async fn are_members_synced(&self, room_id: &RoomId) -> bool {
self.base_client self.base_client
.get_room(room_id) .get_room(room_id)

View File

@ -24,10 +24,13 @@ use std::{
}; };
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
use futures::StreamExt; use futures::{StreamExt, TryStreamExt};
use futures::TryStreamExt;
use matrix_sdk_common::{ use matrix_sdk_common::{
api::r0 as api, api::r0 as api,
deserialized_responses::{
AccountData, Ephemeral, InviteState, InvitedRoom, JoinedRoom, LeftRoom, MemberEvent,
Presence, Rooms, State, StrippedMemberEvent, SyncResponse, Timeline,
},
events::{ events::{
presence::PresenceEvent, presence::PresenceEvent,
room::member::{MemberEventContent, MembershipState}, room::member::{MemberEventContent, MembershipState},
@ -41,10 +44,6 @@ use matrix_sdk_common::{
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
use matrix_sdk_common::{ use matrix_sdk_common::{
api::r0::keys::claim_keys::Request as KeysClaimRequest, api::r0::keys::claim_keys::Request as KeysClaimRequest,
deserialized_responses::{
AccountData, Ephemeral, InviteState, InvitedRoom, JoinedRoom, LeftRoom, MemberEvent,
Presence, Rooms, State, StrippedMemberEvent, SyncResponse, Timeline,
},
events::{room::encrypted::EncryptedEventContent, AnyMessageEventContent, AnySyncMessageEvent}, events::{room::encrypted::EncryptedEventContent, AnyMessageEventContent, AnySyncMessageEvent},
identifiers::DeviceId, identifiers::DeviceId,
locks::Mutex, locks::Mutex,
@ -675,7 +674,7 @@ impl BaseClient {
/// * `response` - The response that we received after a successful sync. /// * `response` - The response that we received after a successful sync.
pub async fn receive_sync_response( pub async fn receive_sync_response(
&self, &self,
mut response: api::sync::sync_events::Response, response: api::sync::sync_events::Response,
) -> Result<SyncResponse> { ) -> Result<SyncResponse> {
// The server might respond multiple times with the same sync token, in // The server might respond multiple times with the same sync token, in
// that case we already received this response and there's nothing to // that case we already received this response and there's nothing to
@ -687,7 +686,7 @@ impl BaseClient {
let now = SystemTime::now(); let now = SystemTime::now();
#[cfg(feature = "encryption")] #[cfg(feature = "encryption")]
{ let to_device = {
let olm = self.olm.lock().await; let olm = self.olm.lock().await;
if let Some(o) = &*olm { if let Some(o) = &*olm {
@ -695,9 +694,25 @@ impl BaseClient {
// decryptes to-device events, but leaves room events alone. // decryptes to-device events, but leaves room events alone.
// This makes sure that we have the deryption keys for the room // This makes sure that we have the deryption keys for the room
// events at hand. // events at hand.
o.receive_sync_response(&mut response).await?; o.receive_sync_response(&response).await?
} else {
response
.to_device
.events
.into_iter()
.filter_map(|e| e.deserialize().ok())
.collect::<Vec<AnyToDeviceEvent>>()
.into()
} }
} };
#[cfg(not(feature = "encryption"))]
let to_device = response
.to_device
.events
.into_iter()
.filter_map(|e| e.deserialize().ok())
.collect::<Vec<AnyToDeviceEvent>>()
.into();
let mut changes = StateChanges::new(response.next_batch.clone()); let mut changes = StateChanges::new(response.next_batch.clone());
let mut rooms = Rooms::default(); let mut rooms = Rooms::default();
@ -868,13 +883,7 @@ impl BaseClient {
account_data: AccountData { account_data: AccountData {
events: changes.account_data.into_iter().map(|(_, e)| e).collect(), events: changes.account_data.into_iter().map(|(_, e)| e).collect(),
}, },
to_device: response to_device,
.to_device
.events
.into_iter()
.filter_map(|e| e.deserialize().ok())
.collect::<Vec<AnyToDeviceEvent>>()
.into(),
device_lists: response.device_lists, device_lists: response.device_lists,
device_one_time_keys_count: response device_one_time_keys_count: response
.device_one_time_keys_count .device_one_time_keys_count

View File

@ -36,7 +36,6 @@ use matrix_sdk_common::{
}, },
identifiers::{DeviceId, DeviceIdBox, EventEncryptionAlgorithm, RoomId, UserId}, identifiers::{DeviceId, DeviceIdBox, EventEncryptionAlgorithm, RoomId, UserId},
uuid::Uuid, uuid::Uuid,
Raw,
}; };
use crate::{ use crate::{
@ -623,8 +622,7 @@ impl KeyRequestMachine {
&self, &self,
sender_key: &str, sender_key: &str,
event: &mut ToDeviceEvent<ForwardedRoomKeyToDeviceEventContent>, event: &mut ToDeviceEvent<ForwardedRoomKeyToDeviceEventContent>,
) -> Result<(Option<Raw<AnyToDeviceEvent>>, Option<InboundGroupSession>), CryptoStoreError> ) -> Result<(Option<AnyToDeviceEvent>, Option<InboundGroupSession>), CryptoStoreError> {
{
let key_info = self.get_key_info(&event.content).await?; let key_info = self.get_key_info(&event.content).await?;
if let Some(info) = key_info { if let Some(info) = key_info {
@ -658,7 +656,7 @@ impl KeyRequestMachine {
}; };
Ok(( Ok((
Some(Raw::from(AnyToDeviceEvent::ForwardedRoomKey(event.clone()))), Some(AnyToDeviceEvent::ForwardedRoomKey(event.clone())),
session, session,
)) ))
} else { } else {

View File

@ -30,6 +30,7 @@ use matrix_sdk_common::{
sync::sync_events::Response as SyncResponse, sync::sync_events::Response as SyncResponse,
}, },
assign, assign,
deserialized_responses::ToDevice,
events::{ events::{
room::encrypted::EncryptedEventContent, room_key::RoomKeyEventContent, room::encrypted::EncryptedEventContent, room_key::RoomKeyEventContent,
AnyMessageEventContent, AnySyncRoomEvent, AnyToDeviceEvent, SyncMessageEvent, AnyMessageEventContent, AnySyncRoomEvent, AnyToDeviceEvent, SyncMessageEvent,
@ -573,7 +574,7 @@ impl OlmMachine {
// don't want them to be able to do silly things with it. Handling // don't want them to be able to do silly things with it. Handling
// events modifies them and returns a modified one, so replace it // events modifies them and returns a modified one, so replace it
// here if we get one. // here if we get one.
decrypted.event = event; decrypted.deserialized_event = Some(event);
decrypted.inbound_group_session = group_session; decrypted.inbound_group_session = group_session;
} }
@ -586,7 +587,7 @@ impl OlmMachine {
sender_key: &str, sender_key: &str,
signing_key: &str, signing_key: &str,
event: &mut ToDeviceEvent<RoomKeyEventContent>, event: &mut ToDeviceEvent<RoomKeyEventContent>,
) -> OlmResult<(Option<Raw<AnyToDeviceEvent>>, Option<InboundGroupSession>)> { ) -> OlmResult<(Option<AnyToDeviceEvent>, Option<InboundGroupSession>)> {
match event.content.algorithm { match event.content.algorithm {
EventEncryptionAlgorithm::MegolmV1AesSha2 => { EventEncryptionAlgorithm::MegolmV1AesSha2 => {
let session_key = GroupSessionKey(mem::take(&mut event.content.session_key)); let session_key = GroupSessionKey(mem::take(&mut event.content.session_key));
@ -597,7 +598,7 @@ impl OlmMachine {
&event.content.room_id, &event.content.room_id,
session_key, session_key,
)?; )?;
let event = Raw::from(AnyToDeviceEvent::RoomKey(event.clone())); let event = AnyToDeviceEvent::RoomKey(event.clone());
Ok((Some(event), Some(session))) Ok((Some(event), Some(session)))
} }
_ => { _ => {
@ -697,7 +698,7 @@ impl OlmMachine {
async fn handle_decrypted_to_device_event( async fn handle_decrypted_to_device_event(
&self, &self,
decrypted: &OlmDecryptionInfo, decrypted: &OlmDecryptionInfo,
) -> OlmResult<(Option<Raw<AnyToDeviceEvent>>, Option<InboundGroupSession>)> { ) -> OlmResult<(Option<AnyToDeviceEvent>, Option<InboundGroupSession>)> {
let event = match decrypted.event.deserialize() { let event = match decrypted.event.deserialize() {
Ok(e) => e, Ok(e) => e,
Err(e) => { Err(e) => {
@ -719,7 +720,7 @@ impl OlmMachine {
.await?), .await?),
_ => { _ => {
warn!("Received an unexpected encrypted to-device event"); warn!("Received an unexpected encrypted to-device event");
Ok((None, None)) Ok((Some(event), None))
} }
} }
} }
@ -774,7 +775,7 @@ impl OlmMachine {
/// * `response` - The sync latest sync response. /// * `response` - The sync latest sync response.
/// ///
/// [`decrypt_room_event`]: #method.decrypt_room_event /// [`decrypt_room_event`]: #method.decrypt_room_event
pub async fn receive_sync_response(&self, response: &mut SyncResponse) -> OlmResult<()> { pub async fn receive_sync_response(&self, response: &SyncResponse) -> OlmResult<ToDevice> {
// Remove verification objects that have expired or are done. // Remove verification objects that have expired or are done.
self.verification_machine.garbage_collect(); self.verification_machine.garbage_collect();
@ -794,7 +795,9 @@ impl OlmMachine {
} }
} }
for event_result in &mut response.to_device.events { let mut events = Vec::new();
for event_result in &response.to_device.events {
let mut event = if let Ok(e) = event_result.deserialize() { let mut event = if let Ok(e) = event_result.deserialize() {
e e
} else { } else {
@ -849,7 +852,9 @@ impl OlmMachine {
changes.inbound_group_sessions.push(group_session); changes.inbound_group_sessions.push(group_session);
} }
*event_result = decrypted.event; if let Some(e) = decrypted.deserialized_event {
event = e;
}
} }
AnyToDeviceEvent::RoomKeyRequest(e) => { AnyToDeviceEvent::RoomKeyRequest(e) => {
self.key_request_machine.receive_incoming_key_request(e) self.key_request_machine.receive_incoming_key_request(e)
@ -864,6 +869,8 @@ impl OlmMachine {
} }
_ => continue, _ => continue,
} }
events.push(event);
} }
let changed_sessions = self let changed_sessions = self
@ -873,7 +880,9 @@ impl OlmMachine {
changes.sessions.extend(changed_sessions); changes.sessions.extend(changed_sessions);
Ok(self.store.save_changes(changes).await?) self.store.save_changes(changes).await?;
Ok(ToDevice { events })
} }
/// Decrypt an event from a room timeline. /// Decrypt an event from a room timeline.
@ -1661,7 +1670,7 @@ pub(crate) mod test {
.save_inbound_group_sessions(&[decrypted.inbound_group_session.unwrap()]) .save_inbound_group_sessions(&[decrypted.inbound_group_session.unwrap()])
.await .await
.unwrap(); .unwrap();
let event = decrypted.event.deserialize().unwrap(); let event = decrypted.deserialized_event.unwrap();
if let AnyToDeviceEvent::RoomKey(event) = event { if let AnyToDeviceEvent::RoomKey(event) = event {
assert_eq!(&event.sender, alice.user_id()); assert_eq!(&event.sender, alice.user_id());

View File

@ -91,6 +91,7 @@ impl SessionType {
pub struct OlmDecryptionInfo { pub struct OlmDecryptionInfo {
pub session: SessionType, pub session: SessionType,
pub message_hash: OlmMessageHash, pub message_hash: OlmMessageHash,
pub deserialized_event: Option<AnyToDeviceEvent>,
pub event: Raw<AnyToDeviceEvent>, pub event: Raw<AnyToDeviceEvent>,
pub signing_key: String, pub signing_key: String,
pub sender_key: String, pub sender_key: String,
@ -179,6 +180,7 @@ impl Account {
message_hash, message_hash,
event, event,
signing_key, signing_key,
deserialized_event: None,
sender_key: content.sender_key.clone(), sender_key: content.sender_key.clone(),
inbound_group_session: None, inbound_group_session: None,
}) })