LIBS = \
suricata/__init__.py \
- suricata/config/__init__.py \
- suricata/ctl/__init__.py \
- suricata/ctl/filestore.py \
- suricata/ctl/loghandler.py \
- suricata/ctl/main.py \
- suricata/ctl/test_filestore.py \
- suricata/sc/__init__.py \
- suricata/sc/specs.py \
- suricata/sc/suricatasc.py \
- suricatasc/__init__.py
+ suricata/config/__init__.py
-EXTRA_DIST = $(LIBS) bin suricata/config/defaults.py
+EXTRA_DIST = $(LIBS) suricata/config/defaults.py
if HAVE_PYTHON
install-exec-local:
install -d -m 0755 "$(DESTDIR)$(prefix)/lib/suricata/python/suricata/config"
- install -d -m 0755 "$(DESTDIR)$(prefix)/lib/suricata/python/suricata/ctl"
- install -d -m 0755 "$(DESTDIR)$(prefix)/lib/suricata/python/suricata/sc"
- install -d -m 0755 "$(DESTDIR)$(prefix)/lib/suricata/python/suricatasc"
- for src in $(LIBS); do \
- install -m 0644 $(srcdir)/$$src "$(DESTDIR)$(prefix)/lib/suricata/python/$$src"; \
- done
install suricata/config/defaults.py \
"$(DESTDIR)$(prefix)/lib/suricata/python/suricata/config/defaults.py"
+++ /dev/null
-#! /usr/bin/env python
-#
-# Copyright (C) 2017-2022 Open Information Security Foundation
-#
-# You can copy, redistribute or modify this Program under the terms of
-# the GNU General Public License version 2 as published by the Free
-# Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# version 2 along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
-
-import sys
-import os
-import site
-
-exec_dir = os.path.dirname(__file__)
-
-if os.path.exists(os.path.join(exec_dir, "..", "suricata", "ctl", "main.py")):
- # Looks like we're running from the development directory.
- sys.path.insert(0, ".")
-else:
- # Check if the Python modules are installed in the Suricata installation
- # prefix.
- version_info = sys.version_info
- pyver = "%d.%d" % (version_info.major, version_info.minor)
- path = os.path.realpath(os.path.join(
- exec_dir, "..", "lib", "suricata", "python", "suricata"))
- if os.path.exists(path):
- sys.path.insert(0, os.path.dirname(path))
-
-from suricata.ctl.main import main
-sys.exit(main())
+++ /dev/null
-#! /usr/bin/env python
-#
-# Copyright(C) 2013-2023 Open Information Security Foundation
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-from __future__ import print_function
-
-import sys
-import os
-import argparse
-
-# Find the Python libdir.
-exec_dir = os.path.dirname(__file__)
-if os.path.exists(os.path.join(exec_dir, "..", "suricata", "ctl", "main.py")):
- # Looks like we're running from the development directory.
- sys.path.insert(0, ".")
-else:
- # Check if the Python modules are installed in the Suricata installation
- # prefix.
- version_info = sys.version_info
- pyver = "%d.%d" % (version_info.major, version_info.minor)
- path = os.path.realpath(os.path.join(
- exec_dir, "..", "lib", "suricata", "python", "suricata"))
- if os.path.exists(path):
- sys.path.insert(0, os.path.dirname(path))
-
-from suricata.sc import *
-
-try:
- from suricata.config import defaults
- has_defaults = True
-except:
- has_defaults = False
-
-parser = argparse.ArgumentParser(prog='suricatasc', description='Client for Suricata unix socket')
-parser.add_argument('-v', '--verbose', action='store_const', const=True, help='verbose output (including JSON dump)')
-parser.add_argument('-c', '--command', default=None, help='execute on single command and return JSON')
-parser.add_argument('socket', metavar='socket', nargs='?', help='socket file to connect to', default=None)
-args = parser.parse_args()
-
-if args.socket != None:
- SOCKET_PATH = args.socket
-elif has_defaults:
- SOCKET_PATH = os.path.join(defaults.localstatedir, "suricata-command.socket")
-else:
- print("Unable to determine path to suricata-command.socket.", file=sys.stderr)
- sys.exit(1)
-
-sc = SuricataSC(SOCKET_PATH, verbose=args.verbose)
-try:
- sc.connect()
-except SuricataNetException as err:
- print("Unable to connect to socket %s: %s" % (SOCKET_PATH, err), file=sys.stderr)
- sys.exit(1)
-except SuricataReturnException as err:
- print("Unable to negotiate version with server: %s" % (err), file=sys.stderr)
- sys.exit(1)
-
-if args.command:
- try:
- (command, arguments) = sc.parse_command(args.command)
- except SuricataCommandException as err:
- print(err.value)
- sys.exit(1)
- try:
- res = sc.send_command(command, arguments)
- except (SuricataCommandException, SuricataReturnException) as err:
- print(err.value)
- sys.exit(1)
- print(json.dumps(res))
- sc.close()
- if res['return'] == 'OK':
- sys.exit(0)
- else:
- sys.exit(1)
-
-try:
- sc.interactive()
-except SuricataNetException as err:
- print("Communication error: %s" % (err))
- sys.exit(1)
-except SuricataReturnException as err:
- print("Invalid return from server: %s" % (err))
- sys.exit(1)
-
-print("[+] Quit command client")
-
-sc.close()
+++ /dev/null
-# Copyright (C) 2018 Open Information Security Foundation
-#
-# You can copy, redistribute or modify this Program under the terms of
-# the GNU General Public License version 2 as published by the Free
-# Software Foundation.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# version 2 along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
-
-from __future__ import print_function
-
-import sys
-import os
-import os.path
-import time
-import re
-import logging
-
-logger = logging.getLogger("filestore")
-
-
-class InvalidAgeFormatError(Exception):
- pass
-
-
-def register_args(parser):
- subparser = parser.add_subparsers(help="sub-command help")
- prune_parser = subparser.add_parser("prune",
- help="Remove files in specified directory older than specified age")
- required_args = prune_parser.add_argument_group("required arguments")
- required_args.add_argument("-d", "--directory",
- help="filestore directory", required=True)
- required_args.add_argument("--age",
- help="prune files older than age, units: s, m, h, d")
- prune_parser.add_argument(
- "-n", "--dry-run", action="store_true", default=False,
- help="only print what would happen")
- prune_parser.add_argument(
- "-v", "--verbose", action="store_true",
- default=False, help="increase verbosity")
- prune_parser.add_argument(
- "-q", "--quiet", action="store_true", default=False,
- help="be quiet, log warnings and errors only")
- prune_parser.set_defaults(func=prune)
-
-
-def is_fileinfo(path):
- return path.endswith(".json")
-
-
-def parse_age(age):
- matched_age = re.match(r"(\d+)\s*(\w+)", age)
- if not matched_age:
- raise InvalidAgeFormatError(age)
- val = int(matched_age.group(1))
- unit = matched_age.group(2)
- ts_units = ["s", "m", "h", "d"]
- try:
- idx = ts_units.index(unit)
- except ValueError:
- raise InvalidAgeFormatError("bad unit: %s" % (unit))
- multiplier = 60 ** idx if idx != 3 else 24 * 60 ** 2
- return val * multiplier
-
-
-def get_filesize(path):
- return os.stat(path).st_size
-
-
-def remove_file(path, dry_run):
- size = 0
- size += get_filesize(path)
- if not dry_run:
- os.unlink(path)
- return size
-
-
-def set_logger_level(args):
- if args.verbose:
- logger.setLevel(logging.DEBUG)
- if args.quiet:
- logger.setLevel(logging.WARNING)
-
-
-def perform_sanity_checks(args):
- set_logger_level(args)
- err_msg = {
- "directory": "filestore directory must be provided",
- "age": "no age provided, nothing to do",
- }
- for val, msg in err_msg.items():
- if not getattr(args, val):
- print("Error: {}".format(msg), file=sys.stderr)
- sys.exit(1)
- required_dirs = ["tmp", "00", "ff"]
- for required_dir in required_dirs:
- if not os.path.exists(os.path.join(args.directory, required_dir)):
- logger.error("Provided directory is not a filestore directory")
- sys.exit(1)
-
-
-def prune(args):
- perform_sanity_checks(args)
- age = parse_age(args.age)
- now = time.time()
- size = 0
- count = 0
-
- for dirpath, dirnames, filenames in os.walk(args.directory, topdown=True):
- # Do not go into the tmp directory.
- if "tmp" in dirnames:
- dirnames.remove("tmp")
- for filename in filenames:
- path = os.path.join(dirpath, filename)
- mtime = os.path.getmtime(path)
- this_age = now - mtime
- if this_age > age:
- logger.debug("Deleting %s; age=%ds", path, this_age)
- size += remove_file(path, args.dry_run)
- count += 1
- logger.info("Removed %d files; %d bytes.", count, size)
- return 0
+++ /dev/null
-# Copyright (C) 2017 Open Information Security Foundation
-# Copyright (c) 2016 Jason Ish
-#
-# You can copy, redistribute or modify this Program under the terms of
-# the GNU General Public License version 2 as published by the Free
-# Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# version 2 along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
-
-import logging
-import time
-
-GREEN = "\x1b[32m"
-BLUE = "\x1b[34m"
-REDB = "\x1b[1;31m"
-YELLOW = "\x1b[33m"
-RED = "\x1b[31m"
-YELLOWB = "\x1b[1;33m"
-ORANGE = "\x1b[38;5;208m"
-RESET = "\x1b[0m"
-
-# A list of secrets that will be replaced in the log output.
-secrets = {}
-
-def add_secret(secret, replacement):
- """Register a secret to be masked. The secret will be replaced with:
- <replacement>
- """
- secrets[str(secret)] = str(replacement)
-
-class SuriColourLogHandler(logging.StreamHandler):
- """An alternative stream log handler that logs with Suricata inspired
- log colours."""
-
- @staticmethod
- def format_time(record):
- local_time = time.localtime(record.created)
- formatted_time = "%d/%d/%d -- %02d:%02d:%02d" % (local_time.tm_mday,
- local_time.tm_mon,
- local_time.tm_year,
- local_time.tm_hour,
- local_time.tm_min,
- local_time.tm_sec)
- return "%s" % (formatted_time)
-
- def emit(self, record):
-
- if record.levelname == "ERROR":
- level_prefix = REDB
- message_prefix = REDB
- elif record.levelname == "WARNING":
- level_prefix = ORANGE
- message_prefix = ORANGE
- else:
- level_prefix = YELLOW
- message_prefix = ""
-
- self.stream.write("%s%s%s - <%s%s%s> -- %s%s%s\n" % (
- GREEN,
- self.format_time(record),
- RESET,
- level_prefix,
- record.levelname.title(),
- RESET,
- message_prefix,
- self.mask_secrets(record.getMessage()),
- RESET))
-
- @staticmethod
- def mask_secrets(msg):
- for secret in secrets:
- msg = msg.replace(secret, "<%s>" % secrets[secret])
- return msg
+++ /dev/null
-# Copyright (C) 2018 Open Information Security Foundation
-#
-# You can copy, redistribute or modify this Program under the terms of
-# the GNU General Public License version 2 as published by the Free
-# Software Foundation.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# version 2 along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
-
-import sys
-import os
-import argparse
-import logging
-
-from suricata.ctl import filestore, loghandler
-
-def init_logger():
- """ Initialize logging, use colour if on a tty. """
- if os.isatty(sys.stderr.fileno()):
- logger = logging.getLogger()
- logger.setLevel(level=logging.INFO)
- logger.addHandler(loghandler.SuriColourLogHandler())
- else:
- logging.basicConfig(
- level=logging.INFO,
- format="%(asctime)s - <%(levelname)s> - %(message)s")
-
-def main():
- init_logger()
- parser = argparse.ArgumentParser()
- subparsers = parser.add_subparsers(help='sub-command help')
- fs_parser = subparsers.add_parser("filestore", help="Filestore related commands")
- filestore.register_args(parser=fs_parser)
- args = parser.parse_args()
- try:
- func = args.func
- except AttributeError:
- parser.error("too few arguments")
- func(args)
+++ /dev/null
-from __future__ import print_function
-
-import unittest
-
-from suricata.ctl import filestore
-
-class PruneTestCase(unittest.TestCase):
-
- def test_parse_age(self):
- self.assertEqual(filestore.parse_age("1s"), 1)
- self.assertEqual(filestore.parse_age("1m"), 60)
- self.assertEqual(filestore.parse_age("1h"), 3600)
- self.assertEqual(filestore.parse_age("1d"), 86400)
-
- with self.assertRaises(filestore.InvalidAgeFormatError):
- filestore.parse_age("1")
- with self.assertRaises(filestore.InvalidAgeFormatError):
- filestore.parse_age("1y")
+++ /dev/null
-from suricata.sc.suricatasc import *
+++ /dev/null
-argsd = {
- "pcap-file": [
- {
- "name": "filename",
- "required": 1,
- },
- {
- "name": "output-dir",
- "required": 1,
- },
- {
- "name": "tenant",
- "type": int,
- "required": 0,
- },
- {
- "name": "continuous",
- "required": 0,
- },
- {
- "name": "delete-when-done",
- "required": 0,
- },
- ],
- "pcap-file-continuous": [
- {
- "name": "filename",
- "required": 1,
- },
- {
- "name": "output-dir",
- "required": 1,
- },
- {
- "name": "continuous",
- "val": True,
- "required": 1,
- },
- {
- "name": "tenant",
- "type": int,
- "required": 0,
- },
- {
- "name": "delete-when-done",
- "required": 0,
- },
- ],
- "iface-stat": [
- {
- "name": "iface",
- "required": 1,
- },
- ],
- "conf-get": [
- {
- "name": "variable",
- "required": 1,
- }
- ],
- "unregister-tenant-handler": [
- {
- "name": "id",
- "type": int,
- "required": 1,
- },
- {
- "name": "htype",
- "required": 1,
- },
- {
- "name": "hargs",
- "type": int,
- "required": 0,
- },
- ],
- "register-tenant-handler": [
- {
- "name": "id",
- "type": int,
- "required": 1,
- },
- {
- "name": "htype",
- "required": 1,
- },
- {
- "name": "hargs",
- "type": int,
- "required": 0,
- },
- ],
- "unregister-tenant": [
- {
- "name": "id",
- "type": int,
- "required": 1,
- },
- ],
- "register-tenant": [
- {
- "name": "id",
- "type": int,
- "required": 1,
- },
- {
- "name": "filename",
- "required": 1,
- },
- ],
- "reload-tenant": [
- {
- "name": "id",
- "type": int,
- "required": 1,
- },
- {
- "name": "filename",
- "required": 0,
- },
- ],
- "add-hostbit": [
- {
- "name": "ipaddress",
- "required": 1,
- },
- {
- "name": "hostbit",
- "required": 1,
- },
- {
- "name": "expire",
- "type": int,
- "required": 1,
- },
- ],
- "remove-hostbit": [
- {
- "name": "ipaddress",
- "required": 1,
- },
- {
- "name": "hostbit",
- "required": 1,
- },
- ],
- "list-hostbit": [
- {
- "name": "ipaddress",
- "required": 1,
- },
- ],
- "memcap-set": [
- {
- "name": "config",
- "required": 1,
- },
- {
- "name": "memcap",
- "required": 1,
- },
- ],
- "memcap-show": [
- {
- "name": "config",
- "required": 1,
- },
- ],
- "dataset-add": [
- {
- "name": "setname",
- "required": 1,
- },
- {
- "name": "settype",
- "required": 1,
- },
- {
- "name": "datavalue",
- "required": 1,
- },
- ],
- "dataset-remove": [
- {
- "name": "setname",
- "required": 1,
- },
- {
- "name": "settype",
- "required": 1,
- },
- {
- "name": "datavalue",
- "required": 1,
- },
- ],
- "get-flow-stats-by-id": [
- {
- "name": "flow_id",
- "type": int,
- "required": 1,
- },
- ],
- "dataset-clear": [
- {
- "name": "setname",
- "required": 1,
- },
- {
- "name": "settype",
- "required": 1,
- }
- ],
- "dataset-lookup": [
- {
- "name": "setname",
- "required": 1,
- },
- {
- "name": "settype",
- "required": 1,
- },
- {
- "name": "datavalue",
- "required": 1,
- },
- ],
- }
+++ /dev/null
-# Copyright(C) 2012-2023 Open Information Security Foundation
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, version 2 of the License.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
-
-try:
- import simplejson as json
-except ImportError:
- import json
-import readline
-import select
-import sys
-from socket import AF_UNIX, error, socket
-from inspect import currentframe
-
-from suricata.sc.specs import argsd
-
-SURICATASC_VERSION = "1.0"
-VERSION = "0.2"
-INC_SIZE = 1024
-
-
-def get_linenumber():
- cf = currentframe()
- return cf.f_back.f_lineno
-
-
-class SuricataException(Exception):
- """
- Generic class for suricatasc exception
- """
- def __init__(self, value):
- super(SuricataException, self).__init__(value)
- self.value = value
-
- def __str__(self):
- return str(self.value)
-
-
-class SuricataNetException(SuricataException):
- """
- Exception raised when a network error occurs
- """
-
-
-class SuricataCommandException(SuricataException):
- """
- Exception raised when the command is incorrect
- """
-
-
-class SuricataReturnException(SuricataException):
- """
- Exception raised when return message is incorrect
- """
-
-
-class SuricataCompleter:
- def __init__(self, words):
- self.words = words
- self.generator = None
-
- def complete(self, text):
- for word in self.words:
- if word.startswith(text):
- yield word
-
- def __call__(self, text, state):
- if state == 0:
- self.generator = self.complete(text)
- try:
- return next(self.generator)
- except StopIteration:
- return None
-
-
-class SuricataSC:
- def __init__(self, sck_path, verbose=False):
- self.basic_commands = [
- "shutdown",
- "quit",
- "pcap-file-number",
- "pcap-file-list",
- "pcap-last-processed",
- "pcap-interrupt",
- "iface-list",
- "reload-tenants",
- ]
- self.fn_commands = [
- "pcap-file",
- "pcap-file-continuous",
- "iface-stat",
- "conf-get",
- "unregister-tenant-handler",
- "register-tenant-handler",
- "unregister-tenant",
- "register-tenant",
- "reload-tenant",
- "add-hostbit",
- "remove-hostbit",
- "list-hostbit",
- "memcap-set",
- "memcap-show",
- "dataset-add",
- "dataset-remove",
- "get-flow-stats-by-id",
- "dataset-clear",
- "dataset-lookup",
- ]
- self.cmd_list = self.basic_commands + self.fn_commands
- self.sck_path = sck_path
- self.verbose = verbose
- self.socket = socket(AF_UNIX)
-
- def json_recv(self):
- cmdret = None
- data = ""
- while True:
- if sys.version < '3':
- received = self.socket.recv(INC_SIZE)
- else:
- received = self.socket.recv(INC_SIZE).decode('iso-8859-1')
-
- if not received:
- break
-
- data += received
- if data.endswith('\n'):
- cmdret = json.loads(data)
- break
- return cmdret
-
- def send_command(self, command, arguments=None):
- if command not in self.cmd_list and command != 'command-list':
- raise SuricataCommandException("L{}: Command not found: {}".format(get_linenumber(), command))
-
- cmdmsg = {}
- cmdmsg['command'] = command
- if arguments:
- cmdmsg['arguments'] = arguments
- if self.verbose:
- print("SND: " + json.dumps(cmdmsg))
- cmdmsg_str = json.dumps(cmdmsg) + "\n"
- if sys.version < '3':
- self.socket.send(cmdmsg_str)
- else:
- self.socket.send(bytes(cmdmsg_str, 'iso-8859-1'))
-
- ready = select.select([self.socket], [], [], 600)
- if ready[0]:
- cmdret = self.json_recv()
- else:
- cmdret = None
- if not cmdret:
- raise SuricataReturnException("L{}: Unable to get message from server".format(get_linenumber))
-
- if self.verbose:
- print("RCV: "+ json.dumps(cmdret))
-
- return cmdret
-
- def connect(self):
- try:
- if self.socket is None:
- self.socket = socket(AF_UNIX)
- self.socket.connect(self.sck_path)
- except error as err:
- raise SuricataNetException("L{}: {}".format(get_linenumber(), err))
-
- self.socket.settimeout(10)
- #send version
- if self.verbose:
- print("SND: " + json.dumps({"version": VERSION}))
- if sys.version < '3':
- self.socket.send(json.dumps({"version": VERSION}))
- else:
- self.socket.send(bytes(json.dumps({"version": VERSION}), 'iso-8859-1'))
-
- ready = select.select([self.socket], [], [], 600)
- if ready[0]:
- cmdret = self.json_recv()
- else:
- cmdret = None
-
- if not cmdret:
- raise SuricataReturnException("L{}: Unable to get message from server".format(get_linenumber()))
-
- if self.verbose:
- print("RCV: "+ json.dumps(cmdret))
-
- if cmdret["return"] == "NOK":
- raise SuricataReturnException("L{}: Error: {}".format(get_linenumber(), cmdret["message"]))
-
- cmdret = self.send_command("command-list")
-
- # we silently ignore NOK as this means server is old
- if cmdret["return"] == "OK":
- self.cmd_list = cmdret["message"]["commands"]
- self.cmd_list.append("quit")
-
- def close(self):
- self.socket.close()
- self.socket = None
-
- def execute(self, command):
- full_cmd = command.split()
- cmd = full_cmd[0]
- cmd_specs = argsd[cmd]
- required_args_count = len([d["required"] for d in cmd_specs if d["required"] and not "val" in d])
- arguments = dict()
- for c, spec in enumerate(cmd_specs, 1):
- spec_type = str if "type" not in spec else spec["type"]
- if spec["required"]:
- if spec.get("val"):
- arguments[spec["name"]] = spec_type(spec["val"])
- continue
- try:
- arguments[spec["name"]] = spec_type(full_cmd[c])
- except IndexError:
- phrase = " at least" if required_args_count != len(cmd_specs) else ""
- msg = "Missing arguments: expected{} {}".format(phrase, required_args_count)
- raise SuricataCommandException("L{}: {}".format(get_linenumber(), msg))
- except ValueError as ve:
- raise SuricataCommandException("L{}: Erroneous arguments: {}".format(get_linenumber(), ve))
- elif c < len(full_cmd):
- arguments[spec["name"]] = spec_type(full_cmd[c])
- return cmd, arguments
-
- def parse_command(self, command):
- arguments = None
- cmd = command.split()[0] if command else None
- if cmd in self.cmd_list:
- if cmd in self.fn_commands:
- cmd, arguments = getattr(self, "execute")(command=command)
- else:
- raise SuricataCommandException("L{}: Unknown command: {}".format(get_linenumber(), command))
- return cmd, arguments
-
- def interactive(self):
- print("Command list: " + ", ".join(self.cmd_list))
- try:
- readline.set_completer(SuricataCompleter(self.cmd_list))
- readline.set_completer_delims(";")
- readline.parse_and_bind('tab: complete')
- while True:
- if sys.version < '3':
- command = raw_input(">>> ").strip()
- else:
- command = input(">>> ").strip()
- if command == "quit":
- break
- if len(command.strip()) == 0:
- continue
- try:
- cmd, arguments = self.parse_command(command)
- except SuricataCommandException as err:
- print(err)
- continue
- try:
- cmdret = self.send_command(cmd, arguments)
- except IOError as err:
- # try to reconnect and resend command
- print("Connection lost, trying to reconnect")
- try:
- self.close()
- self.connect()
- except (SuricataNetException, SuricataReturnException) as err:
- print(err.value)
- continue
- cmdret = self.send_command(cmd, arguments)
- except (SuricataCommandException, SuricataReturnException) as err:
- print("An exception occured: " + str(err.value))
- continue
- #decode json message
- if cmdret["return"] == "NOK":
- print("Error:")
- print(json.dumps(cmdret["message"], sort_keys=True, indent=4, separators=(',', ': ')))
- else:
- print("Success:")
- print(json.dumps(cmdret["message"], sort_keys=True, indent=4, separators=(',', ': ')))
- except KeyboardInterrupt:
- print("[!] Interrupted")
- sys.exit(0)
+++ /dev/null
-from suricata.sc import *