Merge pull request #4969 from owncloud/fixing-4043-master
adding privilege check on move and rename operations
This commit is contained in:
commit
5899485ca1
|
@ -78,6 +78,11 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||||
*/
|
*/
|
||||||
public function setName($name) {
|
public function setName($name) {
|
||||||
|
|
||||||
|
// rename is only allowed if the update privilege is granted
|
||||||
|
if (!\OC\Files\Filesystem::isUpdatable($this->path)) {
|
||||||
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
|
}
|
||||||
|
|
||||||
list($parentPath, ) = Sabre_DAV_URLUtil::splitPath($this->path);
|
list($parentPath, ) = Sabre_DAV_URLUtil::splitPath($this->path);
|
||||||
list(, $newName) = Sabre_DAV_URLUtil::splitPath($name);
|
list(, $newName) = Sabre_DAV_URLUtil::splitPath($name);
|
||||||
|
|
||||||
|
@ -135,6 +140,12 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
|
||||||
* Even if the modification time is set to a custom value the access time is set to now.
|
* Even if the modification time is set to a custom value the access time is set to now.
|
||||||
*/
|
*/
|
||||||
public function touch($mtime) {
|
public function touch($mtime) {
|
||||||
|
|
||||||
|
// touch is only allowed if the update privilege is granted
|
||||||
|
if (!\OC\Files\Filesystem::isUpdatable($this->path)) {
|
||||||
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
|
}
|
||||||
|
|
||||||
\OC\Files\Filesystem::touch($this->path, $mtime);
|
\OC\Files\Filesystem::touch($this->path, $mtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,14 @@ namespace OC\Connector\Sabre;
|
||||||
use OC\Files\Filesystem;
|
use OC\Files\Filesystem;
|
||||||
|
|
||||||
class ObjectTree extends \Sabre_DAV_ObjectTree {
|
class ObjectTree extends \Sabre_DAV_ObjectTree {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* keep this public to allow mock injection during unit test
|
||||||
|
*
|
||||||
|
* @var \OC\Files\View
|
||||||
|
*/
|
||||||
|
public $fileView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the INode object for the requested path
|
* Returns the INode object for the requested path
|
||||||
*
|
*
|
||||||
|
@ -21,14 +29,16 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
|
||||||
public function getNodeForPath($path) {
|
public function getNodeForPath($path) {
|
||||||
|
|
||||||
$path = trim($path, '/');
|
$path = trim($path, '/');
|
||||||
if (isset($this->cache[$path])) return $this->cache[$path];
|
if (isset($this->cache[$path])) {
|
||||||
|
return $this->cache[$path];
|
||||||
|
}
|
||||||
|
|
||||||
// Is it the root node?
|
// Is it the root node?
|
||||||
if (!strlen($path)) {
|
if (!strlen($path)) {
|
||||||
return $this->rootNode;
|
return $this->rootNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
$info = Filesystem::getFileInfo($path);
|
$info = $this->getFileView()->getFileInfo($path);
|
||||||
|
|
||||||
if (!$info) {
|
if (!$info) {
|
||||||
throw new \Sabre_DAV_Exception_NotFound('File with name ' . $path . ' could not be located');
|
throw new \Sabre_DAV_Exception_NotFound('File with name ' . $path . ' could not be located');
|
||||||
|
@ -64,7 +74,25 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
|
||||||
list($sourceDir,) = \Sabre_DAV_URLUtil::splitPath($sourcePath);
|
list($sourceDir,) = \Sabre_DAV_URLUtil::splitPath($sourcePath);
|
||||||
list($destinationDir,) = \Sabre_DAV_URLUtil::splitPath($destinationPath);
|
list($destinationDir,) = \Sabre_DAV_URLUtil::splitPath($destinationPath);
|
||||||
|
|
||||||
Filesystem::rename($sourcePath, $destinationPath);
|
// check update privileges
|
||||||
|
$fs = $this->getFileView();
|
||||||
|
if (!$fs->isUpdatable($sourcePath)) {
|
||||||
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
|
}
|
||||||
|
if ($sourceDir !== $destinationDir) {
|
||||||
|
// for a full move we need update privileges on sourcePath and sourceDir as well as destinationDir
|
||||||
|
if (!$fs->isUpdatable($sourceDir)) {
|
||||||
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
|
}
|
||||||
|
if (!$fs->isUpdatable($destinationDir)) {
|
||||||
|
throw new \Sabre_DAV_Exception_Forbidden();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$renameOkay = $fs->rename($sourcePath, $destinationPath);
|
||||||
|
if (!$renameOkay) {
|
||||||
|
throw new \Sabre_DAV_Exception_Forbidden('');
|
||||||
|
}
|
||||||
|
|
||||||
$this->markDirty($sourceDir);
|
$this->markDirty($sourceDir);
|
||||||
$this->markDirty($destinationDir);
|
$this->markDirty($destinationDir);
|
||||||
|
@ -101,4 +129,14 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
|
||||||
list($destinationDir,) = \Sabre_DAV_URLUtil::splitPath($destination);
|
list($destinationDir,) = \Sabre_DAV_URLUtil::splitPath($destination);
|
||||||
$this->markDirty($destinationDir);
|
$this->markDirty($destinationDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \OC\Files\View
|
||||||
|
*/
|
||||||
|
public function getFileView() {
|
||||||
|
if (is_null($this->fileView)) {
|
||||||
|
$this->fileView = \OC\Files\Filesystem::getView();
|
||||||
|
}
|
||||||
|
return $this->fileView;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Copyright (c) 2013 Thomas Müller <thomas.mueller@tmit.eu>
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Test\OC\Connector\Sabre;
|
||||||
|
|
||||||
|
|
||||||
|
use OC_Connector_Sabre_Directory;
|
||||||
|
use PHPUnit_Framework_TestCase;
|
||||||
|
use Sabre_DAV_Exception_Forbidden;
|
||||||
|
|
||||||
|
class TestDoubleFileView extends \OC\Files\View{
|
||||||
|
|
||||||
|
public function __construct($updatables, $canRename = true) {
|
||||||
|
$this->updatables = $updatables;
|
||||||
|
$this->canRename = $canRename;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isUpdatable($path) {
|
||||||
|
return $this->updatables[$path];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rename($path1, $path2) {
|
||||||
|
return $this->canRename;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ObjectTree extends PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider moveFailedProvider
|
||||||
|
* @expectedException Sabre_DAV_Exception_Forbidden
|
||||||
|
*/
|
||||||
|
public function testMoveFailed($source, $dest, $updatables) {
|
||||||
|
$this->moveTest($source, $dest, $updatables);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider moveSuccessProvider
|
||||||
|
*/
|
||||||
|
public function testMoveSuccess($source, $dest, $updatables) {
|
||||||
|
$this->moveTest($source, $dest, $updatables);
|
||||||
|
$this->assertTrue(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveFailedProvider() {
|
||||||
|
return array(
|
||||||
|
array('a/b', 'a/c', array('a' => false, 'a/b' => false, 'a/c' => false)),
|
||||||
|
array('a/b', 'b/b', array('a' => false, 'a/b' => false, 'b' => false, 'b/b' => false)),
|
||||||
|
array('a/b', 'b/b', array('a' => false, 'a/b' => true, 'b' => false, 'b/b' => false)),
|
||||||
|
array('a/b', 'b/b', array('a' => true, 'a/b' => true, 'b' => false, 'b/b' => false)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function moveSuccessProvider() {
|
||||||
|
return array(
|
||||||
|
array('a/b', 'a/c', array('a' => false, 'a/b' => true, 'a/c' => false)),
|
||||||
|
array('a/b', 'b/b', array('a' => true, 'a/b' => true, 'b' => true, 'b/b' => false)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $source
|
||||||
|
* @param $dest
|
||||||
|
* @param $updatables
|
||||||
|
*/
|
||||||
|
private function moveTest($source, $dest, $updatables) {
|
||||||
|
$rootDir = new OC_Connector_Sabre_Directory('');
|
||||||
|
$objectTree = $this->getMock('\OC\Connector\Sabre\ObjectTree',
|
||||||
|
array('nodeExists', 'getNodeForPath'),
|
||||||
|
array($rootDir));
|
||||||
|
|
||||||
|
$objectTree->expects($this->once())
|
||||||
|
->method('getNodeForPath')
|
||||||
|
->with($this->identicalTo($source))
|
||||||
|
->will($this->returnValue(false));
|
||||||
|
|
||||||
|
/** @var $objectTree \OC\Connector\Sabre\ObjectTree */
|
||||||
|
$objectTree->fileView = new TestDoubleFileView($updatables);
|
||||||
|
$objectTree->move($source, $dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue