mirror of
https://github.com/chatmail/core.git
synced 2026-04-20 23:16:30 +03:00
feat: Auto-restore 1:1 chat protection after receiving old unverified message
I.e. add the "Messages are guaranteed to be end-to-end encrypted from now on." message and mark the chat as protected again because no user action is required in this case. There are a couple of problems though: - If the program crashes earlier than the protection is restored, the chat remains protection-broken. But this problem already exists because `ChatId::set_protection()` is never retried. - If multiple old unverified messages are received, protection messages added in between don't annihilate, so they clutter the chat.
This commit is contained in:
@@ -762,6 +762,7 @@ async fn add_parts(
|
||||
let state: MessageState;
|
||||
let mut hidden = false;
|
||||
let mut needs_delete_job = false;
|
||||
let mut restore_protection = false;
|
||||
|
||||
// if contact renaming is prevented (for mailinglists and bots),
|
||||
// we use name from From:-header as override name
|
||||
@@ -1006,6 +1007,13 @@ async fn add_parts(
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
if let Some(peerstate) = &mime_parser.decryption_info.peerstate {
|
||||
restore_protection = new_protection != ProtectionStatus::Protected
|
||||
&& peerstate.prefer_encrypt == EncryptPreference::Mutual
|
||||
// Check that the contact still has the Autocrypt key same as the
|
||||
// verified key, see also `Peerstate::is_using_verified_key()`.
|
||||
&& contact.is_verified(context).await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1741,7 +1749,16 @@ RETURNING id
|
||||
// delete it.
|
||||
needs_delete_job = true;
|
||||
}
|
||||
|
||||
if restore_protection {
|
||||
chat_id
|
||||
.set_protection(
|
||||
context,
|
||||
ProtectionStatus::Protected,
|
||||
mime_parser.timestamp_rcvd,
|
||||
Some(from_id),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
Ok(ReceivedMsg {
|
||||
chat_id,
|
||||
state,
|
||||
|
||||
@@ -297,6 +297,7 @@ async fn test_verified_oneonone_chat_enable_disable() -> Result<()> {
|
||||
assert!(chat.is_protected());
|
||||
|
||||
for alice_accepts_breakage in [true, false] {
|
||||
SystemTime::shift(std::time::Duration::from_secs(300));
|
||||
// Bob uses Thunderbird to send a message
|
||||
receive_imf(
|
||||
&alice,
|
||||
@@ -760,10 +761,14 @@ async fn test_message_from_old_dc_setup() -> Result<()> {
|
||||
// The outdated Bob's Autocrypt header isn't applied, so the verification preserves.
|
||||
assert!(contact.is_verified(alice).await.unwrap());
|
||||
let chat = alice.get_chat(bob).await;
|
||||
// But the chat protection is broken because the old message is sorted to the bottom as it
|
||||
// mustn't be sorted over the protection info message (which is `InNoticed` moreover).
|
||||
assert_eq!(chat.is_protected(), false);
|
||||
assert_eq!(chat.is_protection_broken(), true);
|
||||
assert!(chat.is_protected());
|
||||
assert_eq!(chat.is_protection_broken(), false);
|
||||
let protection_msg = alice.get_last_msg().await;
|
||||
assert_eq!(
|
||||
protection_msg.param.get_cmd(),
|
||||
SystemMessage::ChatProtectionEnabled
|
||||
);
|
||||
assert!(protection_msg.timestamp_sort >= msg.timestamp_rcvd);
|
||||
alice
|
||||
.golden_test_chat(msg.chat_id, "verified_chats_message_from_old_dc_setup")
|
||||
.await;
|
||||
|
||||
Reference in New Issue
Block a user