Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions deltachat-rpc-client/tests/test_securejoin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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")
Expand All @@ -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:
Expand Down
9 changes: 6 additions & 3 deletions python/tests/test_0_complex_or_slow.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ def test_synchronize_member_list_on_group_rejoin(self, acfactory, lp):

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()
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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):
Expand Down
5 changes: 4 additions & 1 deletion python/tests/test_1_online.py
Original file line number Diff line number Diff line change
Expand Up @@ -1252,8 +1252,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):
Expand Down
11 changes: 7 additions & 4 deletions src/aheader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -282,8 +284,9 @@ mod tests {
.contains("[email protected]")
);

// We don't send the _verified header yet:
assert!(
format!(
!format!(
"{}",
Aheader {
addr: "[email protected]".to_string(),
Expand Down
37 changes: 37 additions & 0 deletions src/mimefactory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1353,6 +1353,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() {
Expand Down
8 changes: 7 additions & 1 deletion src/receive_imf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3568,10 +3568,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 {
Expand Down
1 change: 1 addition & 0 deletions src/receive_imf/receive_imf_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5135,6 +5135,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;
Expand Down
12 changes: 12 additions & 0 deletions src/test_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1122,6 +1122,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 {
Expand Down
3 changes: 3 additions & 0 deletions src/tests/verified_chats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down
Loading