Skip to content

Commit

Permalink
fix(sharing): Move permission validation to share manager
Browse files Browse the repository at this point in the history
Signed-off-by: Ferdinand Thiessen <[email protected]>
  • Loading branch information
susnux committed Jan 31, 2025
1 parent 61edfd5 commit 2ae9954
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 6 deletions.
13 changes: 12 additions & 1 deletion lib/private/Share20/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,6 @@ protected function generalCreateChecks(IShare $share, bool $isUpdate = false) {
throw new \InvalidArgumentException('A share requires permissions');
}

$isFederatedShare = $share->getNode()->getStorage()->instanceOfStorage('\OCA\Files_Sharing\External\Storage');
$permissions = 0;

$isReshare = $share->getNode()->getOwner() && $share->getNode()->getOwner()->getUID() !== $share->getSharedBy();
Expand All @@ -305,6 +304,7 @@ protected function generalCreateChecks(IShare $share, bool $isUpdate = false) {
$isReshare = $share->getShareOwner() !== $share->getSharedBy();
}

$isFederatedShare = $share->getNode()->getStorage()->instanceOfStorage('\OCA\Files_Sharing\External\Storage');
if (!$isFederatedShare && $isReshare) {
$userMounts = array_filter($userFolder->getById($share->getNode()->getId()), function ($mount) {
// We need to filter since there might be other mountpoints that contain the file
Expand Down Expand Up @@ -349,6 +349,17 @@ protected function generalCreateChecks(IShare $share, bool $isUpdate = false) {
}
}

// Permissions must be valid
if ($share->getPermissions() < 0 || $share->getPermissions() > \OCP\Constants::PERMISSION_ALL) {
throw new \InvalidArgumentException($this->l->t('Valid permissions are required for sharing'));
}

// Single file shares should never have delete or create permissions
if (($share->getNode() instanceof File)
&& (($share->getPermissions() & (\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE)) !== 0)) {
throw new \InvalidArgumentException($this->l->t('File shares cannot have create or delete permissions'));
}

// Check that we do not share with more permissions than we have
if ($share->getPermissions() & ~$permissions) {
$path = $userFolder->getRelativePath($share->getNode()->getPath());
Expand Down
30 changes: 25 additions & 5 deletions tests/lib/Share20/ManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -690,10 +690,9 @@ public function dataGeneralChecks() {
$mount = $this->createMock(MoveableMount::class);
$limitedPermssions->method('getMountPoint')->willReturn($mount);


$data[] = [$this->createShare(null, IShare::TYPE_USER, $limitedPermssions, $user2, $user0, $user0, 31, null, null), 'Cannot increase permissions of path', true];
// increase permissions of a re-share
$data[] = [$this->createShare(null, IShare::TYPE_GROUP, $limitedPermssions, $group0, $user0, $user0, 17, null, null), 'Cannot increase permissions of path', true];
$data[] = [$this->createShare(null, IShare::TYPE_LINK, $limitedPermssions, null, $user0, $user0, 3, null, null), 'Cannot increase permissions of path', true];
$data[] = [$this->createShare(null, IShare::TYPE_USER, $limitedPermssions, $user2, $user0, $user0, 3, null, null), 'Cannot increase permissions of path', true];

$nonMoveableMountPermssions = $this->createMock(Folder::class);
$nonMoveableMountPermssions->method('isShareable')->willReturn(true);
Expand All @@ -718,6 +717,20 @@ public function dataGeneralChecks() {
$data[] = [$this->createShare(null, IShare::TYPE_GROUP, $rootFolder, $group0, $user0, $user0, 2, null, null), 'You cannot share your root folder', true];
$data[] = [$this->createShare(null, IShare::TYPE_LINK, $rootFolder, null, $user0, $user0, 16, null, null), 'You cannot share your root folder', true];

$allPermssionsFiles = $this->createMock(File::class);
$allPermssionsFiles->method('isShareable')->willReturn(true);
$allPermssionsFiles->method('getPermissions')->willReturn(\OCP\Constants::PERMISSION_ALL);
$allPermssionsFiles->method('getId')->willReturn(187);
$allPermssionsFiles->method('getOwner')
->willReturn($owner);
$allPermssionsFiles->method('getStorage')
->willReturn($storage);

// test invalid CREATE or DELETE permissions
$data[] = [$this->createShare(null, IShare::TYPE_USER, $allPermssionsFiles, $user2, $user0, $user0, \OCP\Constants::PERMISSION_ALL, null, null), 'File shares cannot have create or delete permissions', true];
$data[] = [$this->createShare(null, IShare::TYPE_GROUP, $allPermssionsFiles, $group0, $user0, $user0, \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_CREATE, null, null), 'File shares cannot have create or delete permissions', true];
$data[] = [$this->createShare(null, IShare::TYPE_LINK, $allPermssionsFiles, null, $user0, $user0, \OCP\Constants::PERMISSION_READ | \OCP\Constants::PERMISSION_DELETE, null, null), 'File shares cannot have create or delete permissions', true];

$allPermssions = $this->createMock(Folder::class);
$allPermssions->method('isShareable')->willReturn(true);
$allPermssions->method('getPermissions')->willReturn(\OCP\Constants::PERMISSION_ALL);
Expand All @@ -730,6 +743,12 @@ public function dataGeneralChecks() {
$data[] = [$this->createShare(null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 30, null, null), 'Shares need at least read permissions', true];
$data[] = [$this->createShare(null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 2, null, null), 'Shares need at least read permissions', true];

// test invalid permissions
$data[] = [$this->createShare(null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 32, null, null), 'Valid permissions are required for sharing', true];
$data[] = [$this->createShare(null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 63, null, null), 'Valid permissions are required for sharing', true];
$data[] = [$this->createShare(null, IShare::TYPE_LINK, $allPermssions, null, $user0, $user0, -1, null, null), 'Valid permissions are required for sharing', true];

// working shares
$data[] = [$this->createShare(null, IShare::TYPE_USER, $allPermssions, $user2, $user0, $user0, 31, null, null), null, false];
$data[] = [$this->createShare(null, IShare::TYPE_GROUP, $allPermssions, $group0, $user0, $user0, 3, null, null), null, false];
$data[] = [$this->createShare(null, IShare::TYPE_LINK, $allPermssions, null, $user0, $user0, 17, null, null), null, false];
Expand Down Expand Up @@ -2185,9 +2204,10 @@ public function testCanShare($expected, $sharingEnabled, $disabledForUser) {
$this->assertEquals($expected, !$exception);
}

public function testCreateShareUser() {
public function testCreateShareUser(): void {
/** @var Manager|MockObject $manager */
$manager = $this->createManagerMock()
->setMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks'])
->onlyMethods(['canShare', 'generalCreateChecks', 'userCreateChecks', 'pathCreateChecks'])
->getMock();

$shareOwner = $this->createMock(IUser::class);
Expand Down

0 comments on commit 2ae9954

Please sign in to comment.