File git_2025_03-10.diff of Package roundcubemail-plugin-authres_status
diff --git a/authres_status.php b/authres_status.php
index f022688..c400316 100755
--- a/authres_status.php
+++ b/authres_status.php
@@ -336,54 +336,96 @@ class authres_status extends rcube_plugin
if (($results = ($headers->others['x-dkim-authentication-results'] ?? '')) && strpos($results, 'none') !== false) {
$status = self::STATUS_NOSIG;
} else {
- if ($headers->others['authentication-results'] ?? null) {
+ $hasAuthenticationResultHeaders = (bool)$headers->others['authentication-results'];
+ if ($hasAuthenticationResultHeaders) {
$results = $this->rfc5451_extract_authresheader($headers->others['authentication-results']);
$status = 0;
$title = '';
foreach ($results as $result) {
$status = $status | (isset(self::$RFC5451_authentication_results[$result['result']]) ? self::$RFC5451_authentication_results[$result['result']] : self::STATUS_FAIL);
-
$title .= ($title ? '; ' : '') . $result['title'];
}
- if ($status == self::STATUS_PASS) {
- /* Verify if its an author's domain signature or a third party
- */
- if (preg_match("/[@]([a-zA-Z0-9]+([.][a-zA-Z0-9]+)?\.[a-zA-Z]{2,4})/", $headers->from, $m)) {
+ if ($status === self::STATUS_PASS || $status === self::STATUS_THIRD) {
+ // Extract emailaddress from From: header
+ $authorEmail = '';
+ $authorDomain = '';
+
+ if (preg_match('/<([^>]+)>/', $headers->from, $m)) {
+ $authorEmail = $m[1];
+ }
+
+ if (str_contains($authorEmail, '@')) {
+ $authorDomain = explode('@', $authorEmail, 2)[1];
+ }
+
+ if ($authorDomain) {
$title = '';
- $authorDomain = $m[1];
$authorDomainFound = false;
+ /* Verify if its an author's domain signature or a third party
+ */
foreach ($results as $result) {
- if ($result['method'] == 'dkim' || $result['method'] == 'domainkeys') {
- if (is_array($result['props']) && isset($result['props']['header'])) {
- $pvalue = '';
-
- // d is required, but still not always present
- if (isset($result['props']['header']['d'])) {
- $pvalue = $result['props']['header']['d'];
- } elseif (isset($result['props']['header']['i'])) {
- $pvalue = substr($result['props']['header']['i'], strpos($result['props']['header']['i'], '@') + 1);
- }
+ if (
+ !in_array($result['method'], array('auth', 'dkim', 'dmarc', 'domainkeys'))
+ || !is_array($result['props'])
+ ) {
+ continue;
+ }
- if ($pvalue == $authorDomain || substr($authorDomain, -1 * strlen($pvalue)) == $pvalue) {
- $authorDomainFound = true;
+ if ($result['method'] === 'auth') {
+ $method_props = $result['props']['smtp'];
+ } else {
+ $method_props = $result['props']['header'];
+ }
- if ($status != self::STATUS_PASS) {
- $status = self::STATUS_PASS;
- $title = $result['title'];
- } else {
- $title.= ($title ? '; ' : '') . $result['title'];
- }
- } else {
- if ($status == self::STATUS_THIRD) {
- $title .= '; ' . $this->gettext('for') . ' ' . $pvalue . ' ' . $this->gettext('by') . ' ' . $result['title'];
- } elseif (!$authorDomainFound) {
- $status = self::STATUS_THIRD;
- $title = $pvalue . ' ' . $this->gettext('by') . ' ' . $result['title'];
- }
- }
+ if (!isset($method_props)) {
+ continue;
+ }
+
+ $pvalue = ''; // pvalue refers to the definition in RFC-5451 (p10)
+
+ if (isset($method_props['d'])) {
+ // d is required, but still not always present
+ $pvalue = $method_props['d'];
+ } elseif (isset($method_props['i'])) {
+ $pvalue = substr($method_props['i'], strpos($method_props['i'], '@') + 1);
+ } elseif ($result['method'] === 'dmarc' && isset($method_props['from'])) {
+ // from is used with dmarc results
+ $pvalue = $method_props['from'];
+ } elseif ($result['method'] === 'auth' && isset($method_props['mailfrom'])) {
+ // mailfrom is used with smtp.auth results (RFC-4954)
+ $pvalue = $method_props['mailfrom'];
+ }
+
+ $isAuthorValid = false;
+ if ($result['method'] === 'auth') {
+ $isAuthorValid = $pvalue === $authorEmail;
+ } else {
+ $isAuthorValid = $pvalue === $authorDomain;
+
+ if (!$isAuthorValid) {
+ // Check if authorDomain is a subdomain of the signee
+ $isAuthorValid = str_ends_with($authorDomain, '.' . str_replace('@', '', $pvalue));
+ }
+ }
+
+ if ($isAuthorValid) {
+ $authorDomainFound = true;
+
+ if ($status != self::STATUS_PASS) {
+ $status = self::STATUS_PASS;
+ $title = $result['title'];
+ } else {
+ $title.= ($title ? '; ' : '') . $result['title'];
+ }
+ } else {
+ if ($status == self::STATUS_THIRD) {
+ $title .= '; ' . $this->gettext('for') . ' ' . $pvalue . ' ' . $this->gettext('by') . ' ' . $result['title'];
+ } elseif (!$authorDomainFound) {
+ $status = self::STATUS_THIRD;
+ $title = $pvalue . ' ' . $this->gettext('by') . ' ' . $result['title'];
}
}
}
@@ -421,12 +463,12 @@ class authres_status extends rcube_plugin
}
}
}
- } elseif ($headers->others['dkim-signature'] ?? null || $headers->others['domainkey-signature'] ?? null) {
+ } elseif (($headers->others['dkim-signature'] ?? null) || ($headers->others['domainkey-signature'] ?? null)) {
$status = 0;
if ($uid) {
$rcmail = rcmail::get_instance();
- if ($headers->others['dkim-signature'] ?? null && $rcmail->config->get('use_fallback_verifier')) {
+ if (($headers->others['dkim-signature'] ?? null) && ($rcmail->config->get('use_fallback_verifier'))) {
if (!class_exists('Crypt_RSA')) {
$autoload = require __DIR__ . "/../../vendor/autoload.php";
$autoload->loadClass('Crypt_RSA'); // Preload for use in DKIM_Verify
@@ -478,7 +520,7 @@ class authres_status extends rcube_plugin
} elseif ($status == self::STATUS_NORES) {
$image = 'status_nores.png';
$alt = 'noauthresults';
- } elseif ($status == self::STATUS_PASS) {
+ } elseif (($status == self::STATUS_PASS) || ($status == self::STATUS_PASS + self::STATUS_NOSIG)) {
$image = 'status_pass.png';
$alt = 'signaturepass';
} else {