diff --git a/docker/kolab/utils/patches/0002-WOAT-support.patch b/docker/kolab/utils/patches/0002-WOAT-support.patch index abed158c..0a14f879 100644 --- a/docker/kolab/utils/patches/0002-WOAT-support.patch +++ b/docker/kolab/utils/patches/0002-WOAT-support.patch @@ -1,208 +1,208 @@ From d140792bdd838fc543128c977bfe47199c914e64 Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Thu, 14 Jul 2022 15:03:22 +0200 Subject: [PATCH 2/3] WOAT support --- plugins/enigma/config.inc.php.dist | 5 ++ plugins/enigma/lib/enigma_engine.php | 93 +++++++++++++++++++++++-- program/lib/Roundcube/rcube_message.php | 10 +-- 3 files changed, 99 insertions(+), 9 deletions(-) diff --git a/plugins/enigma/config.inc.php.dist b/plugins/enigma/config.inc.php.dist index fc620587e..f77ad26a8 100644 --- a/plugins/enigma/config.inc.php.dist +++ b/plugins/enigma/config.inc.php.dist @@ -75,3 +75,8 @@ $config['enigma_password_time'] = 5; // - enigma_options_lock = array('sign') // - dont_override = array('enigma_sign_all') $config['enigma_options_lock'] = array(); + +// Enable Kolab's Web Of Anti-Trust feature +// Fetches public keys from DNS. Default: false +// To enable set it to True or an array of domain names. +$config['enigma_woat'] = false; diff --git a/plugins/enigma/lib/enigma_engine.php b/plugins/enigma/lib/enigma_engine.php index 4dbb464a5..45c98caef 100644 --- a/plugins/enigma/lib/enigma_engine.php +++ b/plugins/enigma/lib/enigma_engine.php @@ -28,6 +28,7 @@ class enigma_engine private $pgp_driver; private $smime_driver; private $password_time; + private $sender; private $cache = array(); public $decryptions = array(); @@ -267,6 +268,9 @@ class enigma_engine $recipients = array_unique($recipients); + // Fetch keys from external sources, if configured + $this->sync_keys($recipients); + // find recipient public keys foreach ((array) $recipients as $email) { if ($email == $from && $sign_key) { @@ -377,6 +381,17 @@ class enigma_engine return; } + // Get the message/part sender + if (!empty($p['object']->sender) && !empty($p['object']->sender['mailto'])) { + $this->sender = $p['object']->sender['mailto']; + } + if (!empty($p['structure']->headers) && !empty($p['structure']->headers['from'])) { + $from = rcube_mime::decode_address_list($p['structure']->headers['from'], 1, false); + if (($from = current($from)) && !empty($from['mailto'])) { + $this->sender = $from['mailto']; + } + } + // Don't be tempted to support encryption in text/html parts // Because of EFAIL vulnerability we should never support this (#6289) @@ -875,6 +890,11 @@ class enigma_engine { // @TODO: Handle big bodies using (temp) files + // Import sender's key from external sources, if configured + if ($this->sender) { + $this->sync_keys([$this->sender]); + } + // Get rid of possible non-ascii characters (#5962) $sig_body = preg_replace('/[^\x00-\x7F]/', '', $sig_body); @@ -899,6 +919,11 @@ class enigma_engine { // @TODO: Handle big bodies using (temp) files + // Import sender's key from external sources, if configured + if ($this->sender) { + $this->sync_keys([$this->sender]); + } + // Get rid of possible non-ascii characters (#5962) $msg_body = preg_replace('/[^\x00-\x7F]/', '', $msg_body); @@ -1014,19 +1039,25 @@ class enigma_engine return; } - $mode = $can_sign ? enigma_key::CAN_SIGN : enigma_key::CAN_ENCRYPT; - $ret = null; + $mode = $can_sign ? enigma_key::CAN_SIGN : enigma_key::CAN_ENCRYPT; + $found = []; // check key validity and type foreach ($result as $key) { if (($subkey = $key->find_subkey($email, $mode)) && (!$can_sign || $key->get_type() == enigma_key::TYPE_KEYPAIR) ) { - $ret = $key; - break; -+ $found[$subkey->get_creation_date(true)] = $key; ++ $found[] = $key; //$found[$subkey->get_creation_date(true)] = $key; } } + // Use the most recent one -+ if (count($found) > 1) { -+ ksort($found, SORT_NUMERIC); -+ } ++ //if (count($found) > 1) { ++ //ksort($found, SORT_NUMERIC); ++ //} + + $ret = count($found) > 0 ? array_pop($found) : null; + // cache private key info for better performance // we can skip one list_keys() call when signing and attaching a key if ($can_sign) { @@ -1422,4 +1453,58 @@ class enigma_engine ), true, $abort); } } + + /** + * Import public keys from DNS according to Kolab Web-Of-Anti-Trust + * + * @param array $recipients List of email addresses + */ + protected function sync_keys($recipients) + { + $import = []; + $woat = $this->rc->config->get('enigma_woat'); + + if (empty($woat)) { + return; + } + + foreach ($recipients as $recipient) { + if (!strpos($recipient, '@')) { + continue; + } + + list($local, $domain) = explode('@', $recipient); + + // Do this for configured domains only + if (is_array($woat) && !in_array_nocase($domain, $woat)) { + continue; + } + + // remove parts behind a recipient delimiter ("jeroen+Trash" => "jeroen") + $local = preg_replace('/\+.*$/', '', $local); + + $fqdn = sha1($local) . '._woat.' . $domain; + + // Fetch the TXT record(s) + if (($records = dns_get_record($fqdn, DNS_TXT)) === false) { + continue; + } + + foreach ($records as $record) { + if (strpos($record['txt'], 'v=woat1,') === 0) { + $entry = explode('public_key=', $record['txt']); + if (count($entry) == 2) { + $import[] = $entry[1]; + // For now we support only one key + break; + } + } + } + } + + // Import the fetched keys + if (!empty($import)) { + $this->import_key(implode("\n", $import)); + } + } } diff --git a/program/lib/Roundcube/rcube_message.php b/program/lib/Roundcube/rcube_message.php index 01b0e6dec..d5459bb50 100644 --- a/program/lib/Roundcube/rcube_message.php +++ b/program/lib/Roundcube/rcube_message.php @@ -118,6 +118,11 @@ class rcube_message false, false, true) ); + $this->mime = new rcube_mime($this->headers->charset); + $this->subject = str_replace("\n", '', $this->headers->get('subject')); + $from = $this->mime->decode_address_list($this->headers->from, 1); + $this->sender = current($from); + if (!empty($this->headers->structure)) { $this->get_mime_numbers($this->headers->structure); $this->parse_structure($this->headers->structure); @@ -126,11 +131,6 @@ class rcube_message $this->body = $this->storage->get_body($uid); } - $this->mime = new rcube_mime($this->headers->charset); - $this->subject = str_replace("\n", '', $this->headers->get('subject')); - $from = $this->mime->decode_address_list($this->headers->from, 1); - $this->sender = current($from); - // notify plugins and let them analyze this structured message object $this->app->plugins->exec_hook('message_load', array('object' => $this)); } -- 2.35.3