Implementing sharing support
New file-specific methods in lib/public/share Changes to how keyfiles are stored
This commit is contained in:
parent
b3e59ca1e3
commit
92f06243be
|
@ -82,8 +82,12 @@ class Hooks {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
\OC_FileProxy::$enabled = false;
|
||||||
|
|
||||||
$publicKey = Keymanager::getPublicKey( $view, $params['uid'] );
|
$publicKey = Keymanager::getPublicKey( $view, $params['uid'] );
|
||||||
|
|
||||||
|
\OC_FileProxy::$enabled = false;
|
||||||
|
|
||||||
// Encrypt existing user files:
|
// Encrypt existing user files:
|
||||||
// This serves to upgrade old versions of the encryption
|
// This serves to upgrade old versions of the encryption
|
||||||
// app (see appinfo/spec.txt)
|
// app (see appinfo/spec.txt)
|
||||||
|
@ -175,8 +179,9 @@ class Hooks {
|
||||||
$view = new \OC_FilesystemView( '/' );
|
$view = new \OC_FilesystemView( '/' );
|
||||||
$userId = \OCP\User::getUser();
|
$userId = \OCP\User::getUser();
|
||||||
$util = new Util( $view, $userId );
|
$util = new Util( $view, $userId );
|
||||||
|
$session = new Session();
|
||||||
|
|
||||||
$shares = \OCP\Share::getUsersSharingFile( $params['fileTarget'] );
|
$shares = \OCP\Share::getUsersSharingFile( $params['fileTarget'], 1 );
|
||||||
|
|
||||||
$userIds = array();
|
$userIds = array();
|
||||||
|
|
||||||
|
@ -202,41 +207,35 @@ class Hooks {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trigger_error("UIDS = ".var_export($userIds, 1));
|
|
||||||
|
|
||||||
$userPubKeys = Keymanager::getPublicKeys( $view, $userIds );
|
$userPubKeys = Keymanager::getPublicKeys( $view, $userIds );
|
||||||
|
|
||||||
// trigger_error("PUB KEYS = ".var_export($userPubKeys, 1));
|
\OC_FileProxy::$enabled = false;
|
||||||
|
|
||||||
// TODO: Fetch path from Crypt{} getter
|
// get the keyfile
|
||||||
$plainContent = $view->file_get_contents( $userId . '/' . 'files'. '/' . $params['fileTarget'] );
|
$encKeyfile = Keymanager::getFileKey( $view, $userId, $params['fileTarget'] );
|
||||||
|
|
||||||
// Generate new catfile and share keys
|
$privateKey = $session->getPrivateKey();
|
||||||
if ( ! $encrypted = Crypt::multiKeyEncrypt( $plainContent, $userPubKeys ) ) {
|
|
||||||
|
|
||||||
// If the re-encryption failed, don't risk deleting data
|
// decrypt the keyfile
|
||||||
return false;
|
$plainKeyfile = Crypt::keyDecrypt( $encKeyfile, $privateKey );
|
||||||
|
|
||||||
|
// re-enc keyfile to sharekeys
|
||||||
|
$shareKeys = Crypt::multiKeyEncrypt( $plainKeyfile, $userPubKeys );
|
||||||
|
|
||||||
|
// save sharekeys
|
||||||
|
if ( ! Keymanager::setShareKeys( $view, $params['fileTarget'], $shareKeys['keys'] ) ) {
|
||||||
|
|
||||||
|
trigger_error( "SET Share keys failed" );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trigger_error("ENCRYPTED = ". var_export($encrypted, 1));
|
// Delete existing keyfile
|
||||||
|
|
||||||
// Save env keys to user folders
|
|
||||||
foreach ( $encrypted['keys'] as $key ) {
|
|
||||||
|
|
||||||
// Keymanager::setShareKey( $view, $params['fileTarget'], $userId, $key );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete existing catfile
|
|
||||||
// Check if keyfile exists (it won't if file has been shared before)
|
|
||||||
// Do this last to ensure file is recoverable in case of error
|
// Do this last to ensure file is recoverable in case of error
|
||||||
if ( $util->isEncryptedPath( $params['fileTarget'] ) ) {
|
// Keymanager::deleteFileKey( $view, $userId, $params['fileTarget'] );
|
||||||
|
|
||||||
// NOTE: This will trigger an error if keyfile isn't found
|
\OC_FileProxy::$enabled = true;
|
||||||
// Keymanager::deleteFileKey( $params['fileTarget'] );
|
|
||||||
|
|
||||||
}
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -370,22 +370,41 @@ class Crypt {
|
||||||
/**
|
/**
|
||||||
* @brief Create asymmetrically encrypted keyfile content using a generated key
|
* @brief Create asymmetrically encrypted keyfile content using a generated key
|
||||||
* @param string $plainContent content to be encrypted
|
* @param string $plainContent content to be encrypted
|
||||||
* @returns array keys: key, encrypted
|
* @param array $publicKeys array keys must be the userId of corresponding user
|
||||||
* @note symmetricDecryptFileContent() can be used to decrypt files created using this method
|
* @returns array keys: keys (array, key = userId), encrypted
|
||||||
*
|
* @note symmetricDecryptFileContent() can decrypt files created using this method
|
||||||
* This function decrypts a file
|
|
||||||
*/
|
*/
|
||||||
public static function multiKeyEncrypt( $plainContent, array $publicKeys ) {
|
public static function multiKeyEncrypt( $plainContent, array $publicKeys ) {
|
||||||
|
|
||||||
|
// openssl_seal returns false without errors if $plainContent
|
||||||
|
// is empty, so trigger our own error
|
||||||
|
if ( empty( $plainContent ) ) {
|
||||||
|
|
||||||
|
trigger_error( "Cannot mutliKeyEncrypt empty plain content" );
|
||||||
|
throw new \Exception( 'Cannot mutliKeyEncrypt empty plain content' );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Set empty vars to be set by openssl by reference
|
// Set empty vars to be set by openssl by reference
|
||||||
$sealed = '';
|
$sealed = '';
|
||||||
$envKeys = array();
|
$shareKeys = array();
|
||||||
|
|
||||||
if( openssl_seal( $plainContent, $sealed, $envKeys, $publicKeys ) ) {
|
if( openssl_seal( $plainContent, $sealed, $shareKeys, $publicKeys ) ) {
|
||||||
|
|
||||||
|
$i = 0;
|
||||||
|
|
||||||
|
// Ensure each shareKey is labelled with its
|
||||||
|
// corresponding userId
|
||||||
|
foreach ( $publicKeys as $userId => $publicKey ) {
|
||||||
|
|
||||||
|
$mappedShareKeys[$userId] = $shareKeys[$i];
|
||||||
|
$i++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'keys' => $envKeys
|
'keys' => $mappedShareKeys
|
||||||
, 'encrypted' => $sealed
|
, 'data' => $sealed
|
||||||
);
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -404,7 +423,7 @@ class Crypt {
|
||||||
*
|
*
|
||||||
* This function decrypts a file
|
* This function decrypts a file
|
||||||
*/
|
*/
|
||||||
public static function multiKeyDecrypt( $encryptedContent, $envKey, $privateKey ) {
|
public static function multiKeyDecrypt( $encryptedContent, $shareKey, $privateKey ) {
|
||||||
|
|
||||||
if ( !$encryptedContent ) {
|
if ( !$encryptedContent ) {
|
||||||
|
|
||||||
|
@ -412,7 +431,7 @@ class Crypt {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( openssl_open( $encryptedContent, $plainContent, $envKey, $privateKey ) ) {
|
if ( openssl_open( $encryptedContent, $plainContent, $shareKey, $privateKey ) ) {
|
||||||
|
|
||||||
return $plainContent;
|
return $plainContent;
|
||||||
|
|
||||||
|
|
|
@ -52,8 +52,11 @@ class Keymanager {
|
||||||
*/
|
*/
|
||||||
public static function getPublicKey( \OC_FilesystemView $view, $userId ) {
|
public static function getPublicKey( \OC_FilesystemView $view, $userId ) {
|
||||||
|
|
||||||
|
\OC_FileProxy::$enabled = false;
|
||||||
|
|
||||||
return $view->file_get_contents( '/public-keys/' . '/' . $userId . '.public.key' );
|
return $view->file_get_contents( '/public-keys/' . '/' . $userId . '.public.key' );
|
||||||
|
|
||||||
|
\OC_FileProxy::$enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,20 +80,16 @@ class Keymanager {
|
||||||
* @param array $userIds
|
* @param array $userIds
|
||||||
* @return array of public keys for the specified users
|
* @return array of public keys for the specified users
|
||||||
*/
|
*/
|
||||||
public static function getPublicKeys( \OC_FilesystemView $view, $userIds ) {
|
public static function getPublicKeys( \OC_FilesystemView $view, array $userIds ) {
|
||||||
|
|
||||||
$i = 0;
|
|
||||||
$keys = array();
|
$keys = array();
|
||||||
|
|
||||||
foreach ( $userIds as $userId ) {
|
foreach ( $userIds as $userId ) {
|
||||||
|
|
||||||
$i++;
|
|
||||||
$keys[$userId] = self::getPublicKey( $view, $userId );
|
$keys[$userId] = self::getPublicKey( $view, $userId );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$keys['total'] = $i;
|
|
||||||
|
|
||||||
return $keys;
|
return $keys;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -137,11 +136,11 @@ class Keymanager {
|
||||||
|
|
||||||
$filePath_f = ltrim( $filePath, '/' );
|
$filePath_f = ltrim( $filePath, '/' );
|
||||||
|
|
||||||
$catfilePath = '/' . $userId . '/files_encryption/keyfiles/' . $filePath_f . '.key';
|
$keyfilePath = '/' . $userId . '/files_encryption/keyfiles/' . $filePath_f . '.key';
|
||||||
|
|
||||||
if ( $view->file_exists( $catfilePath ) ) {
|
if ( $view->file_exists( $keyfilePath ) ) {
|
||||||
|
|
||||||
return $view->file_get_contents( $catfilePath );
|
return $view->file_get_contents( $keyfilePath );
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
@ -239,7 +238,7 @@ class Keymanager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief store file encryption key
|
* @brief store share key
|
||||||
*
|
*
|
||||||
* @param string $path relative path of the file, including filename
|
* @param string $path relative path of the file, including filename
|
||||||
* @param string $key
|
* @param string $key
|
||||||
|
@ -255,7 +254,85 @@ class Keymanager {
|
||||||
|
|
||||||
$shareKeyPath = self::keySetPreparation( $view, $path, $basePath, $userId );
|
$shareKeyPath = self::keySetPreparation( $view, $path, $basePath, $userId );
|
||||||
|
|
||||||
return $view->file_put_contents( $basePath . '/' . $shareKeyPath . '.shareKey', $shareKey );
|
$writePath = $basePath . '/' . $shareKeyPath . '.shareKey';
|
||||||
|
|
||||||
|
\OC_FileProxy::$enabled = false;
|
||||||
|
|
||||||
|
$result = $view->file_put_contents( $writePath, $shareKey );
|
||||||
|
|
||||||
|
if (
|
||||||
|
is_int( $result )
|
||||||
|
&& $result > 0
|
||||||
|
) {
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief store multiple share keys for a single file
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function setShareKeys( \OC_FilesystemView $view, $path, array $shareKeys ) {
|
||||||
|
|
||||||
|
// $shareKeys must be an array with the following format:
|
||||||
|
// [userId] => [encrypted key]
|
||||||
|
|
||||||
|
$result = true;
|
||||||
|
|
||||||
|
foreach ( $shareKeys as $userId => $shareKey ) {
|
||||||
|
|
||||||
|
if ( ! self::setShareKey( $view, $path, $userId, $shareKey ) ) {
|
||||||
|
|
||||||
|
// If any of the keys are not set, flag false
|
||||||
|
$result = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns false if any of the keys weren't set
|
||||||
|
return $result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief retrieve shareKey for an encrypted file
|
||||||
|
* @param \OC_FilesystemView $view
|
||||||
|
* @param $userId
|
||||||
|
* @param $filePath
|
||||||
|
* @internal param \OCA\Encryption\file $string name
|
||||||
|
* @return string file key or false
|
||||||
|
* @note The sharekey returned is encrypted. Decryption
|
||||||
|
* of the keyfile must be performed by client code
|
||||||
|
*/
|
||||||
|
public static function getShareKey( \OC_FilesystemView $view, $userId, $filePath ) {
|
||||||
|
|
||||||
|
\OC_FileProxy::$enabled = false;
|
||||||
|
|
||||||
|
$filePath_f = ltrim( $filePath, '/' );
|
||||||
|
|
||||||
|
$shareKeyPath = '/' . $userId . '/files_encryption/share-keys/' . $filePath_f . '.shareKey';
|
||||||
|
|
||||||
|
if ( $view->file_exists( $shareKeyPath ) ) {
|
||||||
|
|
||||||
|
$result = $view->file_get_contents( $shareKeyPath );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
$result = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
\OC_FileProxy::$enabled = true;
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,58 +99,65 @@ class Proxy extends \OC_FileProxy {
|
||||||
if ( !is_resource( $data ) ) {
|
if ( !is_resource( $data ) ) {
|
||||||
|
|
||||||
$userId = \OCP\USER::getUser();
|
$userId = \OCP\USER::getUser();
|
||||||
|
|
||||||
$rootView = new \OC_FilesystemView( '/' );
|
$rootView = new \OC_FilesystemView( '/' );
|
||||||
|
$util = new Util( $rootView, $userId );
|
||||||
|
$filePath = $util->stripUserFilesPath( $path );
|
||||||
// Set the filesize for userland, before encrypting
|
// Set the filesize for userland, before encrypting
|
||||||
$size = strlen( $data );
|
$size = strlen( $data );
|
||||||
|
|
||||||
// Disable encryption proxy to prevent recursive calls
|
// Disable encryption proxy to prevent recursive calls
|
||||||
\OC_FileProxy::$enabled = false;
|
\OC_FileProxy::$enabled = false;
|
||||||
|
|
||||||
$fileOwner = \OC\Files\Filesystem::getOwner( $path );
|
// Encrypt data
|
||||||
|
$encData = Crypt::symmetricEncryptFileContentKeyfile( $data );
|
||||||
|
|
||||||
// Check if the keyfile needs to be shared
|
// Check if the keyfile needs to be shared
|
||||||
if (
|
if ( \OCP\Share::isSharedFile( $filePath ) ) {
|
||||||
$fileOwner !== true
|
|
||||||
or $fileOwner !== $userId
|
// $fileOwner = \OC\Files\Filesystem::getOwner( $path );
|
||||||
) {
|
|
||||||
|
// List everyone sharing the file
|
||||||
|
$shares = \OCP\Share::getUsersSharingFile( $filePath, 1 );
|
||||||
|
|
||||||
|
$userIds = array();
|
||||||
|
|
||||||
|
foreach ( $shares as $share ) {
|
||||||
|
|
||||||
|
$userIds[] = $share['userId'];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$publicKeys = Keymanager::getPublicKeys( $rootView, $userIds );
|
||||||
|
|
||||||
|
\OC_FileProxy::$enabled = false;
|
||||||
|
|
||||||
|
// Encrypt plain keyfile to multiple sharefiles
|
||||||
|
$multiEncrypted = Crypt::multiKeyEncrypt( $encData['key'], $publicKeys );
|
||||||
|
|
||||||
|
// Save sharekeys to user folders
|
||||||
|
Keymanager::setShareKeys( $rootView, $filePath, $multiEncrypted['keys'] );
|
||||||
|
|
||||||
|
// Set encrypted keyfile as common varname
|
||||||
|
$encKey = $multiEncrypted['encrypted'];
|
||||||
|
|
||||||
// Shared storage backend isn't loaded
|
|
||||||
|
|
||||||
$users = \OCP\Share::getItemShared( 'file', $path, \OC_Share_backend_File::FORMAT_SHARED_STORAGE );
|
|
||||||
//
|
|
||||||
trigger_error("SHARE USERS = ". var_export($users, 1));
|
|
||||||
//
|
|
||||||
// $publicKeys = Keymanager::getPublicKeys( $rootView, $users);
|
|
||||||
//
|
|
||||||
// // Encrypt plain data to multiple users
|
|
||||||
// $encrypted = Crypt::multiKeyEncrypt( $data, $publicKeys );
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
$publicKey = Keymanager::getPublicKey( $rootView, $userId );
|
$publicKey = Keymanager::getPublicKey( $rootView, $userId );
|
||||||
|
|
||||||
// Encrypt plain data to a single user
|
// Encrypt plain data to a single user
|
||||||
$encrypted = Crypt::keyEncryptKeyfile( $data, $publicKey );
|
$encKey = Crypt::keyEncrypt( $encData['key'], $publicKey );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace plain content with encrypted content by reference
|
// TODO: Replace userID with ownerId so keyfile is saved centrally
|
||||||
$data = $encrypted['data'];
|
|
||||||
|
|
||||||
$filePath = explode( '/', $path );
|
|
||||||
|
|
||||||
$filePath = array_slice( $filePath, 3 );
|
|
||||||
|
|
||||||
$filePath = '/' . implode( '/', $filePath );
|
|
||||||
|
|
||||||
// TODO: make keyfile dir dynamic from app config
|
|
||||||
|
|
||||||
$view = new \OC_FilesystemView( '/' );
|
|
||||||
|
|
||||||
// Save keyfile for newly encrypted file in parallel directory tree
|
// Save keyfile for newly encrypted file in parallel directory tree
|
||||||
Keymanager::setFileKey( $view, $filePath, $userId, $encrypted['key'] );
|
Keymanager::setFileKey( $rootView, $filePath, $userId, $encKey );
|
||||||
|
|
||||||
|
// Replace plain content with encrypted content by reference
|
||||||
|
$data = $encData['encrypted'];
|
||||||
|
|
||||||
// Update the file cache with file info
|
// Update the file cache with file info
|
||||||
\OC\Files\Filesystem::putFileInfo( $path, array( 'encrypted'=>true, 'size' => $size ), '' );
|
\OC\Files\Filesystem::putFileInfo( $path, array( 'encrypted'=>true, 'size' => $size ), '' );
|
||||||
|
@ -169,8 +176,6 @@ class Proxy extends \OC_FileProxy {
|
||||||
*/
|
*/
|
||||||
public function postFile_get_contents( $path, $data ) {
|
public function postFile_get_contents( $path, $data ) {
|
||||||
|
|
||||||
// TODO: Use dependency injection to add required args for view and user etc. to this method
|
|
||||||
|
|
||||||
// Disable encryption proxy to prevent recursive calls
|
// Disable encryption proxy to prevent recursive calls
|
||||||
\OC_FileProxy::$enabled = false;
|
\OC_FileProxy::$enabled = false;
|
||||||
|
|
||||||
|
@ -180,25 +185,35 @@ class Proxy extends \OC_FileProxy {
|
||||||
&& Crypt::isCatfile( $data )
|
&& Crypt::isCatfile( $data )
|
||||||
) {
|
) {
|
||||||
|
|
||||||
$split = explode( '/', $path );
|
$view = new \OC_FilesystemView( '/' );
|
||||||
|
|
||||||
$filePath = array_slice( $split, 3 );
|
|
||||||
|
|
||||||
$filePath = '/' . implode( '/', $filePath );
|
|
||||||
|
|
||||||
//$cached = \OC\Files\Filesystem::getFileInfo( $path, '' );
|
|
||||||
|
|
||||||
$view = new \OC_FilesystemView( '' );
|
|
||||||
|
|
||||||
$userId = \OCP\USER::getUser();
|
$userId = \OCP\USER::getUser();
|
||||||
|
|
||||||
// TODO: Check if file is shared, if so, use multiKeyDecrypt
|
|
||||||
|
|
||||||
$encryptedKeyfile = Keymanager::getFileKey( $view, $userId, $filePath );
|
|
||||||
|
|
||||||
$session = new Session();
|
$session = new Session();
|
||||||
|
$util = new Util( $view, $userId );
|
||||||
|
$filePath = $util->stripUserFilesPath( $path );
|
||||||
|
$privateKey = $session->getPrivateKey( $userId );
|
||||||
|
|
||||||
$decrypted = Crypt::keyDecryptKeyfile( $data, $encryptedKeyfile, $session->getPrivateKey( $split[1] ) );
|
// Get the encrypted keyfile
|
||||||
|
$encKeyfile = Keymanager::getFileKey( $view, $userId, $filePath );
|
||||||
|
|
||||||
|
// Check if key is shared or not
|
||||||
|
if ( \OCP\Share::isSharedFile( $filePath ) ) {
|
||||||
|
|
||||||
|
// If key is shared, fetch the user's shareKey
|
||||||
|
$shareKey = Keymanager::getShareKey( $view, $userId, $filePath );
|
||||||
|
|
||||||
|
\OC_FileProxy::$enabled = false;
|
||||||
|
|
||||||
|
// Decrypt keyfile with shareKey
|
||||||
|
$plainKeyfile = Crypt::multiKeyDecrypt( $encKeyfile, $shareKey, $privateKey );
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// If key is unshared, decrypt with user private key
|
||||||
|
$plainKeyfile = Crypt::keyDecrypt( $encKeyfile, $privateKey );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$plainData = Crypt::symmetricDecryptFileContent( $data, $plainKeyfile );
|
||||||
|
|
||||||
} elseif (
|
} elseif (
|
||||||
Crypt::mode() == 'server'
|
Crypt::mode() == 'server'
|
||||||
|
@ -206,19 +221,19 @@ class Proxy extends \OC_FileProxy {
|
||||||
&& Crypt::isEncryptedMeta( $path )
|
&& Crypt::isEncryptedMeta( $path )
|
||||||
) {
|
) {
|
||||||
|
|
||||||
$decrypted = Crypt::legacyDecrypt( $data, $_SESSION['legacyenckey'] );
|
$plainData = Crypt::legacyDecrypt( $data, $session->getLegacyKey() );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
\OC_FileProxy::$enabled = true;
|
\OC_FileProxy::$enabled = true;
|
||||||
|
|
||||||
if ( ! isset( $decrypted ) ) {
|
if ( ! isset( $plainData ) ) {
|
||||||
|
|
||||||
$decrypted = $data;
|
$plainData = $data;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $decrypted;
|
return $plainData;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -439,14 +439,14 @@ class Test_Crypt extends \PHPUnit_Framework_TestCase {
|
||||||
$this->assertTrue( strlen( $pair1['privateKey'] ) > 1 );
|
$this->assertTrue( strlen( $pair1['privateKey'] ) > 1 );
|
||||||
|
|
||||||
|
|
||||||
$crypted = Encryption\Crypt::multiKeyEncrypt( $this->dataUrl, array( $pair1['publicKey'] ) );
|
$crypted = Encryption\Crypt::multiKeyEncrypt( $this->dataShort, array( $pair1['publicKey'] ) );
|
||||||
|
|
||||||
$this->assertNotEquals( $this->dataUrl, $crypted['encrypted'] );
|
$this->assertNotEquals( $this->dataShort, $crypted['data'] );
|
||||||
|
|
||||||
|
|
||||||
$decrypt = Encryption\Crypt::multiKeyDecrypt( $crypted['encrypted'], $crypted['keys'][0], $pair1['privateKey'] );
|
$decrypt = Encryption\Crypt::multiKeyDecrypt( $crypted['data'], $crypted['keys'][0], $pair1['privateKey'] );
|
||||||
|
|
||||||
$this->assertEquals( $this->dataUrl, $decrypt );
|
$this->assertEquals( $this->dataShort, $decrypt );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,19 +93,72 @@ class Share {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Find which users can access a shared item
|
* @brief Prepare a path to be passed to DB as file_target
|
||||||
* @param string Item type
|
* @return string Prepared path
|
||||||
* @param int Format (optional) Format type must be defined by the backend
|
|
||||||
* @param int Number of items to return (optional) Returns all by default
|
|
||||||
* @return Return depends on format
|
|
||||||
*/
|
*/
|
||||||
public static function getUsersSharingFile( $path ) {
|
public static function prepFileTarget( $path ) {
|
||||||
|
|
||||||
|
// Paths in DB are stored with leading slashes, so add one if necessary
|
||||||
|
if ( substr( $path, 0, 1 ) !== '/' ) {
|
||||||
|
|
||||||
|
$path = '/' . $path;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return $path;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isSharedFile( $path ) {
|
||||||
|
|
||||||
|
$fPath = self::prepFileTarget( $path );
|
||||||
|
|
||||||
|
// Fetch all shares of this file path from DB
|
||||||
|
$query = \OC_DB::prepare(
|
||||||
|
'SELECT
|
||||||
|
id
|
||||||
|
FROM
|
||||||
|
`*PREFIX*share`
|
||||||
|
WHERE
|
||||||
|
file_target = ?'
|
||||||
|
);
|
||||||
|
|
||||||
|
$result = $query->execute( array( $fPath ) );
|
||||||
|
|
||||||
|
if ( \OC_DB::isError( $result ) ) {
|
||||||
|
|
||||||
|
\OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage( $result ) . ', path=' . $fPath, \OC_Log::ERROR );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $result->fetchRow() !== false ) {
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Find which users can access a shared item
|
||||||
|
* @return bool / array
|
||||||
|
* @note $path needs to be relative to user data dir, e.g. 'file.txt'
|
||||||
|
* not '/admin/data/file.txt'
|
||||||
|
*/
|
||||||
|
public static function getUsersSharingFile( $path, $includeOwner = 0 ) {
|
||||||
|
|
||||||
|
$fPath = self::prepFileTarget( $path );
|
||||||
|
|
||||||
// Fetch all shares of this file path from DB
|
// Fetch all shares of this file path from DB
|
||||||
$query = \OC_DB::prepare(
|
$query = \OC_DB::prepare(
|
||||||
'SELECT
|
'SELECT
|
||||||
share_type
|
share_type
|
||||||
, share_with
|
, share_with
|
||||||
|
, uid_owner
|
||||||
, permissions
|
, permissions
|
||||||
FROM
|
FROM
|
||||||
`*PREFIX*share`
|
`*PREFIX*share`
|
||||||
|
@ -113,11 +166,11 @@ class Share {
|
||||||
file_target = ?'
|
file_target = ?'
|
||||||
);
|
);
|
||||||
|
|
||||||
$result = $query->execute( array( $path ) );
|
$result = $query->execute( array( $fPath ) );
|
||||||
|
|
||||||
if ( \OC_DB::isError( $result ) ) {
|
if ( \OC_DB::isError( $result ) ) {
|
||||||
|
|
||||||
\OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result) . ', path=' . $path, \OC_Log::ERROR );
|
\OC_Log::write( 'OCP\Share', \OC_DB::getErrorMessage($result) . ', path=' . $fPath, \OC_Log::ERROR );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +181,7 @@ class Share {
|
||||||
// Set helpful array keys
|
// Set helpful array keys
|
||||||
$shares[] = array(
|
$shares[] = array(
|
||||||
'userId' => $row['share_with']
|
'userId' => $row['share_with']
|
||||||
|
, 'owner' => $row['uid_owner'] // we just set this so it can be used once, hugly hack :/
|
||||||
, 'shareType' => $row['share_type']
|
, 'shareType' => $row['share_type']
|
||||||
, 'permissions' => $row['permissions']
|
, 'permissions' => $row['permissions']
|
||||||
);
|
);
|
||||||
|
@ -136,6 +190,20 @@ class Share {
|
||||||
|
|
||||||
if ( ! empty( $shares ) ) {
|
if ( ! empty( $shares ) ) {
|
||||||
|
|
||||||
|
// Include owner in list of users, if requested
|
||||||
|
if ( $includeOwner == 1 ) {
|
||||||
|
|
||||||
|
// NOTE: The values are incorrect for shareType and
|
||||||
|
// permissions of the owner; we just include them for
|
||||||
|
// optional convenience
|
||||||
|
$shares[] = array(
|
||||||
|
'userId' => $shares[0]['owner']
|
||||||
|
, 'shareType' => 0
|
||||||
|
, 'permissions' => 0
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
return $shares;
|
return $shares;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue