summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/private/app/codechecker.php2
-rw-r--r--lib/private/connector/sabre/blocklegacyclientplugin.php79
-rw-r--r--lib/private/encryption/file.php4
-rw-r--r--lib/private/encryption/keys/storage.php9
-rw-r--r--lib/private/encryption/manager.php20
-rw-r--r--lib/private/encryption/update.php66
-rw-r--r--lib/private/encryption/util.php20
-rw-r--r--lib/private/files/storage/wrapper/encryption.php58
-rw-r--r--lib/private/files/stream/encryption.php40
-rw-r--r--lib/public/encryption/keys/istorage.php2
10 files changed, 232 insertions, 68 deletions
diff --git a/lib/private/app/codechecker.php b/lib/private/app/codechecker.php
index c8c66d6dcab..75db9ab3560 100644
--- a/lib/private/app/codechecker.php
+++ b/lib/private/app/codechecker.php
@@ -99,7 +99,7 @@ class CodeChecker extends BasicEmitter {
$excludes = array_map(function($item) use ($folder) {
return $folder . '/' . $item;
- }, ['vendor', '3rdparty', '.git', 'l10n']);
+ }, ['vendor', '3rdparty', '.git', 'l10n', 'tests', 'test']);
$iterator = new RecursiveDirectoryIterator($folder, RecursiveDirectoryIterator::SKIP_DOTS);
$iterator = new RecursiveCallbackFilterIterator($iterator, function($item) use ($folder, $excludes){
diff --git a/lib/private/connector/sabre/blocklegacyclientplugin.php b/lib/private/connector/sabre/blocklegacyclientplugin.php
new file mode 100644
index 00000000000..9480cd1f06d
--- /dev/null
+++ b/lib/private/connector/sabre/blocklegacyclientplugin.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * @author Lukas Reschke <lukas@owncloud.com>
+ *
+ * @copyright Copyright (c) 2015, 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 <http://www.gnu.org/licenses/>
+ *
+ */
+
+namespace OC\Connector\Sabre;
+
+use OCP\IConfig;
+use Sabre\HTTP\RequestInterface;
+use Sabre\DAV\ServerPlugin;
+use Sabre\DAV\Exception;
+
+/**
+ * Class BlockLegacyClientPlugin is used to detect old legacy sync clients and
+ * returns a 403 status to those clients
+ *
+ * @package OC\Connector\Sabre
+ */
+class BlockLegacyClientPlugin extends ServerPlugin {
+ /** @var \Sabre\DAV\Server */
+ protected $server;
+ /** @var IConfig */
+ protected $config;
+
+ /**
+ * @param IConfig $config
+ */
+ public function __construct(IConfig $config) {
+ $this->config = $config;
+ }
+
+ /**
+ * @param \Sabre\DAV\Server $server
+ * @return void
+ */
+ public function initialize(\Sabre\DAV\Server $server) {
+ $this->server = $server;
+ $this->server->on('beforeMethod', [$this, 'beforeHandler'], 200);
+ }
+
+ /**
+ * Detects all unsupported clients and throws a \Sabre\DAV\Exception\Forbidden
+ * exception which will result in a 403 to them.
+ * @param RequestInterface $request
+ * @throws \Sabre\DAV\Exception\Forbidden If the client version is not supported
+ */
+ public function beforeHandler(RequestInterface $request) {
+ $userAgent = $request->getHeader('User-Agent');
+ if($userAgent === null) {
+ return;
+ }
+
+ $minimumSupportedDesktopVersion = $this->config->getSystemValue('minimum.supported.desktop.version', '1.7.0');
+
+ // Match on the mirall version which is in scheme "Mozilla/5.0 (%1) mirall/%2" or
+ // "mirall/%1" for older releases
+ preg_match("/(?:mirall\\/)([\d.]+)/i", $userAgent, $versionMatches);
+ if(isset($versionMatches[1]) &&
+ version_compare($versionMatches[1], $minimumSupportedDesktopVersion) === -1) {
+ throw new \Sabre\DAV\Exception\Forbidden('Unsupported client version.');
+ }
+ }
+}
diff --git a/lib/private/encryption/file.php b/lib/private/encryption/file.php
index 48cd0d1187b..5a7357b9e28 100644
--- a/lib/private/encryption/file.php
+++ b/lib/private/encryption/file.php
@@ -36,7 +36,7 @@ class File implements \OCP\Encryption\IFile {
* get list of users with access to the file
*
* @param string $path to the file
- * @return array
+ * @return array ['users' => $uniqueUserIds, 'public' => $public]
*/
public function getAccessList($path) {
@@ -46,7 +46,7 @@ class File implements \OCP\Encryption\IFile {
// always add owner to the list of users with access to the file
$userIds = array($owner);
- if (!$this->util->isFile($ownerPath)) {
+ if (!$this->util->isFile($owner . '/' . $ownerPath)) {
return array('users' => $userIds, 'public' => false);
}
diff --git a/lib/private/encryption/keys/storage.php b/lib/private/encryption/keys/storage.php
index e34d7370ef1..118c8dc920d 100644
--- a/lib/private/encryption/keys/storage.php
+++ b/lib/private/encryption/keys/storage.php
@@ -235,6 +235,7 @@ class Storage implements IStorage {
*
* @param string $source
* @param string $target
+ * @return boolean
*/
public function renameKeys($source, $target) {
@@ -253,7 +254,11 @@ class Storage implements IStorage {
if ($this->view->file_exists($sourcePath)) {
$this->keySetPreparation(dirname($targetPath));
$this->view->rename($sourcePath, $targetPath);
+
+ return true;
}
+
+ return false;
}
/**
@@ -261,6 +266,7 @@ class Storage implements IStorage {
*
* @param string $source
* @param string $target
+ * @return boolean
*/
public function copyKeys($source, $target) {
@@ -279,7 +285,10 @@ class Storage implements IStorage {
if ($this->view->file_exists($sourcePath)) {
$this->keySetPreparation(dirname($targetPath));
$this->view->copy($sourcePath, $targetPath);
+ return true;
}
+
+ return false;
}
/**
diff --git a/lib/private/encryption/manager.php b/lib/private/encryption/manager.php
index 97203b7756d..8e080507c81 100644
--- a/lib/private/encryption/manager.php
+++ b/lib/private/encryption/manager.php
@@ -22,6 +22,7 @@
namespace OC\Encryption;
+use OC\Files\Filesystem;
use OC\Files\Storage\Shared;
use OC\Files\Storage\Wrapper\Encryption;
use OC\Files\View;
@@ -222,7 +223,24 @@ class Manager implements IManager {
$uid = $user ? $user->getUID() : null;
$fileHelper = \OC::$server->getEncryptionFilesHelper();
$keyStorage = \OC::$server->getEncryptionKeyStorage();
- return new Encryption($parameters, $manager, $util, $logger, $fileHelper, $uid, $keyStorage);
+ $update = new Update(
+ new View(),
+ $util,
+ Filesystem::getMountManager(),
+ $manager,
+ $fileHelper,
+ $uid
+ );
+ return new Encryption(
+ $parameters,
+ $manager,
+ $util,
+ $logger,
+ $fileHelper,
+ $uid,
+ $keyStorage,
+ $update
+ );
} else {
return $storage;
}
diff --git a/lib/private/encryption/update.php b/lib/private/encryption/update.php
index 7a170a03adc..f262099a3c5 100644
--- a/lib/private/encryption/update.php
+++ b/lib/private/encryption/update.php
@@ -22,6 +22,7 @@
namespace OC\Encryption;
+use OC\Files\Filesystem;
use \OC\Files\Mount;
use \OC\Files\View;
@@ -74,46 +75,73 @@ class Update {
$this->uid = $uid;
}
+ /**
+ * hook after file was shared
+ *
+ * @param array $params
+ */
public function postShared($params) {
if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
- $this->update($params['fileSource']);
+ $path = Filesystem::getPath($params['fileSource']);
+ list($owner, $ownerPath) = $this->getOwnerPath($path);
+ $absPath = '/' . $owner . '/files/' . $ownerPath;
+ $this->update($absPath);
}
}
+ /**
+ * hook after file was unshared
+ *
+ * @param array $params
+ */
public function postUnshared($params) {
if ($params['itemType'] === 'file' || $params['itemType'] === 'folder') {
- $this->update($params['fileSource']);
+ $path = Filesystem::getPath($params['fileSource']);
+ list($owner, $ownerPath) = $this->getOwnerPath($path);
+ $absPath = '/' . $owner . '/files/' . $ownerPath;
+ $this->update($absPath);
}
}
/**
- * update keyfiles and share keys recursively
+ * get owner and path relative to data/<owner>/files
*
- * @param int $fileSource file source id
+ * @param string $path path to file for current user
+ * @return array ['owner' => $owner, 'path' => $path]
+ * @throw \InvalidArgumentException
*/
- private function update($fileSource) {
- $path = \OC\Files\Filesystem::getPath($fileSource);
- $info = \OC\Files\Filesystem::getFileInfo($path);
- $owner = \OC\Files\Filesystem::getOwner($path);
- $view = new \OC\Files\View('/' . $owner . '/files');
- $ownerPath = $view->getPath($info->getId());
- $absPath = '/' . $owner . '/files' . $ownerPath;
+ private function getOwnerPath($path) {
+ $info = Filesystem::getFileInfo($path);
+ $owner = Filesystem::getOwner($path);
+ $view = new View('/' . $owner . '/files');
+ $path = $view->getPath($info->getId());
+ if ($path === null) {
+ throw new \InvalidArgumentException('No file found for ' . $info->getId());
+ }
+
+ return array($owner, $path);
+ }
- $mount = $this->mountManager->find($path);
- $mountPoint = $mount->getMountPoint();
+ /**
+ * notify encryption module about added/removed users from a file/folder
+ *
+ * @param string $path relative to data/
+ * @throws Exceptions\ModuleDoesNotExistsException
+ */
+ public function update($path) {
// if a folder was shared, get a list of all (sub-)folders
- if ($this->view->is_dir($absPath)) {
- $allFiles = $this->util->getAllFiles($absPath, $mountPoint);
+ if ($this->view->is_dir($path)) {
+ $allFiles = $this->util->getAllFiles($path);
} else {
- $allFiles = array($absPath);
+ $allFiles = array($path);
}
$encryptionModule = $this->encryptionManager->getDefaultEncryptionModule();
- foreach ($allFiles as $path) {
- $usersSharing = $this->file->getAccessList($path);
- $encryptionModule->update($path, $this->uid, $usersSharing);
+ foreach ($allFiles as $file) {
+ $usersSharing = $this->file->getAccessList($file);
+ $encryptionModule->update($file, $this->uid, $usersSharing);
}
}
diff --git a/lib/private/encryption/util.php b/lib/private/encryption/util.php
index 98a38012dba..032ac83f37e 100644
--- a/lib/private/encryption/util.php
+++ b/lib/private/encryption/util.php
@@ -25,6 +25,7 @@ namespace OC\Encryption;
use OC\Encryption\Exceptions\EncryptionHeaderKeyExistsException;
use OC\Encryption\Exceptions\EncryptionHeaderToLargeException;
use OC\Encryption\Exceptions\ModuleDoesNotExistsException;
+use OC\Files\Filesystem;
use OC\Files\View;
use OCP\Encryption\IEncryptionModule;
use OCP\IConfig;
@@ -181,10 +182,9 @@ class Util {
* go recursively through a dir and collect all files and sub files.
*
* @param string $dir relative to the users files folder
- * @param string $mountPoint
* @return array with list of files relative to the users files folder
*/
- public function getAllFiles($dir, $mountPoint = '') {
+ public function getAllFiles($dir) {
$result = array();
$dirList = array($dir);
@@ -193,13 +193,10 @@ class Util {
$content = $this->view->getDirectoryContent($dir);
foreach ($content as $c) {
- // getDirectoryContent() returns the paths relative to the mount points, so we need
- // to re-construct the complete path
- $path = ($mountPoint !== '') ? $mountPoint . '/' . $c->getPath() : $c->getPath();
- if ($c['type'] === 'dir') {
- $dirList[] = \OC\Files\Filesystem::normalizePath($path);
+ if ($c->getType() === 'dir') {
+ $dirList[] = $c->getPath();
} else {
- $result[] = \OC\Files\Filesystem::normalizePath($path);
+ $result[] = $c->getPath();
}
}
@@ -212,11 +209,12 @@ class Util {
* check if it is a file uploaded by the user stored in data/user/files
* or a metadata file
*
- * @param string $path
+ * @param string $path relative to the data/ folder
* @return boolean
*/
public function isFile($path) {
- if (substr($path, 0, strlen('/files/')) === '/files/') {
+ $parts = explode('/', Filesystem::normalizePath($path), 4);
+ if (isset($parts[2]) && $parts[2] === 'files') {
return true;
}
return false;
@@ -262,7 +260,7 @@ class Util {
$ownerPath = implode('/', array_slice($parts, 2));
- return array($uid, \OC\Files\Filesystem::normalizePath($ownerPath));
+ return array($uid, Filesystem::normalizePath($ownerPath));
}
diff --git a/lib/private/files/storage/wrapper/encryption.php b/lib/private/files/storage/wrapper/encryption.php
index 0a9e6d61d2e..0dc59cbb2a0 100644
--- a/lib/private/files/storage/wrapper/encryption.php
+++ b/lib/private/files/storage/wrapper/encryption.php
@@ -23,10 +23,15 @@
namespace OC\Files\Storage\Wrapper;
use OC\Encryption\Exceptions\ModuleDoesNotExistsException;
-use OC\Encryption\File;
+use OC\Encryption\Update;
+use OC\Encryption\Util;
use OC\Files\Filesystem;
use OC\Files\Storage\LocalTempFileTrait;
+use OCP\Encryption\IFile;
+use OCP\Encryption\IManager;
+use OCP\Encryption\Keys\IStorage;
use OCP\Files\Mount\IMountPoint;
+use OCP\ILogger;
class Encryption extends Wrapper {
@@ -38,10 +43,10 @@ class Encryption extends Wrapper {
/** @var \OC\Encryption\Util */
private $util;
- /** @var \OC\Encryption\Manager */
+ /** @var \OCP\Encryption\IManager */
private $encryptionManager;
- /** @var \OC\Log */
+ /** @var \OCP\ILogger */
private $logger;
/** @var string */
@@ -50,7 +55,7 @@ class Encryption extends Wrapper {
/** @var array */
private $unencryptedSize;
- /** @var File */
+ /** @var \OCP\Encryption\IFile */
private $fileHelper;
/** @var IMountPoint */
@@ -59,22 +64,28 @@ class Encryption extends Wrapper {
/** @var \OCP\Encryption\Keys\IStorage */
private $keyStorage;
+ /** @var \OC\Encryption\Update */
+ private $update;
+
/**
* @param array $parameters
- * @param \OC\Encryption\Manager $encryptionManager
+ * @param \OCP\Encryption\IManager $encryptionManager
* @param \OC\Encryption\Util $util
- * @param \OC\Log $logger
- * @param File $fileHelper
+ * @param \OCP\ILogger $logger
+ * @param \OCP\Encryption\IFile $fileHelper
* @param string $uid user who perform the read/write operation (null for public access)
+ * @param IStorage $keyStorage
+ * @param Update $update
*/
public function __construct(
$parameters,
- \OC\Encryption\Manager $encryptionManager = null,
- \OC\Encryption\Util $util = null,
- \OC\Log $logger = null,
- File $fileHelper = null,
+ IManager $encryptionManager = null,
+ Util $util = null,
+ ILogger $logger = null,
+ IFile $fileHelper = null,
$uid = null,
- $keyStorage = null
+ IStorage $keyStorage = null,
+ Update $update = null
) {
$this->mountPoint = $parameters['mountPoint'];
@@ -86,6 +97,7 @@ class Encryption extends Wrapper {
$this->fileHelper = $fileHelper;
$this->keyStorage = $keyStorage;
$this->unencryptedSize = array();
+ $this->update = $update;
parent::__construct($parameters);
}
@@ -207,19 +219,24 @@ class Encryption extends Wrapper {
* @return bool
*/
public function rename($path1, $path2) {
- $fullPath1 = $this->getFullPath($path1);
- if ($this->util->isExcluded($fullPath1)) {
+ $source = $this->getFullPath($path1);
+ if ($this->util->isExcluded($source)) {
return $this->storage->rename($path1, $path2);
}
- $source = $this->getFullPath($path1);
$result = $this->storage->rename($path1, $path2);
if ($result) {
$target = $this->getFullPath($path2);
if (isset($this->unencryptedSize[$source])) {
$this->unencryptedSize[$target] = $this->unencryptedSize[$source];
}
- $this->keyStorage->renameKeys($source, $target);
+ $keysRenamed = $this->keyStorage->renameKeys($source, $target);
+ if ($keysRenamed &&
+ dirname($source) !== dirname($target) &&
+ $this->util->isFile($target)
+ ) {
+ $this->update->update($target);
+ }
}
return $result;
@@ -242,9 +259,12 @@ class Encryption extends Wrapper {
$result = $this->storage->copy($path1, $path2);
if ($result) {
$target = $this->getFullPath($path2);
- $encryptionModule = $this->getEncryptionModule($path2);
- if ($encryptionModule) {
- $this->keyStorage->copyKeys($source, $target);
+ $keysCopied = $this->keyStorage->copyKeys($source, $target);
+ if ($keysCopied &&
+ dirname($source) !== dirname($target) &&
+ $this->util->isFile($target)
+ ) {
+ $this->update->update($target);
}
}
diff --git a/lib/private/files/stream/encryption.php b/lib/private/files/stream/encryption.php
index 910357eef45..5f39207db87 100644
--- a/lib/private/files/stream/encryption.php
+++ b/lib/private/files/stream/encryption.php
@@ -1,7 +1,7 @@
<?php
/**
* @author Björn Schießle <schiessle@owncloud.com>
- * @author jknockaert <jasper@knockaert.nl>
+ * @author Jasper Knockaert <jasper@knockaert.nl>
* @author Thomas Müller <thomas.mueller@tmit.eu>
*
* @copyright Copyright (c) 2015, ownCloud, Inc.
@@ -221,10 +221,9 @@ class Encryption extends Wrapper {
|| $mode === 'w+'
|| $mode === 'wb'
|| $mode === 'wb+'
+ || $mode === 'r+'
+ || $mode === 'rb+'
) {
- // We're writing a new file so start write counter with 0 bytes
- $this->unencryptedSize = 0;
- $this->size = 0;
$this->readOnly = false;
} else {
$this->readOnly = true;
@@ -238,6 +237,20 @@ class Encryption extends Wrapper {
$accessList = $this->file->getAccessList($sharePath);
$this->newHeader = $this->encryptionModule->begin($this->fullPath, $this->uid, $this->header, $accessList);
+ if (
+ $mode === 'w'
+ || $mode === 'w+'
+ || $mode === 'wb'
+ || $mode === 'wb+'
+ ) {
+ // We're writing a new file so start write counter with 0 bytes
+ $this->unencryptedSize = 0;
+ $this->writeHeader();
+ $this->size = $this->util->getHeaderSize();
+ } else {
+ $this->skipHeader();
+ }
+
return true;
}
@@ -250,11 +263,6 @@ class Encryption extends Wrapper {
$result = '';
- // skip the header if we read the file from the beginning
- if ($this->position === 0) {
- parent::stream_read($this->util->getHeaderSize());
- }
-
// $count = min($count, $this->unencryptedSize - $this->position);
while ($count > 0) {
$remainingLength = $count;
@@ -281,11 +289,6 @@ class Encryption extends Wrapper {
public function stream_write($data) {
- if ($this->position === 0) {
- $this->writeHeader();
- $this->size = $this->util->getHeaderSize();
- }
-
$length = 0;
// loop over $data to fit it in 6126 sized unencrypted blocks
while (strlen($data) > 0) {
@@ -428,9 +431,16 @@ class Encryption extends Wrapper {
* @return integer
* @throws EncryptionHeaderKeyExistsException if header key is already in use
*/
- private function writeHeader() {
+ protected function writeHeader() {
$header = $this->util->createHeader($this->newHeader, $this->encryptionModule);
return parent::stream_write($header);
}
+ /**
+ * read first block to skip the header
+ */
+ protected function skipHeader() {
+ parent::stream_read($this->util->getHeaderSize());
+ }
+
}
diff --git a/lib/public/encryption/keys/istorage.php b/lib/public/encryption/keys/istorage.php
index 696d5373310..752c073375d 100644
--- a/lib/public/encryption/keys/istorage.php
+++ b/lib/public/encryption/keys/istorage.php
@@ -153,6 +153,7 @@ interface IStorage {
*
* @param string $source
* @param string $target
+ * @return boolean
* @since 8.1.0
*/
public function renameKeys($source, $target);
@@ -162,6 +163,7 @@ interface IStorage {
*
* @param string $source
* @param string $target
+ * @return boolean
* @since 8.1.0
*/
public function copyKeys($source, $target);