majorly de-indent code structure in secure_join by introducing cleanup function, also majorly reducing unsafety in several places

This commit is contained in:
holger krekel
2019-09-05 01:26:45 +02:00
parent b2fafeff19
commit 4bbab876ae
5 changed files with 572 additions and 641 deletions

View File

@@ -854,7 +854,7 @@ pub fn unarchive(context: &Context, chat_id: u32) -> Result<(), Error> {
/// However, this does not imply, the message really reached the recipient - /// However, this does not imply, the message really reached the recipient -
/// sending may be delayed eg. due to network problems. However, from your /// sending may be delayed eg. due to network problems. However, from your
/// view, you're done with the message. Sooner or later it will find its way. /// view, you're done with the message. Sooner or later it will find its way.
pub unsafe fn send_msg<'a>( pub fn send_msg<'a>(
context: &'a Context, context: &'a Context,
chat_id: u32, chat_id: u32,
msg: &mut Message<'a>, msg: &mut Message<'a>,
@@ -872,7 +872,7 @@ pub unsafe fn send_msg<'a>(
} }
ensure!( ensure!(
job_send_msg(context, msg.id) != 0, unsafe { job_send_msg(context, msg.id) } != 0,
"Failed to initiate send job" "Failed to initiate send job"
); );
@@ -1394,7 +1394,7 @@ pub unsafe fn add_contact_to_chat(context: &Context, chat_id: u32, contact_id: u
// TODO should return bool /rtn // TODO should return bool /rtn
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub unsafe fn add_contact_to_chat_ex( pub fn add_contact_to_chat_ex(
context: &Context, context: &Context,
chat_id: u32, chat_id: u32,
contact_id: u32, contact_id: u32,
@@ -1407,7 +1407,7 @@ pub unsafe fn add_contact_to_chat_ex(
if contact.is_err() || chat_id <= DC_CHAT_ID_LAST_SPECIAL { if contact.is_err() || chat_id <= DC_CHAT_ID_LAST_SPECIAL {
return 0; return 0;
} }
let mut msg = dc_msg_new_untyped(context); let mut msg = unsafe { dc_msg_new_untyped(context) };
reset_gossiped_timestamp(context, chat_id); reset_gossiped_timestamp(context, chat_id);
let contact = contact.unwrap(); let contact = contact.unwrap();

View File

@@ -33,7 +33,7 @@ macro_rules! progress {
// connect // connect
pub unsafe fn configure(context: &Context) { pub unsafe fn configure(context: &Context) {
if 0 != dc_has_ongoing(context) { if dc_has_ongoing(context) {
warn!( warn!(
context, context,
0, "There is already another ongoing process running.", 0, "There is already another ongoing process running.",
@@ -43,6 +43,7 @@ pub unsafe fn configure(context: &Context) {
job_kill_action(context, Action::ConfigureImap); job_kill_action(context, Action::ConfigureImap);
job_add(context, Action::ConfigureImap, 0, Params::new(), 0); job_add(context, Action::ConfigureImap, 0, Params::new(), 0);
} }
/// Check if the context is already configured. /// Check if the context is already configured.
pub fn dc_is_configured(context: &Context) -> libc::c_int { pub fn dc_is_configured(context: &Context) -> libc::c_int {
if context if context
@@ -56,17 +57,6 @@ pub fn dc_is_configured(context: &Context) -> libc::c_int {
0 0
} }
} }
/// Check if there is an ongoing process.
unsafe fn dc_has_ongoing(context: &Context) -> libc::c_int {
let s_a = context.running_state.clone();
let s = s_a.read().unwrap();
if s.ongoing_running || !s.shall_stop_ongoing {
1
} else {
0
}
}
/******************************************************************************* /*******************************************************************************
* Configure JOB * Configure JOB
@@ -80,7 +70,7 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
let mut ongoing_allocated_here = false; let mut ongoing_allocated_here = false;
let mut param_autoconfig: Option<dc_loginparam_t> = None; let mut param_autoconfig: Option<dc_loginparam_t> = None;
if !(0 == dc_alloc_ongoing(context)) { if dc_alloc_ongoing(context) {
ongoing_allocated_here = true; ongoing_allocated_here = true;
if !context.sql.is_open() { if !context.sql.is_open() {
error!(context, 0, "Cannot configure, database not opened.",); error!(context, 0, "Cannot configure, database not opened.",);
@@ -591,7 +581,45 @@ pub unsafe fn dc_job_do_DC_JOB_CONFIGURE_IMAP(context: &Context, _job: &Job) {
progress!(context, (if success { 1000 } else { 0 })); progress!(context, (if success { 1000 } else { 0 }));
} }
/* File Structure like in C: */ /*******************************************************************************
* Ongoing process allocation/free/check
******************************************************************************/
pub fn dc_alloc_ongoing(context: &Context) -> bool {
if dc_has_ongoing(context) {
warn!(
context,
0, "There is already another ongoing process running.",
);
false
} else {
let s_a = context.running_state.clone();
let mut s = s_a.write().unwrap();
s.ongoing_running = true;
s.shall_stop_ongoing = false;
true
}
}
pub fn dc_free_ongoing(context: &Context) {
let s_a = context.running_state.clone();
let mut s = s_a.write().unwrap();
s.ongoing_running = false;
s.shall_stop_ongoing = true;
}
fn dc_has_ongoing(context: &Context) -> bool {
let s_a = context.running_state.clone();
let s = s_a.read().unwrap();
s.ongoing_running || !s.shall_stop_ongoing
}
/******************************************************************************* /*******************************************************************************
* Connect to configured account * Connect to configured account
@@ -624,35 +652,6 @@ pub fn dc_connect_to_configured_imap(context: &Context, imap: &Imap) -> libc::c_
* Configure a Context * Configure a Context
******************************************************************************/ ******************************************************************************/
/// Request an ongoing process to start.
/// Returns 0=process started, 1=not started, there is running another process
pub unsafe fn dc_alloc_ongoing(context: &Context) -> libc::c_int {
if 0 != dc_has_ongoing(context) {
warn!(
context,
0, "There is already another ongoing process running.",
);
return 0;
}
let s_a = context.running_state.clone();
let mut s = s_a.write().unwrap();
s.ongoing_running = true;
s.shall_stop_ongoing = false;
1
}
/// Frees the process allocated with dc_alloc_ongoing() - independently of dc_shall_stop_ongoing.
/// If dc_alloc_ongoing() fails, this function MUST NOT be called.
pub unsafe fn dc_free_ongoing(context: &Context) {
let s_a = context.running_state.clone();
let mut s = s_a.write().unwrap();
s.ongoing_running = false;
s.shall_stop_ongoing = true;
}
/// Signal an ongoing process to stop. /// Signal an ongoing process to stop.
pub fn dc_stop_ongoing_process(context: &Context) { pub fn dc_stop_ongoing_process(context: &Context) {
let s_a = context.running_state.clone(); let s_a = context.running_state.clone();

View File

@@ -103,7 +103,7 @@ pub unsafe fn dc_imex_has_backup(
pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char { pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
let mut setup_file_name: *mut libc::c_char = ptr::null_mut(); let mut setup_file_name: *mut libc::c_char = ptr::null_mut();
let mut msg: Message; let mut msg: Message;
if dc_alloc_ongoing(context) == 0 { if !dc_alloc_ongoing(context) {
return std::ptr::null_mut(); return std::ptr::null_mut();
} }
let setup_code = dc_create_setup_code(context); let setup_code = dc_create_setup_code(context);
@@ -502,11 +502,9 @@ pub unsafe fn dc_normalize_setup_code(
pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) { pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) {
let mut ok_to_continue = true; let mut ok_to_continue = true;
let mut success: libc::c_int = 0; let mut success: libc::c_int = 0;
let mut ongoing_allocated_here: libc::c_int = 0;
let what: libc::c_int; let what: libc::c_int;
if !(0 == dc_alloc_ongoing(context)) { if dc_alloc_ongoing(context) {
ongoing_allocated_here = 1;
what = job.param.get_int(Param::Cmd).unwrap_or_default(); what = job.param.get_int(Param::Cmd).unwrap_or_default();
let param1_s = job.param.get(Param::Arg).unwrap_or_default(); let param1_s = job.param.get(Param::Arg).unwrap_or_default();
let param1 = CString::yolo(param1_s); let param1 = CString::yolo(param1_s);
@@ -564,9 +562,6 @@ pub unsafe fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) {
} }
} }
} }
}
if 0 != ongoing_allocated_here {
dc_free_ongoing(context); dc_free_ongoing(context);
} }
context.call_cb( context.call_cb(

View File

@@ -24,7 +24,7 @@ use crate::types::*;
pub const NON_ALPHANUMERIC_WITHOUT_DOT: &AsciiSet = &NON_ALPHANUMERIC.remove(b'.'); pub const NON_ALPHANUMERIC_WITHOUT_DOT: &AsciiSet = &NON_ALPHANUMERIC.remove(b'.');
pub unsafe fn dc_get_securejoin_qr(context: &Context, group_chat_id: uint32_t) -> Option<String> { pub fn dc_get_securejoin_qr(context: &Context, group_chat_id: uint32_t) -> Option<String> {
/* ========================================================= /* =========================================================
==== Alice - the inviter side ==== ==== Alice - the inviter side ====
==== Step 1 in "Setup verified contact" protocol ==== ==== Step 1 in "Setup verified contact" protocol ====
@@ -117,36 +117,57 @@ fn get_self_fingerprint(context: &Context) -> Option<String> {
None None
} }
pub unsafe fn dc_join_securejoin(context: &Context, qr: &str) -> uint32_t { pub fn dc_join_securejoin(context: &Context, qr: &str) -> uint32_t {
let cleanup =
|context: &Context, contact_chat_id: u32, ongoing_allocated: bool, join_vg: bool| {
let mut bob = context.bob.write().unwrap();
bob.expects = 0;
let ret_chat_id = if bob.status == DC_BOB_SUCCESS {
if join_vg {
chat::get_chat_id_by_grpid(
context,
bob.qr_scan.as_ref().unwrap().text2.as_ref().unwrap(),
)
.0
} else {
contact_chat_id
}
} else {
0
};
bob.qr_scan = None;
if ongoing_allocated {
dc_free_ongoing(context);
}
ret_chat_id as uint32_t
};
/* ========================================================== /* ==========================================================
==== Bob - the joiner's side ===== ==== Bob - the joiner's side =====
==== Step 2 in "Setup verified contact" protocol ===== ==== Step 2 in "Setup verified contact" protocol =====
========================================================== */ ========================================================== */
let ongoing_allocated: libc::c_int;
let mut contact_chat_id: uint32_t = 0; let mut contact_chat_id: uint32_t = 0;
let mut join_vg: bool = false; let mut join_vg: bool = false;
info!(context, 0, "Requesting secure-join ...",); info!(context, 0, "Requesting secure-join ...",);
ensure_secret_key_exists(context).ok(); ensure_secret_key_exists(context).ok();
ongoing_allocated = dc_alloc_ongoing(context); if !dc_alloc_ongoing(context) {
return cleanup(&context, contact_chat_id, false, join_vg);
if ongoing_allocated != 0 { }
let qr_scan = check_qr(context, &qr); let qr_scan = check_qr(context, &qr);
if qr_scan.state != LotState::QrAskVerifyContact if qr_scan.state != LotState::QrAskVerifyContact && qr_scan.state != LotState::QrAskVerifyGroup
&& qr_scan.state != LotState::QrAskVerifyGroup
{ {
error!(context, 0, "Unknown QR code.",); error!(context, 0, "Unknown QR code.",);
} else { return cleanup(&context, contact_chat_id, true, join_vg);
}
contact_chat_id = chat::create_by_contact_id(context, qr_scan.id).unwrap_or_default(); contact_chat_id = chat::create_by_contact_id(context, qr_scan.id).unwrap_or_default();
if contact_chat_id == 0 { if contact_chat_id == 0 {
error!(context, 0, "Unknown contact.",); error!(context, 0, "Unknown contact.",);
} else if !(context return cleanup(&context, contact_chat_id, true, join_vg);
.running_state }
.clone() if check_exit(context) {
.read() return cleanup(&context, contact_chat_id, true, join_vg);
.unwrap() }
.shall_stop_ongoing)
{
join_vg = qr_scan.get_state() == LotState::QrAskVerifyGroup; join_vg = qr_scan.get_state() == LotState::QrAskVerifyGroup;
{ {
let mut bob = context.bob.write().unwrap(); let mut bob = context.bob.write().unwrap();
@@ -233,42 +254,22 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: &str) -> uint32_t {
} }
// Bob -> Alice // Bob -> Alice
while !(context while !check_exit(&context) {
std::thread::sleep(std::time::Duration::new(0, 3_000_000));
}
cleanup(&context, contact_chat_id, true, join_vg)
}
fn check_exit(context: &Context) -> bool {
context
.running_state .running_state
.clone() .clone()
.read() .read()
.unwrap() .unwrap()
.shall_stop_ongoing) .shall_stop_ongoing
{
std::thread::sleep(std::time::Duration::new(0, 3_000_000));
}
}
}
}
let mut bob = context.bob.write().unwrap();
bob.expects = 0;
let ret_chat_id = if bob.status == 1 {
if join_vg {
chat::get_chat_id_by_grpid(
context,
bob.qr_scan.as_ref().unwrap().text2.as_ref().unwrap(),
)
.0
} else {
contact_chat_id
}
} else {
0
};
bob.qr_scan = None;
if 0 != ongoing_allocated {
dc_free_ongoing(context);
}
ret_chat_id as uint32_t
} }
unsafe fn send_handshake_msg( fn send_handshake_msg(
context: &Context, context: &Context,
contact_chat_id: uint32_t, contact_chat_id: uint32_t,
step: &str, step: &str,
@@ -276,7 +277,7 @@ unsafe fn send_handshake_msg(
fingerprint: Option<String>, fingerprint: Option<String>,
grpid: impl AsRef<str>, grpid: impl AsRef<str>,
) { ) {
let mut msg = dc_msg_new_untyped(context); let mut msg = unsafe { dc_msg_new_untyped(context) };
msg.type_0 = Viewtype::Text; msg.type_0 = Viewtype::Text;
msg.text = Some(format!("Secure-Join: {}", step)); msg.text = Some(format!("Secure-Join: {}", step));
msg.hidden = true; msg.hidden = true;
@@ -340,38 +341,34 @@ fn fingerprint_equals_sender(
} }
/* library private: secure-join */ /* library private: secure-join */
pub unsafe fn dc_handle_securejoin_handshake( pub fn dc_handle_securejoin_handshake(
context: &Context, context: &Context,
mimeparser: &dc_mimeparser_t, mimeparser: &dc_mimeparser_t,
contact_id: uint32_t, contact_id: uint32_t,
) -> libc::c_int { ) -> libc::c_int {
let mut ok_to_continue: bool;
let step: String;
let join_vg: bool;
let own_fingerprint: String; let own_fingerprint: String;
let contact_chat_id: u32;
let contact_chat_id_blocked: Blocked;
let mut grpid = "".to_string();
let mut ret: libc::c_int = 0i32;
if !(contact_id <= DC_CONTACT_ID_LAST_SPECIAL) { if contact_id <= DC_CONTACT_ID_LAST_SPECIAL {
step = lookup_field(mimeparser, "Secure-Join"); return 0;
if !step.is_empty() { }
let step = lookup_field(mimeparser, "Secure-Join");
if step.is_empty() {
return 0;
}
info!( info!(
context, context,
0, ">>>>>>>>>>>>>>>>>>>>>>>>> secure-join message \'{}\' received", step, 0, ">>>>>>>>>>>>>>>>>>>>>>>>> secure-join message \'{}\' received", step,
); );
join_vg = step.starts_with("vg-"); let (contact_chat_id, contact_chat_id_blocked) =
let (id, bl) = chat::create_or_lookup_by_contact_id(context, contact_id, Blocked::Not) chat::create_or_lookup_by_contact_id(context, contact_id, Blocked::Not).unwrap_or_default();
.unwrap_or_default();
contact_chat_id = id;
contact_chat_id_blocked = bl;
if Blocked::Not != contact_chat_id_blocked { if contact_chat_id_blocked != Blocked::Not {
chat::unblock(context, contact_chat_id); chat::unblock(context, contact_chat_id);
} }
ret = DC_HANDSHAKE_STOP_NORMAL_PROCESSING; let mut ret: libc::c_int = DC_HANDSHAKE_STOP_NORMAL_PROCESSING;
if step == "vg-request" || step == "vc-request" { let join_vg = step.starts_with("vg-");
match step.as_str() {
"vg-request" | "vc-request" => {
/* ========================================================= /* =========================================================
==== Alice - the inviter side ==== ==== Alice - the inviter side ====
==== Step 3 in "Setup verified contact" protocol ==== ==== Step 3 in "Setup verified contact" protocol ====
@@ -383,11 +380,12 @@ pub unsafe fn dc_handle_securejoin_handshake(
let invitenumber = lookup_field(mimeparser, "Secure-Join-Invitenumber"); let invitenumber = lookup_field(mimeparser, "Secure-Join-Invitenumber");
if invitenumber == "" { if invitenumber == "" {
warn!(context, 0, "Secure-join denied (invitenumber missing).",); warn!(context, 0, "Secure-join denied (invitenumber missing).",);
ok_to_continue = false; return ret;
} else if !dc_token_exists(context, DC_TOKEN_INVITENUMBER, &invitenumber) { }
if !dc_token_exists(context, DC_TOKEN_INVITENUMBER, &invitenumber) {
warn!(context, 0, "Secure-join denied (bad invitenumber).",); warn!(context, 0, "Secure-join denied (bad invitenumber).",);
ok_to_continue = false; return ret;
} else { }
info!(context, 0, "Secure-join requested.",); info!(context, 0, "Secure-join requested.",);
context.call_cb( context.call_cb(
@@ -407,9 +405,8 @@ pub unsafe fn dc_handle_securejoin_handshake(
None, None,
"", "",
); );
ok_to_continue = true;
} }
} else if step == "vg-auth-required" || step == "vc-auth-required" { "vg-auth-required" | "vc-auth-required" => {
let cond = { let cond = {
let bob = context.bob.read().unwrap(); let bob = context.bob.read().unwrap();
let scan = bob.qr_scan.as_ref(); let scan = bob.qr_scan.as_ref();
@@ -421,8 +418,8 @@ pub unsafe fn dc_handle_securejoin_handshake(
if cond { if cond {
warn!(context, 0, "auth-required message out of sync.",); warn!(context, 0, "auth-required message out of sync.",);
// no error, just aborted somehow or a mail from another handshake // no error, just aborted somehow or a mail from another handshake
ok_to_continue = false; return ret;
} else { }
let scanned_fingerprint_of_alice = context let scanned_fingerprint_of_alice = context
.bob .bob
.read() .read()
@@ -446,20 +443,6 @@ pub unsafe fn dc_handle_securejoin_handshake(
.as_ref() .as_ref()
.unwrap() .unwrap()
.to_string(); .to_string();
if join_vg {
grpid = context
.bob
.read()
.unwrap()
.qr_scan
.as_ref()
.unwrap()
.text2
.as_ref()
.unwrap()
.to_string();
}
if !encrypted_and_signed(mimeparser, &scanned_fingerprint_of_alice) { if !encrypted_and_signed(mimeparser, &scanned_fingerprint_of_alice) {
could_not_establish_secure_connection( could_not_establish_secure_connection(
context, context,
@@ -471,20 +454,17 @@ pub unsafe fn dc_handle_securejoin_handshake(
}, },
); );
end_bobs_joining(context, DC_BOB_ERROR); end_bobs_joining(context, DC_BOB_ERROR);
ok_to_continue = false; return ret;
} else if !fingerprint_equals_sender( }
context, if !fingerprint_equals_sender(context, &scanned_fingerprint_of_alice, contact_chat_id) {
&scanned_fingerprint_of_alice,
contact_chat_id,
) {
could_not_establish_secure_connection( could_not_establish_secure_connection(
context, context,
contact_chat_id, contact_chat_id,
"Fingerprint mismatch on joiner-side.", "Fingerprint mismatch on joiner-side.",
); );
end_bobs_joining(context, DC_BOB_ERROR); end_bobs_joining(context, DC_BOB_ERROR);
ok_to_continue = false; return ret;
} else { }
info!(context, 0, "Fingerprint verified.",); info!(context, 0, "Fingerprint verified.",);
own_fingerprint = get_self_fingerprint(context).unwrap(); own_fingerprint = get_self_fingerprint(context).unwrap();
context.call_cb( context.call_cb(
@@ -494,6 +474,22 @@ pub unsafe fn dc_handle_securejoin_handshake(
); );
context.bob.write().unwrap().expects = DC_VC_CONTACT_CONFIRM; context.bob.write().unwrap().expects = DC_VC_CONTACT_CONFIRM;
let grpid = if join_vg {
context
.bob
.read()
.unwrap()
.qr_scan
.as_ref()
.unwrap()
.text2
.as_ref()
.unwrap()
.to_string()
} else {
"".to_string()
};
send_handshake_msg( send_handshake_msg(
context, context,
contact_chat_id, contact_chat_id,
@@ -506,10 +502,8 @@ pub unsafe fn dc_handle_securejoin_handshake(
Some(own_fingerprint), Some(own_fingerprint),
grpid, grpid,
); );
ok_to_continue = true;
} }
} "vg-request-with-auth" | "vc-request-with-auth" => {
} else if step == "vg-request-with-auth" || step == "vc-request-with-auth" {
/* ============================================================ /* ============================================================
==== Alice - the inviter side ==== ==== Alice - the inviter side ====
==== Steps 5+6 in "Setup verified contact" protocol ==== ==== Steps 5+6 in "Setup verified contact" protocol ====
@@ -523,22 +517,24 @@ pub unsafe fn dc_handle_securejoin_handshake(
contact_chat_id, contact_chat_id,
"Fingerprint not provided.", "Fingerprint not provided.",
); );
ok_to_continue = false; return ret;
} else if !encrypted_and_signed(mimeparser, &fingerprint) { }
if !encrypted_and_signed(mimeparser, &fingerprint) {
could_not_establish_secure_connection( could_not_establish_secure_connection(
context, context,
contact_chat_id, contact_chat_id,
"Auth not encrypted.", "Auth not encrypted.",
); );
ok_to_continue = false; return ret;
} else if !fingerprint_equals_sender(context, &fingerprint, contact_chat_id) { }
if !fingerprint_equals_sender(context, &fingerprint, contact_chat_id) {
could_not_establish_secure_connection( could_not_establish_secure_connection(
context, context,
contact_chat_id, contact_chat_id,
"Fingerprint mismatch on inviter-side.", "Fingerprint mismatch on inviter-side.",
); );
ok_to_continue = false; return ret;
} else { }
info!(context, 0, "Fingerprint verified.",); info!(context, 0, "Fingerprint verified.",);
// verify that the `Secure-Join-Auth:`-header matches the secret written to the QR code // verify that the `Secure-Join-Auth:`-header matches the secret written to the QR code
let auth_0 = lookup_field(mimeparser, "Secure-Join-Auth"); let auth_0 = lookup_field(mimeparser, "Secure-Join-Auth");
@@ -548,27 +544,21 @@ pub unsafe fn dc_handle_securejoin_handshake(
contact_chat_id, contact_chat_id,
"Auth not provided.", "Auth not provided.",
); );
ok_to_continue = false; return ret;
} else if !dc_token_exists(context, DC_TOKEN_AUTH, &auth_0) { }
could_not_establish_secure_connection( if !dc_token_exists(context, DC_TOKEN_AUTH, &auth_0) {
context, could_not_establish_secure_connection(context, contact_chat_id, "Auth invalid.");
contact_chat_id, return ret;
"Auth invalid.", }
); if mark_peer_as_verified(context, fingerprint).is_err() {
ok_to_continue = false;
} else if mark_peer_as_verified(context, fingerprint).is_err() {
could_not_establish_secure_connection( could_not_establish_secure_connection(
context, context,
contact_chat_id, contact_chat_id,
"Fingerprint mismatch on inviter-side.", "Fingerprint mismatch on inviter-side.",
); );
ok_to_continue = false; return ret;
} else { }
Contact::scaleup_origin_by_id( Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinInvited);
context,
contact_id,
Origin::SecurejoinInvited,
);
info!(context, 0, "Auth verified.",); info!(context, 0, "Auth verified.",);
secure_connection_established(context, contact_chat_id); secure_connection_established(context, contact_chat_id);
context.call_cb( context.call_cb(
@@ -582,59 +572,43 @@ pub unsafe fn dc_handle_securejoin_handshake(
600i32 as uintptr_t, 600i32 as uintptr_t,
); );
if join_vg { if join_vg {
grpid = lookup_field(mimeparser, "Secure-Join-Group"); let grpid = lookup_field(mimeparser, "Secure-Join-Group");
let (group_chat_id, _, _) = chat::get_chat_id_by_grpid(context, &grpid); let (group_chat_id, _, _) = chat::get_chat_id_by_grpid(context, &grpid);
if group_chat_id == 0 { if group_chat_id == 0 {
error!(context, 0, "Chat {} not found.", &grpid); error!(context, 0, "Chat {} not found.", &grpid);
ok_to_continue = false; return ret;
} else { } else {
chat::add_contact_to_chat_ex( chat::add_contact_to_chat_ex(context, group_chat_id, contact_id, 0x1i32);
context,
group_chat_id,
contact_id,
0x1i32,
);
ok_to_continue = true;
} }
} else { } else {
send_handshake_msg( send_handshake_msg(context, contact_chat_id, "vc-contact-confirm", "", None, "");
context,
contact_chat_id,
"vc-contact-confirm",
"",
None,
"",
);
context.call_cb( context.call_cb(
Event::SECUREJOIN_INVITER_PROGRESS, Event::SECUREJOIN_INVITER_PROGRESS,
contact_id as uintptr_t, contact_id as uintptr_t,
1000i32 as uintptr_t, 1000i32 as uintptr_t,
); );
ok_to_continue = true;
} }
} }
} "vg-member-added" | "vc-contact-confirm" => {
} else if step == "vg-member-added" || step == "vc-contact-confirm" {
if join_vg { if join_vg {
ret = DC_HANDSHAKE_CONTINUE_NORMAL_PROCESSING; ret = DC_HANDSHAKE_CONTINUE_NORMAL_PROCESSING;
} }
if context.bob.read().unwrap().expects != DC_VC_CONTACT_CONFIRM { if context.bob.read().unwrap().expects != DC_VC_CONTACT_CONFIRM {
info!(context, 0, "Message belongs to a different handshake.",); info!(context, 0, "Message belongs to a different handshake.",);
ok_to_continue = false; return ret;
} else { }
let cond = { let cond = {
let bob = context.bob.read().unwrap(); let bob = context.bob.read().unwrap();
let scan = bob.qr_scan.as_ref(); let scan = bob.qr_scan.as_ref();
scan.is_none() scan.is_none() || join_vg && scan.unwrap().state != LotState::QrAskVerifyGroup
|| join_vg && scan.unwrap().state != LotState::QrAskVerifyGroup
}; };
if cond { if cond {
warn!( warn!(
context, context,
0, "Message out of sync or belongs to a different handshake.", 0, "Message out of sync or belongs to a different handshake.",
); );
ok_to_continue = false; return ret;
} else { }
let scanned_fingerprint_of_alice = context let scanned_fingerprint_of_alice = context
.bob .bob
.read() .read()
@@ -647,8 +621,8 @@ pub unsafe fn dc_handle_securejoin_handshake(
.unwrap() .unwrap()
.to_string(); .to_string();
if join_vg { let vg_expect_encrypted = if join_vg {
grpid = context let grpid = context
.bob .bob
.read() .read()
.unwrap() .unwrap()
@@ -659,11 +633,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
.as_ref() .as_ref()
.unwrap() .unwrap()
.to_string(); .to_string();
} let (_, is_verified_group, _) = chat::get_chat_id_by_grpid(context, grpid);
let vg_expect_encrypted = if join_vg {
let (_, is_verified_group, _) =
chat::get_chat_id_by_grpid(context, grpid);
// when joining a non-verified group // when joining a non-verified group
// the vg-member-added message may be unencrypted // the vg-member-added message may be unencrypted
// when not all group members have keys or prefer encryption. // when not all group members have keys or prefer encryption.
@@ -672,60 +642,38 @@ pub unsafe fn dc_handle_securejoin_handshake(
} else { } else {
true true
}; };
if vg_expect_encrypted { if vg_expect_encrypted
if !encrypted_and_signed(mimeparser, &scanned_fingerprint_of_alice) { && !encrypted_and_signed(mimeparser, &scanned_fingerprint_of_alice)
{
could_not_establish_secure_connection( could_not_establish_secure_connection(
context, context,
contact_chat_id, contact_chat_id,
"Contact confirm message not encrypted.", "Contact confirm message not encrypted.",
); );
end_bobs_joining(context, DC_BOB_ERROR); end_bobs_joining(context, DC_BOB_ERROR);
ok_to_continue = false; return ret;
} else {
ok_to_continue = true;
} }
} else {
ok_to_continue = true; if mark_peer_as_verified(context, &scanned_fingerprint_of_alice).is_err() {
}
if ok_to_continue {
if mark_peer_as_verified(context, &scanned_fingerprint_of_alice)
.is_err()
{
could_not_establish_secure_connection( could_not_establish_secure_connection(
context, context,
contact_chat_id, contact_chat_id,
"Fingerprint mismatch on joiner-side.", "Fingerprint mismatch on joiner-side.",
); );
ok_to_continue = false; return ret;
} else { }
Contact::scaleup_origin_by_id( Contact::scaleup_origin_by_id(context, contact_id, Origin::SecurejoinJoined);
context,
contact_id,
Origin::SecurejoinJoined,
);
context.call_cb( context.call_cb(
Event::CONTACTS_CHANGED, Event::CONTACTS_CHANGED,
0i32 as uintptr_t, 0i32 as uintptr_t,
0i32 as uintptr_t, 0i32 as uintptr_t,
); );
if join_vg { if join_vg
if !addr_equals_self( && !addr_equals_self(context, lookup_field(mimeparser, "Chat-Group-Member-Added"))
context, {
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).");
) { return ret;
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;
} }
} else {
ok_to_continue = true;
}
if ok_to_continue {
secure_connection_established(context, contact_chat_id); secure_connection_established(context, contact_chat_id);
context.bob.write().unwrap().expects = 0; context.bob.write().unwrap().expects = 0;
if join_vg { if join_vg {
@@ -739,13 +687,8 @@ pub unsafe fn dc_handle_securejoin_handshake(
); );
} }
end_bobs_joining(context, DC_BOB_SUCCESS); end_bobs_joining(context, DC_BOB_SUCCESS);
ok_to_continue = true;
} }
} "vg-member-added-received" => {
}
}
}
} else if step == "vg-member-added-received" {
/* ============================================================ /* ============================================================
==== Alice - the inviter side ==== ==== Alice - the inviter side ====
==== Step 8 in "Out-of-band verified groups" protocol ==== ==== Step 8 in "Out-of-band verified groups" protocol ====
@@ -753,8 +696,8 @@ pub unsafe fn dc_handle_securejoin_handshake(
if let Ok(contact) = Contact::get_by_id(context, contact_id) { if let Ok(contact) = Contact::get_by_id(context, contact_id) {
if contact.is_verified() == VerifiedStatus::Unverified { if contact.is_verified() == VerifiedStatus::Unverified {
warn!(context, 0, "vg-member-added-received invalid.",); warn!(context, 0, "vg-member-added-received invalid.",);
ok_to_continue = false; return ret;
} else { }
context.call_cb( context.call_cb(
Event::SECUREJOIN_INVITER_PROGRESS, Event::SECUREJOIN_INVITER_PROGRESS,
contact_id as uintptr_t, contact_id as uintptr_t,
@@ -765,23 +708,18 @@ pub unsafe fn dc_handle_securejoin_handshake(
contact_id as uintptr_t, contact_id as uintptr_t,
1000i32 as uintptr_t, 1000i32 as uintptr_t,
); );
ok_to_continue = true;
}
} else { } else {
warn!(context, 0, "vg-member-added-received invalid.",); warn!(context, 0, "vg-member-added-received invalid.",);
ok_to_continue = false; return ret;
}
}
_ => {
warn!(context, 0, "invalid step: {}", step);
} }
} else {
ok_to_continue = true;
} }
if ok_to_continue {
if ret == DC_HANDSHAKE_STOP_NORMAL_PROCESSING { if ret == DC_HANDSHAKE_STOP_NORMAL_PROCESSING {
ret |= DC_HANDSHAKE_ADD_DELETE_JOB; ret |= DC_HANDSHAKE_ADD_DELETE_JOB;
} }
}
}
}
ret ret
} }
@@ -790,7 +728,7 @@ fn end_bobs_joining(context: &Context, status: libc::c_int) {
dc_stop_ongoing_process(context); dc_stop_ongoing_process(context);
} }
unsafe fn secure_connection_established(context: &Context, contact_chat_id: uint32_t) { fn secure_connection_established(context: &Context, contact_chat_id: uint32_t) {
let contact_id: uint32_t = chat_id_2_contact_id(context, contact_chat_id); let contact_id: uint32_t = chat_id_2_contact_id(context, contact_chat_id);
let contact = Contact::get_by_id(context, contact_id); let contact = Contact::get_by_id(context, contact_id);
let addr = if let Ok(ref contact) = contact { let addr = if let Ok(ref contact) = contact {
@@ -807,8 +745,9 @@ unsafe fn secure_connection_established(context: &Context, contact_chat_id: uint
); );
} }
unsafe fn lookup_field(mimeparser: &dc_mimeparser_t, key: &str) -> String { fn lookup_field(mimeparser: &dc_mimeparser_t, key: &str) -> String {
let field: *mut mailimf_field = dc_mimeparser_lookup_field(mimeparser, key); let field: *mut mailimf_field = dc_mimeparser_lookup_field(mimeparser, key);
unsafe {
let mut value: *const libc::c_char = ptr::null(); let mut value: *const libc::c_char = ptr::null();
if field.is_null() if field.is_null()
|| (*field).fld_type != MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int || (*field).fld_type != MAILIMF_FIELD_OPTIONAL_FIELD as libc::c_int
@@ -822,6 +761,7 @@ unsafe fn lookup_field(mimeparser: &dc_mimeparser_t, key: &str) -> String {
} }
as_str(value).to_string() as_str(value).to_string()
} }
}
fn could_not_establish_secure_connection( fn could_not_establish_secure_connection(
context: &Context, context: &Context,
@@ -864,23 +804,20 @@ fn mark_peer_as_verified(context: &Context, fingerprint: impl AsRef<str>) -> Res
* Tools: Misc. * Tools: Misc.
******************************************************************************/ ******************************************************************************/
unsafe fn encrypted_and_signed( fn encrypted_and_signed(
mimeparser: &dc_mimeparser_t, mimeparser: &dc_mimeparser_t,
expected_fingerprint: impl AsRef<str>, expected_fingerprint: impl AsRef<str>,
) -> bool { ) -> bool {
if !mimeparser.e2ee_helper.encrypted { if !mimeparser.e2ee_helper.encrypted {
warn!(mimeparser.context, 0, "Message not encrypted.",); warn!(mimeparser.context, 0, "Message not encrypted.",);
return false; false
} } else if mimeparser.e2ee_helper.signatures.len() <= 0 {
if mimeparser.e2ee_helper.signatures.len() <= 0 {
warn!(mimeparser.context, 0, "Message not signed.",); warn!(mimeparser.context, 0, "Message not signed.",);
return false; false
} } else if expected_fingerprint.as_ref().is_empty() {
if expected_fingerprint.as_ref().is_empty() {
warn!(mimeparser.context, 0, "Fingerprint for comparison missing.",); warn!(mimeparser.context, 0, "Fingerprint for comparison missing.",);
return false; false
} } else if !mimeparser
if !mimeparser
.e2ee_helper .e2ee_helper
.signatures .signatures
.contains(expected_fingerprint.as_ref()) .contains(expected_fingerprint.as_ref())
@@ -891,13 +828,13 @@ unsafe fn encrypted_and_signed(
"Message does not match expected fingerprint {}.", "Message does not match expected fingerprint {}.",
expected_fingerprint.as_ref(), expected_fingerprint.as_ref(),
); );
return false; false
} } else {
true true
} }
}
pub unsafe fn dc_handle_degrade_event(context: &Context, peerstate: &Peerstate) { pub fn dc_handle_degrade_event(context: &Context, peerstate: &Peerstate) {
// - we do not issue an warning for DC_DE_ENCRYPTION_PAUSED as this is quite normal // - we do not issue an warning for DC_DE_ENCRYPTION_PAUSED as this is quite normal
// - currently, we do not issue an extra warning for DC_DE_VERIFICATION_LOST - this always comes // - currently, we do not issue an extra warning for DC_DE_VERIFICATION_LOST - this always comes
// together with DC_DE_FINGERPRINT_CHANGED which is logged, the idea is not to bother // together with DC_DE_FINGERPRINT_CHANGED which is logged, the idea is not to bother

View File

@@ -220,7 +220,7 @@ pub fn send_locations_to_chat(context: &Context, chat_id: u32, seconds: i64) {
msg.text = msg.text =
Some(context.stock_system_msg(StockMessage::MsgLocationEnabled, "", "", 0)); Some(context.stock_system_msg(StockMessage::MsgLocationEnabled, "", "", 0));
msg.param.set_int(Param::Cmd, 8); msg.param.set_int(Param::Cmd, 8);
unsafe { chat::send_msg(context, chat_id, &mut msg).unwrap() }; chat::send_msg(context, chat_id, &mut msg).unwrap();
} else if 0 == seconds && is_sending_locations_before { } else if 0 == seconds && is_sending_locations_before {
let stock_str = let stock_str =
context.stock_system_msg(StockMessage::MsgLocationDisabled, "", "", 0); context.stock_system_msg(StockMessage::MsgLocationDisabled, "", "", 0);
@@ -607,7 +607,7 @@ pub fn job_do_DC_JOB_MAYBE_SEND_LOCATIONS(context: &Context, _job: &Job) {
msg.hidden = true; msg.hidden = true;
msg.param.set_int(Param::Cmd, 9); msg.param.set_int(Param::Cmd, 9);
// TODO: handle cleanup on error // TODO: handle cleanup on error
unsafe { chat::send_msg(context, chat_id as u32, &mut msg).unwrap() }; chat::send_msg(context, chat_id as u32, &mut msg).unwrap();
} }
Ok(()) Ok(())
}, },