[Pkg-roundcube-maintainers] CVE-2023-47272/roundcube: {bullseye, bookworm}-security uploads

Guilhem Moulin guilhem at debian.org
Tue Nov 28 22:27:57 GMT 2023


Dear security team,

I'd like to propose the attach debdiffs to fix CVE-2023-47272/roundcube.

Bullseye and Bookworm have respectively been following upstream's LTS
(1.4) and stable (1.6) branch.  Upstream has not released 1.4.16 yet so
I backported the fix from the release-1.4 branch for Bullseye.   However
for Bookworm I imported new bugfix/security upstream release 1.6.5 like
for previous security fixes.

Both 1.4.15+dfsg.1-1~deb11u2 and 1.6.5+dfsg-1~deb12u1 have been tested.
(Also upstream's new unit tests are run at build time.)

Cheers,
-- 
Guilhem.
-------------- next part --------------
diffstat for roundcube-1.4.15+dfsg.1 roundcube-1.4.15+dfsg.1

 changelog                    |    8 +
 patches/CVE-2023-47272.patch |  226 +++++++++++++++++++++++++++++++++++++++++++
 patches/series               |    1 
 3 files changed, 235 insertions(+)

diff -Nru roundcube-1.4.15+dfsg.1/debian/changelog roundcube-1.4.15+dfsg.1/debian/changelog
--- roundcube-1.4.15+dfsg.1/debian/changelog	2023-10-18 23:40:57.000000000 +0200
+++ roundcube-1.4.15+dfsg.1/debian/changelog	2023-11-28 15:49:21.000000000 +0100
@@ -1,3 +1,11 @@
+roundcube (1.4.15+dfsg.1-1~deb11u2) bullseye-security; urgency=high
+
+  * Fix CVE-2023-47272: Cross-site scripting (XSS) vulnerability in setting
+    Content-Type/Content-Disposition for attachment preview/download.
+    (Closes: #1055421)
+
+ -- Guilhem Moulin <guilhem at debian.org>  Tue, 28 Nov 2023 15:49:21 +0100
+
 roundcube (1.4.15+dfsg.1-1~deb11u1) bullseye-security; urgency=high
 
   * New security/bugfix upstream release:
diff -Nru roundcube-1.4.15+dfsg.1/debian/patches/CVE-2023-47272.patch roundcube-1.4.15+dfsg.1/debian/patches/CVE-2023-47272.patch
--- roundcube-1.4.15+dfsg.1/debian/patches/CVE-2023-47272.patch	1970-01-01 01:00:00.000000000 +0100
+++ roundcube-1.4.15+dfsg.1/debian/patches/CVE-2023-47272.patch	2023-11-28 15:49:21.000000000 +0100
@@ -0,0 +1,226 @@
+From: Aleksander Machniak <alec at alec.pl>
+Date: Sat, 4 Nov 2023 17:52:00 +0100
+Subject: Fix cross-site scripting (XSS) vulnerability in setting
+ Content-Type/Content-Disposition for attachment preview/download
+
+Thanks to rehme.infosec for reporting the issues.
+
+Origin: https://github.com/roundcube/roundcubemail/commit/bf599fe1cfbb9a6a13681524fd27e85aeb1f549a
+Bug-Debian: https://security-tracker.debian.org/tracker/CVE-2023-47272
+Bug-Debian: https://bugs.debian.org/1055421
+---
+ program/lib/Roundcube/rcube_charset.php | 12 ++++++++
+ program/lib/Roundcube/rcube_imap.php    |  5 ++++
+ program/lib/Roundcube/rcube_output.php  | 53 +++++++++++++++++++++++----------
+ program/steps/mail/viewsource.inc       | 18 ++++++-----
+ tests/Framework/Charset.php             | 30 ++++++++++++++++++-
+ 5 files changed, 95 insertions(+), 23 deletions(-)
+
+diff --git a/program/lib/Roundcube/rcube_charset.php b/program/lib/Roundcube/rcube_charset.php
+index 88eb600..1f69e11 100644
+--- a/program/lib/Roundcube/rcube_charset.php
++++ b/program/lib/Roundcube/rcube_charset.php
+@@ -182,6 +182,18 @@ class rcube_charset
+         throw new ErrorException($errstr, 0, $errno);
+     }
+ 
++    /**
++     * Validate character set identifier.
++     *
++     * @param string $input Character set identifier
++     *
++     * @return bool True if valid, False if not valid
++     */
++    public static function is_valid($input)
++    {
++        return is_string($input) && preg_match('|^[a-zA-Z0-9_./:#-]{2,32}$|', $input) > 0;
++    }
++
+     /**
+      * Parse and validate charset name string.
+      * Sometimes charset string is malformed, there are also charset aliases,
+diff --git a/program/lib/Roundcube/rcube_imap.php b/program/lib/Roundcube/rcube_imap.php
+index 714ba33..c1eebe1 100644
+--- a/program/lib/Roundcube/rcube_imap.php
++++ b/program/lib/Roundcube/rcube_imap.php
+@@ -2129,6 +2129,11 @@ class rcube_imap extends rcube_storage
+             $struct->charset = $mime_headers->charset;
+         }
+ 
++        // Sanitize charset for security
++        if ($struct->charset && !rcube_charset::is_valid($struct->charset)) {
++            $struct->charset = '';
++        }
++
+         // read content encoding
+         if (!empty($part[5])) {
+             $struct->encoding = strtolower($part[5]);
+diff --git a/program/lib/Roundcube/rcube_output.php b/program/lib/Roundcube/rcube_output.php
+index 27acc70..f24c47f 100644
+--- a/program/lib/Roundcube/rcube_output.php
++++ b/program/lib/Roundcube/rcube_output.php
+@@ -212,7 +212,7 @@ abstract class rcube_output
+     }
+ 
+     /**
+-     * Send headers related to file downloads
++     * Send headers related to file downloads.
+      *
+      * @param string $filename File name
+      * @param array  $params   Optional parameters:
+@@ -225,31 +225,54 @@ abstract class rcube_output
+      */
+     public function download_headers($filename, $params = array())
+     {
++        // For security reasons we validate type, filename and charset params.
++        // Some HTTP servers might drop a header that is malformed or very long, this then
++        // can lead to web browsers unintentionally executing javascript code in the body.
++
+         if (empty($params['disposition'])) {
+             $params['disposition'] = 'attachment';
+         }
+ 
+-        if ($params['disposition'] == 'inline' && stripos($params['type'], 'text') === 0) {
+-            $params['type'] .= '; charset=' . ($params['type_charset'] ?: $this->charset);
+-        }
+-
+-        header("Content-Type: " . ($params['type'] ?: "application/octet-stream"));
++        $ctype       = 'application/octet-stream';
++        $disposition = $params['disposition'];
+ 
+-        if ($params['disposition'] == 'attachment' && $this->browser->ie) {
+-            header("Content-Type: application/force-download");
++        if (!empty($params['type']) && is_string($params['type']) && strlen($params['type']) < 256
++            && preg_match('/^[a-z0-9!#$&.+^_-]+\/[a-z0-9!#$&.+^_-]+$/i', $params['type'])
++        ) {
++            $ctype = $params['type'];
+         }
+ 
+-        $disposition = "Content-Disposition: " . $params['disposition'];
++        if ($disposition == 'inline' && stripos($ctype, 'text') === 0) {
++            $charset = $this->charset;
++            if (!empty($params['type_charset']) && rcube_charset::is_valid($params['type_charset'])) {
++                $charset = $params['type_charset'];
++            }
+ 
+-        // For non-ascii characters we'll use RFC2231 syntax
+-        if (!preg_match('/[^a-zA-Z0-9_.:,?;@+ -]/', $filename)) {
+-            $disposition .= sprintf("; filename=\"%s\"", $filename);
++            $ctype .= "; charset={$charset}";
+         }
+-        else {
+-            $disposition .= sprintf("; filename*=%s''%s", $params['charset'] ?: $this->charset, rawurlencode($filename));
++
++        if (is_string($filename) && strlen($filename) > 0 && strlen($filename) <= 1024) {
++            // For non-ascii characters we'll use RFC2231 syntax
++            if (!preg_match('/[^a-zA-Z0-9_.:,?;@+ -]/', $filename)) {
++                $disposition .= "; filename=\"{$filename}\"";
++            }
++            else {
++                $filename = rawurlencode($filename);
++                $charset  = $this->charset;
++                if (!empty($params['charset']) && rcube_charset::is_valid($params['charset'])) {
++                    $charset = $params['charset'];
++                }
++
++                $disposition .= "; filename*={$charset}''{$filename}";
++            }
+         }
+ 
+-        header($disposition);
++        header("Content-Disposition: {$disposition}");
++        header("Content-Type: {$ctype}");
++
++        if ($params['disposition'] == 'attachment' && $this->browser->ie) {
++            header("Content-Type: application/force-download");
++        }
+ 
+         if (isset($params['length'])) {
+             header("Content-Length: " . $params['length']);
+diff --git a/program/steps/mail/viewsource.inc b/program/steps/mail/viewsource.inc
+index 532ea07..91b1703 100644
+--- a/program/steps/mail/viewsource.inc
++++ b/program/steps/mail/viewsource.inc
+@@ -34,23 +34,27 @@ if ($uid = rcube_utils::get_input_value('_uid', rcube_utils::INPUT_GET)) {
+         $headers = $RCMAIL->storage->get_message_headers($uid);
+     }
+ 
+-    $charset = $headers->charset ?: $RCMAIL->config->get('default_charset');
++    $charset  = $headers->charset ?: $RCMAIL->config->get('default_charset');
++    $filename = '';
++    $params   = array(
++        'type'         => 'text/plain',
++        'type_charset' => $charset,
++    );
+ 
+     if (!empty($_GET['_save'])) {
+         $subject  = rcube_mime::decode_header($headers->subject, $headers->charset);
+         $filename = rcmail_filename_from_subject(mb_substr($subject, 0, 128));
+         $filename = ($filename ?: $uid)  . '.eml';
+ 
+-        $RCMAIL->output->download_headers($filename, array(
+-                'length'       => $headers->size,
+-                'type'         => 'text/plain',
+-                'type_charset' => $charset,
+-        ));
++        $params['length'] = $headers->size;
++        $params['disposition'] = 'attachment';
+     }
+     else {
+-        header("Content-Type: text/plain; charset={$charset}");
++        $params['disposition'] = 'inline';
+     }
+ 
++    $RCMAIL->output->download_headers($filename, $params);
++
+     if (isset($message)) {
+         $message->get_part_body($part_id, empty($_GET['_save']), 0, -1);
+     }
+diff --git a/tests/Framework/Charset.php b/tests/Framework/Charset.php
+index d141aa6..c74f670 100644
+--- a/tests/Framework/Charset.php
++++ b/tests/Framework/Charset.php
+@@ -9,7 +9,6 @@
+  */
+ class Framework_Charset extends \PHPUnit\Framework\TestCase
+ {
+-
+     /**
+      * Data for test_clean()
+      */
+@@ -40,6 +39,35 @@ class Framework_Charset extends \PHPUnit\Framework\TestCase
+         $this->assertDoesNotMatchRegularExpression('/\xD0\xD0/', rcube_charset::clean($bogus));
+     }
+ 
++    /**
++     * Data for test_is_valid()
++     */
++    function data_is_valid()
++    {
++        $list = [];
++        foreach (mb_list_encodings() as $charset) {
++            $list[] = [$charset, true];
++        }
++
++        return array_merge($list, [
++            ['', false],
++            ['a', false],
++            ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', false],
++            [null, false],
++
++            ['TCVN5712-1:1993', true],
++            ['JUS_I.B1.002', true],
++        ]);
++    }
++
++    /**
++     * @dataProvider data_is_valid
++     */
++    function test_is_valid($input, $result)
++    {
++        $this->assertSame($result, rcube_charset::is_valid($input));
++    }
++
+     /**
+      * Data for test_parse_charset()
+      */
diff -Nru roundcube-1.4.15+dfsg.1/debian/patches/series roundcube-1.4.15+dfsg.1/debian/patches/series
--- roundcube-1.4.15+dfsg.1/debian/patches/series	2023-10-18 23:40:57.000000000 +0200
+++ roundcube-1.4.15+dfsg.1/debian/patches/series	2023-11-28 15:49:21.000000000 +0100
@@ -19,3 +19,4 @@
 hint-at-which-packages-needs-installing-under-PHP8.patch
 fix-Framework_Washtml-test_wash_xss_tests.patch
 bump-upstream-version.patch
+CVE-2023-47272.patch
-------------- next part --------------
diffstat for roundcube-1.6.4+dfsg roundcube-1.6.5+dfsg

 CHANGELOG.md                                                         |   17 ++-
 Makefile                                                             |    2 
 config/defaults.inc.php                                              |    8 -
 debian/changelog                                                     |   18 +++
 debian/patches/default-charset-utf8.patch                            |    2 
 debian/patches/use-enchant.patch                                     |    2 
 plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php             |   15 ++
 plugins/managesieve/localization/ja_JP.inc                           |    4 
 program/actions/mail/viewsource.php                                  |   18 ++-
 program/actions/utils/error.php                                      |    1 
 program/lib/Roundcube/rcube_charset.php                              |   12 ++
 program/lib/Roundcube/rcube_imap.php                                 |   13 +-
 program/lib/Roundcube/rcube_imap_generic.php                         |   12 ++
 program/lib/Roundcube/rcube_message.php                              |   10 +
 program/lib/Roundcube/rcube_message_part.php                         |    7 +
 program/lib/Roundcube/rcube_output.php                               |   54 ++++++----
 program/lib/Roundcube/rcube_smtp.php                                 |    7 -
 public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php |   15 ++
 public_html/plugins/managesieve/localization/ja_JP.inc               |    4 
 tests/Framework/Charset.php                                          |   30 +++++
 20 files changed, 191 insertions(+), 60 deletions(-)

diff -Nru roundcube-1.6.4+dfsg/CHANGELOG.md roundcube-1.6.5+dfsg/CHANGELOG.md
--- roundcube-1.6.4+dfsg/CHANGELOG.md	2023-10-14 18:17:17.000000000 +0200
+++ roundcube-1.6.5+dfsg/CHANGELOG.md	2023-11-04 17:52:34.000000000 +0100
@@ -2,10 +2,21 @@
 
 ## Unreleased
 
+- Fix PHP8 fatal error when parsing a malformed BODYSTRUCTURE (#9171)
+- Fix duplicated Inbox folder on IMAP servers that do not use Inbox folder with all capital letters (#9166)
+- Fix PHP warnings (#9174)
+- Fix UI issue when dealing with an invalid managesieve_default_headers value (#9175)
+- Fix bug where images attached to application/smil messages weren't displayed (#8870)
+- Fix PHP string replacement error in utils/error.php (#9185)
+- Fix regression where `smtp_user` did not allow pre/post strings before/after `%u` placeholder (#9162)
+- Fix cross-site scripting (XSS) vulnerability in setting Content-Type/Content-Disposition for attachment preview/download
+
+## Release 1.6.4
+
 - Fix PHP8 warnings (#9142, #9160)
 - Fix default 'mime.types' path on Windows (#9113)
 - Managesieve: Fix javascript error when relational or spamtest extension is not enabled (#9139)
-- Fix cross-site scripting (XSS) vulnerability in handling of SVG in HTML messages (#9168)
+- Fix cross-site scripting (XSS) vulnerability in handling of SVG in HTML messages [CVE-2023-5631] (#9168)
 
 ## Release 1.6.3
 
@@ -24,7 +35,7 @@
 - Fix "Show source" on mobile with x_frame_options = deny (#9084)
 - Fix various PHP warnings (#9098)
 - Fix deprecated use of ldap_connect() in password's ldap_simple driver (#9060)
-- Fix cross-site scripting (XSS) vulnerability in handling of linkrefs in plain text messages
+- Fix cross-site scripting (XSS) vulnerability in handling of linkrefs in plain text messages [CVE-2023-43770]
 
 ## Release 1.6.2
 
@@ -180,7 +191,7 @@
 - Fix locked SQLite database for the CLI tools (#8035)
 - Fix Makefile on Linux (#8211)
 - Fix so PHP warnings are ignored when resizing a malformed image attachment (#8387)
-- Fix various PHP8 warnings (#8392)
+- Fix various PHP8 warnings (#8392, #9193)
 - Fix mail headers injection via the subject field on mail compose (#8404)
 - Fix bug where small message/rfc822 parts could not be decoded (#8408)
 - Fix setting HTML mode on reply/forward of a signed message (#8405)
diff -Nru roundcube-1.6.4+dfsg/config/defaults.inc.php roundcube-1.6.5+dfsg/config/defaults.inc.php
--- roundcube-1.6.4+dfsg/config/defaults.inc.php	2023-10-14 18:17:17.000000000 +0200
+++ roundcube-1.6.5+dfsg/config/defaults.inc.php	2023-11-04 17:52:34.000000000 +0100
@@ -270,12 +270,12 @@
 // of IMAP host (no prefix or port) and SMTP server e.g. ['imap.example.com' => 'smtp.example.net']
 $config['smtp_host'] = 'localhost:587';
 
-// SMTP username (if required) if you use %u as the username Roundcube
-// will use the current username for login
+// SMTP username (if required)
+// Note: %u variable will be replaced with current user's username
 $config['smtp_user'] = '%u';
 
-// SMTP password (if required) if you use %p as the password Roundcube
-// will use the current user's password for login
+// SMTP password (if required)
+// Note: When set to '%p' current user's password will be used
 $config['smtp_pass'] = '%p';
 
 // SMTP AUTH type (DIGEST-MD5, CRAM-MD5, LOGIN, PLAIN or empty to use
diff -Nru roundcube-1.6.4+dfsg/debian/changelog roundcube-1.6.5+dfsg/debian/changelog
--- roundcube-1.6.4+dfsg/debian/changelog	2023-10-19 00:20:52.000000000 +0200
+++ roundcube-1.6.5+dfsg/debian/changelog	2023-11-28 16:10:54.000000000 +0100
@@ -1,3 +1,21 @@
+roundcube (1.6.5+dfsg-1~deb12u1) bookworm-security; urgency=high
+
+  * New upstream security and bugfix release:
+    + Fix CVE-2023-47272: Cross-site scripting (XSS) vulnerability in setting
+      Content-Type/Content-Disposition for attachment preview/download.
+      (Closes: #1055421)
+    + Fix PHP8 fatal error when parsing a malformed BODYSTRUCTURE.
+    + Fix UI issue when dealing with an invalid managesieve_default_headers
+      value.
+    + Fix bug where images attached to application/smil messages weren't
+      displayed.
+    + Fix PHP8 warnings.
+    + Fix regression where ‘smtp_user’ did not allow pre/post strings
+      before/after ‘%u’ placeholder.
+  * Refresh d/patches.
+
+ -- Guilhem Moulin <guilhem at debian.org>  Tue, 28 Nov 2023 16:10:54 +0100
+
 roundcube (1.6.4+dfsg-1~deb12u1) bookworm-security; urgency=high
 
   * New upstream security and bugfix release:
diff -Nru roundcube-1.6.4+dfsg/debian/patches/default-charset-utf8.patch roundcube-1.6.5+dfsg/debian/patches/default-charset-utf8.patch
--- roundcube-1.6.4+dfsg/debian/patches/default-charset-utf8.patch	2023-10-19 00:20:52.000000000 +0200
+++ roundcube-1.6.5+dfsg/debian/patches/default-charset-utf8.patch	2023-11-28 16:10:54.000000000 +0100
@@ -8,7 +8,7 @@
  1 file changed, 1 insertion(+), 1 deletion(-)
 
 diff --git a/config/defaults.inc.php b/config/defaults.inc.php
-index 00f1a8d..4338ec9 100644
+index aa2b1c0..65a8214 100644
 --- a/config/defaults.inc.php
 +++ b/config/defaults.inc.php
 @@ -1259,7 +1259,7 @@ $config['collected_senders'] = true;
diff -Nru roundcube-1.6.4+dfsg/debian/patches/use-enchant.patch roundcube-1.6.5+dfsg/debian/patches/use-enchant.patch
--- roundcube-1.6.4+dfsg/debian/patches/use-enchant.patch	2023-10-19 00:20:52.000000000 +0200
+++ roundcube-1.6.5+dfsg/debian/patches/use-enchant.patch	2023-11-28 16:10:54.000000000 +0100
@@ -10,7 +10,7 @@
  1 file changed, 2 insertions(+), 1 deletion(-)
 
 diff --git a/config/defaults.inc.php b/config/defaults.inc.php
-index 85481d2..00f1a8d 100644
+index bfa09da..aa2b1c0 100644
 --- a/config/defaults.inc.php
 +++ b/config/defaults.inc.php
 @@ -939,7 +939,8 @@ $config['spellcheck_dictionary'] = false;
diff -Nru roundcube-1.6.4+dfsg/Makefile roundcube-1.6.5+dfsg/Makefile
--- roundcube-1.6.4+dfsg/Makefile	2023-10-14 18:17:17.000000000 +0200
+++ roundcube-1.6.5+dfsg/Makefile	2023-11-04 17:52:34.000000000 +0100
@@ -69,7 +69,7 @@
 	(cd roundcubemail-git; find . -name '.gitignore' | xargs rm -f)
 	(cd roundcubemail-git; find . -name '.travis.yml' | xargs rm -f)
 	(cd roundcubemail-git; rm -rf tests plugins/*/tests .git* .tx* .ci* .editorconfig* index-test.php Dockerfile Makefile)
-	(cd roundcubemail-git; $(SEDI) 's/1.6-git/$(VERSION)/' index.php public_html/index.php program/include/iniset.php program/lib/Roundcube/bootstrap.php)
+	(cd roundcubemail-git; $(SEDI) 's/1.6-git/$(VERSION)/' index.php public_html/index.php installer/index.php program/include/iniset.php program/lib/Roundcube/bootstrap.php)
 	(cd roundcubemail-git; $(SEDI) 's/# Unreleased/# Release $(VERSION)'/ CHANGELOG.md)
 
 buildtools: /tmp/composer.phar
diff -Nru roundcube-1.6.4+dfsg/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php roundcube-1.6.5+dfsg/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php
--- roundcube-1.6.4+dfsg/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php	2023-10-14 18:17:17.000000000 +0200
+++ roundcube-1.6.5+dfsg/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php	2023-11-04 17:52:34.000000000 +0100
@@ -727,7 +727,7 @@
                         $this->form['tests'][$i]['type'] = $sizeop;
                         $this->form['tests'][$i]['arg']  = $sizetarget;
 
-                        if ($sizetarget == '') {
+                        if ($sizetarget === '') {
                             $this->errors['tests'][$i]['sizetarget'] = $this->plugin->gettext('cannotbeempty');
                         }
                         else if (!preg_match('/^[0-9]+(K|M|G)?$/i', $sizetarget.$sizeitem, $m)) {
@@ -1067,8 +1067,8 @@
 
                 case 'redirect':
                 case 'redirect_copy':
-                    $target = $this->strip_value(isset($act_targets[$idx]) ? $act_targets[$idx] : null);
-                    $domain = $this->strip_value(isset($domain_targets[$idx]) ? $domain_targets[$idx] : null);
+                    $target = $this->strip_value($act_targets[$idx] ?? null);
+                    $domain = $this->strip_value($domain_targets[$idx] ?? null);
 
                     // force one of the configured domains
                     $domains = (array) $this->rc->config->get('managesieve_domains');
@@ -1082,7 +1082,7 @@
 
                     $this->form['actions'][$i]['target'] = $target;
 
-                    if ($target == '') {
+                    if ($target === '') {
                         $this->errors['actions'][$i]['target'] = $this->plugin->gettext('cannotbeempty');
                     }
                     else if (!rcube_utils::check_email($target)) {
@@ -2776,6 +2776,8 @@
             return $str;
         }
 
+        $str = (string) $str;
+
         if (!$allow_html) {
             $str = strip_tags($str);
         }
@@ -3275,6 +3277,11 @@
     {
         $default = ['Subject', 'From', 'To'];
         $headers = (array) $this->rc->config->get('managesieve_default_headers', $default);
+
+        if (empty($headers) || $headers === ['']) {
+            $headers = $default;
+        }
+
         $keys    = array_map('strtolower', $headers);
         $headers = array_combine($keys, $headers);
 
diff -Nru roundcube-1.6.4+dfsg/plugins/managesieve/localization/ja_JP.inc roundcube-1.6.5+dfsg/plugins/managesieve/localization/ja_JP.inc
--- roundcube-1.6.4+dfsg/plugins/managesieve/localization/ja_JP.inc	2023-10-14 18:17:17.000000000 +0200
+++ roundcube-1.6.5+dfsg/plugins/managesieve/localization/ja_JP.inc	2023-11-04 17:52:34.000000000 +0100
@@ -267,8 +267,8 @@
 $messages['setcreated'] = 'フィルターセットを作成しました。';
 $messages['activateerror'] = '選択したフィルターを有効にできません。サーバーでエラーが発生しました。';
 $messages['deactivateerror'] = '選択したフィルターを無効にできません。サーバーでエラーが発生しました。';
-$messages['deactivated'] = 'フィルターを有効にしました。';
-$messages['activated'] = 'フィルターを無効にしました。';
+$messages['deactivated'] = 'フィルターを無効にしました。';
+$messages['activated'] = 'フィルターを有効にしました。';
 $messages['moved'] = 'フィルターを移動しました。';
 $messages['moveerror'] = '選択したフィルターを移動できません。サーバーでエラーが発生しました。';
 $messages['nametoolong'] = '名前が長すぎます。';
diff -Nru roundcube-1.6.4+dfsg/program/actions/mail/viewsource.php roundcube-1.6.5+dfsg/program/actions/mail/viewsource.php
--- roundcube-1.6.4+dfsg/program/actions/mail/viewsource.php	2023-10-14 18:17:17.000000000 +0200
+++ roundcube-1.6.5+dfsg/program/actions/mail/viewsource.php	2023-11-04 17:52:34.000000000 +0100
@@ -45,26 +45,30 @@
                 $headers = $rcmail->storage->get_message_headers($uid);
             }
 
-            $charset = $headers->charset ?: $rcmail->config->get('default_charset', RCUBE_CHARSET);
+            $charset  = $headers->charset ?: $rcmail->config->get('default_charset', RCUBE_CHARSET);
+            $filename = '';
+            $params   = [
+                'type'         => 'text/plain',
+                'type_charset' => $charset,
+            ];
 
             if (!empty($_GET['_save'])) {
                 $subject  = rcube_mime::decode_header($headers->subject, $headers->charset);
                 $filename = self::filename_from_subject(mb_substr($subject, 0, 128));
                 $filename = ($filename ?: $uid)  . '.eml';
 
-                $rcmail->output->download_headers($filename, [
-                        'length'       => $headers->size,
-                        'type'         => 'text/plain',
-                        'type_charset' => $charset,
-                ]);
+                $params['length'] = $headers->size;
+                $params['disposition'] = 'attachment';
             }
             else {
                 // Make sure it works in an iframe (#9084)
                 $rcmail->output->page_headers();
 
-                header("Content-Type: text/plain; charset={$charset}");
+                $params['disposition'] = 'inline';
             }
 
+            $rcmail->output->download_headers($filename, $params);
+
             if (isset($part_id) && isset($message)) {
                 $message->get_part_body($part_id, empty($_GET['_save']), 0, -1);
             }
diff -Nru roundcube-1.6.4+dfsg/program/actions/utils/error.php roundcube-1.6.5+dfsg/program/actions/utils/error.php
--- roundcube-1.6.4+dfsg/program/actions/utils/error.php	2023-10-14 18:17:17.000000000 +0200
+++ roundcube-1.6.5+dfsg/program/actions/utils/error.php	2023-11-04 17:52:34.000000000 +0100
@@ -134,7 +134,6 @@
 
         $output = '<!doctype html><html><head>'
             . '<title>' . $product . ':: ERROR</title>'
-            . '<link rel="stylesheet" type="text/css" href="skins/$skin/common.css" />'
             . '</head><body>'
             . '<table border="0" cellspacing="0" cellpadding="0" width="100%" height="80%">'
             . '<tr><td align="center">' . $page_content . '</td></tr>'
diff -Nru roundcube-1.6.4+dfsg/program/lib/Roundcube/rcube_charset.php roundcube-1.6.5+dfsg/program/lib/Roundcube/rcube_charset.php
--- roundcube-1.6.4+dfsg/program/lib/Roundcube/rcube_charset.php	2023-10-14 18:17:17.000000000 +0200
+++ roundcube-1.6.5+dfsg/program/lib/Roundcube/rcube_charset.php	2023-11-04 17:52:34.000000000 +0100
@@ -179,6 +179,18 @@
     ];
 
     /**
+     * Validate character set identifier.
+     *
+     * @param string $input Character set identifier
+     *
+     * @return bool True if valid, False if not valid
+     */
+    public static function is_valid($input)
+    {
+        return is_string($input) && preg_match('|^[a-zA-Z0-9_./:#-]{2,32}$|', $input) > 0;
+    }
+
+    /**
      * Parse and validate charset name string.
      * Sometimes charset string is malformed, there are also charset aliases,
      * but we need strict names for charset conversion (specially utf8 class)
diff -Nru roundcube-1.6.4+dfsg/program/lib/Roundcube/rcube_imap_generic.php roundcube-1.6.5+dfsg/program/lib/Roundcube/rcube_imap_generic.php
--- roundcube-1.6.4+dfsg/program/lib/Roundcube/rcube_imap_generic.php	2023-10-14 18:17:17.000000000 +0200
+++ roundcube-1.6.5+dfsg/program/lib/Roundcube/rcube_imap_generic.php	2023-11-04 17:52:34.000000000 +0100
@@ -1650,6 +1650,18 @@
                         $mailbox = rtrim($mailbox, $delim);
                     }
 
+                    // Make it easier for the client to deal with INBOX folder
+                    // by always returning the word with all capital letters
+                    if (strlen($mailbox) == 5
+                        && ($mailbox[0] == 'i' || $mailbox[0] == 'I')
+                        && ($mailbox[1] == 'n' || $mailbox[1] == 'N')
+                        && ($mailbox[2] == 'b' || $mailbox[2] == 'B')
+                        && ($mailbox[3] == 'o' || $mailbox[3] == 'O')
+                        && ($mailbox[4] == 'x' || $mailbox[4] == 'X')
+                    ) {
+                        $mailbox = 'INBOX';
+                    }
+
                     // Add to result array
                     if (!$lstatus) {
                         $folders[] = $mailbox;
diff -Nru roundcube-1.6.4+dfsg/program/lib/Roundcube/rcube_imap.php roundcube-1.6.5+dfsg/program/lib/Roundcube/rcube_imap.php
--- roundcube-1.6.4+dfsg/program/lib/Roundcube/rcube_imap.php	2023-10-14 18:17:17.000000000 +0200
+++ roundcube-1.6.5+dfsg/program/lib/Roundcube/rcube_imap.php	2023-11-04 17:52:34.000000000 +0100
@@ -2163,8 +2163,13 @@
             $struct->charset = $mime_headers->charset;
         }
 
+        // Sanitize charset for security
+        if ($struct->charset && !rcube_charset::is_valid($struct->charset)) {
+            $struct->charset = '';
+        }
+
         // read content encoding
-        if (!empty($part[5])) {
+        if (!empty($part[5]) && !is_array($part[5])) {
             $struct->encoding = strtolower($part[5]);
             $struct->headers['content-transfer-encoding'] = $struct->encoding;
         }
@@ -2234,6 +2239,7 @@
         if (!empty($part[3])) {
             $struct->content_id = $struct->headers['content-id'] = trim($part[3]);
 
+            // FIXME: This is not the best idea. We should get rid of this at some point
             if (empty($struct->disposition)) {
                 $struct->disposition = 'inline';
             }
@@ -2862,11 +2868,6 @@
             return false;
         }
 
-        if (!$this->conn->data['READ-WRITE']) {
-            $this->conn->setError(rcube_imap_generic::ERROR_READONLY, "Folder is read-only");
-            return false;
-        }
-
         // CLOSE(+SELECT) should be faster than EXPUNGE
         if (empty($uids) || !empty($all_mode)) {
             $result = $this->conn->close();
diff -Nru roundcube-1.6.4+dfsg/program/lib/Roundcube/rcube_message_part.php roundcube-1.6.5+dfsg/program/lib/Roundcube/rcube_message_part.php
--- roundcube-1.6.4+dfsg/program/lib/Roundcube/rcube_message_part.php	2023-10-14 18:17:17.000000000 +0200
+++ roundcube-1.6.5+dfsg/program/lib/Roundcube/rcube_message_part.php	2023-11-04 17:52:34.000000000 +0100
@@ -56,6 +56,13 @@
     public $mimetype = 'text/plain';
 
     /**
+     * Real content type (for fake parts)
+     *
+     * @var string|null
+     */
+    public $realtype;
+
+    /**
      * Real content type of a message/rfc822 part
      *
      * @var string
diff -Nru roundcube-1.6.4+dfsg/program/lib/Roundcube/rcube_message.php roundcube-1.6.5+dfsg/program/lib/Roundcube/rcube_message.php
--- roundcube-1.6.4+dfsg/program/lib/Roundcube/rcube_message.php	2023-10-14 18:17:17.000000000 +0200
+++ roundcube-1.6.5+dfsg/program/lib/Roundcube/rcube_message.php	2023-11-04 17:52:34.000000000 +0100
@@ -932,6 +932,16 @@
                         $mail_part->content_location .= $mail_part->headers['content-location'];
                     }
 
+                    // application/smil message's are known to use inline images that aren't really inline (#8870)
+                    // TODO: This code probably does not belong here. I.e. we should not default to
+                    // disposition=inline in rcube_imap::structure_part().
+                    if ($primary_type === 'image'
+                        && !empty($structure->ctype_parameters['type'])
+                        && $structure->ctype_parameters['type'] === 'application/smil'
+                    ) {
+                        $mail_part->disposition = 'attachment';
+                    }
+
                     // part belongs to a related message and is linked
                     // Note: mixed is not supposed to contain inline images, but we've found such examples (#5905)
                     if (
diff -Nru roundcube-1.6.4+dfsg/program/lib/Roundcube/rcube_output.php roundcube-1.6.5+dfsg/program/lib/Roundcube/rcube_output.php
--- roundcube-1.6.4+dfsg/program/lib/Roundcube/rcube_output.php	2023-10-14 18:17:17.000000000 +0200
+++ roundcube-1.6.5+dfsg/program/lib/Roundcube/rcube_output.php	2023-11-04 17:52:34.000000000 +0100
@@ -212,7 +212,7 @@
     }
 
     /**
-     * Send headers related to file downloads
+     * Send headers related to file downloads.
      *
      * @param string $filename File name
      * @param array  $params   Optional parameters:
@@ -225,34 +225,54 @@
      */
     public function download_headers($filename, $params = [])
     {
+        // For security reasons we validate type, filename and charset params.
+        // Some HTTP servers might drop a header that is malformed or very long, this then
+        // can lead to web browsers unintentionally executing javascript code in the body.
+
         if (empty($params['disposition'])) {
             $params['disposition'] = 'attachment';
         }
 
-        if ($params['disposition'] == 'inline' && stripos($params['type'], 'text') === 0) {
-            $params['type'] .= '; charset=' . ($params['type_charset'] ?: $this->charset);
+        $ctype       = 'application/octet-stream';
+        $disposition = $params['disposition'];
+
+        if (!empty($params['type']) && is_string($params['type']) && strlen($params['type']) < 256
+            && preg_match('/^[a-z0-9!#$&.+^_-]+\/[a-z0-9!#$&.+^_-]+$/i', $params['type'])
+        ) {
+            $ctype = $params['type'];
         }
 
-        header("Content-Type: " . (!empty($params['type']) ? $params['type'] : "application/octet-stream"));
+        if ($disposition == 'inline' && stripos($ctype, 'text') === 0) {
+            $charset = $this->charset;
+            if (!empty($params['type_charset']) && rcube_charset::is_valid($params['type_charset'])) {
+                $charset = $params['type_charset'];
+            }
 
-        if ($params['disposition'] == 'attachment' && $this->browser->ie) {
-            header("Content-Type: application/force-download");
+            $ctype .= "; charset={$charset}";
         }
 
-        $disposition = "Content-Disposition: " . $params['disposition'];
+        if (is_string($filename) && strlen($filename) > 0 && strlen($filename) <= 1024) {
+            // For non-ascii characters we'll use RFC2231 syntax
+            if (!preg_match('/[^a-zA-Z0-9_.:,?;@+ -]/', $filename)) {
+                $disposition .= "; filename=\"{$filename}\"";
+            }
+            else {
+                $filename = rawurlencode($filename);
+                $charset  = $this->charset;
+                if (!empty($params['charset']) && rcube_charset::is_valid($params['charset'])) {
+                    $charset = $params['charset'];
+                }
 
-        // For non-ascii characters we'll use RFC2231 syntax
-        if (!preg_match('/[^a-zA-Z0-9_.:,?;@+ -]/', $filename)) {
-            $disposition .= sprintf("; filename=\"%s\"", $filename);
-        }
-        else {
-            $disposition .= sprintf("; filename*=%s''%s",
-                !empty($params['charset']) ? $params['charset'] : $this->charset,
-                rawurlencode($filename)
-            );
+                $disposition .= "; filename*={$charset}''{$filename}";
+            }
         }
 
-        header($disposition);
+        header("Content-Disposition: {$disposition}");
+        header("Content-Type: {$ctype}");
+
+        if ($params['disposition'] == 'attachment' && $this->browser->ie) {
+            header("Content-Type: application/force-download");
+        }
 
         if (isset($params['length'])) {
             header("Content-Length: " . $params['length']);
diff -Nru roundcube-1.6.4+dfsg/program/lib/Roundcube/rcube_smtp.php roundcube-1.6.5+dfsg/program/lib/Roundcube/rcube_smtp.php
--- roundcube-1.6.4+dfsg/program/lib/Roundcube/rcube_smtp.php	2023-10-14 18:17:17.000000000 +0200
+++ roundcube-1.6.5+dfsg/program/lib/Roundcube/rcube_smtp.php	2023-11-04 17:52:34.000000000 +0100
@@ -170,18 +170,13 @@
             }
         }
 
-        if ($CONFIG['smtp_user'] == '%u') {
-            $smtp_user = (string) $rcube->get_user_name();
-        } else {
-            $smtp_user = $CONFIG['smtp_user'];
-        }
-
         if ($CONFIG['smtp_pass'] == '%p') {
             $smtp_pass = (string) $rcube->get_user_password();
         } else {
             $smtp_pass = $CONFIG['smtp_pass'];
         }
 
+        $smtp_user      = str_replace('%u', (string) $rcube->get_user_name(), $CONFIG['smtp_user']);
         $smtp_auth_type = $CONFIG['smtp_auth_type'] ?: null;
         $smtp_authz     = null;
 
diff -Nru roundcube-1.6.4+dfsg/public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php roundcube-1.6.5+dfsg/public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php
--- roundcube-1.6.4+dfsg/public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php	2023-10-14 18:17:17.000000000 +0200
+++ roundcube-1.6.5+dfsg/public_html/plugins/managesieve/lib/Roundcube/rcube_sieve_engine.php	2023-11-04 17:52:34.000000000 +0100
@@ -727,7 +727,7 @@
                         $this->form['tests'][$i]['type'] = $sizeop;
                         $this->form['tests'][$i]['arg']  = $sizetarget;
 
-                        if ($sizetarget == '') {
+                        if ($sizetarget === '') {
                             $this->errors['tests'][$i]['sizetarget'] = $this->plugin->gettext('cannotbeempty');
                         }
                         else if (!preg_match('/^[0-9]+(K|M|G)?$/i', $sizetarget.$sizeitem, $m)) {
@@ -1067,8 +1067,8 @@
 
                 case 'redirect':
                 case 'redirect_copy':
-                    $target = $this->strip_value(isset($act_targets[$idx]) ? $act_targets[$idx] : null);
-                    $domain = $this->strip_value(isset($domain_targets[$idx]) ? $domain_targets[$idx] : null);
+                    $target = $this->strip_value($act_targets[$idx] ?? null);
+                    $domain = $this->strip_value($domain_targets[$idx] ?? null);
 
                     // force one of the configured domains
                     $domains = (array) $this->rc->config->get('managesieve_domains');
@@ -1082,7 +1082,7 @@
 
                     $this->form['actions'][$i]['target'] = $target;
 
-                    if ($target == '') {
+                    if ($target === '') {
                         $this->errors['actions'][$i]['target'] = $this->plugin->gettext('cannotbeempty');
                     }
                     else if (!rcube_utils::check_email($target)) {
@@ -2776,6 +2776,8 @@
             return $str;
         }
 
+        $str = (string) $str;
+
         if (!$allow_html) {
             $str = strip_tags($str);
         }
@@ -3275,6 +3277,11 @@
     {
         $default = ['Subject', 'From', 'To'];
         $headers = (array) $this->rc->config->get('managesieve_default_headers', $default);
+
+        if (empty($headers) || $headers === ['']) {
+            $headers = $default;
+        }
+
         $keys    = array_map('strtolower', $headers);
         $headers = array_combine($keys, $headers);
 
diff -Nru roundcube-1.6.4+dfsg/public_html/plugins/managesieve/localization/ja_JP.inc roundcube-1.6.5+dfsg/public_html/plugins/managesieve/localization/ja_JP.inc
--- roundcube-1.6.4+dfsg/public_html/plugins/managesieve/localization/ja_JP.inc	2023-10-14 18:17:17.000000000 +0200
+++ roundcube-1.6.5+dfsg/public_html/plugins/managesieve/localization/ja_JP.inc	2023-11-04 17:52:34.000000000 +0100
@@ -267,8 +267,8 @@
 $messages['setcreated'] = 'フィルターセットを作成しました。';
 $messages['activateerror'] = '選択したフィルターを有効にできません。サーバーでエラーが発生しました。';
 $messages['deactivateerror'] = '選択したフィルターを無効にできません。サーバーでエラーが発生しました。';
-$messages['deactivated'] = 'フィルターを有効にしました。';
-$messages['activated'] = 'フィルターを無効にしました。';
+$messages['deactivated'] = 'フィルターを無効にしました。';
+$messages['activated'] = 'フィルターを有効にしました。';
 $messages['moved'] = 'フィルターを移動しました。';
 $messages['moveerror'] = '選択したフィルターを移動できません。サーバーでエラーが発生しました。';
 $messages['nametoolong'] = '名前が長すぎます。';
diff -Nru roundcube-1.6.4+dfsg/tests/Framework/Charset.php roundcube-1.6.5+dfsg/tests/Framework/Charset.php
--- roundcube-1.6.4+dfsg/tests/Framework/Charset.php	2023-10-14 18:17:17.000000000 +0200
+++ roundcube-1.6.5+dfsg/tests/Framework/Charset.php	2023-11-04 17:52:34.000000000 +0100
@@ -8,7 +8,6 @@
  */
 class Framework_Charset extends PHPUnit\Framework\TestCase
 {
-
     /**
      * Data for test_clean()
      */
@@ -34,6 +33,35 @@
     }
 
     /**
+     * Data for test_is_valid()
+     */
+    function data_is_valid()
+    {
+        $list = [];
+        foreach (mb_list_encodings() as $charset) {
+            $list[] = [$charset, true];
+        }
+
+        return array_merge($list, [
+            ['', false],
+            ['a', false],
+            ['aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', false],
+            [null, false],
+
+            ['TCVN5712-1:1993', true],
+            ['JUS_I.B1.002', true],
+        ]);
+    }
+
+    /**
+     * @dataProvider data_is_valid
+     */
+    function test_is_valid($input, $result)
+    {
+        $this->assertSame($result, rcube_charset::is_valid($input));
+    }
+
+    /**
      * Data for test_parse_charset()
      */
     function data_parse_charset()
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://alioth-lists.debian.net/pipermail/pkg-roundcube-maintainers/attachments/20231128/69fdff7c/attachment-0001.sig>


More information about the Pkg-roundcube-maintainers mailing list