Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/roundcube/roundcubemail.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Mollekopf <cmollekopf@gmail.com>2022-08-01 12:51:32 +0300
committerGitHub <noreply@github.com>2022-08-01 12:51:32 +0300
commite495fc73b513cae26205f0dc931abbb98f35b718 (patch)
treecba015b0c14d93371bb77abb0a87c30fe10de67a
parent47a2e2c536049fc242da483c2982bb9e875feb1e (diff)
Enigma: WOAT Support (#8626)
* Enigma: WOAT Support * Fixed public key extraction from dns record Co-authored-by: Aleksander Machniak <alec@alec.pl> Co-authored-by: Christian Mollekopf <mollekopf@apheleia-it.ch>
-rw-r--r--plugins/enigma/config.inc.php.dist5
-rw-r--r--plugins/enigma/lib/enigma_engine.php93
-rw-r--r--plugins/enigma/lib/enigma_subkey.php12
-rw-r--r--program/lib/Roundcube/rcube_message.php10
4 files changed, 108 insertions, 12 deletions
diff --git a/plugins/enigma/config.inc.php.dist b/plugins/enigma/config.inc.php.dist
index a5a5233c2..d654c764d 100644
--- a/plugins/enigma/config.inc.php.dist
+++ b/plugins/enigma/config.inc.php.dist
@@ -78,3 +78,8 @@ $config['enigma_passwordless'] = false;
// - enigma_options_lock = ['sign']
// - dont_override = ['enigma_sign_all']
$config['enigma_options_lock'] = [];
+
+// 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 9fe453669..75cfde1a0 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 = [];
public $decryptions = [];
@@ -272,6 +273,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) {
@@ -380,6 +384,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)
@@ -881,6 +896,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);
@@ -905,6 +925,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);
@@ -1020,19 +1045,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;
}
}
+ // Use the most recent one
+ 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) {
@@ -1442,4 +1473,58 @@ class enigma_engine
);
}
}
+
+ /**
+ * 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/plugins/enigma/lib/enigma_subkey.php b/plugins/enigma/lib/enigma_subkey.php
index ffdb3e8ce..014ab7de3 100644
--- a/plugins/enigma/lib/enigma_subkey.php
+++ b/plugins/enigma/lib/enigma_subkey.php
@@ -93,12 +93,18 @@ class enigma_subkey
/**
* Returns subkey creation date-time string
*
- * @return string|null
+ * @param bool $asInt Return the date as an integer
+ *
+ * @return string|null|int
*/
- function get_creation_date()
+ function get_creation_date($asInt = false)
{
if (empty($this->created)) {
- return null;
+ return $asInt ? 0 : null;
+ }
+
+ if ($asInt) {
+ return (int) $this->created->format('U');
}
$date_format = rcube::get_instance()->config->get('date_format', 'Y-m-d');
diff --git a/program/lib/Roundcube/rcube_message.php b/program/lib/Roundcube/rcube_message.php
index 6fd0d6f24..d95fc6c16 100644
--- a/program/lib/Roundcube/rcube_message.php
+++ b/program/lib/Roundcube/rcube_message.php
@@ -124,6 +124,11 @@ class rcube_message
)
];
+ $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);
@@ -132,11 +137,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', ['object' => $this]);
}