diff --git a/matrix_sdk/src/sas.rs b/matrix_sdk/src/sas.rs index 389633f7..01d548fe 100644 --- a/matrix_sdk/src/sas.rs +++ b/matrix_sdk/src/sas.rs @@ -12,7 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -use matrix_sdk_base::crypto::{OutgoingVerificationRequest, ReadOnlyDevice, Sas as BaseSas}; +use matrix_sdk_base::crypto::{ + AcceptSettings, OutgoingVerificationRequest, ReadOnlyDevice, Sas as BaseSas, +}; use crate::{error::Result, Client}; @@ -26,7 +28,29 @@ pub struct Sas { impl Sas { /// Accept the interactive verification flow. pub async fn accept(&self) -> Result<()> { - if let Some(req) = self.inner.accept() { + self.accept_with_settings(Default::default()).await + } + + /// Accept the interactive verification flow with specific settings. + /// + /// # Arguments + /// + /// * `settings` - specific customizations to the verification flow. + /// + /// # Examples + /// + /// ```ignore + /// use matrix_sdk::Sas; + /// use matrix_sdk_base::crypto::AcceptSettings; + /// use matrix_sdk::events::key::verification::ShortAuthenticationString; + /// + /// let only_decimal = AcceptSettings::with_allowed_methods( + /// vec![ShortAuthenticationString::Decimal] + /// ); + /// sas.accept_with_settings(only_decimal); + /// ``` + pub async fn accept_with_settings(&self, settings: AcceptSettings) -> Result<()> { + if let Some(req) = self.inner.accept_with_settings(settings) { match req { OutgoingVerificationRequest::ToDevice(r) => { self.client.send_to_device(&r).await?; diff --git a/matrix_sdk_crypto/src/lib.rs b/matrix_sdk_crypto/src/lib.rs index e5fcfad3..96dde71a 100644 --- a/matrix_sdk_crypto/src/lib.rs +++ b/matrix_sdk_crypto/src/lib.rs @@ -55,4 +55,4 @@ pub use requests::{ OutgoingVerificationRequest, RoomMessageRequest, ToDeviceRequest, }; pub use store::CryptoStoreError; -pub use verification::{Sas, VerificationRequest}; +pub use verification::{AcceptSettings, Sas, VerificationRequest}; diff --git a/matrix_sdk_crypto/src/verification/mod.rs b/matrix_sdk_crypto/src/verification/mod.rs index eeed8de5..c642dd21 100644 --- a/matrix_sdk_crypto/src/verification/mod.rs +++ b/matrix_sdk_crypto/src/verification/mod.rs @@ -18,7 +18,7 @@ mod sas; pub use machine::VerificationMachine; pub use requests::VerificationRequest; -pub use sas::{Sas, VerificationResult}; +pub use sas::{AcceptSettings, Sas, VerificationResult}; #[cfg(test)] pub(crate) mod test { diff --git a/matrix_sdk_crypto/src/verification/sas/mod.rs b/matrix_sdk_crypto/src/verification/sas/mod.rs index 22445fa0..12b5f161 100644 --- a/matrix_sdk_crypto/src/verification/sas/mod.rs +++ b/matrix_sdk_crypto/src/verification/sas/mod.rs @@ -27,8 +27,12 @@ use tracing::{error, info, trace, warn}; use matrix_sdk_common::{ api::r0::keys::upload_signatures::Request as SignatureUploadRequest, events::{ - key::verification::cancel::CancelCode, AnyMessageEvent, AnyMessageEventContent, - AnyToDeviceEvent, AnyToDeviceEventContent, + key::verification::{ + accept::{AcceptEventContent, AcceptMethod, AcceptToDeviceEventContent}, + cancel::CancelCode, + ShortAuthenticationString, + }, + AnyMessageEvent, AnyMessageEventContent, AnyToDeviceEvent, AnyToDeviceEventContent, }, identifiers::{DeviceId, EventId, RoomId, UserId}, uuid::Uuid, @@ -253,18 +257,35 @@ 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| 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(), - }) + self.accept_with_settings(Default::default()) + } + + /// Accept the SAS verification customizing the accept method. + /// + /// This does nothing if the verification was already accepted, otherwise it + /// returns an `AcceptEventContent` that needs to be sent out. + /// + /// Specify a function modifying the attributes of the accept request. + pub fn accept_with_settings( + &self, + settings: AcceptSettings, + ) -> Option { + self.inner + .lock() + .unwrap() + .accept() + .map(|c| match settings.apply(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(), + }) } /// Confirm the Sas verification. @@ -654,6 +675,58 @@ impl Sas { } } +/// Customize the accept-reply for a verification process +#[derive(Debug)] +pub struct AcceptSettings { + allowed_methods: Vec, +} + +impl Default for AcceptSettings { + /// All methods are allowed + fn default() -> Self { + Self { + allowed_methods: vec![ + ShortAuthenticationString::Decimal, + ShortAuthenticationString::Emoji, + ], + } + } +} + +impl AcceptSettings { + /// Create settings restricting the allowed SAS methods + /// + /// # Arguments + /// + /// * `methods` - The methods this client allows at most + pub fn with_allowed_methods(methods: Vec) -> Self { + Self { + allowed_methods: methods, + } + } + + fn apply(self, mut content: AcceptContent) -> AcceptContent { + match &mut content { + AcceptContent::ToDevice(AcceptToDeviceEventContent { + method: AcceptMethod::MSasV1(c), + .. + }) + | AcceptContent::Room( + _, + AcceptEventContent { + method: AcceptMethod::MSasV1(c), + .. + }, + ) => { + c.short_authentication_string + .retain(|sas| self.allowed_methods.contains(sas)); + content + } + _ => content, + } + } +} + #[cfg(test)] mod test { use std::{convert::TryFrom, sync::Arc};