detect system wide mount points correctly

This commit is contained in:
Bjoern Schiessle 2015-04-15 13:19:17 +02:00
parent 67500d5f2f
commit b25c06f576
8 changed files with 85 additions and 24 deletions

View file

@ -728,6 +728,7 @@ class OC {
new \OC\Encryption\Util(
new \OC\Files\View(),
\OC::$server->getUserManager(),
\OC::$server->getGroupManager(),
\OC::$server->getConfig()),
\OC\Files\Filesystem::getMountManager(),
\OC::$server->getEncryptionManager(),

View file

@ -266,7 +266,7 @@ class Storage implements \OCP\Encryption\Keys\IStorage {
$filename = $this->util->stripPartialFileExtension($filename);
// in case of system wide mount points the keys are stored directly in the data directory
if ($this->util->isSystemWideMountPoint($filename)) {
if ($this->util->isSystemWideMountPoint($filename, $owner)) {
$keyPath = $this->keys_base_dir . $filename . '/';
} else {
$keyPath = '/' . $owner . $this->keys_base_dir . $filename . '/';
@ -287,7 +287,7 @@ class Storage implements \OCP\Encryption\Keys\IStorage {
list($owner, $source) = $this->util->getUidAndFilename($source);
list(, $target) = $this->util->getUidAndFilename($target);
$systemWide = $this->util->isSystemWideMountPoint($target);
$systemWide = $this->util->isSystemWideMountPoint($target, $owner);
if ($systemWide) {
$sourcePath = $this->keys_base_dir . $source . '/';
@ -315,7 +315,7 @@ class Storage implements \OCP\Encryption\Keys\IStorage {
list($owner, $source) = $this->util->getUidAndFilename($source);
list(, $target) = $this->util->getUidAndFilename($target);
$systemWide = $this->util->isSystemWideMountPoint($target);
$systemWide = $this->util->isSystemWideMountPoint($target, $owner);
if ($systemWide) {
$sourcePath = $this->keys_base_dir . $source . '/';

View file

@ -216,7 +216,11 @@ class Manager implements IManager {
if (!($storage instanceof Shared)) {
$manager = \OC::$server->getEncryptionManager();
$util = new Util(
new View(), \OC::$server->getUserManager(), \OC::$server->getConfig());
new View(),
\OC::$server->getUserManager(),
\OC::$server->getGroupManager(),
\OC::$server->getConfig()
);
$user = \OC::$server->getUserSession()->getUser();
$logger = \OC::$server->getLogger();
$uid = $user ? $user->getUID() : null;

View file

@ -66,15 +66,20 @@ class Util {
/** @var array paths excluded from encryption */
protected $excludedPaths;
/** @var \OC\Group\Manager $manager */
protected $groupManager;
/**
*
* @param \OC\Files\View $view
* @param \OC\User\Manager $userManager
* @param \OC\Group\Manager $groupManager
* @param IConfig $config
*/
public function __construct(
\OC\Files\View $view,
\OC\User\Manager $userManager,
\OC\Group\Manager $groupManager,
IConfig $config) {
$this->ocHeaderKeys = [
@ -83,6 +88,7 @@ class Util {
$this->view = $view;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
$this->config = $config;
$this->excludedPaths[] = 'files_encryption';
@ -304,15 +310,15 @@ class Util {
/**
* check if the file is stored on a system wide mount point
* @param string $path relative to /data/user with leading '/'
* @param string $uid
* @return boolean
*/
public function isSystemWideMountPoint($path) {
$normalizedPath = ltrim($path, '/');
public function isSystemWideMountPoint($path, $uid) {
if (\OCP\App::isEnabled("files_external")) {
$mounts = \OC_Mount_Config::getSystemMountPoints();
foreach ($mounts as $mount) {
if ($mount['mountpoint'] == substr($normalizedPath, 0, strlen($mount['mountpoint']))) {
if ($this->isMountPointApplicableToUser($mount)) {
if (strpos($path, '/files/' . $mount['mountpoint']) === 0) {
if ($this->isMountPointApplicableToUser($mount, $uid)) {
return true;
}
}
@ -321,6 +327,29 @@ class Util {
return false;
}
/**
* check if mount point is applicable to user
*
* @param array $mount contains $mount['applicable']['users'], $mount['applicable']['groups']
* @param string $uid
* @return boolean
*/
private function isMountPointApplicableToUser($mount, $uid) {
$acceptedUids = array('all', $uid);
// check if mount point is applicable for the user
$intersection = array_intersect($acceptedUids, $mount['applicable']['users']);
if (!empty($intersection)) {
return true;
}
// check if mount point is applicable for group where the user is a member
foreach ($mount['applicable']['groups'] as $gid) {
if ($this->groupManager->isInGroup($uid, $gid)) {
return true;
}
}
return false;
}
/**
* check if it is a path which is excluded by ownCloud from encryption
*

View file

@ -88,7 +88,12 @@ class Server extends SimpleContainer implements IServerContainer {
});
$this->registerService('EncryptionFileHelper', function (Server $c) {
$util = new \OC\Encryption\Util(new \OC\Files\View(), $c->getUserManager(), $c->getConfig());
$util = new \OC\Encryption\Util(
new \OC\Files\View(),
$c->getUserManager(),
$c->getGroupManager(),
$c->getConfig()
);
return new Encryption\File($util);
});
@ -437,7 +442,12 @@ class Server extends SimpleContainer implements IServerContainer {
*/
function getEncryptionKeyStorage($encryptionModuleId) {
$view = new \OC\Files\View();
$util = new \OC\Encryption\Util($view, \OC::$server->getUserManager(), \OC::$server->getConfig());
$util = new \OC\Encryption\Util(
$view,
\OC::$server->getUserManager(),
\OC::$server->getGroupManager(),
\OC::$server->getConfig()
);
return $this->query('EncryptionKeyStorageFactory')->get($encryptionModuleId, $view, $util);
}

View file

@ -20,9 +20,15 @@ class UtilTest extends TestCase {
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $userManager;
/** @var \PHPUnit_Framework_MockObject_MockObject */
protected $groupManager;
/** @var \PHPUnit_Framework_MockObject_MockObject */
private $config;
/** @var \OC\Encryption\Util */
private $util;
public function setUp() {
parent::setUp();
$this->view = $this->getMockBuilder('OC\Files\View')
@ -33,18 +39,28 @@ class UtilTest extends TestCase {
->disableOriginalConstructor()
->getMock();
$this->groupManager = $this->getMockBuilder('OC\Group\Manager')
->disableOriginalConstructor()
->getMock();
$this->config = $this->getMockBuilder('OCP\IConfig')
->disableOriginalConstructor()
->getMock();
$this->util = new Util(
$this->view,
$this->userManager,
$this->groupManager,
$this->config
);
}
/**
* @dataProvider providesHeadersForEncryptionModule
*/
public function testGetEncryptionModuleId($expected, $header) {
$u = new Util($this->view, $this->userManager, $this->config);
$id = $u->getEncryptionModuleId($header);
$id = $this->util->getEncryptionModuleId($header);
$this->assertEquals($expected, $id);
}
@ -61,8 +77,7 @@ class UtilTest extends TestCase {
*/
public function testReadHeader($header, $expected, $moduleId) {
$expected['oc_encryption_module'] = $moduleId;
$u = new Util($this->view, $this->userManager, $this->config);
$result = $u->readHeader($header);
$result = $this->util->readHeader($header);
$this->assertSameSize($expected, $result);
foreach ($expected as $key => $value) {
$this->assertArrayHasKey($key, $result);
@ -78,8 +93,7 @@ class UtilTest extends TestCase {
$em = $this->getMock('\OCP\Encryption\IEncryptionModule');
$em->expects($this->any())->method('getId')->willReturn($moduleId);
$u = new Util($this->view, $this->userManager, $this->config);
$result = $u->createHeader($header, $em);
$result = $this->util->createHeader($header, $em);
$this->assertEquals($expected, $result);
}
@ -102,23 +116,20 @@ class UtilTest extends TestCase {
$em = $this->getMock('\OCP\Encryption\IEncryptionModule');
$em->expects($this->any())->method('getId')->willReturn('moduleId');
$u = new Util($this->view, $this->userManager, $this->config);
$u->createHeader($header, $em);
$this->util->createHeader($header, $em);
}
/**
* @dataProvider providePathsForTestIsExcluded
*/
public function testIsEcluded($path, $expected) {
public function testIsExcluded($path, $expected) {
$this->userManager
->expects($this->any())
->method('userExists')
->will($this->returnCallback(array($this, 'isExcludedCallback')));
$u = new Util($this->view, $this->userManager, $this->config);
$this->assertSame($expected,
$u->isExcluded($path)
$this->util->isExcluded($path)
);
}

View file

@ -34,8 +34,11 @@ class Encryption extends \Test\Files\Storage\Storage {
$config = $this->getMockBuilder('\OCP\IConfig')
->disableOriginalConstructor()
->getMock();
$groupManager = $this->getMockBuilder('\OC\Group\Manager')
->disableOriginalConstructor()
->getMock();
$util = $this->getMock('\OC\Encryption\Util', ['getUidAndFilename'], [new View(), new \OC\User\Manager(), $config]);
$util = $this->getMock('\OC\Encryption\Util', ['getUidAndFilename'], [new View(), new \OC\User\Manager(), $groupManager, $config]);
$util->expects($this->any())
->method('getUidAndFilename')
->willReturnCallback(function ($path) {

View file

@ -27,12 +27,15 @@ class Encryption extends \Test\TestCase {
$config = $this->getMockBuilder('\OCP\IConfig')
->disableOriginalConstructor()
->getMock();
$groupManager = $this->getMockBuilder('\OC\Group\Manager')
->disableOriginalConstructor()
->getMock();
$file = $this->getMockBuilder('\OC\Encryption\File')
->disableOriginalConstructor()
->setMethods(['getAccessList'])
->getMock();
$file->expects($this->any())->method('getAccessList')->willReturn([]);
$util = $this->getMock('\OC\Encryption\Util', ['getUidAndFilename'], [new View(), new \OC\User\Manager(), $config]);
$util = $this->getMock('\OC\Encryption\Util', ['getUidAndFilename'], [new View(), new \OC\User\Manager(), $groupManager, $config]);
$util->expects($this->any())
->method('getUidAndFilename')
->willReturn(['user1', $internalPath]);