mirror of
https://github.com/chatmail/core.git
synced 2026-05-04 05:46:29 +03:00
feat(backwards-compat): For now, send Chat-Verified header (instead of _verified) again
This commit is contained in:
@@ -279,8 +279,10 @@ def test_verified_group_member_added_recovery(acfactory) -> None:
|
||||
ac1_contact_ac2 = ac1.create_contact(ac2)
|
||||
ac1_contact_ac3 = ac1.create_contact(ac3)
|
||||
ac1_contact_ac2_snapshot = ac1_contact_ac2.get_snapshot()
|
||||
assert ac1_contact_ac2_snapshot.is_verified
|
||||
assert ac1_contact_ac2_snapshot.verifier_id == ac1_contact_ac3.id
|
||||
# Until we reset verifications and then send the _verified header,
|
||||
# verification is not gossiped here:
|
||||
assert not ac1_contact_ac2_snapshot.is_verified
|
||||
assert ac1_contact_ac2_snapshot.verifier_id != ac1_contact_ac3.id
|
||||
|
||||
|
||||
def test_qr_join_chat_with_pending_bobstate_issue4894(acfactory):
|
||||
@@ -442,7 +444,9 @@ def test_gossip_verification(acfactory) -> None:
|
||||
|
||||
# Group propagates verification using Autocrypt-Gossip header.
|
||||
carol_contact_alice_snapshot = carol_contact_alice.get_snapshot()
|
||||
assert carol_contact_alice_snapshot.is_verified
|
||||
# Until we reset verifications and then send the _verified header,
|
||||
# verification is not gossiped here:
|
||||
assert not carol_contact_alice_snapshot.is_verified
|
||||
|
||||
logging.info("Bob creates a Securejoin group")
|
||||
bob_group_chat = bob.create_group("Securejoin Group")
|
||||
@@ -456,7 +460,9 @@ def test_gossip_verification(acfactory) -> None:
|
||||
|
||||
# Securejoin propagates verification.
|
||||
carol_contact_alice_snapshot = carol_contact_alice.get_snapshot()
|
||||
assert carol_contact_alice_snapshot.is_verified
|
||||
# Until we reset verifications and then send the _verified header,
|
||||
# verification is not gossiped here:
|
||||
assert not carol_contact_alice_snapshot.is_verified
|
||||
|
||||
|
||||
def test_securejoin_after_contact_resetup(acfactory) -> None:
|
||||
|
||||
@@ -116,7 +116,6 @@ class TestGroupStressTests:
|
||||
|
||||
def test_qr_verified_group_and_chatting(acfactory, lp):
|
||||
ac1, ac2, ac3 = acfactory.get_online_accounts(3)
|
||||
ac1_addr = ac1.get_self_contact().addr
|
||||
lp.sec("ac1: create verified-group QR, ac2 scans and joins")
|
||||
chat1 = ac1.create_group_chat("hello")
|
||||
qr = chat1.get_join_qr()
|
||||
@@ -174,7 +173,9 @@ def test_qr_verified_group_and_chatting(acfactory, lp):
|
||||
for ac2_contact in chat2.get_contacts():
|
||||
if ac2_contact == ac2_ac1_contact or ac2_contact.id == dc.const.DC_CONTACT_ID_SELF:
|
||||
continue
|
||||
assert ac2.get_self_contact().get_verifier(ac2_contact).addr == ac1_addr
|
||||
# Until we reset verifications and then send the _verified header,
|
||||
# verification is not gossiped here:
|
||||
assert ac2.get_self_contact().get_verifier(ac2_contact) is None
|
||||
|
||||
lp.sec("ac2: send message and let ac3 read it")
|
||||
chat2.send_text("hi")
|
||||
@@ -409,7 +410,9 @@ def test_verified_group_vs_delete_server_after(acfactory, tmp_path, lp):
|
||||
assert msg_in.text == "hi2"
|
||||
assert msg_in.chat == chat2_offl
|
||||
assert msg_in.get_sender_contact().addr == ac2.get_config("addr")
|
||||
assert ac2_offl_ac1_contact.is_verified()
|
||||
# Until we reset verifications and then send the _verified header,
|
||||
# verification is not gossiped here:
|
||||
assert not ac2_offl_ac1_contact.is_verified()
|
||||
|
||||
|
||||
def test_deleted_msgs_dont_reappear(acfactory):
|
||||
|
||||
@@ -1238,8 +1238,11 @@ def test_qr_email_capitalization(acfactory, lp):
|
||||
|
||||
# ac1 should see both ac3 and ac2 as verified.
|
||||
assert len(ac1_chat.get_contacts()) == 3
|
||||
# Until we reset verifications and then send the _verified header,
|
||||
# the verification of ac2 is not gossiped here:
|
||||
for contact in ac1_chat.get_contacts():
|
||||
assert contact.is_verified()
|
||||
is_ac2 = contact.addr == ac2.get_config("addr")
|
||||
assert contact.is_verified() != is_ac2
|
||||
|
||||
|
||||
def test_set_get_contact_avatar(acfactory, data, lp):
|
||||
|
||||
@@ -61,9 +61,11 @@ impl fmt::Display for Aheader {
|
||||
if self.prefer_encrypt == EncryptPreference::Mutual {
|
||||
write!(fmt, " prefer-encrypt=mutual;")?;
|
||||
}
|
||||
if self.verified {
|
||||
write!(fmt, " _verified=1;")?;
|
||||
}
|
||||
// TODO After we reset all existing verifications,
|
||||
// we want to start sending the _verified attribute
|
||||
// if self.verified {
|
||||
// write!(fmt, " _verified=1;")?;
|
||||
// }
|
||||
|
||||
// adds a whitespace every 78 characters, this allows
|
||||
// email crate to wrap the lines according to RFC 5322
|
||||
@@ -282,8 +284,9 @@ mod tests {
|
||||
.contains("test@example.com")
|
||||
);
|
||||
|
||||
// We don't send the _verified header yet:
|
||||
assert!(
|
||||
format!(
|
||||
!format!(
|
||||
"{}",
|
||||
Aheader {
|
||||
addr: "test@example.com".to_string(),
|
||||
|
||||
@@ -1352,6 +1352,43 @@ impl MimeFactory {
|
||||
let command = msg.param.get_cmd();
|
||||
let mut placeholdertext = None;
|
||||
|
||||
let send_verified_headers = match chat.typ {
|
||||
Chattype::Single => true,
|
||||
Chattype::Group => true,
|
||||
// Mailinglists and broadcast channels can actually never be verified:
|
||||
Chattype::Mailinglist => false,
|
||||
Chattype::OutBroadcast | Chattype::InBroadcast => false,
|
||||
};
|
||||
|
||||
if send_verified_headers {
|
||||
let was_protected: bool = context
|
||||
.sql
|
||||
.query_get_value("SELECT protected FROM chats WHERE id=?", (chat.id,))
|
||||
.await?
|
||||
.unwrap_or_default();
|
||||
|
||||
if was_protected {
|
||||
let unverified_member_exists = context
|
||||
.sql
|
||||
.exists(
|
||||
"SELECT COUNT(*)
|
||||
FROM contacts, chats_contacts
|
||||
WHERE chats_contacts.contact_id=contacts.id AND chats_contacts.chat_id=?
|
||||
AND contacts.id>9
|
||||
AND contacts.verifier=0",
|
||||
(chat.id,),
|
||||
)
|
||||
.await?;
|
||||
|
||||
if !unverified_member_exists {
|
||||
headers.push((
|
||||
"Chat-Verified",
|
||||
mail_builder::headers::raw::Raw::new("1").into(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if chat.typ == Chattype::Group {
|
||||
// Send group ID unless it is an ad hoc group that has no ID.
|
||||
if !chat.grpid.is_empty() {
|
||||
|
||||
@@ -3554,10 +3554,16 @@ async fn mark_recipients_as_verified(
|
||||
mimeparser: &MimeMessage,
|
||||
) -> Result<()> {
|
||||
let verifier_id = Some(from_id).filter(|&id| id != ContactId::SELF);
|
||||
|
||||
// We don't yet send the _verified property in autocrypt headers.
|
||||
// Until we do, we instead accept the Chat-Verified header as indication all contacts are verified.
|
||||
// TODO: Ignore ChatVerified header once we reset existing verifications.
|
||||
let chat_verified = mimeparser.get_header(HeaderDef::ChatVerified).is_some();
|
||||
|
||||
for gossiped_key in mimeparser
|
||||
.gossiped_keys
|
||||
.values()
|
||||
.filter(|gossiped_key| gossiped_key.verified)
|
||||
.filter(|gossiped_key| gossiped_key.verified || chat_verified)
|
||||
{
|
||||
let fingerprint = gossiped_key.public_key.dc_fingerprint().hex();
|
||||
let Some(to_id) = lookup_key_contact_by_fingerprint(context, &fingerprint).await? else {
|
||||
|
||||
@@ -5133,6 +5133,7 @@ async fn test_dont_reverify_by_self_on_outgoing_msg() -> Result<()> {
|
||||
let fiona = &tcm.fiona().await;
|
||||
|
||||
let bob_chat_id = chat::create_group(bob, "Group").await?;
|
||||
bob.set_chat_protected(bob_chat_id).await;
|
||||
let qr = get_securejoin_qr(bob, Some(bob_chat_id)).await?;
|
||||
tcm.exec_securejoin_qr(fiona, bob, &qr).await;
|
||||
tcm.exec_securejoin_qr(a0, bob, &qr).await;
|
||||
|
||||
@@ -1121,6 +1121,18 @@ impl TestContext {
|
||||
|
||||
chat_id
|
||||
}
|
||||
|
||||
/// Set the legacy `protected` column in the chats table to 1,
|
||||
/// because for now, only these chats that were once protected can be used
|
||||
/// to gossip verifications.
|
||||
// TODO remove the next statement
|
||||
// when we send the _verified header for all verified contacts
|
||||
pub(crate) async fn set_chat_protected(self: &TestContext, chat_id: chat::ChatId) {
|
||||
self.sql
|
||||
.execute("UPDATE chats SET protected=1 WHERE id=?", (chat_id,))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for TestContext {
|
||||
|
||||
@@ -97,6 +97,7 @@ async fn test_create_verified_oneonone_chat() -> Result<()> {
|
||||
let group_id = bob
|
||||
.create_group_with_members("Group with everyone", &[&alice, &fiona])
|
||||
.await;
|
||||
bob.set_chat_protected(group_id).await;
|
||||
assert_eq!(
|
||||
get_chat_msg(&bob, group_id, 0, 1).await.get_info_type(),
|
||||
SystemMessage::ChatE2ee
|
||||
@@ -735,6 +736,7 @@ async fn test_no_reverification() -> Result<()> {
|
||||
let alice_chat_id = alice
|
||||
.create_group_with_members("Group", &[bob, charlie, fiona])
|
||||
.await;
|
||||
alice.set_chat_protected(alice_chat_id).await;
|
||||
let alice_sent = alice.send_text(alice_chat_id, "Hi!").await;
|
||||
let bob_rcvd_msg = bob.recv_msg(&alice_sent).await;
|
||||
let bob_alice_id = bob_rcvd_msg.from_id;
|
||||
@@ -802,6 +804,7 @@ async fn test_no_direct_verification_via_bcc() -> Result<()> {
|
||||
mark_as_verified(alice, bob).await;
|
||||
|
||||
let alice_chat_id = alice.create_chat_id(bob).await;
|
||||
alice.set_chat_protected(alice_chat_id).await;
|
||||
let alice_sent_msg = alice.send_text(alice_chat_id, "Hello!").await;
|
||||
alice2.recv_msg(&alice_sent_msg).await;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user