crypto: Add settings to customize SAS accepting

Offer specifying settings to SAS accept() requests to limit the allowed
verification methods.
master
Jan Veen 2021-03-11 21:10:26 +01:00
parent e5585b57e8
commit e9be23f853
4 changed files with 97 additions and 18 deletions

View File

@ -12,7 +12,9 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use matrix_sdk_base::crypto::{OutgoingVerificationRequest, ReadOnlyDevice, Sas as BaseSas}; use matrix_sdk_base::crypto::{
AcceptSettings, OutgoingVerificationRequest, ReadOnlyDevice, Sas as BaseSas,
};
use crate::{error::Result, Client}; use crate::{error::Result, Client};
@ -26,7 +28,14 @@ pub struct Sas {
impl Sas { impl Sas {
/// Accept the interactive verification flow. /// Accept the interactive verification flow.
pub async fn accept(&self) -> Result<()> { pub async fn accept(&self) -> Result<()> {
if let Some(req) = self.inner.accept() { self.accept_with_settings(Default::default()).await
}
/// Accept the interactive verification flow with specific settings.
///
/// Pass `settings` to customizes the accept-request before sending it.
pub async fn accept_with_settings(&self, settings: AcceptSettings) -> Result<()> {
if let Some(req) = self.inner.accept_with_settings(settings) {
match req { match req {
OutgoingVerificationRequest::ToDevice(r) => { OutgoingVerificationRequest::ToDevice(r) => {
self.client.send_to_device(&r).await?; self.client.send_to_device(&r).await?;

View File

@ -55,4 +55,4 @@ pub use requests::{
OutgoingVerificationRequest, RoomMessageRequest, ToDeviceRequest, OutgoingVerificationRequest, RoomMessageRequest, ToDeviceRequest,
}; };
pub use store::CryptoStoreError; pub use store::CryptoStoreError;
pub use verification::{Sas, VerificationRequest}; pub use verification::{AcceptSettings, Sas, VerificationRequest};

View File

@ -18,7 +18,7 @@ mod sas;
pub use machine::VerificationMachine; pub use machine::VerificationMachine;
pub use requests::VerificationRequest; pub use requests::VerificationRequest;
pub use sas::{Sas, VerificationResult}; pub use sas::{AcceptSettings, Sas, VerificationResult};
#[cfg(test)] #[cfg(test)]
pub(crate) mod test { pub(crate) mod test {

View File

@ -27,8 +27,12 @@ use tracing::{error, info, trace, warn};
use matrix_sdk_common::{ use matrix_sdk_common::{
api::r0::keys::upload_signatures::Request as SignatureUploadRequest, api::r0::keys::upload_signatures::Request as SignatureUploadRequest,
events::{ events::{
key::verification::cancel::CancelCode, AnyMessageEvent, AnyMessageEventContent, key::verification::{
AnyToDeviceEvent, AnyToDeviceEventContent, accept::{AcceptEventContent, AcceptMethod, AcceptToDeviceEventContent},
cancel::CancelCode,
ShortAuthenticationString,
},
AnyMessageEvent, AnyMessageEventContent, AnyToDeviceEvent, AnyToDeviceEventContent,
}, },
identifiers::{DeviceId, EventId, RoomId, UserId}, identifiers::{DeviceId, EventId, RoomId, UserId},
uuid::Uuid, uuid::Uuid,
@ -253,18 +257,35 @@ impl Sas {
/// This does nothing if the verification was already accepted, otherwise it /// This does nothing if the verification was already accepted, otherwise it
/// returns an `AcceptEventContent` that needs to be sent out. /// returns an `AcceptEventContent` that needs to be sent out.
pub fn accept(&self) -> Option<OutgoingVerificationRequest> { pub fn accept(&self) -> Option<OutgoingVerificationRequest> {
self.inner.lock().unwrap().accept().map(|c| match c { self.accept_with_settings(Default::default())
AcceptContent::ToDevice(c) => { }
let content = AnyToDeviceEventContent::KeyVerificationAccept(c);
self.content_to_request(content).into() /// Accept the SAS verification customizing the accept method.
} ///
AcceptContent::Room(room_id, content) => RoomMessageRequest { /// This does nothing if the verification was already accepted, otherwise it
room_id, /// returns an `AcceptEventContent` that needs to be sent out.
txn_id: Uuid::new_v4(), ///
content: AnyMessageEventContent::KeyVerificationAccept(content), /// Specify a function modifying the attributes of the accept request.
} pub fn accept_with_settings(
.into(), &self,
}) settings: AcceptSettings,
) -> Option<OutgoingVerificationRequest> {
self.inner
.lock()
.unwrap()
.accept()
.map(|c| match settings.apply(c) {
AcceptContent::ToDevice(c) => {
let content = AnyToDeviceEventContent::KeyVerificationAccept(c);
self.content_to_request(content).into()
}
AcceptContent::Room(room_id, content) => RoomMessageRequest {
room_id,
txn_id: Uuid::new_v4(),
content: AnyMessageEventContent::KeyVerificationAccept(content),
}
.into(),
})
} }
/// Confirm the Sas verification. /// Confirm the Sas verification.
@ -654,6 +675,55 @@ impl Sas {
} }
} }
/// Customize the accept-reply for a verification process
#[derive(Debug)]
pub struct AcceptSettings {
allowed_methods: Vec<ShortAuthenticationString>,
}
impl Default for AcceptSettings {
fn default() -> Self {
Self {
allowed_methods: vec![
ShortAuthenticationString::Decimal,
ShortAuthenticationString::Emoji,
],
}
}
}
impl AcceptSettings {
/// Create settings with exactly the specified SAS methods
pub fn with_allowed_methods(methods: Vec<ShortAuthenticationString>) -> Self {
Self {
allowed_methods: methods,
}
}
fn apply(self, mut content: AcceptContent) -> AcceptContent {
match &mut content {
AcceptContent::ToDevice(AcceptToDeviceEventContent {
method: AcceptMethod::MSasV1(c),
..
}) => {
c.short_authentication_string = self.allowed_methods;
content
}
AcceptContent::Room(
_,
AcceptEventContent {
method: AcceptMethod::MSasV1(c),
..
},
) => {
c.short_authentication_string = self.allowed_methods;
content
}
_ => content,
}
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use std::{convert::TryFrom, sync::Arc}; use std::{convert::TryFrom, sync::Arc};