Merge pull request #19399 from nextcloud/smb-read-acl
Add option to check share ACL's when listing directories
This commit is contained in:
commit
4a8871f5f2
|
@ -56,6 +56,10 @@ class SMB extends Backend {
|
||||||
(new DefinitionParameter('show_hidden', $l->t('Show hidden files')))
|
(new DefinitionParameter('show_hidden', $l->t('Show hidden files')))
|
||||||
->setType(DefinitionParameter::VALUE_BOOLEAN)
|
->setType(DefinitionParameter::VALUE_BOOLEAN)
|
||||||
->setFlag(DefinitionParameter::FLAG_OPTIONAL),
|
->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')))
|
(new DefinitionParameter('timeout', $l->t('Timeout')))
|
||||||
->setType(DefinitionParameter::VALUE_HIDDEN)
|
->setType(DefinitionParameter::VALUE_HIDDEN)
|
||||||
->setFlag(DefinitionParameter::FLAG_OPTIONAL),
|
->setFlag(DefinitionParameter::FLAG_OPTIONAL),
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
|
|
||||||
namespace OCA\Files_External\Lib\Storage;
|
namespace OCA\Files_External\Lib\Storage;
|
||||||
|
|
||||||
|
use Icewind\SMB\ACL;
|
||||||
use Icewind\SMB\BasicAuth;
|
use Icewind\SMB\BasicAuth;
|
||||||
use Icewind\SMB\Exception\AlreadyExistsException;
|
use Icewind\SMB\Exception\AlreadyExistsException;
|
||||||
use Icewind\SMB\Exception\ConnectException;
|
use Icewind\SMB\Exception\ConnectException;
|
||||||
|
@ -90,6 +91,9 @@ class SMB extends Common implements INotifyStorage {
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
protected $showHidden;
|
protected $showHidden;
|
||||||
|
|
||||||
|
/** @var bool */
|
||||||
|
protected $checkAcl;
|
||||||
|
|
||||||
public function __construct($params) {
|
public function __construct($params) {
|
||||||
if (!isset($params['host'])) {
|
if (!isset($params['host'])) {
|
||||||
throw new \Exception('Invalid configuration, no host provided');
|
throw new \Exception('Invalid configuration, no host provided');
|
||||||
|
@ -126,6 +130,7 @@ class SMB extends Common implements INotifyStorage {
|
||||||
$this->root = rtrim($this->root, '/') . '/';
|
$this->root = rtrim($this->root, '/') . '/';
|
||||||
|
|
||||||
$this->showHidden = isset($params['show_hidden']) && $params['show_hidden'];
|
$this->showHidden = isset($params['show_hidden']) && $params['show_hidden'];
|
||||||
|
$this->checkAcl = isset($params['check_acl']) && $params['check_acl'];
|
||||||
|
|
||||||
$this->statCache = new CappedMemoryCache();
|
$this->statCache = new CappedMemoryCache();
|
||||||
parent::__construct($params);
|
parent::__construct($params);
|
||||||
|
@ -202,6 +207,24 @@ class SMB extends Common implements INotifyStorage {
|
||||||
throw new StorageAuthException($e->getMessage(), $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
|
* @param string $path
|
||||||
* @return \Icewind\SMB\IFileInfo[]
|
* @return \Icewind\SMB\IFileInfo[]
|
||||||
|
@ -220,6 +243,17 @@ class SMB extends Common implements INotifyStorage {
|
||||||
// the isHidden check is done before checking the config boolean to ensure that the metadata is always fetch
|
// 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
|
// so we trigger the below exceptions where applicable
|
||||||
$hide = $file->isHidden() && !$this->showHidden;
|
$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) {
|
if ($hide) {
|
||||||
$this->logger->debug('hiding hidden file ' . $file->getName());
|
$this->logger->debug('hiding hidden file ' . $file->getName());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue