Commit 48b42b9a authored by Predhumeau Manon's avatar Predhumeau Manon Committed by Guillaume Perréal
Browse files

Add antivirus analyse (xenelop quahog)

parent 1c62bf2d
No related merge requests found
Showing with 91 additions and 65 deletions
+91 -65
...@@ -6,9 +6,10 @@ ...@@ -6,9 +6,10 @@
namespace Irstea\FileUploadBundle\Listener; namespace Irstea\FileUploadBundle\Listener;
use CL\Tissue\Adapter\AdapterInterface; use Xenolope\Quahog\Client;
use Irstea\FileUploadBundle\Event\FileUploadCompleteEvent; use Irstea\FileUploadBundle\Event\FileUploadCompleteEvent;
use Irstea\FileUploadBundle\Exception\RejectedFileException; use Irstea\FileUploadBundle\Exception\RejectedFileException;
use Xenolope\Quahog\Exception\ConnectionException;
/** /**
* Description of AntivirusListener. * Description of AntivirusListener.
...@@ -16,42 +17,57 @@ use Irstea\FileUploadBundle\Exception\RejectedFileException; ...@@ -16,42 +17,57 @@ use Irstea\FileUploadBundle\Exception\RejectedFileException;
class VirusScannerListener class VirusScannerListener
{ {
/** /**
* @var AdapterInterface * @var Client
*/ */
private $scanner; private $client;
/** /**
* @param AdapterInterface $scanner * @param Client $client
*/ */
public function __construct(AdapterInterface $scanner) public function __construct(Client $client)
{ {
$this->scanner = $scanner; $this->client = $client;
try {
// Check clamd server's state
$this->client->ping();
// Reload the virus database
$this->client->reload();
} catch (ConnectionException $connectionException) {
$this->client->shutdown();
$this->client = null;
}
} }
/** /**
* @param FileUploadCompleteEvent $event * @param FileUploadCompleteEvent $event
*/ */
public function onFileUploadCompleted(FileUploadCompleteEvent $event) public function onFileUploadCompleted(FileUploadCompleteEvent $event)
{ {
$file = $event->getUploadedFile(); if ($this->client != null) {
$path = $file->getLocalPath(); $file = $event->getUploadedFile();
$path = $file->getLocalPath();
$result = $this->scanner->scan([$path]);
$meta = $file->getMetadata(); $result = $this->client->scanFile($path);
$hasVirus = $result['status'] == Client::RESULT_FOUND;
$meta['virus_scanner'] = ['has_virus' => $result->hasVirus()]; $meta = $file->getMetadata();
$meta['virus_scanner'] = ['has_virus' => $hasVirus];
if ($result->hasVirus()) { if ($hasVirus) {
if (null !== $desc = $result->getDetections()[0]->getDescription()) { $desc = $result['reason'];
$meta['virus_scanner']['detected'] = $desc; $meta['virus_scanner']['detected'] = $result['reason'];
} }
}
$file->setMetadata($meta); $file->setMetadata($meta);
if ($result->hasVirus()) { if ($hasVirus) {
throw new RejectedFileException($file, $desc ? sprintf('Found the %s virus !', $desc) : 'Virus found !'); throw new RejectedFileException($file, $desc ? sprintf('Found the %s virus !', $desc) : 'Virus found !');
}
$this->client->shutdown();
} }
} }
} }
...@@ -10,6 +10,10 @@ parameters: ...@@ -10,6 +10,10 @@ parameters:
irstea_file_upload.max_chunk_size: 0 irstea_file_upload.max_chunk_size: 0
irstea_file_upload.clamav_socket_path: unix:///var/run/clamav/clamd.ctl
irstea_file_upload.client_timeout: 30
irstea_file_upload.client_mode: PHP_NORMAL_READ
services: services:
# Le gestionnaire de fichiers # Le gestionnaire de fichiers
...@@ -70,12 +74,24 @@ services: ...@@ -70,12 +74,24 @@ services:
- "%irstea_file_upload.filesystem.name%" - "%irstea_file_upload.filesystem.name%"
# Scanner anti-virus # Scanner anti-virus
# irstea_file_upload.virus_scanner: irstea_file_upload.socket:
# class: Irstea\FileUploadBundle\Listener\VirusScannerListener class: Socket\Raw\Socket
# arguments: arguments:
# - @cl_tissue.scanner - "%irstea_file_upload.clamav_socket_path"
# tags:
# - { name: kernel.event_listener, event: file_upload.complete, method: onFileUploadCompleted } irstea_file_upload.client:
class: Xenolope\Quahog\Client
arguments:
- "@irstea_file_upload.socket"
- "%irstea_file_upload.client_timeout"
- "%irstea_file_upload.client_mode"
irstea_file_upload.virus_scanner:
class: Irstea\FileUploadBundle\Listener\VirusScannerListener
arguments:
- "@irstea_file_upload.client"
tags:
- { name: kernel.event_listener, event: file_upload.complete, method: onFileUploadCompleted }
# Extension Twig # Extension Twig
irstea_file_upload.twig_extension: irstea_file_upload.twig_extension:
......
...@@ -6,12 +6,12 @@ ...@@ -6,12 +6,12 @@
namespace Irstea\FileUploadBundle\Tests\Listener; namespace Irstea\FileUploadBundle\Tests\Listener;
use CL\Tissue\Model\Detection;
use CL\Tissue\Model\ScanResult;
use Irstea\FileUploadBundle\Event\FileUploadCompleteEvent; use Irstea\FileUploadBundle\Event\FileUploadCompleteEvent;
use Irstea\FileUploadBundle\Listener\VirusScannerListener; use Irstea\FileUploadBundle\Listener\VirusScannerListener;
use PHPUnit_Framework_MockObject_MockObject; use PHPUnit_Framework_MockObject_MockObject;
use PHPUnit_Framework_TestCase; use PHPUnit_Framework_TestCase;
use Irstea\FileUploadBundle\Model\UploadedFileInterface;
use Xenolope\Quahog\Client;
/** /**
* Generated by PHPUnit_SkeletonGenerator on 2015-01-29 at 14:43:16. * Generated by PHPUnit_SkeletonGenerator on 2015-01-29 at 14:43:16.
...@@ -26,7 +26,7 @@ class VirusScannerListenerTest extends PHPUnit_Framework_TestCase ...@@ -26,7 +26,7 @@ class VirusScannerListenerTest extends PHPUnit_Framework_TestCase
/** /**
* @var PHPUnit_Framework_MockObject_MockObject * @var PHPUnit_Framework_MockObject_MockObject
*/ */
protected $scanner; protected $client;
/** /**
* @var FileUploadCompleteEvent * @var FileUploadCompleteEvent
...@@ -43,38 +43,27 @@ class VirusScannerListenerTest extends PHPUnit_Framework_TestCase ...@@ -43,38 +43,27 @@ class VirusScannerListenerTest extends PHPUnit_Framework_TestCase
*/ */
protected function setUp() protected function setUp()
{ {
self::markTestSkipped('No CL\Tissue'); $this->client = $this->getMockBuilder(Client::class)->disableOriginalConstructor()->getMock();
}
public function testOnFileUploadCompletedResultOk() $this->file = $this->getMock(UploadedFileInterface::class);
{ $this->file->expects(static::once())->method('getLocalPath')->willReturn('foopath');
$result = new ScanResult( $this->file->expects(static::once())->method('getMetadata')->willReturn([]);
['foopath'],
['foopath'],
[]
);
$this->scanner->expects(static::once())->method('scan')->with(['foopath'])->willReturn($result);
$this->file->expects(static::once())->method('setMetadata')->with(['virus_scanner' => ['has_virus' => false]]); $this->event = new FileUploadCompleteEvent($this->file);
$this->listener->onFileUploadCompleted($this->event); $this->listener = new VirusScannerListener($this->client);
} }
/** public function testOnFileUploadCompletedResultOk()
* @expectedException \Irstea\FileUploadBundle\Exception\RejectedFileException
*/
public function testOnFileUploadCompletedVirusFound()
{ {
$result = new ScanResult( $result = [
['foopath'], 'filename' => 'footpath',
['foopath'], 'reason' => null,
[new Detection('foopath', Detection::TYPE_VIRUS, 'BAR')] 'status' => Client::RESULT_OK
); ];
$this->scanner->expects(static::once())->method('scan')->with(['foopath'])->willReturn($result);
$this->file->expects(static::once())->method('setMetadata')->with( $this->client->expects(static::once())->method('scanFile')->with('foopath')->willReturn($result);
['virus_scanner' => ['has_virus' => true, 'detected' => 'BAR']] $this->file->expects(static::once())->method('setMetadata')->with(['virus_scanner' => ['has_virus' => false]]);
);
$this->listener->onFileUploadCompleted($this->event); $this->listener->onFileUploadCompleted($this->event);
} }
...@@ -82,18 +71,22 @@ class VirusScannerListenerTest extends PHPUnit_Framework_TestCase ...@@ -82,18 +71,22 @@ class VirusScannerListenerTest extends PHPUnit_Framework_TestCase
/** /**
* @expectedException \Irstea\FileUploadBundle\Exception\RejectedFileException * @expectedException \Irstea\FileUploadBundle\Exception\RejectedFileException
*/ */
public function testOnFileUploadCompletedVirusFoundNoDescription() public function testOnFileUploadCompletedVirusFound()
{ {
$result = new ScanResult( $result = [
['foopath'], 'filename' => 'footpath',
['foopath'], 'reason' => 'Terrible virus',
[new Detection('foopath', Detection::TYPE_VIRUS)] 'status' => Client::RESULT_FOUND
); ];
$this->scanner->expects(static::once())->method('scan')->with(['foopath'])->willReturn($result);
$this->client->expects($this->any())
$this->file->expects(static::once())->method('setMetadata')->with( ->method('scanFile')
['virus_scanner' => ['has_virus' => true]] ->with('foopath')
); ->willReturn($result);
$this->file->expects(static::once())
->method('setMetadata')
->with(['virus_scanner' => ['has_virus' => true, 'detected' => 'Terrible virus']]);
$this->listener->onFileUploadCompleted($this->event); $this->listener->onFileUploadCompleted($this->event);
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment