mirror of
https://github.com/chatmail/core.git
synced 2026-05-09 01:46:30 +03:00
feat: protect Autocrypt header
This commit is contained in:
@@ -389,12 +389,6 @@ pub enum Config {
|
|||||||
/// Make all outgoing messages with Autocrypt header "multipart/signed".
|
/// Make all outgoing messages with Autocrypt header "multipart/signed".
|
||||||
SignUnencrypted,
|
SignUnencrypted,
|
||||||
|
|
||||||
/// Enable header protection for `Autocrypt` header.
|
|
||||||
///
|
|
||||||
/// This is an experimental setting not compatible to other MUAs
|
|
||||||
/// and older Delta Chat versions (core version <= v1.149.0).
|
|
||||||
ProtectAutocrypt,
|
|
||||||
|
|
||||||
/// Let the core save all events to the database.
|
/// Let the core save all events to the database.
|
||||||
/// This value is used internally to remember the MsgId of the logging xdc
|
/// This value is used internally to remember the MsgId of the logging xdc
|
||||||
#[strum(props(default = "0"))]
|
#[strum(props(default = "0"))]
|
||||||
|
|||||||
@@ -1035,12 +1035,6 @@ impl Context {
|
|||||||
.await?
|
.await?
|
||||||
.to_string(),
|
.to_string(),
|
||||||
);
|
);
|
||||||
res.insert(
|
|
||||||
"protect_autocrypt",
|
|
||||||
self.get_config_int(Config::ProtectAutocrypt)
|
|
||||||
.await?
|
|
||||||
.to_string(),
|
|
||||||
);
|
|
||||||
res.insert(
|
res.insert(
|
||||||
"debug_logging",
|
"debug_logging",
|
||||||
self.get_config_int(Config::DebugLogging).await?.to_string(),
|
self.get_config_int(Config::DebugLogging).await?.to_string(),
|
||||||
|
|||||||
@@ -964,10 +964,6 @@ impl MimeFactory {
|
|||||||
hidden_headers.push(header.clone());
|
hidden_headers.push(header.clone());
|
||||||
} else if is_hidden(&header_name) {
|
} else if is_hidden(&header_name) {
|
||||||
hidden_headers.push(header.clone());
|
hidden_headers.push(header.clone());
|
||||||
} else if header_name == "autocrypt"
|
|
||||||
&& !context.get_config_bool(Config::ProtectAutocrypt).await?
|
|
||||||
{
|
|
||||||
unprotected_headers.push(header.clone());
|
|
||||||
} else if header_name == "from" {
|
} else if header_name == "from" {
|
||||||
// Unencrypted securejoin messages should _not_ include the display name:
|
// Unencrypted securejoin messages should _not_ include the display name:
|
||||||
if is_encrypted || !is_securejoin_message {
|
if is_encrypted || !is_securejoin_message {
|
||||||
|
|||||||
@@ -666,7 +666,7 @@ async fn test_selfavatar_unencrypted_signed() {
|
|||||||
assert_eq!(part.match_indices("From:").count(), 1);
|
assert_eq!(part.match_indices("From:").count(), 1);
|
||||||
assert_eq!(part.match_indices("Message-ID:").count(), 0);
|
assert_eq!(part.match_indices("Message-ID:").count(), 0);
|
||||||
assert_eq!(part.match_indices("Subject:").count(), 1);
|
assert_eq!(part.match_indices("Subject:").count(), 1);
|
||||||
assert_eq!(part.match_indices("Autocrypt:").count(), 0);
|
assert_eq!(part.match_indices("Autocrypt:").count(), 1);
|
||||||
assert_eq!(part.match_indices("Chat-User-Avatar:").count(), 0);
|
assert_eq!(part.match_indices("Chat-User-Avatar:").count(), 0);
|
||||||
|
|
||||||
let part = payload.next().unwrap();
|
let part = payload.next().unwrap();
|
||||||
@@ -717,7 +717,7 @@ async fn test_selfavatar_unencrypted_signed() {
|
|||||||
assert_eq!(part.match_indices("From:").count(), 1);
|
assert_eq!(part.match_indices("From:").count(), 1);
|
||||||
assert_eq!(part.match_indices("Message-ID:").count(), 0);
|
assert_eq!(part.match_indices("Message-ID:").count(), 0);
|
||||||
assert_eq!(part.match_indices("Subject:").count(), 1);
|
assert_eq!(part.match_indices("Subject:").count(), 1);
|
||||||
assert_eq!(part.match_indices("Autocrypt:").count(), 0);
|
assert_eq!(part.match_indices("Autocrypt:").count(), 1);
|
||||||
assert_eq!(part.match_indices("Chat-User-Avatar:").count(), 0);
|
assert_eq!(part.match_indices("Chat-User-Avatar:").count(), 0);
|
||||||
|
|
||||||
let part = payload.next().unwrap();
|
let part = payload.next().unwrap();
|
||||||
|
|||||||
@@ -1817,39 +1817,6 @@ async fn test_take_last_header() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn test_protect_autocrypt(enabled: bool) -> Result<()> {
|
|
||||||
let mut tcm = TestContextManager::new();
|
|
||||||
let alice = &tcm.alice().await;
|
|
||||||
let bob = &tcm.bob().await;
|
|
||||||
|
|
||||||
let chat = alice.create_chat(bob).await;
|
|
||||||
alice
|
|
||||||
.set_config_bool(Config::ProtectAutocrypt, enabled)
|
|
||||||
.await?;
|
|
||||||
let sent = alice.send_text(chat.id, "Hello!").await;
|
|
||||||
assert_eq!(sent.payload().contains("Autocrypt: "), !enabled);
|
|
||||||
let msg = bob.recv_msg(&sent).await;
|
|
||||||
assert_eq!(msg.get_showpadlock(), true);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tests that if `protect_autocrypt` is enabled,
|
|
||||||
/// `Autocrypt` header does not appear in the outer headers
|
|
||||||
/// of encrypted messages.
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
||||||
async fn test_protect_autocrypt_enabled() -> Result<()> {
|
|
||||||
test_protect_autocrypt(true).await
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tests that if `protect_autocrypt` is disabled,
|
|
||||||
/// `Autocrypt` header appears in the outer headers
|
|
||||||
/// of encrypted messages.
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
|
||||||
async fn test_protect_autocrypt_false() -> Result<()> {
|
|
||||||
test_protect_autocrypt(false).await
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tests that CRLF before MIME boundary
|
/// Tests that CRLF before MIME boundary
|
||||||
/// is not treated as the part body.
|
/// is not treated as the part body.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -217,10 +217,12 @@ async fn test_aeap_replay_attack() -> Result<()> {
|
|||||||
// Fiona gets the message, replaces the From addr...
|
// Fiona gets the message, replaces the From addr...
|
||||||
let sent = sent
|
let sent = sent
|
||||||
.payload()
|
.payload()
|
||||||
.replace("From: <alice@example.org>", "From: <fiona@example.net>")
|
.replace("From: <alice@example.org>", "From: <fiona@example.net>");
|
||||||
.replace("addr=alice@example.org;", "addr=fiona@example.net;");
|
|
||||||
sent.find("From: <fiona@example.net>").unwrap(); // Assert that it worked
|
sent.find("From: <fiona@example.net>").unwrap(); // Assert that it worked
|
||||||
sent.find("addr=fiona@example.net;").unwrap(); // Assert that it worked
|
|
||||||
|
// Autocrypt header is protected, nothing to replace outside.
|
||||||
|
// In the signed part we cannot replace it without breaking the signature.
|
||||||
|
assert!(!sent.contains("addr=alice@example.org;"));
|
||||||
|
|
||||||
tcm.section("Fiona replaced the From addr and forwards the message to Bob");
|
tcm.section("Fiona replaced the From addr and forwards the message to Bob");
|
||||||
receive_imf(&bob, sent.as_bytes(), false).await?.unwrap();
|
receive_imf(&bob, sent.as_bytes(), false).await?.unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user