Skip to content

Commit 17d673d

Browse files
iequidoolink2xt
authored andcommitted
fix: Don't treat forged outgoing messages as Autocrypt-encrypted
1 parent 2c669c7 commit 17d673d

File tree

4 files changed

+67
-4
lines changed

4 files changed

+67
-4
lines changed

src/decrypt.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::authres::{self, DkimResults};
1212
use crate::contact::addr_cmp;
1313
use crate::context::Context;
1414
use crate::headerdef::{HeaderDef, HeaderDefMap};
15-
use crate::key::{DcKey, Fingerprint, SignedPublicKey, SignedSecretKey};
15+
use crate::key::{self, DcKey, Fingerprint, SignedPublicKey, SignedSecretKey};
1616
use crate::peerstate::Peerstate;
1717
use crate::pgp;
1818

@@ -264,16 +264,22 @@ pub(crate) fn validate_detached_signature<'a, 'b>(
264264
}
265265
}
266266

267-
pub(crate) fn keyring_from_peerstate(peerstate: Option<&Peerstate>) -> Vec<SignedPublicKey> {
267+
/// Returns public keyring for `peerstate`.
268+
pub(crate) async fn keyring_from_peerstate(
269+
context: &Context,
270+
peerstate: Option<&Peerstate>,
271+
) -> Result<Vec<SignedPublicKey>> {
268272
let mut public_keyring_for_validate = Vec::new();
269273
if let Some(peerstate) = peerstate {
270274
if let Some(key) = &peerstate.public_key {
271275
public_keyring_for_validate.push(key.clone());
272276
} else if let Some(key) = &peerstate.gossip_key {
273277
public_keyring_for_validate.push(key.clone());
278+
} else if context.is_self_addr(&peerstate.addr).await? {
279+
public_keyring_for_validate = key::load_self_public_keyring(context).await?;
274280
}
275281
}
276-
public_keyring_for_validate
282+
Ok(public_keyring_for_validate)
277283
}
278284

279285
/// Applies Autocrypt header to Autocrypt peer state and saves it into the database.
@@ -292,6 +298,7 @@ pub(crate) async fn get_autocrypt_peerstate(
292298
message_time: i64,
293299
allow_change: bool,
294300
) -> Result<Option<Peerstate>> {
301+
let allow_change = allow_change && !context.is_self_addr(from).await?;
295302
let mut peerstate;
296303

297304
// Apply Autocrypt header

src/key.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,25 @@ pub(crate) async fn load_self_public_key(context: &Context) -> Result<SignedPubl
101101
}
102102
}
103103

104+
/// Returns our own public keyring.
105+
pub(crate) async fn load_self_public_keyring(context: &Context) -> Result<Vec<SignedPublicKey>> {
106+
let keys = context
107+
.sql
108+
.query_map(
109+
r#"SELECT public_key
110+
FROM keypairs
111+
ORDER BY id=(SELECT value FROM config WHERE keyname='key_id') DESC"#,
112+
(),
113+
|row| row.get::<_, Vec<u8>>(0),
114+
|keys| keys.collect::<Result<Vec<_>, _>>().map_err(Into::into),
115+
)
116+
.await?
117+
.into_iter()
118+
.filter_map(|bytes| SignedPublicKey::from_slice(&bytes).log_err(context).ok())
119+
.collect();
120+
Ok(keys)
121+
}
122+
104123
pub(crate) async fn load_self_secret_key(context: &Context) -> Result<SignedSecretKey> {
105124
let private_key = context
106125
.sql

src/mimeparser.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,8 @@ impl MimeMessage {
304304
hop_info += "\n\n";
305305
hop_info += &decryption_info.dkim_results.to_string();
306306

307-
let public_keyring = keyring_from_peerstate(decryption_info.peerstate.as_ref());
307+
let public_keyring =
308+
keyring_from_peerstate(context, decryption_info.peerstate.as_ref()).await?;
308309
let (mail, mut signatures, encrypted) = match tokio::task::block_in_place(|| {
309310
try_decrypt(&mail, &private_keyring, &public_keyring)
310311
}) {

src/peerstate.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::message::Message;
1616
use crate::mimeparser::SystemMessage;
1717
use crate::sql::Sql;
1818
use crate::stock_str;
19+
use crate::tools;
1920

2021
/// Type of the public key stored inside the peerstate.
2122
#[derive(Debug)]
@@ -165,6 +166,9 @@ impl Peerstate {
165166

166167
/// Loads peerstate corresponding to the given address from the database.
167168
pub async fn from_addr(context: &Context, addr: &str) -> Result<Option<Peerstate>> {
169+
if context.is_self_addr(addr).await? {
170+
return Ok(Some(Peerstate::get_self_stub(addr)));
171+
}
168172
let query = "SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, \
169173
gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, \
170174
verified_key, verified_key_fingerprint, \
@@ -182,6 +186,7 @@ impl Peerstate {
182186
context: &Context,
183187
fingerprint: &Fingerprint,
184188
) -> Result<Option<Peerstate>> {
189+
// NOTE: If it's our key fingerprint, this returns None currently.
185190
let query = "SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, \
186191
gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, \
187192
verified_key, verified_key_fingerprint, \
@@ -206,6 +211,9 @@ impl Peerstate {
206211
fingerprint: &Fingerprint,
207212
addr: &str,
208213
) -> Result<Option<Peerstate>> {
214+
if context.is_self_addr(addr).await? {
215+
return Ok(Some(Peerstate::get_self_stub(addr)));
216+
}
209217
let query = "SELECT addr, last_seen, last_seen_autocrypt, prefer_encrypted, public_key, \
210218
gossip_timestamp, gossip_key, public_key_fingerprint, gossip_key_fingerprint, \
211219
verified_key, verified_key_fingerprint, \
@@ -221,6 +229,34 @@ impl Peerstate {
221229
Self::from_stmt(context, query, (&fp, &addr, &fp)).await
222230
}
223231

232+
/// Returns peerstate stub for self `addr`.
233+
///
234+
/// Needed for [`crate::decrypt::keyring_from_peerstate()`] which returns a keyring of all our
235+
/// pubkeys for such a stub so that we can check if a message is signed by us.
236+
fn get_self_stub(addr: &str) -> Self {
237+
let now = tools::time();
238+
// We can have multiple pubkeys, just make the corresponding fields None.
239+
Self {
240+
addr: addr.to_string(),
241+
last_seen: now,
242+
last_seen_autocrypt: now,
243+
prefer_encrypt: EncryptPreference::Mutual,
244+
public_key: None,
245+
public_key_fingerprint: None,
246+
gossip_key: None,
247+
gossip_key_fingerprint: None,
248+
gossip_timestamp: 0,
249+
verified_key: None,
250+
verified_key_fingerprint: None,
251+
verifier: None,
252+
secondary_verified_key: None,
253+
secondary_verified_key_fingerprint: None,
254+
secondary_verifier: None,
255+
backward_verified_key_id: None,
256+
fingerprint_changed: false,
257+
}
258+
}
259+
224260
async fn from_stmt(
225261
context: &Context,
226262
query: &str,

0 commit comments

Comments
 (0)