Fixed proxy class handing of read / write files

Various work on other classes
This commit is contained in:
Sam Tuke 2013-04-10 17:37:03 +02:00
parent 854b920787
commit f378a7f572
9 changed files with 114 additions and 58 deletions

View file

@ -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();

View file

@ -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() )

View file

@ -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'] );

View file

@ -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 );
}
);
}

View file

@ -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));

View file

@ -236,7 +236,7 @@ class Stream {
$this->getUser();
$session = new Session($this->rootView);
$session = new Session( $this->rootView );
$privateKey = $session->getPrivateKey( $this->userId );

View file

@ -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 . '"' );
}
}
}

View file

@ -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-----

View file

@ -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