diff --git a/matrix_sdk/src/client.rs b/matrix_sdk/src/client.rs index 3d695be4..d3c94028 100644 --- a/matrix_sdk/src/client.rs +++ b/matrix_sdk/src/client.rs @@ -45,7 +45,7 @@ use matrix_sdk_base::{BaseClient, BaseClientConfig, Room, Session, StateStore}; #[cfg(feature = "encryption")] use matrix_sdk_base::crypto::{ decrypt_key_export, encrypt_key_export, olm::InboundGroupSession, store::CryptoStoreError, - AttachmentEncryptor, OutgoingRequests, ToDeviceRequest, + AttachmentEncryptor, OutgoingRequests, RoomMessageRequest, ToDeviceRequest, }; /// Enum controlling if a loop running callbacks should continue or abort. @@ -1160,6 +1160,17 @@ impl Client { Ok(()) } + async fn room_send_helper( + &self, + request: &RoomMessageRequest, + ) -> Result { + let content = request.content.clone(); + let txn_id = request.txn_id.into(); + let room_id = &request.room_id; + + self.room_send(&room_id, content, Some(txn_id)).await + } + /// Send a room message to the homeserver. /// /// Returns the parsed response from the server. @@ -1458,7 +1469,10 @@ impl Client { } #[cfg(feature = "encryption")] - async fn send_to_device(&self, request: &ToDeviceRequest) -> Result { + pub(crate) async fn send_to_device( + &self, + request: &ToDeviceRequest, + ) -> Result { let txn_id_string = request.txn_id_string(); let request = RumaToDeviceRequest::new( request.event_type.clone(), @@ -1737,6 +1751,14 @@ impl Client { .unwrap(); } } + OutgoingRequests::RoomMessage(request) => { + if let Ok(resp) = self.room_send_helper(request).await { + self.base_client + .mark_request_as_sent(&r.request_id(), &resp) + .await + .unwrap(); + } + } } } } @@ -1891,7 +1913,7 @@ impl Client { .await .map(|sas| Sas { inner: sas, - http_client: self.http_client.clone(), + client: self.clone(), }) } @@ -1953,7 +1975,7 @@ impl Client { Ok(device.map(|d| Device { inner: d, - http_client: self.http_client.clone(), + client: self.clone(), })) } @@ -2070,7 +2092,7 @@ impl Client { Ok(UserDevices { inner: devices, - http_client: self.http_client.clone(), + client: self.clone(), }) } diff --git a/matrix_sdk/src/device.rs b/matrix_sdk/src/device.rs index 776b9f0e..39274896 100644 --- a/matrix_sdk/src/device.rs +++ b/matrix_sdk/src/device.rs @@ -18,18 +18,15 @@ use matrix_sdk_base::crypto::{ store::CryptoStoreError, Device as BaseDevice, LocalTrust, ReadOnlyDevice, UserDevices as BaseUserDevices, }; -use matrix_sdk_common::{ - api::r0::to_device::send_event_to_device::Request as ToDeviceRequest, - identifiers::{DeviceId, DeviceIdBox}, -}; +use matrix_sdk_common::identifiers::{DeviceId, DeviceIdBox}; -use crate::{error::Result, http_client::HttpClient, Sas}; +use crate::{error::Result, Client, Sas}; #[derive(Clone, Debug)] /// A device represents a E2EE capable client of an user. pub struct Device { pub(crate) inner: BaseDevice, - pub(crate) http_client: HttpClient, + pub(crate) client: Client, } impl Deref for Device { @@ -66,14 +63,11 @@ impl Device { /// ``` pub async fn start_verification(&self) -> Result { let (sas, request) = self.inner.start_verification().await?; - let txn_id_string = request.txn_id_string(); - let request = ToDeviceRequest::new(request.event_type, &txn_id_string, request.messages); - - self.http_client.send(request).await?; + self.client.send_to_device(&request).await?; Ok(Sas { inner: sas, - http_client: self.http_client.clone(), + client: self.client.clone(), }) } @@ -102,7 +96,7 @@ impl Device { #[derive(Debug)] pub struct UserDevices { pub(crate) inner: BaseUserDevices, - pub(crate) http_client: HttpClient, + pub(crate) client: Client, } impl UserDevices { @@ -110,7 +104,7 @@ impl UserDevices { pub fn get(&self, device_id: &DeviceId) -> Option { self.inner.get(device_id).map(|d| Device { inner: d, - http_client: self.http_client.clone(), + client: self.client.clone(), }) } @@ -121,11 +115,11 @@ impl UserDevices { /// Iterator over all the devices of the user devices. pub fn devices(&self) -> impl Iterator + '_ { - let client = self.http_client.clone(); + let client = self.client.clone(); self.inner.devices().map(move |d| Device { inner: d, - http_client: client.clone(), + client: client.clone(), }) } } diff --git a/matrix_sdk/src/sas.rs b/matrix_sdk/src/sas.rs index 3db1df47..16da6156 100644 --- a/matrix_sdk/src/sas.rs +++ b/matrix_sdk/src/sas.rs @@ -12,26 +12,27 @@ // See the License for the specific language governing permissions and // limitations under the License. -use matrix_sdk_base::crypto::{ReadOnlyDevice, Sas as BaseSas}; -use matrix_sdk_common::api::r0::to_device::send_event_to_device::Request as ToDeviceRequest; +use matrix_sdk_base::crypto::{OutgoingVerificationRequest, ReadOnlyDevice, Sas as BaseSas}; -use crate::{error::Result, http_client::HttpClient}; +use crate::{error::Result, Client}; /// An object controling the interactive verification flow. #[derive(Debug, Clone)] pub struct Sas { pub(crate) inner: BaseSas, - pub(crate) http_client: HttpClient, + pub(crate) client: Client, } impl Sas { /// Accept the interactive verification flow. pub async fn accept(&self) -> Result<()> { if let Some(req) = self.inner.accept() { - let txn_id_string = req.txn_id_string(); - let request = ToDeviceRequest::new(req.event_type, &txn_id_string, req.messages); - - self.http_client.send(request).await?; + match req { + OutgoingVerificationRequest::ToDevice(r) => { + self.client.send_to_device(&r).await?; + } + OutgoingVerificationRequest::InRoom(_) => todo!(), + } } Ok(()) } @@ -40,15 +41,12 @@ impl Sas { pub async fn confirm(&self) -> Result<()> { let (to_device, signature) = self.inner.confirm().await?; - if let Some(req) = to_device { - let txn_id_string = req.txn_id_string(); - let request = ToDeviceRequest::new(req.event_type, &txn_id_string, req.messages); - - self.http_client.send(request).await?; + if let Some(request) = to_device { + self.client.send_to_device(&request).await?; } if let Some(s) = signature { - self.http_client.send(s).await?; + self.client.send(s).await?; } Ok(()) @@ -56,12 +54,10 @@ impl Sas { /// Cancel the interactive verification flow. pub async fn cancel(&self) -> Result<()> { - if let Some(req) = self.inner.cancel() { - let txn_id_string = req.txn_id_string(); - let request = ToDeviceRequest::new(req.event_type, &txn_id_string, req.messages); - - self.http_client.send(request).await?; + if let Some(request) = self.inner.cancel() { + self.client.send_to_device(&request).await?; } + Ok(()) } diff --git a/matrix_sdk_crypto/src/identities/device.rs b/matrix_sdk_crypto/src/identities/device.rs index 705b90be..377a7d45 100644 --- a/matrix_sdk_crypto/src/identities/device.rs +++ b/matrix_sdk_crypto/src/identities/device.rs @@ -42,7 +42,7 @@ use tracing::warn; use crate::{ olm::{InboundGroupSession, PrivateCrossSigningIdentity, Session}, store::{Changes, DeviceChanges}, - OutgoingRequest, OutgoingRequests, + OutgoingRequest, OutgoingRequests, OutgoingVerificationRequest, }; #[cfg(test)] use crate::{OlmMachine, ReadOnlyAccount}; @@ -97,7 +97,7 @@ impl Device { .start_sas(self.inner.clone()) .await?; - if let OutgoingRequests::ToDeviceRequest(r) = request { + if let OutgoingVerificationRequest::ToDevice(r) = request { Ok((sas, r)) } else { panic!("Invalid verification request type"); diff --git a/matrix_sdk_crypto/src/lib.rs b/matrix_sdk_crypto/src/lib.rs index fd31a94a..e4262e3c 100644 --- a/matrix_sdk_crypto/src/lib.rs +++ b/matrix_sdk_crypto/src/lib.rs @@ -51,6 +51,7 @@ pub use machine::OlmMachine; pub use olm::EncryptionSettings; pub(crate) use olm::ReadOnlyAccount; pub use requests::{ - IncomingResponse, KeysQueryRequest, OutgoingRequest, OutgoingRequests, ToDeviceRequest, + IncomingResponse, KeysQueryRequest, OutgoingRequest, OutgoingRequests, + OutgoingVerificationRequest, RoomMessageRequest, ToDeviceRequest, }; pub use verification::{Sas, VerificationRequest}; diff --git a/matrix_sdk_crypto/src/machine.rs b/matrix_sdk_crypto/src/machine.rs index f4755f4d..585962a2 100644 --- a/matrix_sdk_crypto/src/machine.rs +++ b/matrix_sdk_crypto/src/machine.rs @@ -322,6 +322,7 @@ impl OlmMachine { } requests.append(&mut self.outgoing_to_device_requests()); + requests.append(&mut self.verification_machine.outgoing_room_message_requests()); requests.append(&mut self.key_request_machine.outgoing_to_device_requests()); requests @@ -360,6 +361,9 @@ impl OlmMachine { IncomingResponse::SignatureUpload(_) => { self.verification_machine.mark_request_as_sent(request_id); } + IncomingResponse::RoomMessage(_) => { + self.verification_machine.mark_request_as_sent(request_id); + } }; Ok(()) diff --git a/matrix_sdk_crypto/src/requests.rs b/matrix_sdk_crypto/src/requests.rs index fb619018..97cd4e89 100644 --- a/matrix_sdk_crypto/src/requests.rs +++ b/matrix_sdk_crypto/src/requests.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#![allow(missing_docs)] + use std::{collections::BTreeMap, sync::Arc, time::Duration}; use matrix_sdk_common::{ @@ -26,10 +28,11 @@ use matrix_sdk_common::{ upload_signing_keys::Response as SigningKeysUploadResponse, CrossSigningKey, }, + message::send_message_event::Response as RoomMessageResponse, to_device::{send_event_to_device::Response as ToDeviceResponse, DeviceIdOrAllDevices}, }, - events::EventType, - identifiers::{DeviceIdBox, UserId}, + events::{AnyMessageEventContent, EventType}, + identifiers::{DeviceIdBox, RoomId, UserId}, uuid::Uuid, }; @@ -120,6 +123,7 @@ pub enum OutgoingRequests { /// Signature upload request, this request is used after a successful device /// or user verification is done. SignatureUpload(SignatureUploadRequest), + RoomMessage(RoomMessageRequest), } #[cfg(test)] @@ -150,6 +154,12 @@ impl From for OutgoingRequests { } } +impl From for OutgoingRequests { + fn from(request: RoomMessageRequest) -> Self { + OutgoingRequests::RoomMessage(request) + } +} + impl From for OutgoingRequests { fn from(request: SignatureUploadRequest) -> Self { OutgoingRequests::SignatureUpload(request) @@ -176,6 +186,7 @@ pub enum IncomingResponse<'a> { /// The cross signing keys upload response, marking our private cross /// signing identity as shared. SignatureUpload(&'a SignatureUploadResponse), + RoomMessage(&'a RoomMessageResponse), } impl<'a> From<&'a KeysUploadResponse> for IncomingResponse<'a> { @@ -196,6 +207,12 @@ impl<'a> From<&'a ToDeviceResponse> for IncomingResponse<'a> { } } +impl<'a> From<&'a RoomMessageResponse> for IncomingResponse<'a> { + fn from(response: &'a RoomMessageResponse) -> Self { + IncomingResponse::RoomMessage(response) + } +} + impl<'a> From<&'a KeysClaimResponse> for IncomingResponse<'a> { fn from(response: &'a KeysClaimResponse) -> Self { IncomingResponse::KeysClaim(response) @@ -230,3 +247,55 @@ impl OutgoingRequest { &self.request } } + +#[derive(Clone, Debug)] +pub struct RoomMessageRequest { + /// The room to send the event to. + pub room_id: RoomId, + + /// The transaction ID for this event. + /// + /// Clients should generate an ID unique across requests with the + /// same access token; it will be used by the server to ensure + /// idempotency of requests. + pub txn_id: Uuid, + + /// The event content to send. + pub content: AnyMessageEventContent, +} + +#[derive(Clone, Debug)] +pub enum OutgoingVerificationRequest { + ToDevice(ToDeviceRequest), + InRoom(RoomMessageRequest), +} + +impl OutgoingVerificationRequest { + pub fn request_id(&self) -> Uuid { + match self { + OutgoingVerificationRequest::ToDevice(t) => t.txn_id, + OutgoingVerificationRequest::InRoom(r) => r.txn_id, + } + } +} + +impl From for OutgoingVerificationRequest { + fn from(r: ToDeviceRequest) -> Self { + OutgoingVerificationRequest::ToDevice(r) + } +} + +impl From for OutgoingVerificationRequest { + fn from(r: RoomMessageRequest) -> Self { + OutgoingVerificationRequest::InRoom(r) + } +} + +impl From for OutgoingRequests { + fn from(request: OutgoingVerificationRequest) -> Self { + match request { + OutgoingVerificationRequest::ToDevice(r) => OutgoingRequests::ToDeviceRequest(r), + OutgoingVerificationRequest::InRoom(r) => OutgoingRequests::RoomMessage(r), + } + } +} diff --git a/matrix_sdk_crypto/src/verification/machine.rs b/matrix_sdk_crypto/src/verification/machine.rs index ad2e49f3..b2bace8b 100644 --- a/matrix_sdk_crypto/src/verification/machine.rs +++ b/matrix_sdk_crypto/src/verification/machine.rs @@ -37,7 +37,8 @@ use crate::{ olm::PrivateCrossSigningIdentity, requests::{OutgoingRequest, ToDeviceRequest}, store::{CryptoStore, CryptoStoreError}, - OutgoingRequests, ReadOnlyAccount, ReadOnlyDevice, + OutgoingRequests, OutgoingVerificationRequest, ReadOnlyAccount, ReadOnlyDevice, + RoomMessageRequest, }; #[derive(Clone, Debug)] @@ -49,6 +50,7 @@ pub struct VerificationMachine { room_verifications: Arc>, requests: Arc>, outgoing_to_device_messages: Arc>, + outgoing_room_messages: Arc>, } impl VerificationMachine { @@ -65,13 +67,14 @@ impl VerificationMachine { requests: DashMap::new().into(), outgoing_to_device_messages: DashMap::new().into(), room_verifications: DashMap::new().into(), + outgoing_room_messages: DashMap::new().into(), } } pub async fn start_sas( &self, device: ReadOnlyDevice, - ) -> Result<(Sas, OutgoingRequests), CryptoStoreError> { + ) -> Result<(Sas, OutgoingVerificationRequest), CryptoStoreError> { let identity = self.store.get_user_identity(device.user_id()).await?; let private_identity = self.private_identity.lock().await.clone(); @@ -83,8 +86,13 @@ impl VerificationMachine { identity, ); - let request: OutgoingRequests = match content { - OutgoingContent::Room(c) => todo!(), + let request = match content { + OutgoingContent::Room(r, c) => RoomMessageRequest { + room_id: r, + txn_id: Uuid::new_v4(), + content: c, + } + .into(), OutgoingContent::ToDevice(c) => { let request = content_to_request(device.user_id(), device.device_id(), c); @@ -127,7 +135,23 @@ impl VerificationMachine { self.outgoing_to_device_messages.insert(request_id, request); } - OutgoingContent::Room(c) => todo!(), + OutgoingContent::Room(r, c) => { + let request_id = Uuid::new_v4(); + + let request = OutgoingRequest { + request: Arc::new( + RoomMessageRequest { + room_id: r, + txn_id: request_id.clone(), + content: c, + } + .into(), + ), + request_id, + }; + + self.outgoing_room_messages.insert(request_id, request); + } } } @@ -138,9 +162,17 @@ impl VerificationMachine { } pub fn mark_request_as_sent(&self, uuid: &Uuid) { + self.outgoing_room_messages.remove(uuid); self.outgoing_to_device_messages.remove(uuid); } + pub fn outgoing_room_message_requests(&self) -> Vec { + self.outgoing_room_messages + .iter() + .map(|r| (*r).clone()) + .collect() + } + pub fn outgoing_to_device_requests(&self) -> Vec { #[allow(clippy::map_clone)] self.outgoing_to_device_messages @@ -215,9 +247,23 @@ impl VerificationMachine { Ok(s) => { // TODO we need to queue up the accept event // here. - let accept_event = s.accept(); + info!( + "Started a new SAS verification, \ + automatically accepting because of in-room" + ); + + let accept_request = s.accept().unwrap(); + self.room_verifications .insert(e.content.relation.event_id.clone(), s); + + self.outgoing_room_messages.insert( + accept_request.request_id(), + OutgoingRequest { + request_id: accept_request.request_id(), + request: Arc::new(accept_request.into()), + }, + ); } Err(c) => { warn!( diff --git a/matrix_sdk_crypto/src/verification/requests.rs b/matrix_sdk_crypto/src/verification/requests.rs index ffffa55e..c7f9d950 100644 --- a/matrix_sdk_crypto/src/verification/requests.rs +++ b/matrix_sdk_crypto/src/verification/requests.rs @@ -93,13 +93,15 @@ impl VerificationRequest { ) -> Result { match &*self.inner.lock().unwrap() { InnerRequest::Ready(s) => s.into_started_sas( - event, + &event.clone().into_full_event(self.room_id().clone()), self.store.clone(), self.account.clone(), self.private_cross_signing_identity.clone(), device, user_identity, ), + // TODO cancel here since we got a missmatched message or do + // nothing? _ => todo!(), } } @@ -128,7 +130,7 @@ impl InnerRequest { fn into_started_sas( &mut self, - event: &SyncMessageEvent, + event: &MessageEvent, store: Arc>, account: ReadOnlyAccount, private_identity: PrivateCrossSigningIdentity, @@ -299,7 +301,7 @@ struct Ready { impl RequestState { fn into_started_sas( &self, - event: &SyncMessageEvent, + event: &MessageEvent, store: Arc>, account: ReadOnlyAccount, private_identity: PrivateCrossSigningIdentity, @@ -312,7 +314,7 @@ impl RequestState { other_device, store, &event.sender, - event.content.clone(), + (event.room_id.clone(), event.content.clone()), other_identity, ) } @@ -325,13 +327,14 @@ impl RequestState { other_device: ReadOnlyDevice, other_identity: Option, ) -> (Sas, OutgoingContent) { - Sas::start( - account, - private_identity, - other_device, - store, - other_identity, - ) + todo!() + // Sas::start_in_room( + // account, + // private_identity, + // other_device, + // store, + // other_identity, + // ) } } diff --git a/matrix_sdk_crypto/src/verification/sas/event_enums.rs b/matrix_sdk_crypto/src/verification/sas/event_enums.rs index 830b2939..7d9d3f7c 100644 --- a/matrix_sdk_crypto/src/verification/sas/event_enums.rs +++ b/matrix_sdk_crypto/src/verification/sas/event_enums.rs @@ -19,11 +19,13 @@ use std::convert::TryInto; use matrix_sdk_common::{ events::{ key::verification::{ + accept::{AcceptEventContent, AcceptToDeviceEventContent}, start::{StartEventContent, StartMethod, StartToDeviceEventContent}, KeyAgreementProtocol, }, AnyMessageEventContent, AnyToDeviceEventContent, MessageEvent, ToDeviceEvent, }, + identifiers::RoomId, CanonicalJsonValue, }; @@ -32,28 +34,28 @@ use super::FlowId; #[derive(Clone, Debug)] pub enum StartContent { ToDevice(StartToDeviceEventContent), - Room(StartEventContent), + Room(RoomId, StartEventContent), } impl StartContent { pub fn method(&self) -> &StartMethod { match self { StartContent::ToDevice(c) => &c.method, - StartContent::Room(c) => &c.method, + StartContent::Room(_, c) => &c.method, } } pub fn flow_id(&self) -> FlowId { match self { StartContent::ToDevice(c) => FlowId::ToDevice(c.transaction_id.clone()), - StartContent::Room(c) => FlowId::InRoom(c.relation.event_id.clone()), + StartContent::Room(r, c) => FlowId::InRoom(r.clone(), c.relation.event_id.clone()), } } pub fn to_canonical_json(self) -> CanonicalJsonValue { let content = match self { - StartContent::Room(c) => serde_json::to_value(c), StartContent::ToDevice(c) => serde_json::to_value(c), + StartContent::Room(_, c) => serde_json::to_value(c), }; content @@ -63,9 +65,9 @@ impl StartContent { } } -impl From for StartContent { - fn from(content: StartEventContent) -> Self { - StartContent::Room(content) +impl From<(RoomId, StartEventContent)> for StartContent { + fn from(tuple: (RoomId, StartEventContent)) -> Self { + StartContent::Room(tuple.0, tuple.1) } } @@ -75,16 +77,34 @@ impl From for StartContent { } } +#[derive(Clone, Debug)] +pub enum AcceptContent { + ToDevice(AcceptToDeviceEventContent), + Room(RoomId, AcceptEventContent), +} + +impl From for AcceptContent { + fn from(content: AcceptToDeviceEventContent) -> Self { + AcceptContent::ToDevice(content) + } +} + +impl From<(RoomId, AcceptEventContent)> for AcceptContent { + fn from(content: (RoomId, AcceptEventContent)) -> Self { + AcceptContent::Room(content.0, content.1) + } +} + #[derive(Clone, Debug)] pub enum OutgoingContent { - Room(AnyMessageEventContent), + Room(RoomId, AnyMessageEventContent), ToDevice(AnyToDeviceEventContent), } impl From for OutgoingContent { fn from(content: StartContent) -> Self { match content { - StartContent::Room(c) => AnyMessageEventContent::KeyVerificationStart(c).into(), + StartContent::Room(r, c) => (r, AnyMessageEventContent::KeyVerificationStart(c)).into(), StartContent::ToDevice(c) => AnyToDeviceEventContent::KeyVerificationStart(c).into(), } } @@ -96,8 +116,8 @@ impl From for OutgoingContent { } } -impl From for OutgoingContent { - fn from(content: AnyMessageEventContent) -> Self { - OutgoingContent::Room(content) +impl From<(RoomId, AnyMessageEventContent)> for OutgoingContent { + fn from(content: (RoomId, AnyMessageEventContent)) -> Self { + OutgoingContent::Room(content.0, content.1) } } diff --git a/matrix_sdk_crypto/src/verification/sas/inner_sas.rs b/matrix_sdk_crypto/src/verification/sas/inner_sas.rs index cf2a2476..1db06ab2 100644 --- a/matrix_sdk_crypto/src/verification/sas/inner_sas.rs +++ b/matrix_sdk_crypto/src/verification/sas/inner_sas.rs @@ -27,7 +27,7 @@ use matrix_sdk_common::{ }, AnyToDeviceEvent, AnyToDeviceEventContent, MessageEvent, ToDeviceEvent, }, - identifiers::{EventId, UserId}, + identifiers::{EventId, RoomId, UserId}, }; use crate::{ @@ -36,7 +36,7 @@ use crate::{ }; use super::{ - event_enums::OutgoingContent, + event_enums::{AcceptContent, OutgoingContent}, sas_state::{ Accepted, Canceled, Confirmed, Created, Done, FlowId, KeyReceived, MacReceived, SasState, Started, @@ -69,11 +69,18 @@ impl InnerSas { pub fn start_in_room( event_id: EventId, + room_id: RoomId, account: ReadOnlyAccount, other_device: ReadOnlyDevice, other_identity: Option, ) -> (InnerSas, OutgoingContent) { - let sas = SasState::::new_in_room(event_id, account, other_device, other_identity); + let sas = SasState::::new_in_room( + room_id, + event_id, + account, + other_device, + other_identity, + ); let content = sas.as_content(); (InnerSas::Created(sas), content) } @@ -97,7 +104,7 @@ impl InnerSas { } } - pub fn accept(&self) -> Option { + pub fn accept(&self) -> Option { if let InnerSas::Started(s) = self { Some(s.as_content()) } else { diff --git a/matrix_sdk_crypto/src/verification/sas/mod.rs b/matrix_sdk_crypto/src/verification/sas/mod.rs index 590f0de7..0e17d5e5 100644 --- a/matrix_sdk_crypto/src/verification/sas/mod.rs +++ b/matrix_sdk_crypto/src/verification/sas/mod.rs @@ -20,6 +20,7 @@ mod sas_state; #[cfg(test)] use std::time::Instant; +use event_enums::AcceptContent; use std::sync::{Arc, Mutex}; use tracing::{error, info, trace, warn}; @@ -30,15 +31,18 @@ use matrix_sdk_common::{ cancel::CancelCode, start::{StartEventContent, StartToDeviceEventContent}, }, - AnyToDeviceEvent, AnyToDeviceEventContent, MessageEvent, ToDeviceEvent, + AnyMessageEventContent, AnyToDeviceEvent, AnyToDeviceEventContent, MessageEvent, + ToDeviceEvent, }, identifiers::{DeviceId, EventId, RoomId, UserId}, + uuid::Uuid, }; use crate::{ error::SignatureError, identities::{LocalTrust, ReadOnlyDevice, UserIdentities}, olm::PrivateCrossSigningIdentity, + requests::{OutgoingVerificationRequest, RoomMessageRequest}, store::{Changes, CryptoStore, CryptoStoreError, DeviceChanges}, ReadOnlyAccount, ToDeviceRequest, }; @@ -189,6 +193,7 @@ impl Sas { ) -> (Sas, OutgoingContent) { let (inner, content) = InnerSas::start_in_room( flow_id, + room_id, account.clone(), other_device.clone(), other_identity.clone(), @@ -249,10 +254,18 @@ impl Sas { /// /// This does nothing if the verification was already accepted, otherwise it /// returns an `AcceptEventContent` that needs to be sent out. - pub fn accept(&self) -> Option { - self.inner.lock().unwrap().accept().map(|c| { - let content = AnyToDeviceEventContent::KeyVerificationAccept(c); - self.content_to_request(content) + pub fn accept(&self) -> Option { + self.inner.lock().unwrap().accept().map(|c| match c { + AcceptContent::ToDevice(c) => { + let content = AnyToDeviceEventContent::KeyVerificationAccept(c); + self.content_to_request(content).into() + } + AcceptContent::Room(room_id, content) => RoomMessageRequest { + room_id, + txn_id: Uuid::new_v4(), + content: AnyMessageEventContent::KeyVerificationAccept(content), + } + .into(), }) } diff --git a/matrix_sdk_crypto/src/verification/sas/sas_state.rs b/matrix_sdk_crypto/src/verification/sas/sas_state.rs index 3f1d7373..2ae05e32 100644 --- a/matrix_sdk_crypto/src/verification/sas/sas_state.rs +++ b/matrix_sdk_crypto/src/verification/sas/sas_state.rs @@ -14,6 +14,7 @@ use std::{ convert::TryFrom, + matches, sync::{Arc, Mutex}, time::{Duration, Instant}, }; @@ -24,8 +25,8 @@ use matrix_sdk_common::{ events::{ key::verification::{ accept::{ - AcceptMethod, AcceptToDeviceEventContent, MSasV1Content as AcceptV1Content, - MSasV1ContentInit as AcceptV1ContentInit, + AcceptEventContent, AcceptMethod, AcceptToDeviceEventContent, + MSasV1Content as AcceptV1Content, MSasV1ContentInit as AcceptV1ContentInit, }, cancel::{CancelCode, CancelToDeviceEventContent}, key::KeyToDeviceEventContent, @@ -39,13 +40,13 @@ use matrix_sdk_common::{ }, AnyMessageEventContent, AnyToDeviceEventContent, MessageEvent, ToDeviceEvent, }, - identifiers::{DeviceId, EventId, UserId}, + identifiers::{DeviceId, EventId, RoomId, UserId}, uuid::Uuid, }; use tracing::error; use super::{ - event_enums::{OutgoingContent, StartContent}, + event_enums::{AcceptContent, OutgoingContent, StartContent}, helpers::{ calculate_commitment, get_decimal, get_emoji, get_mac_content, receive_mac_event, SasIds, }, @@ -74,20 +75,28 @@ const MAX_EVENT_TIMEOUT: Duration = Duration::from_secs(60); #[derive(Clone, Debug)] pub enum FlowId { ToDevice(String), - InRoom(EventId), + InRoom(RoomId, EventId), } impl FlowId { + pub fn room_id(&self) -> Option<&RoomId> { + if let FlowId::InRoom(r, _) = &self { + Some(r) + } else { + None + } + } + pub fn to_string(&self) -> String { match self { - FlowId::InRoom(r) => r.to_string(), + FlowId::InRoom(_, r) => r.to_string(), FlowId::ToDevice(t) => t.to_string(), } } pub fn as_str(&self) -> &str { match self { - FlowId::InRoom(r) => r.as_str(), + FlowId::InRoom(_, r) => r.as_str(), FlowId::ToDevice(t) => t.as_str(), } } @@ -340,12 +349,13 @@ impl SasState { /// /// * `other_identity` - The identity of the other user if one exists. pub fn new_in_room( + room_id: RoomId, event_id: EventId, account: ReadOnlyAccount, other_device: ReadOnlyDevice, other_identity: Option, ) -> SasState { - let flow_id = FlowId::InRoom(event_id); + let flow_id = FlowId::InRoom(room_id, event_id); Self::new_helper(flow_id, account, other_device, other_identity) } @@ -380,7 +390,7 @@ impl SasState { pub fn as_start_content(&self) -> StartContent { match self.verification_flow_id.as_ref() { - FlowId::ToDevice(s) => StartContent::ToDevice(StartToDeviceEventContent { + FlowId::ToDevice(_) => StartContent::ToDevice(StartToDeviceEventContent { transaction_id: self.verification_flow_id.to_string(), from_device: self.device_id().into(), method: StartMethod::MSasV1( @@ -388,16 +398,19 @@ impl SasState { .expect("Invalid initial protocol definitions."), ), }), - FlowId::InRoom(e) => StartContent::Room(StartEventContent { - from_device: self.device_id().into(), - method: StartMethod::MSasV1( - MSasV1Content::new(self.state.protocol_definitions.clone()) - .expect("Invalid initial protocol definitions."), - ), - relation: Relation { - event_id: e.clone(), + FlowId::InRoom(r, e) => StartContent::Room( + r.clone(), + StartEventContent { + from_device: self.device_id().into(), + method: StartMethod::MSasV1( + MSasV1Content::new(self.state.protocol_definitions.clone()) + .expect("Invalid initial protocol definitions."), + ), + relation: Relation { + event_id: e.clone(), + }, }, - }), + ), } } @@ -558,25 +571,40 @@ impl SasState { /// This should be sent out automatically if the SAS verification flow has /// been started because of a /// m.key.verification.request -> m.key.verification.ready flow. - pub fn as_content(&self) -> AcceptToDeviceEventContent { + pub fn as_content(&self) -> AcceptContent { let accepted_protocols = AcceptedProtocols::default(); - AcceptToDeviceEventContent { - transaction_id: self.verification_flow_id.to_string(), - method: AcceptMethod::MSasV1( - AcceptV1ContentInit { - commitment: self.state.commitment.clone(), - hash: accepted_protocols.hash, - key_agreement_protocol: accepted_protocols.key_agreement_protocol, - message_authentication_code: accepted_protocols.message_auth_code, - short_authentication_string: self - .state - .protocol_definitions - .short_authentication_string - .clone(), - } + let method = AcceptMethod::MSasV1( + AcceptV1ContentInit { + commitment: self.state.commitment.clone(), + hash: accepted_protocols.hash, + key_agreement_protocol: accepted_protocols.key_agreement_protocol, + message_authentication_code: accepted_protocols.message_auth_code, + short_authentication_string: self + .state + .protocol_definitions + .short_authentication_string + .clone(), + } + .into(), + ); + + match self.verification_flow_id.as_ref() { + FlowId::ToDevice(_) => AcceptToDeviceEventContent { + transaction_id: self.verification_flow_id.to_string(), + method, + } + .into(), + FlowId::InRoom(r, e) => ( + r.clone(), + AcceptEventContent { + method, + relation: Relation { + event_id: e.clone(), + }, + }, + ) .into(), - ), } } @@ -676,7 +704,7 @@ impl SasState { transaction_id: s.to_string(), key: self.inner.lock().unwrap().public_key(), }, - FlowId::InRoom(r) => { + FlowId::InRoom(_, r) => { todo!("In-room verifications aren't implemented") } }