diff --git a/src/opnsense/scripts/suricata/getRuleJSON.py b/src/opnsense/scripts/suricata/getRuleJSON.py index b6e2e1d1a..5827e6e58 100755 --- a/src/opnsense/scripts/suricata/getRuleJSON.py +++ b/src/opnsense/scripts/suricata/getRuleJSON.py @@ -46,7 +46,7 @@ if __name__ == '__main__': rc.create() # load parameters, ignore validation here the search method only processes valid input - parameters = {'limit':'0','offset':'0','sort_by':'', 'filter':'', 'filter_fields':''} + parameters = {'limit':'0','offset':'0','sort_by':'', 'filter':''} cmd=None for arg in sys.argv[1:]: if cmd is None: @@ -60,3 +60,5 @@ if __name__ == '__main__': result=rc.search(**parameters) result['parameters'] = parameters print (json.dumps(result)) + + diff --git a/src/opnsense/scripts/suricata/rulecache.py b/src/opnsense/scripts/suricata/rulecache.py index 4825c67e4..5b2462fa7 100644 --- a/src/opnsense/scripts/suricata/rulecache.py +++ b/src/opnsense/scripts/suricata/rulecache.py @@ -33,6 +33,7 @@ import os import os.path import glob import sqlite3 +import shlex class RuleCache(object): """ @@ -42,6 +43,7 @@ class RuleCache(object): self.rule_source_dir = '/usr/local/etc/suricata/rules/' self.cachefile = '%srules.sqlite'%self.rule_source_dir self._rule_fields = ['sid','msg','classtype','rev','gid','source','enabled'] + self._rule_defaults = {'classtype':'##none##'} def listLocal(self): all_rule_files=[] @@ -113,7 +115,10 @@ class RuleCache(object): for rule_field in self._rule_fields: if rule_field not in record: - record[rule_field] = None + if rule_field in self._rule_defaults: + record[rule_field] = self._rule_defaults[rule_field] + else: + record[rule_field] = None rules.append(record) @@ -123,12 +128,11 @@ class RuleCache(object): cur.execute('insert into stats (timestamp,files) values (?,?) ',(last_mtime,len(all_rule_files))) db.commit() - def search(self, limit, offset, filter, filter_fields, sort_by): + def search(self, limit, offset, filter, sort_by): """ search installed rules :param limit: limit number of rows :param offset: limit offset - :param filter: text to search - :param filter_fields: list of fields to apply filter + :param filter: text to search, used format fieldname1,fieldname2/searchphrase include % to match on a part :param sort: order by, list of fields and possible asc/desc parameter :return: dict """ @@ -139,14 +143,27 @@ class RuleCache(object): # construct query including filters sql = 'select * from rules ' sql_filters = {} - for field in map(lambda x:x.lower().strip(),filter_fields.split(',')): - if field in self._rule_fields: - if len(sql_filters) > 0: - sql += ' or ' + + for filtertag in shlex.split(filter): + fieldnames = filtertag.split('/')[0] + searchcontent = '/'.join(filtertag.split('/')[1:]) + if len(sql_filters) > 0: + sql += ' and ( ' + else: + sql += ' where ( ' + for fieldname in map(lambda x: x.lower().strip(), fieldnames.split(',')): + if fieldname in self._rule_fields: + if fieldname != fieldnames.split(',')[0].strip(): + sql += ' or ' + if searchcontent.find('%') == -1: + sql += 'cast('+fieldname + " as text) like :"+fieldname+" " + else: + sql += 'cast('+fieldname + " as text) like '%'|| :"+fieldname+" || '%' " + sql_filters[fieldname] = searchcontent.replace('%', '') else: - sql += ' where ' - sql += 'cast('+field + " as text) like '%'|| :"+field+" || '%' " - sql_filters[field] = filter + # not a valid fieldname, add a tag to make sure our sql statement is valid + sql += ' 1 = 1 ' + sql += ' ) ' # apply sort order (if any) sql_sort =[]