diff --git a/cmdline/cmdline.c b/cmdline/cmdline.c index 6b02c43c..f593c1da 100644 --- a/cmdline/cmdline.c +++ b/cmdline/cmdline.c @@ -317,6 +317,7 @@ char* mrmailbox_cmdline(mrmailbox_t* mailbox, const char* cmdline) "export-keys\n" "import-keys\n" "export-setup\n" + "transfer-key\n" "poke [|| ]\n" "reset \n" "=============================================" @@ -449,8 +450,23 @@ char* mrmailbox_cmdline(mrmailbox_t* mailbox, const char* cmdline) else if( strcmp(cmd, "export-setup")==0 ) { char* setup_code = mrmailbox_create_setup_code(mailbox); - ret = mr_mprintf("Setup code for the exported setup: %s", setup_code); - mrmailbox_imex(mailbox, MR_IMEX_EXPORT_SETUP_MESSAGE, mailbox->m_blobdir, setup_code); + char* file_name = mr_mprintf("%s/autocrypt-key-backup.html", mailbox->m_blobdir); + char* file_content = NULL; + if( mrmailbox_render_setup_file(mailbox, setup_code, &file_content) + && mr_write_file(file_name, file_content, strlen(file_content), mailbox) ) { + ret = mr_mprintf("Setup message written to: %s\nSetup code: %s", file_name, setup_code); + } + else { + ret = COMMAND_FAILED; + } + free(file_content); + free(file_name); + free(setup_code); + } + else if( strcmp(cmd, "transfer-key")==0 ) + { + char* setup_code = mrmailbox_initiate_key_transfer(mailbox); + ret = mr_mprintf("Setup code for the transferred setup message: %s", setup_code); free(setup_code); } else if( strcmp(cmd, "poke")==0 ) diff --git a/src/mrmailbox.h b/src/mrmailbox.h index 2cc88af7..b3b38eee 100644 --- a/src/mrmailbox.h +++ b/src/mrmailbox.h @@ -323,14 +323,13 @@ mrcontact_t* mrmailbox_get_contact (mrmailbox_t*, uint32_t contact_id); #define MR_IMEX_IMPORT_SELF_KEYS 2 /* param1 is a directory where the keys are searched in and read from */ #define MR_IMEX_EXPORT_BACKUP 11 /* param1 is a directory where the backup is written to */ #define MR_IMEX_IMPORT_BACKUP 12 /* param1 is the file with the backup to import */ -#define MR_IMEX_EXPORT_SETUP_MESSAGE 20 /* param1 is a directory where the setup file is written to */ #define MR_BAK_PREFIX "delta-chat" #define MR_BAK_SUFFIX "bak" int mrmailbox_imex (mrmailbox_t*, int what, const char* param1, const char* param2); void mrmailbox_imex_cancel (mrmailbox_t*); char* mrmailbox_imex_has_backup (mrmailbox_t*, const char* dir); int mrmailbox_check_password (mrmailbox_t*, const char* pw); -char* mrmailbox_create_setup_code (mrmailbox_t*); +char* mrmailbox_initiate_key_transfer(mrmailbox_t*); void mrmailbox_heartbeat (mrmailbox_t*); @@ -415,7 +414,8 @@ void mrmailbox_e2ee_encrypt (mrmailbox_t*, const clist* recipien int mrmailbox_e2ee_decrypt (mrmailbox_t*, struct mailmime* in_out_message, int* ret_validation_errors); /* returns 1 if sth. was decrypted, 0 in other cases */ void mrmailbox_e2ee_thanks (mrmailbox_e2ee_helper_t*); /* frees data referenced by "mailmime" but not freed by mailmime_free(). After calling mre2ee_unhelp(), in_out_message cannot be used any longer! */ int mrmailbox_ensure_secret_key_exists (mrmailbox_t*); /* makes sure, the private key exists, needed only for exporting keys and the case no message was sent before */ - +char* mrmailbox_create_setup_code (mrmailbox_t*); +int mrmailbox_render_setup_file (mrmailbox_t* mailbox, const char* passphrase, char** ret_msg); #ifdef __cplusplus } /* /extern "C" */ diff --git a/src/mrmailbox_imex.c b/src/mrmailbox_imex.c index 594edc27..7d9975fc 100644 --- a/src/mrmailbox_imex.c +++ b/src/mrmailbox_imex.c @@ -91,7 +91,7 @@ static int s_imex_do_exit = 1; /* the value 1 avoids mrmailbox_imex_cancel() fro * ..... * -----END PGP PRIVATE KEY BLOCK----- * - * mrmailbox_render_keys_to_html() renders the body after the second + * mrmailbox_render_setup_file() renders the body after the second * `-==break1==` in this example. * * @private @memberof mrmailbox_t @@ -104,7 +104,7 @@ static int s_imex_do_exit = 1; /* the value 1 avoids mrmailbox_imex_cancel() fro * * @return 1=success, 0=error */ -int mrmailbox_render_keys_to_html(mrmailbox_t* mailbox, const char* passphrase, char** ret_msg) +int mrmailbox_render_setup_file(mrmailbox_t* mailbox, const char* passphrase, char** ret_msg) { int success = 0, locked = 0; sqlite3_stmt* stmt = NULL; @@ -365,34 +365,6 @@ cleanup: } -static int export_setup_file(mrmailbox_t* mailbox, const char* dir, const char* setup_code) -{ - int success = 0; - char* file_content = NULL; - char* file_name = NULL; - - if( !mrmailbox_render_keys_to_html(mailbox, setup_code, &file_content) ) { - mrmailbox_log_error(mailbox, 0, "Cannot generate Autocrypt setup file,"); - goto cleanup; - } - - file_name = mr_mprintf("%s/autocrypt-key-backup.html", dir); - if( !mr_write_file(file_name, file_content, strlen(file_content), mailbox) ) { - mrmailbox_log_error(mailbox, 0, "Cannot write keys to %s", file_name); - } - else { - mailbox->m_cb(mailbox, MR_EVENT_IMEX_FILE_WRITTEN, (uintptr_t)file_name, 0); - } - - success = 1; - -cleanup: - free(file_content); - free(file_name); - return success; -} - - /******************************************************************************* * Import keys ******************************************************************************/ @@ -984,12 +956,6 @@ int mrmailbox_imex(mrmailbox_t* mailbox, int what, const char* param1, const cha } break; - case MR_IMEX_EXPORT_SETUP_MESSAGE: - if( !export_setup_file(mailbox, param1, param2) ) { - goto cleanup; - } - break; - default: goto cleanup; } @@ -1211,7 +1177,7 @@ cleanup: * Linebreaks and spaces are not added to the setup code, but the "-" are. * Should be given to mrmailbox_imex() for encryption, should be wiped and free()'d after usage. * - * @memberof mrmailbox_t + * @private @memberof mrmailbox_t * * @param mailbox Mailbox object as created by mrmailbox_new(). * @@ -1240,3 +1206,62 @@ char* mrmailbox_create_setup_code(mrmailbox_t* mailbox) (int)buf[3], (int)buf[4], (int)buf[5], (int)buf[6], (int)buf[7], (int)buf[8]); } + + +/** + * Initiate Autocrypt key transfer. + * + * Before starting the key transfer with this function, the user should be asked: + * + * ``` + * "The 'Autocrypt key transfer' requires that the mail client on the other device is Autocrypt-compliant. + * We will then send the key to yourself. The key will be encrypted by a setup code which is displayed herer and must be typed on the other device." + * ``` + * + * After that, this function should be called to send the Autocrypt setup message. + * The required setup code is then returned by this function, does not contain + * linebreaks or spaces and has the follwing format: + * + * ``` + * 1234-1234-1234-1234-1234-1234-1234-1234-1234 + * ``` + * + * The setup code should be shown to the user then: + * + * ``` + * "The setup message has been sent to yourself. + * + * Please switch to the other device now and open the setup message. + * You should be promptet for a setup code. + * Please type the following digits into the prompt: + * + * 1234-1234-1234- + * 1234-1234-1234- + * 1234-1234-1234 + * + * Once you're done, your other device will be ready to use Autocrypt." + * ``` + * + * For more details about the Autocrypt setup process, please refer to + * https://autocrypt.org/en/latest/level1.html#autocrypt-setup-message + * + * @memberof mrmailbox_t + * + * @param mailbox The mailbox object. + * + * @return The setup code. Must be free()'d after usage. + * On errors, eg. if the message could not be sent, NULL is returned. + */ +char* mrmailbox_initiate_key_transfer(mrmailbox_t* mailbox) +{ + char* setup_code = NULL; + + if( (setup_code=mrmailbox_create_setup_code(mailbox)) ) { + goto cleanup; + } + + // TODO: send message ... + +cleanup: + return setup_code; +}