Fixed proxy class handing of read / write files
Various work on other classes
This commit is contained in:
parent
854b920787
commit
f378a7f572
9 changed files with 114 additions and 58 deletions
|
@ -15,6 +15,8 @@ use OCA\Encryption;
|
|||
\OCP\JSON::checkAppEnabled( 'files_encryption' );
|
||||
\OCP\JSON::callCheck();
|
||||
|
||||
$return = $doSetup = false;
|
||||
|
||||
if (
|
||||
isset( $_POST['adminEnableRecovery'] )
|
||||
&& $_POST['adminEnableRecovery'] == 1
|
||||
|
@ -47,7 +49,7 @@ if (
|
|||
// If the recoveryAdmin UID exists but doesn't have admin rights
|
||||
} else {
|
||||
|
||||
\OCP\JSON::error();
|
||||
$return = false;
|
||||
|
||||
}
|
||||
|
||||
|
@ -63,10 +65,12 @@ if (
|
|||
$util->setupServerSide( $_POST['recoveryPassword'] );
|
||||
|
||||
// Store the UID in the DB
|
||||
OC_Appconfig::setValue( 'encryption', 'recoveryAdminUid', $recoveryAdminUid );
|
||||
OC_Appconfig::setValue( 'files_encryption', 'recoveryAdminUid', $recoveryAdminUid );
|
||||
|
||||
\OCP\JSON::success();
|
||||
$return = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
($return) ? OC_JSON::success() : OC_JSON::error();
|
|
@ -24,8 +24,10 @@ OCP\Util::connectHook( 'OCP\Share', 'post_unshareAll', 'OCA\Encryption\Hooks', '
|
|||
OCP\Util::connectHook( 'OC_Webdav_Properties', 'update', 'OCA\Encryption\Hooks', 'updateKeyfileFromClient' );
|
||||
|
||||
stream_wrapper_register( 'crypt', 'OCA\Encryption\Stream' );
|
||||
$view = new OC_FilesystemView('/');
|
||||
$session = new OCA\Encryption\Session($view);
|
||||
|
||||
$view = new OC_FilesystemView( '/' );
|
||||
|
||||
$session = new OCA\Encryption\Session( $view );
|
||||
|
||||
if (
|
||||
! $session->getPrivateKey( \OCP\USER::getUser() )
|
||||
|
|
|
@ -63,7 +63,7 @@ class Hooks {
|
|||
|
||||
$privateKey = Crypt::symmetricDecryptFileContent( $encryptedKey, $params['password'] );
|
||||
|
||||
$session = new Session($view);
|
||||
$session = new Session( $view );
|
||||
|
||||
$session->setPrivateKey( $privateKey, $params['uid'] );
|
||||
|
||||
|
@ -116,8 +116,8 @@ class Hooks {
|
|||
// is in use (client-side encryption does not have access to
|
||||
// the necessary keys)
|
||||
if ( Crypt::mode() == 'server' ) {
|
||||
$view = new \OC_FilesystemView( '/' );
|
||||
$session = new Session($view);
|
||||
|
||||
$session = new Session();
|
||||
|
||||
// Get existing decrypted private key
|
||||
$privateKey = $session->getPrivateKey();
|
||||
|
@ -189,7 +189,7 @@ class Hooks {
|
|||
if ( $params['itemType'] === 'file' ) {
|
||||
|
||||
$view = new \OC_FilesystemView( '/' );
|
||||
$session = new Session($view);
|
||||
$session = new Session();
|
||||
$userId = \OCP\User::getUser();
|
||||
$util = new Util( $view, $userId );
|
||||
$path = $util->fileIdToPath( $params['itemSource'] );
|
||||
|
@ -244,7 +244,7 @@ class Hooks {
|
|||
if ( $params['itemType'] === 'file' ) {
|
||||
|
||||
$view = new \OC_FilesystemView( '/' );
|
||||
$session = new Session($view);
|
||||
$session = new Session();
|
||||
$userId = \OCP\User::getUser();
|
||||
$util = new Util( $view, $userId );
|
||||
$path = $util->fileIdToPath( $params['itemSource'] );
|
||||
|
|
|
@ -16,11 +16,14 @@ $(document).ready(function(){
|
|||
// Trigger ajax on recoveryAdmin status change
|
||||
$( 'input:radio[name="adminEnableRecovery"]' ).change(
|
||||
function() {
|
||||
|
||||
var foo = $( this ).val();
|
||||
|
||||
$.post(
|
||||
'../ajax/adminrecovery.php'
|
||||
, $( this ).val()
|
||||
OC.filePath('files_encryption', 'ajax', 'adminrecovery.php')
|
||||
, { adminEnableRecovery: foo, recoveryPassword: 'password' }
|
||||
, function( data ) {
|
||||
// TODO: provide user with feedback of outcome
|
||||
alert( data );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ class Proxy extends \OC_FileProxy {
|
|||
$userId = \OCP\USER::getUser();
|
||||
$rootView = new \OC_FilesystemView( '/' );
|
||||
$util = new Util( $rootView, $userId );
|
||||
$session = new Session($rootView);
|
||||
$session = new Session( $rootView );
|
||||
$fileOwner = \OC\Files\Filesystem::getOwner( $path );
|
||||
$privateKey = $session->getPrivateKey();
|
||||
$filePath = $util->stripUserFilesPath( $path );
|
||||
|
@ -115,9 +115,16 @@ class Proxy extends \OC_FileProxy {
|
|||
if ( $encKeyfile = Keymanager::getFileKey( $rootView, $fileOwner, $filePath ) ) {
|
||||
|
||||
$keyPreExists = true;
|
||||
|
||||
|
||||
// Fetch shareKey
|
||||
$shareKey = Keymanager::getShareKey( $rootView, $userId, $filePath );
|
||||
|
||||
// Decrypt the keyfile
|
||||
$plainKey = $util->decryptUnknownKeyfile( $filePath, $fileOwner, $privateKey );
|
||||
$plainKey = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey );
|
||||
|
||||
trigger_error("\$shareKey = $shareKey");
|
||||
|
||||
trigger_error("\$plainKey = $plainKey");
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -170,6 +177,7 @@ class Proxy extends \OC_FileProxy {
|
|||
|
||||
// Save sharekeys to user folders
|
||||
// TODO: openssl_seal generates new shareKeys (envelope keys) each time data is encrypted, but will data still be decryptable using old shareKeys? If so we don't need to replace the old shareKeys here, we only need to set the new ones
|
||||
|
||||
Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] );
|
||||
|
||||
// Set encrypted keyfile as common varname
|
||||
|
@ -219,15 +227,18 @@ class Proxy extends \OC_FileProxy {
|
|||
// If data is a catfile
|
||||
if (
|
||||
Crypt::mode() == 'server'
|
||||
&& Crypt::isCatfileContent( $data )
|
||||
&& Crypt::isCatfileContent( $data ) // TODO: Do we really need this check? Can't we assume it is properly encrypted?
|
||||
) {
|
||||
|
||||
// TODO use get owner to find correct location of key files for shared files
|
||||
$session = new Session($view);
|
||||
// TODO: use get owner to find correct location of key files for shared files
|
||||
$session = new Session( $view );
|
||||
$privateKey = $session->getPrivateKey( $userId );
|
||||
|
||||
// Get the file owner so we can retrieve its keyfile
|
||||
list($fileOwner, $ownerPath) = $util->getUidAndFilename($relPath);
|
||||
// list( $fileOwner, $ownerPath ) = $util->getUidAndFilename( $relPath );
|
||||
|
||||
$fileOwner = \OC\Files\Filesystem::getOwner( $path );
|
||||
$ownerPath = $util->stripUserFilesPath( $path ); // TODO: Don't trust $path, fetch owner path
|
||||
|
||||
// Get the encrypted keyfile
|
||||
$encKeyfile = Keymanager::getFileKey( $view, $fileOwner, $ownerPath );
|
||||
|
@ -235,27 +246,9 @@ class Proxy extends \OC_FileProxy {
|
|||
// Attempt to fetch the user's shareKey
|
||||
$shareKey = Keymanager::getShareKey( $view, $userId, $relPath );
|
||||
|
||||
// Check if key is shared or not
|
||||
if ( $shareKey ) {
|
||||
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
// trigger_error("\$encKeyfile = $encKeyfile, \$shareKey = $shareKey, \$privateKey = $privateKey");
|
||||
|
||||
// Decrypt keyfile with shareKey
|
||||
$plainKeyfile = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey );
|
||||
|
||||
// $plainKeyfile = $encKeyfile;
|
||||
|
||||
// trigger_error("PROXY plainkeyfile = ". var_export($plainKeyfile, 1));
|
||||
|
||||
} else {
|
||||
|
||||
// If key is unshared, decrypt with user private key
|
||||
$plainKeyfile = Crypt::keyDecrypt( $encKeyfile, $privateKey );
|
||||
|
||||
}
|
||||
|
||||
// Decrypt keyfile with shareKey
|
||||
$plainKeyfile = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey );
|
||||
|
||||
$plainData = Crypt::symmetricDecryptFileContent( $data, $plainKeyfile );
|
||||
|
||||
// trigger_error("PLAINDATA = ". var_export($plainData, 1));
|
||||
|
|
|
@ -236,7 +236,7 @@ class Stream {
|
|||
|
||||
$this->getUser();
|
||||
|
||||
$session = new Session($this->rootView);
|
||||
$session = new Session( $this->rootView );
|
||||
|
||||
$privateKey = $session->getPrivateKey( $this->userId );
|
||||
|
||||
|
|
|
@ -24,13 +24,17 @@
|
|||
# Bugs
|
||||
# ----
|
||||
# Sharing a file to a user without encryption set up will not provide them with access but won't notify the sharer
|
||||
# Timeouts on first login due to encryption of very large files
|
||||
# Sharing files to other users currently broken (due to merge + ongoing implementation of support for lost password recovery)
|
||||
# Timeouts on first login due to encryption of very large files (fix in progress, as a result streaming is currently broken)
|
||||
# Sharing all files to admin for recovery purposes still in progress
|
||||
# Possibly public links are broken (not tested since last merge of master)
|
||||
# getOwner() currently returns false in all circumstances, unsure what code is returning this...
|
||||
|
||||
|
||||
# Missing features
|
||||
# ----------------
|
||||
# Re-use existing keyfiles so they don't need version control (part implemented, stream{} and util{} remain)
|
||||
# Make sure user knows if large files weren't encrypted
|
||||
# Support for resharing encrypted files
|
||||
|
||||
|
||||
# Test
|
||||
|
@ -122,7 +126,8 @@ class Util {
|
|||
$this->userId = $userId;
|
||||
$this->client = $client;
|
||||
$this->userDir = '/' . $this->userId;
|
||||
$this->userFilesDir = '/' . $this->userId . '/' . 'files';
|
||||
$this->fileFolderName = 'files';
|
||||
$this->userFilesDir = '/' . $this->userId . '/' . $this->fileFolderName; // TODO: Does this need to be user configurable?
|
||||
$this->publicKeyDir = '/' . 'public-keys';
|
||||
$this->encryptionDir = '/' . $this->userId . '/' . 'files_encryption';
|
||||
$this->keyfilesPath = $this->encryptionDir . '/' . 'keyfiles';
|
||||
|
@ -690,7 +695,6 @@ class Util {
|
|||
|
||||
/**
|
||||
* @brief Expand given path to all sub files & folders
|
||||
* @param Session $session
|
||||
* @param string $path path which needs to be updated
|
||||
* @return array $pathsArray all found file paths
|
||||
* @note Paths of directories excluded, only *file* paths are returned
|
||||
|
@ -747,6 +751,8 @@ class Util {
|
|||
* @param string $privateKey
|
||||
* @note Checks whether file was encrypted with openssl_seal or
|
||||
* openssl_encrypt, and decrypts accrdingly
|
||||
* @note This was used when 2 types of encryption for keyfiles was used,
|
||||
* but now we've switched to exclusively using openssl_seal()
|
||||
*/
|
||||
public function decryptUnknownKeyfile( $filePath, $fileOwner, $privateKey ) {
|
||||
|
||||
|
@ -861,19 +867,55 @@ class Util {
|
|||
|
||||
/**
|
||||
* @brief get uid of the owners of the file and the path to the file
|
||||
* @param $filename
|
||||
* @param $shareFilePath Path of the file to check
|
||||
* @note $shareFilePath must be relative to data/UID/files. Files
|
||||
* relative to /Shared are also acceptable
|
||||
* @return array
|
||||
*/
|
||||
public function getUidAndFilename($filename) {
|
||||
$uid = \OC\Files\Filesystem::getOwner($filename);
|
||||
|
||||
\OC\Files\Filesystem::initMountPoints($uid);
|
||||
if ( $uid != \OCP\User::getUser() ) {
|
||||
$info = \OC\Files\Filesystem::getFileInfo($filename);
|
||||
$ownerView = new \OC\Files\View('/'.$uid.'/files');
|
||||
$filename = $ownerView->getPath($info['fileid']);
|
||||
public function getUidAndFilename( $shareFilePath ) {
|
||||
|
||||
$fileOwnerUid = \OC\Files\Filesystem::getOwner( $shareFilePath );
|
||||
|
||||
// Check that UID is valid
|
||||
if ( ! \OCP\User::userExists( $fileOwnerUid ) ) {
|
||||
|
||||
throw new \Exception( 'Could not find owner (UID = "' . var_export( $fileOwnerUid, 1 ) . '") of file "' . $shareFilePath . '"' );
|
||||
|
||||
}
|
||||
return array($uid, $filename);
|
||||
|
||||
// NOTE: Bah, this dependency should be elsewhere
|
||||
\OC\Files\Filesystem::initMountPoints( $fileOwnerUid );
|
||||
|
||||
// If the file owner is the currently logged in user
|
||||
if ( $fileOwnerUid == $this->userId ) {
|
||||
|
||||
// Assume the path supplied is correct
|
||||
$filename = $shareFilePath;
|
||||
|
||||
} else {
|
||||
|
||||
$info = \OC\Files\Filesystem::getFileInfo( $shareFilePath );
|
||||
$ownerView = new \OC\Files\View( '/' . $fileOwnerUid . '/files' );
|
||||
|
||||
// Fetch real file path from DB
|
||||
$filename = $ownerView->getPath( $info['fileid'] ); // TODO: Check that this returns a path without including the user data dir
|
||||
|
||||
}
|
||||
|
||||
// Make path relative for use by $view
|
||||
$relpath = $fileOwnerUid . '/' . $this->fileFolderName . '/' . $filename;
|
||||
|
||||
// Check that the filename we're using is working
|
||||
if ( $this->view->file_exists( $relpath ) ) {
|
||||
|
||||
return array ( $fileOwnerUid, $relpath );
|
||||
|
||||
} else {
|
||||
|
||||
throw new \Exception( 'Supplied path could not be resolved "' . $shareFilePath . '"' );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
// $this->userId = 'admin';
|
||||
// $this->pass = 'admin';
|
||||
//
|
||||
// $this->session = new Encryption\Session();
|
||||
// $this->session = new Encryption\Session( $view ); // FIXME: Provide a $view object for use here
|
||||
//
|
||||
// $this->session->setPrivateKey(
|
||||
// '-----BEGIN PRIVATE KEY-----
|
||||
|
|
|
@ -24,6 +24,8 @@ $loader->register();
|
|||
use \Mockery as m;
|
||||
use OCA\Encryption;
|
||||
|
||||
\OC_User::login( 'admin', 'admin' );
|
||||
|
||||
class Test_Enc_Util extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
function setUp() {
|
||||
|
@ -184,6 +186,16 @@ class Test_Enc_Util extends \PHPUnit_Framework_TestCase {
|
|||
$this->assertTrue( $util->setRecovery( $enabled ) );
|
||||
|
||||
}
|
||||
|
||||
function testGetUidAndFilename() {
|
||||
|
||||
\OC_User::setUserId( 'admin' );
|
||||
|
||||
$this->util->getUidAndFilename( 'test1.txt' );
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @brief test decryption using legacy blowfish method
|
||||
|
|
Loading…
Reference in a new issue