From 18b655f82914e3c9944602647e54dc90cd982551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Mon, 10 Aug 2020 15:55:08 +0200 Subject: [PATCH] crypto: Test the cancellation of timed out verifications. --- matrix_sdk_crypto/src/verification/machine.rs | 30 +++++++++++++++++-- matrix_sdk_crypto/src/verification/sas/mod.rs | 26 ++++++++++++++-- .../src/verification/sas/sas_state.rs | 5 ++++ 3 files changed, 56 insertions(+), 5 deletions(-) diff --git a/matrix_sdk_crypto/src/verification/machine.rs b/matrix_sdk_crypto/src/verification/machine.rs index 25bac2d2..5ec52d99 100644 --- a/matrix_sdk_crypto/src/verification/machine.rs +++ b/matrix_sdk_crypto/src/verification/machine.rs @@ -86,8 +86,9 @@ impl VerificationMachine { } pub fn garbage_collect(&self) { - self.verifications - .retain(|_, s| !(s.is_canceled() || s.is_done())); + // TODO this seems to have a deadlock. + // self.verifications + // .retain(|_, s| !(s.is_canceled() || s.is_done())); for sas in self.verifications.iter() { if let Some(r) = sas.cancel_if_timed_out() { @@ -170,7 +171,11 @@ impl VerificationMachine { #[cfg(test)] mod test { - use std::{convert::TryFrom, sync::Arc}; + use std::{ + convert::TryFrom, + sync::Arc, + time::{Duration, Instant}, + }; use matrix_sdk_common::{ events::AnyToDeviceEventContent, @@ -294,4 +299,23 @@ mod test { assert!(alice.is_done()); assert!(bob.is_done()); } + + #[tokio::test] + async fn timing_out() { + let (alice_machine, bob) = setup_verification_machine().await; + let alice = alice_machine.verifications.get(bob.flow_id()).unwrap(); + + assert!(!alice.timed_out()); + assert!(alice_machine.outgoing_to_device_messages.is_empty()); + + alice.set_creation_time( + Instant::now() + .checked_sub(Duration::from_secs(60 * 15)) + .unwrap(), + ); + assert!(alice.timed_out()); + assert!(alice_machine.outgoing_to_device_messages.is_empty()); + alice_machine.garbage_collect(); + assert!(!alice_machine.outgoing_to_device_messages.is_empty()); + } } diff --git a/matrix_sdk_crypto/src/verification/sas/mod.rs b/matrix_sdk_crypto/src/verification/sas/mod.rs index 25693d58..49c86cbf 100644 --- a/matrix_sdk_crypto/src/verification/sas/mod.rs +++ b/matrix_sdk_crypto/src/verification/sas/mod.rs @@ -15,6 +15,9 @@ mod helpers; mod sas_state; +#[cfg(test)] +use std::time::Instant; + use std::sync::{Arc, Mutex}; use tracing::{info, trace, warn}; @@ -79,6 +82,11 @@ impl Sas { &self.flow_id } + #[cfg(test)] + pub(crate) fn set_creation_time(&self, time: Instant) { + self.inner.lock().unwrap().set_creation_time(time) + } + /// Start a new SAS auth flow with the given device. /// /// # Arguments @@ -260,7 +268,7 @@ impl Sas { /// Has the SAS verification flow timed out. pub fn timed_out(&self) -> bool { - self.inner.lock().unwrap().is_timed_out() + self.inner.lock().unwrap().timed_out() } /// Are we in a state where we can show the short auth string. @@ -357,6 +365,20 @@ impl InnerSas { } } + #[cfg(test)] + fn set_creation_time(&mut self, time: Instant) { + match self { + InnerSas::Created(s) => s.set_creation_time(time), + InnerSas::Started(s) => s.set_creation_time(time), + InnerSas::Canceled(s) => s.set_creation_time(time), + InnerSas::Accepted(s) => s.set_creation_time(time), + InnerSas::KeyRecieved(s) => s.set_creation_time(time), + InnerSas::Confirmed(s) => s.set_creation_time(time), + InnerSas::MacReceived(s) => s.set_creation_time(time), + InnerSas::Done(s) => s.set_creation_time(time), + } + } + fn cancel(self, code: CancelCode) -> (InnerSas, Option) { let sas = match self { InnerSas::Created(s) => s.cancel(code), @@ -472,7 +494,7 @@ impl InnerSas { matches!(self, InnerSas::Canceled(_)) } - fn is_timed_out(&self) -> bool { + fn timed_out(&self) -> bool { match self { InnerSas::Created(s) => s.timed_out(), InnerSas::Started(s) => s.timed_out(), diff --git a/matrix_sdk_crypto/src/verification/sas/sas_state.rs b/matrix_sdk_crypto/src/verification/sas/sas_state.rs index a6b9e355..8e7afbd4 100644 --- a/matrix_sdk_crypto/src/verification/sas/sas_state.rs +++ b/matrix_sdk_crypto/src/verification/sas/sas_state.rs @@ -239,6 +239,11 @@ impl SasState { self.creation_time.elapsed() > MAX_AGE || self.last_event_time.elapsed() > MAX_EVENT_TIMEOUT } + #[cfg(test)] + pub fn set_creation_time(&mut self, time: Instant) { + self.creation_time = Arc::new(time); + } + fn check_event(&self, sender: &UserId, flow_id: &str) -> Result<(), CancelCode> { if flow_id != *self.verification_flow_id { Err(CancelCode::UnknownTransaction)