From fb9641fb3c0e888dec7bd6f69ee55c6217cba241 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 18 Jun 2015 16:42:27 +0200 Subject: [PATCH] Controller: Validate restriction columns --- library/Icinga/Data/Filter/FilterChain.php | 39 +++++++++++++++++++ .../library/Monitoring/Controller.php | 35 ++++++++++++++++- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/library/Icinga/Data/Filter/FilterChain.php b/library/Icinga/Data/Filter/FilterChain.php index 19a170c19..51d511785 100644 --- a/library/Icinga/Data/Filter/FilterChain.php +++ b/library/Icinga/Data/Filter/FilterChain.php @@ -4,6 +4,7 @@ namespace Icinga\Data\Filter; use Icinga\Exception\ProgrammingError; +use Icinga\Exception\QueryException; /** * FilterChain @@ -18,6 +19,8 @@ abstract class FilterChain extends Filter protected $operatorSymbol; + protected $allowedColumns; + public function hasId($id) { foreach ($this->filters() as $filter) { @@ -116,6 +119,12 @@ abstract class FilterChain extends Filter return $this->operatorSymbol; } + public function setAllowedFilterColumns(array $columns) + { + $this->allowedColumns = $columns; + return $this; + } + public function listFilteredColumns() { $columns = array(); @@ -196,11 +205,41 @@ abstract class FilterChain extends Filter public function addFilter(Filter $filter) { + if (! empty($this->allowedColumns)) { + $this->validateFilterColumns($filter); + } + $this->filters[] = $filter; $filter->setId($this->getId() . '-' . $this->count()); return $this; } + protected function validateFilterColumns(Filter $filter) + { + if ($filter->isExpression()) { + $valid = false; + foreach ($this->allowedColumns as $column) { + if (is_callable($column)) { + if (call_user_func($column, $filter->getColumn())) { + $valid = true; + break; + } + } elseif ($filter->getColumn() === $column) { + $valid = true; + break; + } + } + + if (! $valid) { + throw new QueryException('Invalid filter column provided: %s', $filter->getColumn()); + } + } else { + foreach ($filter->filters() as $subFilter) { + $this->validateFilterColumns($subFilter); + } + } + } + public function &filters() { return $this->filters; diff --git a/modules/monitoring/library/Monitoring/Controller.php b/modules/monitoring/library/Monitoring/Controller.php index b6b65fc0c..c3449e01d 100644 --- a/modules/monitoring/library/Monitoring/Controller.php +++ b/modules/monitoring/library/Monitoring/Controller.php @@ -3,6 +3,8 @@ namespace Icinga\Module\Monitoring; +use Icinga\Exception\ConfigurationError; +use Icinga\Exception\QueryException; use Icinga\Data\Filter\Filter; use Icinga\Data\Filterable; use Icinga\File\Csv; @@ -52,16 +54,45 @@ class Controller extends IcingaWebController * Apply a restriction on the given data view * * @param string $restriction The name of restriction - * @param Filterable $filterable The filterable to restrict + * @param Filterable $view The filterable to restrict * * @return Filterable The filterable */ protected function applyRestriction($restriction, Filterable $view) { $restrictions = Filter::matchAny(); + $restrictions->setAllowedFilterColumns(array( + 'host_name', + 'hostgroup_name', + 'service_description', + 'servicegroup_name', + function ($c) { + return preg_match('/^_(?:host|service)_/', $c); + } + )); + foreach ($this->getRestrictions($restriction) as $filter) { - $restrictions->addFilter(Filter::fromQueryString($filter)); + try { + $restrictions->addFilter(Filter::fromQueryString($filter)); + } catch (QueryException $e) { + throw new ConfigurationError( + $this->translate( + 'Cannot apply restriction %s using the filter %s. You can only use the following columns: %s' + ), + $restriction, + $filter, + implode(', ', array( + 'host_name', + 'hostgroup_name', + 'service_description', + 'servicegroup_name', + '_(host|service)_' + )), + $e + ); + } } + $view->applyFilter($restrictions); return $view; }