truncate decrypted files based on size

This commit is contained in:
Robin Appelman 2012-06-21 17:37:53 +02:00
parent 096f5598b4
commit 7b4cb44af8
8 changed files with 88 additions and 29 deletions

View file

@ -205,12 +205,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");
}
}
}

View file

@ -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);
}

View file

@ -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::getCached($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::getCached($path,'/');
$data['size']=$cached['size'];
}
return $data;
}
public function postFileSize($path,$size){
if(self::isEncrypted($path)){
$cached=OC_FileCache::getCached($path,'/');
return $cached['size'];
}else{
return $size;
}
}
}

View file

@ -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);
}
}

View file

@ -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));
}
}

View file

@ -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));

Binary file not shown.

View file

@ -85,24 +85,20 @@ class OC_FileCache{
$root='';
}
$path=$root.$path;
if($path=='/'){
$parent=-1;
}else{
$parent=self::getFileId(dirname($path));
}
$id=self::getFileId($path);
if($id!=-1){
self::update($id,$data);
return;
}
if(isset(self::$savedData[$path])){
$data=array_merge($data,self::$savedData[$path]);
unset(self::$savedData[$path]);
$parent=self::getParentId($path);
$id=self::getId($path,'');
if(isset(OC_FileCache::$savedData[$path])){
$data=array_merge(OC_FileCache::$savedData[$path],$data);
unset(OC_FileCache::$savedData[$path]);
}
if(!isset($data['size']) or !isset($data['mtime'])){//save incomplete data for the next time we write it
self::$savedData[$path]=$data;
return;
}
if($id!=-1){
self::update($id,$data);
return;
}
if(!isset($data['encrypted'])){
$data['encrypted']=false;
}