mirror of
https://github.com/nextcloud/server.git
synced 2026-05-28 04:32:30 -04:00
fixed finding encrypted files in subfolders and removed unused code
This commit is contained in:
parent
095fc790ac
commit
9ca9a22c6a
4 changed files with 62 additions and 201 deletions
|
|
@ -326,44 +326,6 @@ class Keymanager
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief store private keys from the user
|
||||
*
|
||||
* @param string $privatekey
|
||||
* @param string $publickey
|
||||
* @return bool true/false
|
||||
*/
|
||||
public static function setUserKeys($privatekey, $publickey)
|
||||
{
|
||||
|
||||
return (self::setPrivateKey($privatekey) && self::setPublicKey($publickey));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief store public key of the user
|
||||
*
|
||||
* @param string $key
|
||||
* @return bool true/false
|
||||
*/
|
||||
public static function setPublicKey($key)
|
||||
{
|
||||
|
||||
$view = new \OC_FilesystemView('/public-keys');
|
||||
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
if (!$view->file_exists('')) $view->mkdir('');
|
||||
|
||||
$result = $view->file_put_contents(\OCP\User::getUser() . '.public.key', $key);
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief store share key
|
||||
*
|
||||
|
|
@ -538,7 +500,7 @@ class Keymanager
|
|||
|
||||
list($owner, $filename) = $util->getUidAndFilename($filePath);
|
||||
|
||||
$shareKeyPath = '/' . $owner . '/files_encryption/share-keys/' . $filename;
|
||||
$shareKeyPath = \OC\Files\Filesystem::normalizePath('/' . $owner . '/files_encryption/share-keys/' . $filename);
|
||||
|
||||
if ($view->is_dir($shareKeyPath)) {
|
||||
|
||||
|
|
@ -611,22 +573,4 @@ class Keymanager
|
|||
return $targetPath;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fetch the legacy encryption key from user files
|
||||
* @internal param string $login used to locate the legacy key
|
||||
* @internal param string $passphrase used to decrypt the legacy key
|
||||
* @return boolean
|
||||
*
|
||||
* if the key is left out, the default handeler will be used
|
||||
*/
|
||||
public function getLegacyKey()
|
||||
{
|
||||
|
||||
$user = \OCP\User::getUser();
|
||||
$view = new \OC_FilesystemView('/' . $user);
|
||||
return $view->file_get_contents('encryption.key');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -170,7 +170,7 @@ class Proxy extends \OC_FileProxy
|
|||
$data = $encData;
|
||||
|
||||
// Update the file cache with file info
|
||||
\OC\Files\Filesystem::putFileInfo($filePath, array('encrypted' => true, 'size' => strlen($size), 'unencrypted_size' => $size), '');
|
||||
\OC\Files\Filesystem::putFileInfo($filePath, array('encrypted' => true, 'size' => strlen($data), 'unencrypted_size' => $size), '');
|
||||
|
||||
// Re-enable proxy - our work is done
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
|
@ -189,28 +189,25 @@ class Proxy extends \OC_FileProxy
|
|||
public function postFile_get_contents($path, $data)
|
||||
{
|
||||
|
||||
// FIXME: $path for shared files is just /uid/files/Shared/filepath
|
||||
|
||||
$userId = \OCP\USER::getUser();
|
||||
$view = new \OC_FilesystemView('/');
|
||||
$util = new Util($view, $userId);
|
||||
|
||||
$relPath = $util->stripUserFilesPath($path);
|
||||
|
||||
|
||||
// TODO check for existing key file and reuse it if possible to avoid problems with versioning etc.
|
||||
// Disable encryption proxy to prevent recursive calls
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
// init session
|
||||
$session = new Session($view);
|
||||
|
||||
// If data is a catfile
|
||||
if (
|
||||
Crypt::mode() == 'server'
|
||||
&& Crypt::isCatfileContent($data) // TODO: Do we really need this check? Can't we assume it is properly encrypted?
|
||||
&& Crypt::isCatfileContent($data)
|
||||
) {
|
||||
|
||||
// TODO: use get owner to find correct location of key files for shared files
|
||||
$session = new Session($view);
|
||||
$privateKey = $session->getPrivateKey($userId);
|
||||
|
||||
// Get the encrypted keyfile
|
||||
|
|
@ -229,9 +226,7 @@ class Proxy extends \OC_FileProxy
|
|||
&& isset($_SESSION['legacyenckey'])
|
||||
&& Crypt::isEncryptedMeta($path)
|
||||
) {
|
||||
|
||||
$plainData = Crypt::legacyDecrypt($data, $session->getLegacyKey());
|
||||
|
||||
}
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
|
@ -292,19 +287,6 @@ class Proxy extends \OC_FileProxy
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief When a file is renamed, rename its keyfile also
|
||||
* @param $path
|
||||
* @return bool Result of rename()
|
||||
* @note This is pre rather than post because using post didn't work
|
||||
*/
|
||||
public function postWrite($path)
|
||||
{
|
||||
$this->handleFile($path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @return bool
|
||||
|
|
@ -362,7 +344,6 @@ class Proxy extends \OC_FileProxy
|
|||
// protocol and let it do the decryption work instead
|
||||
$result = fopen('crypt://' . $path_f, $meta['mode']);
|
||||
|
||||
|
||||
} elseif (
|
||||
self::shouldEncrypt($path)
|
||||
and $meta ['mode'] != 'r'
|
||||
|
|
@ -428,11 +409,28 @@ class Proxy extends \OC_FileProxy
|
|||
*/
|
||||
public function postStat($path, $data)
|
||||
{
|
||||
$content = '';
|
||||
$view = new \OC_FilesystemView('/');
|
||||
if($view->file_exists($path)) {
|
||||
// disable encryption proxy
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
// we only need 24 byte from the last chunk
|
||||
$handle = $view->fopen($path, 'r');
|
||||
if (!fseek($handle, -24, SEEK_END)) {
|
||||
$content = fgets($handle);
|
||||
}
|
||||
|
||||
// re-enable proxy
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
}
|
||||
|
||||
// check if file is encrypted
|
||||
if (Crypt::isCatfileContent($path)) {
|
||||
if (Crypt::isCatfileContent($content)) {
|
||||
|
||||
// get file info from cache
|
||||
$cached = \OC\Files\Filesystem::getFileInfo($path, '');
|
||||
$cached = $view->getFileInfo($path);
|
||||
|
||||
// set the real file size
|
||||
$data['size'] = $cached['unencrypted_size'];
|
||||
|
|
|
|||
|
|
@ -50,8 +50,6 @@ namespace OCA\Encryption;
|
|||
*/
|
||||
class Stream
|
||||
{
|
||||
|
||||
public static $sourceStreams = array();
|
||||
private $plainKey;
|
||||
private $encKeyfiles;
|
||||
|
||||
|
|
@ -96,58 +94,42 @@ class Stream
|
|||
// rawPath is relative to the data directory
|
||||
$this->rawPath = $util->getUserFilesDir() . $this->relPath;
|
||||
|
||||
// Disable fileproxies so we can get the file size and open the source file without recursive encryption
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
if (
|
||||
dirname($this->rawPath) == 'streams'
|
||||
and isset(self::$sourceStreams[basename($this->rawPath)])
|
||||
$mode == 'w'
|
||||
or $mode == 'w+'
|
||||
or $mode == 'wb'
|
||||
or $mode == 'wb+'
|
||||
) {
|
||||
|
||||
// Is this just for unit testing purposes?
|
||||
|
||||
$this->handle = self::$sourceStreams[basename($this->rawPath)]['stream'];
|
||||
|
||||
$this->path = self::$sourceStreams[basename($this->rawPath)]['path'];
|
||||
|
||||
$this->size = self::$sourceStreams[basename($this->rawPath)]['size'];
|
||||
// We're writing a new file so start write counter with 0 bytes
|
||||
$this->size = 0;
|
||||
$this->unencryptedSize = 0;
|
||||
|
||||
} else {
|
||||
|
||||
// Disable fileproxies so we can get the file size and open the source file without recursive encryption
|
||||
$proxyStatus = \OC_FileProxy::$enabled;
|
||||
\OC_FileProxy::$enabled = false;
|
||||
$this->size = $this->rootView->filesize($this->rawPath, $mode);
|
||||
}
|
||||
|
||||
if (
|
||||
$mode == 'w'
|
||||
or $mode == 'w+'
|
||||
or $mode == 'wb'
|
||||
or $mode == 'wb+'
|
||||
) {
|
||||
$this->handle = $this->rootView->fopen($this->rawPath, $mode);
|
||||
|
||||
// We're writing a new file so start write counter with 0 bytes
|
||||
$this->size = 0;
|
||||
$this->unencryptedSize = 0;
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
||||
} else {
|
||||
if (!is_resource($this->handle)) {
|
||||
|
||||
$this->size = $this->rootView->filesize($this->rawPath, $mode);
|
||||
\OCP\Util::writeLog('files_encryption', 'failed to open file "' . $this->rawPath . '"', \OCP\Util::ERROR);
|
||||
|
||||
}
|
||||
} else {
|
||||
|
||||
$this->handle = $this->rootView->fopen($this->rawPath, $mode);
|
||||
|
||||
\OC_FileProxy::$enabled = $proxyStatus;
|
||||
|
||||
if (!is_resource($this->handle)) {
|
||||
|
||||
\OCP\Util::writeLog('files_encryption', 'failed to open file "' . $this->rawPath . '"', \OCP\Util::ERROR);
|
||||
|
||||
} else {
|
||||
|
||||
$this->meta = stream_get_meta_data($this->handle);
|
||||
|
||||
}
|
||||
$this->meta = stream_get_meta_data($this->handle);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return is_resource($this->handle);
|
||||
|
||||
}
|
||||
|
|
@ -165,14 +147,6 @@ class Stream
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function stream_tell()
|
||||
{
|
||||
return ftell($this->handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $count
|
||||
* @return bool|string
|
||||
|
|
@ -259,7 +233,6 @@ class Stream
|
|||
|
||||
// If a keyfile already exists
|
||||
if ($this->encKeyfile) {
|
||||
$this->setUserProperty();
|
||||
|
||||
$session = new Session($this->rootView);
|
||||
|
||||
|
|
@ -279,23 +252,6 @@ class Stream
|
|||
|
||||
}
|
||||
|
||||
public function setUserProperty()
|
||||
{
|
||||
|
||||
// Only get the user again if it isn't already set
|
||||
if (empty($this->userId)) {
|
||||
|
||||
// TODO: Move this user call out of here - it belongs
|
||||
// elsewhere
|
||||
$this->userId = \OCP\User::getUser();
|
||||
|
||||
}
|
||||
|
||||
// TODO: Add a method for getting the user in case OCP\User::
|
||||
// getUser() doesn't work (can that scenario ever occur?)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle plain data from the stream, and write it in 8192 byte blocks
|
||||
* @param string $data data to be written to disk
|
||||
|
|
@ -318,16 +274,10 @@ class Stream
|
|||
// Get the length of the unencrypted data that we are handling
|
||||
$length = strlen($data);
|
||||
|
||||
// So far this round, no data has been written
|
||||
$written = 0;
|
||||
|
||||
// Find out where we are up to in the writing of data to the
|
||||
// Find out where we are up to in the writing of data to the
|
||||
// file
|
||||
$pointer = ftell($this->handle);
|
||||
|
||||
// Make sure the userId is set
|
||||
$this->setUserProperty();
|
||||
|
||||
// Get / generate the keyfile for the file we're handling
|
||||
// If we're writing a new file (not overwriting an existing
|
||||
// one), save the newly generated keyfile
|
||||
|
|
@ -337,7 +287,6 @@ class Stream
|
|||
|
||||
}
|
||||
|
||||
|
||||
// If extra data is left over from the last round, make sure it
|
||||
// is integrated into the next 6126 / 8192 block
|
||||
if ($this->writeCache) {
|
||||
|
|
@ -351,17 +300,16 @@ class Stream
|
|||
|
||||
}
|
||||
|
||||
|
||||
// While there still remains somed data to be processed & written
|
||||
while (strlen($data) > 0) {
|
||||
|
||||
// Remaining length for this iteration, not of the
|
||||
// entire file (may be greater than 8192 bytes)
|
||||
$remainingLength = strlen( $data );
|
||||
$remainingLength = strlen($data);
|
||||
|
||||
// If data remaining to be written is less than the
|
||||
// size of 1 6126 byte block
|
||||
if (strlen($data) < 6126) {
|
||||
if ($remainingLength < 6126) {
|
||||
|
||||
// Set writeCache to contents of $data
|
||||
// The writeCache will be carried over to the
|
||||
|
|
@ -388,9 +336,7 @@ class Stream
|
|||
// being handled totals more than 6126 bytes
|
||||
fwrite($this->handle, $encrypted);
|
||||
|
||||
$writtenLen = strlen($encrypted);
|
||||
|
||||
// Remove the chunk we just processed from
|
||||
// Remove the chunk we just processed from
|
||||
// $data, leaving only unprocessed data in $data
|
||||
// var, for handling on the next round
|
||||
$data = substr($data, 6126);
|
||||
|
|
@ -416,16 +362,19 @@ class Stream
|
|||
*/
|
||||
public function stream_set_option($option, $arg1, $arg2)
|
||||
{
|
||||
$return = false;
|
||||
switch ($option) {
|
||||
case STREAM_OPTION_BLOCKING:
|
||||
stream_set_blocking($this->handle, $arg1);
|
||||
$return = stream_set_blocking($this->handle, $arg1);
|
||||
break;
|
||||
case STREAM_OPTION_READ_TIMEOUT:
|
||||
stream_set_timeout($this->handle, $arg1, $arg2);
|
||||
$return = stream_set_timeout($this->handle, $arg1, $arg2);
|
||||
break;
|
||||
case STREAM_OPTION_WRITE_BUFFER:
|
||||
stream_set_write_buffer($this->handle, $arg1, $arg2);
|
||||
$return = stream_set_write_buffer($this->handle, $arg1);
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -441,7 +390,7 @@ class Stream
|
|||
*/
|
||||
public function stream_lock($mode)
|
||||
{
|
||||
flock($this->handle, $mode);
|
||||
return flock($this->handle, $mode);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -367,14 +367,16 @@ class Util
|
|||
* @note $directory needs to be a path relative to OC data dir. e.g.
|
||||
* /admin/files NOT /backup OR /home/www/oc/data/admin/files
|
||||
*/
|
||||
public function findEncFiles($directory)
|
||||
public function findEncFiles($directory, &$found = false)
|
||||
{
|
||||
|
||||
// Disable proxy - we don't want files to be decrypted before
|
||||
// we handle them
|
||||
\OC_FileProxy::$enabled = false;
|
||||
|
||||
$found = array('plain' => array(), 'encrypted' => array(), 'legacy' => array());
|
||||
if($found == false) {
|
||||
$found = array('plain' => array(), 'encrypted' => array(), 'legacy' => array());
|
||||
}
|
||||
|
||||
if (
|
||||
$this->view->is_dir($directory)
|
||||
|
|
@ -395,7 +397,7 @@ class Util
|
|||
// its contents
|
||||
if ($this->view->is_dir($filePath)) {
|
||||
|
||||
$this->findEncFiles($filePath);
|
||||
$this->findEncFiles($filePath, $found);
|
||||
|
||||
// If the path is a file, determine
|
||||
// its encryption status
|
||||
|
|
@ -636,38 +638,6 @@ class Util
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Format a path to be relative to the /user directory
|
||||
* @note e.g. turns '/admin/files/test.txt' into 'files/test.txt'
|
||||
*/
|
||||
public function stripFilesPath($path)
|
||||
{
|
||||
|
||||
$trimmed = ltrim($path, '/');
|
||||
$split = explode('/', $trimmed);
|
||||
$sliced = array_slice($split, 1);
|
||||
$relPath = implode('/', $sliced);
|
||||
|
||||
return $relPath;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Format a shared path to be relative to the /user/files/ directory
|
||||
* @note Expects a path like /uid/files/Shared/filepath
|
||||
*/
|
||||
public function stripSharedFilePath($path)
|
||||
{
|
||||
|
||||
$trimmed = ltrim($path, '/');
|
||||
$split = explode('/', $trimmed);
|
||||
$sliced = array_slice($split, 3);
|
||||
$relPath = implode('/', $sliced);
|
||||
|
||||
return $relPath;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @return bool
|
||||
|
|
|
|||
Loading…
Reference in a new issue