-
-
Notifications
You must be signed in to change notification settings - Fork 89
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: Never allow a message timestamp to be a lot in the future (#5249)
We must finish what was started in #5088.
- Loading branch information
Showing
1 changed file
with
44 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -208,11 +208,12 @@ impl MimeMessage { | |
) -> Result<Self> { | ||
let mail = mailparse::parse_mail(body)?; | ||
|
||
let message_time = mail | ||
let timestamp_rcvd = smeared_time(context); | ||
let timestamp_sent = mail | ||
.headers | ||
.get_header_value(HeaderDef::Date) | ||
.and_then(|v| mailparse::dateparse(&v).ok()) | ||
.unwrap_or_default(); | ||
.map_or(timestamp_rcvd, |value| min(value, timestamp_rcvd + 60)); | ||
let mut hop_info = parse_receive_headers(&mail.get_headers()); | ||
|
||
let mut headers = Default::default(); | ||
|
@@ -279,7 +280,7 @@ impl MimeMessage { | |
let private_keyring = load_self_secret_keyring(context).await?; | ||
|
||
let mut decryption_info = | ||
prepare_decryption(context, &mail, &from.addr, message_time).await?; | ||
prepare_decryption(context, &mail, &from.addr, timestamp_sent).await?; | ||
|
||
// Memory location for a possible decrypted message. | ||
let mut mail_raw = Vec::new(); | ||
|
@@ -325,7 +326,7 @@ impl MimeMessage { | |
let gossip_headers = mail.headers.get_all_values("Autocrypt-Gossip"); | ||
gossiped_keys = update_gossip_peerstates( | ||
context, | ||
message_time, | ||
timestamp_sent, | ||
&from.addr, | ||
&recipients, | ||
gossip_headers, | ||
|
@@ -376,12 +377,12 @@ impl MimeMessage { | |
|
||
// If it is not a read receipt, degrade encryption. | ||
if let (Some(peerstate), Ok(mail)) = (&mut decryption_info.peerstate, mail) { | ||
if message_time > peerstate.last_seen_autocrypt | ||
if timestamp_sent > peerstate.last_seen_autocrypt | ||
&& mail.ctype.mimetype != "multipart/report" | ||
// Disallowing keychanges is disabled for now: | ||
// && decryption_info.dkim_results.allow_keychange | ||
{ | ||
peerstate.degrade_encryption(message_time); | ||
peerstate.degrade_encryption(timestamp_sent); | ||
} | ||
} | ||
} | ||
|
@@ -395,12 +396,6 @@ impl MimeMessage { | |
} | ||
} | ||
|
||
let timestamp_rcvd = smeared_time(context); | ||
let timestamp_sent = headers | ||
.get(HeaderDef::Date.get_headername()) | ||
.and_then(|value| mailparse::dateparse(value).ok()) | ||
.map_or(timestamp_rcvd, |value| min(value, timestamp_rcvd + 60)); | ||
|
||
let mut parser = MimeMessage { | ||
parts: Vec::new(), | ||
headers, | ||
|
@@ -2237,6 +2232,7 @@ mod tests { | |
message::{Message, MessageState, MessengerMessage}, | ||
receive_imf::receive_imf, | ||
test_utils::TestContext, | ||
tools::time, | ||
}; | ||
|
||
impl AvatarAction { | ||
|
@@ -3849,4 +3845,40 @@ Content-Disposition: reaction\n\ | |
|
||
Ok(()) | ||
} | ||
|
||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)] | ||
async fn test_time_in_future() -> Result<()> { | ||
let alice = TestContext::new_alice().await; | ||
|
||
let beginning_time = time(); | ||
|
||
// Receive a message with a date far in the future (year 3004) | ||
// I'm just going to assume that no one uses this code after the year 3000 | ||
let mime_message = MimeMessage::from_bytes( | ||
&alice, | ||
b"To: [email protected]\n\ | ||
From: [email protected]\n\ | ||
Date: Today, 29 February 3004 00:00:10 -800\n\ | ||
Message-ID: [email protected]\n\ | ||
Subject: Meeting\n\ | ||
Mime-Version: 1.0 (1.0)\n\ | ||
Content-Type: text/plain; charset=utf-8\n\ | ||
\n\ | ||
Hi", | ||
None, | ||
) | ||
.await?; | ||
|
||
// We do allow the time to be in the future a bit (because of unsynchronized clocks), | ||
// but only 60 seconds: | ||
assert!(mime_message.decryption_info.message_time <= time() + 60); | ||
assert!(mime_message.decryption_info.message_time >= beginning_time + 60); | ||
assert_eq!( | ||
mime_message.decryption_info.message_time, | ||
mime_message.timestamp_sent | ||
); | ||
assert!(mime_message.timestamp_rcvd <= time()); | ||
|
||
Ok(()) | ||
} | ||
} |