Skip to content
Snippets Groups Projects
Commit bd71a1b7 authored by Vincent Petry's avatar Vincent Petry
Browse files

Added file name check in webdav connector

- added file name check for the put, rename and setNames() methods which
  throw a "Bad Request" whenever invalid characters are used
- replaced \OC\Filesystem usage with $this->getFS() to be able to write
  unit tests
parent 797e0a61
No related branches found
No related tags found
No related merge requests found
...@@ -58,6 +58,11 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D ...@@ -58,6 +58,11 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
throw new \Sabre_DAV_Exception_ServiceUnavailable(); throw new \Sabre_DAV_Exception_ServiceUnavailable();
} }
$fileName = basename($this->path);
if (!\OCP\Util::isValidFileName($fileName)) {
throw new \Sabre_DAV_Exception_BadRequest();
}
// chunked handling // chunked handling
if (isset($_SERVER['HTTP_OC_CHUNKED'])) { if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
return $this->createFileChunked($data); return $this->createFileChunked($data);
...@@ -142,15 +147,16 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D ...@@ -142,15 +147,16 @@ class OC_Connector_Sabre_File extends OC_Connector_Sabre_Node implements Sabre_D
* @throws Sabre_DAV_Exception_Forbidden * @throws Sabre_DAV_Exception_Forbidden
*/ */
public function delete() { public function delete() {
$fs = $this->getFS();
if ($this->path === 'Shared') { if ($this->path === 'Shared') {
throw new \Sabre_DAV_Exception_Forbidden(); throw new \Sabre_DAV_Exception_Forbidden();
} }
if (!\OC\Files\Filesystem::isDeletable($this->path)) { if (!$fs->isDeletable($this->path)) {
throw new \Sabre_DAV_Exception_Forbidden(); throw new \Sabre_DAV_Exception_Forbidden();
} }
\OC\Files\Filesystem::unlink($this->path); $fs->unlink($this->path);
// remove properties // remove properties
$this->removeProperties(); $this->removeProperties();
......
...@@ -85,19 +85,24 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr ...@@ -85,19 +85,24 @@ abstract class OC_Connector_Sabre_Node implements Sabre_DAV_INode, Sabre_DAV_IPr
* @return void * @return void
*/ */
public function setName($name) { public function setName($name) {
$fs = $this->getFS();
// rename is only allowed if the update privilege is granted // rename is only allowed if the update privilege is granted
if (!\OC\Files\Filesystem::isUpdatable($this->path)) { if (!$fs->isUpdatable($this->path)) {
throw new \Sabre_DAV_Exception_Forbidden(); 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);
if (!\OCP\Util::isValidFileName($newName)) {
throw new \Sabre_DAV_Exception_BadRequest();
}
$newPath = $parentPath . '/' . $newName; $newPath = $parentPath . '/' . $newName;
$oldPath = $this->path; $oldPath = $this->path;
\OC\Files\Filesystem::rename($this->path, $newPath); $fs->rename($this->path, $newPath);
$this->path = $newPath; $this->path = $newPath;
......
...@@ -105,6 +105,11 @@ class ObjectTree extends \Sabre_DAV_ObjectTree { ...@@ -105,6 +105,11 @@ class ObjectTree extends \Sabre_DAV_ObjectTree {
} }
} }
$fileName = basename($destinationPath);
if (!\OCP\Util::isValidFileName($fileName)) {
throw new \Sabre_DAV_Exception_BadRequest();
}
$renameOkay = $fs->rename($sourcePath, $destinationPath); $renameOkay = $fs->rename($sourcePath, $destinationPath);
if (!$renameOkay) { if (!$renameOkay) {
throw new \Sabre_DAV_Exception_Forbidden(''); throw new \Sabre_DAV_Exception_Forbidden('');
......
...@@ -35,6 +35,46 @@ class Test_OC_Connector_Sabre_File extends PHPUnit_Framework_TestCase { ...@@ -35,6 +35,46 @@ class Test_OC_Connector_Sabre_File extends PHPUnit_Framework_TestCase {
$etag = $file->put('test data'); $etag = $file->put('test data');
} }
/**
* @expectedException Sabre_DAV_Exception_BadRequest
*/
public function testSimplePutInvalidChars() {
// setup
$file = new OC_Connector_Sabre_File('/super*star.txt');
$file->fileView = $this->getMock('\OC\Files\View', array('file_put_contents'), array(), '', FALSE);
$file->fileView->expects($this->any())->method('file_put_contents')->withAnyParameters()->will($this->returnValue(false));
// action
$etag = $file->put('test data');
}
/**
* Test setting name with setName()
*/
public function testSetName() {
// setup
$file = new OC_Connector_Sabre_File('/test.txt');
$file->fileView = $this->getMock('\OC\Files\View', array('isUpdatable'), array(), '', FALSE);
$file->fileView->expects($this->any())->method('isUpdatable')->withAnyParameters()->will($this->returnValue(true));
$etag = $file->put('test data');
$file->setName('/renamed.txt');
$this->assertTrue($file->fileView->file_exists('/renamed.txt'));
// clean up
$file->delete();
}
/**
* Test setting name with setName() with invalid chars
* @expectedException Sabre_DAV_Exception_BadRequest
*/
public function testSetNameInvalidChars() {
// setup
$file = new OC_Connector_Sabre_File('/test.txt');
$file->fileView = $this->getMock('\OC\Files\View', array('isUpdatable'), array(), '', FALSE);
$file->fileView->expects($this->any())->method('isUpdatable')->withAnyParameters()->will($this->returnValue(true));
$file->setName('/super*star.txt');
}
/** /**
* @expectedException Sabre_DAV_Exception_Forbidden * @expectedException Sabre_DAV_Exception_Forbidden
*/ */
......
...@@ -52,6 +52,20 @@ class ObjectTree extends PHPUnit_Framework_TestCase { ...@@ -52,6 +52,20 @@ class ObjectTree extends PHPUnit_Framework_TestCase {
$this->assertTrue(true); $this->assertTrue(true);
} }
/**
* @dataProvider moveFailedInvalidCharsProvider
* @expectedException Sabre_DAV_Exception_BadRequest
*/
public function testMoveFailedInvalidChars($source, $dest, $updatables, $deletables) {
$this->moveTest($source, $dest, $updatables, $deletables);
}
function moveFailedInvalidCharsProvider() {
return array(
array('a/b', 'a/c*', array('a' => false, 'a/b' => true, 'a/c*' => false), array()),
);
}
function moveFailedProvider() { function moveFailedProvider() {
return array( return array(
array('a/b', 'a/c', array('a' => false, 'a/b' => false, 'a/c' => false), array()), array('a/b', 'a/c', array('a' => false, 'a/b' => false, 'a/c' => false), array()),
...@@ -66,6 +80,8 @@ class ObjectTree extends PHPUnit_Framework_TestCase { ...@@ -66,6 +80,8 @@ class ObjectTree extends PHPUnit_Framework_TestCase {
return array( return array(
array('a/b', 'a/c', array('a' => false, 'a/b' => true, 'a/c' => false), array()), array('a/b', 'a/c', array('a' => false, 'a/b' => true, 'a/c' => false), array()),
array('a/b', 'b/b', array('a' => true, 'a/b' => true, 'b' => true, 'b/b' => false), array('a/b' => true)), array('a/b', 'b/b', array('a' => true, 'a/b' => true, 'b' => true, 'b/b' => false), array('a/b' => true)),
// older files with special chars can still be renamed to valid names
array('a/b*', 'b/b', array('a' => true, 'a/b*' => true, 'b' => true, 'b/b' => false), array('a/b*' => true)),
); );
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment