diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 4da59e069..90e362bc9 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -378,13 +378,20 @@ impl MimeMessage { // signed part, but it doesn't match the outer one. // This _might_ be because the sender's mail server // replaced the sending address, e.g. in a mailing list. - // Or it's because someone is doing some replay attack - // - OTOH, I can't come up with an attack scenario - // where this would be useful. + // Or it's because someone is doing some replay attack. + // Resending encrypted messages via mailing lists + // without reencrypting is not useful anyway, + // so we return an error below. warn!( context, "From header in signed part doesn't match the outer one", ); + + // Return an error from the parser. + // This will result in creating a tombstone + // and no further message processing + // as if the MIME structure is broken. + bail!("From header is forged"); } } } diff --git a/src/receive_imf/tests.rs b/src/receive_imf/tests.rs index 6f814e2cb..3fa1da211 100644 --- a/src/receive_imf/tests.rs +++ b/src/receive_imf/tests.rs @@ -4241,3 +4241,22 @@ Chat-Group-Member-Added: charlie@example.com", Ok(()) } + +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_forged_from() -> Result<()> { + let mut tcm = TestContextManager::new(); + let alice = tcm.alice().await; + let bob = tcm.bob().await; + + let bob_chat_id = tcm.send_recv_accept(&alice, &bob, "hi").await.chat_id; + chat::send_text_msg(&bob, bob_chat_id, "hi!".to_string()).await?; + + let mut sent_msg = bob.pop_sent_msg().await; + sent_msg.payload = sent_msg + .payload + .replace("bob@example.net", "notbob@example.net"); + + let msg = alice.recv_msg(&sent_msg).await; + assert!(msg.chat_id.is_trash()); + Ok(()) +}