]> source.dussan.org Git - nextcloud-server.git/commitdiff
Add option to check share ACL's when listing directories
authorRobin Appelman <robin@icewind.nl>
Mon, 10 Feb 2020 15:36:03 +0000 (16:36 +0100)
committerRobin Appelman <robin@icewind.nl>
Tue, 21 Apr 2020 14:26:12 +0000 (16:26 +0200)
If a file or folder in a directory doesn't have read permissions they
will not be shown

Note that enabling this option incurs a performance penalty additional
requests need to be made to get all the acl.

Additionally the acl resolving logic is fairly primitive at the moment
and might not work correctly in all setups (it should error to showing
the entry)

Signed-off-by: Robin Appelman <robin@icewind.nl>
apps/files_external/lib/Lib/Backend/SMB.php
apps/files_external/lib/Lib/Storage/SMB.php

index eefeb137bf8bda57a6f43bad6dadd38876d5fb6b..7cb692ad9a43597923e8da0bc25084b3d346e9cc 100644 (file)
@@ -56,6 +56,9 @@ class SMB extends Backend {
                                (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),
                                (new DefinitionParameter('timeout', $l->t('Timeout')))
                                        ->setType(DefinitionParameter::VALUE_HIDDEN)
                                        ->setFlag(DefinitionParameter::FLAG_OPTIONAL),
index 3ff8179c7b48e5b499e6a48f38ba2a769bb38bee..ce37d5561299340b0a2593a06f770b9e475ed8af 100644 (file)
@@ -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;
@@ -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');
@@ -126,6 +130,7 @@ class SMB extends Common implements INotifyStorage {
                $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);
@@ -202,6 +207,24 @@ class SMB extends Common implements INotifyStorage {
                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[]
@@ -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
                                        // 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());
                                        }