Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use privacy-preserving webxdc addresses #6237

Merged
merged 11 commits into from
Nov 21, 2024
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ serde_json = { workspace = true }
serde_urlencoded = "0.7.1"
serde = { workspace = true, features = ["derive"] }
sha-1 = "0.10"
sha2 = "0.10"
shadowsocks = { version = "1.21.0", default-features = false, features = ["aead-cipher-2022"] }
smallvec = "1.13.2"
strum = "0.26"
Expand Down
1 change: 1 addition & 0 deletions deltachat-ffi/deltachat.h
Original file line number Diff line number Diff line change
Expand Up @@ -4197,6 +4197,7 @@ char* dc_msg_get_webxdc_blob (const dc_msg_t* msg, const char*
* true if the Webxdc should get full internet access, including Webrtc.
* currently, this is only true for encrypted Webxdc's in the self chat
* that have requested internet access in the manifest.
* - self_addr: address to be used for `window.webxdc.selfAddr` in JS land.
*
* @memberof dc_msg_t
* @param msg The webxdc instance.
Expand Down
4 changes: 4 additions & 0 deletions deltachat-jsonrpc/src/api/types/webxdc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ pub struct WebxdcMessageInfo {
source_code_url: Option<String>,
/// True if full internet access should be granted to the app.
internet_access: bool,
/// Address to be used for `window.webxdc.selfAddr` in JS land.
self_addr: String,
}

impl WebxdcMessageInfo {
Expand All @@ -50,6 +52,7 @@ impl WebxdcMessageInfo {
summary,
source_code_url,
internet_access,
self_addr,
} = message.get_webxdc_info(context).await?;

Ok(Self {
Expand All @@ -59,6 +62,7 @@ impl WebxdcMessageInfo {
summary: maybe_empty_string_to_option(summary),
source_code_url: maybe_empty_string_to_option(source_code_url),
internet_access,
self_addr,
})
}
}
4 changes: 2 additions & 2 deletions src/summary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ mod tests {
use super::*;
use crate::chat::ChatId;
use crate::param::Param;
use crate::test_utils as test;
use crate::test_utils::TestContext;

async fn assert_summary_texts(msg: &Message, ctx: &Context, expected: &str) {
assert_eq!(msg.get_summary_text(ctx).await, expected);
Expand All @@ -298,7 +298,7 @@ mod tests {

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_get_summary_text() {
let d = test::TestContext::new().await;
let d = TestContext::new_alice().await;
let ctx = &d.ctx;
let chat_id = ChatId::create_for_contact(ctx, ContactId::SELF)
.await
Expand Down
39 changes: 39 additions & 0 deletions src/webxdc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ use lettre_email::PartBuilder;
use rusqlite::OptionalExtension;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use sha2::{Digest, Sha256};

use crate::chat::{self, Chat};
use crate::constants::Chattype;
use crate::contact::ContactId;
use crate::context::Context;
use crate::events::EventType;
use crate::key::{load_self_secret_key, DcKey};
use crate::message::{Message, MessageState, MsgId, Viewtype};
use crate::mimefactory::wrapped_base64_encode;
use crate::mimeparser::SystemMessage;
Expand Down Expand Up @@ -97,6 +99,9 @@ pub struct WebxdcInfo {
/// It should request access, be encrypted
/// and sent to self for this.
pub internet_access: bool,

/// Address to be used for `window.webxdc.selfAddr` in JS land.
pub self_addr: String,
}

/// Status Update ID.
Expand Down Expand Up @@ -872,6 +877,8 @@ impl Message {
&& self.chat_id.is_self_talk(context).await.unwrap_or_default()
&& self.get_showpadlock();

let self_addr = self.get_webxdc_self_addr(context).await?;

Ok(WebxdcInfo {
name: if let Some(name) = manifest.name {
name
Expand Down Expand Up @@ -904,8 +911,23 @@ impl Message {
"".to_string()
},
internet_access,
self_addr,
})
}

async fn get_webxdc_self_addr(&self, context: &Context) -> Result<String> {
let secret_key_bytes = &load_self_secret_key(context).await?.to_bytes();
r10s marked this conversation as resolved.
Show resolved Hide resolved
let rfc724_mid_bytes = self.rfc724_mid.as_bytes();

let mut hasher = Sha256::new();
hasher.update(secret_key_bytes);
hasher.update(rfc724_mid_bytes);
let hash = hasher.finalize();

let hash_str = format!("{:x}", hash);

Ok(hash_str)
}
}

#[cfg(test)]
Expand Down Expand Up @@ -2288,6 +2310,23 @@ sth_for_the = "future""#
Ok(())
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_get_webxdc_self_addr() -> Result<()> {
let t = TestContext::new_alice().await;
let chat_id = create_group_chat(&t, ProtectionStatus::Unprotected, "foo").await?;

let instance = send_webxdc_instance(&t, chat_id).await?;
let info1 = instance.get_webxdc_info(&t).await?;
let instance = send_webxdc_instance(&t, chat_id).await?;
let info2 = instance.get_webxdc_info(&t).await?;

let real_addr = t.get_primary_self_addr().await?;
assert!(!info1.self_addr.contains(&real_addr));
assert_ne!(info1.self_addr, info2.self_addr);

Ok(())
}

#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn test_webxdc_info_summary() -> Result<()> {
let alice = TestContext::new_alice().await;
Expand Down
Loading