Skip to content

Commit 4d65a9f

Browse files
committed
fix: improve checks for moving shares/storages into other mounts
Signed-off-by: Robin Appelman <robin@icewind.nl>
1 parent dd101dd commit 4d65a9f

File tree

1 file changed

+40
-51
lines changed

1 file changed

+40
-51
lines changed

lib/private/Files/View.php

Lines changed: 40 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use OCP\Files\InvalidCharacterInPathException;
2525
use OCP\Files\InvalidDirectoryException;
2626
use OCP\Files\InvalidPathException;
27+
use OCP\Files\Mount\IMountManager;
2728
use OCP\Files\Mount\IMountPoint;
2829
use OCP\Files\NotFoundException;
2930
use OCP\Files\ReservedWordException;
@@ -32,8 +33,6 @@
3233
use OCP\Lock\ILockingProvider;
3334
use OCP\Lock\LockedException;
3435
use OCP\Server;
35-
use OCP\Share\IManager;
36-
use OCP\Share\IShare;
3736
use Psr\Log\LoggerInterface;
3837

3938
/**
@@ -701,6 +700,9 @@ public function rename($source, $target) {
701700
throw new ForbiddenException('Moving a folder into a child folder is forbidden', false);
702701
}
703702

703+
/** @var IMountManager $mountManager */
704+
$mountManager = \OC::$server->get(IMountManager::class);
705+
704706
$targetParts = explode('/', $absolutePath2);
705707
$targetUser = $targetParts[1] ?? null;
706708
$result = false;
@@ -758,22 +760,20 @@ public function rename($source, $target) {
758760
try {
759761
$this->changeLock($target, ILockingProvider::LOCK_EXCLUSIVE, true);
760762

763+
$movedMounts = $mountManager->findIn($this->getAbsolutePath($source));
764+
761765
if ($internalPath1 === '') {
762-
if ($mount1 instanceof MoveableMount) {
763-
$sourceParentMount = $this->getMount(dirname($source));
764-
if ($sourceParentMount === $mount2 && $this->targetIsNotShared($targetUser, $absolutePath2)) {
765-
/**
766-
* @var \OC\Files\Mount\MountPoint | \OC\Files\Mount\MoveableMount $mount1
767-
*/
768-
$sourceMountPoint = $mount1->getMountPoint();
769-
$result = $mount1->moveMount($absolutePath2);
770-
$manager->moveMount($sourceMountPoint, $mount1->getMountPoint());
771-
} else {
772-
$result = false;
773-
}
774-
} else {
775-
$result = false;
776-
}
766+
$sourceParentMount = $this->getMount(dirname($source));
767+
$movedMounts[] = $mount1;
768+
$this->validateMountMove($movedMounts, $sourceParentMount, $mount2);
769+
770+
/**
771+
* @var \OC\Files\Mount\MountPoint | \OC\Files\Mount\MoveableMount $mount1
772+
*/
773+
$sourceMountPoint = $mount1->getMountPoint();
774+
$result = $mount1->moveMount($absolutePath2);
775+
$manager->moveMount($sourceMountPoint, $mount1->getMountPoint());
776+
777777
// moving a file/folder within the same mount point
778778
} elseif ($storage1 === $storage2) {
779779
if ($storage1) {
@@ -783,6 +783,7 @@ public function rename($source, $target) {
783783
}
784784
// moving a file/folder between storages (from $storage1 to $storage2)
785785
} else {
786+
$this->validateMountMove($movedMounts, $mount1, $mount2);
786787
$result = $storage2->moveFromStorage($storage1, $internalPath1, $internalPath2);
787788
}
788789

@@ -832,6 +833,28 @@ public function rename($source, $target) {
832833
return $result;
833834
}
834835

836+
private function validateMountMove(array $mounts, IMountPoint $sourceMount, IMountPoint $targetMount): void {
837+
$targetType = 'storage';
838+
if ($targetMount instanceof SharedMount) {
839+
$targetType = 'share';
840+
}
841+
$targetPath = rtrim($targetMount->getMountPoint(), '/');
842+
843+
if ($sourceMount !== $targetMount) {
844+
foreach ($mounts as $mount) {
845+
$sourcePath = rtrim($mount->getMountPoint(), '/');
846+
if (!$mount instanceof MoveableMount) {
847+
throw new ForbiddenException("Storage {$sourcePath} cannot be moved", false);
848+
}
849+
$sourceType = 'storage';
850+
if ($mount instanceof SharedMount) {
851+
$sourceType = 'share';
852+
}
853+
throw new ForbiddenException("Moving a $sourceType ($sourcePath) into another $targetType ($targetPath) is not allowed", false);
854+
}
855+
}
856+
}
857+
835858
/**
836859
* Copy a file/folder from the source path to target path
837860
*
@@ -1791,40 +1814,6 @@ private function assertPathLength($path): void {
17911814
}
17921815
}
17931816

1794-
/**
1795-
* check if it is allowed to move a mount point to a given target.
1796-
* It is not allowed to move a mount point into a different mount point or
1797-
* into an already shared folder
1798-
*/
1799-
private function targetIsNotShared(string $user, string $targetPath): bool {
1800-
$providers = [
1801-
IShare::TYPE_USER,
1802-
IShare::TYPE_GROUP,
1803-
IShare::TYPE_EMAIL,
1804-
IShare::TYPE_CIRCLE,
1805-
IShare::TYPE_ROOM,
1806-
IShare::TYPE_DECK,
1807-
IShare::TYPE_SCIENCEMESH
1808-
];
1809-
$shareManager = Server::get(IManager::class);
1810-
/** @var IShare[] $shares */
1811-
$shares = array_merge(...array_map(function (int $type) use ($shareManager, $user) {
1812-
return $shareManager->getSharesBy($user, $type);
1813-
}, $providers));
1814-
1815-
foreach ($shares as $share) {
1816-
$sharedPath = $share->getNode()->getPath();
1817-
if ($targetPath === $sharedPath || str_starts_with($targetPath, $sharedPath . '/')) {
1818-
$this->logger->debug(
1819-
'It is not allowed to move one mount point into a shared folder',
1820-
['app' => 'files']);
1821-
return false;
1822-
}
1823-
}
1824-
1825-
return true;
1826-
}
1827-
18281817
/**
18291818
* Get a fileinfo object for files that are ignored in the cache (part files)
18301819
*/

0 commit comments

Comments
 (0)