mirror of
https://github.com/chatmail/core.git
synced 2026-05-15 12:56:30 +03:00
Turn the function safe
This commit is contained in:
committed by
Floris Bruynooghe
parent
c568d5dcac
commit
d37dda6f50
@@ -561,30 +561,17 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E
|
|||||||
}
|
}
|
||||||
"export-setup" => {
|
"export-setup" => {
|
||||||
let setup_code = dc_create_setup_code(context);
|
let setup_code = dc_create_setup_code(context);
|
||||||
let setup_code_c = CString::new(setup_code.clone()).unwrap();
|
|
||||||
let file_name: *mut libc::c_char = dc_mprintf(
|
let file_name: *mut libc::c_char = dc_mprintf(
|
||||||
b"%s/autocrypt-setup-message.html\x00" as *const u8 as *const libc::c_char,
|
b"%s/autocrypt-setup-message.html\x00" as *const u8 as *const libc::c_char,
|
||||||
context.get_blobdir(),
|
context.get_blobdir(),
|
||||||
);
|
);
|
||||||
let file_content: *mut libc::c_char;
|
let file_content = dc_render_setup_file(context, &setup_code)?;
|
||||||
file_content = dc_render_setup_file(context, setup_code_c.as_ptr());
|
std::fs::write(as_str(file_name), file_content)?;
|
||||||
if !file_content.is_null()
|
println!(
|
||||||
&& 0 != dc_write_file(
|
"Setup message written to: {}\nSetup code: {}",
|
||||||
context,
|
as_str(file_name),
|
||||||
file_name,
|
&setup_code,
|
||||||
file_content as *const libc::c_void,
|
);
|
||||||
strlen(file_content),
|
|
||||||
)
|
|
||||||
{
|
|
||||||
println!(
|
|
||||||
"Setup message written to: {}\nSetup code: {}",
|
|
||||||
as_str(file_name),
|
|
||||||
&setup_code,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
bail!("");
|
|
||||||
}
|
|
||||||
free(file_content as *mut libc::c_void);
|
|
||||||
free(file_name as *mut libc::c_void);
|
free(file_name as *mut libc::c_void);
|
||||||
}
|
}
|
||||||
"poke" => {
|
"poke" => {
|
||||||
|
|||||||
167
src/dc_imex.rs
167
src/dc_imex.rs
@@ -14,6 +14,7 @@ use crate::dc_e2ee::*;
|
|||||||
use crate::dc_job::*;
|
use crate::dc_job::*;
|
||||||
use crate::dc_msg::*;
|
use crate::dc_msg::*;
|
||||||
use crate::dc_tools::*;
|
use crate::dc_tools::*;
|
||||||
|
use crate::error::*;
|
||||||
use crate::key::*;
|
use crate::key::*;
|
||||||
use crate::param::*;
|
use crate::param::*;
|
||||||
use crate::pgp::*;
|
use crate::pgp::*;
|
||||||
@@ -99,13 +100,12 @@ 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_content: *mut libc::c_char = 0 as *mut libc::c_char;
|
|
||||||
let mut setup_file_name: *mut libc::c_char = 0 as *mut libc::c_char;
|
let mut setup_file_name: *mut libc::c_char = 0 as *mut libc::c_char;
|
||||||
let mut msg: *mut dc_msg_t = 0 as *mut dc_msg_t;
|
let mut msg: *mut dc_msg_t = 0 as *mut dc_msg_t;
|
||||||
if dc_alloc_ongoing(context) == 0 {
|
if dc_alloc_ongoing(context) == 0 {
|
||||||
return std::ptr::null_mut();
|
return std::ptr::null_mut();
|
||||||
}
|
}
|
||||||
let setup_code = CString::new(dc_create_setup_code(context)).unwrap();
|
let setup_code = dc_create_setup_code(context);
|
||||||
/* this may require a keypair to be created. this may take a second ... */
|
/* this may require a keypair to be created. this may take a second ... */
|
||||||
if !context
|
if !context
|
||||||
.running_state
|
.running_state
|
||||||
@@ -114,8 +114,8 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.shall_stop_ongoing
|
.shall_stop_ongoing
|
||||||
{
|
{
|
||||||
setup_file_content = dc_render_setup_file(context, setup_code.as_ptr());
|
if let Ok(setup_file_content) = dc_render_setup_file(context, &setup_code) {
|
||||||
if !setup_file_content.is_null() {
|
let setup_file_content_c = CString::yolo(setup_file_content.as_str());
|
||||||
/* encrypting may also take a while ... */
|
/* encrypting may also take a while ... */
|
||||||
if !context
|
if !context
|
||||||
.running_state
|
.running_state
|
||||||
@@ -133,8 +133,8 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
|||||||
|| 0 == dc_write_file(
|
|| 0 == dc_write_file(
|
||||||
context,
|
context,
|
||||||
setup_file_name,
|
setup_file_name,
|
||||||
setup_file_content as *const libc::c_void,
|
setup_file_content_c.as_ptr() as *const libc::c_void,
|
||||||
strlen(setup_file_content),
|
setup_file_content_c.as_bytes().len(),
|
||||||
))
|
))
|
||||||
{
|
{
|
||||||
let chat_id = dc_create_chat_by_contact_id(context, 1i32 as uint32_t);
|
let chat_id = dc_create_chat_by_contact_id(context, 1i32 as uint32_t);
|
||||||
@@ -188,79 +188,78 @@ pub unsafe fn dc_initiate_key_transfer(context: &Context) -> *mut libc::c_char {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(setup_file_name as *mut libc::c_void);
|
free(setup_file_name as *mut libc::c_void);
|
||||||
free(setup_file_content as *mut libc::c_void);
|
|
||||||
dc_msg_unref(msg);
|
dc_msg_unref(msg);
|
||||||
dc_free_ongoing(context);
|
dc_free_ongoing(context);
|
||||||
|
|
||||||
dc_strdup(setup_code.as_ptr())
|
setup_code.strdup()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn dc_render_setup_file(
|
pub fn dc_render_setup_file(context: &Context, passphrase: &str) -> Result<String> {
|
||||||
context: &Context,
|
ensure!(
|
||||||
passphrase: *const libc::c_char,
|
passphrase.len() >= 2,
|
||||||
) -> *mut libc::c_char {
|
"Passphrase must be at least 2 chars long."
|
||||||
let mut ret_setupfilecontent: *mut libc::c_char = 0 as *mut libc::c_char;
|
);
|
||||||
if !(passphrase.is_null() || strlen(passphrase) < 2) {
|
unsafe {
|
||||||
/* create the payload */
|
ensure!(
|
||||||
if !(0 == dc_ensure_secret_key_exists(context)) {
|
!(dc_ensure_secret_key_exists(context) == 0),
|
||||||
let self_addr = context
|
"No secret key available."
|
||||||
.sql
|
);
|
||||||
.get_config(context, Config::ConfiguredAddr)
|
|
||||||
.unwrap_or_default();
|
|
||||||
let curr_private_key = Key::from_self_private(context, self_addr, &context.sql);
|
|
||||||
let e2ee_enabled = context
|
|
||||||
.sql
|
|
||||||
.get_config_int(context, Config::E2eeEnabled)
|
|
||||||
.unwrap_or_else(|| 1);
|
|
||||||
|
|
||||||
let headers = if 0 != e2ee_enabled {
|
|
||||||
Some(("Autocrypt-Prefer-Encrypt", "mutual"))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Some(payload_key_asc) = curr_private_key.map(|k| k.to_asc(headers)) {
|
|
||||||
let payload_key_asc_c = CString::new(payload_key_asc).unwrap();
|
|
||||||
if let Some(encr) = dc_pgp_symm_encrypt(
|
|
||||||
passphrase,
|
|
||||||
payload_key_asc_c.as_ptr() as *const libc::c_void,
|
|
||||||
payload_key_asc_c.as_bytes().len(),
|
|
||||||
) {
|
|
||||||
let replacement = format!(
|
|
||||||
concat!(
|
|
||||||
"-----BEGIN PGP MESSAGE-----\r\n",
|
|
||||||
"Passphrase-Format: numeric9x4\r\n",
|
|
||||||
"Passphrase-Begin: {}"
|
|
||||||
),
|
|
||||||
&as_str(passphrase)[..2]
|
|
||||||
);
|
|
||||||
let pgp_msg = encr.replace("-----BEGIN PGP MESSAGE-----", &replacement);
|
|
||||||
|
|
||||||
let msg_subj = context.stock_str(StockMessage::AcSetupMsgSubject);
|
|
||||||
let msg_body = context.stock_str(StockMessage::AcSetupMsgBody);
|
|
||||||
let msg_body_head: &str = msg_body.split('\r').next().unwrap();
|
|
||||||
let msg_body_html = msg_body_head.replace("\n", "<br>");
|
|
||||||
ret_setupfilecontent = to_cstring(format!(
|
|
||||||
concat!(
|
|
||||||
"<!DOCTYPE html>\r\n",
|
|
||||||
"<html>\r\n",
|
|
||||||
" <head>\r\n",
|
|
||||||
" <title>{}</title>\r\n",
|
|
||||||
" </head>\r\n",
|
|
||||||
" <body>\r\n",
|
|
||||||
" <h1>{}</h1>\r\n",
|
|
||||||
" <p>{}</p>\r\n",
|
|
||||||
" <pre>\r\n{}\r\n</pre>\r\n",
|
|
||||||
" </body>\r\n",
|
|
||||||
"</html>\r\n"
|
|
||||||
),
|
|
||||||
msg_subj, msg_subj, msg_body_html, pgp_msg
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ret_setupfilecontent
|
let self_addr = context
|
||||||
|
.get_config(Config::ConfiguredAddr)
|
||||||
|
.ok_or(format_err!("Failed to get self address."))?;
|
||||||
|
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
|
||||||
|
.sql
|
||||||
|
.get_config_int(context, Config::E2eeEnabled)
|
||||||
|
.unwrap_or(1)
|
||||||
|
{
|
||||||
|
0 => None,
|
||||||
|
_ => Some(("Autocrypt-Prefer-Encrypt", "mutual")),
|
||||||
|
};
|
||||||
|
let private_key_asc = private_key.to_asc(ac_headers);
|
||||||
|
let encr = {
|
||||||
|
let private_key_asc_c = CString::yolo(private_key_asc);
|
||||||
|
let passphrase_c = CString::yolo(passphrase);
|
||||||
|
dc_pgp_symm_encrypt(
|
||||||
|
passphrase_c.as_ptr(),
|
||||||
|
private_key_asc_c.as_ptr() as *const libc::c_void,
|
||||||
|
private_key_asc_c.as_bytes().len(),
|
||||||
|
)
|
||||||
|
.ok_or(format_err!("Failed to encrypt private key."))?
|
||||||
|
};
|
||||||
|
let replacement = format!(
|
||||||
|
concat!(
|
||||||
|
"-----BEGIN PGP MESSAGE-----\r\n",
|
||||||
|
"Passphrase-Format: numeric9x4\r\n",
|
||||||
|
"Passphrase-Begin: {}"
|
||||||
|
),
|
||||||
|
&passphrase[..2]
|
||||||
|
);
|
||||||
|
let pgp_msg = encr.replace("-----BEGIN PGP MESSAGE-----", &replacement);
|
||||||
|
|
||||||
|
let msg_subj = context.stock_str(StockMessage::AcSetupMsgSubject);
|
||||||
|
let msg_body = context.stock_str(StockMessage::AcSetupMsgBody);
|
||||||
|
// let msg_body_head: &str = msg_body.split('\r').next().unwrap();
|
||||||
|
// let msg_body_html = msg_body_head.replace("\n", "<br>");
|
||||||
|
let msg_body_html = msg_body.replace("\n", "<br>");
|
||||||
|
Ok(format!(
|
||||||
|
concat!(
|
||||||
|
"<!DOCTYPE html>\r\n",
|
||||||
|
"<html>\r\n",
|
||||||
|
" <head>\r\n",
|
||||||
|
" <title>{}</title>\r\n",
|
||||||
|
" </head>\r\n",
|
||||||
|
" <body>\r\n",
|
||||||
|
" <h1>{}</h1>\r\n",
|
||||||
|
" <p>{}</p>\r\n",
|
||||||
|
" <pre>\r\n{}\r\n</pre>\r\n",
|
||||||
|
" </body>\r\n",
|
||||||
|
"</html>\r\n"
|
||||||
|
),
|
||||||
|
msg_subj, msg_subj, msg_body_html, pgp_msg
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dc_create_setup_code(_context: &Context) -> String {
|
pub fn dc_create_setup_code(_context: &Context) -> String {
|
||||||
@@ -1427,12 +1426,7 @@ mod tests {
|
|||||||
let t = test_context(Some(logging_cb));
|
let t = test_context(Some(logging_cb));
|
||||||
|
|
||||||
create_alice_keypair(&t.ctx); // Trick things to think we're configured.
|
create_alice_keypair(&t.ctx); // Trick things to think we're configured.
|
||||||
let msg = unsafe {
|
let msg = dc_render_setup_file(&t.ctx, "hello").unwrap();
|
||||||
to_string(dc_render_setup_file(
|
|
||||||
&t.ctx,
|
|
||||||
b"hello\x00" as *const u8 as *const libc::c_char,
|
|
||||||
))
|
|
||||||
};
|
|
||||||
println!("{}", &msg);
|
println!("{}", &msg);
|
||||||
// Check some substrings, indicating things got substituted.
|
// Check some substrings, indicating things got substituted.
|
||||||
// In particular note the mixing of `\r\n` and `\n` depending
|
// In particular note the mixing of `\r\n` and `\n` depending
|
||||||
@@ -1446,4 +1440,19 @@ mod tests {
|
|||||||
assert!(msg.contains("==\n"));
|
assert!(msg.contains("==\n"));
|
||||||
assert!(msg.contains("-----END PGP MESSAGE-----\n"));
|
assert!(msg.contains("-----END PGP MESSAGE-----\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_setup_code() {
|
||||||
|
let t = dummy_context();
|
||||||
|
let setupcode = dc_create_setup_code(&t.ctx);
|
||||||
|
assert_eq!(setupcode.len(), 44);
|
||||||
|
assert_eq!(setupcode.chars().nth(4).unwrap(), '-');
|
||||||
|
assert_eq!(setupcode.chars().nth(9).unwrap(), '-');
|
||||||
|
assert_eq!(setupcode.chars().nth(14).unwrap(), '-');
|
||||||
|
assert_eq!(setupcode.chars().nth(19).unwrap(), '-');
|
||||||
|
assert_eq!(setupcode.chars().nth(24).unwrap(), '-');
|
||||||
|
assert_eq!(setupcode.chars().nth(29).unwrap(), '-');
|
||||||
|
assert_eq!(setupcode.chars().nth(34).unwrap(), '-');
|
||||||
|
assert_eq!(setupcode.chars().nth(39).unwrap(), '-');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -521,51 +521,13 @@ unsafe fn stress_functions(context: &Context) {
|
|||||||
);
|
);
|
||||||
free(buf_1 as *mut libc::c_void);
|
free(buf_1 as *mut libc::c_void);
|
||||||
if 0 != dc_is_configured(context) {
|
if 0 != dc_is_configured(context) {
|
||||||
let setupfile: *mut libc::c_char;
|
let setupcode = dc_create_setup_code(context);
|
||||||
let setupcode_c =
|
let setupcode_c = CString::yolo(setupcode.clone());
|
||||||
CString::new(dc_create_setup_code(context)).expect("invalid string converted");
|
let setupfile = dc_render_setup_file(context, &setupcode).unwrap();
|
||||||
assert_eq!(setupcode_c.to_bytes().len(), 44);
|
let setupfile_c = CString::yolo(setupfile);
|
||||||
let setupcode = setupcode_c.as_ptr();
|
|
||||||
assert!(
|
|
||||||
0 != !(*setupcode.offset(4isize) as libc::c_int == '-' as i32
|
|
||||||
&& *setupcode.offset(9isize) as libc::c_int == '-' as i32
|
|
||||||
&& *setupcode.offset(14isize) as libc::c_int == '-' as i32
|
|
||||||
&& *setupcode.offset(19isize) as libc::c_int == '-' as i32
|
|
||||||
&& *setupcode.offset(24isize) as libc::c_int == '-' as i32
|
|
||||||
&& *setupcode.offset(29isize) as libc::c_int == '-' as i32
|
|
||||||
&& *setupcode.offset(34isize) as libc::c_int == '-' as i32
|
|
||||||
&& *setupcode.offset(39isize) as libc::c_int == '-' as i32)
|
|
||||||
as usize
|
|
||||||
);
|
|
||||||
setupfile = dc_render_setup_file(context, setupcode);
|
|
||||||
assert!(!setupfile.is_null());
|
|
||||||
let buf_2: *mut libc::c_char = dc_strdup(setupfile);
|
|
||||||
let mut headerline_1: *const libc::c_char = 0 as *const libc::c_char;
|
|
||||||
let mut setupcodebegin_1: *const libc::c_char = 0 as *const libc::c_char;
|
|
||||||
assert!(!dc_split_armored_data(
|
|
||||||
buf_2,
|
|
||||||
&mut headerline_1,
|
|
||||||
&mut setupcodebegin_1,
|
|
||||||
0 as *mut *const libc::c_char,
|
|
||||||
0 as *mut *const libc::c_char,
|
|
||||||
));
|
|
||||||
assert!(!headerline_1.is_null());
|
|
||||||
assert_eq!(
|
|
||||||
strcmp(
|
|
||||||
headerline_1,
|
|
||||||
b"-----BEGIN PGP MESSAGE-----\x00" as *const u8 as *const libc::c_char,
|
|
||||||
),
|
|
||||||
0
|
|
||||||
);
|
|
||||||
assert!(
|
|
||||||
!(!setupcodebegin_1.is_null()
|
|
||||||
&& strlen(setupcodebegin_1) == 2
|
|
||||||
&& strncmp(setupcodebegin_1, setupcode, 2) == 0i32)
|
|
||||||
);
|
|
||||||
free(buf_2 as *mut libc::c_void);
|
|
||||||
let payload: *mut libc::c_char;
|
let payload: *mut libc::c_char;
|
||||||
let mut headerline_2: *const libc::c_char = 0 as *const libc::c_char;
|
let mut headerline_2: *const libc::c_char = 0 as *const libc::c_char;
|
||||||
payload = dc_decrypt_setup_file(context, setupcode, setupfile);
|
payload = dc_decrypt_setup_file(context, setupcode_c.as_ptr(), setupfile_c.as_ptr());
|
||||||
assert!(payload.is_null());
|
assert!(payload.is_null());
|
||||||
assert!(!dc_split_armored_data(
|
assert!(!dc_split_armored_data(
|
||||||
payload,
|
payload,
|
||||||
@@ -583,7 +545,6 @@ unsafe fn stress_functions(context: &Context) {
|
|||||||
0
|
0
|
||||||
);
|
);
|
||||||
free(payload as *mut libc::c_void);
|
free(payload as *mut libc::c_void);
|
||||||
free(setupfile as *mut libc::c_void);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if 0 != dc_is_configured(context) {
|
if 0 != dc_is_configured(context) {
|
||||||
|
|||||||
Reference in New Issue
Block a user