Skip to content

Commit

Permalink
Merge pull request #28107 from owncloud/transfer-ownership-masterkey-…
Browse files Browse the repository at this point in the history
…task

Transfer ownership work with masterkey
  • Loading branch information
sharidas authored Jul 28, 2017
2 parents dd9d2f3 + 9602182 commit 082eb95
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 33 deletions.
8 changes: 8 additions & 0 deletions apps/files/lib/Command/TransferOwnership.php
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,14 @@ function (FileInfo $fileInfo) use ($progress, $self) {
$progress->advance();
$this->allFiles[] = $fileInfo;
if ($fileInfo->isEncrypted()) {
if (\OC::$server->getAppConfig()->getValue('encryption', 'useMasterKey', 0) !== 0) {
/**
* We are not going to add this to encryptedFiles array.
* Because its encrypted with masterKey and hence it doesn't
* require user's specific password.
*/
return true;
}
$this->encryptedFiles[] = $fileInfo;
}
return true;
Expand Down
3 changes: 3 additions & 0 deletions lib/private/Files/Filesystem.php
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,9 @@ public static function getDirectoryContent($directory, $mimetype_filter = '') {
* @return string
*/
public static function getPath($id) {
if (self::$defaultInstance === null) {
throw new NotFoundException("defaultInstance is null");
}
return self::$defaultInstance->getPath($id);
}

Expand Down
25 changes: 18 additions & 7 deletions lib/private/Files/Storage/Wrapper/Encryption.php
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ public function unlink($path) {
return $this->storage->unlink($path);
}

$encryptionModule = $this->getEncryptionModule($path);
$encryptionModule = ($this->encryptionManager->isEnabled()) ? $this->getEncryptionModule($path) : "";
if ($encryptionModule) {
$this->keyStorage->deleteAllFileKeys($this->getFullPath($path));
}
Expand Down Expand Up @@ -358,11 +358,12 @@ public function copy($path1, $path2) {
*
* @param string $path
* @param string $mode
* @param string|null $sourceFileOfRename
* @return resource|bool
* @throws GenericEncryptionException
* @throws ModuleDoesNotExistsException
*/
public function fopen($path, $mode) {
public function fopen($path, $mode, $sourceFileOfRename = null) {

// check if the file is stored in the array cache, this means that we
// copy a file over to the versions folder, in this case we don't want to
Expand All @@ -378,7 +379,7 @@ public function fopen($path, $mode) {
$header = $this->getHeader($path);
$signed = (isset($header['signed']) && $header['signed'] === 'true') ? true : false;
$fullPath = $this->getFullPath($path);
$encryptionModuleId = $this->util->getEncryptionModuleId($header);
$encryptionModuleId = ($encryptionEnabled) ? $this->util->getEncryptionModuleId($header): "";

if ($this->util->isExcluded($fullPath) === false) {

Expand Down Expand Up @@ -457,7 +458,7 @@ public function fopen($path, $mode) {
}
$handle = \OC\Files\Stream\Encryption::wrap($source, $path, $fullPath, $header,
$this->uid, $encryptionModule, $this->storage, $this, $this->util, $this->fileHelper, $mode,
$size, $unencryptedSize, $headerSize, $signed);
$size, $unencryptedSize, $headerSize, $signed, $sourceFileOfRename);
return $handle;
}

Expand Down Expand Up @@ -569,7 +570,7 @@ protected function fixUnencryptedSize($path, $size, $unencryptedSize) {
fclose($stream);

// we have to decrypt the last chunk to get it actual size
$encryptionModule->begin($this->getFullPath($path), $this->uid, 'r', $header, []);
$encryptionModule->begin($this->getFullPath($path), $this->uid, 'r', $header, [], null);
$decryptedLastChunk = $encryptionModule->decrypt($lastChunkContentEncrypted, $lastChunkNr . 'end');
$decryptedLastChunk .= $encryptionModule->end($this->getFullPath($path), $lastChunkNr . 'end');

Expand Down Expand Up @@ -672,6 +673,12 @@ private function updateEncryptedVersion(Storage $sourceStorage, $sourceInternalP
// in case of a rename we need to manipulate the source cache because
// this information will be kept for the new target
if ($isRename) {
/*
* Rename is a process of creating a new file. Here we try to use the
* incremented version of source file, for the destination file.
*/
$encryptedVersion = $sourceStorage->getCache()->get($sourceInternalPath)['encryptedVersion'];
$cacheInformation['encryptedVersion'] = $encryptedVersion + 1;
$sourceStorage->getCache()->put($sourceInternalPath, $cacheInformation);
} else {
$this->getCache()->put($targetInternalPath, $cacheInformation);
Expand All @@ -690,7 +697,6 @@ private function updateEncryptedVersion(Storage $sourceStorage, $sourceInternalP
* @throws \Exception
*/
private function copyBetweenStorage(Storage $sourceStorage, $sourceInternalPath, $targetInternalPath, $preserveMtime, $isRename) {

// for versions we have nothing to do, because versions should always use the
// key from the original file. Just create a 1:1 copy and done
if ($this->isVersion($targetInternalPath) ||
Expand Down Expand Up @@ -740,7 +746,12 @@ private function copyBetweenStorage(Storage $sourceStorage, $sourceInternalPath,
} else {
try {
$source = $sourceStorage->fopen($sourceInternalPath, 'r');
$target = $this->fopen($targetInternalPath, 'w');
if ($isRename) {
$absSourcePath = Filesystem::normalizePath($sourceStorage->getOwner($sourceInternalPath). '/' . $sourceInternalPath);
$target = $this->fopen($targetInternalPath, 'w', $absSourcePath);
} else {
$target = $this->fopen($targetInternalPath, 'w');
}
list(, $result) = \OC_Helper::streamCopy($source, $target);
fclose($source);
fclose($target);
Expand Down
11 changes: 7 additions & 4 deletions lib/private/Files/Stream/Encryption.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ public function __construct() {
'unencryptedSize',
'encryptionStorage',
'headerSize',
'signed'
'signed',
'sourceFileOfRename'
];
}

Expand Down Expand Up @@ -155,6 +156,7 @@ public static function wrap($source, $internalPath, $fullPath, array $header,
$unencryptedSize,
$headerSize,
$signed,
$sourceFileOfRename = null,
$wrapper = 'OC\Files\Stream\Encryption') {

$context = stream_context_create([
Expand All @@ -172,7 +174,8 @@ public static function wrap($source, $internalPath, $fullPath, array $header,
'unencryptedSize' => $unencryptedSize,
'encryptionStorage' => $encStorage,
'headerSize' => $headerSize,
'signed' => $signed
'signed' => $signed,
'sourceFileOfRename' => $sourceFileOfRename
]
]);

Expand Down Expand Up @@ -228,7 +231,7 @@ protected function loadContext($name) {
}

public function stream_open($path, $mode, $options, &$opened_path) {
$this->loadContext('ocencryption');
$context = $this->loadContext('ocencryption');

$this->position = 0;
$this->cache = '';
Expand All @@ -254,7 +257,7 @@ public function stream_open($path, $mode, $options, &$opened_path) {
}

$accessList = $this->file->getAccessList($sharePath);
$this->newHeader = $this->encryptionModule->begin($this->fullPath, $this->uid, $mode, $this->header, $accessList);
$this->newHeader = $this->encryptionModule->begin($this->fullPath, $this->uid, $mode, $this->header, $accessList, $context['sourceFileOfRename']);

if (
$mode === 'w'
Expand Down
4 changes: 3 additions & 1 deletion lib/public/Encryption/IEncryptionModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,15 @@ public function getDisplayName();
* @param string $mode php stream open mode
* @param array $header contains the header data read from the file
* @param array $accessList who has access to the file contains the key 'users' and 'public'
* @param string|null $sourceFileOfRename contains false or the rename source file. This is required
* for version increment.
*
* $return array $header contain data as key-value pairs which should be
* written to the header, in case of a write operation
* or if no additional data is needed return a empty array
* @since 8.1.0
*/
public function begin($path, $user, $mode, array $header, array $accessList);
public function begin($path, $user, $mode, array $header, array $accessList, $sourceFileOfRename);

/**
* last chunk received. This is the place where you can perform some final
Expand Down
34 changes: 13 additions & 21 deletions tests/integration/features/transfer-ownership.feature
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
Feature: transfer-ownership

# TODO: change to @no_default_encryption once all this works with master key
@no_encryption
Scenario: transfering ownership of a file
Given user "user0" exists
And user "user1" exists
Expand All @@ -12,7 +11,19 @@ Feature: transfer-ownership
And using received transfer folder of "user1" as dav path
Then Downloaded content when downloading file "/somefile.txt" with range "bytes=0-6" should be "This is"

@no_encryption
Scenario: transfering ownership of a file after updating the file
Given user "user0" exists
And user "user1" exists
And User "user0" uploads file "data/file_to_overwrite.txt" to "/PARENT/textfile0.txt"
And user "user0" uploads chunk file "1" of "3" with "AA" to "/PARENT/textfile0.txt"
And user "user0" uploads chunk file "2" of "3" with "BB" to "/PARENT/textfile0.txt"
And user "user0" uploads chunk file "3" of "3" with "CC" to "/PARENT/textfile0.txt"
When transfering ownership from "user0" to "user1"
Then the command was successful
And As an "user1"
And using received transfer folder of "user1" as dav path
Then Downloaded content when downloading file "/PARENT/textfile0.txt" with range "bytes=0-5" should be "AABBCC"

Scenario: transfering ownership of a folder
Given user "user0" exists
And user "user1" exists
Expand All @@ -24,7 +35,6 @@ Feature: transfer-ownership
And using received transfer folder of "user1" as dav path
Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"

@no_encryption
Scenario: transfering ownership of file shares
Given user "user0" exists
And user "user1" exists
Expand All @@ -36,7 +46,6 @@ Feature: transfer-ownership
And As an "user2"
Then Downloaded content when downloading file "/somefile.txt" with range "bytes=0-6" should be "This is"

@no_encryption
Scenario: transfering ownership of folder shared with third user
Given user "user0" exists
And user "user1" exists
Expand All @@ -49,7 +58,6 @@ Feature: transfer-ownership
And As an "user2"
Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"

@no_encryption
Scenario: transfering ownership of folder shared with transfer recipient
Given user "user0" exists
And user "user1" exists
Expand All @@ -63,7 +71,6 @@ Feature: transfer-ownership
And using received transfer folder of "user1" as dav path
And Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"

@no_encryption
Scenario: transfering ownership of folder doubly shared with third user
Given group "group1" exists
And user "user0" exists
Expand All @@ -79,7 +86,6 @@ Feature: transfer-ownership
And As an "user2"
Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"

@no_encryption
Scenario: transfering ownership does not transfer received shares
Given user "user0" exists
And user "user1" exists
Expand All @@ -92,7 +98,6 @@ Feature: transfer-ownership
And using received transfer folder of "user1" as dav path
Then as "user1" the folder "/test" does not exist

@no_encryption
@local_storage
Scenario: transfering ownership does not transfer external storage
Given user "user0" exists
Expand All @@ -103,7 +108,6 @@ Feature: transfer-ownership
And using received transfer folder of "user1" as dav path
Then as "user1" the folder "/local_storage" does not exist

@no_encryption
Scenario: transfering ownership does not fail with shared trashed files
Given user "user0" exists
And user "user1" exists
Expand All @@ -115,21 +119,18 @@ Feature: transfer-ownership
When transfering ownership from "user0" to "user1"
Then the command was successful

@no_encryption
Scenario: transfering ownership fails with invalid source user
Given user "user0" exists
When transfering ownership from "invalid_user" to "user0"
Then the command error output contains the text "Unknown source user"
And the command failed with exit code 1

@no_encryption
Scenario: transfering ownership fails with invalid target user
Given user "user0" exists
When transfering ownership from "user0" to "invalid_user"
Then the command error output contains the text "Unknown target user"
And the command failed with exit code 1

@no_encryption
Scenario: transfering ownership of a folder
Given user "user0" exists
And user "user1" exists
Expand All @@ -141,7 +142,6 @@ Feature: transfer-ownership
And using received transfer folder of "user1" as dav path
Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"

@no_encryption
Scenario: transfering ownership of file shares
Given user "user0" exists
And user "user1" exists
Expand All @@ -154,7 +154,6 @@ Feature: transfer-ownership
And As an "user2"
Then Downloaded content when downloading file "/somefile.txt" with range "bytes=0-6" should be "This is"

@no_encryption
Scenario: transfering ownership of folder shared with third user
Given user "user0" exists
And user "user1" exists
Expand All @@ -167,7 +166,6 @@ Feature: transfer-ownership
And As an "user2"
Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"

@no_encryption
Scenario: transfering ownership of folder shared with transfer recipient
Given user "user0" exists
And user "user1" exists
Expand All @@ -181,7 +179,6 @@ Feature: transfer-ownership
And using received transfer folder of "user1" as dav path
And Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"

@no_encryption
Scenario: transfering ownership of folder doubly shared with third user
Given group "group1" exists
And user "user0" exists
Expand All @@ -197,7 +194,6 @@ Feature: transfer-ownership
And As an "user2"
Then Downloaded content when downloading file "/test/somefile.txt" with range "bytes=0-6" should be "This is"

@no_encryption
Scenario: transfering ownership does not transfer received shares
Given user "user0" exists
And user "user1" exists
Expand All @@ -212,7 +208,6 @@ Feature: transfer-ownership
And using received transfer folder of "user1" as dav path
Then as "user1" the folder "/sub/test" does not exist

@no_encryption
@local_storage
Scenario: transfering ownership does not transfer external storage
Given user "user0" exists
Expand All @@ -224,23 +219,20 @@ Feature: transfer-ownership
And using received transfer folder of "user1" as dav path
Then as "user1" the folder "/local_storage" does not exist

@no_encryption
Scenario: transfering ownership fails with invalid source user
Given user "user0" exists
And User "user0" created a folder "/sub"
When transfering ownership of path "sub" from "invalid_user" to "user0"
Then the command error output contains the text "Unknown source user"
And the command failed with exit code 1

@no_encryption
Scenario: transfering ownership fails with invalid target user
Given user "user0" exists
And User "user0" created a folder "/sub"
When transfering ownership of path "sub" from "user0" to "invalid_user"
Then the command error output contains the text "Unknown target user"
And the command failed with exit code 1

@no_encryption
Scenario: transfering ownership fails with invalid path
Given user "user0" exists
And user "user1" exists
Expand Down

0 comments on commit 082eb95

Please sign in to comment.