From 037af6890fe6fdb84a08d3c86083e847c90ec0ad Mon Sep 17 00:00:00 2001
From: Aleksander Machniak <alec@alec.pl>
Date: Tue, 22 Oct 2013 08:17:26 -0400
Subject: [PATCH] Fix vulnerability in handling _session argument of utils/save-prefs (#1489382)

---
 program/lib/Roundcube/rcube_imap_generic.php |   75 +++++++++++++++++++++++++------------
 1 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/program/lib/Roundcube/rcube_imap_generic.php b/program/lib/Roundcube/rcube_imap_generic.php
index ddde684..1b28c3b 100644
--- a/program/lib/Roundcube/rcube_imap_generic.php
+++ b/program/lib/Roundcube/rcube_imap_generic.php
@@ -702,18 +702,11 @@
      */
     function connect($host, $user, $password, $options=null)
     {
-        // set options
-        if (is_array($options)) {
-            $this->prefs = $options;
-        }
-        // set auth method
-        if (!empty($this->prefs['auth_type'])) {
-            $auth_method = strtoupper($this->prefs['auth_type']);
-        } else {
-            $auth_method = 'CHECK';
-        }
+        // configure
+        $this->set_prefs($options);
 
-        $result = false;
+        $auth_method = $this->prefs['auth_type'];
+        $result      = false;
 
         // initialize connection
         $this->error    = '';
@@ -889,6 +882,31 @@
         $this->closeConnection();
 
         return false;
+    }
+
+    /**
+     * Initializes environment
+     */
+    protected function set_prefs($prefs)
+    {
+        // set preferences
+        if (is_array($prefs)) {
+            $this->prefs = $prefs;
+        }
+
+        // set auth method
+        if (!empty($this->prefs['auth_type'])) {
+            $this->prefs['auth_type'] = strtoupper($this->prefs['auth_type']);
+        }
+        else {
+            $this->prefs['auth_type'] = 'CHECK';
+        }
+
+        // additional message flags
+        if (!empty($this->prefs['message_flags'])) {
+            $this->flags = array_merge($this->flags, $this->prefs['message_flags']);
+            unset($this->prefs['message_flags']);
+        }
     }
 
     /**
@@ -2130,14 +2148,18 @@
                     else if ($name == 'RFC822') {
                         $result[$id]->body = $value;
                     }
-                    else if ($name == 'BODY') {
-                        $body = $this->tokenizeResponse($line, 1);
-                        if ($value[0] == 'HEADER.FIELDS')
-                            $headers = $body;
-                        else if (!empty($value))
-                            $result[$id]->bodypart[$value[0]] = $body;
+                    else if (stripos($name, 'BODY[') === 0) {
+                        $name = str_replace(']', '', substr($name, 5));
+
+                        if ($name == 'HEADER.FIELDS') {
+                            // skip ']' after headers list
+                            $this->tokenizeResponse($line, 1);
+                            $headers = $this->tokenizeResponse($line, 1);
+                        }
+                        else if (strlen($name))
+                            $result[$id]->bodypart[$name] = $value;
                         else
-                            $result[$id]->body = $body;
+                            $result[$id]->body = $value;
                     }
                 }
 
@@ -2505,7 +2527,11 @@
                 $prev  = '';
                 $found = true;
 
-                while ($bytes > 0) {
+                // empty body
+                if (!$bytes) {
+                    $result = '';
+                }
+                else while ($bytes > 0) {
                     $line = $this->readLine(8192);
 
                     if ($line === NULL) {
@@ -2980,7 +3006,7 @@
         }
 
         foreach ($entries as $name => $value) {
-            $entries[$name] = $this->escape($name) . ' ' . $this->escape($value);
+            $entries[$name] = $this->escape($name) . ' ' . $this->escape($value, true);
         }
 
         $entries = implode(' ', $entries);
@@ -3477,25 +3503,24 @@
 
             // Parenthesized list
             case '(':
-            case '[':
                 $str = substr($str, 1);
                 $result[] = self::tokenizeResponse($str);
                 break;
             case ')':
-            case ']':
                 $str = substr($str, 1);
                 return $result;
                 break;
 
-            // String atom, number, NIL, *, %
+            // String atom, number, astring, NIL, *, %
             default:
                 // empty string
                 if ($str === '' || $str === null) {
                     break 2;
                 }
 
-                // excluded chars: SP, CTL, ), [, ]
-                if (preg_match('/^([^\x00-\x20\x29\x5B\x5D\x7F]+)/', $str, $m)) {
+                // excluded chars: SP, CTL, ), DEL
+                // we do not exclude [ and ] (#1489223)
+                if (preg_match('/^([^\x00-\x20\x29\x7F]+)/', $str, $m)) {
                     $result[] = $m[1] == 'NIL' ? NULL : $m[1];
                     $str = substr($str, strlen($m[1]));
                 }

--
Gitblit v1.9.1