feat: Make one-to-one chats read-only the first seconds of a SecureJoin (#5512)

This protects Bob (the joiner) of sending unexpected-unencrypted messages during an otherwise nicely
running SecureJoin.

If things get stuck, however, we do not want to block communication -- the chat is just
opportunistic as usual, but that needs to be communicated:
1. If Bob's chat with Alice is `Unprotected` and a SecureJoin is started, then add info-message
   "Establishing guaranteed end-to-end encryption, please wait..." and let `Chat::can_send()` return
   `false`.
2. Once the info-message "Messages are guaranteed to be e2ee from now on" is added, let
   `Chat::can_send()` return `true`.
3. If after SECUREJOIN_WAIT_TIMEOUT seconds `2.` did not happen, add another info-message "Could not
   yet establish guaranteed end-to-end encryption but you may already send a message" and also let
   `Chat::can_send()` return `true`.

Both `2.` and `3.` require the event `ChatModified` being sent out so that UI pick up the change wrt
`Chat::can_send()` (this is the same way how groups become updated wrt `can_send()` changes).

SECUREJOIN_WAIT_TIMEOUT should be 10-20 seconds so that we are reasonably sure that the app remains
active and receiving also on mobile devices. If the app is killed during this time then we may need
to do step 3 for any pending Bob-join chats (right now, Bob can only join one chat at a time).
This commit is contained in:
iequidoo
2024-05-07 18:47:26 -03:00
committed by bjoern
parent edf8aafbdc
commit 518db9a20f
10 changed files with 221 additions and 30 deletions

View File

@@ -29,7 +29,7 @@ mod bob;
mod bobstate;
mod qrinvite;
use bobstate::BobState;
pub(crate) use bobstate::BobState;
use qrinvite::QrInvite;
use crate::token::Namespace;
@@ -764,7 +764,7 @@ mod tests {
use crate::constants::Chattype;
use crate::imex::{imex, ImexMode};
use crate::receive_imf::receive_imf;
use crate::stock_str::chat_protection_enabled;
use crate::stock_str::{self, chat_protection_enabled};
use crate::test_utils::get_chat_msg;
use crate::test_utils::{TestContext, TestContextManager};
use crate::tools::SystemTime;
@@ -961,7 +961,7 @@ mod tests {
let expected_text = chat_protection_enabled(&alice).await;
assert_eq!(msg.get_text(), expected_text);
if case == SetupContactCase::CheckProtectionTimestamp {
assert_eq!(msg.timestamp_sort, vc_request_with_auth_ts_sent);
assert_eq!(msg.timestamp_sort, vc_request_with_auth_ts_sent + 1);
}
}
@@ -990,10 +990,12 @@ mod tests {
// Check Bob got the verified message in his 1:1 chat.
let chat = bob.create_chat(&alice).await;
let msg = get_chat_msg(&bob, chat.get_id(), 0, 1).await;
let msg = get_chat_msg(&bob, chat.get_id(), 0, 2).await;
assert!(msg.is_info());
let expected_text = chat_protection_enabled(&bob).await;
assert_eq!(msg.get_text(), expected_text);
assert_eq!(msg.get_text(), stock_str::securejoin_wait(&bob).await);
let msg = get_chat_msg(&bob, chat.get_id(), 1, 2).await;
assert!(msg.is_info());
assert_eq!(msg.get_text(), chat_protection_enabled(&bob).await);
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]