crypto: Test the cancellation of timed out verifications.

master
Damir Jelić 2020-08-10 15:55:08 +02:00
parent e2e70d6583
commit 18b655f829
3 changed files with 56 additions and 5 deletions

View File

@ -86,8 +86,9 @@ impl VerificationMachine {
} }
pub fn garbage_collect(&self) { pub fn garbage_collect(&self) {
self.verifications // TODO this seems to have a deadlock.
.retain(|_, s| !(s.is_canceled() || s.is_done())); // self.verifications
// .retain(|_, s| !(s.is_canceled() || s.is_done()));
for sas in self.verifications.iter() { for sas in self.verifications.iter() {
if let Some(r) = sas.cancel_if_timed_out() { if let Some(r) = sas.cancel_if_timed_out() {
@ -170,7 +171,11 @@ impl VerificationMachine {
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std::{convert::TryFrom, sync::Arc}; use std::{
convert::TryFrom,
sync::Arc,
time::{Duration, Instant},
};
use matrix_sdk_common::{ use matrix_sdk_common::{
events::AnyToDeviceEventContent, events::AnyToDeviceEventContent,
@ -294,4 +299,23 @@ mod test {
assert!(alice.is_done()); assert!(alice.is_done());
assert!(bob.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());
}
} }

View File

@ -15,6 +15,9 @@
mod helpers; mod helpers;
mod sas_state; mod sas_state;
#[cfg(test)]
use std::time::Instant;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use tracing::{info, trace, warn}; use tracing::{info, trace, warn};
@ -79,6 +82,11 @@ impl Sas {
&self.flow_id &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. /// Start a new SAS auth flow with the given device.
/// ///
/// # Arguments /// # Arguments
@ -260,7 +268,7 @@ impl Sas {
/// Has the SAS verification flow timed out. /// Has the SAS verification flow timed out.
pub fn timed_out(&self) -> bool { 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. /// 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<AnyToDeviceEventContent>) { fn cancel(self, code: CancelCode) -> (InnerSas, Option<AnyToDeviceEventContent>) {
let sas = match self { let sas = match self {
InnerSas::Created(s) => s.cancel(code), InnerSas::Created(s) => s.cancel(code),
@ -472,7 +494,7 @@ impl InnerSas {
matches!(self, InnerSas::Canceled(_)) matches!(self, InnerSas::Canceled(_))
} }
fn is_timed_out(&self) -> bool { fn timed_out(&self) -> bool {
match self { match self {
InnerSas::Created(s) => s.timed_out(), InnerSas::Created(s) => s.timed_out(),
InnerSas::Started(s) => s.timed_out(), InnerSas::Started(s) => s.timed_out(),

View File

@ -239,6 +239,11 @@ impl<S: Clone> SasState<S> {
self.creation_time.elapsed() > MAX_AGE || self.last_event_time.elapsed() > MAX_EVENT_TIMEOUT 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> { fn check_event(&self, sender: &UserId, flow_id: &str) -> Result<(), CancelCode> {
if flow_id != *self.verification_flow_id { if flow_id != *self.verification_flow_id {
Err(CancelCode::UnknownTransaction) Err(CancelCode::UnknownTransaction)