crypto: Remember who cancelled the verification

This seems to be of limited use considering that people can just see the
sender of the cancellation event or they perform the cancellation
themselves using the cancel() method but EA seems to want this.
master
Damir Jelić 2021-06-25 12:54:00 +02:00
parent d4e80883dc
commit af084528c8
6 changed files with 64 additions and 42 deletions

View File

@ -167,12 +167,13 @@ impl Done {
#[derive(Clone, Debug)]
pub struct Cancelled {
cancelled_by_us: bool,
cancel_code: CancelCode,
reason: &'static str,
}
impl Cancelled {
fn new(code: CancelCode) -> Self {
fn new(cancelled_by_us: bool, code: CancelCode) -> Self {
let reason = match code {
CancelCode::Accepted => {
"A m.key.verification.request was accepted by a different device."
@ -192,7 +193,7 @@ impl Cancelled {
_ => "Unknown cancel reason",
};
Self { cancel_code: code, reason }
Self { cancelled_by_us, cancel_code: code, reason }
}
pub fn as_content(&self, flow_id: &FlowId) -> OutgoingContent {

View File

@ -210,7 +210,7 @@ impl QrVerification {
}
fn cancel_with_code(&self, code: CancelCode) -> Option<OutgoingContent> {
let new_state = QrState::<Cancelled>::new(code);
let new_state = QrState::<Cancelled>::new(true, code);
let content = new_state.as_content(self.flow_id());
let mut state = self.state.lock().unwrap();
@ -243,7 +243,7 @@ impl QrVerification {
match self.identities.mark_as_done(Some(&devices), Some(&identities)).await? {
VerificationResult::Ok => (None, None),
VerificationResult::Cancel(c) => {
let canceled = QrState::<Cancelled>::new(c);
let canceled = QrState::<Cancelled>::new(false, c);
let content = canceled.as_content(self.flow_id());
new_state = InnerState::Cancelled(canceled);
(Some(content), None)
@ -594,8 +594,8 @@ impl QrState<Scanned> {
}
impl QrState<Cancelled> {
fn new(cancel_code: CancelCode) -> Self {
QrState { state: Cancelled::new(cancel_code) }
fn new(cancelled_by_us: bool, cancel_code: CancelCode) -> Self {
QrState { state: Cancelled::new(cancelled_by_us, cancel_code) }
}
fn as_content(&self, flow_id: &FlowId) -> OutgoingContent {
@ -614,10 +614,10 @@ impl QrState<Created> {
if self.state.secret == m.secret {
Ok(QrState { state: Scanned {} })
} else {
Err(QrState::<Cancelled>::new(CancelCode::KeyMismatch))
Err(QrState::<Cancelled>::new(false, CancelCode::KeyMismatch))
}
}
_ => Err(QrState::<Cancelled>::new(CancelCode::UnknownMethod)),
_ => Err(QrState::<Cancelled>::new(false, CancelCode::UnknownMethod)),
}
}
}

View File

@ -376,7 +376,7 @@ impl VerificationRequest {
/// Cancel the verification request
pub fn cancel(&self) -> Option<OutgoingVerificationRequest> {
let mut inner = self.inner.lock().unwrap();
inner.cancel(&CancelCode::User);
inner.cancel(true, &CancelCode::User);
let content = if let InnerRequest::Cancelled(c) = &*inner {
Some(c.state.as_content(self.flow_id()))
@ -436,7 +436,7 @@ impl VerificationRequest {
pub(crate) fn receive_cancel(&self, sender: &UserId, content: &CancelContent<'_>) {
if sender == self.other_user() {
let mut inner = self.inner.lock().unwrap().clone();
inner.cancel(content.cancel_code());
inner.cancel(false, content.cancel_code());
}
}
@ -539,12 +539,12 @@ impl InnerRequest {
})
}
fn cancel(&mut self, cancel_code: &CancelCode) {
fn cancel(&mut self, cancelled_by_us: bool, cancel_code: &CancelCode) {
*self = InnerRequest::Cancelled(match self {
InnerRequest::Created(s) => s.clone().into_canceled(cancel_code),
InnerRequest::Requested(s) => s.clone().into_canceled(cancel_code),
InnerRequest::Ready(s) => s.clone().into_canceled(cancel_code),
InnerRequest::Passive(s) => s.clone().into_canceled(cancel_code),
InnerRequest::Created(s) => s.clone().into_canceled(cancelled_by_us, cancel_code),
InnerRequest::Requested(s) => s.clone().into_canceled(cancelled_by_us, cancel_code),
InnerRequest::Ready(s) => s.clone().into_canceled(cancelled_by_us, cancel_code),
InnerRequest::Passive(s) => s.clone().into_canceled(cancelled_by_us, cancel_code),
InnerRequest::Done(_) => return,
InnerRequest::Cancelled(_) => return,
})
@ -604,7 +604,11 @@ impl<S: Clone> RequestState<S> {
}
}
fn into_canceled(self, cancel_code: &CancelCode) -> RequestState<Cancelled> {
fn into_canceled(
self,
cancelled_by_us: bool,
cancel_code: &CancelCode,
) -> RequestState<Cancelled> {
RequestState::<Cancelled> {
account: self.account,
private_cross_signing_identity: self.private_cross_signing_identity,
@ -612,7 +616,7 @@ impl<S: Clone> RequestState<S> {
store: self.store,
flow_id: self.flow_id,
other_user_id: self.other_user_id,
state: Cancelled::new(cancel_code.clone()),
state: Cancelled::new(cancelled_by_us, cancel_code.clone()),
}
}
}

View File

@ -168,13 +168,17 @@ impl InnerSas {
}
}
pub fn cancel(self, code: CancelCode) -> (InnerSas, Option<OutgoingContent>) {
pub fn cancel(
self,
cancelled_by_us: bool,
code: CancelCode,
) -> (InnerSas, Option<OutgoingContent>) {
let sas = match self {
InnerSas::Created(s) => s.cancel(code),
InnerSas::Started(s) => s.cancel(code),
InnerSas::Accepted(s) => s.cancel(code),
InnerSas::KeyReceived(s) => s.cancel(code),
InnerSas::MacReceived(s) => s.cancel(code),
InnerSas::Created(s) => s.cancel(cancelled_by_us, code),
InnerSas::Started(s) => s.cancel(cancelled_by_us, code),
InnerSas::Accepted(s) => s.cancel(cancelled_by_us, code),
InnerSas::KeyReceived(s) => s.cancel(cancelled_by_us, code),
InnerSas::MacReceived(s) => s.cancel(cancelled_by_us, code),
_ => return (self, None),
};
@ -230,7 +234,7 @@ impl InnerSas {
}
}
AnyVerificationContent::Cancel(c) => {
let (sas, _) = self.cancel(c.cancel_code().to_owned());
let (sas, _) = self.cancel(false, c.cancel_code().to_owned());
(sas, None)
}
AnyVerificationContent::Key(c) => match self {
@ -324,6 +328,14 @@ impl InnerSas {
}
}
pub fn cancelled_by_us(&self) -> Option<bool> {
if let InnerSas::Cancelled(c) = self {
Some(c.state.cancelled_by_us)
} else {
None
}
}
pub fn timed_out(&self) -> bool {
match self {
InnerSas::Created(s) => s.timed_out(),

View File

@ -115,6 +115,11 @@ impl Sas {
self.inner.lock().unwrap().cancel_code()
}
/// Has the verification flow been cancelled by us.
pub fn cancelled_by_us(&self) -> Option<bool> {
self.inner.lock().unwrap().cancelled_by_us()
}
/// Did we initiate the verification flow.
pub fn we_started(&self) -> bool {
self.we_started
@ -390,7 +395,7 @@ impl Sas {
pub fn cancel_with_code(&self, code: CancelCode) -> Option<OutgoingVerificationRequest> {
let mut guard = self.inner.lock().unwrap();
let sas: InnerSas = (*guard).clone();
let (sas, content) = sas.cancel(code);
let (sas, content) = sas.cancel(true, code);
*guard = sas;
content.map(|c| match c {
OutgoingContent::Room(room_id, content) => {

View File

@ -298,14 +298,14 @@ impl<S: Clone> SasState<S> {
self.ids.other_device.clone()
}
pub fn cancel(self, cancel_code: CancelCode) -> SasState<Cancelled> {
pub fn cancel(self, cancelled_by_us: bool, cancel_code: CancelCode) -> SasState<Cancelled> {
SasState {
inner: self.inner,
ids: self.ids,
creation_time: self.creation_time,
last_event_time: self.last_event_time,
verification_flow_id: self.verification_flow_id,
state: Arc::new(Cancelled::new(cancel_code)),
state: Arc::new(Cancelled::new(cancelled_by_us, cancel_code)),
started_from_request: self.started_from_request,
}
}
@ -444,11 +444,11 @@ impl SasState<Created> {
sender: &UserId,
content: &AcceptContent,
) -> Result<SasState<Accepted>, SasState<Cancelled>> {
self.check_event(sender, content.flow_id()).map_err(|c| self.clone().cancel(c))?;
self.check_event(sender, content.flow_id()).map_err(|c| self.clone().cancel(true, c))?;
if let AcceptMethod::SasV1(content) = content.method() {
let accepted_protocols =
AcceptedProtocols::try_from(content.clone()).map_err(|c| self.clone().cancel(c))?;
let accepted_protocols = AcceptedProtocols::try_from(content.clone())
.map_err(|c| self.clone().cancel(true, c))?;
let start_content = self.as_content().into();
@ -466,7 +466,7 @@ impl SasState<Created> {
}),
})
} else {
Err(self.cancel(CancelCode::UnknownMethod))
Err(self.cancel(true, CancelCode::UnknownMethod))
}
}
}
@ -509,7 +509,7 @@ impl SasState<Started> {
},
verification_flow_id: flow_id.clone(),
state: Arc::new(Cancelled::new(CancelCode::UnknownMethod)),
state: Arc::new(Cancelled::new(true, CancelCode::UnknownMethod)),
};
if let StartMethod::SasV1(method_content) = content.method() {
@ -600,7 +600,7 @@ impl SasState<Started> {
sender: &UserId,
content: &KeyContent,
) -> Result<SasState<KeyReceived>, SasState<Cancelled>> {
self.check_event(sender, content.flow_id()).map_err(|c| self.clone().cancel(c))?;
self.check_event(sender, content.flow_id()).map_err(|c| self.clone().cancel(true, c))?;
let their_pubkey = content.public_key().to_owned();
@ -640,7 +640,7 @@ impl SasState<Accepted> {
sender: &UserId,
content: &KeyContent,
) -> Result<SasState<KeyReceived>, SasState<Cancelled>> {
self.check_event(sender, content.flow_id()).map_err(|c| self.clone().cancel(c))?;
self.check_event(sender, content.flow_id()).map_err(|c| self.clone().cancel(true, c))?;
let commitment = calculate_commitment(
content.public_key(),
@ -648,7 +648,7 @@ impl SasState<Accepted> {
);
if self.state.commitment != commitment {
Err(self.cancel(CancelCode::InvalidMessage))
Err(self.cancel(true, CancelCode::InvalidMessage))
} else {
let their_pubkey = content.public_key().to_owned();
@ -777,7 +777,7 @@ impl SasState<KeyReceived> {
sender: &UserId,
content: &MacContent,
) -> Result<SasState<MacReceived>, SasState<Cancelled>> {
self.check_event(sender, content.flow_id()).map_err(|c| self.clone().cancel(c))?;
self.check_event(sender, content.flow_id()).map_err(|c| self.clone().cancel(true, c))?;
let (devices, master_keys) = receive_mac_event(
&self.inner.lock().unwrap(),
@ -786,7 +786,7 @@ impl SasState<KeyReceived> {
sender,
content,
)
.map_err(|c| self.clone().cancel(c))?;
.map_err(|c| self.clone().cancel(true, c))?;
Ok(SasState {
inner: self.inner,
@ -837,7 +837,7 @@ impl SasState<Confirmed> {
sender: &UserId,
content: &MacContent,
) -> Result<SasState<Done>, SasState<Cancelled>> {
self.check_event(sender, content.flow_id()).map_err(|c| self.clone().cancel(c))?;
self.check_event(sender, content.flow_id()).map_err(|c| self.clone().cancel(true, c))?;
let (devices, master_keys) = receive_mac_event(
&self.inner.lock().unwrap(),
@ -846,7 +846,7 @@ impl SasState<Confirmed> {
sender,
content,
)
.map_err(|c| self.clone().cancel(c))?;
.map_err(|c| self.clone().cancel(true, c))?;
Ok(SasState {
inner: self.inner,
@ -877,7 +877,7 @@ impl SasState<Confirmed> {
sender: &UserId,
content: &MacContent,
) -> Result<SasState<WaitingForDone>, SasState<Cancelled>> {
self.check_event(sender, content.flow_id()).map_err(|c| self.clone().cancel(c))?;
self.check_event(sender, content.flow_id()).map_err(|c| self.clone().cancel(true, c))?;
let (devices, master_keys) = receive_mac_event(
&self.inner.lock().unwrap(),
@ -886,7 +886,7 @@ impl SasState<Confirmed> {
sender,
content,
)
.map_err(|c| self.clone().cancel(c))?;
.map_err(|c| self.clone().cancel(true, c))?;
Ok(SasState {
inner: self.inner,
@ -1032,7 +1032,7 @@ impl SasState<WaitingForDone> {
sender: &UserId,
content: &DoneContent,
) -> Result<SasState<Done>, SasState<Cancelled>> {
self.check_event(sender, content.flow_id()).map_err(|c| self.clone().cancel(c))?;
self.check_event(sender, content.flow_id()).map_err(|c| self.clone().cancel(true, c))?;
Ok(SasState {
inner: self.inner,