]> source.dussan.org Git - nextcloud-server.git/commitdiff
basic lockdown logic
authorRobin Appelman <icewind@owncloud.com>
Mon, 1 Aug 2016 16:27:07 +0000 (18:27 +0200)
committerRobin Appelman <robin@icewind.nl>
Wed, 16 Nov 2016 14:24:23 +0000 (15:24 +0100)
Signed-off-by: Robin Appelman <icewind@owncloud.com>
apps/dav/lib/Connector/Sabre/Auth.php
lib/private/App/AppManager.php
lib/private/Files/Filesystem.php
lib/private/Lockdown/Filesystem/NullCache.php [new file with mode: 0644]
lib/private/Lockdown/Filesystem/NullStorage.php [new file with mode: 0644]
lib/private/Lockdown/LockdownManager.php [new file with mode: 0644]
lib/private/Server.php
lib/private/User/Session.php
lib/private/legacy/app.php
lib/public/Lockdown/ILockdownManager.php [new file with mode: 0644]

index a35eed8807395c71b6b4066d366fdfaf59aa7d4f..95222dafec915b34a5454f86bb40fec45ecc3eb9 100644 (file)
@@ -159,6 +159,7 @@ class Auth extends AbstractBasic {
                } catch (Exception $e) {
                        $class = get_class($e);
                        $msg = $e->getMessage();
+                       \OC::$server->getLogger()->logException($e);
                        throw new ServiceUnavailable("$class: $msg");
                }
        }
index 55fd575e1292edda6c996f053d2d1b704f2f3ca3..354f891828b302a97902d5b523924ceb7bd4293e 100644 (file)
@@ -112,6 +112,11 @@ class AppManager implements IAppManager {
                                return $value !== 'no';
                        });
                        ksort($this->installedAppsCache);
+                       foreach ($this->installedAppsCache as $appId => $value) {
+                               if (!\OC::$server->getLockdownManager()->canAccessApp($appId)) {
+                                       unset($this->installedAppsCache[$appId]);
+                               }
+                       }
                }
                return $this->installedAppsCache;
        }
index 55cf38bbdc92c4d66d9148c5288d40f58726edc9..ac0e66973d41d8b8a502dc2fd1e6d1e8cc9af54f 100644 (file)
@@ -62,6 +62,7 @@ use OC\Cache\CappedMemoryCache;
 use OC\Files\Config\MountProviderCollection;
 use OC\Files\Mount\MountPoint;
 use OC\Files\Storage\StorageFactory;
+use OC\Lockdown\Filesystem\NullStorage;
 use OCP\Files\Config\IMountProvider;
 use OCP\Files\Mount\IMountPoint;
 use OCP\Files\NotFoundException;
@@ -216,7 +217,7 @@ class Filesystem {
         * @internal
         */
        public static function logWarningWhenAddingStorageWrapper($shouldLog) {
-               self::$logWarningWhenAddingStorageWrapper = (bool) $shouldLog;
+               self::$logWarningWhenAddingStorageWrapper = (bool)$shouldLog;
        }
 
        /**
@@ -426,25 +427,36 @@ class Filesystem {
                        self::$usersSetup[$user] = true;
                }
 
-               /** @var \OC\Files\Config\MountProviderCollection $mountConfigManager */
-               $mountConfigManager = \OC::$server->getMountProviderCollection();
+               if (\OC::$server->getLockdownManager()->canAccessFilesystem()) {
+                       /** @var \OC\Files\Config\MountProviderCollection $mountConfigManager */
+                       $mountConfigManager = \OC::$server->getMountProviderCollection();
 
-               // home mounts are handled seperate since we need to ensure this is mounted before we call the other mount providers
-               $homeMount = $mountConfigManager->getHomeMountForUser($userObject);
+                       // home mounts are handled seperate since we need to ensure this is mounted before we call the other mount providers
+                       $homeMount = $mountConfigManager->getHomeMountForUser($userObject);
 
-               self::getMountManager()->addMount($homeMount);
+                       self::getMountManager()->addMount($homeMount);
 
-               \OC\Files\Filesystem::getStorage($user);
+                       \OC\Files\Filesystem::getStorage($user);
 
-               // Chance to mount for other storages
-               if ($userObject) {
-                       $mounts = $mountConfigManager->getMountsForUser($userObject);
-                       array_walk($mounts, array(self::$mounts, 'addMount'));
-                       $mounts[] = $homeMount;
-                       $mountConfigManager->registerMounts($userObject, $mounts);
-               }
+                       // Chance to mount for other storages
+                       if ($userObject) {
+                               $mounts = $mountConfigManager->getMountsForUser($userObject);
+                               array_walk($mounts, array(self::$mounts, 'addMount'));
+                               $mounts[] = $homeMount;
+                               $mountConfigManager->registerMounts($userObject, $mounts);
+                       }
 
-               self::listenForNewMountProviders($mountConfigManager, $userManager);
+                       self::listenForNewMountProviders($mountConfigManager, $userManager);
+               } else {
+                       self::$mounts->addMount(new MountPoint(
+                               new NullStorage([]),
+                               '/' . $user
+                       ));
+                       self::$mounts->addMount(new MountPoint(
+                               new NullStorage([]),
+                               '/' . $user . '/files'
+                       ));
+               }
                \OC_Hook::emit('OC_Filesystem', 'post_initMountPoints', array('user' => $user));
        }
 
diff --git a/lib/private/Lockdown/Filesystem/NullCache.php b/lib/private/Lockdown/Filesystem/NullCache.php
new file mode 100644 (file)
index 0000000..8c6b525
--- /dev/null
@@ -0,0 +1,122 @@
+<?php
+
+/**
+ * @copyright Copyright (c) 2016, Robin Appelman <robin@icewind.nl>
+ *
+ * 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 <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Lockdown\Filesystem;
+
+use OC\Files\Cache\CacheEntry;
+use OCP\Constants;
+use OCP\Files\Cache\ICache;
+use OCP\Files\Cache\ICacheEntry;
+use OCP\Files\FileInfo;
+
+class NullCache implements ICache {
+       public function getNumericStorageId() {
+               return -1;
+       }
+
+       public function get($file) {
+               return $file !== '' ? null :
+                       new CacheEntry([
+                               'fileid' => -1,
+                               'parent' => -1,
+                               'name' => '',
+                               'path' => '',
+                               'size' => '0',
+                               'mtime' => time(),
+                               'storage_mtime' => time(),
+                               'etag' => '',
+                               'mimetype' => FileInfo::MIMETYPE_FOLDER,
+                               'mimepart' => 'httpd',
+                               'permissions' => Constants::PERMISSION_READ
+                       ]);
+       }
+
+       public function getFolderContents($folder) {
+               return [];
+       }
+
+       public function getFolderContentsById($fileId) {
+               return [];
+       }
+
+       public function put($file, array $data) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function insert($file, array $data) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function update($id, array $data) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function getId($file) {
+               return -1;
+       }
+
+       public function getParentId($file) {
+               return -1;
+       }
+
+       public function inCache($file) {
+               return $file === '';
+       }
+
+       public function remove($file) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function move($source, $target) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function getStatus($file) {
+               return ICache::COMPLETE;
+       }
+
+       public function search($pattern) {
+               return [];
+       }
+
+       public function searchByMime($mimetype) {
+               return [];
+       }
+
+       public function searchByTag($tag, $userId) {
+               return [];
+       }
+
+       public function getIncomplete() {
+               return [];
+       }
+
+       public function getPathById($id) {
+               return '';
+       }
+
+       public function normalize($path) {
+               return $path;
+       }
+
+}
diff --git a/lib/private/Lockdown/Filesystem/NullStorage.php b/lib/private/Lockdown/Filesystem/NullStorage.php
new file mode 100644 (file)
index 0000000..967b6d2
--- /dev/null
@@ -0,0 +1,177 @@
+<?php
+
+/**
+ * @copyright Copyright (c) 2016, Robin Appelman <robin@icewind.nl>
+ *
+ * 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 <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Lockdown\Filesystem;
+
+use Icewind\Streams\IteratorDirectory;
+use OC\Files\Storage\Common;
+
+class NullStorage extends Common {
+       public function __construct($parameters) {
+               parent::__construct($parameters);
+       }
+
+       public function getId() {
+               return 'null';
+       }
+
+       public function mkdir($path) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function rmdir($path) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function opendir($path) {
+               return new IteratorDirectory([]);
+       }
+
+       public function is_dir($path) {
+               return $path === '';
+       }
+
+       public function is_file($path) {
+               return false;
+       }
+
+       public function stat($path) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function filetype($path) {
+               return ($path === '') ? 'dir' : false;
+       }
+
+       public function filesize($path) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function isCreatable($path) {
+               return false;
+       }
+
+       public function isReadable($path) {
+               return $path === '';
+       }
+
+       public function isUpdatable($path) {
+               return false;
+       }
+
+       public function isDeletable($path) {
+               return false;
+       }
+
+       public function isSharable($path) {
+               return false;
+       }
+
+       public function getPermissions($path) {
+               return null;
+       }
+
+       public function file_exists($path) {
+               return $path === '';
+       }
+
+       public function filemtime($path) {
+               return ($path === '') ? time() : false;
+       }
+
+       public function file_get_contents($path) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function file_put_contents($path, $data) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function unlink($path) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function rename($path1, $path2) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function copy($path1, $path2) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function fopen($path, $mode) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function getMimeType($path) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function hash($type, $path, $raw = false) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function free_space($path) {
+               return 0;
+       }
+
+       public function touch($path, $mtime = null) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function getLocalFile($path) {
+               return false;
+       }
+
+       public function hasUpdated($path, $time) {
+               return false;
+       }
+
+       public function getETag($path) {
+               return '';
+       }
+
+       public function isLocal() {
+               return false;
+       }
+
+       public function getDirectDownload($path) {
+               return false;
+       }
+
+       public function copyFromStorage(\OCP\Files\Storage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function moveFromStorage(\OCP\Files\Storage $sourceStorage, $sourceInternalPath, $targetInternalPath) {
+               throw new \OC\ForbiddenException('This request is not allowed to access the filesystem');
+       }
+
+       public function test() {
+               return true;
+       }
+
+       public function getOwner($path) {
+               return null;
+       }
+
+       public function getCache($path = '', $storage = null) {
+               return new NullCache();
+       }
+}
diff --git a/lib/private/Lockdown/LockdownManager.php b/lib/private/Lockdown/LockdownManager.php
new file mode 100644 (file)
index 0000000..9f10646
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * @copyright Copyright (c) 2016, Robin Appelman <robin@icewind.nl>
+ *
+ * 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 <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Lockdown;
+
+use OC\Authentication\Token\IToken;
+use OCP\Lockdown\ILockdownManager;
+
+class LockdownManager implements ILockdownManager {
+       /** @var IToken|null */
+       private $token;
+
+       private $enabled = false;
+
+       public function enable() {
+               $this->enabled = true;
+       }
+
+       public function setToken(IToken $token) {
+               $this->token = $token;
+       }
+
+       public function canAccessFilesystem() {
+               return true;
+       }
+
+       public function canAccessApp($app) {
+               return $app === 'logreader' || $app === 'files' || $app === 'dav';
+       }
+}
index abedf8230ed9b3bfc50c56f32a8e11d33fc760f0..c6755357a1d53d7a9cc2906760671c3ac4361ca5 100644 (file)
@@ -69,6 +69,7 @@ use OC\IntegrityCheck\Helpers\FileAccessHelper;
 use OC\Lock\DBLockingProvider;
 use OC\Lock\MemcacheLockingProvider;
 use OC\Lock\NoopLockingProvider;
+use OC\Lockdown\LockdownManager;
 use OC\Mail\Mailer;
 use OC\Memcache\ArrayCache;
 use OC\Notification\Manager;
@@ -795,6 +796,9 @@ class Server extends ServerContainer implements IServerContainer {
                                $c->getSystemConfig()
                        );
                });
+               $this->registerService('LockdownManager', function (Server $c) {
+                       return new LockdownManager();
+               });
        }
 
        /**
@@ -1534,4 +1538,11 @@ class Server extends ServerContainer implements IServerContainer {
                $factory = $this->query(\OC\Files\AppData\Factory::class);
                return $factory->get($app);
        }
+
+       /**
+        * @return \OCP\Lockdown\ILockdownManager
+        */
+       public function getLockdownManager() {
+               return $this->query('LockdownManager');
+       }
 }
index ef408aa40776bb43e520e907e3906f1888d42abf..82af9281a4cc5f953672fbb7f7ae87a2c7d9ddf0 100644 (file)
@@ -341,10 +341,12 @@ class Session implements IUserSession, Emitter {
 
                if ($isTokenPassword) {
                        $this->session->set('app_password', $password);
+                       \OC::$server->getLockdownManager()->setToken($this->tokenProvider->getToken($password));
                } else if($this->supportsCookies($request)) {
                        // Password login, but cookies supported -> create (browser) session token
                        $this->createSessionToken($request, $this->getUser()->getUID(), $user, $password);
                }
+               \OC::$server->getLockdownManager()->enable();
 
                return true;
        }
index c2ff9a5be3c07b344c066238bcc32ff22560252f..5503b8b525c4015fdaad17bf2cfb19640330a883 100644 (file)
@@ -140,7 +140,7 @@ class OC_App {
        public static function loadApp($app, $checkUpgrade = true) {
                self::$loadedApps[] = $app;
                $appPath = self::getAppPath($app);
-               if($appPath === false) {
+               if($appPath === false || !\OC::$server->getLockdownManager()->canAccessApp($app)) {
                        return;
                }
 
diff --git a/lib/public/Lockdown/ILockdownManager.php b/lib/public/Lockdown/ILockdownManager.php
new file mode 100644 (file)
index 0000000..0b0c525
--- /dev/null
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * @copyright Copyright (c) 2016, Robin Appelman <robin@icewind.nl>
+ *
+ * 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 <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OCP\Lockdown;
+
+use OC\Authentication\Token\IToken;
+
+interface ILockdownManager {
+       public function enable();
+
+       public function setToken(IToken $token);
+
+       public function canAccessFilesystem();
+
+       public function canAccessApp($app);
+}