diff plugins/filesystem_attachments/filesystem_attachments.php @ 8:bf99236cc5cd

try to recover from upgrade fail
author Charlie Root
date Sat, 29 Dec 2018 07:07:34 -0500
parents 4681f974d28b
children
line wrap: on
line diff
--- a/plugins/filesystem_attachments/filesystem_attachments.php	Sat Dec 29 06:32:49 2018 -0500
+++ b/plugins/filesystem_attachments/filesystem_attachments.php	Sat Dec 29 07:07:34 2018 -0500
@@ -7,12 +7,19 @@
  * attachments of messages currently being composed, writing attachments
  * to disk when drafts with attachments are re-opened and writing
  * attachments to disk for inline display in current html compositions.
+ * It also handles uploaded files for other uses, so not only attachments.
  *
  * Developers may wish to extend this class when creating attachment
  * handler plugins:
  *   require_once('plugins/filesystem_attachments/filesystem_attachments.php');
  *   class myCustom_attachments extends filesystem_attachments
  *
+ * Note for developers: It is plugin's responsibility to care about security.
+ * So, e.g. if the plugin is asked about some file path it should check
+ * if it's really the storage path of the plugin and not e.g. /etc/passwd.
+ * It is done by setting 'status' flag on every plugin hook it uses.
+ * Roundcube core will trust the returned path if status=true.
+ *
  * @license GNU GPLv3+
  * @author Ziba Scott <ziba@umich.edu>
  * @author Thomas Bruederli <roundcube@gmail.com>
@@ -50,7 +57,7 @@
     {
         $args['status'] = false;
         $group  = $args['group'];
-        $rcmail = rcmail::get_instance();
+        $rcmail = rcube::get_instance();
 
         // use common temp dir for file uploads
         $temp_dir = $rcmail->config->get('temp_dir');
@@ -78,7 +85,7 @@
         $args['status'] = false;
 
         if (!$args['path']) {
-            $rcmail   = rcmail::get_instance();
+            $rcmail   = rcube::get_instance();
             $temp_dir = $rcmail->config->get('temp_dir');
             $tmp_path = tempnam($temp_dir, 'rcmAttmnt');
 
@@ -107,18 +114,18 @@
      */
     function remove($args)
     {
-        $args['status'] = @unlink($args['path']);
+        $args['status'] = $this->verify_path($args['path']) && @unlink($args['path']);
         return $args;
     }
 
     /**
      * When composing an html message, image attachments may be shown
      * For this plugin, the file is already in place, just check for
-     * the existance of the proper metadata
+     * the existence of the proper metadata
      */
     function display($args)
     {
-        $args['status'] = file_exists($args['path']);
+        $args['status'] = $this->verify_path($args['path']) && file_exists($args['path']);
         return $args;
     }
 
@@ -129,6 +136,10 @@
      */
     function get($args)
     {
+        if (!$this->verify_path($args['path'])) {
+            $args['path'] = null;
+        }
+
         return $args;
     }
 
@@ -147,7 +158,7 @@
                 }
 
                 foreach ((array)$files as $filename) {
-                    if(file_exists($filename)) {
+                    if (file_exists($filename)) {
                         unlink($filename);
                     }
                 }
@@ -160,7 +171,7 @@
 
     function file_id()
     {
-        $userid = rcmail::get_instance()->user->ID;
+        $userid = rcube::get_instance()->user->ID;
         list($usec, $sec) = explode(' ', microtime());
         $id = preg_replace('/[^0-9]/', '', $userid . $sec . $usec);
 
@@ -182,4 +193,34 @@
             }
         }
     }
+
+    /**
+     * For security we'll always verify the file path stored in session,
+     * as session entries can be faked in various ways e.g. #6026.
+     * We allow only files in Roundcube temp dir
+     */
+    protected function verify_path($path)
+    {
+        if (empty($path)) {
+            return false;
+        }
+
+        $rcmail    = rcube::get_instance();
+        $temp_dir  = $rcmail->config->get('temp_dir');
+        $file_path = pathinfo($path, PATHINFO_DIRNAME);
+
+        if ($temp_dir !== $file_path) {
+            rcube::raise_error(array(
+                    'code'    => 403,
+                    'file'    => __FILE__,
+                    'line'    => __LINE__,
+                    'message' => sprintf("%s can't read %s (not in temp_dir)",
+                        $rcmail->get_user_name(), substr($path, 0, 512))
+                ), true, false);
+
+            return false;
+        }
+
+        return true;
+    }
 }