From 12b2a706f062fc25397efd529387877a04592421 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 5 Jul 2019 01:02:22 +0200 Subject: [PATCH 01/12] address on flub comment, start on autocryt transfer test --- python/src/deltachat/account.py | 9 +++++++-- python/src/deltachat/message.py | 5 +++++ python/tests/conftest.py | 11 +++++++++++ python/tests/test_account.py | 12 ++++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/python/src/deltachat/account.py b/python/src/deltachat/account.py index a5404f04e..bec760da2 100644 --- a/python/src/deltachat/account.py +++ b/python/src/deltachat/account.py @@ -305,6 +305,12 @@ class Account(object): lib.dc_perform_imap_jobs(self._dc_context) self._imex_completed.wait() + def initiate_key_transfer(self): + """initiate Autocrypt key transfer by sending a self-sent message. + + """ + return from_dc_charpointer(lib.dc_initiate_key_transfer(self._dc_context)) + def start_threads(self): """ start IMAP/SMTP threads (and configure account if it hasn't happened). @@ -317,6 +323,7 @@ class Account(object): def stop_threads(self): """ stop IMAP/SMTP threads. """ + lib.dc_stop_ongoing_process(self._dc_context) self._threads.stop(wait=True) def _process_event(self, ctx, evt_name, data1, data2): @@ -362,14 +369,12 @@ class IOThreads: thread.join() def imap_thread_run(self): - print("starting imap thread") while not self._thread_quitflag: lib.dc_perform_imap_jobs(self._dc_context) lib.dc_perform_imap_fetch(self._dc_context) lib.dc_perform_imap_idle(self._dc_context) def smtp_thread_run(self): - print("starting smtp thread") while not self._thread_quitflag: lib.dc_perform_smtp_jobs(self._dc_context) lib.dc_perform_smtp_idle(self._dc_context) diff --git a/python/src/deltachat/message.py b/python/src/deltachat/message.py index 4719e0b45..0b4029af6 100644 --- a/python/src/deltachat/message.py +++ b/python/src/deltachat/message.py @@ -93,6 +93,10 @@ class Message(object): """ return MessageType(lib.dc_msg_get_viewtype(self._dc_msg)) + def is_setup_message(self): + """ return True if this message is a setup message. """ + return lib.dc_is_setupmessage(self._dc_msg) + @props.with_doc def time_sent(self): """UTC time when the message was sent. @@ -198,6 +202,7 @@ class MessageType(object): return self._type == const.DC_MSG_FILE + @attr.s class MessageState(object): """ Current Message In/Out state, updated on each call of is_* methods. diff --git a/python/tests/conftest.py b/python/tests/conftest.py index ff1d4425c..d005fc408 100644 --- a/python/tests/conftest.py +++ b/python/tests/conftest.py @@ -106,6 +106,17 @@ def acfactory(pytestconfig, tmpdir, request): self._finalizers.append(ac.stop_threads) return ac + def clone_online_account(self, account): + self.live_count += 1 + tmpdb = tmpdir.join("livedb%d" % self.live_count) + ac = Account(tmpdb.strpath, logid="ac{}".format(self.live_count)) + ac._evlogger.init_time = self.init_time + ac._evlogger.set_timeout(30) + ac.configure(addr=account.get_config("addr"), mail_pw=account.get_config("mail_pw")) + ac.start_threads() + self._finalizers.append(ac.stop_threads) + return ac + return AccountMaker() diff --git a/python/tests/test_account.py b/python/tests/test_account.py index b1e4aa00b..e78b8fe0b 100644 --- a/python/tests/test_account.py +++ b/python/tests/test_account.py @@ -441,3 +441,15 @@ class TestOnlineAccount: messages = chat2.get_messages() assert len(messages) == 1 assert messages[0].text == "msg1" + + def test_ac_setup(self, acfactory): + ac1 = acfactory.get_online_configuring_account() + wait_configuration_progress(ac1, 1000) + setup_code = ac1.initiate_key_transfer() + ac2 = acfactory.clone_online_account(ac1) + wait_configuration_progress(ac2, 1000) + ac2._timeout = 10 + ev = ac2._evlogger.get_matching("DC_EVENT_INCOMING_MSG|DC_EVENT_MSGS_CHANGED") + msg = ac2.get_message_by_id(ev[2]) + assert msg.is_setup_message() + assert 0, setup_code From 699b2d48e6ca74f176d632fb8023ee6de90f027d Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 5 Jul 2019 12:46:14 +0200 Subject: [PATCH 02/12] add a failing test for Autocrypt Key Transfer failing to extract a private key from an incoming ASM message --- python/src/deltachat/account.py | 13 ++++++++++--- python/src/deltachat/message.py | 6 +++++- python/tests/test_account.py | 21 ++++++++++++++++----- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/python/src/deltachat/account.py b/python/src/deltachat/account.py index bec760da2..75e5f414b 100644 --- a/python/src/deltachat/account.py +++ b/python/src/deltachat/account.py @@ -306,10 +306,17 @@ class Account(object): self._imex_completed.wait() def initiate_key_transfer(self): - """initiate Autocrypt key transfer by sending a self-sent message. - + """return setup code after a Autocrypt setup message + has been successfully sent to our own e-mail address ("self-sent message"). + If sending out was unsuccessful, a RuntimeError is raised. """ - return from_dc_charpointer(lib.dc_initiate_key_transfer(self._dc_context)) + self.check_is_configured() + if not self._threads.is_started(): + raise RuntimeError("threads not running, can not send out") + res = lib.dc_initiate_key_transfer(self._dc_context) + if res == ffi.NULL: + raise RuntimeError("could not send out autocrypt setup message") + return from_dc_charpointer(res) def start_threads(self): """ start IMAP/SMTP threads (and configure account if it hasn't happened). diff --git a/python/src/deltachat/message.py b/python/src/deltachat/message.py index 0b4029af6..aa4d49596 100644 --- a/python/src/deltachat/message.py +++ b/python/src/deltachat/message.py @@ -95,7 +95,11 @@ class Message(object): def is_setup_message(self): """ return True if this message is a setup message. """ - return lib.dc_is_setupmessage(self._dc_msg) + return lib.dc_msg_is_setupmessage(self._dc_msg) + + def continue_key_transfer(self, setup_code): + """ extract key and use it as primary key for this account. """ + lib.dc_continue_key_transfer(self._dc_context, self.id, as_dc_charpointer(setup_code)) @props.with_doc def time_sent(self): diff --git a/python/tests/test_account.py b/python/tests/test_account.py index e78b8fe0b..be8735db2 100644 --- a/python/tests/test_account.py +++ b/python/tests/test_account.py @@ -252,6 +252,11 @@ class TestOfflineAccount: assert messages[0].text == "msg1" assert os.path.exists(messages[1].filename) + def test_ac_setup_message_fails(self, acfactory): + ac1 = acfactory.get_configured_offline_account() + with pytest.raises(RuntimeError): + ac1.initiate_key_transfer() + class TestOnlineAccount: def test_one_account_init(self, acfactory): @@ -442,14 +447,20 @@ class TestOnlineAccount: assert len(messages) == 1 assert messages[0].text == "msg1" - def test_ac_setup(self, acfactory): + def test_ac_setup_message(self, acfactory): + # note that the receiving account needs to be configured and running + # before ther setup message is send. DC does not read old messages + # as of Jul2019 ac1 = acfactory.get_online_configuring_account() - wait_configuration_progress(ac1, 1000) - setup_code = ac1.initiate_key_transfer() ac2 = acfactory.clone_online_account(ac1) wait_configuration_progress(ac2, 1000) - ac2._timeout = 10 + wait_configuration_progress(ac1, 1000) + assert ac1.get_info()["fingerprint"] != ac2.get_info()["fingerprint"] + setup_code = ac1.initiate_key_transfer() + ac2._evlogger.set_timeout(10) ev = ac2._evlogger.get_matching("DC_EVENT_INCOMING_MSG|DC_EVENT_MSGS_CHANGED") msg = ac2.get_message_by_id(ev[2]) assert msg.is_setup_message() - assert 0, setup_code + print("*************** Incoming ASM File at: ", msg.filename) + msg.continue_key_transfer(setup_code) + assert ac1.get_info()["fingerprint"] == ac2.get_info()["fingerprint"] From dfa2fcda732001979e9e25937adf12be26e13a41 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 5 Jul 2019 13:04:26 +0200 Subject: [PATCH 03/12] use safe logging, and add some info on the processed key (this is WIP and needs to be removed) --- python/tests/test_account.py | 1 + src/dc_imex.rs | 35 ++++++++++++++++++----------------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/python/tests/test_account.py b/python/tests/test_account.py index be8735db2..b24ebb367 100644 --- a/python/tests/test_account.py +++ b/python/tests/test_account.py @@ -462,5 +462,6 @@ class TestOnlineAccount: msg = ac2.get_message_by_id(ev[2]) assert msg.is_setup_message() print("*************** Incoming ASM File at: ", msg.filename) + print("*************** Setup Code: ", setup_code) msg.continue_key_transfer(setup_code) assert ac1.get_info()["fingerprint"] == ac2.get_info()["fingerprint"] diff --git a/src/dc_imex.rs b/src/dc_imex.rs index 22b81c891..5ae71c5c0 100644 --- a/src/dc_imex.rs +++ b/src/dc_imex.rs @@ -362,10 +362,10 @@ pub unsafe fn dc_continue_key_transfer( } || *filename.offset(0isize) as libc::c_int == 0i32 { - dc_log_error( + error!( context, - 0i32, - b"Message is no Autocrypt Setup Message.\x00" as *const u8 as *const libc::c_char, + 0, + "Message is no Autocrypt Setup Message.", ); } else if 0 == dc_read_file( @@ -377,28 +377,26 @@ pub unsafe fn dc_continue_key_transfer( || filecontent.is_null() || filebytes <= 0 { - dc_log_error( + error!( context, - 0i32, - b"Cannot read Autocrypt Setup Message file.\x00" as *const u8 - as *const libc::c_char, + 0, + "Cannot read Autocrypt Setup Message file.", ); } else { norm_sc = dc_normalize_setup_code(context, setup_code); if norm_sc.is_null() { - dc_log_warning( + warn!( context, - 0i32, - b"Cannot normalize Setup Code.\x00" as *const u8 as *const libc::c_char, + 0, + "Cannot normalize Setup Code.", ); } else { armored_key = dc_decrypt_setup_file(context, norm_sc, filecontent); if armored_key.is_null() { - dc_log_warning( + warn!( context, - 0i32, - b"Cannot decrypt Autocrypt Setup Message.\x00" as *const u8 - as *const libc::c_char, + 0, + "Cannot decrypt Autocrypt Setup Message.", ); } else if !(0 == set_self_key(context, armored_key, 1i32)) { /*set default*/ @@ -433,6 +431,8 @@ unsafe fn set_self_key( let mut buf_base64: *const libc::c_char = 0 as *const libc::c_char; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut self_addr: *mut libc::c_char = 0 as *mut libc::c_char; + info!(context, 0, "armored key: {}", as_str(armored)); + buf = dc_strdup(armored); if 0 == dc_split_armored_data( buf, @@ -446,10 +446,10 @@ unsafe fn set_self_key( ) != 0i32 || buf_base64.is_null() { - dc_log_warning( + warn!( context, - 0i32, - b"File does not contain a private key.\x00" as *const u8 as *const libc::c_char, + 0, + "File does not contain a private key.", ); } else { if let Some((private_key, public_key)) = Key::from_base64( @@ -568,6 +568,7 @@ pub unsafe fn dc_decrypt_setup_file( let mut indx: size_t = 0i32 as size_t; let mut payload: *mut libc::c_char = 0 as *mut libc::c_char; + info!(_context, 0, "trying to decrypt ASM file"); fc_buf = dc_strdup(filecontent); if !(0 == dc_split_armored_data( From 35248296afd564a3dcaa47936be883a21217329b Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 5 Jul 2019 13:08:08 +0200 Subject: [PATCH 04/12] some refinements, bump versions already --- Cargo.toml | 2 +- deltachat-ffi/Cargo.toml | 2 +- python/install_py_bindings.sh | 2 +- python/src/deltachat/__init__.py | 2 +- python/src/deltachat/message.py | 1 - src/constants.rs | 2 +- src/dc_imex.rs | 41 +++++--------------- src/key.rs | 66 +++++++++++++++++++++++++++++++- 8 files changed, 80 insertions(+), 38 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ef6323620..a077c9de4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deltachat" -version = "1.0.0-alpha.2" +version = "1.0.0-alpha.3" authors = ["dignifiedquire "] edition = "2018" license = "MPL" diff --git a/deltachat-ffi/Cargo.toml b/deltachat-ffi/Cargo.toml index 5df91a47b..2094c0d8b 100644 --- a/deltachat-ffi/Cargo.toml +++ b/deltachat-ffi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deltachat_ffi" -version = "1.0.0-alpha.1" +version = "1.0.0-alpha.3" description = "Deltachat FFI" authors = ["dignifiedquire "] edition = "2018" diff --git a/python/install_py_bindings.sh b/python/install_py_bindings.sh index 1b5c71cf6..718229252 100755 --- a/python/install_py_bindings.sh +++ b/python/install_py_bindings.sh @@ -3,5 +3,5 @@ set -ex cargo build -p deltachat_ffi --release -rm -rf build/ +rm -rf build/ src/deltachat/*.so DCC_RS_DEV=`pwd`/.. pip install -e . diff --git a/python/src/deltachat/__init__.py b/python/src/deltachat/__init__.py index 7ad9d6052..624b58c69 100644 --- a/python/src/deltachat/__init__.py +++ b/python/src/deltachat/__init__.py @@ -2,7 +2,7 @@ from deltachat import capi, const from deltachat.capi import ffi from deltachat.account import Account # noqa -__version__ = "0.10.0.dev3" +__version__ = "0.10.0.dev4" _DC_CALLBACK_MAP = {} diff --git a/python/src/deltachat/message.py b/python/src/deltachat/message.py index aa4d49596..87d4e9445 100644 --- a/python/src/deltachat/message.py +++ b/python/src/deltachat/message.py @@ -206,7 +206,6 @@ class MessageType(object): return self._type == const.DC_MSG_FILE - @attr.s class MessageState(object): """ Current Message In/Out state, updated on each call of is_* methods. diff --git a/src/constants.rs b/src/constants.rs index 237df3f83..4ab48782d 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1,6 +1,6 @@ //! Constants -pub const DC_VERSION_STR: &'static [u8; 14] = b"1.0.0-alpha.1\x00"; +pub const DC_VERSION_STR: &'static [u8; 14] = b"1.0.0-alpha.3\x00"; pub const DC_MOVE_STATE_MOVING: u32 = 3; pub const DC_MOVE_STATE_STAY: u32 = 2; diff --git a/src/dc_imex.rs b/src/dc_imex.rs index 5ae71c5c0..b43d550e2 100644 --- a/src/dc_imex.rs +++ b/src/dc_imex.rs @@ -362,11 +362,7 @@ pub unsafe fn dc_continue_key_transfer( } || *filename.offset(0isize) as libc::c_int == 0i32 { - error!( - context, - 0, - "Message is no Autocrypt Setup Message.", - ); + error!(context, 0, "Message is no Autocrypt Setup Message.",); } else if 0 == dc_read_file( context, @@ -377,27 +373,15 @@ pub unsafe fn dc_continue_key_transfer( || filecontent.is_null() || filebytes <= 0 { - error!( - context, - 0, - "Cannot read Autocrypt Setup Message file.", - ); + error!(context, 0, "Cannot read Autocrypt Setup Message file.",); } else { norm_sc = dc_normalize_setup_code(context, setup_code); if norm_sc.is_null() { - warn!( - context, - 0, - "Cannot normalize Setup Code.", - ); + warn!(context, 0, "Cannot normalize Setup Code.",); } else { armored_key = dc_decrypt_setup_file(context, norm_sc, filecontent); if armored_key.is_null() { - warn!( - context, - 0, - "Cannot decrypt Autocrypt Setup Message.", - ); + warn!(context, 0, "Cannot decrypt Autocrypt Setup Message.",); } else if !(0 == set_self_key(context, armored_key, 1i32)) { /*set default*/ /* error already logged */ @@ -431,7 +415,7 @@ unsafe fn set_self_key( let mut buf_base64: *const libc::c_char = 0 as *const libc::c_char; let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut self_addr: *mut libc::c_char = 0 as *mut libc::c_char; - info!(context, 0, "armored key: {}", as_str(armored)); + info!(context, 0, "XXX armored key: {}", as_str(armored)); buf = dc_strdup(armored); if 0 == dc_split_armored_data( @@ -446,11 +430,7 @@ unsafe fn set_self_key( ) != 0i32 || buf_base64.is_null() { - warn!( - context, - 0, - "File does not contain a private key.", - ); + warn!(context, 0, "File does not contain a private key.",); } else { if let Some((private_key, public_key)) = Key::from_base64( CStr::from_ptr(buf_base64).to_str().unwrap(), @@ -539,11 +519,10 @@ unsafe fn set_self_key( success = 1; } } else { - dc_log_error( + let x = CStr::from_ptr(buf_base64).to_str().unwrap(); + error!( context, - 0i32, - b"File does not contain a valid private key.\x00" as *const u8 - as *const libc::c_char, + 0, "File does not contain a private key. XXX key: {}", x ); } } @@ -568,7 +547,7 @@ pub unsafe fn dc_decrypt_setup_file( let mut indx: size_t = 0i32 as size_t; let mut payload: *mut libc::c_char = 0 as *mut libc::c_char; - info!(_context, 0, "trying to decrypt ASM file"); + info!(_context, 0, "XXX trying to decrypt ASM file"); fc_buf = dc_strdup(filecontent); if !(0 == dc_split_armored_data( diff --git a/src/key.rs b/src/key.rs index 7744132ab..cd68eca6f 100644 --- a/src/key.rs +++ b/src/key.rs @@ -90,6 +90,7 @@ impl Key { } pub fn from_slice(bytes: &[u8], key_type: KeyType) -> Option { + println!("hello from_slice"); let res: Result = match key_type { KeyType::Public => SignedPublicKey::from_bytes(Cursor::new(bytes)).map(Into::into), KeyType::Private => SignedSecretKey::from_bytes(Cursor::new(bytes)).map(Into::into), @@ -130,7 +131,6 @@ impl Key { // strip newlines and other whitespace let cleaned: String = encoded_data.trim().split_whitespace().collect(); let bytes = cleaned.as_bytes(); - base64::decode(bytes) .ok() .and_then(|decoded| Self::from_slice(&decoded, key_type)) @@ -436,6 +436,70 @@ mod tests { assert_eq!(fingerprint, "1234567890ABCDABCDEFABCDEF"); } + #[test] + fn test_from_base64() { + let private_key = Key::from_base64( + "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 + QCNYLJNVfJcrBDGvkDR9/bwEnw===GU1/ + ", + KeyType::Private, + ) + .expect("failed to decode"); + let binary = private_key.to_bytes(); + let private_key2 = Key::from_slice(&binary, KeyType::Private).expect("invalid private key"); + } + #[test] fn test_format_fingerprint() { let fingerprint = dc_format_fingerprint("1234567890ABCDABCDEFABCDEF1234567890ABCD"); From f7d13fd12f7a76ad88b2715c90a9368ba223019d Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 5 Jul 2019 16:32:26 +0200 Subject: [PATCH 05/12] comment on when it passes --- src/key.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/key.rs b/src/key.rs index cd68eca6f..d65e32150 100644 --- a/src/key.rs +++ b/src/key.rs @@ -495,7 +495,7 @@ mod tests { ", KeyType::Private, ) - .expect("failed to decode"); + .expect("failed to decode"); // NOTE: if you take out the ===GU1/ part, everything passes! let binary = private_key.to_bytes(); let private_key2 = Key::from_slice(&binary, KeyType::Private).expect("invalid private key"); } From 4c95664992cf0eacf6e1fa8de0d1c4b2dffc1dd2 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Fri, 5 Jul 2019 19:12:08 +0200 Subject: [PATCH 06/12] fix and improve key import --- src/dc_imex.rs | 198 +++++++++++++++++++++---------------------------- src/key.rs | 167 ++++++++++++++++++++++++----------------- 2 files changed, 182 insertions(+), 183 deletions(-) diff --git a/src/dc_imex.rs b/src/dc_imex.rs index b43d550e2..3318c2756 100644 --- a/src/dc_imex.rs +++ b/src/dc_imex.rs @@ -1,4 +1,4 @@ -use std::ffi::{CStr, CString}; +use std::ffi::CString; use mmime::mailmime_content::*; use mmime::mmapstring::*; @@ -402,133 +402,101 @@ pub unsafe fn dc_continue_key_transfer( // TODO should return bool /rtn unsafe fn set_self_key( context: &Context, - armored: *const libc::c_char, + armored_c: *const libc::c_char, set_default: libc::c_int, ) -> libc::c_int { - let mut success: libc::c_int = 0i32; - let buf: *mut libc::c_char; - // pointer inside buf, MUST NOT be free()'d - let mut buf_headerline: *const libc::c_char = 0 as *const libc::c_char; - // - " - - let mut buf_preferencrypt: *const libc::c_char = 0 as *const libc::c_char; - // - " - - let mut buf_base64: *const libc::c_char = 0 as *const libc::c_char; + let mut success = 0; + let mut stmt: *mut sqlite3_stmt = 0 as *mut sqlite3_stmt; let mut self_addr: *mut libc::c_char = 0 as *mut libc::c_char; - info!(context, 0, "XXX armored key: {}", as_str(armored)); - buf = dc_strdup(armored); - if 0 == dc_split_armored_data( - buf, - &mut buf_headerline, - 0 as *mut *const libc::c_char, - &mut buf_preferencrypt, - &mut buf_base64, - ) || strcmp( - buf_headerline, - b"-----BEGIN PGP PRIVATE KEY BLOCK-----\x00" as *const u8 as *const libc::c_char, - ) != 0i32 - || buf_base64.is_null() + assert!(!armored_c.is_null(), "invalid buffer"); + let armored = as_str(armored_c); + + info!(context, 0, "XXX armored key: {}", armored); + + if let Some((private_key, public_key, header)) = + Key::from_armored_string(armored, KeyType::Private) + .and_then(|(k, h)| if k.verify() { Some((k, h)) } else { None }) + .and_then(|(k, h)| k.split_key().map(|pub_key| (k, pub_key, h))) { - warn!(context, 0, "File does not contain a private key.",); - } else { - if let Some((private_key, public_key)) = Key::from_base64( - CStr::from_ptr(buf_base64).to_str().unwrap(), - KeyType::Private, - ) - .and_then(|k| if k.verify() { Some(k) } else { None }) - .and_then(|k| k.split_key().map(|pub_key| (k, pub_key))) - { - stmt = dc_sqlite3_prepare( + stmt = dc_sqlite3_prepare( + context, + &context.sql, + b"DELETE FROM keypairs WHERE public_key=? OR private_key=?;\x00" as *const u8 + as *const libc::c_char, + ); + let pub_bytes = public_key.to_bytes(); + sqlite3_bind_blob( + stmt, + 1, + pub_bytes.as_ptr() as *const _, + pub_bytes.len() as libc::c_int, + None, + ); + let priv_bytes = private_key.to_bytes(); + sqlite3_bind_blob( + stmt, + 2, + priv_bytes.as_ptr() as *const _, + priv_bytes.len() as libc::c_int, + None, + ); + sqlite3_step(stmt); + sqlite3_finalize(stmt); + stmt = 0 as *mut sqlite3_stmt; + if 0 != set_default { + dc_sqlite3_execute( context, &context.sql, - b"DELETE FROM keypairs WHERE public_key=? OR private_key=?;\x00" as *const u8 - as *const libc::c_char, - ); - let pub_bytes = public_key.to_bytes(); - sqlite3_bind_blob( - stmt, - 1, - pub_bytes.as_ptr() as *const _, - pub_bytes.len() as libc::c_int, - None, - ); - let priv_bytes = private_key.to_bytes(); - sqlite3_bind_blob( - stmt, - 2, - priv_bytes.as_ptr() as *const _, - priv_bytes.len() as libc::c_int, - None, - ); - sqlite3_step(stmt); - sqlite3_finalize(stmt); - stmt = 0 as *mut sqlite3_stmt; - if 0 != set_default { - dc_sqlite3_execute( - context, - &context.sql, - b"UPDATE keypairs SET is_default=0;\x00" as *const u8 as *const libc::c_char, - ); - } - self_addr = dc_sqlite3_get_config( - context, - &context.sql, - b"configured_addr\x00" as *const u8 as *const libc::c_char, - 0 as *const libc::c_char, - ); - if !dc_key_save_self_keypair( - context, - &public_key, - &private_key, - self_addr, - set_default, - &context.sql, - ) { - dc_log_error( - context, - 0i32, - b"Cannot save keypair.\x00" as *const u8 as *const libc::c_char, - ); - } else { - if !buf_preferencrypt.is_null() { - if strcmp( - buf_preferencrypt, - b"nopreference\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - dc_sqlite3_set_config_int( - context, - &context.sql, - b"e2ee_enabled\x00" as *const u8 as *const libc::c_char, - 0i32, - ); - } else if strcmp( - buf_preferencrypt, - b"mutual\x00" as *const u8 as *const libc::c_char, - ) == 0i32 - { - dc_sqlite3_set_config_int( - context, - &context.sql, - b"e2ee_enabled\x00" as *const u8 as *const libc::c_char, - 1i32, - ); - } - } - success = 1; - } - } else { - let x = CStr::from_ptr(buf_base64).to_str().unwrap(); - error!( - context, - 0, "File does not contain a private key. XXX key: {}", x + b"UPDATE keypairs SET is_default=0;\x00" as *const u8 as *const libc::c_char, ); } + self_addr = dc_sqlite3_get_config( + context, + &context.sql, + b"configured_addr\x00" as *const u8 as *const libc::c_char, + 0 as *const libc::c_char, + ); + if !dc_key_save_self_keypair( + context, + &public_key, + &private_key, + self_addr, + set_default, + &context.sql, + ) { + error!(context, 0, "Cannot save keypair.",); + } else { + let prefer_encrypt = header.get("Autocrypt-Prefer-Encrypt"); + + if let Some(prefer_encrypt) = prefer_encrypt { + if prefer_encrypt == "nopreference" { + dc_sqlite3_set_config_int( + context, + &context.sql, + b"e2ee_enabled\x00" as *const u8 as *const libc::c_char, + 0i32, + ); + } else if prefer_encrypt == "mutual" { + dc_sqlite3_set_config_int( + context, + &context.sql, + b"e2ee_enabled\x00" as *const u8 as *const libc::c_char, + 1i32, + ); + } + } + success = 1; + } + } else { + error!( + context, + 0, "File does not contain a private key. XXX key: {}", armored + ); } sqlite3_finalize(stmt); - free(buf as *mut libc::c_void); free(self_addr as *mut libc::c_void); success diff --git a/src/key.rs b/src/key.rs index d65e32150..0bcb21436 100644 --- a/src/key.rs +++ b/src/key.rs @@ -127,6 +127,27 @@ impl Key { Self::from_binary(data, len, key_type) } + pub fn from_armored_string( + data: &str, + key_type: KeyType, + ) -> Option<(Self, BTreeMap)> { + let bytes = data.as_bytes(); + let res: Result<(Key, _), _> = match key_type { + KeyType::Public => SignedPublicKey::from_armor_single(Cursor::new(bytes)) + .map(|(k, h)| (Into::into(k), h)), + KeyType::Private => SignedSecretKey::from_armor_single(Cursor::new(bytes)) + .map(|(k, h)| (Into::into(k), h)), + }; + + match res { + Ok(res) => Some(res), + Err(err) => { + eprintln!("Invalid key bytes: {:?}", err); + None + } + } + } + pub fn from_base64(encoded_data: &str, key_type: KeyType) -> Option { // strip newlines and other whitespace let cleaned: String = encoded_data.trim().split_whitespace().collect(); @@ -226,16 +247,6 @@ impl Key { .to_string() } - /// the result must be freed - pub fn to_base64_c(&self, break_every: usize) -> *mut libc::c_char { - let res = self.to_base64(break_every); - let res_c = CString::new(res.trim()).unwrap(); - - // need to use strdup to allocate the result with malloc - // so it can be `free`d later. - unsafe { strdup(res_c.as_ptr()) } - } - pub fn to_armored_string( &self, headers: Option<&BTreeMap>, @@ -437,67 +448,70 @@ mod tests { } #[test] - fn test_from_base64() { - let private_key = Key::from_base64( - "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 - QCNYLJNVfJcrBDGvkDR9/bwEnw===GU1/ - ", + fn test_from_armored_string() { + let (private_key, _) = Key::from_armored_string( + "-----BEGIN PGP PRIVATE KEY BLOCK----- + +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 +7yPJeQ== +=KZk/ +-----END PGP PRIVATE KEY BLOCK-----", KeyType::Private, ) - .expect("failed to decode"); // NOTE: if you take out the ===GU1/ part, everything passes! + .expect("failed to decode"); // NOTE: if you take out the ===GU1/ part, everything passes! let binary = private_key.to_bytes(); - let private_key2 = Key::from_slice(&binary, KeyType::Private).expect("invalid private key"); + Key::from_slice(&binary, KeyType::Private).expect("invalid private key"); } #[test] @@ -523,4 +537,21 @@ mod tests { let private_key2 = Key::from_slice(&binary, KeyType::Private).expect("invalid private key"); assert_eq!(private_key, private_key2); } + + #[test] + fn test_ascii_roundtrip() { + let (public_key, private_key) = + crate::pgp::dc_pgp_create_keypair(CString::new("hello").unwrap().as_ptr()).unwrap(); + + let s = public_key.to_armored_string(None).unwrap(); + let (public_key2, _) = + Key::from_armored_string(&s, KeyType::Public).expect("invalid public key"); + assert_eq!(public_key, public_key2); + + let s = private_key.to_armored_string(None).unwrap(); + println!("{}", &s); + let (private_key2, _) = + Key::from_armored_string(&s, KeyType::Private).expect("invalid private key"); + assert_eq!(private_key, private_key2); + } } From 27c8bb64c8580b77f97dfe2dea4281f0ff2e4391 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 5 Jul 2019 19:26:40 +0200 Subject: [PATCH 07/12] remove some debuging --- src/dc_imex.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/dc_imex.rs b/src/dc_imex.rs index 3318c2756..883304aad 100644 --- a/src/dc_imex.rs +++ b/src/dc_imex.rs @@ -413,8 +413,6 @@ unsafe fn set_self_key( assert!(!armored_c.is_null(), "invalid buffer"); let armored = as_str(armored_c); - info!(context, 0, "XXX armored key: {}", armored); - if let Some((private_key, public_key, header)) = Key::from_armored_string(armored, KeyType::Private) .and_then(|(k, h)| if k.verify() { Some((k, h)) } else { None }) @@ -492,7 +490,7 @@ unsafe fn set_self_key( } else { error!( context, - 0, "File does not contain a private key. XXX key: {}", armored + 0, "File does not contain a private key.", ); } @@ -515,7 +513,6 @@ pub unsafe fn dc_decrypt_setup_file( let mut indx: size_t = 0i32 as size_t; let mut payload: *mut libc::c_char = 0 as *mut libc::c_char; - info!(_context, 0, "XXX trying to decrypt ASM file"); fc_buf = dc_strdup(filecontent); if !(0 == dc_split_armored_data( From 3d7be47adfbc1b42dafa92e7f949741aa97ecbb1 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 5 Jul 2019 20:05:08 +0200 Subject: [PATCH 08/12] fix rust format --- src/dc_imex.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/dc_imex.rs b/src/dc_imex.rs index 883304aad..172b7790d 100644 --- a/src/dc_imex.rs +++ b/src/dc_imex.rs @@ -488,10 +488,7 @@ unsafe fn set_self_key( success = 1; } } else { - error!( - context, - 0, "File does not contain a private key.", - ); + error!(context, 0, "File does not contain a private key.",); } sqlite3_finalize(stmt); From 2aa81a7a9a5edfd6d3ae733aa88acd5c7b6b566b Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 5 Jul 2019 23:12:11 +0200 Subject: [PATCH 09/12] speed up test teardown by now waiting for threads to finish ... and remove a debug statement --- python/src/deltachat/account.py | 4 ++-- python/tests/conftest.py | 4 ++-- src/key.rs | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/python/src/deltachat/account.py b/python/src/deltachat/account.py index 75e5f414b..6fb32b73e 100644 --- a/python/src/deltachat/account.py +++ b/python/src/deltachat/account.py @@ -328,10 +328,10 @@ class Account(object): self.configure() self._threads.start() - def stop_threads(self): + def stop_threads(self, wait=True): """ stop IMAP/SMTP threads. """ lib.dc_stop_ongoing_process(self._dc_context) - self._threads.stop(wait=True) + self._threads.stop(wait=wait) def _process_event(self, ctx, evt_name, data1, data2): assert ctx == self._dc_context diff --git a/python/tests/conftest.py b/python/tests/conftest.py index d005fc408..64668d938 100644 --- a/python/tests/conftest.py +++ b/python/tests/conftest.py @@ -103,7 +103,7 @@ def acfactory(pytestconfig, tmpdir, request): ac._evlogger.set_timeout(30) ac.configure(**configdict) ac.start_threads() - self._finalizers.append(ac.stop_threads) + self._finalizers.append(lambda: ac.stop_threads(wait=False)) return ac def clone_online_account(self, account): @@ -114,7 +114,7 @@ def acfactory(pytestconfig, tmpdir, request): ac._evlogger.set_timeout(30) ac.configure(addr=account.get_config("addr"), mail_pw=account.get_config("mail_pw")) ac.start_threads() - self._finalizers.append(ac.stop_threads) + self._finalizers.append(lambda: ac.stop_threads(wait=False)) return ac return AccountMaker() diff --git a/src/key.rs b/src/key.rs index 0bcb21436..0b1fc7895 100644 --- a/src/key.rs +++ b/src/key.rs @@ -90,7 +90,6 @@ impl Key { } pub fn from_slice(bytes: &[u8], key_type: KeyType) -> Option { - println!("hello from_slice"); let res: Result = match key_type { KeyType::Public => SignedPublicKey::from_bytes(Cursor::new(bytes)).map(Into::into), KeyType::Private => SignedSecretKey::from_bytes(Cursor::new(bytes)).map(Into::into), From 184b3c8e917c2150fc36c47368c84a575fecc67d Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 6 Jul 2019 11:30:45 +0200 Subject: [PATCH 10/12] undo version bump --- Cargo.toml | 2 +- deltachat-ffi/Cargo.toml | 2 +- src/constants.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a077c9de4..1180aa24e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deltachat" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.1" authors = ["dignifiedquire "] edition = "2018" license = "MPL" diff --git a/deltachat-ffi/Cargo.toml b/deltachat-ffi/Cargo.toml index 2094c0d8b..5df91a47b 100644 --- a/deltachat-ffi/Cargo.toml +++ b/deltachat-ffi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deltachat_ffi" -version = "1.0.0-alpha.3" +version = "1.0.0-alpha.1" description = "Deltachat FFI" authors = ["dignifiedquire "] edition = "2018" diff --git a/src/constants.rs b/src/constants.rs index 4ab48782d..237df3f83 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1,6 +1,6 @@ //! Constants -pub const DC_VERSION_STR: &'static [u8; 14] = b"1.0.0-alpha.3\x00"; +pub const DC_VERSION_STR: &'static [u8; 14] = b"1.0.0-alpha.1\x00"; pub const DC_MOVE_STATE_MOVING: u32 = 3; pub const DC_MOVE_STATE_STAY: u32 = 2; From 5c53bb5ed75d5697e570675335f0780d46f16a0f Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 6 Jul 2019 11:31:46 +0200 Subject: [PATCH 11/12] fixup --- deltachat-ffi/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deltachat-ffi/Cargo.toml b/deltachat-ffi/Cargo.toml index 5df91a47b..29fb8129b 100644 --- a/deltachat-ffi/Cargo.toml +++ b/deltachat-ffi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deltachat_ffi" -version = "1.0.0-alpha.1" +version = "1.0.0-alpha.2" description = "Deltachat FFI" authors = ["dignifiedquire "] edition = "2018" From fd5cba72421d725e76252fbfd428b44a14698ce8 Mon Sep 17 00:00:00 2001 From: dignifiedquire Date: Sat, 6 Jul 2019 11:32:15 +0200 Subject: [PATCH 12/12] fixup --- Cargo.toml | 2 +- deltachat-ffi/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1180aa24e..ef6323620 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deltachat" -version = "1.0.0-alpha.1" +version = "1.0.0-alpha.2" authors = ["dignifiedquire "] edition = "2018" license = "MPL" diff --git a/deltachat-ffi/Cargo.toml b/deltachat-ffi/Cargo.toml index 29fb8129b..5df91a47b 100644 --- a/deltachat-ffi/Cargo.toml +++ b/deltachat-ffi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "deltachat_ffi" -version = "1.0.0-alpha.2" +version = "1.0.0-alpha.1" description = "Deltachat FFI" authors = ["dignifiedquire "] edition = "2018"