mirror of
https://github.com/chatmail/core.git
synced 2026-05-08 01:16:31 +03:00
fix: don't leak Group-ID in Message-ID
Chat assignment based on In-Reply-To and References works good enough even if the message cannot be decrypted.
This commit is contained in:
24
src/chat.rs
24
src/chat.rs
@@ -1795,13 +1795,7 @@ impl Chat {
|
|||||||
let mut location_id = 0;
|
let mut location_id = 0;
|
||||||
|
|
||||||
let from = context.get_primary_self_addr().await?;
|
let from = context.get_primary_self_addr().await?;
|
||||||
let new_rfc724_mid = {
|
let new_rfc724_mid = create_outgoing_rfc724_mid(&from);
|
||||||
let grpid = match self.typ {
|
|
||||||
Chattype::Group => Some(self.grpid.as_str()),
|
|
||||||
_ => None,
|
|
||||||
};
|
|
||||||
create_outgoing_rfc724_mid(grpid, &from)
|
|
||||||
};
|
|
||||||
|
|
||||||
if self.typ == Chattype::Single {
|
if self.typ == Chattype::Single {
|
||||||
if let Some(id) = context
|
if let Some(id) = context
|
||||||
@@ -4151,7 +4145,7 @@ pub async fn add_device_msg_with_importance(
|
|||||||
if let Some(msg) = msg {
|
if let Some(msg) = msg {
|
||||||
chat_id = ChatId::get_for_contact(context, ContactId::DEVICE).await?;
|
chat_id = ChatId::get_for_contact(context, ContactId::DEVICE).await?;
|
||||||
|
|
||||||
let rfc724_mid = create_outgoing_rfc724_mid(None, "@device");
|
let rfc724_mid = create_outgoing_rfc724_mid("@device");
|
||||||
prepare_msg_blob(context, msg).await?;
|
prepare_msg_blob(context, msg).await?;
|
||||||
|
|
||||||
let timestamp_sent = create_smeared_timestamp(context);
|
let timestamp_sent = create_smeared_timestamp(context);
|
||||||
@@ -4291,7 +4285,7 @@ pub(crate) async fn add_info_msg_with_cmd(
|
|||||||
parent: Option<&Message>,
|
parent: Option<&Message>,
|
||||||
from_id: Option<ContactId>,
|
from_id: Option<ContactId>,
|
||||||
) -> Result<MsgId> {
|
) -> Result<MsgId> {
|
||||||
let rfc724_mid = create_outgoing_rfc724_mid(None, "@device");
|
let rfc724_mid = create_outgoing_rfc724_mid("@device");
|
||||||
let ephemeral_timer = chat_id.get_ephemeral_timer(context).await?;
|
let ephemeral_timer = chat_id.get_ephemeral_timer(context).await?;
|
||||||
|
|
||||||
let mut param = Params::new();
|
let mut param = Params::new();
|
||||||
@@ -5932,11 +5926,11 @@ mod tests {
|
|||||||
// Alice has an SMTP-server replacing the `Message-ID:`-header (as done eg. by outlook.com).
|
// Alice has an SMTP-server replacing the `Message-ID:`-header (as done eg. by outlook.com).
|
||||||
let sent_msg = alice.pop_sent_msg().await;
|
let sent_msg = alice.pop_sent_msg().await;
|
||||||
let msg = sent_msg.payload();
|
let msg = sent_msg.payload();
|
||||||
assert_eq!(msg.match_indices("Message-ID: <Gr.").count(), 2);
|
assert_eq!(msg.match_indices("Message-ID: <Mr.").count(), 2);
|
||||||
assert_eq!(msg.match_indices("References: <Gr.").count(), 1);
|
assert_eq!(msg.match_indices("References: <Mr.").count(), 1);
|
||||||
let msg = msg.replace("Message-ID: <Gr.", "Message-ID: <XXX");
|
let msg = msg.replace("Message-ID: <Mr.", "Message-ID: <XXX");
|
||||||
assert_eq!(msg.match_indices("Message-ID: <Gr.").count(), 0);
|
assert_eq!(msg.match_indices("Message-ID: <Mr.").count(), 0);
|
||||||
assert_eq!(msg.match_indices("References: <Gr.").count(), 1);
|
assert_eq!(msg.match_indices("References: <Mr.").count(), 1);
|
||||||
|
|
||||||
// Bob receives this message, he may detect group by `References:`- or `Chat-Group:`-header
|
// Bob receives this message, he may detect group by `References:`- or `Chat-Group:`-header
|
||||||
receive_imf(&bob, msg.as_bytes(), false).await.unwrap();
|
receive_imf(&bob, msg.as_bytes(), false).await.unwrap();
|
||||||
@@ -5953,7 +5947,7 @@ mod tests {
|
|||||||
send_text_msg(&bob, bob_chat.id, "ho!".to_string()).await?;
|
send_text_msg(&bob, bob_chat.id, "ho!".to_string()).await?;
|
||||||
let sent_msg = bob.pop_sent_msg().await;
|
let sent_msg = bob.pop_sent_msg().await;
|
||||||
let msg = sent_msg.payload();
|
let msg = sent_msg.payload();
|
||||||
let msg = msg.replace("Message-ID: <Gr.", "Message-ID: <XXX");
|
let msg = msg.replace("Message-ID: <Mr.", "Message-ID: <XXX");
|
||||||
let msg = msg.replace("Chat-", "XXXX-");
|
let msg = msg.replace("Chat-", "XXXX-");
|
||||||
assert_eq!(msg.match_indices("Chat-").count(), 0);
|
assert_eq!(msg.match_indices("Chat-").count(), 0);
|
||||||
|
|
||||||
|
|||||||
@@ -1359,7 +1359,7 @@ mod tests {
|
|||||||
\n\
|
\n\
|
||||||
hello\n",
|
hello\n",
|
||||||
contact.get_addr(),
|
contact.get_addr(),
|
||||||
create_outgoing_rfc724_mid(None, contact.get_addr())
|
create_outgoing_rfc724_mid(contact.get_addr())
|
||||||
);
|
);
|
||||||
println!("{msg}");
|
println!("{msg}");
|
||||||
receive_imf(t, msg.as_bytes(), false).await.unwrap();
|
receive_imf(t, msg.as_bytes(), false).await.unwrap();
|
||||||
|
|||||||
@@ -551,7 +551,7 @@ impl<'a> MimeFactory<'a> {
|
|||||||
|
|
||||||
let rfc724_mid = match self.loaded {
|
let rfc724_mid = match self.loaded {
|
||||||
Loaded::Message { .. } => self.msg.rfc724_mid.clone(),
|
Loaded::Message { .. } => self.msg.rfc724_mid.clone(),
|
||||||
Loaded::Mdn { .. } => create_outgoing_rfc724_mid(None, &self.from_addr),
|
Loaded::Mdn { .. } => create_outgoing_rfc724_mid(&self.from_addr),
|
||||||
};
|
};
|
||||||
let rfc724_mid_headervalue = render_rfc724_mid(&rfc724_mid);
|
let rfc724_mid_headervalue = render_rfc724_mid(&rfc724_mid);
|
||||||
let rfc724_mid_header = Header::new("Message-ID".into(), rfc724_mid_headervalue);
|
let rfc724_mid_header = Header::new("Message-ID".into(), rfc724_mid_headervalue);
|
||||||
|
|||||||
20
src/tools.rs
20
src/tools.rs
@@ -281,15 +281,12 @@ pub(crate) fn create_id() -> String {
|
|||||||
/// - this function is called for all outgoing messages.
|
/// - this function is called for all outgoing messages.
|
||||||
/// - the message ID should be globally unique
|
/// - the message ID should be globally unique
|
||||||
/// - do not add a counter or any private data as this leaks information unnecessarily
|
/// - do not add a counter or any private data as this leaks information unnecessarily
|
||||||
pub(crate) fn create_outgoing_rfc724_mid(grpid: Option<&str>, from_addr: &str) -> String {
|
pub(crate) fn create_outgoing_rfc724_mid(from_addr: &str) -> String {
|
||||||
let hostname = from_addr
|
let hostname = from_addr
|
||||||
.find('@')
|
.find('@')
|
||||||
.and_then(|k| from_addr.get(k..))
|
.and_then(|k| from_addr.get(k..))
|
||||||
.unwrap_or("@nohost");
|
.unwrap_or("@nohost");
|
||||||
match grpid {
|
format!("Mr.{}.{}{}", create_id(), create_id(), hostname)
|
||||||
Some(grpid) => format!("Gr.{}.{}{}", grpid, create_id(), hostname),
|
|
||||||
None => format!("Mr.{}.{}{}", create_id(), create_id(), hostname),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract the group id (grpid) from a message id (mid)
|
/// Extract the group id (grpid) from a message id (mid)
|
||||||
@@ -1013,21 +1010,10 @@ DKIM Results: Passed=true, Works=true, Allow_Keychange=true";
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_create_outgoing_rfc724_mid() {
|
fn test_create_outgoing_rfc724_mid() {
|
||||||
// create a normal message-id
|
let mid = create_outgoing_rfc724_mid("foo@bar.de");
|
||||||
let mid = create_outgoing_rfc724_mid(None, "foo@bar.de");
|
|
||||||
assert!(mid.starts_with("Mr."));
|
assert!(mid.starts_with("Mr."));
|
||||||
assert!(mid.ends_with("bar.de"));
|
assert!(mid.ends_with("bar.de"));
|
||||||
assert!(extract_grpid_from_rfc724_mid(mid.as_str()).is_none());
|
assert!(extract_grpid_from_rfc724_mid(mid.as_str()).is_none());
|
||||||
|
|
||||||
// create a message-id containing a group-id
|
|
||||||
let grpid = create_id();
|
|
||||||
let mid = create_outgoing_rfc724_mid(Some(&grpid), "foo@bar.de");
|
|
||||||
assert!(mid.starts_with("Gr."));
|
|
||||||
assert!(mid.ends_with("bar.de"));
|
|
||||||
assert_eq!(
|
|
||||||
extract_grpid_from_rfc724_mid(mid.as_str()),
|
|
||||||
Some(grpid.as_str())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user