summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorRobin Appelman <icewind@owncloud.com>2016-05-30 15:44:19 +0200
committerArthur Schiwon <blizzz@arthur-schiwon.de>2016-06-09 14:00:01 +0200
commitbee918693a70427efc2f33034176e89d7a776bc3 (patch)
tree58a1ebb24c8b4deea8507db3e6d800c15b8cc726 /lib
parenta6134a6d2f4407cb0fa8948877cd7d6e7064d370 (diff)
downloadnextcloud-server-bee918693a70427efc2f33034176e89d7a776bc3.tar.gz
nextcloud-server-bee918693a70427efc2f33034176e89d7a776bc3.zip
dissalow symlinks in local storages that point outside the datadir
Diffstat (limited to 'lib')
-rw-r--r--lib/private/Files/Storage/Local.php30
-rw-r--r--lib/private/legacy/helper.php4
2 files changed, 32 insertions, 2 deletions
diff --git a/lib/private/Files/Storage/Local.php b/lib/private/Files/Storage/Local.php
index acd4c3b4838..005b5f9ab91 100644
--- a/lib/private/Files/Storage/Local.php
+++ b/lib/private/Files/Storage/Local.php
@@ -33,20 +33,31 @@
*/
namespace OC\Files\Storage;
+
+use OCP\Files\ForbiddenException;
+
/**
* for local filestore, we only have to map the paths
*/
class Local extends \OC\Files\Storage\Common {
protected $datadir;
+ protected $dataDirLength;
+
+ protected $allowSymlinks = false;
+
+ protected $realDataDir;
+
public function __construct($arguments) {
if (!isset($arguments['datadir']) || !is_string($arguments['datadir'])) {
throw new \InvalidArgumentException('No data directory set for local storage');
}
$this->datadir = $arguments['datadir'];
+ $this->realDataDir = rtrim(realpath($this->datadir), '/') . '/';
if (substr($this->datadir, -1) !== '/') {
$this->datadir .= '/';
}
+ $this->dataDirLength = strlen($this->realDataDir);
}
public function __destruct() {
@@ -337,10 +348,27 @@ class Local extends \OC\Files\Storage\Common {
*
* @param string $path
* @return string
+ * @throws ForbiddenException
*/
public function getSourcePath($path) {
$fullPath = $this->datadir . $path;
- return $fullPath;
+ if ($this->allowSymlinks || $path === '') {
+ return $fullPath;
+ }
+ $pathToResolve = $fullPath;
+ $realPath = realpath($pathToResolve);
+ while ($realPath === false) { // for non existing files check the parent directory
+ $pathToResolve = dirname($pathToResolve);
+ $realPath = realpath($pathToResolve);
+ }
+ if ($realPath) {
+ $realPath = $realPath . '/';
+ }
+ if (substr($realPath, 0, $this->dataDirLength) === $this->realDataDir) {
+ return $fullPath;
+ } else {
+ throw new ForbiddenException("Following symlinks is not allowed ('$fullPath' -> '$realPath' not inside '{$this->realDataDir}')", false);
+ }
}
/**
diff --git a/lib/private/legacy/helper.php b/lib/private/legacy/helper.php
index f107d47faf7..21fb3cbc5ab 100644
--- a/lib/private/legacy/helper.php
+++ b/lib/private/legacy/helper.php
@@ -206,7 +206,9 @@ class OC_Helper {
foreach ($files as $fileInfo) {
/** @var SplFileInfo $fileInfo */
- if ($fileInfo->isDir()) {
+ if ($fileInfo->isLink()) {
+ unlink($fileInfo->getPathname());
+ } else if ($fileInfo->isDir()) {
rmdir($fileInfo->getRealPath());
} else {
unlink($fileInfo->getRealPath());