Merge pull request #7374 from owncloud/enc_dont_overwrite_keys
[encryption] don't overwrite keys if rename was done by a stream copy
This commit is contained in:
commit
e10ca7c2e9
|
@ -501,12 +501,21 @@ class Hooks {
|
||||||
* @param array $params with the old path and the new path
|
* @param array $params with the old path and the new path
|
||||||
*/
|
*/
|
||||||
public static function preRename($params) {
|
public static function preRename($params) {
|
||||||
$util = new Util(new \OC_FilesystemView('/'), \OCP\User::getUser());
|
$user = \OCP\User::getUser();
|
||||||
|
$view = new \OC_FilesystemView('/');
|
||||||
|
$util = new Util($view, $user);
|
||||||
list($ownerOld, $pathOld) = $util->getUidAndFilename($params['oldpath']);
|
list($ownerOld, $pathOld) = $util->getUidAndFilename($params['oldpath']);
|
||||||
|
|
||||||
|
// we only need to rename the keys if the rename happens on the same mountpoint
|
||||||
|
// otherwise we perform a stream copy, so we get a new set of keys
|
||||||
|
$mp1 = $view->getMountPoint('/' . $user . '/files/' . $params['oldpath']);
|
||||||
|
$mp2 = $view->getMountPoint('/' . $user . '/files/' . $params['newpath']);
|
||||||
|
if ($mp1 === $mp2) {
|
||||||
self::$renamedFiles[$params['oldpath']] = array(
|
self::$renamedFiles[$params['oldpath']] = array(
|
||||||
'uid' => $ownerOld,
|
'uid' => $ownerOld,
|
||||||
'path' => $pathOld);
|
'path' => $pathOld);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief after a file is renamed, rename its keyfile and share-keys also fix the file size and fix also the sharing
|
* @brief after a file is renamed, rename its keyfile and share-keys also fix the file size and fix also the sharing
|
||||||
|
|
|
@ -47,6 +47,7 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
|
||||||
public $rootView; // view on /data/user
|
public $rootView; // view on /data/user
|
||||||
public $data;
|
public $data;
|
||||||
public $filename;
|
public $filename;
|
||||||
|
public $folder;
|
||||||
|
|
||||||
public static function setUpBeforeClass() {
|
public static function setUpBeforeClass() {
|
||||||
// reset backend
|
// reset backend
|
||||||
|
@ -89,6 +90,7 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
|
||||||
// init short data
|
// init short data
|
||||||
$this->data = 'hats';
|
$this->data = 'hats';
|
||||||
$this->filename = 'enc_hooks_tests-' . uniqid() . '.txt';
|
$this->filename = 'enc_hooks_tests-' . uniqid() . '.txt';
|
||||||
|
$this->folder = 'enc_hooks_tests_folder-' . uniqid();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,4 +270,57 @@ class Test_Encryption_Hooks extends \PHPUnit_Framework_TestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief test rename operation
|
||||||
|
*/
|
||||||
|
function testRenameHook() {
|
||||||
|
|
||||||
|
// save file with content
|
||||||
|
$cryptedFile = file_put_contents('crypt:///' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->filename, $this->data);
|
||||||
|
|
||||||
|
// test that data was successfully written
|
||||||
|
$this->assertTrue(is_int($cryptedFile));
|
||||||
|
|
||||||
|
// check if keys exists
|
||||||
|
$this->assertTrue($this->rootView->file_exists(
|
||||||
|
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
|
||||||
|
. $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
|
||||||
|
|
||||||
|
$this->assertTrue($this->rootView->file_exists(
|
||||||
|
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/'
|
||||||
|
. $this->filename . '.key'));
|
||||||
|
|
||||||
|
// make subfolder
|
||||||
|
$this->rootView->mkdir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder);
|
||||||
|
|
||||||
|
$this->assertTrue($this->rootView->is_dir('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder));
|
||||||
|
|
||||||
|
// move the file out of the shared folder
|
||||||
|
$root = $this->rootView->getRoot();
|
||||||
|
$this->rootView->chroot('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/');
|
||||||
|
$this->rootView->rename($this->filename, '/' . $this->folder . '/' . $this->filename);
|
||||||
|
$this->rootView->chroot($root);
|
||||||
|
|
||||||
|
$this->assertFalse($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->filename));
|
||||||
|
$this->assertTrue($this->rootView->file_exists('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder . '/' . $this->filename));
|
||||||
|
|
||||||
|
// keys should be renamed too
|
||||||
|
$this->assertFalse($this->rootView->file_exists(
|
||||||
|
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/'
|
||||||
|
. $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
|
||||||
|
$this->assertFalse($this->rootView->file_exists(
|
||||||
|
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/'
|
||||||
|
. $this->filename . '.key'));
|
||||||
|
|
||||||
|
$this->assertTrue($this->rootView->file_exists(
|
||||||
|
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/share-keys/' . $this->folder . '/'
|
||||||
|
. $this->filename . '.' . self::TEST_ENCRYPTION_HOOKS_USER1 . '.shareKey'));
|
||||||
|
$this->assertTrue($this->rootView->file_exists(
|
||||||
|
'/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files_encryption/keyfiles/' . $this->folder . '/'
|
||||||
|
. $this->filename . '.key'));
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
$this->rootView->unlink('/' . self::TEST_ENCRYPTION_HOOKS_USER1 . '/files/' . $this->folder);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,6 +127,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
|
||||||
\OC_User::deleteUser(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4);
|
\OC_User::deleteUser(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @medium
|
* @medium
|
||||||
* @param bool $withTeardown
|
* @param bool $withTeardown
|
||||||
|
@ -498,6 +499,7 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function testPublicShareFile() {
|
function testPublicShareFile() {
|
||||||
// login as admin
|
// login as admin
|
||||||
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
|
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
|
||||||
|
@ -864,6 +866,13 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
|
||||||
|
|
||||||
\OCA\Encryption\Helper::adminDisableRecovery('test123');
|
\OCA\Encryption\Helper::adminDisableRecovery('test123');
|
||||||
$this->assertEquals(0, \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryAdminEnabled'));
|
$this->assertEquals(0, \OC::$server->getAppConfig()->getValue('files_encryption', 'recoveryAdminEnabled'));
|
||||||
|
|
||||||
|
//clean up, reset passwords
|
||||||
|
\OC_User::setPassword(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, 'test123');
|
||||||
|
$params = array('uid' => \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2,
|
||||||
|
'password' => \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2,
|
||||||
|
'recoveryPassword' => 'test123');
|
||||||
|
\OCA\Encryption\Hooks::setPassphrase($params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -947,4 +956,65 @@ class Test_Encryption_Share extends \PHPUnit_Framework_TestCase {
|
||||||
$this->view->chroot('/');
|
$this->view->chroot('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief test moving a shared file out of the Shared folder
|
||||||
|
*/
|
||||||
|
function testRename() {
|
||||||
|
|
||||||
|
// login as admin
|
||||||
|
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1);
|
||||||
|
|
||||||
|
// save file with content
|
||||||
|
$cryptedFile = file_put_contents('crypt:///' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename, $this->dataShort);
|
||||||
|
|
||||||
|
// test that data was successfully written
|
||||||
|
$this->assertTrue(is_int($cryptedFile));
|
||||||
|
|
||||||
|
// get the file info from previous created file
|
||||||
|
$fileInfo = $this->view->getFileInfo(
|
||||||
|
'/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename);
|
||||||
|
|
||||||
|
// check if we have a valid file info
|
||||||
|
$this->assertTrue($fileInfo instanceof \OC\Files\FileInfo);
|
||||||
|
|
||||||
|
// share the file
|
||||||
|
\OCP\Share::shareItem('file', $fileInfo['fileid'], \OCP\Share::SHARE_TYPE_USER, \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2, OCP\PERMISSION_ALL);
|
||||||
|
|
||||||
|
// check if share key for user2exists
|
||||||
|
$this->assertTrue($this->view->file_exists(
|
||||||
|
'/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files_encryption/share-keys/'
|
||||||
|
. $this->filename . '.' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '.shareKey'));
|
||||||
|
|
||||||
|
|
||||||
|
// login as user2
|
||||||
|
\Test_Encryption_Util::loginHelper(\Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2);
|
||||||
|
|
||||||
|
$this->assertTrue($this->view->file_exists('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared/' . $this->filename));
|
||||||
|
|
||||||
|
// get file contents
|
||||||
|
$retrievedCryptedFile = $this->view->file_get_contents(
|
||||||
|
'/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared/' . $this->filename);
|
||||||
|
|
||||||
|
// check if data is the same as we previously written
|
||||||
|
$this->assertEquals($this->dataShort, $retrievedCryptedFile);
|
||||||
|
|
||||||
|
// move the file out of the shared folder
|
||||||
|
$this->view->rename('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/Shared/' . $this->filename,
|
||||||
|
'/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename);
|
||||||
|
|
||||||
|
// check if we can read the moved file
|
||||||
|
$retrievedRenamedFile = $this->view->file_get_contents(
|
||||||
|
'/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename);
|
||||||
|
|
||||||
|
// check if data is the same as we previously written
|
||||||
|
$this->assertEquals($this->dataShort, $retrievedRenamedFile);
|
||||||
|
|
||||||
|
// the owners file should be deleted
|
||||||
|
$this->assertFalse($this->view->file_exists('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER1 . '/files/' . $this->filename));
|
||||||
|
|
||||||
|
// cleanup
|
||||||
|
$this->view->unlink('/' . \Test_Encryption_Share::TEST_ENCRYPTION_SHARE_USER2 . '/files/' . $this->filename);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -534,6 +534,8 @@ class View {
|
||||||
$source = $this->fopen($path1 . $postFix1, 'r');
|
$source = $this->fopen($path1 . $postFix1, 'r');
|
||||||
$target = $this->fopen($path2 . $postFix2, 'w');
|
$target = $this->fopen($path2 . $postFix2, 'w');
|
||||||
list($count, $result) = \OC_Helper::streamCopy($source, $target);
|
list($count, $result) = \OC_Helper::streamCopy($source, $target);
|
||||||
|
fclose($source);
|
||||||
|
fclose($target);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($this->shouldEmitHooks() && $result !== false) {
|
if ($this->shouldEmitHooks() && $result !== false) {
|
||||||
|
|
Loading…
Reference in New Issue