From 0939520e1a19b5d22e17bcc63a4d421dd63cb807 Mon Sep 17 00:00:00 2001 From: Roeland Jago Douma Date: Fri, 15 Jan 2016 21:15:25 +0100 Subject: [PATCH] [Share 2.0] Share Object creation is a fragile thing * We can't assume that the file still exists * We can't assume that the user/group still exists Basically we do not always nicely cleanup shares. --- lib/private/share20/defaultshareprovider.php | 72 +++++++++++++++---- .../share20/exception/invalidshare.php | 25 +++++++ 2 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 lib/private/share20/exception/invalidshare.php diff --git a/lib/private/share20/defaultshareprovider.php b/lib/private/share20/defaultshareprovider.php index f4c33d68b46..a5afe9ff06b 100644 --- a/lib/private/share20/defaultshareprovider.php +++ b/lib/private/share20/defaultshareprovider.php @@ -20,8 +20,11 @@ */ namespace OC\Share20; +use OC\Share20\Exception\InvalidShare; use OC\Share20\Exception\ShareNotFound; use OC\Share20\Exception\BackendError; +use OCP\Files\NotFoundException; +use OCP\IGroup; use OCP\IUser; use OCP\IGroupManager; use OCP\IUserManager; @@ -95,10 +98,14 @@ class DefaultShareProvider implements IShareProvider { if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { //Set the UID of the user we share with - $qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()->getUID())); + /** @var IUser $sharedWith */ + $sharedWith = $share->getSharedWith(); + $qb->setValue('share_with', $qb->createNamedParameter($sharedWith->getUID())); } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { //Set the GID of the group we share with - $qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()->getGID())); + /** @var IGroup $sharedWith */ + $sharedWith = $share->getSharedWith(); + $qb->setValue('share_with', $qb->createNamedParameter($sharedWith->getGID())); } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { //Set the token of the share $qb->setValue('token', $qb->createNamedParameter($share->getToken())); @@ -152,7 +159,7 @@ class DefaultShareProvider implements IShareProvider { // Now fetch the inserted share and create a complete share object $qb = $this->dbConn->getQueryBuilder(); $qb->select('*') - ->from('*PREFIX*share') + ->from('share') ->where($qb->expr()->eq('id', $qb->createNamedParameter($id))); $cursor = $qb->execute(); @@ -335,6 +342,7 @@ class DefaultShareProvider implements IShareProvider { * * @param mixed[] $data * @return Share + * @throws InvalidShare */ private function createShare($data) { $share = new Share(); @@ -346,31 +354,45 @@ class DefaultShareProvider implements IShareProvider { ->setMailSend((bool)$data['mail_send']); if ($share->getShareType() === \OCP\Share::SHARE_TYPE_USER) { - $share->setSharedWith($this->userManager->get($data['share_with'])); + $sharedWith = $this->userManager->get($data['share_with']); + if ($sharedWith === null) { + throw new InvalidShare(); + } + $share->setSharedWith($sharedWith); } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_GROUP) { - $share->setSharedWith($this->groupManager->get($data['share_with'])); + $sharedWith = $this->groupManager->get($data['share_with']); + if ($sharedWith === null) { + throw new InvalidShare(); + } + $share->setSharedWith($sharedWith); } else if ($share->getShareType() === \OCP\Share::SHARE_TYPE_LINK) { $share->setPassword($data['share_with']); $share->setToken($data['token']); - } else { - $share->setSharedWith($data['share_with']); } if ($data['uid_initiator'] === null) { //OLD SHARE - $share->setSharedBy($this->userManager->get($data['uid_owner'])); - $folder = $this->rootFolder->getUserFolder($share->getSharedBy()->getUID()); - $path = $folder->getById((int)$data['file_source'])[0]; + $sharedBy = $this->userManager->get($data['uid_owner']); + if ($sharedBy === null) { + throw new InvalidShare(); + } + $share->setSharedBy($sharedBy); + $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']); $owner = $path->getOwner(); $share->setShareOwner($owner); } else { //New share! - $share->setSharedBy($this->userManager->get($data['uid_initiator'])); - $share->setShareOwner($this->userManager->get($data['uid_owner'])); + $sharedBy = $this->userManager->get($data['uid_initiator']); + $shareOwner = $this->userManager->get($data['uid_owner']); + if ($sharedBy === null || $shareOwner === null) { + throw new InvalidShare(); + } + $share->setSharedBy($sharedBy); + $share->setShareOwner($shareOwner); } - $path = $this->rootFolder->getUserFolder($share->getShareOwner()->getUID())->getById((int)$data['file_source'])[0]; + $path = $this->getNode($share->getShareOwner(), (int)$data['file_source']); $share->setPath($path); if ($data['expiration'] !== null) { @@ -383,4 +405,28 @@ class DefaultShareProvider implements IShareProvider { return $share; } + /** + * Get the node with file $id for $user + * + * @param IUser $user + * @param int $id + * @return \OCP\Files\File|\OCP\Files\Folder + * @throws InvalidShare + */ + private function getNode(IUser $user, $id) { + try { + $userFolder = $this->rootFolder->getUserFolder($user->getUID()); + } catch (NotFoundException $e) { + throw new InvalidShare(); + } + + $nodes = $userFolder->getById($id); + + if (empty($nodes)) { + throw new InvalidShare(); + } + + return $nodes[0]; + } + } \ No newline at end of file diff --git a/lib/private/share20/exception/invalidshare.php b/lib/private/share20/exception/invalidshare.php new file mode 100644 index 00000000000..c176e4424ba --- /dev/null +++ b/lib/private/share20/exception/invalidshare.php @@ -0,0 +1,25 @@ + + * + * @copyright Copyright (c) 2016, ownCloud, Inc. + * @license AGPL-3.0 + * + * This code is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License, version 3, + * along with this program. If not, see + * + */ +namespace OC\Share20\Exception; + +class InvalidShare extends \Exception { + +} -- 2.39.5