From 1ad0e7da5207ab0403f40ee4e14eb282cfab3080 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Sun, 5 Apr 2015 14:12:37 +0200 Subject: Enigma: fix issues with enabled messages_cache --- plugins/enigma/README | 9 +++--- plugins/enigma/lib/enigma_engine.php | 63 ++++++++++++++++++++++-------------- 2 files changed, 42 insertions(+), 30 deletions(-) diff --git a/plugins/enigma/README b/plugins/enigma/README index f8368a818..33e975abb 100644 --- a/plugins/enigma/README +++ b/plugins/enigma/README @@ -23,20 +23,17 @@ Implemented features: TODO (must have): -- Fix issues with enabled messages_cache - Make working with gnupg-2.x - Keys export to file - Disable Reply/Forward options when viewing encrypted messages until they are decrypted successfully - Handling of replying/forwarding of encrypted/signed messages -- Performance improvements: - - cache decrypted message key id so we can skip decryption if we have no password in session +- Client-side keys generation (with OpenPGP.js?) TODO (later): - Handling of big messages with temp files - Server-side keys generation (warning: no-entropy issue, max_execution_time issue) -- Client-side keys generation (with OpenPGP.js?) - Key info in contact details page (optional) - Extended key management: - disable, @@ -52,7 +49,9 @@ TODO (later): - Change attachment icon on messages list for encrypted messages (like vcard_attachment plugin does) - Support for multi-server installations (store keys in sql database?) - Per-Identity settings (including keys/certs) -- Cache (last or successful only?) sig verification status to not verify on every msg preview (optional) +- Performance improvements: + - cache decrypted message key id so we can skip decryption if we have no password in session + - cache (last or successful only?) sig verification status to not verify on every msg preview (optional) - S/MIME: Certs generation - S/MIME: Certs management diff --git a/plugins/enigma/lib/enigma_engine.php b/plugins/enigma/lib/enigma_engine.php index fd2594454..6c5ee3cc9 100644 --- a/plugins/enigma/lib/enigma_engine.php +++ b/plugins/enigma/lib/enigma_engine.php @@ -27,9 +27,11 @@ class enigma_engine private $pgp_driver; private $smime_driver; - public $decryptions = array(); - public $signatures = array(); - public $signed_parts = array(); + public $decryptions = array(); + public $signatures = array(); + public $signed_parts = array(); + public $encrypted_parts = array(); + const PASSWORD_TIME = 120; @@ -329,6 +331,8 @@ class enigma_engine { // encrypted attachment, see parse_plain_encrypted() if ($p['part']->need_decryption && $p['part']->body === null) { + $this->load_pgp_driver(); + $storage = $this->rc->get_storage(); $body = $storage->get_message_part($p['object']->uid, $p['part']->mime_id, $p['part'], null, null, true, 0, false); $result = $this->pgp_decrypt($body); @@ -354,7 +358,7 @@ class enigma_engine $part = $p['structure']; // exit, if we're already inside a decrypted message - if ($part->encrypted) { + if (in_array($part->mime_id, $this->encrypted_parts)) { return; } @@ -519,9 +523,6 @@ class enigma_engine else { $this->signed_parts[$msg_part->mime_id] = $struct->mime_id; } - - // Remove signature file from attachments list (?) - unset($struct->parts[1]); } } @@ -556,9 +557,6 @@ class enigma_engine else { $this->signed_parts[$msg_part->mime_id] = $struct->mime_id; } - - // Remove signature file from attachments list - unset($struct->parts[1]); } } @@ -579,11 +577,23 @@ class enigma_engine // Store decryption status $this->decryptions[$part->mime_id] = $result; + // find parent part ID + if (strpos($part->mime_id, '.')) { + $items = explode('.', $part->mime_id); + array_pop($items); + $parent = implode('.', $items); + } + else { + $parent = 0; + } + // Parse decrypted message if ($result === true) { $part->body = $body; $part->body_modified = true; - $part->encrypted = true; + + // Remember it was decrypted + $this->encrypted_parts[] = $part->mime_id; // PGP signed inside? verify signature if (preg_match('/^-----BEGIN PGP SIGNED MESSAGE-----/', $body)) { @@ -591,20 +601,10 @@ class enigma_engine } // Encrypted plain message may contain encrypted attachments - // in such case attachments have .pgp extension and application/octet-stream. + // in such case attachments have .pgp extension and type application/octet-stream. // This is what happens when you select "Encrypt each attachment separately // and send the message using inline PGP" in Thunderbird's Enigmail. - // find parent part ID - if (strpos($part->mime_id, '.')) { - $items = explode('.', $part->mime_id); - array_pop($items); - $parent = implode('.', $items); - } - else { - $parent = 0; - } - if ($p['object']->mime_parts[$parent]) { foreach ((array)$p['object']->mime_parts[$parent]->parts as $p) { if ($p->disposition == 'attachment' && $p->mimetype == 'application/octet-stream' @@ -620,6 +620,19 @@ class enigma_engine } } } + // decryption failed, but the message may have already + // been cached with the modified parts (see above), + // let's bring the original state back + else if ($p['object']->mime_parts[$parent]) { + foreach ((array)$p['object']->mime_parts[$parent]->parts as $p) { + if ($p->need_decryption && !preg_match('/^(.*)\.pgp$/i', $p->filename, $m)) { + // modify filename + $p->filename .= '.pgp'; + // flag the part, it will be decrypted when needed + unset($p->need_decryption); + } + } + } } /** @@ -1066,14 +1079,14 @@ class enigma_engine $part->body_modified = true; $part->encoding = 'stream'; - // Cache the fact it was decrypted - $part->encrypted = true; - // modify part identifier if ($old_id) { $part->mime_id = !$part->mime_id ? $old_id : ($old_id . '.' . $part->mime_id); } + // Cache the fact it was decrypted + $this->encrypted_parts[] = $part->mime_id; + $msg->mime_parts[$part->mime_id] = $part; // modify sub-parts -- cgit v1.2.3