Commit 2cae337f authored by Predhumeau Manon's avatar Predhumeau Manon Committed by Guillaume Perréal
Browse files

Add antivirus analyse (xenelop quahog)

parent 3f18f628
...@@ -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
...@@ -39,42 +39,31 @@ class VirusScannerListenerTest extends PHPUnit_Framework_TestCase ...@@ -39,42 +39,31 @@ class VirusScannerListenerTest extends PHPUnit_Framework_TestCase
protected $file; protected $file;
/** /**
* {@inheritdoc} * {@inheritDoc}
*/ */
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);
} }
......
Markdown is supported
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