Skip to content

Commit

Permalink
feat: decrypt the stream of a file version as returned by IVersionedS…
Browse files Browse the repository at this point in the history
…torage
  • Loading branch information
DeepDiver1975 committed Oct 20, 2021
1 parent 256cbfe commit 4bc4c36
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 12 deletions.
87 changes: 81 additions & 6 deletions lib/private/Files/Storage/Wrapper/Encryption.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@
use OCP\Encryption\Keys\IStorage;
use OCP\Files\Mount\IMountPoint;
use OCP\Files\Storage;
use OCP\Files\Storage\IVersionedStorage;
use OCP\ILogger;
use OCP\Files\Cache\ICacheEntry;

class Encryption extends Wrapper {
class Encryption extends Wrapper implements Storage\IVersionedStorage {
use LocalTempFileTrait;

/** @var string */
Expand Down Expand Up @@ -350,9 +351,7 @@ public function copy($path1, $path2) {
// need to stream copy file by file in case we copy between a encrypted
// and a unencrypted storage
$this->unlink($path2);
$result = $this->copyFromStorage($this, $path1, $path2);

return $result;
return $this->copyFromStorage($this, $path1, $path2);
}

/**
Expand Down Expand Up @@ -491,7 +490,8 @@ public function fopen($path, $mode) {
$unencryptedSize,
$headerSize,
$signed,
$sourceFileOfRename
$sourceFileOfRename,
null # TODO: maybe fill it?
);
unset($this->sourcePath[$path]);

Expand Down Expand Up @@ -602,7 +602,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, [], null);
$encryptionModule->begin($this->getFullPath($path), $this->uid, 'r', $header, [], null, null);
$decryptedLastChunk = $encryptionModule->decrypt($lastChunkContentEncrypted, $lastChunkNr . 'end');
$decryptedLastChunk .= $encryptionModule->end($this->getFullPath($path), $lastChunkNr . 'end');

Expand Down Expand Up @@ -1087,4 +1087,79 @@ protected function isVersion($path) {
$normalized = Filesystem::normalizePath($path);
return \substr($normalized, 0, \strlen('/files_versions/')) === '/files_versions/';
}

public function getVersions($internalPath) {
if ($this->storage instanceof IVersionedStorage) {
return $this->storage->getVersions($internalPath);
}
return null;
}

public function getVersion($internalPath, $versionId) {
if ($this->storage instanceof IVersionedStorage) {
return $this->storage->getVersion($internalPath, $versionId);
}
return null;
}

public function getContentOfVersion($internalPath, $versionId) {
if ($this->storage instanceof IVersionedStorage) {
$stream = $this->storage->getContentOfVersion($internalPath, $versionId);
$info = $this->storage->getVersion($internalPath, $versionId);
$header = $this->getHeader($stream);
$signed = (isset($header['signed']) && $header['signed'] === 'true') ? true : false;
$path = $internalPath;
# getFullPath returns wrong information here .....
$fullPath = $this->getFullPath($path);
$encryptionModuleId = $this->util->getEncryptionModuleId($header);
$encryptionModule = $this->encryptionManager->getEncryptionModule($encryptionModuleId);

/* @phan-suppress-next-line PhanUndeclaredMethod */
$size = $this->storage->filesize($internalPath);
$unencryptedSize = $size;
$fileEncryptionVersion = null;
if ($info['size']) {
$unencryptedSize = $info['size'];
}
if ($info['encryptedVersion']) {
$fileEncryptionVersion = $info['encryptedVersion'];
}
$headerSize = $this->getHeaderSize($stream);

return \OC\Files\Stream\Encryption::wrap(
$stream,
$path,
$fullPath,
$header,
$this->uid,
$encryptionModule,
$this->storage,
$this,
$this->util,
$this->fileHelper,
'rb',
$size,
$unencryptedSize,
$headerSize,
$signed,
null,
$fileEncryptionVersion
);
}
return null;
}

public function restoreVersion($internalPath, $versionId) {
if ($this->storage instanceof IVersionedStorage) {
return $this->storage->restoreVersion($internalPath, $versionId);
}
return null;
}

public function saveVersion($internalPath) {
if ($this->storage instanceof IVersionedStorage) {
return $this->storage->saveVersion($internalPath);
}
return null;
}
}
11 changes: 7 additions & 4 deletions lib/private/Files/Stream/Encryption.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ public function __construct() {
'encryptionStorage',
'headerSize',
'signed',
'sourceFileOfRename'
'sourceFileOfRename',
'fileEncryptionVersion'
];
}

Expand Down Expand Up @@ -160,7 +161,8 @@ public static function wrap(
$unencryptedSize,
$headerSize,
$signed,
$sourceFileOfRename = null,
$sourceFileOfRename,
$fileEncryptionVersion,
$wrapper = 'OC\Files\Stream\Encryption'
) {
$context = \stream_context_create([
Expand All @@ -179,7 +181,8 @@ public static function wrap(
'encryptionStorage' => $encStorage,
'headerSize' => $headerSize,
'signed' => $signed,
'sourceFileOfRename' => $sourceFileOfRename
'sourceFileOfRename' => $sourceFileOfRename,
'fileEncryptionVersion' => $fileEncryptionVersion
]
]);

Expand Down Expand Up @@ -259,7 +262,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, $context['sourceFileOfRename']);
$this->newHeader = $this->encryptionModule->begin($this->fullPath, $this->uid, $mode, $this->header, $accessList, $context['sourceFileOfRename'], $context['fileEncryptionVersion']);
$this->unencryptedBlockSize = $this->encryptionModule->getUnencryptedBlockSize($this->signed);

if (
Expand Down
2 changes: 1 addition & 1 deletion lib/public/Encryption/IEncryptionModule.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public function getDisplayName();
* 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, $sourceFileOfRename);
public function begin($path, $user, $mode, array $header, array $accessList, $sourceFileOfRename, $fileEncryptionVersion);

/**
* last chunk received. This is the place where you can perform some final
Expand Down
1 change: 0 additions & 1 deletion settings/ChangePassword/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,6 @@ public static function changeUserPassword($args) {
$keyStorage,
$crypt,
\OC::$server->getConfig(),
\OC::$server->getUserSession(),
/* @phan-suppress-next-line PhanUndeclaredClassMethod */
new \OCA\Encryption\Session(\OC::$server->getSession()),
\OC::$server->getLogger(),
Expand Down

0 comments on commit 4bc4c36

Please sign in to comment.