From bc3550b37bd3a069edc374df58218fb216056c0e Mon Sep 17 00:00:00 2001 From: Sam Tuke Date: Tue, 4 Dec 2012 19:53:13 +0000 Subject: [PATCH] Development Snapshot Opening short files via webdav, that were saved via webdav, now works --- apps/files_encryption/hooks/hooks.php | 4 +- apps/files_encryption/lib/proxy.php | 35 +++++---- apps/files_encryption/lib/util.php | 71 ++++++++++++------ apps/files_encryption/tests/proxy.php | 100 +++++++++++++++++++++++++- apps/files_encryption/tests/util.php | 3 +- 5 files changed, 172 insertions(+), 41 deletions(-) diff --git a/apps/files_encryption/hooks/hooks.php b/apps/files_encryption/hooks/hooks.php index 2c8921ef35..20ce45244a 100644 --- a/apps/files_encryption/hooks/hooks.php +++ b/apps/files_encryption/hooks/hooks.php @@ -67,7 +67,9 @@ class Hooks { $_SESSION['enckey'] = Crypt::symmetricDecryptFileContent( $encryptedKey, $params['password'] ); -// trigger_error( "\$_SESSION['enckey'] = {$_SESSION['enckey']}" ); + \OC_FileProxy::$enabled = false; + file_put_contents( '/home/samtuke/enckey', $_SESSION['enckey'] ); + \OC_FileProxy::$enabled = true; $view1 = new \OC_FilesystemView( '/' . $params['uid'] ); diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index 6dcb5e803e..914632d338 100644 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -142,14 +142,15 @@ class Proxy extends \OC_FileProxy { Crypt::mode() == 'server' && Crypt::isEncryptedContent( $data ) ) { - + //trigger_error("bong"); + $filePath = explode( '/', $path ); $filePath = array_slice( $filePath, 3 ); $filePath = '/' . implode( '/', $filePath ); - $cached = \OC_FileCache_Cached::get( $path, '' ); + //$cached = \OC_FileCache_Cached::get( $path, '' ); $keyFile = Keymanager::getFileKey( $filePath ); @@ -158,8 +159,9 @@ class Proxy extends \OC_FileProxy { } elseif ( Crypt::mode() == 'server' && isset( $_SESSION['legacyenckey'] ) - //&& Crypt::isEncryptedMeta( $path ) + && Crypt::isEncryptedMeta( $path ) ) { + trigger_error("mong"); $data = Crypt::legacyDecrypt( $data, $_SESSION['legacyenckey'] ); //trigger_error($data); @@ -180,6 +182,10 @@ class Proxy extends \OC_FileProxy { } + // Reformat path for use with OC_FSV + $path_split = explode( '/', $path ); + $path_f = implode( array_slice( $path_split, 3 ) ); + // Disable encryption proxy to prevent recursive calls \OC_FileProxy::$enabled = false; @@ -192,14 +198,17 @@ class Proxy extends \OC_FileProxy { $util = new Util( $view, \OCP\USER::getUser()); // If file is already encrypted, decrypt using crypto protocol - if ( Crypt::mode() == 'server' && $util->isEncryptedPath( $path ) ) { + if ( + Crypt::mode() == 'server' + && $util->isEncryptedPath( $path ) + ) { // Close the original encrypted file fclose( $result ); - // Open the file using the crypto protocol and let - // it do the decryption work instead - $result = fopen( 'crypt://' . $path, $meta['mode'] ); + // Open the file using the crypto stream wrapper + // protocol and let it do the decryption work instead + $result = fopen( 'crypt://' . $path_f, $meta['mode'] ); } elseif ( @@ -207,14 +216,10 @@ class Proxy extends \OC_FileProxy { and $meta ['mode'] != 'r' and $meta['mode'] != 'rb' ) { - // If the file should be encrypted and has been opened for - // reading only + // If the file is not yet encrypted, but should be + // encrypted when it's saved (it's not read only) - // Reformat path for use with OC_FSV - $path_split = explode( '/', $path ); - $path_f = implode( array_slice( $path_split, 3 ) ); - -// trigger_error("$path_f = ".var_export($path_f, 1)); + // NOTE: this is the case for new files saved via WebDAV if ( $view->file_exists( $path ) @@ -222,7 +227,7 @@ class Proxy extends \OC_FileProxy { ) { $x = $view->file_get_contents( $path ); - trigger_error( "size = ".var_export( $x, 1 ) ); + //trigger_error( "size = ".var_export( $x, 1 ) ); $tmp = tmpfile(); diff --git a/apps/files_encryption/lib/util.php b/apps/files_encryption/lib/util.php index acc0325077..907a04e5c0 100644 --- a/apps/files_encryption/lib/util.php +++ b/apps/files_encryption/lib/util.php @@ -39,33 +39,51 @@ namespace OCA\Encryption; */ class Util { - - # DONE: add method to check if file is encrypted using new system - # DONE: add method to check if file is encrypted using old system - # DONE: add method to fetch legacy key - # DONE: add method to decrypt legacy encrypted data - # DONE: fix / test the crypt stream proxy class - # DONE: replace cryptstream wrapper new AES based system - # DONE: Encryption works for writing new text files in web ui - # DONE: reading unencrypted files when encryption is enabled works via webdav - # TODO: file uploaded via web ui get encrypted - # TODO: new files created and uploaded via webdav get encrypted - # TODO: add support for optional recovery user in case of lost passphrase / keys - # TODO: add admin optional required long passphrase for users - # TODO: implement flag system to allow user to specify encryption by folder, subfolder, etc. - # TODO: add UI buttons for encrypt / decrypt everything? + # Web UI: - # TODO: add method to encrypt all user files using new system - # TODO: add method to decrypt all user files using new system - # TODO: add method to encrypt all user files using old system - # TODO: add method to decrypt all user files using old system + ## DONE: files created via web ui are encrypted + ## DONE: file created & encrypted via web ui are readable in web ui + + + # WebDAV: + + ## DONE: new data filled files added via webdav get encrypted + ## DONE: new data filled files added via webdav are readable via webdav + ## DONE: reading unencrypted files when encryption is enabled works via webdav + + # TODO: files created & encrypted via web ui are readable via webdav + + + # Legacy support: + + ## DONE: add method to check if file is encrypted using new system + ## DONE: add method to check if file is encrypted using old system + ## DONE: add method to fetch legacy key + ## DONE: add method to decrypt legacy encrypted data + + ## TODO: add method to encrypt all user files using new system + ## TODO: add method to decrypt all user files using new system + ## TODO: add method to encrypt all user files using old system + ## TODO: add method to decrypt all user files using old system + + + # Admin UI: + + ## TODO: add support for optional recovery in case of lost passphrase / keys + ## TODO: add admin optional required long passphrase for users + ## TODO: add UI buttons for encrypt / decrypt everything + ## TODO: implement flag system to allow user to specify encryption by folder, subfolder, etc. + + + # Integration testing: + + ## TODO: test new encryption with webdav + ## TODO: test new encryption with versioning + ## TODO: test new encryption with sharing + ## TODO: test new encryption with proxies - # TODO: test new encryption with webdav - # TODO: test new encryption with versioning - # TODO: test new encryption with sharing - # TODO: test new encryption with proxies # NOTE: Curretly code on line 206 onwards in lib/proxy.php needs work. This code is executed when webdav writes take place, and appears to need to convert streams into fopen resources. Currently code within the if statement on 215 is not executing. Investigate the paths (handled there (which appear to be blank), and whether oc_fsv is borking them during processing. @@ -73,6 +91,7 @@ class Util { # NOTE: for some reason file_get_contents is not working in proxy class postfopen. The same line works in sscce, but always returns an empty string in proxy.php. this is the same regardless of whether oc_fs, oc_fsv, or direct use of phps file_get_contents is used + private $view; // OC_FilesystemView object for filesystem operations private $pwd; // User Password private $client; // Client side encryption mode flag @@ -241,8 +260,14 @@ class Util { */ public function isEncryptedPath( $path ) { + // Disable encryption proxy so data retreived is in its + // original form + \OC_FileProxy::$enabled = false; + $data = $this->view->file_get_contents( $path ); + \OC_FileProxy::$enabled = true; + return Crypt::isEncryptedContent( $data ); } diff --git a/apps/files_encryption/tests/proxy.php b/apps/files_encryption/tests/proxy.php index 253a32164e..8b2c92c2f5 100644 --- a/apps/files_encryption/tests/proxy.php +++ b/apps/files_encryption/tests/proxy.php @@ -1,11 +1,109 @@ + * Copyright (c) 2012 Sam Tuke , + * and Robin Appelman * This file is licensed under the Affero General Public License version 3 or * later. * See the COPYING-README file. */ +require_once "PHPUnit/Framework/TestCase.php"; +require_once realpath( dirname(__FILE__).'/../../../lib/base.php' ); +require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery.php' ); +require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/Generator.php' ); +require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/MockInterface.php' ); +require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/Mock.php' ); +require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/Container.php' ); +require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/Configuration.php' ); +require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/CompositeExpectation.php' ); +require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/ExpectationDirector.php' ); +require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/Expectation.php' ); +require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/Exception.php' ); +require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/CountValidator/CountValidatorAbstract.php' ); +require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/CountValidator/Exception.php' ); +require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/CountValidator/Exact.php' ); + +use \Mockery as m; +use OCA\Encryption; + +class Test_Util extends \PHPUnit_Framework_TestCase { + + public function setUp() { + + $this->proxy = new Encryption\Proxy(); + + $this->tmpFileName = "tmpFile-".time(); + + $this->privateKey = file_get_contents( realpath( dirname(__FILE__).'/data/admin.public.key' ) ); + $this->publicKey = file_get_contents( realpath( dirname(__FILE__).'/data/admin.private.key' ) ); + $this->encDataShort = file_get_contents( realpath( dirname(__FILE__).'/data/yoga-manchester-enc' ) ); + $this->encDataShortKey = file_get_contents( realpath( dirname(__FILE__).'/data/yoga-manchester.key' ) ); + + $this->dataShort = file_get_contents( realpath( dirname(__FILE__).'/data/yoga-manchester' ) ); + $this->dataLong = file_get_contents( realpath( dirname(__FILE__).'/../lib/crypt.php' ) ); + $this->longDataPath = realpath( dirname(__FILE__).'/../lib/crypt.php' ); + + $this->data1 = file_get_contents( realpath( dirname(__FILE__).'/../../../data/admin/files/enc-test.txt' ) ); + + $this->userId = 'admin'; + $this->pass = 'admin'; + +$_SESSION['enckey'] = '-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDiH3EA4EpFA7Fx +s2dyyfL5jwXeYXrTqQJ6DqKgGn8VsbT3eu8R9KzM2XitVwZe8c8L52DvJ06o5vg0 +GqPYxilFdOFJe/ggac5Tq8UmJiZS4EqYEMwxBIfIyWTxeGV06/0HOwnVAkqHMcBz +64qldtgi5O8kZMEM2/gKBgU0kMLJzM+8oEWhL1+gsUWQhxd8cKLXypS6iWgqFJrz +f/X0hJsJR+gyYxNpahtnjzd/LxLAETrOMsl2tue+BAxmjbAM0aG0NEM0div+b59s +2uz/iWbxImp5pOdYVKcVW89D4XBMyGegR40trV2VwiuX1blKCfdjMsJhiaL9pymp +ug1wzyQFAgMBAAECggEAK6c+PZkPPXuVCgpEcliiW6NM0r2m5K3AGKgypQ34csu3 +z/8foCvIIFPrhCtEw5eTDQ1CHWlNOjY8vHJYJ0U6Onpx86nHIRrMBkMm8FJ1G5LJ +U8oKYXwqaozWu/cuPwA//OFc6I5krOzh5n8WaRMkbrgbor8AtebRX74By0AXGrXe +cswJI7zR96oFn4Dm7Pgvpg5Zhk1vFJ+w6QtH+4DDJ6PBvlZsRkGxYBLGVd/3qhAI +sBAyjFlSzuP4eCRhHOhHC/e4gmAH9evFVXB88jFyRZm3K+jQ5W5CwrVRBCV2lph6 +2B6P7CBJN+IjGKMhy+75y13UvvKPv9IwH8Fzl2x1gQKBgQD8qQOr7a6KhSj16wQE +jim2xqt9gQ2jH5No405NrKs/PFQQZnzD4YseQsiK//NUjOJiUhaT+L5jhIpzINHt +RJpt3bGkEZmLyjdjgTpB3GwZdXa28DNK9VdXZ19qIl/ZH0qAjKmJCRahUDASMnVi +M4Pkk9yx9ZIKkri4TcuMWqc0DQKBgQDlHKBTITZq/arYPD6Nl3NsoOdqVRqJrGay +0TjXAVbBXe46+z5lnMsqwXb79nx14hdmSEsZULrw/3f+MnQbdjMTYLFP24visZg9 +MN8vAiALiiiR1a+Crz+DTA1Q8sGOMVCMqMDmD7QBys3ZuWxuapm0txAiIYUtsjJZ +XN76T4nZ2QKBgQCHaT3igzwsWTmesxowJtEMeGWomeXpKx8h89EfqA8PkRGsyIDN +qq+YxEoe1RZgljEuaLhZDdNcGsjo8woPk9kAUPTH7fbRCMuutK+4ZJ469s1tNkcH +QX5SBcEJbOrZvv967ehe3VQXmJZq6kgnHVzuwKBjcC2ZJRGDFY6l5l/+cQKBgCqh ++Adf/8NK7paMJ0urqfPFwSodKfICXZ3apswDWMRkmSbqh4La+Uc8dsqN5Dz/VEFZ +JHhSeGbN8uMfOlG93eU2MehdPxtw1pZUWMNjjtj23XO9ooob2CKzbSrp8TBnZsi1 +widNNr66oTFpeo7VUUK6acsgF6sYJJxSVr+XO1yJAoGAEhvitq8shNKcEY0xCipS +k1kbgyS7KKB7opVxI5+ChEqyUDijS3Y9FZixrRIWE6i2uGu86UG+v2lbKvSbM4Qm +xvbOcX9OVMnlRb7n8woOP10UMY+ZE2x+YEUXQTLtPYq7F66e1OfxltstMxLQA+3d +Y1d5piFV8PXK3Fg2F+Cj5qg= +-----END PRIVATE KEY----- +'; + + \OC_User::setUserId( $this->userId ); + + } + + public function testpreFile_get_contents() { + + // This won't work for now because mocking of the static keymanager class isn't working :( + +// $mock = m::mock( 'alias:OCA\Encryption\Keymanager' ); +// +// $mock->shouldReceive( 'getFileKey' )->times(2)->andReturn( $this->encDataShort ); +// +// $encrypted = $this->proxy->postFile_get_contents( 'data/'.$this->tmpFileName, $this->encDataShortKey ); +// +// $this->assertNotEquals( $this->dataShort, $encrypted ); +// +// var_dump($encrypted); + + $decrypted = $this->proxy->postFile_get_contents( 'data/admin/files/enc-test.txt', $this->data1 ); + + var_dump($decrypted); + + } + +} + // class Test_CryptProxy extends UnitTestCase { // private $oldConfig; // private $oldKey; diff --git a/apps/files_encryption/tests/util.php b/apps/files_encryption/tests/util.php index 593eabd0d5..556ba11fe5 100755 --- a/apps/files_encryption/tests/util.php +++ b/apps/files_encryption/tests/util.php @@ -9,9 +9,10 @@ require_once "PHPUnit/Framework/TestCase.php"; require_once realpath( dirname(__FILE__).'/../../../lib/base.php' ); require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery.php' ); -require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/Container.php' ); require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/Generator.php' ); require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/MockInterface.php' ); +require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/Mock.php' ); +require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/Container.php' ); require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/Configuration.php' ); require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/CompositeExpectation.php' ); require_once realpath( dirname(__FILE__).'/../../../3rdparty/mockery/Mockery/ExpectationDirector.php' );