diff --git a/src/opnsense/mvc/app/controllers/OPNsense/IDS/Api/SettingsController.php b/src/opnsense/mvc/app/controllers/OPNsense/IDS/Api/SettingsController.php index fec1b392e..7fc5f638e 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/IDS/Api/SettingsController.php +++ b/src/opnsense/mvc/app/controllers/OPNsense/IDS/Api/SettingsController.php @@ -29,7 +29,9 @@ namespace OPNsense\IDS\Api; use \OPNsense\Base\ApiControllerBase; +use \OPNsense\Core\Backend; use \OPNsense\IDS\IDS; +use \OPNsense\Core\Config; /** * Class SettingsController Handles settings related API actions for the IDS module @@ -37,5 +39,146 @@ use \OPNsense\IDS\IDS; */ class SettingsController extends ApiControllerBase { + private $idsModel = null; + /** + * get ids model + * @return null|IDS + */ + public function getModel() + { + if ($this->idsModel == null) { + $this->idsModel = new IDS(); + } + + return $this->idsModel; + } + + /** + * search installed ids rules + * @return array + */ + public function searchInstalledRulesAction() + { + if ($this->request->isPost()) { + $this->sessionClose(); + + // fetch query parameters + $itemsPerPage = $this->request->getPost('rowCount', 'int', 9999); + $currentPage = $this->request->getPost('current', 'int', 1); + + if ($this->request->hasPost('sort') && is_array($this->request->getPost("sort"))) { + $sortStr = ''; + $sortBy = array_keys($this->request->getPost("sort")); + if ($this->request->getPost("sort")[$sortBy[0]] == "desc") { + $sortOrd = 'desc'; + } else { + $sortOrd = 'asc'; + } + + foreach ($sortBy as $sortKey) { + if ($sortStr != '') { + $sortStr .= ','; + } + $sortStr .= $sortKey . ' '. $sortOrd . ' '; + } + } else { + $sortStr = 'sid'; + } + if ($this->request->getPost('searchPhrase', 'string', '') != "") { + $searchPhrase = 'msg,classtype,source,sid/"'.$this->request->getPost('searchPhrase', 'string', '').'%"'; + } else { + $searchPhrase = ''; + } + + // add filter for classtype + if ($this->request->getPost("classtype", "string", '') != "") { + $searchPhrase .= "classtype/".$this->request->getPost("classtype", "string", '').' '; + } + + + // request list of installed rules + $backend = new Backend(); + $response = $backend->configdpRun("ids list installedrules", array($itemsPerPage, + ($currentPage-1)*$itemsPerPage, + $searchPhrase, $sortStr)); + $data = json_decode($response, true); + + if ($data != null && array_key_exists("rows", $data)) { + $result = array(); + $result['rows'] = $data['rows']; + // update rule status with own administration + foreach ($result['rows'] as &$row) { + $row['enabled'] = $this->getModel()->getRuleStatus($row['sid'], $row['enabled']); + } + + $result['rowCount'] = count($result['rows']); + $result['total'] = $data['total_rows']; + $result['current'] = (int)$currentPage; + return $result; + } else { + return array(); + } + } else { + return array(); + } + } + + /** + * get rule information + * @param $sid rule identifier + * @return array|mixed + */ + public function getRuleInfoAction($sid) + { + // request list of installed rules + $backend = new Backend(); + $response = $backend->configdpRun("ids list installedrules", array(1, 0,'sid/'.$sid)); + $data = json_decode($response, true); + + if ($data != null && array_key_exists("rows", $data) && count($data['rows'])>0) { + $row = $data['rows'][0]; + $row['enabled'] = $this->getModel()->getRuleStatus($row['sid'], $row['enabled']); + return $row; + } else { + return array(); + } + + } + + /** + * list available classtypes + * @return array + * @throws \Exception + */ + public function listRuleClasstypesAction() + { + $backend = new Backend(); + $response = $backend->configdRun("ids list classtypes"); + $data = json_decode($response, true); + if ($data != null && array_key_exists("items", $data)) { + return $data; + } else { + return array(); + } + } + + /** + * @param $sid + * @return array + */ + public function toggleRuleAction($sid) + { + $ruleinfo = $this->getRuleInfoAction($sid); + if (count($ruleinfo) > 0) { + if ($ruleinfo['enabled'] == 1) { + $this->getModel()->disableRule($sid) ; + } else { + $this->getModel()->enableRule($sid) ; + } + $this->getModel()->serializeToConfig(); + Config::getInstance()->save(); + } + return array(); + } } diff --git a/src/opnsense/mvc/app/models/OPNsense/IDS/IDS.php b/src/opnsense/mvc/app/models/OPNsense/IDS/IDS.php index cb87a2483..899d4b99f 100644 --- a/src/opnsense/mvc/app/models/OPNsense/IDS/IDS.php +++ b/src/opnsense/mvc/app/models/OPNsense/IDS/IDS.php @@ -32,4 +32,84 @@ use OPNsense\Base\BaseModel; class IDS extends BaseModel { + private $sid_list = array(); + + private function updateSIDlist() + { + if (count($this->sid_list) == 0) { + foreach ($this->rules->rule->__items as $NodeKey => $NodeValue) { + $this->sid_list[$NodeValue->sid->__toString()] = $NodeValue; + } + } + } + + /** + * get new or existing rule + * @param $sid + * @return mixed + */ + private function getRule($sid) + { + $this->updateSIDlist(); + if (!array_key_exists($sid, $this->sid_list)) { + $rule = $this->rules->rule->Add(); + $rule->sid = $sid; + $this->sid_list[$sid] = $rule; + } + return $this->sid_list[$sid]; + } + + /** + * enable rule + * @param $sid + */ + public function enableRule($sid) + { + $rule = $this->getRule($sid); + $rule->enabled = "1"; + } + + /** + * disable rule + * @param $sid + */ + public function disableRule($sid) + { + $rule = $this->getRule($sid); + $rule->enabled = "0"; + } + + /** + * remove rule by sid + * @param $sid + */ + public function removeRule($sid) + { + // search and drop rule + foreach ($this->rules->rule->__items as $NodeKey => $NodeValue) { + if ((string)$NodeValue->sid == $sid) { + $this->rules->rule->Del($NodeKey); + unset ($this->sid_list[$sid]); + break; + } + } + } + + /** + * retrieve current altered rule status + * @param $sid + * @param $default default value + * @return default, 0, 1 ( default, true, false) + */ + public function getRuleStatus($sid, $default) + { + $this->updateSIDlist(); + if (array_key_exists($sid, $this->sid_list)) { + return (string)$this->sid_list[$sid]->enabled; + } else { + return $default; + } + + } + } diff --git a/src/opnsense/mvc/app/models/OPNsense/IDS/IDS.xml b/src/opnsense/mvc/app/models/OPNsense/IDS/IDS.xml index 3a0f40b0b..d50158402 100644 --- a/src/opnsense/mvc/app/models/OPNsense/IDS/IDS.xml +++ b/src/opnsense/mvc/app/models/OPNsense/IDS/IDS.xml @@ -4,5 +4,17 @@ OPNsense IDS + + + + sid should be a number + Y + + + 1 + Y + + + diff --git a/src/opnsense/mvc/app/views/OPNsense/IDS/index.volt b/src/opnsense/mvc/app/views/OPNsense/IDS/index.volt index e11271eb9..d19b5ed37 100644 --- a/src/opnsense/mvc/app/views/OPNsense/IDS/index.volt +++ b/src/opnsense/mvc/app/views/OPNsense/IDS/index.volt @@ -30,6 +30,45 @@ POSSIBILITY OF SUCH DAMAGE. $( document ).ready(function() { + function addFilters(request) { + var selected =$('#ruleclass').find("option:selected").val(); + if ( selected != "") { + request['classtype'] = selected; + } + return request; + } + + $("#grid-installedrules").UIBootgrid( + { 'search':'/api/ids/settings/searchinstalledrules', + 'options':{ + 'requestHandler':addFilters, + 'formatters':{ + "rowtoggle": function (column, row) { + if (parseInt(row[column.id], 2) == 1) { + return ""; + } else { + return ""; + } + } + } + }, + 'toggle':'/api/ids/settings/toggleRule/' + } + ); + + // list all known classtypes and add to selection box + ajaxGet(url="/api/ids/settings/listRuleClasstypes",sendData={}, callback=function(data, status) { + if (status == "success") { + $.each(data['items'], function(key, value) { + $('#ruleclass').append($("").attr("value",value).text(value)); + }); + $('.selectpicker').selectpicker('refresh'); + // link on change event + $('#ruleclass').on('change', function(){ + $('#grid-installedrules').bootgrid('reload'); + }); + } + }); }); @@ -44,7 +83,38 @@ POSSIBILITY OF SUCH DAMAGE.
+
+
+
+ Classtype   + +
+
+
+ + + + + + + + + + + + + + + + + + + +
sidSourceClassTypeMessageenabled
+ + +