}
- /**
- * @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
*
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)) {
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');
-
- }
-
}
\ No newline at end of file
$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;
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
&& isset($_SESSION['legacyenckey'])
&& Crypt::isEncryptedMeta($path)
) {
-
$plainData = Crypt::legacyDecrypt($data, $session->getLegacyKey());
-
}
\OC_FileProxy::$enabled = $proxyStatus;
}
- /**
- * @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
// protocol and let it do the decryption work instead
$result = fopen('crypt://' . $path_f, $meta['mode']);
-
} elseif (
self::shouldEncrypt($path)
and $meta ['mode'] != 'r'
*/
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'];
*/
class Stream
{
-
- public static $sourceStreams = array();
private $plainKey;
private $encKeyfiles;
// 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;
-
- if (
- $mode == 'w'
- or $mode == 'w+'
- or $mode == 'wb'
- or $mode == 'wb+'
- ) {
-
- // We're writing a new file so start write counter with 0 bytes
- $this->size = 0;
- $this->unencryptedSize = 0;
-
- } else {
+ $this->size = $this->rootView->filesize($this->rawPath, $mode);
+ }
- $this->size = $this->rootView->filesize($this->rawPath, $mode);
+ $this->handle = $this->rootView->fopen($this->rawPath, $mode);
- }
+ \OC_FileProxy::$enabled = $proxyStatus;
- $this->handle = $this->rootView->fopen($this->rawPath, $mode);
+ if (!is_resource($this->handle)) {
- \OC_FileProxy::$enabled = $proxyStatus;
+ \OCP\Util::writeLog('files_encryption', 'failed to open file "' . $this->rawPath . '"', \OCP\Util::ERROR);
- if (!is_resource($this->handle)) {
+ } else {
- \OCP\Util::writeLog('files_encryption', 'failed to open file "' . $this->rawPath . '"', \OCP\Util::ERROR);
+ $this->meta = stream_get_meta_data($this->handle);
- } else {
+ }
- $this->meta = stream_get_meta_data($this->handle);
- }
-
- }
return is_resource($this->handle);
}
- /**
- * @return int
- */
- public function stream_tell()
- {
- return ftell($this->handle);
- }
-
/**
* @param $count
* @return bool|string
// If a keyfile already exists
if ($this->encKeyfile) {
- $this->setUserProperty();
$session = new Session($this->rootView);
}
- 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
// 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
}
-
// If extra data is left over from the last round, make sure it
// is integrated into the next 6126 / 8192 block
if ($this->writeCache) {
}
-
// 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
// 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);
*/
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;
}
/**
*/
public function stream_lock($mode)
{
- flock($this->handle, $mode);
+ return flock($this->handle, $mode);
}
/**
* @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)
// 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
}
- /**
- * @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