crypto: Only send out automatic key requests if we have a verified device
Sending out automatic key requests is a bit spammy for new logins, they'll likely have many undecryptable events upon an initial sync. It's unlikely that anyone will respond to such a key request since keys are shared only with verified devices between devices of the same user or if the key owner knows that the device should have received the key. Upon initial sync it's unlikely that we have been verified and the key owner likely did not intend to send us the key since we just created the new device.master
parent
78b7dcac61
commit
4a7be13961
|
@ -258,6 +258,14 @@ impl UserDevices {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if there is at least one devices of this user that is
|
||||||
|
/// considered to be verified, false otherwise.
|
||||||
|
pub fn is_any_verified(&self) -> bool {
|
||||||
|
self.inner
|
||||||
|
.values()
|
||||||
|
.any(|d| d.trust_state(&self.own_identity, &self.device_owner_identity))
|
||||||
|
}
|
||||||
|
|
||||||
/// Iterator over all the device ids of the user devices.
|
/// Iterator over all the device ids of the user devices.
|
||||||
pub fn keys(&self) -> impl Iterator<Item = &DeviceIdBox> {
|
pub fn keys(&self) -> impl Iterator<Item = &DeviceIdBox> {
|
||||||
self.inner.keys()
|
self.inner.keys()
|
||||||
|
|
|
@ -407,7 +407,7 @@ impl KeyRequestMachine {
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if let Some(device) = device {
|
if let Some(device) = device {
|
||||||
match self.should_share_session(&device, &session).await {
|
match self.should_share_key(&device, &session).await {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
info!(
|
info!(
|
||||||
"Received a key request from {} {} that we won't serve: {}",
|
"Received a key request from {} {} that we won't serve: {}",
|
||||||
|
@ -509,7 +509,7 @@ impl KeyRequestMachine {
|
||||||
/// * `device` - The device that is requesting a session from us.
|
/// * `device` - The device that is requesting a session from us.
|
||||||
///
|
///
|
||||||
/// * `session` - The session that was requested to be shared.
|
/// * `session` - The session that was requested to be shared.
|
||||||
async fn should_share_session(
|
async fn should_share_key(
|
||||||
&self,
|
&self,
|
||||||
device: &Device,
|
device: &Device,
|
||||||
session: &InboundGroupSession,
|
session: &InboundGroupSession,
|
||||||
|
@ -554,6 +554,38 @@ impl KeyRequestMachine {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if it's ok, or rather if it makes sense to automatically request
|
||||||
|
/// a key from our other devices.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `key_info` - The info of our key request containing information about
|
||||||
|
/// the key we wish to request.
|
||||||
|
async fn should_request_key(
|
||||||
|
&self,
|
||||||
|
key_info: &RequestedKeyInfo,
|
||||||
|
) -> Result<bool, CryptoStoreError> {
|
||||||
|
let request = self.store.get_key_request_by_info(&key_info).await?;
|
||||||
|
|
||||||
|
// Don't send out duplicate requests, users can re-request them if they
|
||||||
|
// think a second request might succeed.
|
||||||
|
if request.is_none() {
|
||||||
|
let devices = self.store.get_user_devices(self.user_id()).await?;
|
||||||
|
|
||||||
|
// Devices will only respond to key requests if the devices are
|
||||||
|
// verified, if the device isn't verified by us it's unlikely that
|
||||||
|
// we're verified by them either. Don't request keys if there isn't
|
||||||
|
// at least one verified device.
|
||||||
|
if devices.is_any_verified() {
|
||||||
|
Ok(true)
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a new outgoing key request for the key with the given session id.
|
/// Create a new outgoing key request for the key with the given session id.
|
||||||
///
|
///
|
||||||
/// This will queue up a new to-device request and store the key info so
|
/// This will queue up a new to-device request and store the key info so
|
||||||
|
@ -644,9 +676,7 @@ impl KeyRequestMachine {
|
||||||
session_id: session_id.to_owned(),
|
session_id: session_id.to_owned(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let request = self.store.get_key_request_by_info(&key_info).await?;
|
if self.should_request_key(&key_info).await? {
|
||||||
|
|
||||||
if request.is_none() {
|
|
||||||
self.request_key_helper(key_info).await?;
|
self.request_key_helper(key_info).await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -828,6 +858,10 @@ mod test {
|
||||||
"ILMLKASTES".into()
|
"ILMLKASTES".into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn alice2_device_id() -> DeviceIdBox {
|
||||||
|
"ILMLKASTES".into()
|
||||||
|
}
|
||||||
|
|
||||||
fn room_id() -> RoomId {
|
fn room_id() -> RoomId {
|
||||||
room_id!("!test:example.org")
|
room_id!("!test:example.org")
|
||||||
}
|
}
|
||||||
|
@ -840,6 +874,10 @@ mod test {
|
||||||
ReadOnlyAccount::new(&bob_id(), &bob_device_id())
|
ReadOnlyAccount::new(&bob_id(), &bob_device_id())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn alice_2_account() -> ReadOnlyAccount {
|
||||||
|
ReadOnlyAccount::new(&alice_id(), &alice2_device_id())
|
||||||
|
}
|
||||||
|
|
||||||
fn bob_machine() -> KeyRequestMachine {
|
fn bob_machine() -> KeyRequestMachine {
|
||||||
let user_id = Arc::new(bob_id());
|
let user_id = Arc::new(bob_id());
|
||||||
let account = ReadOnlyAccount::new(&user_id, &alice_device_id());
|
let account = ReadOnlyAccount::new(&user_id, &alice_device_id());
|
||||||
|
@ -890,7 +928,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_test]
|
#[async_test]
|
||||||
async fn create_key_request() {
|
async fn re_request_keys() {
|
||||||
let machine = get_machine().await;
|
let machine = get_machine().await;
|
||||||
let account = account();
|
let account = account();
|
||||||
|
|
||||||
|
@ -925,9 +963,15 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_test]
|
#[async_test]
|
||||||
async fn re_request_keys() {
|
async fn create_key_request() {
|
||||||
let machine = get_machine().await;
|
let machine = get_machine().await;
|
||||||
let account = account();
|
let account = account();
|
||||||
|
let second_account = alice_2_account();
|
||||||
|
let alice_device = ReadOnlyDevice::from_account(&second_account).await;
|
||||||
|
|
||||||
|
// We need a trusted device, otherwise we won't request keys
|
||||||
|
alice_device.set_trust_state(LocalTrust::Verified);
|
||||||
|
machine.store.save_devices(&[alice_device]).await.unwrap();
|
||||||
|
|
||||||
let (_, session) = account
|
let (_, session) = account
|
||||||
.create_group_session_pair_with_defaults(&room_id())
|
.create_group_session_pair_with_defaults(&room_id())
|
||||||
|
@ -987,6 +1031,13 @@ mod test {
|
||||||
let machine = get_machine().await;
|
let machine = get_machine().await;
|
||||||
let account = account();
|
let account = account();
|
||||||
|
|
||||||
|
let second_account = alice_2_account();
|
||||||
|
let alice_device = ReadOnlyDevice::from_account(&second_account).await;
|
||||||
|
|
||||||
|
// We need a trusted device, otherwise we won't request keys
|
||||||
|
alice_device.set_trust_state(LocalTrust::Verified);
|
||||||
|
machine.store.save_devices(&[alice_device]).await.unwrap();
|
||||||
|
|
||||||
let (_, session) = account
|
let (_, session) = account
|
||||||
.create_group_session_pair_with_defaults(&room_id())
|
.create_group_session_pair_with_defaults(&room_id())
|
||||||
.await
|
.await
|
||||||
|
@ -1118,7 +1169,7 @@ mod test {
|
||||||
// We don't share keys with untrusted devices.
|
// We don't share keys with untrusted devices.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
machine
|
machine
|
||||||
.should_share_session(&own_device, &inbound)
|
.should_share_key(&own_device, &inbound)
|
||||||
.await
|
.await
|
||||||
.expect_err("Should not share with untrusted"),
|
.expect_err("Should not share with untrusted"),
|
||||||
KeyshareDecision::UntrustedDevice
|
KeyshareDecision::UntrustedDevice
|
||||||
|
@ -1126,7 +1177,7 @@ mod test {
|
||||||
own_device.set_trust_state(LocalTrust::Verified);
|
own_device.set_trust_state(LocalTrust::Verified);
|
||||||
// Now we do want to share the keys.
|
// Now we do want to share the keys.
|
||||||
assert!(machine
|
assert!(machine
|
||||||
.should_share_session(&own_device, &inbound)
|
.should_share_key(&own_device, &inbound)
|
||||||
.await
|
.await
|
||||||
.is_ok());
|
.is_ok());
|
||||||
|
|
||||||
|
@ -1144,7 +1195,7 @@ mod test {
|
||||||
// session was provided.
|
// session was provided.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
machine
|
machine
|
||||||
.should_share_session(&bob_device, &inbound)
|
.should_share_key(&bob_device, &inbound)
|
||||||
.await
|
.await
|
||||||
.expect_err("Should not share with other."),
|
.expect_err("Should not share with other."),
|
||||||
KeyshareDecision::MissingOutboundSession
|
KeyshareDecision::MissingOutboundSession
|
||||||
|
@ -1161,7 +1212,7 @@ mod test {
|
||||||
// wasn't shared in the first place.
|
// wasn't shared in the first place.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
machine
|
machine
|
||||||
.should_share_session(&bob_device, &inbound)
|
.should_share_key(&bob_device, &inbound)
|
||||||
.await
|
.await
|
||||||
.expect_err("Should not share with other unless shared."),
|
.expect_err("Should not share with other unless shared."),
|
||||||
KeyshareDecision::OutboundSessionNotShared
|
KeyshareDecision::OutboundSessionNotShared
|
||||||
|
@ -1173,7 +1224,7 @@ mod test {
|
||||||
// wasn't shared in the first place even if the device is trusted.
|
// wasn't shared in the first place even if the device is trusted.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
machine
|
machine
|
||||||
.should_share_session(&bob_device, &inbound)
|
.should_share_key(&bob_device, &inbound)
|
||||||
.await
|
.await
|
||||||
.expect_err("Should not share with other unless shared."),
|
.expect_err("Should not share with other unless shared."),
|
||||||
KeyshareDecision::OutboundSessionNotShared
|
KeyshareDecision::OutboundSessionNotShared
|
||||||
|
@ -1182,7 +1233,7 @@ mod test {
|
||||||
// We now share the session, since it was shared before.
|
// We now share the session, since it was shared before.
|
||||||
outbound.mark_shared_with(bob_device.user_id(), bob_device.device_id());
|
outbound.mark_shared_with(bob_device.user_id(), bob_device.device_id());
|
||||||
assert!(machine
|
assert!(machine
|
||||||
.should_share_session(&bob_device, &inbound)
|
.should_share_key(&bob_device, &inbound)
|
||||||
.await
|
.await
|
||||||
.is_ok());
|
.is_ok());
|
||||||
|
|
||||||
|
@ -1195,7 +1246,7 @@ mod test {
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
machine
|
machine
|
||||||
.should_share_session(&bob_device, &other_inbound)
|
.should_share_key(&bob_device, &other_inbound)
|
||||||
.await
|
.await
|
||||||
.expect_err("Should not share with other unless shared."),
|
.expect_err("Should not share with other unless shared."),
|
||||||
KeyshareDecision::MissingOutboundSession
|
KeyshareDecision::MissingOutboundSession
|
||||||
|
@ -1213,6 +1264,17 @@ mod test {
|
||||||
let bob_machine = bob_machine();
|
let bob_machine = bob_machine();
|
||||||
let bob_account = bob_account();
|
let bob_account = bob_account();
|
||||||
|
|
||||||
|
let second_account = alice_2_account();
|
||||||
|
let alice_device = ReadOnlyDevice::from_account(&second_account).await;
|
||||||
|
|
||||||
|
// We need a trusted device, otherwise we won't request keys
|
||||||
|
alice_device.set_trust_state(LocalTrust::Verified);
|
||||||
|
alice_machine
|
||||||
|
.store
|
||||||
|
.save_devices(&[alice_device])
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Create Olm sessions for our two accounts.
|
// Create Olm sessions for our two accounts.
|
||||||
let (alice_session, bob_session) = alice_account.create_session_for(&bob_account).await;
|
let (alice_session, bob_session) = alice_account.create_session_for(&bob_account).await;
|
||||||
|
|
||||||
|
@ -1381,6 +1443,17 @@ mod test {
|
||||||
let bob_machine = bob_machine();
|
let bob_machine = bob_machine();
|
||||||
let bob_account = bob_account();
|
let bob_account = bob_account();
|
||||||
|
|
||||||
|
let second_account = alice_2_account();
|
||||||
|
let alice_device = ReadOnlyDevice::from_account(&second_account).await;
|
||||||
|
|
||||||
|
// We need a trusted device, otherwise we won't request keys
|
||||||
|
alice_device.set_trust_state(LocalTrust::Verified);
|
||||||
|
alice_machine
|
||||||
|
.store
|
||||||
|
.save_devices(&[alice_device])
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Create Olm sessions for our two accounts.
|
// Create Olm sessions for our two accounts.
|
||||||
let (alice_session, bob_session) = alice_account.create_session_for(&bob_account).await;
|
let (alice_session, bob_session) = alice_account.create_session_for(&bob_account).await;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue