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
parent
d4e80883dc
commit
af084528c8
|
@ -167,12 +167,13 @@ impl Done {
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Cancelled {
|
pub struct Cancelled {
|
||||||
|
cancelled_by_us: bool,
|
||||||
cancel_code: CancelCode,
|
cancel_code: CancelCode,
|
||||||
reason: &'static str,
|
reason: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cancelled {
|
impl Cancelled {
|
||||||
fn new(code: CancelCode) -> Self {
|
fn new(cancelled_by_us: bool, code: CancelCode) -> Self {
|
||||||
let reason = match code {
|
let reason = match code {
|
||||||
CancelCode::Accepted => {
|
CancelCode::Accepted => {
|
||||||
"A m.key.verification.request was accepted by a different device."
|
"A m.key.verification.request was accepted by a different device."
|
||||||
|
@ -192,7 +193,7 @@ impl Cancelled {
|
||||||
_ => "Unknown cancel reason",
|
_ => "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 {
|
pub fn as_content(&self, flow_id: &FlowId) -> OutgoingContent {
|
||||||
|
|
|
@ -210,7 +210,7 @@ impl QrVerification {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cancel_with_code(&self, code: CancelCode) -> Option<OutgoingContent> {
|
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 content = new_state.as_content(self.flow_id());
|
||||||
|
|
||||||
let mut state = self.state.lock().unwrap();
|
let mut state = self.state.lock().unwrap();
|
||||||
|
@ -243,7 +243,7 @@ impl QrVerification {
|
||||||
match self.identities.mark_as_done(Some(&devices), Some(&identities)).await? {
|
match self.identities.mark_as_done(Some(&devices), Some(&identities)).await? {
|
||||||
VerificationResult::Ok => (None, None),
|
VerificationResult::Ok => (None, None),
|
||||||
VerificationResult::Cancel(c) => {
|
VerificationResult::Cancel(c) => {
|
||||||
let canceled = QrState::<Cancelled>::new(c);
|
let canceled = QrState::<Cancelled>::new(false, c);
|
||||||
let content = canceled.as_content(self.flow_id());
|
let content = canceled.as_content(self.flow_id());
|
||||||
new_state = InnerState::Cancelled(canceled);
|
new_state = InnerState::Cancelled(canceled);
|
||||||
(Some(content), None)
|
(Some(content), None)
|
||||||
|
@ -594,8 +594,8 @@ impl QrState<Scanned> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QrState<Cancelled> {
|
impl QrState<Cancelled> {
|
||||||
fn new(cancel_code: CancelCode) -> Self {
|
fn new(cancelled_by_us: bool, cancel_code: CancelCode) -> Self {
|
||||||
QrState { state: Cancelled::new(cancel_code) }
|
QrState { state: Cancelled::new(cancelled_by_us, cancel_code) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_content(&self, flow_id: &FlowId) -> OutgoingContent {
|
fn as_content(&self, flow_id: &FlowId) -> OutgoingContent {
|
||||||
|
@ -614,10 +614,10 @@ impl QrState<Created> {
|
||||||
if self.state.secret == m.secret {
|
if self.state.secret == m.secret {
|
||||||
Ok(QrState { state: Scanned {} })
|
Ok(QrState { state: Scanned {} })
|
||||||
} else {
|
} 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)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -376,7 +376,7 @@ impl VerificationRequest {
|
||||||
/// Cancel the verification request
|
/// Cancel the verification request
|
||||||
pub fn cancel(&self) -> Option<OutgoingVerificationRequest> {
|
pub fn cancel(&self) -> Option<OutgoingVerificationRequest> {
|
||||||
let mut inner = self.inner.lock().unwrap();
|
let mut inner = self.inner.lock().unwrap();
|
||||||
inner.cancel(&CancelCode::User);
|
inner.cancel(true, &CancelCode::User);
|
||||||
|
|
||||||
let content = if let InnerRequest::Cancelled(c) = &*inner {
|
let content = if let InnerRequest::Cancelled(c) = &*inner {
|
||||||
Some(c.state.as_content(self.flow_id()))
|
Some(c.state.as_content(self.flow_id()))
|
||||||
|
@ -436,7 +436,7 @@ impl VerificationRequest {
|
||||||
pub(crate) fn receive_cancel(&self, sender: &UserId, content: &CancelContent<'_>) {
|
pub(crate) fn receive_cancel(&self, sender: &UserId, content: &CancelContent<'_>) {
|
||||||
if sender == self.other_user() {
|
if sender == self.other_user() {
|
||||||
let mut inner = self.inner.lock().unwrap().clone();
|
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 {
|
*self = InnerRequest::Cancelled(match self {
|
||||||
InnerRequest::Created(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(cancel_code),
|
InnerRequest::Requested(s) => s.clone().into_canceled(cancelled_by_us, cancel_code),
|
||||||
InnerRequest::Ready(s) => s.clone().into_canceled(cancel_code),
|
InnerRequest::Ready(s) => s.clone().into_canceled(cancelled_by_us, cancel_code),
|
||||||
InnerRequest::Passive(s) => s.clone().into_canceled(cancel_code),
|
InnerRequest::Passive(s) => s.clone().into_canceled(cancelled_by_us, cancel_code),
|
||||||
InnerRequest::Done(_) => return,
|
InnerRequest::Done(_) => return,
|
||||||
InnerRequest::Cancelled(_) => 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> {
|
RequestState::<Cancelled> {
|
||||||
account: self.account,
|
account: self.account,
|
||||||
private_cross_signing_identity: self.private_cross_signing_identity,
|
private_cross_signing_identity: self.private_cross_signing_identity,
|
||||||
|
@ -612,7 +616,7 @@ impl<S: Clone> RequestState<S> {
|
||||||
store: self.store,
|
store: self.store,
|
||||||
flow_id: self.flow_id,
|
flow_id: self.flow_id,
|
||||||
other_user_id: self.other_user_id,
|
other_user_id: self.other_user_id,
|
||||||
state: Cancelled::new(cancel_code.clone()),
|
state: Cancelled::new(cancelled_by_us, cancel_code.clone()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
let sas = match self {
|
||||||
InnerSas::Created(s) => s.cancel(code),
|
InnerSas::Created(s) => s.cancel(cancelled_by_us, code),
|
||||||
InnerSas::Started(s) => s.cancel(code),
|
InnerSas::Started(s) => s.cancel(cancelled_by_us, code),
|
||||||
InnerSas::Accepted(s) => s.cancel(code),
|
InnerSas::Accepted(s) => s.cancel(cancelled_by_us, code),
|
||||||
InnerSas::KeyReceived(s) => s.cancel(code),
|
InnerSas::KeyReceived(s) => s.cancel(cancelled_by_us, code),
|
||||||
InnerSas::MacReceived(s) => s.cancel(code),
|
InnerSas::MacReceived(s) => s.cancel(cancelled_by_us, code),
|
||||||
_ => return (self, None),
|
_ => return (self, None),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -230,7 +234,7 @@ impl InnerSas {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AnyVerificationContent::Cancel(c) => {
|
AnyVerificationContent::Cancel(c) => {
|
||||||
let (sas, _) = self.cancel(c.cancel_code().to_owned());
|
let (sas, _) = self.cancel(false, c.cancel_code().to_owned());
|
||||||
(sas, None)
|
(sas, None)
|
||||||
}
|
}
|
||||||
AnyVerificationContent::Key(c) => match self {
|
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 {
|
pub fn timed_out(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
InnerSas::Created(s) => s.timed_out(),
|
InnerSas::Created(s) => s.timed_out(),
|
||||||
|
|
|
@ -115,6 +115,11 @@ impl Sas {
|
||||||
self.inner.lock().unwrap().cancel_code()
|
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.
|
/// Did we initiate the verification flow.
|
||||||
pub fn we_started(&self) -> bool {
|
pub fn we_started(&self) -> bool {
|
||||||
self.we_started
|
self.we_started
|
||||||
|
@ -390,7 +395,7 @@ impl Sas {
|
||||||
pub fn cancel_with_code(&self, code: CancelCode) -> Option<OutgoingVerificationRequest> {
|
pub fn cancel_with_code(&self, code: CancelCode) -> Option<OutgoingVerificationRequest> {
|
||||||
let mut guard = self.inner.lock().unwrap();
|
let mut guard = self.inner.lock().unwrap();
|
||||||
let sas: InnerSas = (*guard).clone();
|
let sas: InnerSas = (*guard).clone();
|
||||||
let (sas, content) = sas.cancel(code);
|
let (sas, content) = sas.cancel(true, code);
|
||||||
*guard = sas;
|
*guard = sas;
|
||||||
content.map(|c| match c {
|
content.map(|c| match c {
|
||||||
OutgoingContent::Room(room_id, content) => {
|
OutgoingContent::Room(room_id, content) => {
|
||||||
|
|
|
@ -298,14 +298,14 @@ impl<S: Clone> SasState<S> {
|
||||||
self.ids.other_device.clone()
|
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 {
|
SasState {
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
ids: self.ids,
|
ids: self.ids,
|
||||||
creation_time: self.creation_time,
|
creation_time: self.creation_time,
|
||||||
last_event_time: self.last_event_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(Cancelled::new(cancel_code)),
|
state: Arc::new(Cancelled::new(cancelled_by_us, cancel_code)),
|
||||||
started_from_request: self.started_from_request,
|
started_from_request: self.started_from_request,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -444,11 +444,11 @@ impl SasState<Created> {
|
||||||
sender: &UserId,
|
sender: &UserId,
|
||||||
content: &AcceptContent,
|
content: &AcceptContent,
|
||||||
) -> Result<SasState<Accepted>, SasState<Cancelled>> {
|
) -> 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() {
|
if let AcceptMethod::SasV1(content) = content.method() {
|
||||||
let accepted_protocols =
|
let accepted_protocols = AcceptedProtocols::try_from(content.clone())
|
||||||
AcceptedProtocols::try_from(content.clone()).map_err(|c| self.clone().cancel(c))?;
|
.map_err(|c| self.clone().cancel(true, c))?;
|
||||||
|
|
||||||
let start_content = self.as_content().into();
|
let start_content = self.as_content().into();
|
||||||
|
|
||||||
|
@ -466,7 +466,7 @@ impl SasState<Created> {
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
} else {
|
} 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(),
|
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() {
|
if let StartMethod::SasV1(method_content) = content.method() {
|
||||||
|
@ -600,7 +600,7 @@ impl SasState<Started> {
|
||||||
sender: &UserId,
|
sender: &UserId,
|
||||||
content: &KeyContent,
|
content: &KeyContent,
|
||||||
) -> Result<SasState<KeyReceived>, SasState<Cancelled>> {
|
) -> 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();
|
let their_pubkey = content.public_key().to_owned();
|
||||||
|
|
||||||
|
@ -640,7 +640,7 @@ impl SasState<Accepted> {
|
||||||
sender: &UserId,
|
sender: &UserId,
|
||||||
content: &KeyContent,
|
content: &KeyContent,
|
||||||
) -> Result<SasState<KeyReceived>, SasState<Cancelled>> {
|
) -> 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(
|
let commitment = calculate_commitment(
|
||||||
content.public_key(),
|
content.public_key(),
|
||||||
|
@ -648,7 +648,7 @@ impl SasState<Accepted> {
|
||||||
);
|
);
|
||||||
|
|
||||||
if self.state.commitment != commitment {
|
if self.state.commitment != commitment {
|
||||||
Err(self.cancel(CancelCode::InvalidMessage))
|
Err(self.cancel(true, CancelCode::InvalidMessage))
|
||||||
} else {
|
} else {
|
||||||
let their_pubkey = content.public_key().to_owned();
|
let their_pubkey = content.public_key().to_owned();
|
||||||
|
|
||||||
|
@ -777,7 +777,7 @@ impl SasState<KeyReceived> {
|
||||||
sender: &UserId,
|
sender: &UserId,
|
||||||
content: &MacContent,
|
content: &MacContent,
|
||||||
) -> Result<SasState<MacReceived>, SasState<Cancelled>> {
|
) -> 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(
|
let (devices, master_keys) = receive_mac_event(
|
||||||
&self.inner.lock().unwrap(),
|
&self.inner.lock().unwrap(),
|
||||||
|
@ -786,7 +786,7 @@ impl SasState<KeyReceived> {
|
||||||
sender,
|
sender,
|
||||||
content,
|
content,
|
||||||
)
|
)
|
||||||
.map_err(|c| self.clone().cancel(c))?;
|
.map_err(|c| self.clone().cancel(true, c))?;
|
||||||
|
|
||||||
Ok(SasState {
|
Ok(SasState {
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
|
@ -837,7 +837,7 @@ impl SasState<Confirmed> {
|
||||||
sender: &UserId,
|
sender: &UserId,
|
||||||
content: &MacContent,
|
content: &MacContent,
|
||||||
) -> Result<SasState<Done>, SasState<Cancelled>> {
|
) -> 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(
|
let (devices, master_keys) = receive_mac_event(
|
||||||
&self.inner.lock().unwrap(),
|
&self.inner.lock().unwrap(),
|
||||||
|
@ -846,7 +846,7 @@ impl SasState<Confirmed> {
|
||||||
sender,
|
sender,
|
||||||
content,
|
content,
|
||||||
)
|
)
|
||||||
.map_err(|c| self.clone().cancel(c))?;
|
.map_err(|c| self.clone().cancel(true, c))?;
|
||||||
|
|
||||||
Ok(SasState {
|
Ok(SasState {
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
|
@ -877,7 +877,7 @@ impl SasState<Confirmed> {
|
||||||
sender: &UserId,
|
sender: &UserId,
|
||||||
content: &MacContent,
|
content: &MacContent,
|
||||||
) -> Result<SasState<WaitingForDone>, SasState<Cancelled>> {
|
) -> 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(
|
let (devices, master_keys) = receive_mac_event(
|
||||||
&self.inner.lock().unwrap(),
|
&self.inner.lock().unwrap(),
|
||||||
|
@ -886,7 +886,7 @@ impl SasState<Confirmed> {
|
||||||
sender,
|
sender,
|
||||||
content,
|
content,
|
||||||
)
|
)
|
||||||
.map_err(|c| self.clone().cancel(c))?;
|
.map_err(|c| self.clone().cancel(true, c))?;
|
||||||
|
|
||||||
Ok(SasState {
|
Ok(SasState {
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
|
@ -1032,7 +1032,7 @@ impl SasState<WaitingForDone> {
|
||||||
sender: &UserId,
|
sender: &UserId,
|
||||||
content: &DoneContent,
|
content: &DoneContent,
|
||||||
) -> Result<SasState<Done>, SasState<Cancelled>> {
|
) -> 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 {
|
Ok(SasState {
|
||||||
inner: self.inner,
|
inner: self.inner,
|
||||||
|
|
Loading…
Reference in New Issue