From 5b993f601ff78bb80f9b9d9fe310e0fb1ea4cd33 Mon Sep 17 00:00:00 2001 From: Simon Laux Date: Mon, 2 Sep 2019 15:56:52 +0200 Subject: [PATCH 01/14] transform current_block to ok_to_continue --- src/dc_securejoin.rs | 77 +++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 43 deletions(-) diff --git a/src/dc_securejoin.rs b/src/dc_securejoin.rs index c481a8b23..5e4ef74ee 100644 --- a/src/dc_securejoin.rs +++ b/src/dc_securejoin.rs @@ -369,7 +369,7 @@ pub unsafe fn dc_handle_securejoin_handshake( mimeparser: &dc_mimeparser_t, contact_id: uint32_t, ) -> libc::c_int { - let mut current_block: u64; + let mut ok_to_continue: bool; let step: *const libc::c_char; let join_vg: libc::c_int; let mut own_fingerprint: *mut libc::c_char = ptr::null_mut(); @@ -413,10 +413,10 @@ pub unsafe fn dc_handle_securejoin_handshake( invitenumber = lookup_field(mimeparser, "Secure-Join-Invitenumber"); if invitenumber.is_null() { warn!(context, 0, "Secure-join denied (invitenumber missing).",); - current_block = 4378276786830486580; + ok_to_continue = false; } else if !dc_token_exists(context, DC_TOKEN_INVITENUMBER, invitenumber) { warn!(context, 0, "Secure-join denied (bad invitenumber).",); - current_block = 4378276786830486580; + ok_to_continue = false; } else { info!(context, 0, "Secure-join requested.",); @@ -437,7 +437,7 @@ pub unsafe fn dc_handle_securejoin_handshake( ptr::null(), "", ); - current_block = 10256747982273457880; + ok_to_continue = true; } } else if strcmp( step, @@ -459,7 +459,7 @@ pub unsafe fn dc_handle_securejoin_handshake( if cond { warn!(context, 0, "auth-required message out of sync.",); // no error, just aborted somehow or a mail from another handshake - current_block = 4378276786830486580; + ok_to_continue = false; } else { let scanned_fingerprint_of_alice = context .bob @@ -509,7 +509,7 @@ pub unsafe fn dc_handle_securejoin_handshake( }, ); end_bobs_joining(context, 0i32); - current_block = 4378276786830486580; + ok_to_continue = false; } else if 0 == fingerprint_equals_sender( context, @@ -524,7 +524,7 @@ pub unsafe fn dc_handle_securejoin_handshake( as *const libc::c_char, ); end_bobs_joining(context, 0i32); - current_block = 4378276786830486580; + ok_to_continue = false; } else { info!(context, 0, "Fingerprint verified.",); own_fingerprint = get_self_fingerprint(context); @@ -547,7 +547,7 @@ pub unsafe fn dc_handle_securejoin_handshake( own_fingerprint, grpid, ); - current_block = 10256747982273457880; + ok_to_continue = true; } } } else if strcmp( @@ -572,14 +572,14 @@ pub unsafe fn dc_handle_securejoin_handshake( contact_chat_id, b"Fingerprint not provided.\x00" as *const u8 as *const libc::c_char, ); - current_block = 4378276786830486580; + ok_to_continue = false; } else if !encrypted_and_signed(mimeparser, as_str(fingerprint)) { could_not_establish_secure_connection( context, contact_chat_id, b"Auth not encrypted.\x00" as *const u8 as *const libc::c_char, ); - current_block = 4378276786830486580; + ok_to_continue = false; } else if 0 == fingerprint_equals_sender(context, as_str(fingerprint), contact_chat_id) { @@ -589,7 +589,7 @@ pub unsafe fn dc_handle_securejoin_handshake( b"Fingerprint mismatch on inviter-side.\x00" as *const u8 as *const libc::c_char, ); - current_block = 4378276786830486580; + ok_to_continue = false; } else { info!(context, 0, "Fingerprint verified.",); // verify that the `Secure-Join-Auth:`-header matches the secret written to the QR code @@ -601,14 +601,14 @@ pub unsafe fn dc_handle_securejoin_handshake( contact_chat_id, b"Auth not provided.\x00" as *const u8 as *const libc::c_char, ); - current_block = 4378276786830486580; + ok_to_continue = false; } else if !dc_token_exists(context, DC_TOKEN_AUTH, auth_0) { could_not_establish_secure_connection( context, contact_chat_id, b"Auth invalid.\x00" as *const u8 as *const libc::c_char, ); - current_block = 4378276786830486580; + ok_to_continue = false; } else if 0 == mark_peer_as_verified(context, as_str(fingerprint)) { could_not_establish_secure_connection( context, @@ -616,7 +616,7 @@ pub unsafe fn dc_handle_securejoin_handshake( b"Fingerprint mismatch on inviter-side.\x00" as *const u8 as *const libc::c_char, ); - current_block = 4378276786830486580; + ok_to_continue = false; } else { Contact::scaleup_origin_by_id( context, @@ -641,7 +641,7 @@ pub unsafe fn dc_handle_securejoin_handshake( chat::get_chat_id_by_grpid(context, &grpid, None, ptr::null_mut()); if group_chat_id == 0i32 as libc::c_uint { error!(context, 0, "Chat {} not found.", &grpid); - current_block = 4378276786830486580; + ok_to_continue = false; } else { chat::add_contact_to_chat_ex( context, @@ -649,7 +649,7 @@ pub unsafe fn dc_handle_securejoin_handshake( contact_id, 0x1i32, ); - current_block = 10256747982273457880; + ok_to_continue = true; } } else { send_handshake_msg( @@ -665,7 +665,7 @@ pub unsafe fn dc_handle_securejoin_handshake( contact_id as uintptr_t, 1000i32 as uintptr_t, ); - current_block = 10256747982273457880; + ok_to_continue = true; } } } @@ -683,7 +683,7 @@ pub unsafe fn dc_handle_securejoin_handshake( } if context.bob.read().unwrap().expects != 6 { info!(context, 0, "Message belongs to a different handshake.",); - current_block = 4378276786830486580; + ok_to_continue = false; } else { let cond = { let bob = context.bob.read().unwrap(); @@ -696,7 +696,7 @@ pub unsafe fn dc_handle_securejoin_handshake( context, 0, "Message out of sync or belongs to a different handshake.", ); - current_block = 4378276786830486580; + ok_to_continue = false; } else { let scanned_fingerprint_of_alice = context .bob @@ -746,16 +746,14 @@ pub unsafe fn dc_handle_securejoin_handshake( as *const libc::c_char, ); end_bobs_joining(context, 0i32); - current_block = 4378276786830486580; + ok_to_continue = false; } else { - current_block = 5195798230510548452; + ok_to_continue = true; } } else { - current_block = 5195798230510548452; + ok_to_continue = true; } - match current_block { - 4378276786830486580 => {} - _ => { + if ok_to_continue { if 0 == mark_peer_as_verified( context, &scanned_fingerprint_of_alice, @@ -766,7 +764,7 @@ pub unsafe fn dc_handle_securejoin_handshake( b"Fingerprint mismatch on joiner-side.\x00" as *const u8 as *const libc::c_char, ); - current_block = 4378276786830486580; + ok_to_continue = false; } else { Contact::scaleup_origin_by_id( context, @@ -791,16 +789,14 @@ pub unsafe fn dc_handle_securejoin_handshake( 0, "Message belongs to a different handshake (scaled up contact anyway to allow creation of group)." ); - current_block = 4378276786830486580; + ok_to_continue = false; } else { - current_block = 9180031981464905198; + ok_to_continue = true; } } else { - current_block = 9180031981464905198; + ok_to_continue = true; } - match current_block { - 4378276786830486580 => {} - _ => { + if ok_to_continue { secure_connection_established(context, contact_chat_id); context.bob.write().unwrap().expects = 0; if 0 != join_vg { @@ -815,10 +811,8 @@ pub unsafe fn dc_handle_securejoin_handshake( ); } end_bobs_joining(context, 1i32); - current_block = 10256747982273457880; - } + ok_to_continue = true; } - } } } } @@ -835,7 +829,7 @@ pub unsafe fn dc_handle_securejoin_handshake( if let Ok(contact) = Contact::get_by_id(context, contact_id) { if contact.is_verified() == VerifiedStatus::Unverified { warn!(context, 0, "vg-member-added-received invalid.",); - current_block = 4378276786830486580; + ok_to_continue = false; } else { context.call_cb( Event::SECUREJOIN_INVITER_PROGRESS, @@ -847,22 +841,19 @@ pub unsafe fn dc_handle_securejoin_handshake( contact_id as uintptr_t, 1000i32 as uintptr_t, ); - current_block = 10256747982273457880; + ok_to_continue = true; } } else { warn!(context, 0, "vg-member-added-received invalid.",); - current_block = 4378276786830486580; + ok_to_continue = false; } } else { - current_block = 10256747982273457880; + ok_to_continue = true; } - match current_block { - 4378276786830486580 => {} - _ => { + if ok_to_continue { if 0 != ret & 0x2i32 { ret |= 0x4i32 } - } } } } From 1d09d2f0d1707e884b274ab14c3c577c32fc4a45 Mon Sep 17 00:00:00 2001 From: Simon Laux Date: Mon, 2 Sep 2019 15:57:11 +0200 Subject: [PATCH 02/14] cargo fmt --- src/dc_securejoin.rs | 98 +++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 52 deletions(-) diff --git a/src/dc_securejoin.rs b/src/dc_securejoin.rs index 5e4ef74ee..b3a529b67 100644 --- a/src/dc_securejoin.rs +++ b/src/dc_securejoin.rs @@ -754,65 +754,59 @@ pub unsafe fn dc_handle_securejoin_handshake( ok_to_continue = true; } if ok_to_continue { - if 0 == mark_peer_as_verified( + if 0 == mark_peer_as_verified(context, &scanned_fingerprint_of_alice) { + could_not_establish_secure_connection( context, - &scanned_fingerprint_of_alice, - ) { - could_not_establish_secure_connection( + contact_chat_id, + b"Fingerprint mismatch on joiner-side.\x00" as *const u8 + as *const libc::c_char, + ); + ok_to_continue = false; + } else { + Contact::scaleup_origin_by_id( + context, + contact_id, + Origin::SecurejoinJoined, + ); + context.call_cb( + Event::CONTACTS_CHANGED, + 0i32 as uintptr_t, + 0i32 as uintptr_t, + ); + if 0 != join_vg { + if !addr_equals_self( context, - contact_chat_id, - b"Fingerprint mismatch on joiner-side.\x00" as *const u8 - as *const libc::c_char, - ); - ok_to_continue = false; - } else { - Contact::scaleup_origin_by_id( - context, - contact_id, - Origin::SecurejoinJoined, - ); - context.call_cb( - Event::CONTACTS_CHANGED, - 0i32 as uintptr_t, - 0i32 as uintptr_t, - ); - if 0 != join_vg { - if !addr_equals_self( - context, - as_str(lookup_field( - mimeparser, - "Chat-Group-Member-Added", - )), - ) { - info!( + as_str(lookup_field(mimeparser, "Chat-Group-Member-Added")), + ) { + info!( context, 0, "Message belongs to a different handshake (scaled up contact anyway to allow creation of group)." ); - ok_to_continue = false; - } else { - ok_to_continue = true; - } + ok_to_continue = false; } else { ok_to_continue = true; } - if ok_to_continue { - secure_connection_established(context, contact_chat_id); - context.bob.write().unwrap().expects = 0; - if 0 != join_vg { - send_handshake_msg( - context, - contact_chat_id, - b"vg-member-added-received\x00" as *const u8 - as *const libc::c_char, - "", - ptr::null(), - "", - ); - } - end_bobs_joining(context, 1i32); - ok_to_continue = true; + } else { + ok_to_continue = true; + } + if ok_to_continue { + secure_connection_established(context, contact_chat_id); + context.bob.write().unwrap().expects = 0; + if 0 != join_vg { + send_handshake_msg( + context, + contact_chat_id, + b"vg-member-added-received\x00" as *const u8 + as *const libc::c_char, + "", + ptr::null(), + "", + ); } + end_bobs_joining(context, 1i32); + ok_to_continue = true; + } } } } @@ -851,9 +845,9 @@ pub unsafe fn dc_handle_securejoin_handshake( ok_to_continue = true; } if ok_to_continue { - if 0 != ret & 0x2i32 { - ret |= 0x4i32 - } + if 0 != ret & 0x2i32 { + ret |= 0x4i32 + } } } } From 1ec193991b4273314276768ab660b9557c96dc54 Mon Sep 17 00:00:00 2001 From: Alexander Krotov Date: Mon, 2 Sep 2019 15:07:01 +0300 Subject: [PATCH 03/14] Make dc_token.rs safe --- src/dc_securejoin.rs | 42 ++++++++++++++++++++++-------------------- src/dc_token.rs | 37 +++++++++++-------------------------- 2 files changed, 33 insertions(+), 46 deletions(-) diff --git a/src/dc_securejoin.rs b/src/dc_securejoin.rs index b3a529b67..e03807186 100644 --- a/src/dc_securejoin.rs +++ b/src/dc_securejoin.rs @@ -32,27 +32,29 @@ pub unsafe fn dc_get_securejoin_qr( ========================================================= */ let mut fingerprint = ptr::null_mut(); - let mut invitenumber: *mut libc::c_char; - let mut auth: *mut libc::c_char; let mut qr: Option = None; dc_ensure_secret_key_exists(context).ok(); - invitenumber = dc_token_lookup(context, DC_TOKEN_INVITENUMBER, group_chat_id); - if invitenumber.is_null() { - invitenumber = dc_create_id().strdup(); - dc_token_save(context, DC_TOKEN_INVITENUMBER, group_chat_id, invitenumber); - } - auth = dc_token_lookup(context, DC_TOKEN_AUTH, group_chat_id); - if auth.is_null() { - auth = dc_create_id().strdup(); - dc_token_save(context, DC_TOKEN_AUTH, group_chat_id, auth); - } + let invitenumber = dc_token_lookup(context, DC_TOKEN_INVITENUMBER, group_chat_id) + .unwrap_or_else(|| { + let invitenumber_s = dc_create_id(); + dc_token_save( + context, + DC_TOKEN_INVITENUMBER, + group_chat_id, + &invitenumber_s, + ); + invitenumber_s + }); + let auth = dc_token_lookup(context, DC_TOKEN_AUTH, group_chat_id).unwrap_or_else(|| { + let auth_s = dc_create_id(); + dc_token_save(context, DC_TOKEN_AUTH, group_chat_id, &auth_s); + auth_s + }); let self_addr = context.sql.get_config(context, "configured_addr"); let cleanup = |fingerprint| { free(fingerprint as *mut libc::c_void); - free(invitenumber as *mut libc::c_void); - free(auth as *mut libc::c_void); if let Some(qr) = qr { qr.strdup() @@ -93,8 +95,8 @@ pub unsafe fn dc_get_securejoin_qr( self_addr_urlencoded, &group_name_urlencoded, &chat.grpid, - as_str(invitenumber), - as_str(auth), + &invitenumber, + &auth, )) } else { error!( @@ -109,8 +111,8 @@ pub unsafe fn dc_get_securejoin_qr( as_str(fingerprint), self_addr_urlencoded, self_name_urlencoded, - as_str(invitenumber), - as_str(auth), + &invitenumber, + &auth, )) }; @@ -414,7 +416,7 @@ pub unsafe fn dc_handle_securejoin_handshake( if invitenumber.is_null() { warn!(context, 0, "Secure-join denied (invitenumber missing).",); ok_to_continue = false; - } else if !dc_token_exists(context, DC_TOKEN_INVITENUMBER, invitenumber) { + } else if !dc_token_exists(context, DC_TOKEN_INVITENUMBER, as_str(invitenumber)) { warn!(context, 0, "Secure-join denied (bad invitenumber).",); ok_to_continue = false; } else { @@ -602,7 +604,7 @@ pub unsafe fn dc_handle_securejoin_handshake( b"Auth not provided.\x00" as *const u8 as *const libc::c_char, ); ok_to_continue = false; - } else if !dc_token_exists(context, DC_TOKEN_AUTH, auth_0) { + } else if !dc_token_exists(context, DC_TOKEN_AUTH, as_str(auth_0)) { could_not_establish_secure_connection( context, contact_chat_id, diff --git a/src/dc_token.rs b/src/dc_token.rs index 1ec2fdad2..30eee76e9 100644 --- a/src/dc_token.rs +++ b/src/dc_token.rs @@ -14,17 +14,14 @@ pub fn dc_token_save( context: &Context, namespc: dc_tokennamespc_t, foreign_id: u32, - token: *const libc::c_char, + token: &str, ) -> bool { - if token.is_null() { - return false; - } // foreign_id may be 0 sql::execute( context, &context.sql, "INSERT INTO tokens (namespc, foreign_id, token, timestamp) VALUES (?, ?, ?, ?);", - params![namespc as i32, foreign_id as i32, as_str(token), time()], + params![namespc as i32, foreign_id as i32, token, time()], ) .is_ok() } @@ -33,33 +30,21 @@ pub fn dc_token_lookup( context: &Context, namespc: dc_tokennamespc_t, foreign_id: u32, -) -> *mut libc::c_char { - context - .sql - .query_row_col::<_, String>( - context, - "SELECT token FROM tokens WHERE namespc=? AND foreign_id=?;", - params![namespc as i32, foreign_id as i32], - 0, - ) - .map(|s| unsafe { s.strdup() }) - .unwrap_or_else(|| std::ptr::null_mut()) +) -> Option { + context.sql.query_row_col::<_, String>( + context, + "SELECT token FROM tokens WHERE namespc=? AND foreign_id=?;", + params![namespc as i32, foreign_id as i32], + 0, + ) } -pub fn dc_token_exists( - context: &Context, - namespc: dc_tokennamespc_t, - token: *const libc::c_char, -) -> bool { - if token.is_null() { - return false; - } - +pub fn dc_token_exists(context: &Context, namespc: dc_tokennamespc_t, token: &str) -> bool { context .sql .exists( "SELECT id FROM tokens WHERE namespc=? AND token=?;", - params![namespc as i32, as_str(token)], + params![namespc as i32, token], ) .unwrap_or_default() } From c406675d6a27611e0649a4fa27209b7d06828b8a Mon Sep 17 00:00:00 2001 From: Alexander Krotov Date: Tue, 27 Aug 2019 00:22:34 +0300 Subject: [PATCH 04/14] Mark dc_do_heuristics_moves as safe --- src/dc_move.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dc_move.rs b/src/dc_move.rs index 0116f1570..a4f29751c 100644 --- a/src/dc_move.rs +++ b/src/dc_move.rs @@ -4,7 +4,7 @@ use crate::job::*; use crate::message::*; use crate::param::Params; -pub unsafe fn dc_do_heuristics_moves(context: &Context, folder: &str, msg_id: u32) { +pub fn dc_do_heuristics_moves(context: &Context, folder: &str, msg_id: u32) { if context .sql .get_config_int(context, "mvbox_move") From aeb1a88e7a99460a03f7849c958ab7486f94af70 Mon Sep 17 00:00:00 2001 From: Alexander Krotov Date: Tue, 27 Aug 2019 01:01:01 +0300 Subject: [PATCH 05/14] Remove dc_move.rs and move dc_do_heuristics_moves to context.rs --- src/context.rs | 42 +++++++++++++++++++++++++++++++++++++++-- src/dc_move.rs | 44 ------------------------------------------- src/dc_receive_imf.rs | 5 ++--- src/lib.rs | 1 - 4 files changed, 42 insertions(+), 50 deletions(-) delete mode 100644 src/dc_move.rs diff --git a/src/context.rs b/src/context.rs index e1a0725e8..104db486b 100644 --- a/src/context.rs +++ b/src/context.rs @@ -4,7 +4,6 @@ use crate::chat::*; use crate::constants::*; use crate::contact::*; use crate::dc_loginparam::*; -use crate::dc_move::*; use crate::dc_receive_imf::*; use crate::dc_tools::*; use crate::imap::*; @@ -228,7 +227,7 @@ unsafe fn cb_precheck_imf( if as_str(old_server_folder) != server_folder || old_server_uid != server_uid { dc_update_server_uid(context, rfc724_mid, server_folder, server_uid); } - dc_do_heuristics_moves(context, server_folder, msg_id); + do_heuristics_moves(context, server_folder, msg_id); if 0 != mark_seen { job_add( context, @@ -575,6 +574,45 @@ pub fn dc_is_mvbox(context: &Context, folder_name: impl AsRef) -> bool { } } +pub fn do_heuristics_moves(context: &Context, folder: &str, msg_id: u32) { + if context + .sql + .get_config_int(context, "mvbox_move") + .unwrap_or_else(|| 1) + == 0 + { + return; + } + + if !dc_is_inbox(context, folder) && !dc_is_sentbox(context, folder) { + return; + } + + if let Ok(msg) = dc_msg_new_load(context, msg_id) { + if dc_msg_is_setupmessage(&msg) { + // do not move setup messages; + // there may be a non-delta device that wants to handle it + return; + } + + if dc_is_mvbox(context, folder) { + dc_update_msg_move_state(context, msg.rfc724_mid, MoveState::Stay); + } + + // 1 = dc message, 2 = reply to dc message + if 0 != msg.is_dc_message { + job_add( + context, + Action::MoveMsg, + msg.id as libc::c_int, + Params::new(), + 0, + ); + dc_update_msg_move_state(context, msg.rfc724_mid, MoveState::Moving); + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/dc_move.rs b/src/dc_move.rs deleted file mode 100644 index a4f29751c..000000000 --- a/src/dc_move.rs +++ /dev/null @@ -1,44 +0,0 @@ -use crate::constants::*; -use crate::context::*; -use crate::job::*; -use crate::message::*; -use crate::param::Params; - -pub fn dc_do_heuristics_moves(context: &Context, folder: &str, msg_id: u32) { - if context - .sql - .get_config_int(context, "mvbox_move") - .unwrap_or_else(|| 1) - == 0 - { - return; - } - - if !dc_is_inbox(context, folder) && !dc_is_sentbox(context, folder) { - return; - } - - if let Ok(msg) = dc_msg_new_load(context, msg_id) { - if dc_msg_is_setupmessage(&msg) { - // do not move setup messages; - // there may be a non-delta device that wants to handle it - return; - } - - if dc_is_mvbox(context, folder) { - dc_update_msg_move_state(context, msg.rfc724_mid, MoveState::Stay); - } - - // 1 = dc message, 2 = reply to dc message - if 0 != msg.is_dc_message { - job_add( - context, - Action::MoveMsg, - msg.id as libc::c_int, - Params::new(), - 0, - ); - dc_update_msg_move_state(context, msg.rfc724_mid, MoveState::Moving); - } - } -} diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index 1871a226c..d66e01fe8 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -13,9 +13,8 @@ use sha2::{Digest, Sha256}; use crate::chat::{self, Chat}; use crate::constants::*; use crate::contact::*; -use crate::context::Context; +use crate::context::{do_heuristics_moves, Context}; use crate::dc_mimeparser::*; -use crate::dc_move::*; use crate::dc_securejoin::*; use crate::dc_strencode::*; use crate::dc_tools::*; @@ -735,7 +734,7 @@ unsafe fn add_parts( } } - dc_do_heuristics_moves(context, server_folder.as_ref(), *insert_msg_id); + do_heuristics_moves(context, server_folder.as_ref(), *insert_msg_id); cleanup(mime_in_reply_to, mime_references, txt_raw); Ok(()) diff --git a/src/lib.rs b/src/lib.rs index cfb4ca51c..e67d6c046 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,7 +56,6 @@ pub mod dc_imex; mod dc_loginparam; mod dc_mimefactory; pub mod dc_mimeparser; -mod dc_move; pub mod dc_receive_imf; pub mod dc_securejoin; mod dc_simplify; From e5a1b721f19584c009f4a42fdd029ddb54f5b85d Mon Sep 17 00:00:00 2001 From: holger krekel Date: Tue, 3 Sep 2019 15:30:28 +0200 Subject: [PATCH 06/14] try use py36 for uploads (#429) * try use py36 for uploads * another try * another --- .circleci/config.yml | 4 ++-- ci_scripts/ci_upload.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 430a9b4c2..430826646 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,5 +1,4 @@ version: 2.1 - executors: default: docker: @@ -153,11 +152,12 @@ jobs: - wheelhouse upload_docs_wheels: - machine: True + machine: true steps: - checkout - attach_workspace: at: workspace + - run: pyenv global 3.5.2 - run: ls -laR workspace - run: ci_scripts/ci_upload.sh workspace/py-docs workspace/wheelhouse diff --git a/ci_scripts/ci_upload.sh b/ci_scripts/ci_upload.sh index ae3cb64e3..aff44c61b 100755 --- a/ci_scripts/ci_upload.sh +++ b/ci_scripts/ci_upload.sh @@ -34,7 +34,7 @@ echo ----------------------- # Bundle external shared libraries into the wheels pushd $WHEELHOUSEDIR -pip install devpi-client +pip3 install devpi-client devpi use https://m.devpi.net devpi login dc --password $DEVPI_LOGIN From 50947b81c0db3fad3de25c5f81da4e8588887cb6 Mon Sep 17 00:00:00 2001 From: "B. Petersen" Date: Tue, 3 Sep 2019 00:39:33 +0200 Subject: [PATCH 07/14] set correct default value for inbox_watch --- src/config.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/config.rs b/src/config.rs index 0d23f1101..de85f96bd 100644 --- a/src/config.rs +++ b/src/config.rs @@ -33,6 +33,7 @@ pub enum Config { E2eeEnabled, #[strum(props(default = "1"))] MdnsEnabled, + #[strum(props(default = "1"))] InboxWatch, #[strum(props(default = "1"))] SentboxWatch, From d7b0ecad75723c6e95fc1b5c31a6e6216f956f4e Mon Sep 17 00:00:00 2001 From: Simon Laux Date: Mon, 2 Sep 2019 16:08:24 +0200 Subject: [PATCH 08/14] transform current_block to ok_to_continue --- src/dc_imex.rs | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/dc_imex.rs b/src/dc_imex.rs index 7810fcfe8..29f10da76 100644 --- a/src/dc_imex.rs +++ b/src/dc_imex.rs @@ -712,7 +712,7 @@ The macro avoids weird values of 0% or 100% while still working. */ // TODO should return bool /rtn #[allow(non_snake_case)] unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_int { - let mut current_block: u64; + let mut ok_to_continue: bool; let mut success: libc::c_int = 0; let mut delete_dest_file: libc::c_int = 0; @@ -768,16 +768,14 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_ .is_err() { /* error already logged */ - current_block = 11487273724841241105; + ok_to_continue = false; } else { - current_block = 14648156034262866959; + ok_to_continue = true; } } else { - current_block = 14648156034262866959; + ok_to_continue = true; } - match current_block { - 11487273724841241105 => {} - _ => { + if ok_to_continue { let mut total_files_cnt = 0; let dir = std::path::Path::new(as_str(context.get_blobdir())); if let Ok(dir_handle) = std::fs::read_dir(dir) { @@ -793,7 +791,7 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_ let mut processed_files_cnt = 0; for entry in dir_handle { if entry.is_err() { - current_block = 2631791190359682872; + ok_to_continue = true; break; } let entry = entry.unwrap(); @@ -805,7 +803,7 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_ .shall_stop_ongoing { delete_dest_file = 1; - current_block = 11487273724841241105; + ok_to_continue = false; break; } else { processed_files_cnt += 1; @@ -850,7 +848,7 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_ &curr_pathNfilename, ); /* this is not recoverable! writing to the sqlite database should work! */ - current_block = 11487273724841241105; + ok_to_continue = false; break; } } else { @@ -872,11 +870,9 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_ } } else { info!(context, 0, "Backup: No files to copy.",); - current_block = 2631791190359682872; + ok_to_continue = true; } - match current_block { - 11487273724841241105 => {} - _ => { + if ok_to_continue { if sql .set_config_int(context, "backup_time", now as i32) .is_ok() @@ -888,7 +884,6 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_ ); success = 1; } - } } } else { error!( @@ -898,7 +893,6 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_ as_str(context.get_blobdir()) ); }; - } } } } From 024c2883c093ec836afd092842d0c35b52a6d693 Mon Sep 17 00:00:00 2001 From: Simon Laux Date: Mon, 2 Sep 2019 16:08:43 +0200 Subject: [PATCH 09/14] cargo fmt --- src/dc_imex.rs | 78 +++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/src/dc_imex.rs b/src/dc_imex.rs index 29f10da76..ef7256664 100644 --- a/src/dc_imex.rs +++ b/src/dc_imex.rs @@ -776,16 +776,16 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_ ok_to_continue = true; } if ok_to_continue { - let mut total_files_cnt = 0; - let dir = std::path::Path::new(as_str(context.get_blobdir())); - if let Ok(dir_handle) = std::fs::read_dir(dir) { - total_files_cnt += dir_handle.filter(|r| r.is_ok()).count(); + let mut total_files_cnt = 0; + let dir = std::path::Path::new(as_str(context.get_blobdir())); + if let Ok(dir_handle) = std::fs::read_dir(dir) { + total_files_cnt += dir_handle.filter(|r| r.is_ok()).count(); - info!(context, 0, "EXPORT: total_files_cnt={}", total_files_cnt); - if total_files_cnt > 0 { - // scan directory, pass 2: copy files - if let Ok(dir_handle) = std::fs::read_dir(dir) { - sql.prepare( + info!(context, 0, "EXPORT: total_files_cnt={}", total_files_cnt); + if total_files_cnt > 0 { + // scan directory, pass 2: copy files + if let Ok(dir_handle) = std::fs::read_dir(dir) { + sql.prepare( "INSERT INTO backup_blobs (file_name, file_content) VALUES (?, ?);", move |mut stmt, _| { let mut processed_files_cnt = 0; @@ -860,39 +860,39 @@ unsafe fn export_backup(context: &Context, dir: *const libc::c_char) -> libc::c_ Ok(()) } ).unwrap(); - } else { - error!( - context, - 0, - "Backup: Cannot copy from blob-directory \"{}\".", - as_str(context.get_blobdir()), - ); - } } else { - info!(context, 0, "Backup: No files to copy.",); - ok_to_continue = true; - } - if ok_to_continue { - if sql - .set_config_int(context, "backup_time", now as i32) - .is_ok() - { - context.call_cb( - Event::IMEX_FILE_WRITTEN, - dest_pathNfilename as uintptr_t, - 0, - ); - success = 1; - } + error!( + context, + 0, + "Backup: Cannot copy from blob-directory \"{}\".", + as_str(context.get_blobdir()), + ); } } else { - error!( - context, - 0, - "Backup: Cannot get info for blob-directory \"{}\".", - as_str(context.get_blobdir()) - ); - }; + info!(context, 0, "Backup: No files to copy.",); + ok_to_continue = true; + } + if ok_to_continue { + if sql + .set_config_int(context, "backup_time", now as i32) + .is_ok() + { + context.call_cb( + Event::IMEX_FILE_WRITTEN, + dest_pathNfilename as uintptr_t, + 0, + ); + success = 1; + } + } + } else { + error!( + context, + 0, + "Backup: Cannot get info for blob-directory \"{}\".", + as_str(context.get_blobdir()) + ); + }; } } } From c95f134963fca457402d73b2a2efd43ae1d41a26 Mon Sep 17 00:00:00 2001 From: Dmitry Bogatov Date: Wed, 28 Aug 2019 00:41:10 +0000 Subject: [PATCH 10/14] Change return type of is_known_rfc724_mid_in_list() to bool --- src/dc_receive_imf.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index d66e01fe8..d3e1c814f 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -1874,10 +1874,7 @@ unsafe fn dc_is_reply_to_known_message( if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_IN_REPLY_TO as libc::c_int { let fld_in_reply_to: *mut mailimf_in_reply_to = (*field).fld_data.fld_in_reply_to; if !fld_in_reply_to.is_null() { - if 0 != is_known_rfc724_mid_in_list( - context, - (*(*field).fld_data.fld_in_reply_to).mid_list, - ) { + if is_known_rfc724_mid_in_list(context, (*(*field).fld_data.fld_in_reply_to).mid_list) { return 1; } } @@ -1886,10 +1883,7 @@ unsafe fn dc_is_reply_to_known_message( if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_REFERENCES as libc::c_int { let fld_references: *mut mailimf_references = (*field).fld_data.fld_references; if !fld_references.is_null() { - if 0 != is_known_rfc724_mid_in_list( - context, - (*(*field).fld_data.fld_references).mid_list, - ) { + if is_known_rfc724_mid_in_list(context, (*(*field).fld_data.fld_references).mid_list) { return 1; } } @@ -1897,7 +1891,7 @@ unsafe fn dc_is_reply_to_known_message( 0 } -unsafe fn is_known_rfc724_mid_in_list(context: &Context, mid_list: *const clist) -> libc::c_int { +unsafe fn is_known_rfc724_mid_in_list(context: &Context, mid_list: *const clist) -> bool { if !mid_list.is_null() { let mut cur: *mut clistiter; cur = (*mid_list).first; @@ -1910,7 +1904,7 @@ unsafe fn is_known_rfc724_mid_in_list(context: &Context, mid_list: *const clist) ptr::null_mut() }) as *const libc::c_char, ) { - return 1; + return true; } cur = if !cur.is_null() { (*cur).next @@ -1919,7 +1913,7 @@ unsafe fn is_known_rfc724_mid_in_list(context: &Context, mid_list: *const clist) } } } - 0 + false } /// Check if a message is a reply to a known message (messenger or non-messenger). From 6288909481b81d7b4be975d49f0dda167ad17063 Mon Sep 17 00:00:00 2001 From: Dmitry Bogatov Date: Wed, 28 Aug 2019 01:33:58 +0000 Subject: [PATCH 11/14] Refactor is_known_rfc724_mid() to use Iterator interface --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- src/dc_receive_imf.rs | 29 +++++++++-------------------- 3 files changed, 14 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 10a2d8490..96dc20d9c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -479,7 +479,7 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lettre 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "mmime 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mmime 0.1.2-alpha.0 (git+https://github.com/dignifiedquire/mmime?rev=bccd2c2)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1192,8 +1192,8 @@ dependencies = [ [[package]] name = "mmime" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "0.1.2-alpha.0" +source = "git+https://github.com/dignifiedquire/mmime?rev=bccd2c2#bccd2c2c89e9241e05f321c963f638affdccad96" dependencies = [ "charset 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2884,7 +2884,7 @@ dependencies = [ "checksum miniz_oxide 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7108aff85b876d06f22503dcce091e29f76733b2bfdd91eebce81f5e68203a10" "checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum mmime 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a1246fa340840c36f1fca1507db82463fbc4c2f7763fe84bfde666c7381e0593" +"checksum mmime 0.1.2-alpha.0 (git+https://github.com/dignifiedquire/mmime?rev=bccd2c2)" = "" "checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nix 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4dbdc256eaac2e3bd236d93ad999d3479ef775c863dbda3068c4006a92eec51b" diff --git a/Cargo.toml b/Cargo.toml index 825081cd0..c4f3b8282 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,7 +24,7 @@ num-traits = "0.2.6" native-tls = "0.2.3" lettre = "0.9.0" imap = "1.0.1" -mmime = "0.1.0" +mmime = { git = "https://github.com/dignifiedquire/mmime", rev = "bccd2c2" } base64 = "0.10" charset = "0.1" percent-encoding = "2.0" diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index d3e1c814f..eba56cea9 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -1892,28 +1892,17 @@ unsafe fn dc_is_reply_to_known_message( } unsafe fn is_known_rfc724_mid_in_list(context: &Context, mid_list: *const clist) -> bool { - if !mid_list.is_null() { - let mut cur: *mut clistiter; - cur = (*mid_list).first; - while !cur.is_null() { - if 0 != is_known_rfc724_mid( - context, - (if !cur.is_null() { - (*cur).data - } else { - ptr::null_mut() - }) as *const libc::c_char, - ) { - return true; - } - cur = if !cur.is_null() { - (*cur).next - } else { - ptr::null_mut() - } + if mid_list.is_null() { + return false; + } + + for data in &*mid_list { + if 0 != is_known_rfc724_mid(context, data.cast()) { + return true; } } - false + + return false; } /// Check if a message is a reply to a known message (messenger or non-messenger). From a5f862a564d7ae9251df04484053def096061a30 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Tue, 3 Sep 2019 16:16:26 +0200 Subject: [PATCH 12/14] remove python2 testing --- ci_scripts/run_all.sh | 2 +- python/tox.ini | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ci_scripts/run_all.sh b/ci_scripts/run_all.sh index b8f81e964..697d7f4e5 100755 --- a/ci_scripts/run_all.sh +++ b/ci_scripts/run_all.sh @@ -41,7 +41,7 @@ if [ -n "$TESTS" ]; then # see https://github.com/deltachat/deltachat-core-rust/issues/331 # unset DCC_PY_LIVECONFIG - tox --workdir "$TOXWORKDIR" -e lint,py27,py35,py36,py37,auditwheels + tox --workdir "$TOXWORKDIR" -e lint,py35,py36,py37,auditwheels popd fi diff --git a/python/tox.ini b/python/tox.ini index 38138fde9..c0776790a 100644 --- a/python/tox.ini +++ b/python/tox.ini @@ -1,7 +1,6 @@ [tox] # make sure to update environment list in travis.yml and appveyor.yml envlist = - py27 py35 lint auditwheels From 3944592c097b254e2840d8e61dd0cb427aaa46da Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Mon, 26 Aug 2019 22:24:18 +0200 Subject: [PATCH 13/14] refactor(e2ee): restructure types a and method slightly --- src/dc_e2ee.rs | 935 +++++++++++++++++++++--------------------- src/dc_mimefactory.rs | 17 +- src/dc_mimeparser.rs | 33 +- src/dc_receive_imf.rs | 2 +- src/dc_securejoin.rs | 4 +- 5 files changed, 481 insertions(+), 510 deletions(-) diff --git a/src/dc_e2ee.rs b/src/dc_e2ee.rs index 374d3f357..662aba054 100644 --- a/src/dc_e2ee.rs +++ b/src/dc_e2ee.rs @@ -1,5 +1,6 @@ //! End-to-end encryption support. +use std::any::Any; use std::collections::HashSet; use std::ffi::CStr; use std::ptr; @@ -32,358 +33,463 @@ use crate::pgp::*; use crate::types::*; use crate::x::*; -// backups -// attachments of 25 mb brutto should work on the majority of providers -// (brutto examples: web.de=50, 1&1=40, t-online.de=32, gmail=25, posteo=50, yahoo=25, all-inkl=100). -// as an upper limit, we double the size; the core won't send messages larger than this -// to get the netto sizes, we subtract 1 mb header-overhead and the base64-overhead. -// some defaults -#[derive(Clone)] -#[allow(non_camel_case_types)] -pub struct dc_e2ee_helper_t { - pub encryption_successfull: libc::c_int, - pub cdata_to_free: *mut libc::c_void, - pub encrypted: libc::c_int, +#[derive(Default)] +pub struct E2eeHelper { + pub encryption_successfull: bool, + cdata_to_free: Option>, + pub encrypted: bool, pub signatures: HashSet, pub gossipped_addr: HashSet, } -impl Default for dc_e2ee_helper_t { - fn default() -> Self { - dc_e2ee_helper_t { - encryption_successfull: 0, - cdata_to_free: std::ptr::null_mut(), - encrypted: 0, - signatures: Default::default(), - gossipped_addr: Default::default(), +impl E2eeHelper { + /// Frees data referenced by "mailmime" but not freed by mailmime_free(). After calling this function, + /// in_out_message cannot be used any longer! + pub unsafe fn thanks(&mut self) { + if let Some(data) = self.cdata_to_free.take() { + free(Box::into_raw(data) as *mut _) } } -} -#[allow(non_snake_case)] -pub unsafe fn dc_e2ee_encrypt( - context: &Context, - recipients_addr: *const clist, - force_unencrypted: libc::c_int, - e2ee_guaranteed: libc::c_int, - min_verified: libc::c_int, - do_gossip: libc::c_int, - mut in_out_message: *mut mailmime, - helper: &mut dc_e2ee_helper_t, -) { - let mut ok_to_continue = true; - let mut col: libc::c_int = 0i32; - let mut do_encrypt: libc::c_int = 0i32; - /*just a pointer into mailmime structure, must not be freed*/ - let imffields_unprotected: *mut mailimf_fields; - let mut keyring = Keyring::default(); - let plain: *mut MMAPString = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); - let mut peerstates: Vec = Vec::new(); - *helper = Default::default(); + pub unsafe fn encrypt( + &mut self, + context: &Context, + recipients_addr: *const clist, + force_unencrypted: libc::c_int, + e2ee_guaranteed: libc::c_int, + min_verified: libc::c_int, + do_gossip: libc::c_int, + mut in_out_message: *mut mailmime, + ) { + let mut ok_to_continue = true; + let mut col: libc::c_int = 0i32; + let mut do_encrypt: libc::c_int = 0i32; + /*just a pointer into mailmime structure, must not be freed*/ + let imffields_unprotected: *mut mailimf_fields; + let mut keyring = Keyring::default(); + let plain: *mut MMAPString = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); + let mut peerstates: Vec = Vec::new(); - if !(recipients_addr.is_null() - || in_out_message.is_null() - || !(*in_out_message).mm_parent.is_null() - || plain.is_null()) - { - /* libEtPan's pgp_encrypt_mime() takes the parent as the new root. We just expect the root as being given to this function. */ - let prefer_encrypt = if 0 - != context - .sql - .get_config_int(context, "e2ee_enabled") - .unwrap_or_default() + if !(recipients_addr.is_null() + || in_out_message.is_null() + || !(*in_out_message).mm_parent.is_null() + || plain.is_null()) { - EncryptPreference::Mutual - } else { - EncryptPreference::NoPreference - }; + /* libEtPan's pgp_encrypt_mime() takes the parent as the new root. We just expect the root as being given to this function. */ + let prefer_encrypt = if 0 + != context + .sql + .get_config_int(context, "e2ee_enabled") + .unwrap_or_default() + { + EncryptPreference::Mutual + } else { + EncryptPreference::NoPreference + }; - let addr = context.sql.get_config(context, "configured_addr"); + let addr = context.sql.get_config(context, "configured_addr"); - if let Some(addr) = addr { - let pubkey_ret = load_or_generate_self_public_key(context, &addr).map_err(|err| { - error!(context, 0, "Failed to load public key: {}", err); - err - }); - if let Ok(public_key) = pubkey_ret { - /*only for random-seed*/ - if prefer_encrypt == EncryptPreference::Mutual || 0 != e2ee_guaranteed { - do_encrypt = 1i32; - let mut iter1: *mut clistiter; - iter1 = (*recipients_addr).first; - while !iter1.is_null() { - let recipient_addr = to_string((*iter1).data as *const libc::c_char); - if recipient_addr != addr { - let peerstate = - Peerstate::from_addr(context, &context.sql, &recipient_addr); - if peerstate.is_some() - && (peerstate.as_ref().unwrap().prefer_encrypt - == EncryptPreference::Mutual - || 0 != e2ee_guaranteed) - { - let peerstate = peerstate.unwrap(); - info!( - context, - 0, "dc_e2ee_encrypt {} has peerstate", recipient_addr - ); - if let Some(key) = peerstate.peek_key(min_verified as usize) { - keyring.add_owned(key.clone()); - peerstates.push(peerstate); - } - } else { - info!( - context, - 0, - "dc_e2ee_encrypt {} HAS NO peerstate {}", - recipient_addr, - peerstate.is_some() - ); - do_encrypt = 0i32; - /* if we cannot encrypt to a single recipient, we cannot encrypt the message at all */ - break; - } - } - iter1 = if !iter1.is_null() { - (*iter1).next - } else { - ptr::null_mut() - } - } - } - let sign_key = if 0 != do_encrypt { - keyring.add_ref(&public_key); - let key = Key::from_self_private(context, addr.clone(), &context.sql); - - if key.is_none() { - do_encrypt = 0i32; - } - key - } else { - None - }; - if 0 != force_unencrypted { - do_encrypt = 0i32 - } - imffields_unprotected = mailmime_find_mailimf_fields(in_out_message); - if !imffields_unprotected.is_null() { - /* encrypt message, if possible */ - if 0 != do_encrypt { - mailprivacy_prepare_mime(in_out_message); - let mut part_to_encrypt: *mut mailmime = - (*in_out_message).mm_data.mm_message.mm_msg_mime; - (*part_to_encrypt).mm_parent = ptr::null_mut(); - let imffields_encrypted: *mut mailimf_fields = mailimf_fields_new_empty(); - /* mailmime_new_message_data() calls mailmime_fields_new_with_version() which would add the unwanted MIME-Version:-header */ - let message_to_encrypt: *mut mailmime = mailmime_new( - MAILMIME_MESSAGE as libc::c_int, - ptr::null(), - 0i32 as size_t, - mailmime_fields_new_empty(), - mailmime_get_content_message(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - imffields_encrypted, - part_to_encrypt, - ); - if 0 != do_gossip { - let iCnt: libc::c_int = peerstates.len() as libc::c_int; - if iCnt > 1i32 { - let mut i: libc::c_int = 0i32; - while i < iCnt { - let p = peerstates[i as usize] - .render_gossip_header(min_verified as usize); - - if let Some(header) = p { - mailimf_fields_add( - imffields_encrypted, - mailimf_field_new_custom( - "Autocrypt-Gossip".strdup(), - header.strdup(), - ), - ); + if let Some(addr) = addr { + let pubkey_ret = load_or_generate_self_public_key(context, &addr).map_err(|err| { + error!(context, 0, "Failed to load public key: {}", err); + err + }); + if let Ok(public_key) = pubkey_ret { + /*only for random-seed*/ + if prefer_encrypt == EncryptPreference::Mutual || 0 != e2ee_guaranteed { + do_encrypt = 1i32; + let mut iter1: *mut clistiter; + iter1 = (*recipients_addr).first; + while !iter1.is_null() { + let recipient_addr = to_string((*iter1).data as *const libc::c_char); + if recipient_addr != addr { + let peerstate = + Peerstate::from_addr(context, &context.sql, &recipient_addr); + if peerstate.is_some() + && (peerstate.as_ref().unwrap().prefer_encrypt + == EncryptPreference::Mutual + || 0 != e2ee_guaranteed) + { + let peerstate = peerstate.unwrap(); + info!( + context, + 0, "dc_e2ee_encrypt {} has peerstate", recipient_addr + ); + if let Some(key) = peerstate.peek_key(min_verified as usize) { + keyring.add_owned(key.clone()); + peerstates.push(peerstate); } - i += 1 + } else { + info!( + context, + 0, + "dc_e2ee_encrypt {} HAS NO peerstate {}", + recipient_addr, + peerstate.is_some() + ); + do_encrypt = 0i32; + /* if we cannot encrypt to a single recipient, we cannot encrypt the message at all */ + break; } } - } - /* memoryhole headers */ - let mut cur: *mut clistiter = (*(*imffields_unprotected).fld_list).first; - while !cur.is_null() { - let mut move_to_encrypted: libc::c_int = 0i32; - let field: *mut mailimf_field = (if !cur.is_null() { - (*cur).data + iter1 = if !iter1.is_null() { + (*iter1).next } else { ptr::null_mut() - }) - as *mut mailimf_field; - if !field.is_null() { - if (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int { - move_to_encrypted = 1i32 - } else if (*field).fld_type - == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int - { - let opt_field: *mut mailimf_optional_field = - (*field).fld_data.fld_optional_field; - if !opt_field.is_null() && !(*opt_field).fld_name.is_null() { - if strncmp( - (*opt_field).fld_name, - b"Secure-Join\x00" as *const u8 as *const libc::c_char, - 11, - ) == 0 - || strncmp( - (*opt_field).fld_name, - b"Chat-\x00" as *const u8 as *const libc::c_char, - 5, - ) == 0 - && strcmp( - (*opt_field).fld_name, - b"Chat-Version\x00" as *const u8 - as *const libc::c_char, - ) != 0 + } + } + } + let sign_key = if 0 != do_encrypt { + keyring.add_ref(&public_key); + let key = Key::from_self_private(context, addr.clone(), &context.sql); + + if key.is_none() { + do_encrypt = 0i32; + } + key + } else { + None + }; + if 0 != force_unencrypted { + do_encrypt = 0i32 + } + imffields_unprotected = mailmime_find_mailimf_fields(in_out_message); + if !imffields_unprotected.is_null() { + /* encrypt message, if possible */ + if 0 != do_encrypt { + mailprivacy_prepare_mime(in_out_message); + let mut part_to_encrypt: *mut mailmime = + (*in_out_message).mm_data.mm_message.mm_msg_mime; + (*part_to_encrypt).mm_parent = ptr::null_mut(); + let imffields_encrypted: *mut mailimf_fields = + mailimf_fields_new_empty(); + /* mailmime_new_message_data() calls mailmime_fields_new_with_version() which would add the unwanted MIME-Version:-header */ + let message_to_encrypt: *mut mailmime = mailmime_new( + MAILMIME_MESSAGE as libc::c_int, + ptr::null(), + 0i32 as size_t, + mailmime_fields_new_empty(), + mailmime_get_content_message(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + imffields_encrypted, + part_to_encrypt, + ); + if 0 != do_gossip { + let i_cnt = peerstates.len() as libc::c_int; + if i_cnt > 1 { + let mut i = 0; + while i < i_cnt { + let p = peerstates[i as usize] + .render_gossip_header(min_verified as usize); + + if let Some(header) = p { + mailimf_fields_add( + imffields_encrypted, + mailimf_field_new_custom( + "Autocrypt-Gossip".strdup(), + header.strdup(), + ), + ); + } + i += 1 + } + } + } + /* memoryhole headers */ + let mut cur: *mut clistiter = + (*(*imffields_unprotected).fld_list).first; + while !cur.is_null() { + let mut move_to_encrypted: libc::c_int = 0i32; + let field: *mut mailimf_field = (if !cur.is_null() { + (*cur).data + } else { + ptr::null_mut() + }) + as *mut mailimf_field; + if !field.is_null() { + if (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int { + move_to_encrypted = 1i32 + } else if (*field).fld_type + == MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int + { + let opt_field: *mut mailimf_optional_field = + (*field).fld_data.fld_optional_field; + if !opt_field.is_null() && !(*opt_field).fld_name.is_null() { - move_to_encrypted = 1 + if strncmp( + (*opt_field).fld_name, + b"Secure-Join\x00" as *const u8 + as *const libc::c_char, + 11, + ) == 0 + || strncmp( + (*opt_field).fld_name, + b"Chat-\x00" as *const u8 + as *const libc::c_char, + 5, + ) == 0 + && strcmp( + (*opt_field).fld_name, + b"Chat-Version\x00" as *const u8 + as *const libc::c_char, + ) != 0 + { + move_to_encrypted = 1 + } } } } - } - if 0 != move_to_encrypted { - mailimf_fields_add(imffields_encrypted, field); - cur = clist_delete((*imffields_unprotected).fld_list, cur) - } else { - cur = if !cur.is_null() { - (*cur).next + if 0 != move_to_encrypted { + mailimf_fields_add(imffields_encrypted, field); + cur = clist_delete((*imffields_unprotected).fld_list, cur) } else { - ptr::null_mut() + cur = if !cur.is_null() { + (*cur).next + } else { + ptr::null_mut() + } } } - } - let subject: *mut mailimf_subject = mailimf_subject_new(dc_strdup( - b"...\x00" as *const u8 as *const libc::c_char, - )); - mailimf_fields_add( - imffields_unprotected, - mailimf_field_new( - MAILIMF_FIELD_SUBJECT as libc::c_int, - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - subject, - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ), - ); - clist_insert_after( - (*(*part_to_encrypt).mm_content_type).ct_parameters, - (*(*(*part_to_encrypt).mm_content_type).ct_parameters).last, - mailmime_param_new_with_data( - b"protected-headers\x00" as *const u8 as *const libc::c_char - as *mut libc::c_char, - b"v1\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - ) as *mut libc::c_void, - ); - mailmime_write_mem(plain, &mut col, message_to_encrypt); - if (*plain).str_0.is_null() || (*plain).len <= 0 { - ok_to_continue = false; - } else { - if let Some(ctext_v) = dc_pgp_pk_encrypt( - (*plain).str_0 as *const libc::c_void, - (*plain).len, - &keyring, - sign_key.as_ref(), - ) { - let ctext_bytes = ctext_v.len(); - let ctext = ctext_v.strdup(); - helper.cdata_to_free = ctext as *mut _; - - /* create MIME-structure that will contain the encrypted text */ - let mut encrypted_part: *mut mailmime = new_data_part( + let subject: *mut mailimf_subject = mailimf_subject_new(dc_strdup( + b"...\x00" as *const u8 as *const libc::c_char, + )); + mailimf_fields_add( + imffields_unprotected, + mailimf_field_new( + MAILIMF_FIELD_SUBJECT as libc::c_int, ptr::null_mut(), - 0i32 as size_t, - b"multipart/encrypted\x00" as *const u8 as *const libc::c_char + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + subject, + ptr::null_mut(), + ptr::null_mut(), + ptr::null_mut(), + ), + ); + clist_insert_after( + (*(*part_to_encrypt).mm_content_type).ct_parameters, + (*(*(*part_to_encrypt).mm_content_type).ct_parameters).last, + mailmime_param_new_with_data( + b"protected-headers\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - -1i32, - ); - let content: *mut mailmime_content = - (*encrypted_part).mm_content_type; - clist_insert_after( - (*content).ct_parameters, - (*(*content).ct_parameters).last, - mailmime_param_new_with_data( - b"protocol\x00" as *const u8 as *const libc::c_char + b"v1\x00" as *const u8 as *const libc::c_char + as *mut libc::c_char, + ) as *mut libc::c_void, + ); + mailmime_write_mem(plain, &mut col, message_to_encrypt); + if (*plain).str_0.is_null() || (*plain).len <= 0 { + ok_to_continue = false; + } else { + if let Some(ctext_v) = dc_pgp_pk_encrypt( + (*plain).str_0 as *const libc::c_void, + (*plain).len, + &keyring, + sign_key.as_ref(), + ) { + let ctext_bytes = ctext_v.len(); + let ctext = ctext_v.strdup(); + self.cdata_to_free = Some(Box::new(ctext)); + + /* create MIME-structure that will contain the encrypted text */ + let mut encrypted_part: *mut mailmime = new_data_part( + ptr::null_mut(), + 0i32 as size_t, + b"multipart/encrypted\x00" as *const u8 + as *const libc::c_char as *mut libc::c_char, + -1i32, + ); + let content: *mut mailmime_content = + (*encrypted_part).mm_content_type; + clist_insert_after( + (*content).ct_parameters, + (*(*content).ct_parameters).last, + mailmime_param_new_with_data( + b"protocol\x00" as *const u8 as *const libc::c_char + as *mut libc::c_char, + b"application/pgp-encrypted\x00" as *const u8 + as *const libc::c_char + as *mut libc::c_char, + ) + as *mut libc::c_void, + ); + static mut VERSION_CONTENT: [libc::c_char; 13] = + [86, 101, 114, 115, 105, 111, 110, 58, 32, 49, 13, 10, 0]; + let version_mime: *mut mailmime = new_data_part( + VERSION_CONTENT.as_mut_ptr() as *mut libc::c_void, + strlen(VERSION_CONTENT.as_mut_ptr()), b"application/pgp-encrypted\x00" as *const u8 as *const libc::c_char as *mut libc::c_char, - ) as *mut libc::c_void, - ); - static mut VERSION_CONTENT: [libc::c_char; 13] = - [86, 101, 114, 115, 105, 111, 110, 58, 32, 49, 13, 10, 0]; - let version_mime: *mut mailmime = new_data_part( - VERSION_CONTENT.as_mut_ptr() as *mut libc::c_void, - strlen(VERSION_CONTENT.as_mut_ptr()), - b"application/pgp-encrypted\x00" as *const u8 - as *const libc::c_char - as *mut libc::c_char, - MAILMIME_MECHANISM_7BIT as libc::c_int, - ); - mailmime_smart_add_part(encrypted_part, version_mime); - let ctext_part: *mut mailmime = new_data_part( - ctext as *mut libc::c_void, - ctext_bytes, - b"application/octet-stream\x00" as *const u8 - as *const libc::c_char - as *mut libc::c_char, - MAILMIME_MECHANISM_7BIT as libc::c_int, - ); - mailmime_smart_add_part(encrypted_part, ctext_part); - (*in_out_message).mm_data.mm_message.mm_msg_mime = encrypted_part; - (*encrypted_part).mm_parent = in_out_message; - mailmime_free(message_to_encrypt); - helper.encryption_successfull = 1i32; + MAILMIME_MECHANISM_7BIT as libc::c_int, + ); + mailmime_smart_add_part(encrypted_part, version_mime); + let ctext_part: *mut mailmime = new_data_part( + ctext as *mut libc::c_void, + ctext_bytes, + b"application/octet-stream\x00" as *const u8 + as *const libc::c_char + as *mut libc::c_char, + MAILMIME_MECHANISM_7BIT as libc::c_int, + ); + mailmime_smart_add_part(encrypted_part, ctext_part); + (*in_out_message).mm_data.mm_message.mm_msg_mime = + encrypted_part; + (*encrypted_part).mm_parent = in_out_message; + mailmime_free(message_to_encrypt); + self.encryption_successfull = true; + } } } - } - if ok_to_continue { - let aheader = Aheader::new(addr, public_key, prefer_encrypt); - mailimf_fields_add( - imffields_unprotected, - mailimf_field_new_custom( - "Autocrypt".strdup(), - aheader.to_string().strdup(), - ), - ); + if ok_to_continue { + let aheader = Aheader::new(addr, public_key, prefer_encrypt); + mailimf_fields_add( + imffields_unprotected, + mailimf_field_new_custom( + "Autocrypt".strdup(), + aheader.to_string().strdup(), + ), + ); + } } } } } + + if !plain.is_null() { + mmap_string_free(plain); + } } - if !plain.is_null() { - mmap_string_free(plain); + pub unsafe fn decrypt(&mut self, context: &Context, in_out_message: *mut mailmime) { + let mut iterations: libc::c_int; + /* return values: 0=nothing to decrypt/cannot decrypt, 1=sth. decrypted + (to detect parts that could not be decrypted, simply look for left "multipart/encrypted" MIME types */ + /*just a pointer into mailmime structure, must not be freed*/ + let imffields: *mut mailimf_fields = mailmime_find_mailimf_fields(in_out_message); + let mut message_time = 0; + let mut from: *mut libc::c_char = ptr::null_mut(); + let mut private_keyring = Keyring::default(); + let mut public_keyring_for_validate = Keyring::default(); + let mut gossip_headers: *mut mailimf_fields = ptr::null_mut(); + if !(in_out_message.is_null() || imffields.is_null()) { + let mut field: *mut mailimf_field = + mailimf_find_field(imffields, MAILIMF_FIELD_FROM as libc::c_int); + if !field.is_null() && !(*field).fld_data.fld_from.is_null() { + from = mailimf_find_first_addr((*(*field).fld_data.fld_from).frm_mb_list) + } + field = mailimf_find_field(imffields, MAILIMF_FIELD_ORIG_DATE as libc::c_int); + if !field.is_null() && !(*field).fld_data.fld_orig_date.is_null() { + let orig_date: *mut mailimf_orig_date = (*field).fld_data.fld_orig_date; + if !orig_date.is_null() { + message_time = dc_timestamp_from_date((*orig_date).dt_date_time); + if message_time != 0 && message_time > time() { + message_time = time() + } + } + } + let mut peerstate = None; + let autocryptheader = Aheader::from_imffields(from, imffields); + if message_time > 0 && !from.is_null() { + peerstate = Peerstate::from_addr(context, &context.sql, as_str(from)); + + if let Some(ref mut peerstate) = peerstate { + if let Some(ref header) = autocryptheader { + peerstate.apply_header(&header, message_time); + peerstate.save_to_db(&context.sql, false); + } else if message_time > peerstate.last_seen_autocrypt + && !contains_report(in_out_message) + { + peerstate.degrade_encryption(message_time); + peerstate.save_to_db(&context.sql, false); + } + } else if let Some(ref header) = autocryptheader { + let p = Peerstate::from_header(context, header, message_time); + assert!(p.save_to_db(&context.sql, true)); + peerstate = Some(p); + } + } + /* load private key for decryption */ + let self_addr = context.sql.get_config(context, "configured_addr"); + if let Some(self_addr) = self_addr { + if private_keyring.load_self_private_for_decrypting( + context, + self_addr, + &context.sql, + ) { + if peerstate.as_ref().map(|p| p.last_seen).unwrap_or_else(|| 0) == 0 { + peerstate = Peerstate::from_addr(&context, &context.sql, as_str(from)); + } + if let Some(ref peerstate) = peerstate { + if peerstate.degrade_event.is_some() { + dc_handle_degrade_event(context, &peerstate); + } + if let Some(ref key) = peerstate.gossip_key { + public_keyring_for_validate.add_ref(key); + } + if let Some(ref key) = peerstate.public_key { + public_keyring_for_validate.add_ref(key); + } + } + iterations = 0i32; + while iterations < 10i32 { + let mut has_unencrypted_parts: libc::c_int = 0i32; + if decrypt_recursive( + context, + in_out_message, + &private_keyring, + &public_keyring_for_validate, + &mut self.signatures, + &mut gossip_headers, + &mut has_unencrypted_parts, + ) + .is_err() + { + break; + } + if iterations == 0i32 && 0 == has_unencrypted_parts { + self.encrypted = true; + } + iterations += 1; + } + if !gossip_headers.is_null() { + self.gossipped_addr = update_gossip_peerstates( + context, + message_time, + imffields, + gossip_headers, + ) + } + } + } + } + //mailmime_print(in_out_message); + if !gossip_headers.is_null() { + mailimf_fields_free(gossip_headers); + } + + free(from as *mut libc::c_void); } } -/******************************************************************************* - * Tools - ******************************************************************************/ unsafe fn new_data_part( data: *mut libc::c_void, data_bytes: size_t, @@ -528,111 +634,6 @@ fn load_or_generate_self_public_key(context: &Context, self_addr: impl AsRef time() { - message_time = time() - } - } - } - let mut peerstate = None; - let autocryptheader = Aheader::from_imffields(from, imffields); - if message_time > 0 && !from.is_null() { - peerstate = Peerstate::from_addr(context, &context.sql, as_str(from)); - - if let Some(ref mut peerstate) = peerstate { - if let Some(ref header) = autocryptheader { - peerstate.apply_header(&header, message_time); - peerstate.save_to_db(&context.sql, false); - } else if message_time > peerstate.last_seen_autocrypt - && 0 == contains_report(in_out_message) - { - peerstate.degrade_encryption(message_time); - peerstate.save_to_db(&context.sql, false); - } - } else if let Some(ref header) = autocryptheader { - let p = Peerstate::from_header(context, header, message_time); - assert!(p.save_to_db(&context.sql, true)); - peerstate = Some(p); - } - } - /* load private key for decryption */ - let self_addr = context.sql.get_config(context, "configured_addr"); - if let Some(self_addr) = self_addr { - if private_keyring.load_self_private_for_decrypting(context, self_addr, &context.sql) { - if peerstate.as_ref().map(|p| p.last_seen).unwrap_or_else(|| 0) == 0 { - peerstate = Peerstate::from_addr(&context, &context.sql, as_str(from)); - } - if let Some(ref peerstate) = peerstate { - if peerstate.degrade_event.is_some() { - dc_handle_degrade_event(context, &peerstate); - } - if let Some(ref key) = peerstate.gossip_key { - public_keyring_for_validate.add_ref(key); - } - if let Some(ref key) = peerstate.public_key { - public_keyring_for_validate.add_ref(key); - } - } - iterations = 0i32; - while iterations < 10i32 { - let mut has_unencrypted_parts: libc::c_int = 0i32; - if 0 == decrypt_recursive( - context, - in_out_message, - &private_keyring, - &public_keyring_for_validate, - &mut helper.signatures, - &mut gossip_headers, - &mut has_unencrypted_parts, - ) { - break; - } - if iterations == 0i32 && 0 == has_unencrypted_parts { - helper.encrypted = 1i32 - } - iterations += 1 - } - if !gossip_headers.is_null() { - helper.gossipped_addr = - update_gossip_peerstates(context, message_time, imffields, gossip_headers) - } - } - } - } - //mailmime_print(in_out_message); - if !gossip_headers.is_null() { - mailimf_fields_free(gossip_headers); - } - - free(from as *mut libc::c_void); -} - unsafe fn update_gossip_peerstates( context: &Context, message_time: i64, @@ -706,7 +707,6 @@ unsafe fn update_gossip_peerstates( gossipped_addr } -// TODO should return bool /rtn unsafe fn decrypt_recursive( context: &Context, mime: *mut mailmime, @@ -715,12 +715,11 @@ unsafe fn decrypt_recursive( ret_valid_signatures: &mut HashSet, ret_gossip_headers: *mut *mut mailimf_fields, ret_has_unencrypted_parts: *mut libc::c_int, -) -> libc::c_int { +) -> Result<()> { + ensure!(!mime.is_null(), "Invalid mime reference"); let ct: *mut mailmime_content; let mut cur: *mut clistiter; - if mime.is_null() { - return 0i32; - } + if (*mime).mm_type == MAILMIME_MULTIPLE as libc::c_int { ct = (*mime).mm_content_type; if !ct.is_null() @@ -733,7 +732,7 @@ unsafe fn decrypt_recursive( cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; while !cur.is_null() { let mut decrypted_mime: *mut mailmime = ptr::null_mut(); - if 0 != decrypt_part( + if decrypt_part( context, (if !cur.is_null() { (*cur).data @@ -761,7 +760,7 @@ unsafe fn decrypt_recursive( } mailmime_substitute(mime, decrypted_mime); mailmime_free(mime); - return 1i32; + return Ok(()); } cur = if !cur.is_null() { (*cur).next @@ -773,7 +772,7 @@ unsafe fn decrypt_recursive( } else { cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; while !cur.is_null() { - if 0 != decrypt_recursive( + if decrypt_recursive( context, (if !cur.is_null() { (*cur).data @@ -785,8 +784,10 @@ unsafe fn decrypt_recursive( ret_valid_signatures, ret_gossip_headers, ret_has_unencrypted_parts, - ) { - return 1i32; + ) + .is_ok() + { + return Ok(()); } cur = if !cur.is_null() { (*cur).next @@ -796,7 +797,7 @@ unsafe fn decrypt_recursive( } } } else if (*mime).mm_type == MAILMIME_MESSAGE as libc::c_int { - if 0 != decrypt_recursive( + if decrypt_recursive( context, (*mime).mm_data.mm_message.mm_msg_mime, private_keyring, @@ -804,14 +805,16 @@ unsafe fn decrypt_recursive( ret_valid_signatures, ret_gossip_headers, ret_has_unencrypted_parts, - ) { - return 1i32; + ) + .is_ok() + { + return Ok(()); } } else { - *ret_has_unencrypted_parts = 1i32 + *ret_has_unencrypted_parts = 1; } - 0 + Err(format_err!("Failed to decrypt")) } unsafe fn decrypt_part( @@ -821,7 +824,7 @@ unsafe fn decrypt_part( public_keyring_for_validate: &Keyring, ret_valid_signatures: &mut HashSet, ret_decrypted_mime: *mut *mut mailmime, -) -> libc::c_int { +) -> bool { let mut ok_to_continue = true; let mime_data: *mut mailmime_data; let mut mime_transfer_encoding: libc::c_int = MAILMIME_MECHANISM_BINARY as libc::c_int; @@ -830,7 +833,8 @@ unsafe fn decrypt_part( /* must not be free()'d */ let mut decoded_data: *const libc::c_char = ptr::null_mut(); let mut decoded_data_bytes: size_t = 0i32 as size_t; - let mut sth_decrypted: libc::c_int = 0i32; + let mut sth_decrypted = false; + *ret_decrypted_mime = ptr::null_mut(); mime_data = (*mime).mm_data.mm_single; /* MAILMIME_DATA_FILE indicates, the data is in a file; AFAIK this is not used on parsing */ @@ -894,7 +898,7 @@ unsafe fn decrypt_part( } if ok_to_continue { /* encrypted, decoded data in decoded_data now ... */ - if !(0 == has_decrypted_pgp_armor(decoded_data, decoded_data_bytes as libc::c_int)) { + if has_decrypted_pgp_armor(decoded_data, decoded_data_bytes as libc::c_int) { let add_signatures = if ret_valid_signatures.is_empty() { Some(ret_valid_signatures) } else { @@ -927,7 +931,7 @@ unsafe fn decrypt_part( } } else { *ret_decrypted_mime = decrypted_mime; - sth_decrypted = 1i32 + sth_decrypted = true; } std::mem::forget(plain); } @@ -943,14 +947,7 @@ unsafe fn decrypt_part( sth_decrypted } -/******************************************************************************* - * Decrypt - ******************************************************************************/ -// TODO should return bool /rtn -unsafe fn has_decrypted_pgp_armor( - str__: *const libc::c_char, - mut str_bytes: libc::c_int, -) -> libc::c_int { +unsafe fn has_decrypted_pgp_armor(str__: *const libc::c_char, mut str_bytes: libc::c_int) -> bool { let str_end: *const libc::c_uchar = (str__ as *const libc::c_uchar).offset(str_bytes as isize); let mut p: *const libc::c_uchar = str__ as *const libc::c_uchar; while p < str_end { @@ -960,35 +957,23 @@ unsafe fn has_decrypted_pgp_armor( p = p.offset(1isize); str_bytes -= 1 } - if str_bytes > 27i32 + str_bytes > 27i32 && strncmp( p as *const libc::c_char, b"-----BEGIN PGP MESSAGE-----\x00" as *const u8 as *const libc::c_char, 27, ) == 0 - { - return 1; - } - - 0 } -/** - * Check if a MIME structure contains a multipart/report part. - * - * As reports are often unencrypted, we do not reset the Autocrypt header in - * this case. - * - * However, Delta Chat itself has no problem with encrypted multipart/report - * parts and MUAs should be encouraged to encrpyt multipart/reports as well so - * that we could use the normal Autocrypt processing. - * - * @private - * @param mime The mime structure to check - * @return 1=multipart/report found in MIME, 0=no multipart/report found - */ -// TODO should return bool /rtn -unsafe fn contains_report(mime: *mut mailmime) -> libc::c_int { +/// Check if a MIME structure contains a multipart/report part. +/// +/// As reports are often unencrypted, we do not reset the Autocrypt header in +/// this case. +/// +/// However, Delta Chat itself has no problem with encrypted multipart/report +/// parts and MUAs should be encouraged to encrpyt multipart/reports as well so +/// that we could use the normal Autocrypt processing. +unsafe fn contains_report(mime: *mut mailmime) -> bool { if (*mime).mm_type == MAILMIME_MULTIPLE as libc::c_int { if (*(*(*mime).mm_content_type).ct_type).tp_type == MAILMIME_TYPE_COMPOSITE_TYPE as libc::c_int @@ -1002,19 +987,19 @@ unsafe fn contains_report(mime: *mut mailmime) -> libc::c_int { b"report\x00" as *const u8 as *const libc::c_char, ) == 0i32 { - return 1i32; + return true; } let mut cur: *mut clistiter; cur = (*(*mime).mm_data.mm_multipart.mm_mp_list).first; while !cur.is_null() { - if 0 != contains_report( + if contains_report( (if !cur.is_null() { (*cur).data } else { ptr::null_mut() }) as *mut mailmime, ) { - return 1i32; + return true; } cur = if !cur.is_null() { (*cur).next @@ -1023,18 +1008,12 @@ unsafe fn contains_report(mime: *mut mailmime) -> libc::c_int { } } } else if (*mime).mm_type == MAILMIME_MESSAGE as libc::c_int { - if 0 != contains_report((*mime).mm_data.mm_message.mm_msg_mime) { - return 1i32; + if contains_report((*mime).mm_data.mm_message.mm_msg_mime) { + return true; } } - 0 -} - -/* frees data referenced by "mailmime" but not freed by mailmime_free(). After calling this function, in_out_message cannot be used any longer! */ -pub unsafe fn dc_e2ee_thanks(helper: &mut dc_e2ee_helper_t) { - free(helper.cdata_to_free); - helper.cdata_to_free = ptr::null_mut(); + false } /// Ensures a private key exists for the configured user. diff --git a/src/dc_mimefactory.rs b/src/dc_mimefactory.rs index 9555bdc00..9ab0b188a 100644 --- a/src/dc_mimefactory.rs +++ b/src/dc_mimefactory.rs @@ -353,13 +353,7 @@ pub unsafe fn dc_mimefactory_render(factory: &mut dc_mimefactory_t) -> libc::c_i let mut force_plaintext: libc::c_int = 0; let mut do_gossip: libc::c_int = 0; let mut grpimage = None; - let mut e2ee_helper = dc_e2ee_helper_t { - encryption_successfull: 0, - cdata_to_free: ptr::null_mut(), - encrypted: 0, - signatures: Default::default(), - gossipped_addr: Default::default(), - }; + let mut e2ee_helper = E2eeHelper::default(); if factory.loaded as libc::c_uint == DC_MF_NOTHING_LOADED as libc::c_int as libc::c_uint || !factory.out.is_null() @@ -1033,7 +1027,7 @@ pub unsafe fn dc_mimefactory_render(factory: &mut dc_mimefactory_t) -> libc::c_i ), ); if force_plaintext != 2 { - dc_e2ee_encrypt( + e2ee_helper.encrypt( factory.context, factory.recipients_addr, force_plaintext, @@ -1041,10 +1035,9 @@ pub unsafe fn dc_mimefactory_render(factory: &mut dc_mimefactory_t) -> libc::c_i min_verified, do_gossip, message, - &mut e2ee_helper, ); } - if 0 != e2ee_helper.encryption_successfull { + if e2ee_helper.encryption_successfull { factory.out_encrypted = 1; if 0 != do_gossip { factory.out_gossiped = 1 @@ -1052,14 +1045,14 @@ pub unsafe fn dc_mimefactory_render(factory: &mut dc_mimefactory_t) -> libc::c_i } factory.out = mmap_string_new(b"\x00" as *const u8 as *const libc::c_char); mailmime_write_mem(factory.out, &mut col, message); - success = 1 + success = 1; } } if !message.is_null() { mailmime_free(message); } - dc_e2ee_thanks(&mut e2ee_helper); + e2ee_helper.thanks(); free(message_text as *mut libc::c_void); free(message_text2 as *mut libc::c_void); free(subject_str as *mut libc::c_void); diff --git a/src/dc_mimeparser.rs b/src/dc_mimeparser.rs index 3138509e5..d675be7b5 100644 --- a/src/dc_mimeparser.rs +++ b/src/dc_mimeparser.rs @@ -43,7 +43,6 @@ pub struct dc_mimepart_t { /* * * @class dc_mimeparser_t */ -#[derive(Clone)] #[allow(non_camel_case_types)] pub struct dc_mimeparser_t<'a> { pub parts: Vec, @@ -54,7 +53,7 @@ pub struct dc_mimeparser_t<'a> { pub subject: *mut libc::c_char, pub is_send_by_messenger: bool, pub decrypting_failed: libc::c_int, - pub e2ee_helper: dc_e2ee_helper_t, + pub e2ee_helper: E2eeHelper, pub is_forwarded: libc::c_int, pub context: &'a Context, pub reports: Vec<*mut mailmime>, @@ -109,7 +108,7 @@ unsafe fn dc_mimeparser_empty(mimeparser: &mut dc_mimeparser_t) { mimeparser.is_forwarded = 0i32; mimeparser.reports.clear(); mimeparser.decrypting_failed = 0i32; - dc_e2ee_thanks(&mut mimeparser.e2ee_helper); + mimeparser.e2ee_helper.thanks(); mimeparser.location_kml = None; mimeparser.message_kml = None; @@ -135,14 +134,11 @@ pub unsafe fn dc_mimeparser_parse<'a>(context: &'a Context, body: &[u8]) -> dc_m &mut mimeparser.mimeroot, ); if r == MAILIMF_NO_ERROR as libc::c_int && !mimeparser.mimeroot.is_null() { - dc_e2ee_decrypt( - mimeparser.context, - mimeparser.mimeroot, - &mut mimeparser.e2ee_helper, - ); - let mimeparser_ref = &mut mimeparser; - dc_mimeparser_parse_mime_recursive(mimeparser_ref, mimeparser_ref.mimeroot); - let field: *mut mailimf_field = dc_mimeparser_lookup_field(&mut mimeparser, "Subject"); + mimeparser + .e2ee_helper + .decrypt(mimeparser.context, mimeparser.mimeroot); + dc_mimeparser_parse_mime_recursive(&mut mimeparser, mimeparser.mimeroot); + let field: *mut mailimf_field = dc_mimeparser_lookup_field(&mimeparser, "Subject"); if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int { mimeparser.subject = dc_decode_header_words((*(*field).fld_data.fld_subject).sbj_value) } @@ -1361,9 +1357,9 @@ unsafe fn do_add_single_file_part( } unsafe fn do_add_single_part(parser: &mut dc_mimeparser_t, mut part: dc_mimepart_t) { - if 0 != (*parser).e2ee_helper.encrypted && (*parser).e2ee_helper.signatures.len() > 0 { + if (*parser).e2ee_helper.encrypted && (*parser).e2ee_helper.signatures.len() > 0 { part.param.set_int(Param::GuranteeE2ee, 1); - } else if 0 != (*parser).e2ee_helper.encrypted { + } else if (*parser).e2ee_helper.encrypted { part.param.set_int(Param::ErroneousE2ee, 0x2); } parser.parts.push(part); @@ -1818,19 +1814,22 @@ mod tests { let mut mimeparser = dc_mimeparser_parse(&context.ctx, &raw[..]); assert_eq!( - as_str(mimeparser.subject as *const libc::c_char), + &to_string(mimeparser.subject as *const libc::c_char), "inner-subject", ); let mut of: *mut mailimf_optional_field = dc_mimeparser_lookup_optional_field(&mimeparser, "X-Special-A"); - assert_eq!(as_str((*of).fld_value as *const libc::c_char), "special-a",); + assert_eq!( + &to_string((*of).fld_value as *const libc::c_char), + "special-a", + ); of = dc_mimeparser_lookup_optional_field(&mimeparser, "Foo"); - assert_eq!(as_str((*of).fld_value as *const libc::c_char), "Bar",); + assert_eq!(&to_string((*of).fld_value as *const libc::c_char), "Bar",); of = dc_mimeparser_lookup_optional_field(&mimeparser, "Chat-Version"); - assert_eq!(as_str((*of).fld_value as *const libc::c_char), "1.0",); + assert_eq!(&to_string((*of).fld_value as *const libc::c_char), "1.0",); assert_eq!(mimeparser.parts.len(), 1); dc_mimeparser_unref(&mut mimeparser); diff --git a/src/dc_receive_imf.rs b/src/dc_receive_imf.rs index eba56cea9..6cd7b9f26 100644 --- a/src/dc_receive_imf.rs +++ b/src/dc_receive_imf.rs @@ -1761,7 +1761,7 @@ unsafe fn check_verified_properties( } }; - if 0 == mimeparser.e2ee_helper.encrypted { + if mimeparser.e2ee_helper.encrypted { verify_fail("This message is not encrypted".into()); return 0; } diff --git a/src/dc_securejoin.rs b/src/dc_securejoin.rs index e03807186..bfd25d170 100644 --- a/src/dc_securejoin.rs +++ b/src/dc_securejoin.rs @@ -504,7 +504,7 @@ pub unsafe fn dc_handle_securejoin_handshake( could_not_establish_secure_connection( context, contact_chat_id, - if 0 != mimeparser.e2ee_helper.encrypted { + if mimeparser.e2ee_helper.encrypted { b"No valid signature.\x00" as *const u8 as *const libc::c_char } else { b"Not encrypted.\x00" as *const u8 as *const libc::c_char @@ -943,7 +943,7 @@ unsafe fn encrypted_and_signed( mimeparser: &dc_mimeparser_t, expected_fingerprint: impl AsRef, ) -> bool { - if 0 == mimeparser.e2ee_helper.encrypted { + if !mimeparser.e2ee_helper.encrypted { warn!(mimeparser.context, 0, "Message not encrypted.",); return false; } From 1a1f0c0a7c9d8cf9758631b22dc3cda06f26bee8 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Mon, 26 Aug 2019 22:28:42 +0200 Subject: [PATCH 14/14] refactor(e2ee): rename dc_e2ee -> e2ee --- src/configure/mod.rs | 4 ++-- src/contact.rs | 4 ++-- src/dc_imex.rs | 6 +++--- src/dc_mimefactory.rs | 2 +- src/dc_mimeparser.rs | 5 +++-- src/dc_securejoin.rs | 6 +++--- src/{dc_e2ee.rs => e2ee.rs} | 6 +++--- src/lib.rs | 2 +- 8 files changed, 18 insertions(+), 17 deletions(-) rename src/{dc_e2ee.rs => e2ee.rs} (99%) diff --git a/src/configure/mod.rs b/src/configure/mod.rs index aa0ceedcf..e56b251bf 100644 --- a/src/configure/mod.rs +++ b/src/configure/mod.rs @@ -2,9 +2,9 @@ use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC}; use crate::constants::Event; use crate::context::Context; -use crate::dc_e2ee::*; use crate::dc_loginparam::*; use crate::dc_tools::*; +use crate::e2ee; use crate::imap::*; use crate::job::*; use crate::oauth2::*; @@ -589,7 +589,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) { .ok(); if !s.shall_stop_ongoing { progress!(context, 920); - dc_ensure_secret_key_exists(context); + e2ee::ensure_secret_key_exists(context); success = true; info!( context, diff --git a/src/contact.rs b/src/contact.rs index e8e20c0cd..8a4819004 100644 --- a/src/contact.rs +++ b/src/contact.rs @@ -7,9 +7,9 @@ use crate::aheader::EncryptPreference; use crate::config::Config; use crate::constants::*; use crate::context::Context; -use crate::dc_e2ee::*; use crate::dc_loginparam::*; use crate::dc_tools::*; +use crate::e2ee; use crate::error::Result; use crate::key::*; use crate::message::MessageState; @@ -603,7 +603,7 @@ impl<'a> Contact<'a> { }); ret += &p; if self_key.is_none() { - dc_ensure_secret_key_exists(context)?; + e2ee::ensure_secret_key_exists(context)?; self_key = Key::from_self_public(context, &loginparam.addr, &context.sql); } let p = context.stock_str(StockMessage::FingerPrints); diff --git a/src/dc_imex.rs b/src/dc_imex.rs index ef7256664..3bacdbd28 100644 --- a/src/dc_imex.rs +++ b/src/dc_imex.rs @@ -11,8 +11,8 @@ use crate::config::Config; use crate::configure::*; use crate::constants::*; use crate::context::Context; -use crate::dc_e2ee::*; use crate::dc_tools::*; +use crate::e2ee; use crate::error::*; use crate::job::*; use crate::key::*; @@ -196,7 +196,7 @@ pub fn dc_render_setup_file(context: &Context, passphrase: &str) -> Result= 2, "Passphrase must be at least 2 chars long." ); - let self_addr = dc_ensure_secret_key_exists(context)?; + let self_addr = e2ee::ensure_secret_key_exists(context)?; let private_key = Key::from_self_private(context, self_addr, &context.sql) .ok_or(format_err!("Failed to get private key."))?; let ac_headers = match context @@ -522,7 +522,7 @@ pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) { } else { if what == 1 || what == 11 { /* before we export anything, make sure the private key exists */ - if dc_ensure_secret_key_exists(context).is_err() { + if e2ee::ensure_secret_key_exists(context).is_err() { error!( context, 0, diff --git a/src/dc_mimefactory.rs b/src/dc_mimefactory.rs index 9ab0b188a..cf9e095a0 100644 --- a/src/dc_mimefactory.rs +++ b/src/dc_mimefactory.rs @@ -15,9 +15,9 @@ use crate::chat::{self, Chat}; use crate::constants::*; use crate::contact::*; use crate::context::{dc_get_version_str, Context}; -use crate::dc_e2ee::*; use crate::dc_strencode::*; use crate::dc_tools::*; +use crate::e2ee::*; use crate::error::Error; use crate::location; use crate::message::*; diff --git a/src/dc_mimeparser.rs b/src/dc_mimeparser.rs index d675be7b5..f2d662571 100644 --- a/src/dc_mimeparser.rs +++ b/src/dc_mimeparser.rs @@ -15,10 +15,10 @@ use mmime::other::*; use crate::constants::Viewtype; use crate::contact::*; use crate::context::Context; -use crate::dc_e2ee::*; use crate::dc_simplify::*; use crate::dc_strencode::*; use crate::dc_tools::*; +use crate::e2ee::*; use crate::location; use crate::param::*; use crate::stock::StockMessage; @@ -137,7 +137,8 @@ pub unsafe fn dc_mimeparser_parse<'a>(context: &'a Context, body: &[u8]) -> dc_m mimeparser .e2ee_helper .decrypt(mimeparser.context, mimeparser.mimeroot); - dc_mimeparser_parse_mime_recursive(&mut mimeparser, mimeparser.mimeroot); + let mimeparser_ref = &mut mimeparser; + dc_mimeparser_parse_mime_recursive(mimeparser_ref, mimeparser_ref.mimeroot); let field: *mut mailimf_field = dc_mimeparser_lookup_field(&mimeparser, "Subject"); if !field.is_null() && (*field).fld_type == MAILIMF_FIELD_SUBJECT as libc::c_int { mimeparser.subject = dc_decode_header_words((*(*field).fld_data.fld_subject).sbj_value) diff --git a/src/dc_securejoin.rs b/src/dc_securejoin.rs index bfd25d170..91ded8271 100644 --- a/src/dc_securejoin.rs +++ b/src/dc_securejoin.rs @@ -8,10 +8,10 @@ use crate::configure::*; use crate::constants::*; use crate::contact::*; use crate::context::Context; -use crate::dc_e2ee::*; use crate::dc_mimeparser::*; use crate::dc_token::*; use crate::dc_tools::*; +use crate::e2ee::*; use crate::key::*; use crate::lot::LotState; use crate::message::*; @@ -34,7 +34,7 @@ pub unsafe fn dc_get_securejoin_qr( let mut fingerprint = ptr::null_mut(); let mut qr: Option = None; - dc_ensure_secret_key_exists(context).ok(); + ensure_secret_key_exists(context).ok(); let invitenumber = dc_token_lookup(context, DC_TOKEN_INVITENUMBER, group_chat_id) .unwrap_or_else(|| { let invitenumber_s = dc_create_id(); @@ -142,7 +142,7 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) -> let mut join_vg: libc::c_int = 0i32; info!(context, 0, "Requesting secure-join ...",); - dc_ensure_secret_key_exists(context).ok(); + ensure_secret_key_exists(context).ok(); ongoing_allocated = dc_alloc_ongoing(context); if !(ongoing_allocated == 0i32) { diff --git a/src/dc_e2ee.rs b/src/e2ee.rs similarity index 99% rename from src/dc_e2ee.rs rename to src/e2ee.rs index 662aba054..a868574c8 100644 --- a/src/dc_e2ee.rs +++ b/src/e2ee.rs @@ -1025,7 +1025,7 @@ unsafe fn contains_report(mime: *mut mailmime) -> bool { /// /// If this succeeds you are also guaranteed that the /// [Config::ConfiguredAddr] is configured, this address is returned. -pub fn dc_ensure_secret_key_exists(context: &Context) -> Result { +pub fn ensure_secret_key_exists(context: &Context) -> Result { let self_addr = context .get_config(Config::ConfiguredAddr) .ok_or(format_err!(concat!( @@ -1049,13 +1049,13 @@ mod tests { fn test_prexisting() { let t = dummy_context(); let test_addr = configure_alice_keypair(&t.ctx); - assert_eq!(dc_ensure_secret_key_exists(&t.ctx).unwrap(), test_addr); + assert_eq!(ensure_secret_key_exists(&t.ctx).unwrap(), test_addr); } #[test] fn test_not_configured() { let t = dummy_context(); - assert!(dc_ensure_secret_key_exists(&t.ctx).is_err()); + assert!(ensure_secret_key_exists(&t.ctx).is_err()); } } diff --git a/src/lib.rs b/src/lib.rs index e67d6c046..9ec66784c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,6 +30,7 @@ pub mod configure; pub mod constants; pub mod contact; pub mod context; +mod e2ee; mod imap; pub mod job; mod job_thread; @@ -51,7 +52,6 @@ pub mod x; pub mod dc_array; mod dc_dehtml; -mod dc_e2ee; pub mod dc_imex; mod dc_loginparam; mod dc_mimefactory;