Skip to content
This repository has been archived by the owner on Sep 9, 2021. It is now read-only.

Commit

Permalink
Added new set-config command and new tests
Browse files Browse the repository at this point in the history
  • Loading branch information
xsist10 committed Apr 21, 2014
1 parent 3d514fd commit 311a6cc
Show file tree
Hide file tree
Showing 15 changed files with 232 additions and 15 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,18 @@ If you are using the `shone.phar` file, you can update it to the latest version
$ ./shone.phar self-update


Setting up your configuration
-----

There are some basic settings that make it easier to use the tool. It's recommended to set your API key at the start (the configuration file will be stored in your home folder ~/shone.json or similar location).

# Set the API key so you don't need to declare it everywhere
$ ./shone.phar set-config --key "[API KEY]"

# This is not recommended
$ ./shone.phar set-config --common-checksum=0 --no-cert-check=1


Using the scanner
-----

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "shone/scanner",
"description": "Software Version Scanner",
"description": "A scanner to determine if the version of the popular open source software you are running is vulnerable.",
"keywords": ["version", "scanner", "security", "vulnerability"],
"homepage": "https://www.shone.co.za/",
"type": "tool",
Expand Down
2 changes: 1 addition & 1 deletion res/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,5 @@
"zip"
],
"ssl-cert-check": 1,
"version": "1.1.2"
"version": "1.1.3"
}
Binary file modified shone.phar
Binary file not shown.
16 changes: 8 additions & 8 deletions src/Command/FingerprintCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
}

// Do we have a key to use?
$key = $input->hasOption('key') ? $input->getOption('key') : $config->get('key');
$key = $input->getOption('key') ? $input->getOption('key') : $config->get('key');
$this->log($output, ' Setting key to `' . $key . '`');
$scanner->setKey($key);

Expand All @@ -103,12 +103,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
} else {
$this->log($output, 'Result: <info>' . $result['Detail'] . '</info>', true);

$table = $this->getApplication()->getHelperSet()->get('table');
$table->setHeaders(array('Software', 'Version', 'Status'));
if (!empty($result['Matches'])) {
$table = $this->getApplication()->getHelperSet()->get('table');
$table->setHeaders(array('Software', 'Version', 'Status'));

$data = array();
$data = array();

if (!empty($result['Matches'])) {
foreach ($result['Matches'] as $match) {
$warning = array();
if ($match['is_malicious']) {
Expand All @@ -127,10 +127,10 @@ protected function execute(InputInterface $input, OutputInterface $output)
implode(', ', $warning)
);
}
}

$table->setRows($data);
$table->render($output);
$table->setRows($data);
$table->render($output);
}
}

$this->log($output);
Expand Down
5 changes: 5 additions & 0 deletions src/Command/ScanCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ protected function execute(InputInterface $input, OutputInterface $output)

// Determine the path we're going to scan
$this->log($output, ' Setting path to `' . $config['path'] . '`');
if (!is_dir($config['path']) || !is_readable($config['path'])) {
$this->log($output, '<error>Unable to read the path specified.</error>', true);
$this->log($output);
return false;
}

// Has the user specified a label?
$this->log($output, ' Setting label to `' . $config['label'] .'`');
Expand Down
86 changes: 86 additions & 0 deletions src/Command/SetConfigCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php
/**
* The Shone Security Scanner is used to help a developer determine if the versions of the
* dependencies he is using are vulnerable to known exploits.
*
* @category Shone
* @package Scanner
* @author Thomas Shone <xsist10@gmail.com>
*/

namespace Shone\Scanner\Command;

use Shone\Scanner\Scanner;

use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Command\Command;

use \Exception;

/**
* The self-update command only accessable when accessing from a phar
*
* @category Shone
* @package Scanner\Command
* @author Thomas Shone <xsist10@gmail.com>
*/
class SetConfigCommand extends Command
{
/**
* Configure our command call
*
* @return void
*/
protected function configure()
{
$help = <<<EOT
The <info>set-config</info> command sets the configuration for a user.
EOT;

$this
->setName('set-config')
->setHelp($help)
->setAliases(array('setconfig'))
->setDescription('Setup the configuration for a user.')
->setDefinition(array(
new InputOption('key', null, InputOption::VALUE_REQUIRED, 'Set an API key.'),
new InputOption('common-checksum', 'c', InputOption::VALUE_REQUIRED, 'Set whether to always ignore files that are very common.', true),
new InputOption('no-cert-check', null, InputOption::VALUE_REQUIRED, 'Set whether to disable CA certificate checks.', false),
));
}

/**
* Execute our command call
*
* @param Symfony\Component\Console\Input\InputInterface $input Input source
* @param Symfony\Component\Console\Output\OutputInterface $output Output source
*
* @return void
* @codeCoverageIgnore
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$config = $this->getApplication()->getConfig();

$no_cert_check = $input->getOption('no-cert-check') ? true : false;
$config->set('no-cert-check', $no_cert_check);
$output->writeln(sprintf("Setting no-cert-check to <info>%b</info>.", $no_cert_check));

$common_checksum = $input->getOption('common-checksum') ? true : false;
$config->set('common-checksum', $common_checksum);
$output->writeln(sprintf("Setting common-checksum to <info>%b</info>.", $common_checksum));

if ($input->getOption('key'))
{
$config->set('key', $input->getOption('key'));
$output->writeln(sprintf("Setting key to <info>%s</info>.", $config->get('key')));
}

$output->writeln("<info>Config file saved.</info>");
$config->save();
}
}
80 changes: 77 additions & 3 deletions src/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,25 +37,85 @@
*/
class Config
{
/**
* @var array
*/
public static $defaultConfig = array(
'ignore-ext' => array(),
'ssl-cert-check' => 1
);

/**
* @var array
*/
private $config;

/**
* @var string
*/
private $config_file;

/**
* @var string
*/
private $home_file;

/**
* Build a new config object
*
* @return Shone\Scanner\Config
* @codeCoverageIgnore
*/
public function __construct()
{
// load defaults
$this->config = static::$defaultConfig;

$jsonConfig = __DIR__ . '/../res/config.json';
if (is_file($jsonConfig) && is_readable($jsonConfig)) {
$json = json_decode(file_get_contents($jsonConfig), true);
// Get home directory
if (isset($_SERVER['HOME'])) {
$home = $_SERVER['HOME'];
} elseif (isset($_SERVER['HOMEDRIVE']) && isset($_SERVER['HOMEPATH'])) {
$home = $_SERVER['HOMEDRIVE'] . '/' . $_SERVER['HOMEPATH'];
} else {
$home = getcwd();
}

$this->home_file = $home . '/shone.json';

// Attempt to load a custom config
$this->config_file = realpath($this->home_file);
if (!is_readable($this->config_file))
{
// Failing that, default to the bundled one
$this->config_file = __DIR__ . '/../res/config.json';
}
if (is_file($this->config_file) && is_readable($this->config_file)) {
$json = json_decode(file_get_contents($this->config_file), true);
$this->merge($json);
}
}

/**
* Returns the path to the config file
*
* @return string
*/
public function getConfigFile()
{
return $this->config_file;
}

/**
* Save the config file to the home folder of the user
*
* @return boolean
* @codeCoverageIgnore
*/
public function save()
{
return file_put_contents($this->home_file, json_encode($this->config)) > 0;
}

/**
* Merges new config values with the existing ones (overriding)
*
Expand All @@ -71,6 +131,20 @@ public function merge(array $config)
}
}

/**
* Set a key
*
* @param string $key Key of the config
* @param string $value Value of the config
*
* @return Shone\Scanner\Config
*/
public function set($key, $value)
{
$this->config[$key] = $value;
return $this;
}

/**
* Returns a setting
*
Expand Down
3 changes: 2 additions & 1 deletion src/Console/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ protected function getDefaultCommands()
{
$commands = parent::getDefaultCommands();
$commands[] = new Command\AboutCommand();
$commands[] = new Command\SetConfigCommand();
$commands[] = new Command\ScanCommand();
$commands[] = new Command\FtpScanCommand();
$commands[] = new Command\JobCommand();
Expand All @@ -174,6 +175,6 @@ protected function getDefaultCommands()
*/
public function getLongVersion()
{
return parent::getLongVersion() . ' ' . Scanner::RELEASE_DATE;
return parent::getLongVersion() . ' ' . Scanner::RELEASE_DATE . "\nConfig File: " . $this->getConfig()->getConfigFile();
}
}
3 changes: 3 additions & 0 deletions src/Scanner.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,11 @@ protected function post($page, array $arguments = array())

// Work around for Guzzle not clearing out old cacert files
$cert_file = sys_get_temp_dir() . '/guzzle-cacert.pem';
// @codeCoverageIgnoreStart
if (is_file($cert_file) && is_writable($cert_file)) {
unlink($cert_file);
}
// @codeCoverageIgnoreEnd

$client = $this->getHttpClient();
$client->setBaseUrl(self::API_ENDPOINT);
Expand Down Expand Up @@ -294,6 +296,7 @@ protected function buildFileFingerprint(Filesystem $filesystem, $file)
$context = hash_init('md5');
hash_update_stream($context, $stream);
$md5 = hash_final($context);

// Close the resource to release the handle
fclose($stream);

Expand Down
18 changes: 18 additions & 0 deletions src/Tests/Command/JobCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,22 @@ public function testGetHash()
$this->assertRegExp('/| Joomla! | 2.5.10 | vulnerable | 10\/10 | 96.00% |/', $display);
$this->assertRegExp('/| tinymce | 3.5.2 | deprecated | N\/A | 10.00% |/', $display);
}

public function testPendingJob()
{
$json = '{"status":"In progress"}';
$parameters = array('--hash' => 'abc123');
$display = $this->runCommand('getJob', $parameters, $json);

$this->assertRegExp('/Job still being processed/', $display);
}

public function testEmptyJob()
{
$json = '';
$parameters = array('--hash' => 'abc123');
$display = $this->runCommand('getJob', $parameters, $json);

$this->assertRegExp('/Invalid job result received/', $display);
}
}
10 changes: 10 additions & 0 deletions src/Tests/Command/ScanCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ public function testMissingParameters()
$this->assertRegExp('/Because/', $commandTester->getDisplay());
}

public function testInvalidPath()
{
$command = new ScanCommand();
$command->setApplication(new Application());

$commandTester = new CommandTester($command);
$commandTester->execute(array('path' => '/random/path'));
$this->assertRegExp('/Unable to read the path specified/', $commandTester->getDisplay());
}

public function testExecuteForCommandAlias()
{
// Mock the scanner
Expand Down
8 changes: 8 additions & 0 deletions src/Tests/ConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,12 @@ public function testGet()
$this->assertEquals(null, $config->get('non-existant-key'));
$this->assertEquals(1, $config->get('ssl-cert-check'));
}

public function testSet()
{
$config = new Config();
$this->assertEquals(1, $config->get('ssl-cert-check'));
$config->set('ssl-cert-check', 0);
$this->assertEquals(0, $config->get('ssl-cert-check'));
}
}
Empty file added src/Tests/Fixture/tmp
Empty file.
2 changes: 1 addition & 1 deletion src/Tests/ScannerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ public function testJobPacket()

$property = new ReflectionProperty('Shone\Scanner\Scanner', 'common_checksums');
$property->setAccessible(true);
$property->setValue($scanner, array('742b794187af3520e8a991e207660493' => true));
$property->setValue($scanner, array('d41d8cd98f00b204e9800998ecf8427e' => true));

$files = $scanner->buildFileList($filesystem, '', array('txt'));
$files[] = "non_existant_file";
Expand Down

0 comments on commit 311a6cc

Please sign in to comment.