Mercurial > hg > rc2
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; + } }