diff options
author | Bart Visscher <bartv@thisnet.nl> | 2012-05-04 17:04:11 +0200 |
---|---|---|
committer | Bart Visscher <bartv@thisnet.nl> | 2012-05-04 17:04:11 +0200 |
commit | 1e471562268ff62c59708b724c22930bc1d01d95 (patch) | |
tree | 5b5125ec41e865fa009d51b4293042f6572067f4 /apps/files_encryption | |
parent | 71f9b1968e3d4decc4395db2a1555a872cbb2820 (diff) | |
parent | 07ff1e723ae4fa3a0297b168ef2262e01a0a5e50 (diff) | |
download | nextcloud-server-1e471562268ff62c59708b724c22930bc1d01d95.tar.gz nextcloud-server-1e471562268ff62c59708b724c22930bc1d01d95.zip |
Merge branch 'master' into tasks
Diffstat (limited to 'apps/files_encryption')
-rwxr-xr-x[-rw-r--r--] | apps/files_encryption/appinfo/app.php | 6 | ||||
-rw-r--r-- | apps/files_encryption/appinfo/info.xml | 1 | ||||
-rw-r--r-- | apps/files_encryption/appinfo/version | 1 | ||||
-rw-r--r-- | apps/files_encryption/js/settings.js | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | apps/files_encryption/lib/crypt.php | 59 | ||||
-rwxr-xr-x[-rw-r--r--] | apps/files_encryption/lib/cryptstream.php | 51 | ||||
-rwxr-xr-x[-rw-r--r--] | apps/files_encryption/lib/proxy.php | 34 | ||||
-rwxr-xr-x[-rw-r--r--] | apps/files_encryption/settings.php | 8 | ||||
-rw-r--r-- | apps/files_encryption/templates/settings.php | 1 | ||||
-rwxr-xr-x | apps/files_encryption/tests/encryption.php | 42 | ||||
-rwxr-xr-x | apps/files_encryption/tests/stream.php | 56 |
11 files changed, 176 insertions, 88 deletions
diff --git a/apps/files_encryption/appinfo/app.php b/apps/files_encryption/appinfo/app.php index 68c445d5d77..02fc9dfa267 100644..100755 --- a/apps/files_encryption/appinfo/app.php +++ b/apps/files_encryption/appinfo/app.php @@ -10,10 +10,10 @@ OC_Hook::connect('OC_User','post_login','OC_Crypt','loginListener'); stream_wrapper_register('crypt','OC_CryptStream'); -if(!isset($_SESSION['enckey']) and OC_User::isLoggedIn()){//force the user to re-loggin if the encryption key isn't unlocked (happens when a user is logged in before the encryption app is enabled) - OC_User::logout(); +if(!isset($_SESSION['enckey']) and OCP\User::isLoggedIn()){//force the user to re-loggin if the encryption key isn't unlocked (happens when a user is logged in before the encryption app is enabled) + OCP\User::logout(); header("Location: ".OC::$WEBROOT.'/'); exit(); } -OC_App::registerAdmin('files_encryption', 'settings'); +OCP\App::registerAdmin('files_encryption', 'settings'); diff --git a/apps/files_encryption/appinfo/info.xml b/apps/files_encryption/appinfo/info.xml index 691b265bf60..c2e1aa96043 100644 --- a/apps/files_encryption/appinfo/info.xml +++ b/apps/files_encryption/appinfo/info.xml @@ -3,7 +3,6 @@ <id>files_encryption</id> <name>Encryption</name> <description>Server side encryption of files</description> - <version>0.1</version> <licence>AGPL</licence> <author>Robin Appelman</author> <require>3</require> diff --git a/apps/files_encryption/appinfo/version b/apps/files_encryption/appinfo/version new file mode 100644 index 00000000000..ceab6e11ece --- /dev/null +++ b/apps/files_encryption/appinfo/version @@ -0,0 +1 @@ +0.1
\ No newline at end of file diff --git a/apps/files_encryption/js/settings.js b/apps/files_encryption/js/settings.js index adbf0c87245..37d62265c94 100644 --- a/apps/files_encryption/js/settings.js +++ b/apps/files_encryption/js/settings.js @@ -16,4 +16,9 @@ $(document).ready(function(){ var blackList=$('#encryption_blacklist').val().join(','); OC.AppConfig.setValue('files_encryption','type_blacklist',blackList); } + + $('#enbale_encryption').change(function(){ + var checked=$('#enbale_encryption').is(':checked'); + OC.AppConfig.setValue('files_encryption','enable_encryption',(checked)?'true':'false'); + }) })
\ No newline at end of file diff --git a/apps/files_encryption/lib/crypt.php b/apps/files_encryption/lib/crypt.php index 246d4f672db..37eaedc3fc9 100644..100755 --- a/apps/files_encryption/lib/crypt.php +++ b/apps/files_encryption/lib/crypt.php @@ -91,8 +91,8 @@ class OC_Crypt { } public static function changekeypasscode($oldPassword, $newPassword) { - if(OC_User::isLoggedIn()){ - $username=OC_USER::getUser(); + if(OCP\User::isLoggedIn()){ + $username=OCP\USER::getUser(); $view=new OC_FilesystemView('/'.$username); // read old key @@ -119,7 +119,7 @@ class OC_Crypt { */ public static function encrypt( $content, $key='') { $bf = self::getBlowfish($key); - return($bf->encrypt($content)); + return $bf->encrypt($content); } /** @@ -132,61 +132,62 @@ class OC_Crypt { */ public static function decrypt( $content, $key='') { $bf = self::getBlowfish($key); - return($bf->decrypt($content)); + $data=$bf->decrypt($content); + return rtrim($data, "\0"); } /** * @brief encryption of a file - * @param $filename - * @param $key the encryption key + * @param string $source + * @param string $target + * @param string $key the decryption key * * This function encrypts a file */ - public static function encryptfile( $filename, $key) { - $handleread = fopen($filename, "rb"); - if($handleread<>FALSE) { - $handlewrite = fopen($filename.OC_Crypt::$encription_extension, "wb"); + public static function encryptFile( $source, $target, $key='') { + $handleread = fopen($source, "rb"); + if($handleread!=FALSE) { + $handlewrite = fopen($target, "wb"); while (!feof($handleread)) { $content = fread($handleread, 8192); $enccontent=OC_CRYPT::encrypt( $content, $key); fwrite($handlewrite, $enccontent); } fclose($handlewrite); - unlink($filename); + fclose($handleread); } - fclose($handleread); } - /** - * @brief decryption of a file - * @param $filename - * @param $key the decryption key - * - * This function decrypts a file - */ - public static function decryptfile( $filename, $key) { - $handleread = fopen($filename.OC_Crypt::$encription_extension, "rb"); - if($handleread<>FALSE) { - $handlewrite = fopen($filename, "wb"); + /** + * @brief decryption of a file + * @param string $source + * @param string $target + * @param string $key the decryption key + * + * This function decrypts a file + */ + public static function decryptFile( $source, $target, $key='') { + $handleread = fopen($source, "rb"); + if($handleread!=FALSE) { + $handlewrite = fopen($target, "wb"); while (!feof($handleread)) { $content = fread($handleread, 8192); $enccontent=OC_CRYPT::decrypt( $content, $key); fwrite($handlewrite, $enccontent); } fclose($handlewrite); - unlink($filename.OC_Crypt::$encription_extension); + fclose($handleread); } - fclose($handleread); } /** * encrypt data in 8192b sized blocks */ - public static function blockEncrypt($data){ + public static function blockEncrypt($data, $key=''){ $result=''; while(strlen($data)){ - $result=self::encrypt(substr($data,0,8192)); + $result.=self::encrypt(substr($data,0,8192),$key); $data=substr($data,8192); } return $result; @@ -195,10 +196,10 @@ class OC_Crypt { /** * decrypt data in 8192b sized blocks */ - public static function blockDecrypt($data){ + public static function blockDecrypt($data, $key=''){ $result=''; while(strlen($data)){ - $result=self::decrypt(substr($data,0,8192)); + $result.=self::decrypt(substr($data,0,8192),$key); $data=substr($data,8192); } return $result; diff --git a/apps/files_encryption/lib/cryptstream.php b/apps/files_encryption/lib/cryptstream.php index 86583096f1d..1a7c595cb83 100644..100755 --- a/apps/files_encryption/lib/cryptstream.php +++ b/apps/files_encryption/lib/cryptstream.php @@ -33,6 +33,7 @@ class OC_CryptStream{ private $path; private $readBuffer;//for streams that dont support seeking private $meta=array();//header/meta for source stream + private $count; public function stream_open($path, $mode, $options, &$opened_path){ $path=str_replace('crypt://','',$path); @@ -41,12 +42,12 @@ class OC_CryptStream{ $this->path=self::$sourceStreams[basename($path)]['path']; }else{ $this->path=$path; - OC_Log::write('files_encryption','open encrypted '.$path. ' in '.$mode,OC_Log::DEBUG); + OCP\Util::writeLog('files_encryption','open encrypted '.$path. ' in '.$mode,OCP\Util::DEBUG); OC_FileProxy::$enabled=false;//disable fileproxies so we can open the source file $this->source=OC_FileSystem::fopen($path,$mode); OC_FileProxy::$enabled=true; if(!is_resource($this->source)){ - OC_Log::write('files_encryption','failed to open '.$path,OC_Log::ERROR); + OCP\Util::writeLog('files_encryption','failed to open '.$path,OCP\Util::ERROR); } } if(is_resource($this->source)){ @@ -64,29 +65,19 @@ class OC_CryptStream{ } public function stream_read($count){ - $pos=0; - $currentPos=ftell($this->source); - $offset=$currentPos%8192; - $result=''; - if($offset>0){ - if($this->meta['seekable']){ - fseek($this->source,-$offset,SEEK_CUR);//if seeking isnt supported the internal read buffer will be used - }else{ - $pos=strlen($this->readBuffer); - $result=$this->readBuffer; - } - } - while($count>$pos){ - $data=fread($this->source,8192); - $pos+=8192; - if(strlen($data)){ - $result.=OC_Crypt::decrypt($data); - } + //$count will always be 8192 https://bugs.php.net/bug.php?id=21641 + //This makes this function a lot simpler but will breake everything the moment it's fixed + if($count!=8192){ + OCP\Util::writeLog('files_encryption','php bug 21641 no longer holds, decryption will not work',OCP\Util::FATAL); + die(); } - if(!$this->meta['seekable']){ - $this->readBuffer=substr($result,$count); + $data=fread($this->source,8192); + if(strlen($data)){ + $result=OC_Crypt::decrypt($data); + }else{ + $result=''; } - return substr($result,0,$count); + return $result; } public function stream_write($data){ @@ -102,14 +93,6 @@ class OC_CryptStream{ $data=substr($block,0,$currentPos%8192).$data; } while(strlen($data)>0){ - if(strlen($data)<8192){ - //fetch the current data in that block and append it to the input so we always write entire blocks - $oldPos=ftell($this->source); - $encryptedBlock=fread($this->source,8192); - fseek($this->source,$oldPos); - $block=OC_Crypt::decrypt($encryptedBlock); - $data.=substr($block,strlen($data)); - } $encrypted=OC_Crypt::encrypt(substr($data,0,8192)); fwrite($this->source,$encrypted); $data=substr($data,8192); @@ -147,7 +130,9 @@ class OC_CryptStream{ } public function stream_close(){ - OC_FileCache::put($this->path,array('encrypted'=>true)); + if($this->meta['mode']!='r' and $this->meta['mode']!='rb'){ + OC_FileCache::put($this->path,array('encrypted'=>true)); + } return fclose($this->source); } -}
\ No newline at end of file +} diff --git a/apps/files_encryption/lib/proxy.php b/apps/files_encryption/lib/proxy.php index c1c26d7754f..06f963fc981 100644..100755 --- a/apps/files_encryption/lib/proxy.php +++ b/apps/files_encryption/lib/proxy.php @@ -27,7 +27,7 @@ class OC_FileProxy_Encryption extends OC_FileProxy{ private static $blackList=null; //mimetypes blacklisted from encryption - private static $metaData=array(); //metadata cache + private static $enableEncryption=null; /** * check if a file should be encrypted during write @@ -35,14 +35,20 @@ class OC_FileProxy_Encryption extends OC_FileProxy{ * @return bool */ private static function shouldEncrypt($path){ + if(is_null(self::$enableEncryption)){ + self::$enableEncryption=(OCP\Config::getAppValue('files_encryption','enable_encryption','true')=='true'); + } + if(!self::$enableEncryption){ + return false; + } if(is_null(self::$blackList)){ - self::$blackList=explode(',',OC_Appconfig::getValue('files_encryption','type_blacklist','jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg')); + self::$blackList=explode(',',OCP\Config::getAppValue('files_encryption','type_blacklist','jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg')); } if(self::isEncrypted($path)){ return true; } - $extention=substr($path,strrpos($path,'.')+1); - if(array_search($extention,self::$blackList)===false){ + $extension=substr($path,strrpos($path,'.')+1); + if(array_search($extension,self::$blackList)===false){ return true; } } @@ -53,13 +59,8 @@ class OC_FileProxy_Encryption extends OC_FileProxy{ * @return bool */ private static function isEncrypted($path){ - if(isset(self::$metaData[$path])){ - $metadata=self::$metaData[$path]; - }else{ - $metadata=OC_FileCache::getCached($path); - self::$metaData[$path]=$metadata; - } - return (bool)$metadata['encrypted']; + $metadata=OC_FileCache::getCached($path); + return isset($metadata['encrypted']) and (bool)$metadata['encrypted']; } public function preFile_put_contents($path,&$data){ @@ -89,14 +90,9 @@ class OC_FileProxy_Encryption extends OC_FileProxy{ }elseif(self::shouldEncrypt($path) and $meta['mode']!='r' and $meta['mode']!='rb'){ if(OC_Filesystem::file_exists($path) and OC_Filesystem::filesize($path)>0){ //first encrypt the target file so we don't end up with a half encrypted file - OC_Log::write('files_encryption','Decrypting '.$path.' before writing',OC_Log::DEBUG); + OCP\Util::writeLog('files_encryption','Decrypting '.$path.' before writing',OCP\Util::DEBUG); $tmp=fopen('php://temp'); - while(!feof($result)){ - $chunk=fread($result,8192); - if($chunk){ - fwrite($tmp,$chunk); - } - } + OCP\Files::streamCopy($result,$tmp); fclose($result); OC_Filesystem::file_put_contents($path,$tmp); fclose($tmp); @@ -108,7 +104,7 @@ class OC_FileProxy_Encryption extends OC_FileProxy{ public function postGetMimeType($path,$mime){ if(self::isEncrypted($path)){ - $mime=OC_Helper::getMimeType('crypt://'.$path,'w'); + $mime=OCP\Files::getMimeType('crypt://'.$path,'w'); } return $mime; } diff --git a/apps/files_encryption/settings.php b/apps/files_encryption/settings.php index 396ad1ba78d..aed9079529c 100644..100755 --- a/apps/files_encryption/settings.php +++ b/apps/files_encryption/settings.php @@ -7,10 +7,12 @@ */ $tmpl = new OC_Template( 'files_encryption', 'settings'); -$blackList=explode(',',OC_Appconfig::getValue('files_encryption','type_blacklist','jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg')); +$blackList=explode(',',OCP\Config::getAppValue('files_encryption','type_blacklist','jpg,png,jpeg,avi,mpg,mpeg,mkv,mp3,oga,ogv,ogg')); +$enabled=(OCP\Config::getAppValue('files_encryption','enable_encryption','true')=='true'); $tmpl->assign('blacklist',$blackList); +$tmpl->assign('encryption_enabled',$enabled); -OC_Util::addScript('files_encryption','settings'); -OC_Util::addScript('core','multiselect'); +OCP\Util::addscript('files_encryption','settings'); +OCP\Util::addscript('core','multiselect'); return $tmpl->fetchPage(); diff --git a/apps/files_encryption/templates/settings.php b/apps/files_encryption/templates/settings.php index 724a03836a8..25b5a06f56c 100644 --- a/apps/files_encryption/templates/settings.php +++ b/apps/files_encryption/templates/settings.php @@ -7,5 +7,6 @@ <option selected="selected" value="<?php echo $type;?>"><?php echo $type;?></option> <?php endforeach;?> </select> + <input type='checkbox' id='enbale_encryption' <?php if($_['encryption_enabled']){echo 'checked="checked"';} ?>></input><label for='enbale_encryption'><?php echo $l->t('Enable Encryption')?></label> </fieldset> </form> diff --git a/apps/files_encryption/tests/encryption.php b/apps/files_encryption/tests/encryption.php new file mode 100755 index 00000000000..00466cc671c --- /dev/null +++ b/apps/files_encryption/tests/encryption.php @@ -0,0 +1,42 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +class Test_Encryption extends UnitTestCase { + function testEncryption(){ + $key=uniqid(); + $file=OC::$SERVERROOT.'/3rdparty/MDB2.php'; + $source=file_get_contents($file); //nice large text file + $encrypted=OC_Crypt::encrypt($source,$key); + $decrypted=OC_Crypt::decrypt($encrypted,$key); + $this->assertNotEqual($encrypted,$source); + $this->assertEqual($decrypted,$source); + + $chunk=substr($source,0,8192); + $encrypted=OC_Crypt::encrypt($chunk,$key); + $this->assertEqual(strlen($chunk),strlen($encrypted)); + $decrypted=OC_Crypt::decrypt($encrypted,$key); + $this->assertEqual($decrypted,$chunk); + + $encrypted=OC_Crypt::blockEncrypt($source,$key); + $decrypted=OC_Crypt::blockDecrypt($encrypted,$key); + $this->assertNotEqual($encrypted,$source); + $this->assertEqual($decrypted,$source); + + $tmpFileEncrypted=OCP\Files::tmpFile(); + OC_Crypt::encryptfile($file,$tmpFileEncrypted,$key); + $encrypted=file_get_contents($tmpFileEncrypted); + $decrypted=OC_Crypt::blockDecrypt($encrypted,$key); + $this->assertNotEqual($encrypted,$source); + $this->assertEqual($decrypted,$source); + + $tmpFileDecrypted=OCP\Files::tmpFile(); + OC_Crypt::decryptfile($tmpFileEncrypted,$tmpFileDecrypted,$key); + $decrypted=file_get_contents($tmpFileDecrypted); + $this->assertEqual($decrypted,$source); + } +} diff --git a/apps/files_encryption/tests/stream.php b/apps/files_encryption/tests/stream.php new file mode 100755 index 00000000000..b23805d60b0 --- /dev/null +++ b/apps/files_encryption/tests/stream.php @@ -0,0 +1,56 @@ +<?php +/** + * Copyright (c) 2012 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +class Test_CryptStream extends UnitTestCase { + private $tmpFiles=array(); + + function testStream(){ + $stream=$this->getStream('test1','w'); + fwrite($stream,'foobar'); + fclose($stream); + + $stream=$this->getStream('test1','r'); + $data=fread($stream,6); + fclose($stream); + $this->assertEqual('foobar',$data); + + $file=OC::$SERVERROOT.'/3rdparty/MDB2.php'; + $source=fopen($file,'r'); + $target=$this->getStream('test2','w'); + OCP\Files::streamCopy($source,$target); + fclose($target); + fclose($source); + + $stream=$this->getStream('test2','r'); + $data=stream_get_contents($stream); + $original=file_get_contents($file); + $this->assertEqual(strlen($original),strlen($data)); + $this->assertEqual($original,$data); + } + + /** + * get a cryptstream to a temporary file + * @param string $id + * @param string $mode + * @return resource + */ + function getStream($id,$mode){ + if($id===''){ + $id=uniqid(); + } + if(!isset($this->tmpFiles[$id])){ + $file=OCP\Files::tmpFile(); + $this->tmpFiles[$id]=$file; + }else{ + $file=$this->tmpFiles[$id]; + } + $stream=fopen($file,$mode); + OC_CryptStream::$sourceStreams[$id]=array('path'=>'dummy','stream'=>$stream); + return fopen('crypt://streams/'.$id,$mode); + } +} |