diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 6d7ffa78b..3dca2329a 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -17,7 +17,7 @@ use crate::message::{self, MessageState, MessengerMessage, MsgId}; use crate::mimeparser::*; use crate::param::*; use crate::peerstate::*; -use crate::securejoin::{self, handle_securejoin_handshake}; +use crate::securejoin::{self, handle_securejoin_handshake, observe_securejoin_on_other_device}; use crate::sql; use crate::stock::StockMessage; use crate::{contact, location}; @@ -340,11 +340,9 @@ fn add_parts( }; to_id = DC_CONTACT_ID_SELF; - // handshake messages must be processed _before_ chats are created - // (eg. contacs may be marked as verified) + // handshake may mark contacts as verified and must be processed before chats are created if mime_parser.get(HeaderDef::SecureJoin).is_some() { - // avoid discarding by show_emails setting - msgrmsg = MessengerMessage::Yes; + msgrmsg = MessengerMessage::Yes; // avoid discarding by show_emails setting *chat_id = ChatId::new(0); allow_creation = true; match handle_securejoin_handshake(context, mime_parser, from_id) { @@ -358,8 +356,7 @@ fn add_parts( state = MessageState::InSeen; } Ok(securejoin::HandshakeMessage::Propagate) => { - // Message will still be processed as "member - // added" or similar system message. + // process messages as "member added" normally } Err(err) => { *hidden = true; @@ -476,6 +473,27 @@ fn add_parts( // We cannot recreate other states (read, error). state = MessageState::OutDelivered; to_id = to_ids.get_index(0).cloned().unwrap_or_default(); + + // handshake may mark contacts as verified and must be processed before chats are created + if mime_parser.get(HeaderDef::SecureJoin).is_some() { + msgrmsg = MessengerMessage::Yes; // avoid discarding by show_emails setting + *chat_id = ChatId::new(0); + allow_creation = true; + match observe_securejoin_on_other_device(context, mime_parser, to_id) { + Ok(securejoin::HandshakeMessage::Done) + | Ok(securejoin::HandshakeMessage::Ignore) => { + *hidden = true; + } + Ok(securejoin::HandshakeMessage::Propagate) => { + // process messages as "member added" normally + } + Err(err) => { + *hidden = true; + error!(context, "Error in Secure-Join watching: {}", err); + } + } + } + if !to_ids.is_empty() { if chat_id.is_unset() { let (new_chat_id, new_chat_id_blocked) = create_or_lookup_group( diff --git a/src/securejoin.rs b/src/securejoin.rs index 28a8f0f7f..d6fce24a7 100644 --- a/src/securejoin.rs +++ b/src/securejoin.rs @@ -770,6 +770,38 @@ pub(crate) fn handle_securejoin_handshake( } } +/// observe_securejoin_on_other_device() must be called when a self-sent securejoin message is seen. +/// currently, the message is only ignored, in the future, +/// we may mark peers as verified accross devices: +/// +/// in a multi-device-setup, there may be other devices that "see" the handshake messages. +/// if the seen messages seen are self-sent messages encrypted+signed correctly with our key, +/// we can make some conclusions of it: +/// +/// - if we see the self-sent-message vg-member-added/vc-contact-confirm, +/// we know that we're an inviter-observer. +/// the inviting device has marked a peer as verified on vg-request-with-auth/vc-request-with-auth +/// before sending vg-member-added/vc-contact-confirm - so, if we observe vg-member-added/vc-contact-confirm, +/// we can mark the peer as verified as well. +/// +/// - if we see the self-sent-message vg-member-added-received +/// we know that we're an joiner-observer. +/// the joining device has marked the peer as verified on vg-member-added/vc-contact-confirm +/// before sending vg-member-added-received - so, if we observe vg-member-added-received, +/// we can mark the peer as verified as well. +/// +/// to make this work, (a) some messages must not be deleted, +/// (b) we need a vc-contact-confirm-received message if bcc_self is set, +/// (c) we should make sure, we do not only rely on the unencrypted To:-header for identifying the peer +/// (in handle_securejoin_handshake() we have the oob information for that) +pub(crate) fn observe_securejoin_on_other_device( + _context: &Context, + _mime_message: &MimeMessage, + _contact_id: u32, +) -> Result { + Ok(HandshakeMessage::Ignore) +} + fn secure_connection_established(context: &Context, contact_chat_id: ChatId) { let contact_id: u32 = chat_id_2_contact_id(context, contact_chat_id); let contact = Contact::get_by_id(context, contact_id);