mirror of
https://github.com/chatmail/core.git
synced 2026-05-19 23:06:32 +03:00
Fix some bugs when sending vc-pubkey, decrypt vc-pubkey on Bob's side
This commit is contained in:
@@ -355,7 +355,7 @@ impl MimeMessage {
|
|||||||
|
|
||||||
// Remove headers that are allowed _only_ in the encrypted+signed part. It's ok to leave
|
// Remove headers that are allowed _only_ in the encrypted+signed part. It's ok to leave
|
||||||
// them in signed-only emails, but has no value currently.
|
// them in signed-only emails, but has no value currently.
|
||||||
Self::remove_secured_headers(&mut headers, &mut headers_removed);
|
Self::remove_secured_headers(&mut headers, &mut headers_removed, false);
|
||||||
|
|
||||||
let mut from = from.context("No from in message")?;
|
let mut from = from.context("No from in message")?;
|
||||||
let private_keyring = load_self_secret_keyring(context).await?;
|
let private_keyring = load_self_secret_keyring(context).await?;
|
||||||
@@ -382,6 +382,11 @@ impl MimeMessage {
|
|||||||
|
|
||||||
let mail_raw; // Memory location for a possible decrypted message.
|
let mail_raw; // Memory location for a possible decrypted message.
|
||||||
let decrypted_msg; // Decrypted signed OpenPGP message.
|
let decrypted_msg; // Decrypted signed OpenPGP message.
|
||||||
|
|
||||||
|
// TODO performance:
|
||||||
|
// - maybe we should start sorting by timestamp
|
||||||
|
// - we shouldn't do 3 SQL requests even if the message isn't symm-encrypted
|
||||||
|
// - we're loading the whole bobstate, just to get the auth token
|
||||||
let mut secrets: Vec<String> = context
|
let mut secrets: Vec<String> = context
|
||||||
.sql
|
.sql
|
||||||
.query_map_vec("SELECT secret FROM broadcast_secrets", (), |row| {
|
.query_map_vec("SELECT secret FROM broadcast_secrets", (), |row| {
|
||||||
@@ -389,8 +394,24 @@ impl MimeMessage {
|
|||||||
Ok(secret)
|
Ok(secret)
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
secrets.extend(token::lookup_all(context, token::Namespace::Auth).await?);
|
secrets.extend(token::lookup_all(context, token::Namespace::Auth).await?);
|
||||||
|
context
|
||||||
|
.sql
|
||||||
|
.query_map(
|
||||||
|
"SELECT id, invite FROM bobstate",
|
||||||
|
(),
|
||||||
|
|row| {
|
||||||
|
let invite: crate::securejoin::QrInvite = row.get(1)?;
|
||||||
|
Ok(invite)
|
||||||
|
},
|
||||||
|
|rows| {
|
||||||
|
for row in rows {
|
||||||
|
secrets.push(row?.authcode().to_string());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let (mail, is_encrypted) =
|
let (mail, is_encrypted) =
|
||||||
match tokio::task::block_in_place(|| try_decrypt(&mail, &private_keyring, &secrets)) {
|
match tokio::task::block_in_place(|| try_decrypt(&mail, &private_keyring, &secrets)) {
|
||||||
@@ -608,7 +629,7 @@ impl MimeMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if signatures.is_empty() {
|
if signatures.is_empty() {
|
||||||
Self::remove_secured_headers(&mut headers, &mut headers_removed);
|
Self::remove_secured_headers(&mut headers, &mut headers_removed, is_encrypted);
|
||||||
}
|
}
|
||||||
if !is_encrypted {
|
if !is_encrypted {
|
||||||
signatures.clear();
|
signatures.clear();
|
||||||
@@ -1707,20 +1728,34 @@ impl MimeMessage {
|
|||||||
.and_then(|msgid| parse_message_id(msgid).ok())
|
.and_then(|msgid| parse_message_id(msgid).ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove headers that are only allowed to be present in an encrypted-and-signed message:
|
||||||
fn remove_secured_headers(
|
fn remove_secured_headers(
|
||||||
headers: &mut HashMap<String, String>,
|
headers: &mut HashMap<String, String>,
|
||||||
removed: &mut HashSet<String>,
|
removed: &mut HashSet<String>,
|
||||||
|
// Whether the message was encrypted (but not signed):
|
||||||
|
encrypted: bool,
|
||||||
) {
|
) {
|
||||||
remove_header(headers, "secure-join-fingerprint", removed);
|
remove_header(headers, "secure-join-fingerprint", removed);
|
||||||
remove_header(headers, "secure-join-auth", removed);
|
|
||||||
remove_header(headers, "chat-verified", removed);
|
remove_header(headers, "chat-verified", removed);
|
||||||
remove_header(headers, "autocrypt-gossip", removed);
|
remove_header(headers, "autocrypt-gossip", removed);
|
||||||
|
|
||||||
// Secure-Join is secured unless it is an initial "vc-request"/"vg-request".
|
if headers.get("secure-join") == Some(&"vc-request-pubkey".to_string()) && encrypted {
|
||||||
if let Some(secure_join) = remove_header(headers, "secure-join", removed)
|
// vc-request-pubkey message is encrypted, but unsigned,
|
||||||
&& (secure_join == "vc-request" || secure_join == "vg-request")
|
// and contains a Secure-Join-Auth header.
|
||||||
{
|
//
|
||||||
headers.insert("secure-join".to_string(), secure_join);
|
// It is unsigned in order not to leak Bob's identity to a server operator
|
||||||
|
// that scraped the AUTH token somewhere from the web,
|
||||||
|
// and because Alice anyways couldn't verify his signature at this step,
|
||||||
|
// because she doesn't know his public key yet.
|
||||||
|
} else {
|
||||||
|
remove_header(headers, "secure-join-auth", removed);
|
||||||
|
|
||||||
|
// Secure-Join is secured unless it is an initial "vc-request"/"vg-request".
|
||||||
|
if let Some(secure_join) = remove_header(headers, "secure-join", removed)
|
||||||
|
&& (secure_join == "vc-request" || secure_join == "vg-request")
|
||||||
|
{
|
||||||
|
headers.insert("secure-join".to_string(), secure_join);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -448,7 +448,7 @@ pub(crate) async fn handle_securejoin_handshake(
|
|||||||
// https://www.rfc-editor.org/rfc/rfc9580.html#name-surreptitious-forwarding
|
// https://www.rfc-editor.org/rfc/rfc9580.html#name-surreptitious-forwarding
|
||||||
if !matches!(
|
if !matches!(
|
||||||
step,
|
step,
|
||||||
SecureJoinStep::Request { .. } | SecureJoinStep::RequestPubkey
|
SecureJoinStep::Request { .. } | SecureJoinStep::RequestPubkey | SecureJoinStep::Pubkey
|
||||||
) {
|
) {
|
||||||
let mut self_found = false;
|
let mut self_found = false;
|
||||||
let self_fingerprint = load_self_public_key(context).await?.dc_fingerprint();
|
let self_fingerprint = load_self_public_key(context).await?.dc_fingerprint();
|
||||||
@@ -523,8 +523,8 @@ pub(crate) async fn handle_securejoin_handshake(
|
|||||||
==== Bob requests our public key (Securejoin v3) =====
|
==== Bob requests our public key (Securejoin v3) =====
|
||||||
========================================================*/
|
========================================================*/
|
||||||
|
|
||||||
if !mime_message.was_encrypted() {
|
if mime_message.signature.is_some() {
|
||||||
warn!(context, "Ignoring unencrypted RequestPubkey");
|
warn!(context, "RequestPubkey is not supposed to be signed");
|
||||||
return Ok(HandshakeMessage::Ignore);
|
return Ok(HandshakeMessage::Ignore);
|
||||||
}
|
}
|
||||||
let Some(auth) = mime_message.get_header(HeaderDef::SecureJoinAuth) else {
|
let Some(auth) = mime_message.get_header(HeaderDef::SecureJoinAuth) else {
|
||||||
@@ -562,7 +562,7 @@ pub(crate) async fn handle_securejoin_handshake(
|
|||||||
==== Bob - the joiner's side =====
|
==== Bob - the joiner's side =====
|
||||||
==== Alice sent us her pubkey (Securejoin v3) =====
|
==== Alice sent us her pubkey (Securejoin v3) =====
|
||||||
========================================================*/
|
========================================================*/
|
||||||
todo!()
|
todo!("Hocuri Pubkey not implemented")
|
||||||
}
|
}
|
||||||
SecureJoinStep::RequestWithAuth => {
|
SecureJoinStep::RequestWithAuth => {
|
||||||
/*==========================================================
|
/*==========================================================
|
||||||
|
|||||||
@@ -302,6 +302,7 @@ pub(crate) async fn send_handshake_message(
|
|||||||
step: BobHandshakeMsg,
|
step: BobHandshakeMsg,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
if invite.is_v3() && matches!(step, BobHandshakeMsg::Request) {
|
if invite.is_v3() && matches!(step, BobHandshakeMsg::Request) {
|
||||||
|
// TODO this code might be moved "up" into the caller function
|
||||||
// Send a minimal symmetrically-encrypted vc-request message
|
// Send a minimal symmetrically-encrypted vc-request message
|
||||||
|
|
||||||
let rfc724_mid = create_outgoing_rfc724_mid();
|
let rfc724_mid = create_outgoing_rfc724_mid();
|
||||||
|
|||||||
Reference in New Issue
Block a user