Skip to content

Commit

Permalink
Merge pull request #19399 from nextcloud/smb-read-acl
Browse files Browse the repository at this point in the history
Add option to check share ACL's when listing directories
  • Loading branch information
blizzz authored Apr 22, 2020
2 parents 8c5bb22 + 7f32fe6 commit 4a8871f
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 0 deletions.
4 changes: 4 additions & 0 deletions apps/files_external/lib/Lib/Backend/SMB.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ public function __construct(IL10N $l, Password $legacyAuth) {
(new DefinitionParameter('show_hidden', $l->t('Show hidden files')))
->setType(DefinitionParameter::VALUE_BOOLEAN)
->setFlag(DefinitionParameter::FLAG_OPTIONAL),
(new DefinitionParameter('check_acl', $l->t('Verify ACL access when listing files')))
->setType(DefinitionParameter::VALUE_BOOLEAN)
->setFlag(DefinitionParameter::FLAG_OPTIONAL)
->setTooltip($l->t("Check the ACL's of each file or folder inside a directory to filter out items where the user has no read permissions, comes with a performance penalty")),
(new DefinitionParameter('timeout', $l->t('Timeout')))
->setType(DefinitionParameter::VALUE_HIDDEN)
->setFlag(DefinitionParameter::FLAG_OPTIONAL),
Expand Down
34 changes: 34 additions & 0 deletions apps/files_external/lib/Lib/Storage/SMB.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@

namespace OCA\Files_External\Lib\Storage;

use Icewind\SMB\ACL;
use Icewind\SMB\BasicAuth;
use Icewind\SMB\Exception\AlreadyExistsException;
use Icewind\SMB\Exception\ConnectException;
Expand Down Expand Up @@ -90,6 +91,9 @@ class SMB extends Common implements INotifyStorage {
/** @var bool */
protected $showHidden;

/** @var bool */
protected $checkAcl;

public function __construct($params) {
if (!isset($params['host'])) {
throw new \Exception('Invalid configuration, no host provided');
Expand Down Expand Up @@ -126,6 +130,7 @@ public function __construct($params) {
$this->root = rtrim($this->root, '/') . '/';

$this->showHidden = isset($params['show_hidden']) && $params['show_hidden'];
$this->checkAcl = isset($params['check_acl']) && $params['check_acl'];

$this->statCache = new CappedMemoryCache();
parent::__construct($params);
Expand Down Expand Up @@ -202,6 +207,24 @@ protected function throwUnavailable(\Exception $e) {
throw new StorageAuthException($e->getMessage(), $e);
}

/**
* get the acl from fileinfo that is relevant for the configured user
*
* @param IFileInfo $file
* @return ACL|null
*/
private function getACL(IFileInfo $file): ?ACL {
$acls = $file->getAcls();
foreach ($acls as $user => $acl) {
[, $user] = explode('\\', $user); // strip domain
if ($user === $this->server->getAuth()->getUsername()) {
return $acl;
}
}

return null;
}

/**
* @param string $path
* @return \Icewind\SMB\IFileInfo[]
Expand All @@ -220,6 +243,17 @@ protected function getFolderContents($path): iterable {
// the isHidden check is done before checking the config boolean to ensure that the metadata is always fetch
// so we trigger the below exceptions where applicable
$hide = $file->isHidden() && !$this->showHidden;

if ($this->checkAcl && $acl = $this->getACL($file)) {
// if there is no explicit deny, we assume it's allowed
// this doesn't take inheritance fully into account but if read permissions is denied for a parent we wouldn't be in this folder
// additionally, it's better to have false negatives here then false positives
if ($acl->denies(ACL::MASK_READ) || $acl->denies(ACL::MASK_EXECUTE)) {
$this->logger->debug('Hiding non readable entry ' . $file->getName());
return false;
}
}

if ($hide) {
$this->logger->debug('hiding hidden file ' . $file->getName());
}
Expand Down

0 comments on commit 4a8871f

Please sign in to comment.