truncate decrypted files based on filelength
This commit is contained in:
parent
1338279ca0
commit
d0455c5819
8 changed files with 84 additions and 21 deletions
|
@ -206,12 +206,16 @@ class OC_Crypt {
|
|||
/**
|
||||
* decrypt data in 8192b sized blocks
|
||||
*/
|
||||
public static function blockDecrypt($data, $key=''){
|
||||
public static function blockDecrypt($data, $key='',$maxLength=0){
|
||||
$result='';
|
||||
while(strlen($data)){
|
||||
$result.=self::decrypt(substr($data,0,8192),$key);
|
||||
$data=substr($data,8192);
|
||||
}
|
||||
return rtrim($result, "\0");
|
||||
if($maxLength>0){
|
||||
return substr($result,0,$maxLength);
|
||||
}else{
|
||||
return rtrim($result, "\0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ class OC_CryptStream{
|
|||
private $meta=array();//header/meta for source stream
|
||||
private $count;
|
||||
private $writeCache;
|
||||
private $size;
|
||||
private static $rootView;
|
||||
|
||||
public function stream_open($path, $mode, $options, &$opened_path){
|
||||
|
@ -45,8 +46,14 @@ class OC_CryptStream{
|
|||
if(dirname($path)=='streams' and isset(self::$sourceStreams[basename($path)])){
|
||||
$this->source=self::$sourceStreams[basename($path)]['stream'];
|
||||
$this->path=self::$sourceStreams[basename($path)]['path'];
|
||||
$this->size=self::$sourceStreams[basename($path)]['size'];
|
||||
}else{
|
||||
$this->path=$path;
|
||||
if($mode=='w' or $mode=='w+' or $mode=='wb' or $mode=='wb+'){
|
||||
$this->size=0;
|
||||
}else{
|
||||
$this->size=self::$rootView->filesize($path,$mode);
|
||||
}
|
||||
OC_FileProxy::$enabled=false;//disable fileproxies so we can open the source file
|
||||
$this->source=self::$rootView->fopen($path,$mode);
|
||||
OC_FileProxy::$enabled=true;
|
||||
|
@ -77,14 +84,16 @@ class OC_CryptStream{
|
|||
OCP\Util::writeLog('files_encryption','php bug 21641 no longer holds, decryption will not work',OCP\Util::FATAL);
|
||||
die();
|
||||
}
|
||||
$pos=ftell($this->source);
|
||||
$data=fread($this->source,8192);
|
||||
if(strlen($data)){
|
||||
$result=OC_Crypt::decrypt($data);
|
||||
}else{
|
||||
$result='';
|
||||
}
|
||||
if($this->stream_eof()){
|
||||
$result=rtrim($result, "\0");
|
||||
$length=$this->size-$pos;
|
||||
if($length<8192){
|
||||
$result=substr($result,0,$length);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
@ -116,6 +125,8 @@ class OC_CryptStream{
|
|||
$data=substr($data,8192);
|
||||
}
|
||||
}
|
||||
$currentPos=ftell($this->source);
|
||||
$this->size=max($this->size,$currentPos);
|
||||
return $length;
|
||||
}
|
||||
|
||||
|
@ -159,7 +170,7 @@ class OC_CryptStream{
|
|||
public function stream_close(){
|
||||
$this->flush();
|
||||
if($this->meta['mode']!='r' and $this->meta['mode']!='rb'){
|
||||
OC_FileCache::put($this->path,array('encrypted'=>true),'');
|
||||
OC_FileCache::put($this->path,array('encrypted'=>true,'size'=>$this->size),'');
|
||||
}
|
||||
return fclose($this->source);
|
||||
}
|
||||
|
|
|
@ -66,15 +66,17 @@ class OC_FileProxy_Encryption extends OC_FileProxy{
|
|||
public function preFile_put_contents($path,&$data){
|
||||
if(self::shouldEncrypt($path)){
|
||||
if (!is_resource($data)) {//stream put contents should have been converter to fopen
|
||||
$size=strlen($data);
|
||||
$data=OC_Crypt::blockEncrypt($data);
|
||||
OC_FileCache::put($path,array('encrypted'=>true),'');
|
||||
OC_FileCache::put($path,array('encrypted'=>true,'size'=>$size),'');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function postFile_get_contents($path,$data){
|
||||
if(self::isEncrypted($path)){
|
||||
$data=OC_Crypt::blockDecrypt($data);
|
||||
$cached=OC_FileCache_Cached::get($path,'');
|
||||
$data=OC_Crypt::blockDecrypt($data,'',$cached['size']);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
@ -108,4 +110,21 @@ class OC_FileProxy_Encryption extends OC_FileProxy{
|
|||
}
|
||||
return $mime;
|
||||
}
|
||||
|
||||
public function postStat($path,$data){
|
||||
if(self::isEncrypted($path)){
|
||||
$cached=OC_FileCache_Cached::get($path,'');
|
||||
$data['size']=$cached['size'];
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function postFileSize($path,$size){
|
||||
if(self::isEncrypted($path)){
|
||||
$cached=OC_FileCache_Cached::get($path,'');
|
||||
return $cached['size'];
|
||||
}else{
|
||||
return $size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ class Test_Encryption extends UnitTestCase {
|
|||
$this->assertEqual($decrypted,$source);
|
||||
|
||||
$encrypted=OC_Crypt::blockEncrypt($source,$key);
|
||||
$decrypted=OC_Crypt::blockDecrypt($encrypted,$key);
|
||||
$decrypted=OC_Crypt::blockDecrypt($encrypted,$key,strlen($source));
|
||||
$this->assertEqual($decrypted,$source);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ class Test_CryptProxy extends UnitTestCase {
|
|||
|
||||
$fromFile=OC_Filesystem::file_get_contents('/file');
|
||||
$this->assertNotEqual($original,$stored);
|
||||
$this->assertEqual(strlen($original),strlen($fromFile));
|
||||
$this->assertEqual($original,$fromFile);
|
||||
|
||||
}
|
||||
|
@ -88,6 +89,20 @@ class Test_CryptProxy extends UnitTestCase {
|
|||
|
||||
$fromFile=OC_Filesystem::file_get_contents('/file');
|
||||
$this->assertNotEqual($original,$stored);
|
||||
$this->assertEqual(strlen($original),strlen($fromFile));
|
||||
$this->assertEqual($original,$fromFile);
|
||||
|
||||
$file=__DIR__.'/zeros';
|
||||
$original=file_get_contents($file);
|
||||
|
||||
OC_Filesystem::file_put_contents('/file',$original);
|
||||
|
||||
OC_FileProxy::$enabled=false;
|
||||
$stored=OC_Filesystem::file_get_contents('/file');
|
||||
OC_FileProxy::$enabled=true;
|
||||
|
||||
$fromFile=OC_Filesystem::file_get_contents('/file');
|
||||
$this->assertNotEqual($original,$stored);
|
||||
$this->assertEqual(strlen($original),strlen($fromFile));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,23 +10,23 @@ class Test_CryptStream extends UnitTestCase {
|
|||
private $tmpFiles=array();
|
||||
|
||||
function testStream(){
|
||||
$stream=$this->getStream('test1','w');
|
||||
$stream=$this->getStream('test1','w',strlen('foobar'));
|
||||
fwrite($stream,'foobar');
|
||||
fclose($stream);
|
||||
|
||||
$stream=$this->getStream('test1','r');
|
||||
$stream=$this->getStream('test1','r',strlen('foobar'));
|
||||
$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');
|
||||
$target=$this->getStream('test2','w',0);
|
||||
OCP\Files::streamCopy($source,$target);
|
||||
fclose($target);
|
||||
fclose($source);
|
||||
|
||||
$stream=$this->getStream('test2','r');
|
||||
$stream=$this->getStream('test2','r',filesize($file));
|
||||
$data=stream_get_contents($stream);
|
||||
$original=file_get_contents($file);
|
||||
$this->assertEqual(strlen($original),strlen($data));
|
||||
|
@ -37,9 +37,10 @@ class Test_CryptStream extends UnitTestCase {
|
|||
* get a cryptstream to a temporary file
|
||||
* @param string $id
|
||||
* @param string $mode
|
||||
* @param int size
|
||||
* @return resource
|
||||
*/
|
||||
function getStream($id,$mode){
|
||||
function getStream($id,$mode,$size){
|
||||
if($id===''){
|
||||
$id=uniqid();
|
||||
}
|
||||
|
@ -50,7 +51,7 @@ class Test_CryptStream extends UnitTestCase {
|
|||
$file=$this->tmpFiles[$id];
|
||||
}
|
||||
$stream=fopen($file,$mode);
|
||||
OC_CryptStream::$sourceStreams[$id]=array('path'=>'dummy'.$id,'stream'=>$stream);
|
||||
OC_CryptStream::$sourceStreams[$id]=array('path'=>'dummy'.$id,'stream'=>$stream,'size'=>$size);
|
||||
return fopen('crypt://streams/'.$id,$mode);
|
||||
}
|
||||
|
||||
|
@ -58,11 +59,24 @@ class Test_CryptStream extends UnitTestCase {
|
|||
$file=__DIR__.'/binary';
|
||||
$source=file_get_contents($file);
|
||||
|
||||
$stream=$this->getStream('test','w');
|
||||
$stream=$this->getStream('test','w',strlen($source));
|
||||
fwrite($stream,$source);
|
||||
fclose($stream);
|
||||
|
||||
$stream=$this->getStream('test','r');
|
||||
$stream=$this->getStream('test','r',strlen($source));
|
||||
$data=stream_get_contents($stream);
|
||||
fclose($stream);
|
||||
$this->assertEqual(strlen($data),strlen($source));
|
||||
$this->assertEqual($source,$data);
|
||||
|
||||
$file=__DIR__.'/zeros';
|
||||
$source=file_get_contents($file);
|
||||
|
||||
$stream=$this->getStream('test2','w',strlen($source));
|
||||
fwrite($stream,$source);
|
||||
fclose($stream);
|
||||
|
||||
$stream=$this->getStream('test2','r',strlen($source));
|
||||
$data=stream_get_contents($stream);
|
||||
fclose($stream);
|
||||
$this->assertEqual(strlen($data),strlen($source));
|
||||
|
|
BIN
apps/files_encryption/tests/zeros
Normal file
BIN
apps/files_encryption/tests/zeros
Normal file
Binary file not shown.
|
@ -68,18 +68,18 @@ class OC_FileCache{
|
|||
$path=$root.$path;
|
||||
$parent=self::getParentId($path);
|
||||
$id=self::getId($path,'');
|
||||
if($id!=-1){
|
||||
self::update($id,$data);
|
||||
return;
|
||||
}
|
||||
if(isset(OC_FileCache_Cached::$savedData[$path])){
|
||||
$data=array_merge($data,OC_FileCache_Cached::$savedData[$path]);
|
||||
$data=array_merge(OC_FileCache_Cached::$savedData[$path],$data);
|
||||
unset(OC_FileCache_Cached::$savedData[$path]);
|
||||
}
|
||||
if(!isset($data['size']) or !isset($data['mtime'])){//save incomplete data for the next time we write it
|
||||
OC_FileCache_Cached::$savedData[$path]=$data;
|
||||
return;
|
||||
}
|
||||
if($id!=-1){
|
||||
self::update($id,$data);
|
||||
return;
|
||||
}
|
||||
if(!isset($data['encrypted'])){
|
||||
$data['encrypted']=false;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue