Skip to content

Commit

Permalink
Fix shares read permissions
Browse files Browse the repository at this point in the history
A user with reshare permissions on a file is now able to get any share
of that file (just like the owner).

Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
  • Loading branch information
skjnldsv committed Oct 4, 2019
1 parent b1069b2 commit ff895ab
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 14 deletions.
26 changes: 21 additions & 5 deletions apps/files_sharing/lib/Controller/ShareAPIController.php
Original file line number Diff line number Diff line change
Expand Up @@ -305,13 +305,13 @@ public function getShare(string $id): DataResponse {
throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
}

if ($this->canAccessShare($share)) {
try {
try {
if ($this->canAccessShare($share)) {
$share = $this->formatShare($share);
return new DataResponse([$share]);
} catch (NotFoundException $e) {
//Fall trough
}
} catch (NotFoundException $e) {
// Fall trough
}

throw new OCSNotFoundException($this->l->t('Wrong share ID, share doesn\'t exist'));
Expand Down Expand Up @@ -983,6 +983,13 @@ public function updateShare(
}

/**
* Does the user have read permission on the share
*
* @param \OCP\Share\IShare $share the share to check
* @param boolean $checkGroups check groups as well?
* @return boolean
* @throws NotFoundException
*
* @suppress PhanUndeclaredClassMethod
*/
protected function canAccessShare(\OCP\Share\IShare $share, bool $checkGroups = true): bool {
Expand All @@ -997,12 +1004,21 @@ protected function canAccessShare(\OCP\Share\IShare $share, bool $checkGroups =
return true;
}

// If the share is shared with you (or a group you are a member of)
// If the share is shared with you, you can access it!
if ($share->getShareType() === Share::SHARE_TYPE_USER
&& $share->getSharedWith() === $this->currentUser) {
return true;
}

// Have reshare rights on the shared file/folder ?
// Does the currentUser have access to the shared file?
$userFolder = $this->rootFolder->getUserFolder($this->currentUser);
$files = $userFolder->getById($share->getNodeId());
if (!empty($files) && $this->shareProviderResharingRights($this->currentUser, $share, $files[0])) {
return true;
}

// If in the recipient group, you can see the share
if ($checkGroups && $share->getShareType() === Share::SHARE_TYPE_GROUP) {
$sharedWith = $this->groupManager->get($share->getSharedWith());
$user = $this->userManager->get($this->currentUser);
Expand Down
62 changes: 62 additions & 0 deletions apps/files_sharing/tests/Controller/ShareAPIControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,15 @@ public function testDeleteSharedWithMyGroup() {
->method('lock')
->with(\OCP\Lock\ILockingProvider::LOCK_SHARED);

$userFolder = $this->getMockBuilder('OCP\Files\Folder')->getMock();
$this->rootFolder->method('getUserFolder')
->with($this->currentUser)
->willReturn($userFolder);

$userFolder->method('getById')
->with($share->getNodeId())
->willReturn([$share->getNode()]);

$this->shareManager->expects($this->once())
->method('deleteFromSelf')
->with($share, $this->currentUser);
Expand Down Expand Up @@ -427,6 +436,15 @@ public function testDeleteSharedWithGroupIDontBelongTo() {
->method('lock')
->with(\OCP\Lock\ILockingProvider::LOCK_SHARED);

$userFolder = $this->getMockBuilder('OCP\Files\Folder')->getMock();
$this->rootFolder->method('getUserFolder')
->with($this->currentUser)
->willReturn($userFolder);

$userFolder->method('getById')
->with($share->getNodeId())
->willReturn([$share->getNode()]);

$this->shareManager->expects($this->never())
->method('deleteFromSelf');

Expand Down Expand Up @@ -758,6 +776,11 @@ public function testGetShareInvalidNode() {
->with('ocinternal:42', 'currentUser')
->willReturn($share);

$userFolder = $this->getMockBuilder('OCP\Files\Folder')->getMock();
$this->rootFolder->method('getUserFolder')
->with($this->currentUser)
->willReturn($userFolder);

$this->ocs->getShare(42);
}

Expand All @@ -775,6 +798,27 @@ public function testCanAccessShare() {
$share->method('getSharedWith')->willReturn($this->currentUser);
$this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));

$file = $this->getMockBuilder(File::class)->getMock();

$userFolder = $this->getMockBuilder('OCP\Files\Folder')->getMock();
$this->rootFolder->method('getUserFolder')
->with($this->currentUser)
->willReturn($userFolder);

$userFolder->method('getById')
->with($share->getNodeId())
->willReturn([$file]);

$file->method('getPermissions')
->will($this->onConsecutiveCalls(\OCP\Constants::PERMISSION_SHARE, \OCP\Constants::PERMISSION_READ));

// getPermissions -> share
$share = $this->getMockBuilder(IShare::class)->getMock();
$share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_USER);
$share->method('getSharedWith')->willReturn($this->getMockBuilder(IUser::class)->getMock());
$this->assertTrue($this->invokePrivate($this->ocs, 'canAccessShare', [$share]));

// getPermissions -> read
$share = $this->getMockBuilder(IShare::class)->getMock();
$share->method('getShareType')->willReturn(\OCP\Share::SHARE_TYPE_USER);
$share->method('getSharedWith')->willReturn($this->getMockBuilder(IUser::class)->getMock());
Expand Down Expand Up @@ -852,6 +896,15 @@ public function dataCanAccessRoomShare() {
* @param bool canAccessShareByHelper
*/
public function testCanAccessRoomShare(bool $expected, \OCP\Share\IShare $share, bool $helperAvailable, bool $canAccessShareByHelper) {
$userFolder = $this->getMockBuilder('OCP\Files\Folder')->getMock();
$this->rootFolder->method('getUserFolder')
->with($this->currentUser)
->willReturn($userFolder);

$userFolder->method('getById')
->with($share->getNodeId())
->willReturn([$share->getNode()]);

if (!$helperAvailable) {
$this->appManager->method('isEnabledForUser')
->with('spreed')
Expand Down Expand Up @@ -1727,6 +1780,15 @@ public function testUpdateShareCantAccess() {

$this->shareManager->method('getShareById')->with('ocinternal:42')->willReturn($share);

$userFolder = $this->getMockBuilder('OCP\Files\Folder')->getMock();
$this->rootFolder->method('getUserFolder')
->with($this->currentUser)
->willReturn($userFolder);

$userFolder->method('getById')
->with($share->getNodeId())
->willReturn([$share->getNode()]);

$this->ocs->updateShare(42);
}

Expand Down
8 changes: 4 additions & 4 deletions apps/oauth2/js/oauth2.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/oauth2/js/oauth2.js.map

Large diffs are not rendered by default.

34 changes: 32 additions & 2 deletions build/integration/sharing_features/sharing-v1-part2.feature
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,36 @@ Feature: sharing
Then the OCS status code should be "404"
And the HTTP status code should be "200"

Scenario: Get a share with a user with resharing rights
Given user "user0" exists
And user "user1" exists
And user "user2" exists
And file "textfile0.txt" of user "user0" is shared with user "user1"
And file "textfile0.txt" of user "user0" is shared with user "user2"
And As an "user1"
When Getting info of last share
Then the OCS status code should be "100"
And the HTTP status code should be "200"
And Share fields of last share match with
| id | A_NUMBER |
| item_type | file |
| item_source | A_NUMBER |
| share_type | 0 |
| share_with | user2 |
| file_source | A_NUMBER |
| file_target | /textfile0.txt |
| path | /textfile0 (2).txt |
| permissions | 19 |
| stime | A_NUMBER |
| storage | A_NUMBER |
| mail_send | 0 |
| uid_owner | user0 |
| storage_id | shared::/textfile0 (2).txt |
| file_parent | A_NUMBER |
| share_with_displayname | user2 |
| displayname_owner | user0 |
| mimetype | text/plain |

Scenario: Share of folder and sub-folder to same user - core#20645
Given As an "admin"
And user "user0" exists
Expand Down Expand Up @@ -427,8 +457,8 @@ Feature: sharing
And file "textfile0.txt" of user "user0" is shared with user "user2"
And As an "user1"
When Deleting last share
Then the OCS status code should be "404"
And the HTTP status code should be "200"
Then the OCS status code should be "403"
And the HTTP status code should be "401"

Scenario: Keep usergroup shares (#22143)
Given As an "admin"
Expand Down
4 changes: 2 additions & 2 deletions build/integration/sharing_features/sharing-v1-part3.feature
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,8 @@ Feature: sharing
When As an "user1"
And Updating last share with
| permissions | 19 |
Then the OCS status code should be "404"
And the HTTP status code should be "200"
Then the OCS status code should be "403"
And the HTTP status code should be "401"

Scenario: do not allow to increase link share permissions on reshare
Given As an "admin"
Expand Down

0 comments on commit ff895ab

Please sign in to comment.