Skip to content

Commit

Permalink
refactor(Stream\Encryption): Migrate to strong types
Browse files Browse the repository at this point in the history
Signed-off-by: provokateurin <[email protected]>
  • Loading branch information
provokateurin committed Oct 1, 2024
1 parent 5434005 commit 0420b58
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 100 deletions.
116 changes: 42 additions & 74 deletions lib/private/Files/Stream/Encryption.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
Expand All @@ -9,81 +11,42 @@

use Icewind\Streams\Wrapper;
use OC\Encryption\Exceptions\EncryptionHeaderKeyExistsException;
use OC\Encryption\File;
use OC\Encryption\Util;
use OC\Files\Storage\Storage;
use OCP\Encryption\IEncryptionModule;
use function is_array;
use function stream_context_create;

class Encryption extends Wrapper {
/** @var \OC\Encryption\Util */
protected $util;

/** @var \OC\Encryption\File */
protected $file;

/** @var \OCP\Encryption\IEncryptionModule */
protected $encryptionModule;

/** @var \OC\Files\Storage\Storage */
protected $storage;

/** @var \OC\Files\Storage\Wrapper\Encryption */
protected $encryptionStorage;

/** @var string */
protected $internalPath;

/** @var string */
protected $cache;

/** @var integer */
protected $size;

/** @var integer */
protected $position;

/** @var integer */
protected $unencryptedSize;

/** @var integer */
protected $headerSize;

/** @var integer */
protected $unencryptedBlockSize;

/** @var array */
protected $header;

/** @var string */
protected $fullPath;

/** @var bool */
protected $signed;

protected Util $util;
protected File $file;
protected IEncryptionModule $encryptionModule;
protected Storage $storage;
protected \OC\Files\Storage\Wrapper\Encryption $encryptionStorage;
protected string $internalPath;
protected string $cache;
protected ?int $size = null;
protected int $position;
protected ?int $unencryptedSize = null;
protected int $headerSize;
protected int $unencryptedBlockSize;
protected array $header;
protected string $fullPath;
protected bool $signed;
/**
* header data returned by the encryption module, will be written to the file
* in case of a write operation
*
* @var array
*/
protected $newHeader;

protected array $newHeader;
/**
* user who perform the read/write operation null for public access
*
* @var string
*/
protected $uid;

/** @var bool */
protected $readOnly;

/** @var bool */
protected $writeFlag;

/** @var array */
protected $expectedContextProperties;

/** @var bool */
protected $fileUpdated;
protected string $uid;
protected bool $readOnly;
protected bool $writeFlag;
protected array $expectedContextProperties;
protected bool $fileUpdated;

public function __construct() {
$this->expectedContextProperties = [
Expand Down Expand Up @@ -113,11 +76,11 @@ public function __construct() {
* @param string $fullPath relative to data/
* @param array $header
* @param string $uid
* @param \OCP\Encryption\IEncryptionModule $encryptionModule
* @param \OC\Files\Storage\Storage $storage
* @param IEncryptionModule $encryptionModule
* @param Storage $storage
* @param \OC\Files\Storage\Wrapper\Encryption $encStorage
* @param \OC\Encryption\Util $util
* @param \OC\Encryption\File $file
* @param Util $util
* @param File $file
* @param string $mode
* @param int|float $size
* @param int|float $unencryptedSize
Expand All @@ -128,19 +91,24 @@ public function __construct() {
*
* @throws \BadMethodCallException
*/
public static function wrap($source, $internalPath, $fullPath, array $header,
public static function wrap(
$source,
$internalPath,
$fullPath,
array $header,
$uid,
\OCP\Encryption\IEncryptionModule $encryptionModule,
\OC\Files\Storage\Storage $storage,
IEncryptionModule $encryptionModule,
Storage $storage,
\OC\Files\Storage\Wrapper\Encryption $encStorage,
\OC\Encryption\Util $util,
\OC\Encryption\File $file,
Util $util,
File $file,
$mode,
$size,
$unencryptedSize,
$headerSize,
$signed,
$wrapper = Encryption::class) {
$wrapper = Encryption::class,
) {
$context = stream_context_create([
'ocencryption' => [
'source' => $source,
Expand Down
64 changes: 38 additions & 26 deletions tests/lib/Files/Stream/EncryptionTest.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
<?php

declare(strict_types=1);

/**
* SPDX-FileCopyrightText: 2016-2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
Expand All @@ -7,27 +10,27 @@
namespace Test\Files\Stream;

use OC\Files\Cache\CacheEntry;
use OC\Files\Storage\Wrapper\Wrapper;
use OC\Files\View;
use OC\Memcache\ArrayCache;
use OCP\Encryption\IEncryptionModule;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Cache\ICache;
use OCP\ICacheFactory;
use OCP\IConfig;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;

class EncryptionTest extends \Test\TestCase {
public const DEFAULT_WRAPPER = '\OC\Files\Stream\Encryption';

/** @var \OCP\Encryption\IEncryptionModule | \PHPUnit\Framework\MockObject\MockObject */
private $encryptionModule;
private IEncryptionModule&MockObject $encryptionModule;

/**
* @param string $fileName
* @param string $mode
* @param integer $unencryptedSize
* @param class-string<Wrapper> $wrapper
* @return resource
*/
protected function getStream($fileName, $mode, $unencryptedSize, $wrapper = self::DEFAULT_WRAPPER, $unencryptedSizeOnClose = 0) {
protected function getStream(string $fileName, string $mode, int $unencryptedSize, string $wrapper = self::DEFAULT_WRAPPER, int $unencryptedSizeOnClose = 0) {
clearstatcache();
$size = filesize($fileName);
$source = fopen($fileName, $mode);
Expand Down Expand Up @@ -74,31 +77,47 @@ protected function getStream($fileName, $mode, $unencryptedSize, $wrapper = self
$cache->expects($this->any())->method('get')->willReturn($entry);
$cache->expects($this->any())->method('update')->with(5, ['encrypted' => 3, 'encryptedVersion' => 3, 'unencrypted_size' => $unencryptedSizeOnClose]);


return $wrapper::wrap($source, $internalPath,
$fullPath, $header, $uid, $this->encryptionModule, $storage, $encStorage,
$util, $file, $mode, $size, $unencryptedSize, 8192, $wrapper);
return $wrapper::wrap(
$source,
$internalPath,
$fullPath,
$header,
$uid,
$this->encryptionModule,
$storage,
$encStorage,
$util,
$file,
$mode,
$size,
$unencryptedSize,
8192,
true,
$wrapper,
);
}

/**
* @dataProvider dataProviderStreamOpen()
*/
public function testStreamOpen($isMasterKeyUsed,
public function testStreamOpen(
$isMasterKeyUsed,
$mode,
$fullPath,
$fileExists,
$expectedSharePath,
$expectedSize,
$expectedUnencryptedSize,
$expectedReadOnly): void {
$expectedReadOnly,
): void {
// build mocks
$encryptionModuleMock = $this->getMockBuilder('\OCP\Encryption\IEncryptionModule')
->disableOriginalConstructor()->getMock();
$encryptionModuleMock->expects($this->any())->method('needDetailedAccessList')->willReturn(!$isMasterKeyUsed);
$encryptionModuleMock->expects($this->once())
->method('getUnencryptedBlockSize')->willReturn(99);
$encryptionModuleMock->expects($this->once())
->method('begin')->willReturn(true);
->method('begin')->willReturn([]);

$storageMock = $this->getMockBuilder('\OC\Files\Storage\Storage')
->disableOriginalConstructor()->getMock();
Expand Down Expand Up @@ -152,6 +171,8 @@ public function testStreamOpen($isMasterKeyUsed,
$header->setValue($streamWrapper, []);
$header->setAccessible(false);
$this->invokePrivate($streamWrapper, 'signed', [true]);
$this->invokePrivate($streamWrapper, 'internalPath', [$fullPath]);
$this->invokePrivate($streamWrapper, 'uid', ['test']);

// call stream_open, that's the method we want to test
$dummyVar = 'foo';
Expand All @@ -160,23 +181,17 @@ public function testStreamOpen($isMasterKeyUsed,
// check internal properties
$size = $stream->getProperty('size');
$size->setAccessible(true);
$this->assertSame($expectedSize,
$size->getValue($streamWrapper)
);
$this->assertSame($expectedSize, $size->getValue($streamWrapper));
$size->setAccessible(false);

$unencryptedSize = $stream->getProperty('unencryptedSize');
$unencryptedSize->setAccessible(true);
$this->assertSame($expectedUnencryptedSize,
$unencryptedSize->getValue($streamWrapper)
);
$this->assertSame($expectedUnencryptedSize, $unencryptedSize->getValue($streamWrapper));
$unencryptedSize->setAccessible(false);

$readOnly = $stream->getProperty('readOnly');
$readOnly->setAccessible(true);
$this->assertSame($expectedReadOnly,
$readOnly->getValue($streamWrapper)
);
$this->assertSame($expectedReadOnly, $readOnly->getValue($streamWrapper));
$readOnly->setAccessible(false);
}

Expand Down Expand Up @@ -335,10 +350,7 @@ public function testWriteToNonSeekableStorage($testFile): void {
unlink($fileName);
}

/**
* @return \PHPUnit\Framework\MockObject\MockObject
*/
protected function buildMockModule() {
protected function buildMockModule(): IEncryptionModule&MockObject {
$encryptionModule = $this->getMockBuilder('\OCP\Encryption\IEncryptionModule')
->disableOriginalConstructor()
->setMethods(['getId', 'getDisplayName', 'begin', 'end', 'encrypt', 'decrypt', 'update', 'shouldEncrypt', 'getUnencryptedBlockSize', 'isReadable', 'encryptAll', 'prepareDecryptAll', 'isReadyForUser', 'needDetailedAccessList'])
Expand Down

0 comments on commit 0420b58

Please sign in to comment.