mirror of
https://github.com/chatmail/core.git
synced 2026-10-01 18:50:39 +03:00
feat!: stop tracking contact verification
Since V2 a contact is its key, there is no address-to-key binding left to verify. The JSONRPC and FFI APIs are unchanged and report nothing as verified. BREAKING CHANGE: the statistics JSON sent to the self-reporting-bot on Android changes: Contacts have `encrypted` instead of `verified` and lose `transitive_chain` properties and message stats have `encrypted` instead of `verified` and `unverified_encrypted`, and securejoin invites lose `already_verified`. The collecting bot stores incoming reports verbatim but analysis will have to make sense of older and newer reports.
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use deltachat_contact_tools::EmailAddress;
|
||||
use regex::Regex;
|
||||
|
||||
@@ -8,7 +6,6 @@ use crate::chat::{CantSendReason, ChatId, add_contact_to_chat, remove_contact_fr
|
||||
use crate::chatlist::Chatlist;
|
||||
use crate::constants::Chattype;
|
||||
use crate::key::self_fingerprint;
|
||||
use crate::mimeparser::{GossipedKey, SystemMessage};
|
||||
use crate::qr::Qr;
|
||||
use crate::receive_imf::receive_imf;
|
||||
use crate::stock_str::{self, messages_e2ee_info_msg};
|
||||
@@ -16,7 +13,6 @@ use crate::test_utils::{
|
||||
AVATAR_64x64_BYTES, AVATAR_64x64_DEDUPLICATED, TestContext, TestContextManager,
|
||||
TimeShiftFalsePositiveNote, get_chat_msg, sync,
|
||||
};
|
||||
use crate::tools::SystemTime;
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum SetupContactCase {
|
||||
@@ -193,10 +189,7 @@ async fn test_setup_contact_ext(case: SetupContactCase) -> (TestContext, TestCon
|
||||
);
|
||||
|
||||
if case == SetupContactCase::WrongAliceGossip {
|
||||
let wrong_pubkey = GossipedKey {
|
||||
public_key: load_self_public_key(&bob).await.unwrap(),
|
||||
verified: false,
|
||||
};
|
||||
let wrong_pubkey = load_self_public_key(&bob).await.unwrap();
|
||||
let alice_pubkey = msg
|
||||
.gossiped_keys
|
||||
.insert(alice_addr.to_string(), wrong_pubkey)
|
||||
@@ -206,7 +199,6 @@ async fn test_setup_contact_ext(case: SetupContactCase) -> (TestContext, TestCon
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(handshake_msg, HandshakeMessage::Ignore);
|
||||
assert_eq!(contact_bob.is_verified(&alice).await.unwrap(), false);
|
||||
|
||||
msg.gossiped_keys
|
||||
.insert(alice_addr.to_string(), alice_pubkey)
|
||||
@@ -215,20 +207,17 @@ async fn test_setup_contact_ext(case: SetupContactCase) -> (TestContext, TestCon
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(handshake_msg, HandshakeMessage::Ignore);
|
||||
assert!(contact_bob.is_verified(&alice).await.unwrap());
|
||||
return (alice, bob);
|
||||
}
|
||||
|
||||
// Alice should not yet have Bob verified
|
||||
let contact_bob = alice.add_or_lookup_contact_no_key(&bob).await;
|
||||
let contact_bob_id = contact_bob.id;
|
||||
assert_eq!(contact_bob.is_key_contact(), true);
|
||||
assert_eq!(contact_bob.is_verified(&alice).await.unwrap(), false);
|
||||
assert_eq!(contact_bob.get_authname(), "");
|
||||
|
||||
tcm.section("Step 5+6: Alice receives vc-request-with-auth, sends vc-contact-confirm");
|
||||
alice.recv_msg_trash(&sent).await;
|
||||
assert_eq!(contact_bob.is_verified(&alice).await.unwrap(), true);
|
||||
assert_eq!(contact_bob.e2ee_avail(&alice).await.unwrap(), true);
|
||||
let contact_bob = Contact::get_by_id(&alice, contact_bob_id).await.unwrap();
|
||||
assert_eq!(contact_bob.get_authname(), "Bob Examplenet");
|
||||
assert!(contact_bob.get_name().is_empty());
|
||||
@@ -248,7 +237,7 @@ async fn test_setup_contact_ext(case: SetupContactCase) -> (TestContext, TestCon
|
||||
1
|
||||
);
|
||||
|
||||
// Check Alice got the verified message in her single chat.
|
||||
// Check Alice got the message in her single chat.
|
||||
{
|
||||
let chat = alice.get_chat(&bob).await;
|
||||
let msg = get_chat_msg(&alice, chat.get_id(), 0, 1).await;
|
||||
@@ -280,14 +269,14 @@ async fn test_setup_contact_ext(case: SetupContactCase) -> (TestContext, TestCon
|
||||
"vc-contact-confirm"
|
||||
);
|
||||
|
||||
// Bob has verified Alice already.
|
||||
// Bob has Alice's key already.
|
||||
//
|
||||
// Alice may not have verified Bob yet.
|
||||
assert_eq!(contact_alice.is_verified(&bob.ctx).await.unwrap(), true);
|
||||
// Alice may not have Bob's key yet.
|
||||
assert_eq!(contact_alice.e2ee_avail(&bob.ctx).await.unwrap(), true);
|
||||
|
||||
// Step 7: Bob receives vc-contact-confirm
|
||||
bob.recv_msg_trash(&sent).await;
|
||||
assert_eq!(contact_alice.is_verified(&bob.ctx).await.unwrap(), true);
|
||||
assert_eq!(contact_alice.e2ee_avail(&bob.ctx).await.unwrap(), true);
|
||||
let contact_alice = Contact::get_by_id(&bob.ctx, contact_alice_id)
|
||||
.await
|
||||
.unwrap();
|
||||
@@ -359,13 +348,11 @@ async fn test_setup_contact_bob_knows_alice() -> Result<()> {
|
||||
bob_fp.hex()
|
||||
);
|
||||
|
||||
// Alice should not yet have Bob verified
|
||||
let contact_bob = alice.add_or_lookup_contact_no_key(bob).await;
|
||||
assert_eq!(contact_bob.is_verified(alice).await?, false);
|
||||
|
||||
tcm.section("Step 5+6: Alice receives vc-request-with-auth, sends vc-contact-confirm");
|
||||
alice.recv_msg_trash(&sent).await;
|
||||
assert_eq!(contact_bob.is_verified(alice).await?, true);
|
||||
assert_eq!(contact_bob.e2ee_avail(alice).await?, true);
|
||||
|
||||
// Check Alice signalled success via the SecurejoinInviterProgress event.
|
||||
let event = alice
|
||||
@@ -399,16 +386,14 @@ async fn test_setup_contact_bob_knows_alice() -> Result<()> {
|
||||
"vc-contact-confirm"
|
||||
);
|
||||
|
||||
// Bob has verified Alice already.
|
||||
// Bob has Alice's key already.
|
||||
let contact_alice = bob.add_or_lookup_contact_no_key(alice).await;
|
||||
assert_eq!(contact_alice.is_verified(bob).await?, true);
|
||||
assert_eq!(contact_alice.e2ee_avail(bob).await?, true);
|
||||
|
||||
// Alice confirms that Bob is now verified.
|
||||
//
|
||||
// This does not change anything for Bob.
|
||||
tcm.section("Step 7: Bob receives vc-contact-confirm");
|
||||
bob.recv_msg_trash(&sent).await;
|
||||
assert_eq!(contact_alice.is_verified(bob).await?, true);
|
||||
assert_eq!(contact_alice.e2ee_avail(bob).await?, true);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -567,13 +552,11 @@ async fn test_secure_join_group_ext(v3: bool, remove_invite: bool) -> Result<()>
|
||||
bob_fp
|
||||
);
|
||||
|
||||
// Alice should not yet have Bob verified
|
||||
let contact_bob = alice.add_or_lookup_contact_no_key(&bob).await;
|
||||
assert_eq!(contact_bob.is_verified(&alice).await?, false);
|
||||
|
||||
tcm.section("Step 5+6: Alice receives vg-request-with-auth, sends vg-member-added");
|
||||
alice.recv_msg_trash(&sent).await;
|
||||
assert_eq!(contact_bob.is_verified(&alice).await?, true);
|
||||
assert_eq!(contact_bob.e2ee_avail(&alice).await?, true);
|
||||
|
||||
// Check Alice signalled success via the SecurejoinInviterProgress event.
|
||||
let event = alice
|
||||
@@ -615,7 +598,7 @@ async fn test_secure_join_group_ext(v3: bool, remove_invite: bool) -> Result<()>
|
||||
assert!(msg.get_header(HeaderDef::AutocryptGossip).is_some());
|
||||
|
||||
{
|
||||
// Now Alice's chat with Bob should still be hidden, the verified message should
|
||||
// Now Alice's chat with Bob should still be hidden, the member-added message should
|
||||
// appear in the group chat.
|
||||
if v3 {
|
||||
assert!(
|
||||
@@ -641,17 +624,17 @@ async fn test_secure_join_group_ext(v3: bool, remove_invite: bool) -> Result<()>
|
||||
assert_eq!(msg.get_text(), expected_text);
|
||||
}
|
||||
|
||||
// Bob has verified Alice already.
|
||||
// Bob has Alice's key already.
|
||||
//
|
||||
// Alice may not have verified Bob yet.
|
||||
// Alice may not have Bob's key yet.
|
||||
let contact_alice = bob.add_or_lookup_contact_no_key(&alice).await;
|
||||
assert_eq!(contact_alice.is_verified(&bob).await?, true);
|
||||
assert_eq!(contact_alice.e2ee_avail(&bob).await?, true);
|
||||
|
||||
tcm.section("Step 7: Bob receives vg-member-added");
|
||||
bob.recv_msg(&sent).await;
|
||||
{
|
||||
// Bob has Alice verified, message shows up in the group chat.
|
||||
assert_eq!(contact_alice.is_verified(&bob).await?, true);
|
||||
// The message shows up in the group chat.
|
||||
assert_eq!(contact_alice.e2ee_avail(&bob).await?, true);
|
||||
let chat = bob.get_chat(&alice).await;
|
||||
assert_eq!(
|
||||
chat.blocked,
|
||||
@@ -832,11 +815,7 @@ async fn test_unknown_sender() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Tests that Bob gets Alice as verified
|
||||
/// if `vc-contact-confirm` is lost.
|
||||
/// Previously `vc-contact-confirm` was used
|
||||
/// to confirm backward verification,
|
||||
/// but backward verification is not tracked anymore.
|
||||
/// Tests that Bob gets Alice's key if `vc-contact-confirm` is lost.
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_lost_contact_confirm() {
|
||||
let mut tcm = TestContextManager::new();
|
||||
@@ -858,16 +837,16 @@ async fn test_lost_contact_confirm() {
|
||||
let sent = bob.pop_sent_msg().await;
|
||||
alice.recv_msg_trash(&sent).await;
|
||||
|
||||
// Alice has Bob verified now.
|
||||
// Alice has Bob's key now.
|
||||
let contact_bob = alice.add_or_lookup_contact_no_key(&bob).await;
|
||||
assert_eq!(contact_bob.is_verified(&alice).await.unwrap(), true);
|
||||
assert_eq!(contact_bob.e2ee_avail(&alice).await.unwrap(), true);
|
||||
|
||||
// Alice sends vc-contact-confirm, but it gets lost.
|
||||
let _sent_vc_contact_confirm = alice.pop_sent_msg().await;
|
||||
|
||||
// Bob has alice as verified too, even though vc-contact-confirm is lost.
|
||||
// Bob has Alice's key too, even though vc-contact-confirm is lost.
|
||||
let contact_alice = bob.add_or_lookup_contact_no_key(&alice).await;
|
||||
assert_eq!(contact_alice.is_verified(&bob).await.unwrap(), true);
|
||||
assert_eq!(contact_alice.e2ee_avail(&bob).await.unwrap(), true);
|
||||
}
|
||||
|
||||
/// Tests Bob joining two groups by scanning two QR codes
|
||||
@@ -974,7 +953,7 @@ async fn test_parallel_setup_contact(bob_deletes_fiona_contact: bool) -> Result<
|
||||
|
||||
bob.recv_msg_trash(&sent_fiona_vc_contact_confirm).await;
|
||||
let bob_fiona_contact = Contact::get_by_id(bob, bob_fiona_contact_id).await.unwrap();
|
||||
assert_eq!(bob_fiona_contact.is_verified(bob).await.unwrap(), true);
|
||||
assert_eq!(bob_fiona_contact.e2ee_avail(bob).await.unwrap(), true);
|
||||
}
|
||||
|
||||
// Alice gets online and previously started SecureJoin process finishes.
|
||||
@@ -990,7 +969,7 @@ async fn test_parallel_setup_contact(bob_deletes_fiona_contact: bool) -> Result<
|
||||
bob.recv_msg_trash(&sent_alice_vc_contact_confirm).await;
|
||||
let bob_alice_contact_id = bob.add_or_lookup_contact_id(alice).await;
|
||||
let bob_alice_contact = Contact::get_by_id(bob, bob_alice_contact_id).await.unwrap();
|
||||
assert_eq!(bob_alice_contact.is_verified(bob).await.unwrap(), true);
|
||||
assert_eq!(bob_alice_contact.e2ee_avail(bob).await.unwrap(), true);
|
||||
|
||||
bob.assert_warn("Message does not match expected fingerprint")
|
||||
.await;
|
||||
@@ -1027,8 +1006,6 @@ async fn test_wrong_auth_token() -> Result<()> {
|
||||
|
||||
alice.recv_msg_trash(&sent).await;
|
||||
|
||||
let alice_bob_contact = alice.add_or_lookup_contact(bob).await;
|
||||
assert!(!alice_bob_contact.is_verified(alice).await?);
|
||||
alice.assert_warn("invalid auth code").await;
|
||||
Ok(())
|
||||
}
|
||||
@@ -1100,123 +1077,6 @@ async fn test_send_avatar_in_securejoin() -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Tests that scanning a QR code week later
|
||||
/// allows Bob to establish a contact with Alice,
|
||||
/// but does not mark Bob as verified for Alice.
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_expired_contact_auth_token() -> Result<()> {
|
||||
let mut tcm = TestContextManager::new();
|
||||
let alice = &tcm.alice().await;
|
||||
let bob = &tcm.bob().await;
|
||||
|
||||
// Alice creates a QR code.
|
||||
let qr = get_securejoin_qr(alice, None).await?;
|
||||
|
||||
// One week passes, QR code expires.
|
||||
SystemTime::shift(Duration::from_secs(7 * 24 * 3600));
|
||||
|
||||
// Bob scans the QR code.
|
||||
join_securejoin(bob, &qr).await?;
|
||||
|
||||
// vc-request
|
||||
alice.recv_msg_trash(&bob.pop_sent_msg().await).await;
|
||||
|
||||
// vc-auth-requried
|
||||
bob.recv_msg_trash(&alice.pop_sent_msg().await).await;
|
||||
|
||||
// vc-request-with-auth
|
||||
alice.recv_msg_trash(&bob.pop_sent_msg().await).await;
|
||||
|
||||
// Bob should not be verified for Alice.
|
||||
let contact_bob = alice.add_or_lookup_contact_no_key(bob).await;
|
||||
assert_eq!(contact_bob.is_verified(alice).await.unwrap(), false);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_expired_group_auth_token() -> Result<()> {
|
||||
let mut tcm = TestContextManager::new();
|
||||
let alice = &tcm.alice().await;
|
||||
let bob = &tcm.bob().await;
|
||||
|
||||
let alice_chat_id = chat::create_group(alice, "Group").await?;
|
||||
|
||||
// Alice creates a group QR code.
|
||||
let qr = get_securejoin_qr(alice, Some(alice_chat_id)).await.unwrap();
|
||||
|
||||
// One week passes, QR code expires.
|
||||
SystemTime::shift(Duration::from_secs(7 * 24 * 3600));
|
||||
|
||||
// Bob scans the QR code.
|
||||
join_securejoin(bob, &qr).await?;
|
||||
|
||||
// vg-request
|
||||
alice.recv_msg_trash(&bob.pop_sent_msg().await).await;
|
||||
|
||||
// vg-auth-requried
|
||||
bob.recv_msg_trash(&alice.pop_sent_msg().await).await;
|
||||
|
||||
// vg-request-with-auth
|
||||
alice.recv_msg_trash(&bob.pop_sent_msg().await).await;
|
||||
|
||||
// vg-member-added
|
||||
let bob_member_added_msg = bob.recv_msg(&alice.pop_sent_msg().await).await;
|
||||
assert!(bob_member_added_msg.is_info());
|
||||
assert_eq!(
|
||||
bob_member_added_msg.get_info_type(),
|
||||
SystemMessage::MemberAddedToGroup
|
||||
);
|
||||
|
||||
// Bob should not be verified for Alice.
|
||||
let contact_bob = alice.add_or_lookup_contact_no_key(bob).await;
|
||||
assert_eq!(contact_bob.is_verified(alice).await.unwrap(), false);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Tests that old token is considered expired
|
||||
/// even if sync message just arrived.
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_expired_synced_auth_token() -> Result<()> {
|
||||
let mut tcm = TestContextManager::new();
|
||||
let alice = &tcm.alice().await;
|
||||
let alice2 = &tcm.alice().await;
|
||||
let bob = &tcm.bob().await;
|
||||
|
||||
alice.set_config_bool(Config::SyncMsgs, true).await?;
|
||||
alice2.set_config_bool(Config::SyncMsgs, true).await?;
|
||||
|
||||
// Alice creates a QR code on the second device.
|
||||
let qr = get_securejoin_qr(alice2, None).await?;
|
||||
|
||||
alice2.send_sync_msg().await.unwrap();
|
||||
let sync_msg = alice2.pop_sent_msg().await;
|
||||
|
||||
// One week passes, QR code expires.
|
||||
SystemTime::shift(Duration::from_secs(7 * 24 * 3600));
|
||||
|
||||
alice.recv_msg_trash(&sync_msg).await;
|
||||
|
||||
// Bob scans the QR code.
|
||||
join_securejoin(bob, &qr).await?;
|
||||
|
||||
// vc-request
|
||||
alice.recv_msg_trash(&bob.pop_sent_msg().await).await;
|
||||
|
||||
// vc-auth-requried
|
||||
bob.recv_msg_trash(&alice.pop_sent_msg().await).await;
|
||||
|
||||
// vc-request-with-auth
|
||||
alice.recv_msg_trash(&bob.pop_sent_msg().await).await;
|
||||
|
||||
// Bob should not be verified for Alice.
|
||||
let contact_bob = alice.add_or_lookup_contact_no_key(bob).await;
|
||||
assert_eq!(contact_bob.is_verified(alice).await.unwrap(), false);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Tests that attempting to join already joined group does nothing.
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_rejoin_group() -> Result<()> {
|
||||
|
||||
Reference in New Issue
Block a user