From 40d152cfdcace360138ab332e084dfb39a2d2798 Mon Sep 17 00:00:00 2001 From: Thomas Bruederli <thomas@roundcube.net> Date: Mon, 01 Jun 2015 06:53:32 -0400 Subject: [PATCH] Make encrypted pgp/mime message composition work --- program/steps/mail/compose.inc | 4 + program/localization/en_US/messages.inc | 1 program/steps/mail/sendmail.inc | 49 ++++++++++++++++ program/js/app.js | 90 +++++++++++++++++++++++++---- 4 files changed, 129 insertions(+), 15 deletions(-) diff --git a/program/js/app.js b/program/js/app.js index b43ca00..36694b2 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -3347,17 +3347,17 @@ this.check_mailvelope = function(action) { if (typeof window.mailvelope !== 'undefined') { - this.mailvelope_init(action); + this.mailvelope_load(action); } else { $(window).on('mailvelope', function() { - ref.mailvelope_init(action); + ref.mailvelope_load(action); }); } }; // - this.mailvelope_init = function(action) + this.mailvelope_load = function(action) { if (this.env.browser_capabilities) this.env.browser_capabilities['pgpmime'] = 1; @@ -3366,16 +3366,21 @@ mailvelope.getKeyring(keyring).then(function(kr) { ref.mailvelope_keyring = kr; + ref.mailvelope_init(action, kr); }).catch(function(err) { // attempt to create a new keyring for this app/user mailvelope.createKeyring(keyring).then(function(kr) { ref.mailvelope_keyring = kr; - keyring = keyring.identifier; + ref.mailvelope_init(action, kr); }).catch(function(err) { console.error(err); }); }); + }; + // + this.mailvelope_init = function(action, keyring) + { if (action == 'show' || action == 'preview') { // decrypt text body if (this.env.is_pgp_content && window.mailvelope) { @@ -3413,17 +3418,22 @@ // remove Mailvelope editor if active if (ref.mailvelope_editor) { ref.mailvelope_editor = null; + ref.compose_skip_unsavedcheck = false; ref.set_button('compose-encrypted', 'act'); + container.removeClass('mailvelope') .find('iframe:not([aria-hidden=true])').remove(); $('#' + ref.env.composebody).show(); + $("[name='_pgpmime']").remove(); } // embed Mailvelope editor container else { var options = { predefinedText: $('#' + this.env.composebody).val() }; - mailvelope.createEditorContainer('#' + container.attr('id'), ref.mailvelope_keyring.identifier, options).then(function(editor) { + mailvelope.createEditorContainer('#' + container.attr('id'), ref.mailvelope_keyring, options).then(function(editor) { ref.mailvelope_editor = editor; + ref.compose_skip_unsavedcheck = true; ref.set_button('compose-encrypted', 'sel'); + container.addClass('mailvelope'); $('#' + ref.env.composebody).hide(); }).catch(function(err) { @@ -3464,19 +3474,65 @@ return false; } - ref.mailvelope_editor.encrypt(recipients).then(function(armored) { - console.log('encrypted message', armored); - var form = ref.gui_objects.messageform; + // add sender identity to recipients to be able to decrypt our very own message + var senders = [], selected_sender = ref.env.identities[$("[name='_from'] option:selected").val()]; + $.each(ref.env.identities, function(k, sender) { + senders.push(sender.email); + }); - // all checks passed, send message - // var msgid = ref.set_busy(true, draft || saveonly ? 'savingmessage' : 'sendingmessage') + ref.mailvelope_keyring.validKeyForAddress(senders).then(function(status) { + valid_sender = null; + $.each(status, function(k,v) { + if (v !== false) { + valid_sender = k; + if (valid_sender == selected_sender) { + return false; // break + } + } + }); + + if (!valid_sender) { + if (!confirm(ref.get_label('nopubkeyforsender'))) { + return false; + } + } + + recipients.push(valid_sender); + + ref.mailvelope_editor.encrypt(recipients).then(function(armored) { + // all checks passed, send message + var form = ref.gui_objects.messageform, + hidden = $("[name='_pgpmime']", form), + msgid = ref.set_busy(true, draft || saveonly ? 'savingmessage' : 'sendingmessage') + + form.target = 'savetarget'; + form._draft.value = draft ? '1' : ''; + form.action = ref.add_url(form.action, '_unlock', msgid); + form.action = ref.add_url(form.action, '_framed', 1); + + if (saveonly) { + form.action = ref.add_url(form.action, '_saveonly', 1); + } + + // send pgp conent via hidden field + if (!hidden.length) { + hidden = $('<input type="hidden" name="_pgpmime">').appendTo(form); + } + hidden.val(armored); + + form.submit(); + + }).catch(function(err) { + console.log(err); + }); // mailvelope_editor.encrypt() }).catch(function(err) { - console.log(err); - }); + console.error(err); + }); // mailvelope_keyring.validKeyForAddress(senders) + }).catch(function(err) { console.error(err); - }); + }); // mailvelope_keyring.validKeyForAddress(recipients) return false; }; @@ -3767,6 +3823,7 @@ ); } + // delegate sending to Mailvelope routine if (this.mailvelope_editor) { return this.mailvelope_submit_messageform(draft, saveonly); } @@ -4088,7 +4145,7 @@ // reset history of hidden iframe used for saving draft (#1489643) // but don't do this on timer-triggered draft-autosaving (#1489789) - if (window.frames['savetarget'] && window.frames['savetarget'].history && !this.draft_autosave_submit) { + if (window.frames['savetarget'] && window.frames['savetarget'].history && !this.draft_autosave_submit && !this.mailvelope_editor) { window.frames['savetarget'].history.back(); } @@ -4158,6 +4215,11 @@ for (id in this.env.attachments) str += id; + // we can't detect changes in the Mailvelope editor so assume it changed + if (this.mailvelope_editor) { + str += ';' + new Date().getTime(); + } + if (save) this.cmp_hash = str; diff --git a/program/localization/en_US/messages.inc b/program/localization/en_US/messages.inc index 2f712f3..be8a0d8 100644 --- a/program/localization/en_US/messages.inc +++ b/program/localization/en_US/messages.inc @@ -58,6 +58,7 @@ $messages['encryptedmessage'] = 'This is an encrypted message and can not be displayed. Sorry!'; $messages['externalmessagedecryption'] = 'This is an encrypted message and can be decrypted with your browser extension.'; $messages['nopubkeyfor'] = 'No valid public key found for $email'; +$messages['nopubkeyforsender'] = 'No valid public key found for your sender identity. Do you want to encrypt the message for the recipients only?'; $messages['nocontactsfound'] = 'No contacts found.'; $messages['contactnotfound'] = 'The requested contact was not found.'; $messages['contactsearchonly'] = 'Enter some search terms to find contacts'; diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index 44f4612..1896e93 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -83,7 +83,7 @@ 'messagesaved', 'converting', 'editorwarning', 'searching', 'uploading', 'uploadingmany', 'fileuploaderror', 'sendmessage', 'newresponse', 'responsename', 'responsetext', 'save', 'savingresponse', 'restoresavedcomposedata', 'restoremessage', 'delete', 'restore', 'ignore', - 'selectimportfile', 'messageissent', 'nopubkeyfor'); + 'selectimportfile', 'messageissent', 'nopubkeyfor', 'nopubkeyforsender'); $OUTPUT->set_pagetitle($RCMAIL->gettext('compose')); @@ -655,6 +655,8 @@ if (!empty($sql_arr['bcc'])) { $identities[$identity_id]['bcc'] = $sql_arr['bcc']; } + + $identities[$identity_id]['email'] = $sql_arr['email']; } $out = $select_from->show($MESSAGE->compose['from']); diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index b3034f5..a766640 100644 --- a/program/steps/mail/sendmail.inc +++ b/program/steps/mail/sendmail.inc @@ -273,6 +273,18 @@ // fetch message body $message_body = rcube_utils::get_input_value('_message', rcube_utils::INPUT_POST, TRUE, $message_charset); +if (isset($_POST['_pgpmime'])) { + $pgp_mime = rcube_utils::get_input_value('_pgpmime', rcube_utils::INPUT_POST); + $message_body = 'This is an OpenPGP/MIME encrypted message (RFC 2440 and 3156)'; + $isHtml = false; + + // clear unencrypted attachments + foreach ($COMPOSE['attachments'] as $attach) { + $RCMAIL->plugins->exec_hook('attachment_delete', $attach); + } + $COMPOSE['attachments'] = array(); +} + if ($isHtml) { $bstyle = array(); @@ -503,6 +515,43 @@ $text_charset .= ";\r\n format=flowed"; } +// compose PGP/Mime message +if ($pgp_mime) { + $MAIL_MIME->addAttachment( + 'Version: 1', + 'application/pgp-encrypted', + 'version.txt', // required by Mail_mime::addAttachment() + false, + '8bit', + '', // $disposition + '', // $charset + '', // $language + '', // $location + null, // $n_encoding + null, // $f_encoding + 'PGP/MIME version identification' + ); + + // patch filename out of the version part + foreach ($MAIL_MIME->_parts as $_i => $_part) { + if ($_part['c_type'] == 'application/pgp-encrypted') { + $MAIL_MIME->_parts[$_i]['name'] = ''; + break; + } + } + + $MAIL_MIME->addAttachment( + $pgp_mime, + 'application/octet-stream', + 'encrypted.asc', + false, + '8bit', + 'inline' + ); + + $MAIL_MIME->setContentType('multipart/encrypted', array('protocol' => "application/pgp-encrypted")); +} + // encoding settings for mail composing $MAIL_MIME->setParam('text_encoding', $transfer_encoding); $MAIL_MIME->setParam('html_encoding', 'quoted-printable'); -- Gitblit v1.9.1