- remove many *libc::char usages, and c-pointer from fingerprint

- rustify get_chat_id_by_grpid and streamline returned chat id handling (thereby apprently fixing the test, don't ask)
This commit is contained in:
holger krekel
2019-09-04 22:52:05 +02:00
parent d2cb1658e3
commit 135048d63b
6 changed files with 136 additions and 224 deletions

View File

@@ -1341,7 +1341,7 @@ pub unsafe extern "C" fn dc_join_securejoin(
let context = &*context; let context = &*context;
dc_securejoin::dc_join_securejoin(context, qr) dc_securejoin::dc_join_securejoin(context, as_str(qr))
} }
#[no_mangle] #[no_mangle]

View File

@@ -538,7 +538,7 @@ unsafe fn handle_cmd(line: &str, ctx: Arc<RwLock<Context>>) -> Result<ExitResult
"joinqr" => { "joinqr" => {
start_threads(ctx.clone()); start_threads(ctx.clone());
if !arg0.is_empty() { if !arg0.is_empty() {
dc_join_securejoin(&ctx.read().unwrap(), arg1_c); dc_join_securejoin(&ctx.read().unwrap(), arg1);
} }
} }
"exit" | "quit" => return Ok(ExitResult::Exit), "exit" | "quit" => return Ok(ExitResult::Exit),

View File

@@ -316,7 +316,7 @@ class TestOfflineChat:
def test_qr_setup_contact(self, acfactory, lp): def test_qr_setup_contact(self, acfactory, lp):
ac1 = acfactory.get_configured_offline_account() ac1 = acfactory.get_configured_offline_account()
ac2 = acfactory.get_configured_offline_account() ac2 = acfactory.get_configured_offline_account()
qr = ac1.qr_setup_contact() qr = ac1.get_setup_contact_qr()
assert qr.startswith("OPENPGP4FPR:") assert qr.startswith("OPENPGP4FPR:")
res = ac2.check_qr(qr) res = ac2.check_qr(qr)
assert res.is_ask_verifycontact() assert res.is_ask_verifycontact()

View File

@@ -1918,16 +1918,7 @@ pub fn get_chat_cnt(context: &Context) -> usize {
} }
} }
pub unsafe fn get_chat_id_by_grpid( pub fn get_chat_id_by_grpid(context: &Context, grpid: impl AsRef<str>) -> (u32, bool, Blocked) {
context: &Context,
grpid: impl AsRef<str>,
ret_blocked: Option<&mut Blocked>,
ret_verified: *mut libc::c_int,
) -> u32 {
if !ret_verified.is_null() {
*ret_verified = 0;
}
context context
.sql .sql
.query_row( .query_row(
@@ -1936,18 +1927,12 @@ pub unsafe fn get_chat_id_by_grpid(
|row| { |row| {
let chat_id = row.get(0)?; let chat_id = row.get(0)?;
if let Some(b) = ret_blocked { let b = row.get::<_, Option<Blocked>>(1)?.unwrap_or_default();
*b = row.get::<_, Option<Blocked>>(1)?.unwrap_or_default();
}
let v = row.get::<_, Option<Chattype>>(2)?.unwrap_or_default(); let v = row.get::<_, Option<Chattype>>(2)?.unwrap_or_default();
if !ret_verified.is_null() { Ok((chat_id, v == Chattype::VerifiedGroup, b))
*ret_verified = (v == Chattype::VerifiedGroup) as libc::c_int;
}
Ok(chat_id)
}, },
) )
.unwrap_or_default() .unwrap_or((0, false, Blocked::Not))
} }
pub fn add_device_msg(context: &Context, chat_id: u32, text: impl AsRef<str>) { pub fn add_device_msg(context: &Context, chat_id: u32, text: impl AsRef<str>) {

View File

@@ -1034,7 +1034,6 @@ unsafe fn create_or_lookup_group(
let group_explicitly_left: bool; let group_explicitly_left: bool;
let mut chat_id = 0; let mut chat_id = 0;
let mut chat_id_blocked = Blocked::Not; let mut chat_id_blocked = Blocked::Not;
let mut chat_id_verified = 0;
let mut grpid = "".to_string(); let mut grpid = "".to_string();
let mut grpname = std::ptr::null_mut(); let mut grpname = std::ptr::null_mut();
let to_ids_cnt = to_ids.len(); let to_ids_cnt = to_ids.len();
@@ -1216,14 +1215,9 @@ unsafe fn create_or_lookup_group(
set_better_msg(mime_parser, &better_msg); set_better_msg(mime_parser, &better_msg);
// check, if we have a chat with this group ID // check, if we have a chat with this group ID
chat_id = chat::get_chat_id_by_grpid( let (mut chat_id, chat_id_verified, _blocked) = chat::get_chat_id_by_grpid(context, &grpid);
context,
&grpid,
Some(&mut chat_id_blocked),
&mut chat_id_verified,
);
if chat_id != 0 { if chat_id != 0 {
if 0 != chat_id_verified if chat_id_verified
&& 0 == check_verified_properties( && 0 == check_verified_properties(
context, context,
mime_parser, mime_parser,

View File

@@ -21,7 +21,6 @@ use crate::peerstate::*;
use crate::qr::check_qr; use crate::qr::check_qr;
use crate::stock::StockMessage; use crate::stock::StockMessage;
use crate::types::*; use crate::types::*;
use crate::x::*;
pub const NON_ALPHANUMERIC_WITHOUT_DOT: &AsciiSet = &NON_ALPHANUMERIC.remove(b'.'); pub const NON_ALPHANUMERIC_WITHOUT_DOT: &AsciiSet = &NON_ALPHANUMERIC.remove(b'.');
@@ -31,13 +30,7 @@ pub unsafe fn dc_get_securejoin_qr(context: &Context, group_chat_id: uint32_t) -
==== Step 1 in "Setup verified contact" protocol ==== ==== Step 1 in "Setup verified contact" protocol ====
========================================================= */ ========================================================= */
let cleanup = |fingerprint, qr: Option<String>| { let fingerprint: String;
free(fingerprint as *mut libc::c_void);
qr
};
let mut fingerprint = ptr::null_mut();
let mut qr: Option<String> = None;
ensure_secret_key_exists(context).ok(); ensure_secret_key_exists(context).ok();
let invitenumber = dc_token_lookup(context, DC_TOKEN_INVITENUMBER, group_chat_id) let invitenumber = dc_token_lookup(context, DC_TOKEN_INVITENUMBER, group_chat_id)
@@ -60,7 +53,7 @@ pub unsafe fn dc_get_securejoin_qr(context: &Context, group_chat_id: uint32_t) -
if self_addr.is_none() { if self_addr.is_none() {
error!(context, 0, "Not configured, cannot generate QR code.",); error!(context, 0, "Not configured, cannot generate QR code.",);
return cleanup(fingerprint, qr); return None;
} }
let self_addr = self_addr.unwrap(); let self_addr = self_addr.unwrap();
@@ -69,18 +62,19 @@ pub unsafe fn dc_get_securejoin_qr(context: &Context, group_chat_id: uint32_t) -
.get_config(context, "displayname") .get_config(context, "displayname")
.unwrap_or_default(); .unwrap_or_default();
fingerprint = get_self_fingerprint(context); fingerprint = match get_self_fingerprint(context) {
Some(fp) => fp,
if fingerprint.is_null() { None => {
return cleanup(fingerprint, qr); return None;
} }
};
let self_addr_urlencoded = let self_addr_urlencoded =
utf8_percent_encode(&self_addr, NON_ALPHANUMERIC_WITHOUT_DOT).to_string(); utf8_percent_encode(&self_addr, NON_ALPHANUMERIC_WITHOUT_DOT).to_string();
let self_name_urlencoded = let self_name_urlencoded =
utf8_percent_encode(&self_name, NON_ALPHANUMERIC_WITHOUT_DOT).to_string(); utf8_percent_encode(&self_name, NON_ALPHANUMERIC_WITHOUT_DOT).to_string();
qr = if 0 != group_chat_id { let qr = if 0 != group_chat_id {
if let Ok(chat) = Chat::load_from_db(context, group_chat_id) { if let Ok(chat) = Chat::load_from_db(context, group_chat_id) {
let group_name = chat.get_name(); let group_name = chat.get_name();
let group_name_urlencoded = let group_name_urlencoded =
@@ -88,7 +82,7 @@ pub unsafe fn dc_get_securejoin_qr(context: &Context, group_chat_id: uint32_t) -
Some(format!( Some(format!(
"OPENPGP4FPR:{}#a={}&g={}&x={}&i={}&s={}", "OPENPGP4FPR:{}#a={}&g={}&x={}&i={}&s={}",
as_str(fingerprint), fingerprint,
self_addr_urlencoded, self_addr_urlencoded,
&group_name_urlencoded, &group_name_urlencoded,
&chat.grpid, &chat.grpid,
@@ -100,57 +94,51 @@ pub unsafe fn dc_get_securejoin_qr(context: &Context, group_chat_id: uint32_t) -
context, context,
0, "Cannot get QR-code for chat-id {}", group_chat_id, 0, "Cannot get QR-code for chat-id {}", group_chat_id,
); );
return cleanup(fingerprint, qr); return None;
} }
} else { } else {
Some(format!( Some(format!(
"OPENPGP4FPR:{}#a={}&n={}&i={}&s={}", "OPENPGP4FPR:{}#a={}&n={}&i={}&s={}",
as_str(fingerprint), fingerprint, self_addr_urlencoded, self_name_urlencoded, &invitenumber, &auth,
self_addr_urlencoded,
self_name_urlencoded,
&invitenumber,
&auth,
)) ))
}; };
info!(context, 0, "Generated QR code: {}", qr.as_ref().unwrap()); info!(context, 0, "Generated QR code: {}", qr.as_ref().unwrap());
cleanup(fingerprint, qr) qr
} }
fn get_self_fingerprint(context: &Context) -> *mut libc::c_char { fn get_self_fingerprint(context: &Context) -> Option<String> {
if let Some(self_addr) = context.sql.get_config(context, "configured_addr") { if let Some(self_addr) = context.sql.get_config(context, "configured_addr") {
if let Some(key) = Key::from_self_public(context, self_addr, &context.sql) { if let Some(key) = Key::from_self_public(context, self_addr, &context.sql) {
return key.fingerprint_c(); return Some(key.fingerprint());
} }
} }
None
std::ptr::null_mut()
} }
pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) -> uint32_t { pub unsafe fn dc_join_securejoin(context: &Context, qr: &str) -> 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 mut ret_chat_id: libc::c_int = 0i32;
let ongoing_allocated: libc::c_int; let ongoing_allocated: libc::c_int;
let mut contact_chat_id: uint32_t = 0i32 as uint32_t; let mut contact_chat_id: uint32_t = 0;
let mut join_vg: libc::c_int = 0i32; 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); ongoing_allocated = dc_alloc_ongoing(context);
if !(ongoing_allocated == 0i32) { if ongoing_allocated != 0 {
let qr_scan = check_qr(context, as_str(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 { } else {
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 == 0i32 as libc::c_uint { if contact_chat_id == 0 {
error!(context, 0, "Unknown contact.",); error!(context, 0, "Unknown contact.",);
} else if !(context } else if !(context
.running_state .running_state
@@ -159,7 +147,7 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
.unwrap() .unwrap()
.shall_stop_ongoing) .shall_stop_ongoing)
{ {
join_vg = (qr_scan.get_state() == LotState::QrAskVerifyGroup) as libc::c_int; join_vg = qr_scan.get_state() == LotState::QrAskVerifyGroup;
{ {
let mut bob = context.bob.write().unwrap(); let mut bob = context.bob.write().unwrap();
bob.status = 0; bob.status = 0;
@@ -186,14 +174,14 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
chat_id_2_contact_id(context, contact_chat_id) as uintptr_t, chat_id_2_contact_id(context, contact_chat_id) as uintptr_t,
400i32 as uintptr_t, 400i32 as uintptr_t,
); );
let own_fingerprint: *mut libc::c_char = get_self_fingerprint(context); let own_fingerprint = get_self_fingerprint(context).unwrap();
send_handshake_msg( send_handshake_msg(
context, context,
contact_chat_id, contact_chat_id,
if 0 != join_vg { if join_vg {
b"vg-request-with-auth\x00" as *const u8 as *const libc::c_char "vg-request-with-auth"
} else { } else {
b"vc-request-with-auth\x00" as *const u8 as *const libc::c_char "vc-request-with-auth"
}, },
context context
.bob .bob
@@ -206,8 +194,8 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
.as_ref() .as_ref()
.unwrap() .unwrap()
.to_string(), .to_string(),
own_fingerprint, Some(own_fingerprint),
if 0 != join_vg { if join_vg {
context context
.bob .bob
.read() .read()
@@ -223,17 +211,12 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
"".to_string() "".to_string()
}, },
); );
free(own_fingerprint as *mut libc::c_void);
} else { } else {
context.bob.write().unwrap().expects = 2; context.bob.write().unwrap().expects = 2;
send_handshake_msg( send_handshake_msg(
context, context,
contact_chat_id, contact_chat_id,
if 0 != join_vg { if join_vg { "vg-request" } else { "vc-request" },
b"vg-request\x00" as *const u8 as *const libc::c_char
} else {
b"vc-request\x00" as *const u8 as *const libc::c_char
},
context context
.bob .bob
.read() .read()
@@ -244,7 +227,7 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
.invitenumber .invitenumber
.as_ref() .as_ref()
.unwrap(), .unwrap(),
ptr::null(), None,
"", "",
); );
} }
@@ -264,19 +247,19 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
} }
let mut bob = context.bob.write().unwrap(); let mut bob = context.bob.write().unwrap();
bob.expects = 0; bob.expects = 0;
if bob.status == 1 { let ret_chat_id = if bob.status == 1 {
if 0 != join_vg { if join_vg {
ret_chat_id = chat::get_chat_id_by_grpid( chat::get_chat_id_by_grpid(
context, context,
bob.qr_scan.as_ref().unwrap().text2.as_ref().unwrap(), bob.qr_scan.as_ref().unwrap().text2.as_ref().unwrap(),
None, )
ptr::null_mut(), .0
) as libc::c_int
} else { } else {
ret_chat_id = contact_chat_id as libc::c_int contact_chat_id
} }
} } else {
0
};
bob.qr_scan = None; bob.qr_scan = None;
if 0 != ongoing_allocated { if 0 != ongoing_allocated {
@@ -288,33 +271,31 @@ pub unsafe fn dc_join_securejoin(context: &Context, qr: *const libc::c_char) ->
unsafe fn send_handshake_msg( unsafe fn send_handshake_msg(
context: &Context, context: &Context,
contact_chat_id: uint32_t, contact_chat_id: uint32_t,
step: *const libc::c_char, step: &str,
param2: impl AsRef<str>, param2: impl AsRef<str>,
fingerprint: *const libc::c_char, fingerprint: Option<String>,
grpid: impl AsRef<str>, grpid: impl AsRef<str>,
) { ) {
let mut msg = dc_msg_new_untyped(context); let mut msg = dc_msg_new_untyped(context);
msg.type_0 = Viewtype::Text; msg.type_0 = Viewtype::Text;
msg.text = Some(format!("Secure-Join: {}", to_string(step))); msg.text = Some(format!("Secure-Join: {}", step));
msg.hidden = true; msg.hidden = true;
msg.param.set_int(Param::Cmd, 7); msg.param.set_int(Param::Cmd, 7);
if step.is_null() { if step.is_empty() {
msg.param.remove(Param::Arg); msg.param.remove(Param::Arg);
} else { } else {
msg.param.set(Param::Arg, as_str(step)); msg.param.set(Param::Arg, step);
} }
if !param2.as_ref().is_empty() { if !param2.as_ref().is_empty() {
msg.param.set(Param::Arg2, param2); msg.param.set(Param::Arg2, param2);
} }
if !fingerprint.is_null() { if let Some(fp) = fingerprint {
msg.param.set(Param::Arg3, as_str(fingerprint)); msg.param.set(Param::Arg3, fp);
} }
if !grpid.as_ref().is_empty() { if !grpid.as_ref().is_empty() {
msg.param.set(Param::Arg4, grpid.as_ref()); msg.param.set(Param::Arg4, grpid.as_ref());
} }
if strcmp(step, b"vg-request\x00" as *const u8 as *const libc::c_char) == 0i32 if step == "vg-request" || step == "vc-request" {
|| strcmp(step, b"vc-request\x00" as *const u8 as *const libc::c_char) == 0i32
{
msg.param.set_int( msg.param.set_int(
Param::ForcePlaintext, Param::ForcePlaintext,
ForcePlaintext::AddAutocryptHeader as i32, ForcePlaintext::AddAutocryptHeader as i32,
@@ -326,7 +307,7 @@ unsafe fn send_handshake_msg(
chat::send_msg(context, contact_chat_id, &mut msg).unwrap(); chat::send_msg(context, contact_chat_id, &mut msg).unwrap();
} }
unsafe fn chat_id_2_contact_id(context: &Context, contact_chat_id: uint32_t) -> uint32_t { fn chat_id_2_contact_id(context: &Context, contact_chat_id: uint32_t) -> uint32_t {
let contacts = chat::get_chat_contacts(context, contact_chat_id); let contacts = chat::get_chat_contacts(context, contact_chat_id);
if contacts.len() == 1 { if contacts.len() == 1 {
contacts[0] contacts[0]
@@ -365,25 +346,22 @@ pub unsafe fn dc_handle_securejoin_handshake(
contact_id: uint32_t, contact_id: uint32_t,
) -> libc::c_int { ) -> libc::c_int {
let mut ok_to_continue: bool; let mut ok_to_continue: bool;
let step: *const libc::c_char; let step: String;
let join_vg: libc::c_int; let join_vg: bool;
let mut own_fingerprint: *mut libc::c_char = ptr::null_mut(); let own_fingerprint: String;
let contact_chat_id: u32; let contact_chat_id: u32;
let contact_chat_id_blocked: Blocked; let contact_chat_id_blocked: Blocked;
let mut grpid = "".to_string(); let mut grpid = "".to_string();
let mut ret: libc::c_int = 0i32; let mut ret: libc::c_int = 0i32;
if !(contact_id <= 9i32 as libc::c_uint) { if !(contact_id <= DC_CONTACT_ID_LAST_SPECIAL) {
step = lookup_field(mimeparser, "Secure-Join"); step = lookup_field(mimeparser, "Secure-Join");
if !step.is_null() { if !step.is_empty() {
info!( info!(
context, context,
0, 0, ">>>>>>>>>>>>>>>>>>>>>>>>> secure-join message \'{}\' received", step,
">>>>>>>>>>>>>>>>>>>>>>>>> secure-join message \'{}\' received",
as_str(step),
); );
join_vg = (strncmp(step, b"vg-\x00" as *const u8 as *const libc::c_char, 3) == 0) join_vg = step.starts_with("vg-");
as libc::c_int;
let (id, bl) = chat::create_or_lookup_by_contact_id(context, contact_id, Blocked::Not) let (id, bl) = 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 = id;
@@ -393,9 +371,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
chat::unblock(context, contact_chat_id); chat::unblock(context, contact_chat_id);
} }
ret = 0x2i32; ret = 0x2i32;
if strcmp(step, b"vg-request\x00" as *const u8 as *const libc::c_char) == 0i32 if step == "vg-request" || step == "vc-request" {
|| strcmp(step, b"vc-request\x00" as *const u8 as *const libc::c_char) == 0i32
{
/* ========================================================= /* =========================================================
==== Alice - the inviter side ==== ==== Alice - the inviter side ====
==== Step 3 in "Setup verified contact" protocol ==== ==== Step 3 in "Setup verified contact" protocol ====
@@ -404,12 +380,11 @@ pub unsafe fn dc_handle_securejoin_handshake(
// it just ensures, we have Bobs key now. If we do _not_ have the key because eg. MitM has removed it, // it just ensures, we have Bobs key now. If we do _not_ have the key because eg. MitM has removed it,
// send_message() will fail with the error "End-to-end-encryption unavailable unexpectedly.", so, there is no additional check needed here. // send_message() will fail with the error "End-to-end-encryption unavailable unexpectedly.", so, there is no additional check needed here.
// verify that the `Secure-Join-Invitenumber:`-header matches invitenumber written to the QR code // verify that the `Secure-Join-Invitenumber:`-header matches invitenumber written to the QR code
let invitenumber: *const libc::c_char; let invitenumber = lookup_field(mimeparser, "Secure-Join-Invitenumber");
invitenumber = lookup_field(mimeparser, "Secure-Join-Invitenumber"); if invitenumber == "" {
if invitenumber.is_null() {
warn!(context, 0, "Secure-join denied (invitenumber missing).",); warn!(context, 0, "Secure-join denied (invitenumber missing).",);
ok_to_continue = false; ok_to_continue = false;
} else if !dc_token_exists(context, DC_TOKEN_INVITENUMBER, as_str(invitenumber)) { } else 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; ok_to_continue = false;
} else { } else {
@@ -423,32 +398,24 @@ pub unsafe fn dc_handle_securejoin_handshake(
send_handshake_msg( send_handshake_msg(
context, context,
contact_chat_id, contact_chat_id,
if 0 != join_vg { if join_vg {
b"vg-auth-required\x00" as *const u8 as *const libc::c_char "vg-auth-required"
} else { } else {
b"vc-auth-required\x00" as *const u8 as *const libc::c_char "vc-auth-required"
}, },
"", "",
ptr::null(), None,
"", "",
); );
ok_to_continue = true; ok_to_continue = true;
} }
} else if strcmp( } else if step == "vg-auth-required" || step == "vc-auth-required" {
step,
b"vg-auth-required\x00" as *const u8 as *const libc::c_char,
) == 0i32
|| strcmp(
step,
b"vc-auth-required\x00" as *const u8 as *const libc::c_char,
) == 0i32
{
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()
|| bob.expects != 2 || bob.expects != 2
|| 0 != join_vg && scan.unwrap().state != LotState::QrAskVerifyGroup || join_vg && scan.unwrap().state != LotState::QrAskVerifyGroup
}; };
if cond { if cond {
@@ -479,7 +446,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
.as_ref() .as_ref()
.unwrap() .unwrap()
.to_string(); .to_string();
if 0 != join_vg { if join_vg {
grpid = context grpid = context
.bob .bob
.read() .read()
@@ -498,9 +465,9 @@ pub unsafe fn dc_handle_securejoin_handshake(
context, context,
contact_chat_id, contact_chat_id,
if mimeparser.e2ee_helper.encrypted { if mimeparser.e2ee_helper.encrypted {
b"No valid signature.\x00" as *const u8 as *const libc::c_char "No valid signature."
} else { } else {
b"Not encrypted.\x00" as *const u8 as *const libc::c_char "Not encrypted."
}, },
); );
end_bobs_joining(context, 0i32); end_bobs_joining(context, 0i32);
@@ -513,14 +480,13 @@ pub unsafe fn dc_handle_securejoin_handshake(
could_not_establish_secure_connection( could_not_establish_secure_connection(
context, context,
contact_chat_id, contact_chat_id,
b"Fingerprint mismatch on joiner-side.\x00" as *const u8 "Fingerprint mismatch on joiner-side.",
as *const libc::c_char,
); );
end_bobs_joining(context, 0i32); end_bobs_joining(context, 0i32);
ok_to_continue = false; ok_to_continue = false;
} else { } else {
info!(context, 0, "Fingerprint verified.",); info!(context, 0, "Fingerprint verified.",);
own_fingerprint = get_self_fingerprint(context); own_fingerprint = get_self_fingerprint(context).unwrap();
context.call_cb( context.call_cb(
Event::SECUREJOIN_JOINER_PROGRESS, Event::SECUREJOIN_JOINER_PROGRESS,
contact_id as uintptr_t, contact_id as uintptr_t,
@@ -531,27 +497,19 @@ pub unsafe fn dc_handle_securejoin_handshake(
send_handshake_msg( send_handshake_msg(
context, context,
contact_chat_id, contact_chat_id,
if 0 != join_vg { if join_vg {
b"vg-request-with-auth\x00" as *const u8 as *const libc::c_char "vg-request-with-auth"
} else { } else {
b"vc-request-with-auth\x00" as *const u8 as *const libc::c_char "vc-request-with-auth"
}, },
auth, auth,
own_fingerprint, Some(own_fingerprint),
grpid, grpid,
); );
ok_to_continue = true; ok_to_continue = true;
} }
} }
} else if strcmp( } else if step == "vg-request-with-auth" || step == "vc-request-with-auth" {
step,
b"vg-request-with-auth\x00" as *const u8 as *const libc::c_char,
) == 0i32
|| strcmp(
step,
b"vc-request-with-auth\x00" as *const u8 as *const libc::c_char,
) == 0i32
{
/* ============================================================ /* ============================================================
==== Alice - the inviter side ==== ==== Alice - the inviter side ====
==== Steps 5+6 in "Setup verified contact" protocol ==== ==== Steps 5+6 in "Setup verified contact" protocol ====
@@ -559,54 +517,50 @@ pub unsafe fn dc_handle_securejoin_handshake(
============================================================ */ ============================================================ */
// verify that Secure-Join-Fingerprint:-header matches the fingerprint of Bob // verify that Secure-Join-Fingerprint:-header matches the fingerprint of Bob
let fingerprint = lookup_field(mimeparser, "Secure-Join-Fingerprint"); let fingerprint = lookup_field(mimeparser, "Secure-Join-Fingerprint");
if fingerprint.is_null() { if fingerprint.is_empty() {
could_not_establish_secure_connection( could_not_establish_secure_connection(
context, context,
contact_chat_id, contact_chat_id,
b"Fingerprint not provided.\x00" as *const u8 as *const libc::c_char, "Fingerprint not provided.",
); );
ok_to_continue = false; ok_to_continue = false;
} else if !encrypted_and_signed(mimeparser, as_str(fingerprint)) { } else if !encrypted_and_signed(mimeparser, &fingerprint) {
could_not_establish_secure_connection( could_not_establish_secure_connection(
context, context,
contact_chat_id, contact_chat_id,
b"Auth not encrypted.\x00" as *const u8 as *const libc::c_char, "Auth not encrypted.",
); );
ok_to_continue = false; ok_to_continue = false;
} else if !fingerprint_equals_sender(context, as_str(fingerprint), contact_chat_id) } else 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,
b"Fingerprint mismatch on inviter-side.\x00" as *const u8 "Fingerprint mismatch on inviter-side.",
as *const libc::c_char,
); );
ok_to_continue = false; ok_to_continue = false;
} else { } 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: *const libc::c_char; let auth_0 = lookup_field(mimeparser, "Secure-Join-Auth");
auth_0 = lookup_field(mimeparser, "Secure-Join-Auth"); if auth_0.is_empty() {
if auth_0.is_null() {
could_not_establish_secure_connection( could_not_establish_secure_connection(
context, context,
contact_chat_id, contact_chat_id,
b"Auth not provided.\x00" as *const u8 as *const libc::c_char, "Auth not provided.",
); );
ok_to_continue = false; ok_to_continue = false;
} else if !dc_token_exists(context, DC_TOKEN_AUTH, as_str(auth_0)) { } else if !dc_token_exists(context, DC_TOKEN_AUTH, &auth_0) {
could_not_establish_secure_connection( could_not_establish_secure_connection(
context, context,
contact_chat_id, contact_chat_id,
b"Auth invalid.\x00" as *const u8 as *const libc::c_char, "Auth invalid.",
); );
ok_to_continue = false; ok_to_continue = false;
} else if mark_peer_as_verified(context, as_str(fingerprint)).is_err() { } 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,
b"Fingerprint mismatch on inviter-side.\x00" as *const u8 "Fingerprint mismatch on inviter-side.",
as *const libc::c_char,
); );
ok_to_continue = false; ok_to_continue = false;
} else { } else {
@@ -627,11 +581,10 @@ pub unsafe fn dc_handle_securejoin_handshake(
contact_id as uintptr_t, contact_id as uintptr_t,
600i32 as uintptr_t, 600i32 as uintptr_t,
); );
if 0 != join_vg { if join_vg {
grpid = to_string(lookup_field(mimeparser, "Secure-Join-Group")); grpid = lookup_field(mimeparser, "Secure-Join-Group");
let group_chat_id: uint32_t = let (group_chat_id, _, _) = chat::get_chat_id_by_grpid(context, &grpid);
chat::get_chat_id_by_grpid(context, &grpid, None, ptr::null_mut()); if group_chat_id == 0 {
if group_chat_id == 0i32 as libc::c_uint {
error!(context, 0, "Chat {} not found.", &grpid); error!(context, 0, "Chat {} not found.", &grpid);
ok_to_continue = false; ok_to_continue = false;
} else { } else {
@@ -647,9 +600,9 @@ pub unsafe fn dc_handle_securejoin_handshake(
send_handshake_msg( send_handshake_msg(
context, context,
contact_chat_id, contact_chat_id,
b"vc-contact-confirm\x00" as *const u8 as *const libc::c_char, "vc-contact-confirm",
"", "",
ptr::null(), None,
"", "",
); );
context.call_cb( context.call_cb(
@@ -661,16 +614,8 @@ pub unsafe fn dc_handle_securejoin_handshake(
} }
} }
} }
} else if strcmp( } else if step == "vg-member-added" || step == "vc-contact-confirm" {
step, if join_vg {
b"vg-member-added\x00" as *const u8 as *const libc::c_char,
) == 0i32
|| strcmp(
step,
b"vc-contact-confirm\x00" as *const u8 as *const libc::c_char,
) == 0i32
{
if 0 != join_vg {
ret = 0x1i32 ret = 0x1i32
} }
if context.bob.read().unwrap().expects != 6 { if context.bob.read().unwrap().expects != 6 {
@@ -681,7 +626,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
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()
|| 0 != join_vg && scan.unwrap().state != LotState::QrAskVerifyGroup || join_vg && scan.unwrap().state != LotState::QrAskVerifyGroup
}; };
if cond { if cond {
warn!( warn!(
@@ -702,7 +647,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
.unwrap() .unwrap()
.to_string(); .to_string();
if 0 != join_vg { if join_vg {
grpid = context grpid = context
.bob .bob
.read() .read()
@@ -716,26 +661,23 @@ pub unsafe fn dc_handle_securejoin_handshake(
.to_string(); .to_string();
} }
let mut vg_expect_encrypted: libc::c_int = 1i32; let vg_expect_encrypted = if join_vg {
if 0 != join_vg { let (_, is_verified_group, _) =
let mut is_verified_group: libc::c_int = 0i32; chat::get_chat_id_by_grpid(context, grpid);
chat::get_chat_id_by_grpid( // when joining a non-verified group
context, // the vg-member-added message may be unencrypted
grpid, // when not all group members have keys or prefer encryption.
None, // So only expect encryption if this is a verified group
&mut is_verified_group, is_verified_group
); } else {
if 0 == is_verified_group { true
vg_expect_encrypted = 0i32 };
} if vg_expect_encrypted {
}
if 0 != vg_expect_encrypted {
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,
contact_chat_id, contact_chat_id,
b"Contact confirm message not encrypted.\x00" as *const u8 "Contact confirm message not encrypted.",
as *const libc::c_char,
); );
end_bobs_joining(context, 0i32); end_bobs_joining(context, 0i32);
ok_to_continue = false; ok_to_continue = false;
@@ -752,8 +694,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
could_not_establish_secure_connection( could_not_establish_secure_connection(
context, context,
contact_chat_id, contact_chat_id,
b"Fingerprint mismatch on joiner-side.\x00" as *const u8 "Fingerprint mismatch on joiner-side.",
as *const libc::c_char,
); );
ok_to_continue = false; ok_to_continue = false;
} else { } else {
@@ -767,10 +708,10 @@ pub unsafe fn dc_handle_securejoin_handshake(
0i32 as uintptr_t, 0i32 as uintptr_t,
0i32 as uintptr_t, 0i32 as uintptr_t,
); );
if 0 != join_vg { if join_vg {
if !addr_equals_self( if !addr_equals_self(
context, context,
as_str(lookup_field(mimeparser, "Chat-Group-Member-Added")), lookup_field(mimeparser, "Chat-Group-Member-Added"),
) { ) {
info!( info!(
context, context,
@@ -787,14 +728,13 @@ pub unsafe fn dc_handle_securejoin_handshake(
if ok_to_continue { 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 0 != join_vg { if join_vg {
send_handshake_msg( send_handshake_msg(
context, context,
contact_chat_id, contact_chat_id,
b"vg-member-added-received\x00" as *const u8 "vg-member-added-received",
as *const libc::c_char,
"", "",
ptr::null(), None,
"", "",
); );
} }
@@ -805,11 +745,7 @@ pub unsafe fn dc_handle_securejoin_handshake(
} }
} }
} }
} else if strcmp( } else if step == "vg-member-added-received" {
step,
b"vg-member-added-received\x00" as *const u8 as *const libc::c_char,
) == 0i32
{
/* ============================================================ /* ============================================================
==== 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 ====
@@ -846,8 +782,6 @@ pub unsafe fn dc_handle_securejoin_handshake(
} }
} }
free(own_fingerprint as *mut libc::c_void);
ret ret
} }
@@ -873,9 +807,9 @@ unsafe fn secure_connection_established(context: &Context, contact_chat_id: uint
); );
} }
unsafe fn lookup_field(mimeparser: &dc_mimeparser_t, key: &str) -> *const libc::c_char { unsafe fn lookup_field(mimeparser: &dc_mimeparser_t, key: &str) -> String {
let mut value: *const libc::c_char = ptr::null();
let field: *mut mailimf_field = dc_mimeparser_lookup_field(mimeparser, key); let field: *mut mailimf_field = dc_mimeparser_lookup_field(mimeparser, key);
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
|| (*field).fld_data.fld_optional_field.is_null() || (*field).fld_data.fld_optional_field.is_null()
@@ -884,18 +818,17 @@ unsafe fn lookup_field(mimeparser: &dc_mimeparser_t, key: &str) -> *const libc::
value.is_null() value.is_null()
} }
{ {
return ptr::null(); return String::from("");
} }
as_str(value).to_string()
value
} }
unsafe fn could_not_establish_secure_connection( fn could_not_establish_secure_connection(
context: &Context, context: &Context,
contact_chat_id: uint32_t, contact_chat_id: uint32_t,
details: *const libc::c_char, details: &str,
) { ) {
let contact_id: uint32_t = chat_id_2_contact_id(context, contact_chat_id); let contact_id = 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 msg = context.stock_string_repl_str( let msg = context.stock_string_repl_str(
StockMessage::ContactNotVerified, StockMessage::ContactNotVerified,
@@ -907,7 +840,7 @@ unsafe fn could_not_establish_secure_connection(
); );
chat::add_device_msg(context, contact_chat_id, &msg); chat::add_device_msg(context, contact_chat_id, &msg);
error!(context, 0, "{} ({})", &msg, as_str(details)); error!(context, 0, "{} ({})", &msg, details);
} }
fn mark_peer_as_verified(context: &Context, fingerprint: impl AsRef<str>) -> Result<(), Error> { fn mark_peer_as_verified(context: &Context, fingerprint: impl AsRef<str>) -> Result<(), Error> {