* Filemanager/WebDAV: generally deny user to delete directories /, /home, /apps, /templates (last 2 incl. subdirectories)

This commit is contained in:
Ralf Becker 2016-08-18 10:03:53 +02:00
parent 73dbaa0dfb
commit f1f8c4e98d
5 changed files with 64 additions and 9 deletions

View File

@ -723,23 +723,42 @@ class Vfs
return $value > (int) substr($argument,1);
}
/**
* Check if given directory is protected (user not allowed to remove or rename)
*
* Following directorys are protected:
* - /
* - /apps incl. subdirectories
* - /home
* - /templates incl. subdirectories
*
* @param string $dir path or url
* @return boolean true for protected dirs, false otherwise
*/
static function isProtectedDir($dir)
{
if ($dir[0] != '/') $dir = self::parse_url($dir, PHP_URL_PATH);
return preg_match('#^/(apps(/[^/]+)?|home|templates(/[^/]+)?)?/*$#', $dir) > 0;
}
/**
* Recursiv remove all given url's, including it's content if they are files
*
* @param string|array $urls url or array of url's
* @param boolean $allow_urls =false allow to use url's, default no only pathes (to stay within the vfs)
* @throws Exception\AssertionFailed when trainig to remove /, /apps or /home
* @throws Vfs\Exception\ProtectedDirectory if trying to delete a protected directory, see Vfs::isProtected()
* @return array
*/
static function remove($urls,$allow_urls=false)
{
//error_log(__METHOD__.'('.array2string($urls).')');
// some precaution to never allow to (recursivly) remove /, /apps or /home
foreach((array)$urls as $url)
{
if (preg_match('/^\/?(home|apps|)\/*$/',self::parse_url($url,PHP_URL_PATH)))
// some precaution to never allow to (recursivly) remove /, /apps or /home, see Vfs::isProtected()
if (self::isProtectedDir($url))
{
throw new Exception\AssertionFailed(__METHOD__.'('.array2string($urls).") Cautiously rejecting to remove folder '$url'!");
throw new Vfs\Exception\ProtectedDirectory("Deleting protected directory '$url' rejected!");
}
}
return self::find($urls, array('depth'=>true,'url'=>$allow_urls,'hidden'=>true), __CLASS__.'::_rm_rmdir');

View File

@ -0,0 +1,21 @@
<?php
/**
* EGroupware API - Exceptions
*
* @link http://www.egroupware.org
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package vfs
* @subpackage exception
* @access public
* @version $Id$
*/
namespace EGroupware\Api\Vfs\Exception;
/**
* User or code tried to delete or rename a protected directory, see Vfs::isProtectedDir
*
* This exception extends \Exception to not catch it accidently.
*/
class ProtectedDirectory extends \Exception { }

View File

@ -571,9 +571,14 @@ class StreamWrapper implements StreamWrapperIface
* @param string $path_from
* @param string $path_to
* @return boolean TRUE on success or FALSE on failure
* @throws Exception\ProtectedDirectory if trying to delete a protected directory, see Vfs::isProtected()
*/
function rename ( $path_from, $path_to )
{
if (Vfs::isProtectedDir($path_from))
{
throw new Exception\ProtectedDirectory("Renaming protected directory '$path_from' rejected!");
}
if (!($url_from = $this->resolve_url_symlinks($path_from,true,false)) ||
!($url_to = $this->resolve_url_symlinks($path_to,false)))
{
@ -665,9 +670,14 @@ class StreamWrapper implements StreamWrapperIface
* @param string $path
* @param int $options Possible values include STREAM_REPORT_ERRORS.
* @return boolean TRUE on success or FALSE on failure.
* @throws Exception\ProtectedDirectory if trying to delete a protected directory, see Vfs::isProtected()
*/
function rmdir ( $path, $options )
{
if (Vfs::isProtectedDir($path))
{
throw new Exception\ProtectedDirectory("Deleting protected directory '$path' rejected!");
}
unset($options); // not uses but required by function signature
if (!($url = $this->resolve_url_symlinks($path)))
{

View File

@ -95,7 +95,7 @@ class WebDAV extends HTTP_WebDAV_Server_Filesystem
$ret = !empty($deleted[$options['path']]);
//error_log(__METHOD__."() Vfs::remove($options[path]) returned ".array2string($deleted)." --> ".array2string($ret));
}
catch (\Exception $e) {
catch (Exception\ProtectedDirectory $e) {
return '403 Forbidden: '.$e->getMessage();
}
}
@ -221,9 +221,14 @@ class WebDAV extends HTTP_WebDAV_Server_Filesystem
}
if ($del) {
if (!rename($source, $dest)) {
return "500 Internal server error";
}
try {
if (!rename($source, $dest)) {
return "500 Internal server error";
}
}
catch (Exception\ProtectedDirectory $e) {
return "403 Forbidden: ".$e->getMessage();
}
} else {
if (is_dir($source) && $options['depth'] == 'infinity') {
$files = Vfs::find($source,array('depth' => true,'url' => true)); // depth=true: return dirs first, url=true: allow urls!

View File

@ -751,7 +751,7 @@ class filemanager_ui
// some precaution to never allow to (recursivly) remove /, /apps or /home
foreach((array)$selected as $path)
{
if (preg_match('/^\/?(home|apps|)\/*$/',$path))
if (Vfs::isProtectedDir($path))
{
$errs++;
return lang("Cautiously rejecting to remove folder '%1'!",Vfs::decodePath($path));