crypto: Add timestamps to the SAS struct so we can check if it timed out.
parent
81e9a7cefc
commit
87bcba3561
|
@ -15,6 +15,7 @@
|
||||||
use std::{
|
use std::{
|
||||||
mem,
|
mem,
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use olm_rs::{sas::OlmSas, utility::OlmUtility};
|
use olm_rs::{sas::OlmSas, utility::OlmUtility};
|
||||||
|
@ -52,6 +53,12 @@ const STRINGS: &[ShortAuthenticationString] = &[
|
||||||
ShortAuthenticationString::Emoji,
|
ShortAuthenticationString::Emoji,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// The max time a SAS flow can take from start to done.
|
||||||
|
const MAX_AGE: Duration = Duration::from_secs(60 * 5);
|
||||||
|
|
||||||
|
// The max time a SAS object will wait for a new event to arrive.
|
||||||
|
const MAX_EVENT_TIMEOUT: Duration = Duration::from_secs(60 * 1);
|
||||||
|
|
||||||
/// Struct containing the protocols that were agreed to be used for the SAS
|
/// Struct containing the protocols that were agreed to be used for the SAS
|
||||||
/// flow.
|
/// flow.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -101,13 +108,24 @@ impl Default for AcceptedProtocols {
|
||||||
pub struct SasState<S: Clone> {
|
pub struct SasState<S: Clone> {
|
||||||
/// The Olm SAS struct.
|
/// The Olm SAS struct.
|
||||||
inner: Arc<Mutex<OlmSas>>,
|
inner: Arc<Mutex<OlmSas>>,
|
||||||
|
|
||||||
/// Struct holding the identities that are doing the SAS dance.
|
/// Struct holding the identities that are doing the SAS dance.
|
||||||
ids: SasIds,
|
ids: SasIds,
|
||||||
|
|
||||||
|
/// The instant when the SAS object was created. If this more than
|
||||||
|
/// MAX_AGE seconds are elapsed, the event will be canceled with a
|
||||||
|
/// `CancelCode::Timeout`
|
||||||
|
creation_time: Arc<Instant>,
|
||||||
|
|
||||||
|
/// The instant the SAS object last received an event.
|
||||||
|
last_event_time: Arc<Instant>,
|
||||||
|
|
||||||
/// The unique identifier of this SAS flow.
|
/// The unique identifier of this SAS flow.
|
||||||
///
|
///
|
||||||
/// This will be the transaction id for to-device events and the relates_to
|
/// This will be the transaction id for to-device events and the relates_to
|
||||||
/// field for in-room events.
|
/// field for in-room events.
|
||||||
pub verification_flow_id: Arc<String>,
|
pub verification_flow_id: Arc<String>,
|
||||||
|
|
||||||
/// The SAS state we're in.
|
/// The SAS state we're in.
|
||||||
state: Arc<S>,
|
state: Arc<S>,
|
||||||
}
|
}
|
||||||
|
@ -209,12 +227,19 @@ impl<S: Clone> SasState<S> {
|
||||||
SasState {
|
SasState {
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
ids: self.ids,
|
ids: self.ids,
|
||||||
|
creation_time: self.creation_time,
|
||||||
|
last_event_time: self.last_event_time,
|
||||||
verification_flow_id: self.verification_flow_id,
|
verification_flow_id: self.verification_flow_id,
|
||||||
state: Arc::new(Canceled::new(cancel_code)),
|
state: Arc::new(Canceled::new(cancel_code)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_sender_and_txid(&self, sender: &UserId, flow_id: &str) -> Result<(), CancelCode> {
|
/// Did our SAS verification time out.
|
||||||
|
fn timed_out(&self) -> bool {
|
||||||
|
self.creation_time.elapsed() > MAX_AGE || self.last_event_time.elapsed() > MAX_EVENT_TIMEOUT
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
} else if sender != self.ids.other_device.user_id() {
|
} else if sender != self.ids.other_device.user_id() {
|
||||||
|
@ -244,6 +269,9 @@ impl SasState<Created> {
|
||||||
},
|
},
|
||||||
verification_flow_id: Arc::new(verification_flow_id),
|
verification_flow_id: Arc::new(verification_flow_id),
|
||||||
|
|
||||||
|
creation_time: Arc::new(Instant::now()),
|
||||||
|
last_event_time: Arc::new(Instant::now()),
|
||||||
|
|
||||||
state: Arc::new(Created {
|
state: Arc::new(Created {
|
||||||
protocol_definitions: MSasV1ContentInit {
|
protocol_definitions: MSasV1ContentInit {
|
||||||
short_authentication_string: STRINGS.to_vec(),
|
short_authentication_string: STRINGS.to_vec(),
|
||||||
|
@ -280,7 +308,7 @@ impl SasState<Created> {
|
||||||
self,
|
self,
|
||||||
event: &ToDeviceEvent<AcceptEventContent>,
|
event: &ToDeviceEvent<AcceptEventContent>,
|
||||||
) -> Result<SasState<Accepted>, SasState<Canceled>> {
|
) -> Result<SasState<Accepted>, SasState<Canceled>> {
|
||||||
self.check_sender_and_txid(&event.sender, &event.content.transaction_id)
|
self.check_event(&event.sender, &event.content.transaction_id)
|
||||||
.map_err(|c| self.clone().cancel(c))?;
|
.map_err(|c| self.clone().cancel(c))?;
|
||||||
|
|
||||||
if let AcceptMethod::MSasV1(content) = &event.content.method {
|
if let AcceptMethod::MSasV1(content) = &event.content.method {
|
||||||
|
@ -303,6 +331,8 @@ impl SasState<Created> {
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
ids: self.ids,
|
ids: self.ids,
|
||||||
verification_flow_id: self.verification_flow_id,
|
verification_flow_id: self.verification_flow_id,
|
||||||
|
creation_time: self.creation_time,
|
||||||
|
last_event_time: self.last_event_time,
|
||||||
state: Arc::new(Accepted {
|
state: Arc::new(Accepted {
|
||||||
json_start_content,
|
json_start_content,
|
||||||
commitment: content.commitment.clone(),
|
commitment: content.commitment.clone(),
|
||||||
|
@ -351,6 +381,9 @@ impl SasState<Started> {
|
||||||
other_device,
|
other_device,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
creation_time: Arc::new(Instant::now()),
|
||||||
|
last_event_time: Arc::new(Instant::now()),
|
||||||
|
|
||||||
verification_flow_id: Arc::new(event.content.transaction_id.clone()),
|
verification_flow_id: Arc::new(event.content.transaction_id.clone()),
|
||||||
|
|
||||||
state: Arc::new(Started {
|
state: Arc::new(Started {
|
||||||
|
@ -381,6 +414,9 @@ impl SasState<Started> {
|
||||||
Err(SasState {
|
Err(SasState {
|
||||||
inner: Arc::new(Mutex::new(OlmSas::new())),
|
inner: Arc::new(Mutex::new(OlmSas::new())),
|
||||||
|
|
||||||
|
creation_time: Arc::new(Instant::now()),
|
||||||
|
last_event_time: Arc::new(Instant::now()),
|
||||||
|
|
||||||
ids: SasIds {
|
ids: SasIds {
|
||||||
account,
|
account,
|
||||||
other_device,
|
other_device,
|
||||||
|
@ -433,7 +469,7 @@ impl SasState<Started> {
|
||||||
self,
|
self,
|
||||||
event: &mut ToDeviceEvent<KeyEventContent>,
|
event: &mut ToDeviceEvent<KeyEventContent>,
|
||||||
) -> Result<SasState<KeyReceived>, SasState<Canceled>> {
|
) -> Result<SasState<KeyReceived>, SasState<Canceled>> {
|
||||||
self.check_sender_and_txid(&event.sender, &event.content.transaction_id)
|
self.check_event(&event.sender, &event.content.transaction_id)
|
||||||
.map_err(|c| self.clone().cancel(c))?;
|
.map_err(|c| self.clone().cancel(c))?;
|
||||||
|
|
||||||
let accepted_protocols = AcceptedProtocols::default();
|
let accepted_protocols = AcceptedProtocols::default();
|
||||||
|
@ -450,6 +486,8 @@ impl SasState<Started> {
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
ids: self.ids,
|
ids: self.ids,
|
||||||
verification_flow_id: self.verification_flow_id,
|
verification_flow_id: self.verification_flow_id,
|
||||||
|
creation_time: self.creation_time,
|
||||||
|
last_event_time: self.last_event_time,
|
||||||
state: Arc::new(KeyReceived {
|
state: Arc::new(KeyReceived {
|
||||||
we_started: false,
|
we_started: false,
|
||||||
their_pubkey,
|
their_pubkey,
|
||||||
|
@ -472,7 +510,7 @@ impl SasState<Accepted> {
|
||||||
self,
|
self,
|
||||||
event: &mut ToDeviceEvent<KeyEventContent>,
|
event: &mut ToDeviceEvent<KeyEventContent>,
|
||||||
) -> Result<SasState<KeyReceived>, SasState<Canceled>> {
|
) -> Result<SasState<KeyReceived>, SasState<Canceled>> {
|
||||||
self.check_sender_and_txid(&event.sender, &event.content.transaction_id)
|
self.check_event(&event.sender, &event.content.transaction_id)
|
||||||
.map_err(|c| self.clone().cancel(c))?;
|
.map_err(|c| self.clone().cancel(c))?;
|
||||||
|
|
||||||
let utility = OlmUtility::new();
|
let utility = OlmUtility::new();
|
||||||
|
@ -496,6 +534,8 @@ impl SasState<Accepted> {
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
ids: self.ids,
|
ids: self.ids,
|
||||||
verification_flow_id: self.verification_flow_id,
|
verification_flow_id: self.verification_flow_id,
|
||||||
|
creation_time: self.creation_time,
|
||||||
|
last_event_time: self.last_event_time,
|
||||||
state: Arc::new(KeyReceived {
|
state: Arc::new(KeyReceived {
|
||||||
their_pubkey,
|
their_pubkey,
|
||||||
we_started: true,
|
we_started: true,
|
||||||
|
@ -567,7 +607,7 @@ impl SasState<KeyReceived> {
|
||||||
self,
|
self,
|
||||||
event: &ToDeviceEvent<MacEventContent>,
|
event: &ToDeviceEvent<MacEventContent>,
|
||||||
) -> Result<SasState<MacReceived>, SasState<Canceled>> {
|
) -> Result<SasState<MacReceived>, SasState<Canceled>> {
|
||||||
self.check_sender_and_txid(&event.sender, &event.content.transaction_id)
|
self.check_event(&event.sender, &event.content.transaction_id)
|
||||||
.map_err(|c| self.clone().cancel(c))?;
|
.map_err(|c| self.clone().cancel(c))?;
|
||||||
|
|
||||||
let (devices, master_keys) = receive_mac_event(
|
let (devices, master_keys) = receive_mac_event(
|
||||||
|
@ -581,6 +621,8 @@ impl SasState<KeyReceived> {
|
||||||
Ok(SasState {
|
Ok(SasState {
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
verification_flow_id: self.verification_flow_id,
|
verification_flow_id: self.verification_flow_id,
|
||||||
|
creation_time: self.creation_time,
|
||||||
|
last_event_time: self.last_event_time,
|
||||||
ids: self.ids,
|
ids: self.ids,
|
||||||
state: Arc::new(MacReceived {
|
state: Arc::new(MacReceived {
|
||||||
we_started: self.state.we_started,
|
we_started: self.state.we_started,
|
||||||
|
@ -599,6 +641,8 @@ impl SasState<KeyReceived> {
|
||||||
SasState {
|
SasState {
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
verification_flow_id: self.verification_flow_id,
|
verification_flow_id: self.verification_flow_id,
|
||||||
|
creation_time: self.creation_time,
|
||||||
|
last_event_time: self.last_event_time,
|
||||||
ids: self.ids,
|
ids: self.ids,
|
||||||
state: Arc::new(Confirmed {
|
state: Arc::new(Confirmed {
|
||||||
accepted_protocols: self.state.accepted_protocols.clone(),
|
accepted_protocols: self.state.accepted_protocols.clone(),
|
||||||
|
@ -619,7 +663,7 @@ impl SasState<Confirmed> {
|
||||||
self,
|
self,
|
||||||
event: &ToDeviceEvent<MacEventContent>,
|
event: &ToDeviceEvent<MacEventContent>,
|
||||||
) -> Result<SasState<Done>, SasState<Canceled>> {
|
) -> Result<SasState<Done>, SasState<Canceled>> {
|
||||||
self.check_sender_and_txid(&event.sender, &event.content.transaction_id)
|
self.check_event(&event.sender, &event.content.transaction_id)
|
||||||
.map_err(|c| self.clone().cancel(c))?;
|
.map_err(|c| self.clone().cancel(c))?;
|
||||||
|
|
||||||
let (devices, master_keys) = receive_mac_event(
|
let (devices, master_keys) = receive_mac_event(
|
||||||
|
@ -632,6 +676,8 @@ impl SasState<Confirmed> {
|
||||||
|
|
||||||
Ok(SasState {
|
Ok(SasState {
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
|
creation_time: self.creation_time,
|
||||||
|
last_event_time: self.last_event_time,
|
||||||
verification_flow_id: self.verification_flow_id,
|
verification_flow_id: self.verification_flow_id,
|
||||||
ids: self.ids,
|
ids: self.ids,
|
||||||
|
|
||||||
|
@ -663,6 +709,8 @@ impl SasState<MacReceived> {
|
||||||
SasState {
|
SasState {
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
verification_flow_id: self.verification_flow_id,
|
verification_flow_id: self.verification_flow_id,
|
||||||
|
creation_time: self.creation_time,
|
||||||
|
last_event_time: self.last_event_time,
|
||||||
ids: self.ids,
|
ids: self.ids,
|
||||||
state: Arc::new(Done {
|
state: Arc::new(Done {
|
||||||
verified_devices: self.state.verified_devices.clone(),
|
verified_devices: self.state.verified_devices.clone(),
|
||||||
|
|
Loading…
Reference in New Issue