(AEAP) Revert #3491, instead only replace contacts in verified groups (#3510)

#3491 introduced a bug that your address is only replaced in the first group you write to, which was rather hard to fix. In order to be able to release something, we agreed to revert it and instead only replace the contacts in verified groups (and in broadcast lists, if the signing key is verified).

Highlights:

* Revert "Only do the AEAP transition in the chat where it happened"

This reverts commit 22f4cd7b79.

* Only do the transition for verified groups (and broadcast lists)

To be exact, only do the transition if the signing key fingerpring is
verified. And only do it in verified groups and broadcast lists

* Slightly adapt string to this change

* Changelog
This commit is contained in:
Hocuri
2022-07-16 23:03:34 +02:00
committed by GitHub
parent 5f779ca9b2
commit 9f2100deee
6 changed files with 138 additions and 104 deletions

View File

@@ -69,24 +69,24 @@ Message w/out In-Reply-To
}
enum ChatForTransition {
// OneToOne,
OneToOne,
GroupChat,
VerifiedGroup,
}
use ChatForTransition::*;
// #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
// async fn test_aeap_transition_0() {
// check_aeap_transition(OneToOne, false, false).await;
// }
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_aeap_transition_0() {
check_aeap_transition(OneToOne, false, false).await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_aeap_transition_1() {
check_aeap_transition(GroupChat, false, false).await;
}
// #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
// async fn test_aeap_transition_0_verified() {
// check_aeap_transition(OneToOne, true, false).await;
// }
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_aeap_transition_0_verified() {
check_aeap_transition(OneToOne, true, false).await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_aeap_transition_1_verified() {
check_aeap_transition(GroupChat, true, false).await;
@@ -96,18 +96,18 @@ async fn test_aeap_transition_2_verified() {
check_aeap_transition(VerifiedGroup, true, false).await;
}
// #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
// async fn test_aeap_transition_0_bob_knew_new_addr() {
// check_aeap_transition(OneToOne, false, true).await;
// }
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_aeap_transition_0_bob_knew_new_addr() {
check_aeap_transition(OneToOne, false, true).await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_aeap_transition_1_bob_knew_new_addr() {
check_aeap_transition(GroupChat, false, true).await;
}
// #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
// async fn test_aeap_transition_0_verified_bob_knew_new_addr() {
// check_aeap_transition(OneToOne, true, true).await;
// }
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_aeap_transition_0_verified_bob_knew_new_addr() {
check_aeap_transition(OneToOne, true, true).await;
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_aeap_transition_1_verified_bob_knew_new_addr() {
check_aeap_transition(GroupChat, true, true).await;
@@ -184,9 +184,11 @@ async fn check_aeap_transition(
let already_new_contact = Contact::create(&bob, "Alice", "fiona@example.net")
.await
.unwrap();
chat::add_contact_to_chat(&bob, groups[0], already_new_contact)
.await
.unwrap();
if verified {
chat::add_contact_to_chat(&bob, groups[2], already_new_contact)
.await
.unwrap();
}
// groups 0 and 2 stay unpromoted (i.e. local
// on Bob's device, Alice doesn't know about them)
@@ -206,7 +208,7 @@ async fn check_aeap_transition(
tcm.section("Alice sends another message to Bob, this time from her new addr");
// No matter which chat Alice sends to, the transition should be done in all groups
let chat_to_send = match chat_for_transition {
// OneToOne => alice.create_chat(&bob).await.id,
OneToOne => alice.create_chat(&bob).await.id,
GroupChat => group1_alice,
VerifiedGroup => group3_alice.expect("No verified group"),
};
@@ -219,8 +221,7 @@ async fn check_aeap_transition(
tcm.section("Check that the AEAP transition worked");
check_that_transition_worked(
// The transition is only done in the chat where the message was sent for now:
&[recvd.chat_id],
&groups[2..],
&alice,
"alice@example.org",
ALICE_NEW_ADDR,
@@ -228,6 +229,7 @@ async fn check_aeap_transition(
&bob,
)
.await;
check_no_transition_done(&groups[0..2], "alice@example.org", &bob).await;
// Assert that the autocrypt header is also applied to the peerstate
// if the address changed
@@ -247,8 +249,7 @@ async fn check_aeap_transition(
assert_eq!(recvd.text.unwrap(), "Hello from my old addr!");
check_that_transition_worked(
// The transition is only done in the chat where the message was sent for now:
&[recvd.chat_id],
&groups[2..],
&alice,
// Note that "alice@example.org" and ALICE_NEW_ADDR are switched now:
ALICE_NEW_ADDR,
@@ -276,11 +277,19 @@ async fn check_that_transition_worked(
let members = chat::get_chat_contacts(bob, *group).await.unwrap();
// In all the groups, exactly Bob and Alice's new number are members.
// (and Alice's new number isn't in there twice)
assert_eq!(members.len(), 2);
assert_eq!(
members.len(),
2,
"Group {} has members {:?}, but should have members {:?} and {:?}",
group,
&members,
new_contact,
ContactId::SELF
);
assert!(members.contains(&new_contact));
assert!(members.contains(&ContactId::SELF));
let info_msg = get_last_info_msg(bob, *group).await;
let info_msg = get_last_info_msg(bob, *group).await.unwrap();
let expected_text =
stock_str::aeap_addr_changed(bob, name, old_alice_addr, new_alice_addr).await;
assert_eq!(info_msg.text.unwrap(), expected_text);
@@ -293,6 +302,36 @@ async fn check_that_transition_worked(
}
}
async fn check_no_transition_done(groups: &[ChatId], old_alice_addr: &str, bob: &TestContext) {
let old_contact = Contact::lookup_id_by_addr(bob, old_alice_addr, contact::Origin::Unknown)
.await
.unwrap()
.unwrap();
for group in groups {
let members = chat::get_chat_contacts(bob, *group).await.unwrap();
// In all the groups, exactly Bob and Alice's _old_ number are members.
assert_eq!(
members.len(),
2,
"Group {} has members {:?}, but should have members {:?} and {:?}",
group,
&members,
old_contact,
ContactId::SELF
);
assert!(members.contains(&old_contact));
assert!(members.contains(&ContactId::SELF));
let last_info_msg = get_last_info_msg(bob, *group).await;
assert!(
last_info_msg.is_none(),
"{:?} shouldn't be there (or it's an unrelated info msg)",
last_info_msg
);
}
}
async fn mark_as_verified(this: &TestContext, other: &TestContext) {
let other_addr = other.get_primary_self_addr().await.unwrap();
let mut peerstate = peerstate::Peerstate::from_addr(this, &other_addr)
@@ -307,16 +346,16 @@ async fn mark_as_verified(this: &TestContext, other: &TestContext) {
peerstate.save_to_db(&this.sql, false).await.unwrap();
}
async fn get_last_info_msg(t: &TestContext, chat_id: ChatId) -> Message {
async fn get_last_info_msg(t: &TestContext, chat_id: ChatId) -> Option<Message> {
let msgs = chat::get_chat_msgs(&t.ctx, chat_id, constants::DC_GCM_INFO_ONLY)
.await
.unwrap();
let msg_id = if let chat::ChatItem::Message { msg_id } = msgs.last().unwrap() {
let msg_id = if let chat::ChatItem::Message { msg_id } = msgs.last()? {
msg_id
} else {
panic!("Wrong item type");
return None;
};
Message::load_from_db(&t.ctx, *msg_id).await.unwrap()
Some(Message::load_from_db(&t.ctx, *msg_id).await.unwrap())
}
/// Test that an attacker - here Fiona - can't replay a message sent by Alice