diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 15b55a8d7..a1214bc58 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -1528,9 +1528,17 @@ pub unsafe extern "C" fn dc_imex( eprintln!("ignoring careless call to dc_imex()"); return; } + let what = match imex::ImexMode::from_i32(what as i32) { + Some(what) => what, + None => { + eprintln!("ignoring invalid argument {} to dc_imex", what); + return; + } + }; + let ffi_context = &*context; ffi_context - .with_inner(|ctx| dc_imex::dc_imex(ctx, what, as_opt_str(param1))) + .with_inner(|ctx| imex::imex(ctx, what, as_opt_str(param1))) .ok(); } @@ -1545,7 +1553,7 @@ pub unsafe extern "C" fn dc_imex_has_backup( } let ffi_context = &*context; ffi_context - .with_inner(|ctx| match dc_imex::dc_imex_has_backup(ctx, as_str(dir)) { + .with_inner(|ctx| match imex::has_backup(ctx, as_str(dir)) { Ok(res) => res.strdup(), Err(err) => { error!(ctx, "dc_imex_has_backup: {}", err); @@ -1563,7 +1571,7 @@ pub unsafe extern "C" fn dc_initiate_key_transfer(context: *mut dc_context_t) -> } let ffi_context = &*context; ffi_context - .with_inner(|ctx| match dc_imex::dc_initiate_key_transfer(ctx) { + .with_inner(|ctx| match imex::initiate_key_transfer(ctx) { Ok(res) => res.strdup(), Err(err) => { error!(ctx, "dc_initiate_key_transfer(): {}", err); @@ -1588,15 +1596,15 @@ pub unsafe extern "C" fn dc_continue_key_transfer( } let ffi_context = &*context; ffi_context - .with_inner(|ctx| { - match dc_imex::dc_continue_key_transfer(ctx, msg_id, as_str(setup_code)) { + .with_inner( + |ctx| match imex::continue_key_transfer(ctx, msg_id, as_str(setup_code)) { Ok(()) => 1, Err(err) => { error!(ctx, "dc_continue_key_transfer: {}", err); 0 } - } - }) + }, + ) .unwrap_or(0) } diff --git a/examples/repl/cmdline.rs b/examples/repl/cmdline.rs index 414b20acd..2c6a1c21f 100644 --- a/examples/repl/cmdline.rs +++ b/examples/repl/cmdline.rs @@ -8,10 +8,10 @@ use deltachat::configure::*; use deltachat::constants::*; use deltachat::contact::*; use deltachat::context::*; -use deltachat::dc_imex::*; use deltachat::dc_receive_imf::*; use deltachat::dc_tools::*; use deltachat::error::Error; +use deltachat::imex::*; use deltachat::job::*; use deltachat::location; use deltachat::lot::LotState; @@ -102,7 +102,7 @@ fn dc_poke_eml_file(context: &Context, filename: impl AsRef) -> Result<(), /// Import a file to the database. /// For testing, import a folder with eml-files, a single eml-file, e-mail plus public key and so on. -/// For normal importing, use dc_imex(). +/// For normal importing, use imex(). /// /// @private @memberof Context /// @param context The context as created by dc_context_new(). @@ -405,7 +405,7 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E =============================================" ), }, - "initiate-key-transfer" => match dc_initiate_key_transfer(context) { + "initiate-key-transfer" => match initiate_key_transfer(context) { Ok(setup_code) => println!( "Setup code for the transferred setup message: {}", setup_code, @@ -432,28 +432,28 @@ pub unsafe fn dc_cmdline(context: &Context, line: &str) -> Result<(), failure::E !arg1.is_empty() && !arg2.is_empty(), "Arguments expected" ); - dc_continue_key_transfer(context, arg1.parse()?, &arg2)?; + continue_key_transfer(context, arg1.parse()?, &arg2)?; } "has-backup" => { - dc_imex_has_backup(context, blobdir)?; + has_backup(context, blobdir)?; } "export-backup" => { - dc_imex(context, 11, Some(blobdir)); + imex(context, ImexMode::ExportBackup, Some(blobdir)); } "import-backup" => { ensure!(!arg1.is_empty(), "Argument missing."); - dc_imex(context, 12, Some(arg1)); + imex(context, ImexMode::ImportBackup, Some(arg1)); } "export-keys" => { - dc_imex(context, 1, Some(blobdir)); + imex(context, ImexMode::ExportSelfKeys, Some(blobdir)); } "import-keys" => { - dc_imex(context, 2, Some(blobdir)); + imex(context, ImexMode::ImportSelfKeys, Some(blobdir)); } "export-setup" => { - let setup_code = dc_create_setup_code(context); + let setup_code = create_setup_code(context); let file_name = blobdir.join("autocrypt-setup-message.html"); - let file_content = dc_render_setup_file(context, &setup_code)?; + let file_content = render_setup_file(context, &setup_code)?; std::fs::write(&file_name, file_content)?; println!( "Setup message written to: {}\nSetup code: {}", diff --git a/src/constants.rs b/src/constants.rs index f9771a8c0..af7daa023 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -64,15 +64,6 @@ pub const DC_GCL_ADD_SELF: usize = 0x02; pub(crate) const DC_FP_NO_AUTOCRYPT_HEADER: i32 = 2; pub(crate) const DC_FP_ADD_AUTOCRYPT_HEADER: i32 = 1; -/// param1 is a directory where the keys are written to -pub const DC_IMEX_EXPORT_SELF_KEYS: i32 = 1; -/// param1 is a directory where the keys are searched in and read from -pub const DC_IMEX_IMPORT_SELF_KEYS: i32 = 2; -/// param1 is a directory where the backup is written to -pub const DC_IMEX_EXPORT_BACKUP: i32 = 11; -/// param1 is the file with the backup to import -pub const DC_IMEX_IMPORT_BACKUP: i32 = 12; - /// virtual chat showing all messages belonging to chats flagged with chats.blocked=2 pub(crate) const DC_CHAT_ID_DEADDROP: u32 = 1; /// messages that should be deleted get this chat_id; the messages are deleted from the working thread later then. This is also needed as rfc724_mid should be preset as long as the message is not deleted on the server (otherwise it is downloaded again) diff --git a/src/e2ee.rs b/src/e2ee.rs index 2e5c25a15..c0a62e49f 100644 --- a/src/e2ee.rs +++ b/src/e2ee.rs @@ -470,7 +470,7 @@ fn load_or_generate_self_public_key(context: &Context, self_addr: impl AsRef { diff --git a/src/error.rs b/src/error.rs index cd8a3069a..0df1e6129 100644 --- a/src/error.rs +++ b/src/error.rs @@ -26,6 +26,10 @@ pub enum Error { CStringError(crate::dc_tools::CStringError), #[fail(display = "PGP: {:?}", _0)] Pgp(pgp::errors::Error), + #[fail(display = "Base64Decode: {:?}", _0)] + Base64Decode(base64::DecodeError), + #[fail(display = "{:?}", _0)] + FromUtf8(std::string::FromUtf8Error), } pub type Result = std::result::Result; @@ -36,6 +40,12 @@ impl From for Error { } } +impl From for Error { + fn from(err: base64::DecodeError) -> Error { + Error::Base64Decode(err) + } +} + impl From for Error { fn from(err: failure::Error) -> Error { Error::Failure(err) @@ -60,6 +70,12 @@ impl From for Error { } } +impl From for Error { + fn from(err: std::string::FromUtf8Error) -> Error { + Error::FromUtf8(err) + } +} + impl From for Error { fn from(err: image_meta::ImageError) -> Error { Error::Image(err) diff --git a/src/events.rs b/src/events.rs index 570dedf31..0477febce 100644 --- a/src/events.rs +++ b/src/events.rs @@ -167,7 +167,7 @@ pub enum Event { #[strum(props(id = "2041"))] ConfigureProgress(usize), - /// Inform about the import/export progress started by dc_imex(). + /// Inform about the import/export progress started by imex(). /// /// @param data1 (usize) 0=error, 1-999=progress in permille, 1000=success and done /// @param data2 0 @@ -175,8 +175,8 @@ pub enum Event { #[strum(props(id = "2051"))] ImexProgress(usize), - /// A file has been exported. A file has been written by dc_imex(). - /// This event may be sent multiple times by a single call to dc_imex(). + /// A file has been exported. A file has been written by imex(). + /// This event may be sent multiple times by a single call to imex(). /// /// A typical purpose for a handler of this event may be to make the file public to some system /// services. diff --git a/src/dc_imex.rs b/src/imex.rs similarity index 79% rename from src/dc_imex.rs rename to src/imex.rs index 77b55cfc3..9b62d05a7 100644 --- a/src/dc_imex.rs +++ b/src/imex.rs @@ -2,10 +2,7 @@ use std::ffi::CString; use std::path::Path; use std::ptr; -use libc::{free, strlen}; -use mmime::mailmime::content::*; -use mmime::mmapstring::*; -use mmime::other::*; +use num_traits::FromPrimitive; use rand::{thread_rng, Rng}; use crate::chat; @@ -25,12 +22,48 @@ use crate::pgp::*; use crate::sql::{self, Sql}; use crate::stock::StockMessage; -// import/export and tools -// param1 is a directory where the keys are written to -// param1 is a directory where the keys are searched in and read from -// param1 is a directory where the backup is written to -// param1 is the file with the backup to import -pub fn dc_imex(context: &Context, what: libc::c_int, param1: Option>) { +#[derive(Debug, Display, Copy, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)] +#[repr(i32)] +pub enum ImexMode { + /// Export all private keys and all public keys of the user to the + /// directory given as `param1`. The default key is written to the files `public-key-default.asc` + /// and `private-key-default.asc`, if there are more keys, they are written to files as + /// `public-key-.asc` and `private-key-.asc` + ExportSelfKeys = 1, + /// Import private keys found in the directory given as `param1`. + /// The last imported key is made the default keys unless its name contains the string `legacy`. + /// Public keys are not imported. + ImportSelfKeys = 2, + /// Export a backup to the directory given as `param1`. + /// The backup contains all contacts, chats, images and other data and device independent settings. + /// The backup does not contain device dependent settings as ringtones or LED notification settings. + /// The name of the backup is typically `delta-chat..bak`, if more than one backup is create on a day, + /// the format is `delta-chat.-.bak` + ExportBackup = 11, + /// `param1` is the file (not: directory) to import. The file is normally + /// created by DC_IMEX_EXPORT_BACKUP and detected by dc_imex_has_backup(). Importing a backup + /// is only possible as long as the context is not configured or used in another way. + ImportBackup = 12, +} + +/// Import/export things. +/// For this purpose, the function creates a job that is executed in the IMAP-thread then; +/// this requires to call dc_perform_imap_jobs() regularly. +/// +/// What to do is defined by the _what_ parameter. +/// +/// While dc_imex() returns immediately, the started job may take a while, +/// you can stop it using dc_stop_ongoing_process(). During execution of the job, +/// some events are sent out: +/// +/// - A number of #DC_EVENT_IMEX_PROGRESS events are sent and may be used to create +/// a progress bar or stuff like that. Moreover, you'll be informed when the imex-job is done. +/// +/// - For each file written on export, the function sends #DC_EVENT_IMEX_FILE_WRITTEN +/// +/// Only one import-/export-progress can run at the same time. +/// To cancel an import-/export-progress, use dc_stop_ongoing_process(). +pub fn imex(context: &Context, what: ImexMode, param1: Option>) { let mut param = Params::new(); param.set_int(Param::Cmd, what as i32); if let Some(param1) = param1 { @@ -42,7 +75,7 @@ pub fn dc_imex(context: &Context, what: libc::c_int, param1: Option) -> Result { +pub fn has_backup(context: &Context, dir_name: impl AsRef) -> Result { let dir_name = dir_name.as_ref(); let dir_iter = std::fs::read_dir(dir_name)?; let mut newest_backup_time = 0; @@ -75,10 +108,10 @@ pub fn dc_imex_has_backup(context: &Context, dir_name: impl AsRef) -> Resu } } -pub fn dc_initiate_key_transfer(context: &Context) -> Result { +pub fn initiate_key_transfer(context: &Context) -> Result { let mut msg: Message; ensure!(dc_alloc_ongoing(context), "could not allocate ongoing"); - let setup_code = dc_create_setup_code(context); + let setup_code = create_setup_code(context); /* this may require a keypair to be created. this may take a second ... */ if !context .running_state @@ -87,7 +120,7 @@ pub fn dc_initiate_key_transfer(context: &Context) -> Result { .unwrap() .shall_stop_ongoing { - if let Ok(ref setup_file_content) = dc_render_setup_file(context, &setup_code) { + if let Ok(ref setup_file_content) = render_setup_file(context, &setup_code) { /* encrypting may also take a while ... */ if !context .running_state @@ -153,7 +186,7 @@ pub fn dc_initiate_key_transfer(context: &Context) -> Result { /// Renders HTML body of a setup file message. /// /// The `passphrase` must be at least 2 characters long. -pub fn dc_render_setup_file(context: &Context, passphrase: &str) -> Result { +pub fn render_setup_file(context: &Context, passphrase: &str) -> Result { ensure!( passphrase.len() >= 2, "Passphrase must be at least 2 chars long." @@ -203,7 +236,7 @@ pub fn dc_render_setup_file(context: &Context, passphrase: &str) -> Result String { +pub fn create_setup_code(_context: &Context) -> String { let mut random_val: u16; let mut rng = thread_rng(); let mut ret = String::new(); @@ -211,22 +244,22 @@ pub fn dc_create_setup_code(_context: &Context) -> String { for i in 0..9 { loop { random_val = rng.gen(); - if !(random_val as libc::c_int > 60000) { + if !(random_val as usize > 60000) { break; } } - random_val = (random_val as libc::c_int % 10000) as u16; + random_val = (random_val as usize % 10000) as u16; ret += &format!( "{}{:04}", if 0 != i { "-" } else { "" }, - random_val as libc::c_int, + random_val as usize ); } ret } -pub fn dc_continue_key_transfer(context: &Context, msg_id: u32, setup_code: &str) -> Result<()> { +pub fn continue_key_transfer(context: &Context, msg_id: u32, setup_code: &str) -> Result<()> { ensure!(msg_id > DC_MSG_ID_LAST_SPECIAL, "wrong id"); let msg = Message::load_from_db(context, msg_id); @@ -240,17 +273,14 @@ pub fn dc_continue_key_transfer(context: &Context, msg_id: u32, setup_code: &str ); if let Some(filename) = msg.get_file(context) { - if let Ok(buf) = dc_read_file(context, filename) { - let norm_sc = CString::yolo(dc_normalize_setup_code(setup_code)); - unsafe { - if let Ok(armored_key) = - dc_decrypt_setup_file(context, norm_sc.as_ptr(), buf.as_ptr().cast()) - { - set_self_key(context, &armored_key, true, true)?; - } else { - bail!("Bad setup code.") - } + if let Ok(ref mut buf) = dc_read_file(context, filename) { + let sc = normalize_setup_code(setup_code); + if let Ok(armored_key) = decrypt_setup_file(context, sc, buf) { + set_self_key(context, &armored_key, true, true)?; + } else { + bail!("Bad setup code.") } + Ok(()) } else { bail!("Cannot read Autocrypt Setup Message file."); @@ -320,7 +350,7 @@ fn set_self_key( &public_key, &private_key, self_addr.unwrap(), - set_default as libc::c_int, + set_default, &context.sql, ) { bail!("Cannot save keypair, internal key-state possibly corrupted now!"); @@ -328,65 +358,56 @@ fn set_self_key( Ok(()) } -pub unsafe fn dc_decrypt_setup_file( - context: &Context, - passphrase: *const libc::c_char, - filecontent: *const libc::c_char, +fn decrypt_setup_file( + _context: &Context, + passphrase: impl AsRef, + filecontent: &mut [u8], ) -> Result { - let fc_buf: *mut libc::c_char; let mut fc_headerline = String::default(); let mut fc_base64: *const libc::c_char = ptr::null(); - let mut binary: *mut libc::c_char = ptr::null_mut(); - let mut binary_bytes: libc::size_t = 0; - let mut indx: libc::size_t = 0; - let mut payload: Result = Err(format_err!("Failed to decrypt")); + let split_result = unsafe { + dc_split_armored_data( + filecontent.as_mut_ptr().cast(), + &mut fc_headerline, + ptr::null_mut(), + ptr::null_mut(), + &mut fc_base64, + ) + }; - fc_buf = dc_strdup(filecontent); - if dc_split_armored_data( - fc_buf, - &mut fc_headerline, - ptr::null_mut(), - ptr::null_mut(), - &mut fc_base64, - ) && fc_headerline == "-----BEGIN PGP MESSAGE-----" - && !fc_base64.is_null() - { - /* convert base64 to binary */ - /*must be freed using mmap_string_unref()*/ - if !(mailmime_base64_body_parse( - fc_base64, - strlen(fc_base64), - &mut indx, - &mut binary, - &mut binary_bytes, - ) != MAILIMF_NO_ERROR as libc::c_int - || binary.is_null() - || binary_bytes == 0) - { - /* decrypt symmetrically */ - match dc_pgp_symm_decrypt( - as_str(passphrase), - std::slice::from_raw_parts(binary as *const u8, binary_bytes), - ) { - Ok(plain) => payload = Ok(String::from_utf8(plain).unwrap()), - Err(err) => { - error!(context, "Failed to decrypt message: {:?}", err); - payload = Err(err); - } - } - } + if !split_result || fc_headerline != "-----BEGIN PGP MESSAGE-----" || fc_base64.is_null() { + bail!("Invalid armored data"); } - free(fc_buf as *mut libc::c_void); - if !binary.is_null() { - mmap_string_unref(binary); - } + // convert base64 to binary + let base64_encoded = + unsafe { std::slice::from_raw_parts(fc_base64 as *const u8, libc::strlen(fc_base64)) }; - payload + let data = base64_decode(&base64_encoded)?; + + // decrypt symmetrically + let payload = dc_pgp_symm_decrypt(passphrase.as_ref(), &data)?; + let payload_str = String::from_utf8(payload)?; + + Ok(payload_str) } -pub fn dc_normalize_setup_code(s: &str) -> String { +/// Decode the base64 encoded slice. Handles line breaks. +fn base64_decode(input: &[u8]) -> Result> { + use std::io::Read; + let c = std::io::Cursor::new(input); + let lr = pgp::line_reader::LineReader::new(c); + let br = pgp::base64_reader::Base64Reader::new(lr); + let mut reader = pgp::base64_decoder::Base64Decoder::new(br); + + let mut data = Vec::new(); + reader.read_to_end(&mut data)?; + + Ok(data) +} + +pub fn normalize_setup_code(s: &str) -> String { let mut out = String::new(); for c in s.chars() { if c >= '0' && c <= '9' { @@ -400,9 +421,9 @@ pub fn dc_normalize_setup_code(s: &str) -> String { } #[allow(non_snake_case)] -pub fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) -> Result<()> { +pub fn job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) -> Result<()> { ensure!(dc_alloc_ongoing(context), "could not allocate ongoing"); - let what = job.param.get_int(Param::Cmd).unwrap_or_default(); + let what: Option = job.param.get_int(Param::Cmd).and_then(ImexMode::from_i32); let param = job.param.get(Param::Arg).unwrap_or_default(); ensure!(!param.is_empty(), "No Import/export dir/file given."); @@ -410,8 +431,8 @@ pub fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) -> Result<()> { context.call_cb(Event::ImexProgress(10)); ensure!(context.sql.is_open(), "Database not opened."); - if what == DC_IMEX_EXPORT_BACKUP || what == DC_IMEX_EXPORT_SELF_KEYS { - /* before we export anything, make sure the private key exists */ + if what == Some(ImexMode::ExportBackup) || what == Some(ImexMode::ExportSelfKeys) { + // before we export anything, make sure the private key exists if e2ee::ensure_secret_key_exists(context).is_err() { dc_free_ongoing(context); bail!("Cannot create private key or private key not available."); @@ -421,12 +442,12 @@ pub fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) -> Result<()> { } let path = Path::new(param); let success = match what { - DC_IMEX_EXPORT_SELF_KEYS => export_self_keys(context, path), - DC_IMEX_IMPORT_SELF_KEYS => import_self_keys(context, path), - DC_IMEX_EXPORT_BACKUP => unsafe { export_backup(context, path) }, - DC_IMEX_IMPORT_BACKUP => import_backup(context, path), - _ => { - bail!("unknown IMEX type: {}", what); + Some(ImexMode::ExportSelfKeys) => export_self_keys(context, path), + Some(ImexMode::ImportSelfKeys) => import_self_keys(context, path), + Some(ImexMode::ExportBackup) => export_backup(context, path), + Some(ImexMode::ImportBackup) => import_backup(context, path), + None => { + bail!("unknown IMEX type"); } }; dc_free_ongoing(context); @@ -443,11 +464,7 @@ pub fn dc_job_do_DC_JOB_IMEX_IMAP(context: &Context, job: &Job) -> Result<()> { } } -/******************************************************************************* - * Import backup - ******************************************************************************/ - -#[allow(non_snake_case)] +/// Import Backup fn import_backup(context: &Context, backup_to_import: impl AsRef) -> Result<()> { info!( context, @@ -523,13 +540,13 @@ fn import_backup(context: &Context, backup_to_import: impl AsRef) -> Resul continue; } - let pathNfilename = context.get_blobdir().join(file_name); - if dc_write_file(context, &pathNfilename, &file_blob) { + let path_filename = context.get_blobdir().join(file_name); + if dc_write_file(context, &path_filename, &file_blob) { continue; } bail!( "Storage full? Cannot write file {} with {} bytes.", - pathNfilename.display(), + path_filename.display(), file_blob.len(), ); } @@ -550,8 +567,7 @@ fn import_backup(context: &Context, backup_to_import: impl AsRef) -> Resul ******************************************************************************/ /* the FILE_PROGRESS macro calls the callback with the permille of files processed. The macro avoids weird values of 0% or 100% while still working. */ -#[allow(non_snake_case)] -unsafe fn export_backup(context: &Context, dir: impl AsRef) -> Result<()> { +fn export_backup(context: &Context, dir: impl AsRef) -> Result<()> { let mut ok_to_continue = true; let mut success = false; @@ -650,9 +666,9 @@ unsafe fn export_backup(context: &Context, dir: impl AsRef) -> Result<()> continue; } else { info!(context, "EXPORTing filename={}", name); - let curr_pathNfilename = context.get_blobdir().join(entry.file_name()); + let curr_path_filename = context.get_blobdir().join(entry.file_name()); if let Ok(buf) = - dc_read_file(context, &curr_pathNfilename) + dc_read_file(context, &curr_path_filename) { if buf.is_empty() { continue; @@ -661,7 +677,7 @@ unsafe fn export_backup(context: &Context, dir: impl AsRef) -> Result<()> error!( context, "Disk full? Cannot add file \"{}\" to backup.", - curr_pathNfilename.display(), + curr_path_filename.display(), ); /* this is not recoverable! writing to the sqlite database should work! */ ok_to_continue = false; @@ -773,7 +789,7 @@ fn import_self_keys(context: &Context, dir: impl AsRef) -> Result<()> { ptr::null_mut(), ptr::null_mut(), ); - free(buf2 as *mut libc::c_void); + libc::free(buf2 as *mut libc::c_void); } if split_res && buf2_headerline.contains("-----BEGIN PGP PUBLIC KEY BLOCK-----") @@ -884,7 +900,7 @@ mod tests { let t = test_context(Some(Box::new(logging_cb))); configure_alice_keypair(&t.ctx); - let msg = dc_render_setup_file(&t.ctx, "hello").unwrap(); + let msg = render_setup_file(&t.ctx, "hello").unwrap(); println!("{}", &msg); // Check some substrings, indicating things got substituted. // In particular note the mixing of `\r\n` and `\n` depending @@ -910,10 +926,10 @@ mod tests { } #[test] - fn test_render_setup_file_newline_replace() { + fn otest_render_setup_file_newline_replace() { let t = test_context(Some(Box::new(ac_setup_msg_cb))); configure_alice_keypair(&t.ctx); - let msg = dc_render_setup_file(&t.ctx, "pw").unwrap(); + let msg = render_setup_file(&t.ctx, "pw").unwrap(); println!("{}", &msg); assert!(msg.contains("

hello
there

")); } @@ -921,7 +937,7 @@ mod tests { #[test] fn test_create_setup_code() { let t = dummy_context(); - let setupcode = dc_create_setup_code(&t.ctx); + let setupcode = create_setup_code(&t.ctx); assert_eq!(setupcode.len(), 44); assert_eq!(setupcode.chars().nth(4).unwrap(), '-'); assert_eq!(setupcode.chars().nth(9).unwrap(), '-'); @@ -949,12 +965,65 @@ mod tests { #[test] fn test_normalize_setup_code() { - let norm = dc_normalize_setup_code("123422343234423452346234723482349234"); + let norm = normalize_setup_code("123422343234423452346234723482349234"); assert_eq!(norm, "1234-2234-3234-4234-5234-6234-7234-8234-9234"); - let norm = dc_normalize_setup_code( - "\t1 2 3422343234- foo bar-- 423-45 2 34 6234723482349234 ", - ); + let norm = + normalize_setup_code("\t1 2 3422343234- foo bar-- 423-45 2 34 6234723482349234 "); assert_eq!(norm, "1234-2234-3234-4234-5234-6234-7234-8234-9234"); } + + /* S_EM_SETUPFILE is a AES-256 symm. encrypted setup message created by Enigmail + with an "encrypted session key", see RFC 4880. The code is in S_EM_SETUPCODE */ + const S_EM_SETUPCODE: &str = "1742-0185-6197-1303-7016-8412-3581-4441-0597"; + const S_EM_SETUPFILE: &str = include_str!("../test-data/message/stress.txt"); + + #[test] + fn test_split_and_decrypt() { + let ctx = dummy_context(); + let context = &ctx.ctx; + + let mut headerline = String::default(); + let mut setupcodebegin = ptr::null(); + let mut preferencrypt = ptr::null(); + + let mut buf_1 = S_EM_SETUPFILE.to_string(); + + unsafe { + assert!(dc_split_armored_data( + buf_1.as_mut_ptr().cast(), + &mut headerline, + &mut setupcodebegin, + &mut preferencrypt, + ptr::null_mut(), + )); + } + assert_eq!(headerline, "-----BEGIN PGP MESSAGE-----"); + assert!(!setupcodebegin.is_null()); + + // TODO: verify that this is the right check + assert!(S_EM_SETUPCODE.starts_with(as_str(setupcodebegin))); + + assert!(preferencrypt.is_null()); + + let mut setup_file = S_EM_SETUPFILE.to_string(); + let mut decrypted = unsafe { + decrypt_setup_file(context, S_EM_SETUPCODE, setup_file.as_bytes_mut()).unwrap() + }; + + unsafe { + assert!(dc_split_armored_data( + decrypted.as_mut_ptr().cast(), + &mut headerline, + &mut setupcodebegin, + &mut preferencrypt, + ptr::null_mut(), + )); + } + + assert_eq!(headerline, "-----BEGIN PGP PRIVATE KEY BLOCK-----"); + assert!(setupcodebegin.is_null()); + assert!(!preferencrypt.is_null()); + assert_eq!(as_str(preferencrypt), "mutual",); + } } diff --git a/src/job.rs b/src/job.rs index 57e5c1fd0..2e2df3564 100644 --- a/src/job.rs +++ b/src/job.rs @@ -7,10 +7,10 @@ use crate::chat; use crate::configure::*; use crate::constants::*; use crate::context::Context; -use crate::dc_imex::*; use crate::dc_tools::*; use crate::events::Event; use crate::imap::*; +use crate::imex::*; use crate::location; use crate::login_param::LoginParam; use crate::message::{self, Message, MessageState}; @@ -824,7 +824,7 @@ fn job_perform(context: &Context, thread: Thread, probe_network: bool) { Action::MoveMsg => job.do_DC_JOB_MOVE_MSG(context), Action::SendMdn => job.do_DC_JOB_SEND(context), Action::ConfigureImap => unsafe { dc_job_do_DC_JOB_CONFIGURE_IMAP(context) }, - Action::ImexImap => match dc_job_do_DC_JOB_IMEX_IMAP(context, &job) { + Action::ImexImap => match job_do_DC_JOB_IMEX_IMAP(context, &job) { Ok(()) => {} Err(err) => { error!(context, "{}", err); diff --git a/src/key.rs b/src/key.rs index c7193cbd7..3fff7dc46 100644 --- a/src/key.rs +++ b/src/key.rs @@ -2,7 +2,6 @@ use std::collections::BTreeMap; use std::io::Cursor; use std::path::Path; -use libc; use pgp::composed::{Deserializable, SignedPublicKey, SignedSecretKey}; use pgp::ser::Serialize; use pgp::types::{KeyTrait, SecretKeyTrait}; @@ -254,14 +253,14 @@ pub fn dc_key_save_self_keypair( public_key: &Key, private_key: &Key, addr: impl AsRef, - is_default: libc::c_int, + is_default: bool, sql: &Sql, ) -> bool { sql::execute( context, sql, "INSERT INTO keypairs (addr, is_default, public_key, private_key, created) VALUES (?,?,?,?,?);", - params![addr.as_ref(), is_default, public_key.to_bytes(), private_key.to_bytes(), time()], + params![addr.as_ref(), is_default as i32, public_key.to_bytes(), private_key.to_bytes(), time()], ).is_ok() } diff --git a/src/lib.rs b/src/lib.rs index 0c443a4eb..07f98144c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,36 +39,36 @@ pub mod contact; pub mod context; mod e2ee; mod imap; +pub mod imex; pub mod job; mod job_thread; pub mod key; pub mod keyring; pub mod location; +mod login_param; pub mod lot; pub mod message; +mod mimefactory; pub mod oauth2; mod param; pub mod peerstate; pub mod pgp; pub mod qr; +pub mod securejoin; mod smtp; pub mod sql; mod stock; +mod token; +#[macro_use] +mod wrapmime; pub mod dc_array; mod dc_dehtml; -pub mod dc_imex; pub mod dc_mimeparser; pub mod dc_receive_imf; mod dc_simplify; mod dc_strencode; pub mod dc_tools; -mod login_param; -mod mimefactory; -pub mod securejoin; -mod token; -#[macro_use] -mod wrapmime; #[cfg(test)] mod test_utils; diff --git a/src/test_utils.rs b/src/test_utils.rs index 9e2b32be4..0be80ce2d 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -76,7 +76,7 @@ pub fn configure_alice_keypair(ctx: &Context) -> String { KeyType::Private, ) .unwrap(); - let saved = key::dc_key_save_self_keypair(&ctx, &public, &private, &addr, 1, &ctx.sql); + let saved = key::dc_key_save_self_keypair(&ctx, &public, &private, &addr, true, &ctx.sql); assert_eq!(saved, true, "Failed to save Alice's key"); addr } diff --git a/test-data/message/stress.txt b/test-data/message/stress.txt new file mode 100644 index 000000000..aac9b4eff --- /dev/null +++ b/test-data/message/stress.txt @@ -0,0 +1,125 @@ +-----BEGIN PGP MESSAGE----- +Passphrase-Format: numeric9x4 +Passphrase-Begin: 17 + +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 +mngm1QCMMw2v/j8= +=9sJE +-----END PGP MESSAGE----- diff --git a/tests/stress.rs b/tests/stress.rs index 78c2da1b2..0c303179f 100644 --- a/tests/stress.rs +++ b/tests/stress.rs @@ -7,24 +7,16 @@ use deltachat::chat::{self, Chat}; use deltachat::config; use deltachat::contact::*; use deltachat::context::*; -use deltachat::dc_imex::*; use deltachat::dc_tools::*; use deltachat::keyring::*; use deltachat::oauth2::*; use deltachat::pgp::*; use deltachat::Event; -use libc::{free, strcmp, strdup, strlen, strncmp}; +use libc::{free, strcmp, strdup}; use tempfile::{tempdir, TempDir}; /* some data used for testing ******************************************************************************/ -/* S_EM_SETUPFILE is a AES-256 symm. encrypted setup message created by Enigmail -with an "encrypted session key", see RFC 4880. The code is in S_EM_SETUPCODE */ -static mut S_EM_SETUPCODE: *const libc::c_char = - b"1742-0185-6197-1303-7016-8412-3581-4441-0597\x00" as *const u8 as *const libc::c_char; -static mut S_EM_SETUPFILE: *const libc::c_char = - b"-----BEGIN PGP MESSAGE-----\nPassphrase-Format: numeric9x4\nPassphrase-Begin: 17\n\n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\nmngm1QCMMw2v/j8=\n=9sJE\n-----END PGP MESSAGE-----\n\x00" - as *const u8 as *const libc::c_char; unsafe fn stress_functions(context: &Context) { let res = context.get_config(config::Config::SysConfigKeys).unwrap(); @@ -187,50 +179,6 @@ unsafe fn stress_functions(context: &Context) { free(buf_0 as *mut libc::c_void); - let mut buf_1: *mut libc::c_char; - let mut headerline_0 = String::default(); - let mut setupcodebegin_0: *const libc::c_char = ptr::null(); - let mut preferencrypt_0: *const libc::c_char = ptr::null(); - buf_1 = strdup(S_EM_SETUPFILE); - assert!(dc_split_armored_data( - buf_1, - &mut headerline_0, - &mut setupcodebegin_0, - &mut preferencrypt_0, - ptr::null_mut(), - )); - assert_eq!(headerline_0, "-----BEGIN PGP MESSAGE-----"); - assert!(!setupcodebegin_0.is_null()); - assert!(strlen(setupcodebegin_0) < strlen(S_EM_SETUPCODE)); - assert_eq!( - strncmp(setupcodebegin_0, S_EM_SETUPCODE, strlen(setupcodebegin_0)), - 0 - ); - - assert!(preferencrypt_0.is_null()); - free(buf_1 as *mut libc::c_void); - let decrypted = dc_decrypt_setup_file(context, S_EM_SETUPCODE, S_EM_SETUPFILE).unwrap(); - buf_1 = decrypted.strdup(); - assert!(!buf_1.is_null()); - assert!(dc_split_armored_data( - buf_1, - &mut headerline_0, - &mut setupcodebegin_0, - &mut preferencrypt_0, - ptr::null_mut(), - )); - assert_eq!(headerline_0, "-----BEGIN PGP PRIVATE KEY BLOCK-----"); - assert!(setupcodebegin_0.is_null()); - assert!(!preferencrypt_0.is_null()); - assert_eq!( - strcmp( - preferencrypt_0, - b"mutual\x00" as *const u8 as *const libc::c_char, - ), - 0 - ); - free(buf_1 as *mut libc::c_void); - // Cant check, no configured context // assert!(dc_is_configured(context) != 0, "Missing configured context");