summaryrefslogtreecommitdiffstats
path: root/framework/src/suricata/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/suricata/scripts')
-rw-r--r--framework/src/suricata/scripts/Makefile.am1
-rw-r--r--framework/src/suricata/scripts/setup_decoder.sh85
-rw-r--r--framework/src/suricata/scripts/setup_simple_detect.sh93
-rw-r--r--framework/src/suricata/scripts/suricatasc/Makefile.am19
-rwxr-xr-xframework/src/suricata/scripts/suricatasc/setup.py26
-rw-r--r--framework/src/suricata/scripts/suricatasc/src/__init__.py2
-rw-r--r--framework/src/suricata/scripts/suricatasc/src/suricatasc.py314
-rwxr-xr-xframework/src/suricata/scripts/suricatasc/suricatasc.in65
8 files changed, 605 insertions, 0 deletions
diff --git a/framework/src/suricata/scripts/Makefile.am b/framework/src/suricata/scripts/Makefile.am
new file mode 100644
index 00000000..96bd2221
--- /dev/null
+++ b/framework/src/suricata/scripts/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS=suricatasc
diff --git a/framework/src/suricata/scripts/setup_decoder.sh b/framework/src/suricata/scripts/setup_decoder.sh
new file mode 100644
index 00000000..9af4104e
--- /dev/null
+++ b/framework/src/suricata/scripts/setup_decoder.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+#
+# Script to setup a new decoder.
+# Written by Victor Julien <victor@inliniac.net>
+#
+
+set -e
+#set -x
+
+function Usage {
+ echo
+ echo "$(basename $0) -- script to provision a decoder. The script"
+ echo "makes a copy of the decode-template, sets the name and updates"
+ echo " the build system."
+ echo
+ echo "Call from the 'src' directory, with one argument: the decoder name."
+ echo
+ echo "E.g. inside 'src': ../scripts/$(basename $0) ipv7"
+ echo
+}
+
+function Done {
+ echo
+ echo "Decoder $NR has been set up in $FILE_C and $FILE_H and the"
+ echo "build system has been updated."
+ echo
+ echo "The decoder should now compile cleanly. Try running 'make'."
+ echo
+ echo "Next steps are to edit the files to implement the actual"
+ echo "decoding of $NR."
+ echo
+}
+
+if [ $# -ne "1" ]; then
+ Usage
+ echo "ERROR: call with one argument"
+ exit 1
+fi
+
+INPUT=$1
+# lowercase
+LC=${INPUT,,}
+#echo $LC
+# UPPERCASE
+UC=${LC^^}
+#echo $UC
+# Normal
+NR=${LC^}
+#echo $NR
+
+FILE_C="decode-${LC}.c"
+FILE_H="decode-${LC}.h"
+#echo $FILE_C
+#echo $FILE_H
+
+if [ ! -e ../configure.ac ] || [ ! -e Makefile.am ]; then
+ Usage
+ echo "ERROR: call from src/ directory"
+ exit 1
+fi
+if [ ! -e decode-template.c ] || [ ! -e decode-template.h ]; then
+ Usage
+ echo "ERROR: input files decode-template.c and/or decode-template.h are missing"
+ exit 1
+fi
+if [ -e $FILE_C ] || [ -e $FILE_H ]; then
+ Usage
+ echo "ERROR: file(s) $FILE_C and/or $FILE_H already exist, won't overwrite"
+ exit 1
+fi
+
+cp decode-template.c $FILE_C
+cp decode-template.h $FILE_H
+
+# search and replaces
+sed -i "s/TEMPLATE/${UC}/g" $FILE_C
+sed -i "s/TEMPLATE/${UC}/g" $FILE_H
+sed -i "s/Template/${NR}/g" $FILE_C
+sed -i "s/Template/${NR}/g" $FILE_H
+sed -i "s/template/${LC}/g" $FILE_C
+sed -i "s/template/${LC}/g" $FILE_H
+sed -i "s/decode-template.c decode-template.h \\\/decode-template.c decode-template.h \\\\\n${FILE_C} ${FILE_H} \\\/g" Makefile.am
+
+Done
+exit 0
diff --git a/framework/src/suricata/scripts/setup_simple_detect.sh b/framework/src/suricata/scripts/setup_simple_detect.sh
new file mode 100644
index 00000000..309b47cc
--- /dev/null
+++ b/framework/src/suricata/scripts/setup_simple_detect.sh
@@ -0,0 +1,93 @@
+#!/bin/bash
+#
+# Script to setup a new 'simple' detect module.
+# Written by Victor Julien <victor@inliniac.net>
+#
+
+set -e
+#set -x
+
+function Usage {
+ echo
+ echo "$(basename $0) -- script to provision a detect module. The script"
+ echo "makes a copy of detect-template, sets the name and updates"
+ echo "the build system."
+ echo
+ echo "Call from the 'src' directory, with one argument: the detect module"
+ echo "name."
+ echo
+ echo "E.g. inside 'src': ../scripts/$(basename $0) helloworld"
+ echo
+}
+
+function Done {
+ echo
+ echo "Detect module $NR has been set up in $FILE_C and $FILE_H"
+ echo "and the build system has been updated."
+ echo
+ echo "The detect module should now compile cleanly. Try running 'make'."
+ echo
+ echo "Next steps are to edit the files to implement the actual"
+ echo "detection logic of $NR."
+ echo
+}
+
+if [ $# -ne "1" ]; then
+ Usage
+ echo "ERROR: call with one argument"
+ exit 1
+fi
+
+INPUT=$1
+# lowercase
+LC=${INPUT,,}
+#echo $LC
+# UPPERCASE
+UC=${LC^^}
+#echo $UC
+# Normal
+NR=${LC^}
+#echo $NR
+
+FILE_C="detect-${LC}.c"
+FILE_H="detect-${LC}.h"
+#echo $FILE_C
+#echo $FILE_H
+
+if [ ! -e ../configure.ac ] || [ ! -e Makefile.am ]; then
+ Usage
+ echo "ERROR: call from src/ directory"
+ exit 1
+fi
+if [ ! -e detect-template.c ] || [ ! -e detect-template.h ]; then
+ Usage
+ echo "ERROR: input files detect-template.c and/or detect-template.h are missing"
+ exit 1
+fi
+if [ -e $FILE_C ] || [ -e $FILE_H ]; then
+ Usage
+ echo "ERROR: file(s) $FILE_C and/or $FILE_H already exist, won't overwrite"
+ exit 1
+fi
+
+cp detect-template.c $FILE_C
+cp detect-template.h $FILE_H
+
+# search and replaces
+sed -i "s/TEMPLATE/${UC}/g" $FILE_C
+sed -i "s/TEMPLATE/${UC}/g" $FILE_H
+sed -i "s/Template/${NR}/g" $FILE_C
+sed -i "s/Template/${NR}/g" $FILE_H
+sed -i "s/template/${LC}/g" $FILE_C
+sed -i "s/template/${LC}/g" $FILE_H
+# add to Makefile.am
+sed -i "s/detect-template.c detect-template.h \\\/detect-template.c detect-template.h \\\\\n${FILE_C} ${FILE_H} \\\/g" Makefile.am
+# update enum
+sed -i "s/DETECT_TEMPLATE,/DETECT_TEMPLATE,\\n DETECT_${UC},/g" detect.h
+# add include to detect.c
+sed -i "s/#include \"detect-template.h\"/#include \"detect-template.h\"\\n#include \"${FILE_H}\"/g" detect.c
+# add reg func to detect.c
+sed -i "s/DetectTemplateRegister();/DetectTemplateRegister();\\n Detect${NR}Register();/g" detect.c
+
+Done
+exit 0
diff --git a/framework/src/suricata/scripts/suricatasc/Makefile.am b/framework/src/suricata/scripts/suricatasc/Makefile.am
new file mode 100644
index 00000000..63989347
--- /dev/null
+++ b/framework/src/suricata/scripts/suricatasc/Makefile.am
@@ -0,0 +1,19 @@
+EXTRA_DIST = setup.py suricatasc.in src/__init__.py src/suricatasc.py
+
+if HAVE_PYTHON
+all-local:
+ mkdir -p $(top_builddir)/scripts/suricatasc/src
+ $(PYTHON) $(srcdir)/setup.py build;
+
+install-exec-local:
+ $(PYTHON) $(srcdir)/setup.py install --prefix $(DESTDIR)$(prefix)
+
+clean-local:
+ $(PYTHON) $(srcdir)/setup.py clean;
+ rm -rf $(top_builddir)/scripts/suricatasc/build
+
+uninstall-local:
+ [ ! -f "$(DESTDIR)$(prefix)/bin/suricatasc" ] || rm -f "$(DESTDIR)$(prefix)/bin/suricatasc"
+ find "$(DESTDIR)$(prefix)/lib" -name "suricatasc-*.egg-info" -delete ||true
+
+endif
diff --git a/framework/src/suricata/scripts/suricatasc/setup.py b/framework/src/suricata/scripts/suricatasc/setup.py
new file mode 100755
index 00000000..2d37919b
--- /dev/null
+++ b/framework/src/suricata/scripts/suricatasc/setup.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+from distutils.core import setup
+
+SURICATASC_VERSION = "0.9"
+
+setup(name='suricatasc',
+ version=SURICATASC_VERSION,
+ description='Suricata unix socket client',
+ author='Eric Leblond',
+ author_email='eric@regit.org',
+ url='https://www.suricata-ids.org/',
+ scripts=['suricatasc'],
+ packages=['suricatasc'],
+ package_dir={'suricatasc':'src'},
+ provides=['suricatasc'],
+ requires=['argparse','simplejson'],
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Console',
+ 'Intended Audience :: System Administrators',
+ 'License :: OSI Approved :: GNU General Public License (GPL)',
+ 'Operating System :: POSIX',
+ 'Programming Language :: Python',
+ 'Topic :: System :: Systems Administration',
+ ],
+ )
diff --git a/framework/src/suricata/scripts/suricatasc/src/__init__.py b/framework/src/suricata/scripts/suricatasc/src/__init__.py
new file mode 100644
index 00000000..1a61f426
--- /dev/null
+++ b/framework/src/suricata/scripts/suricatasc/src/__init__.py
@@ -0,0 +1,2 @@
+
+from suricatasc import *
diff --git a/framework/src/suricata/scripts/suricatasc/src/suricatasc.py b/framework/src/suricata/scripts/suricatasc/src/suricatasc.py
new file mode 100644
index 00000000..1a776a29
--- /dev/null
+++ b/framework/src/suricata/scripts/suricatasc/src/suricatasc.py
@@ -0,0 +1,314 @@
+#!/usr/bin/python
+# Copyright(C) 2012 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+try:
+ import simplejson as json
+except:
+ import json
+import re
+import readline
+from socket import socket, AF_UNIX, error
+from time import sleep
+import select
+import sys
+
+SURICATASC_VERSION = "0.9"
+
+VERSION = "0.1"
+SIZE = 4096
+
+class SuricataException(Exception):
+ """
+ Generic class for suricatasc exception
+ """
+ def __init__(self, value):
+ self.value = value
+
+ def __str__(self):
+ return str(self.value)
+
+class SuricataNetException(SuricataException):
+ """
+ Exception raised when network error occur.
+ """
+ pass
+
+class SuricataCommandException(SuricataException):
+ """
+ Exception raised when command is not correct.
+ """
+ pass
+
+class SuricataReturnException(SuricataException):
+ """
+ Exception raised when return message is not correct.
+ """
+ pass
+
+
+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
+ return None
+
+class SuricataSC:
+ def __init__(self, sck_path, verbose=False):
+ self.cmd_list=['shutdown','quit','pcap-file','pcap-file-number','pcap-file-list','iface-list','iface-stat','register-tenant','unregister-tenant','register-tenant-handler','unregister-tenant-handler']
+ self.sck_path = sck_path
+ self.verbose = verbose
+
+ def json_recv(self):
+ cmdret = None
+ i = 0
+ data = ""
+ while i < 5:
+ i += 1
+ if sys.version < '3':
+ data += self.socket.recv(SIZE)
+ else:
+ data += self.socket.recv(SIZE).decode('iso-8859-1')
+ try:
+ cmdret = json.loads(data)
+ break
+ except:
+ sleep(0.3)
+ return cmdret
+
+ def send_command(self, command, arguments = None):
+ if command not in self.cmd_list and command != 'command-list':
+ raise SuricataCommandException("No such command: %s", command)
+
+ cmdmsg = {}
+ cmdmsg['command'] = command
+ if (arguments != None):
+ cmdmsg['arguments'] = arguments
+ if self.verbose:
+ print("SND: " + json.dumps(cmdmsg))
+ if sys.version < '3':
+ self.socket.send(json.dumps(cmdmsg))
+ else:
+ self.socket.send(bytes(json.dumps(cmdmsg), 'iso-8859-1'))
+
+ ready = select.select([self.socket], [], [], 600)
+ if ready[0]:
+ cmdret = self.json_recv()
+ else:
+ cmdret = None
+
+ if cmdret == None:
+ raise SuricataReturnException("Unable to get message from server")
+
+ if self.verbose:
+ print("RCV: "+ json.dumps(cmdret))
+
+ return cmdret
+
+ def connect(self):
+ try:
+ self.socket = socket(AF_UNIX)
+ self.socket.connect(self.sck_path)
+ except error as err:
+ raise SuricataNetException(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 cmdret == None:
+ raise SuricataReturnException("Unable to get message from server")
+
+ if self.verbose:
+ print("RCV: "+ json.dumps(cmdret))
+
+ if cmdret["return"] == "NOK":
+ raise SuricataReturnException("Error: %s" % (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()
+
+ def parse_command(self, command):
+ arguments = None
+ if command.split(' ', 2)[0] in self.cmd_list:
+ if "pcap-file " in command:
+ try:
+ parts = command.split(' ');
+ except:
+ raise SuricataCommandException("Arguments to command '%s' is missing" % (command))
+ cmd, filename, output = parts[0], parts[1], parts[2]
+ tenant = None
+ if len(parts) > 3:
+ tenant = parts[3]
+ if cmd != "pcap-file":
+ raise SuricataCommandException("Invalid command '%s'" % (command))
+ else:
+ arguments = {}
+ arguments["filename"] = filename
+ arguments["output-dir"] = output
+ if tenant != None:
+ arguments["tenant"] = int(tenant)
+ elif "iface-stat" in command:
+ try:
+ [cmd, iface] = command.split(' ', 1)
+ except:
+ raise SuricataCommandException("Unable to split command '%s'" % (command))
+ if cmd != "iface-stat":
+ raise SuricataCommandException("Invalid command '%s'" % (command))
+ else:
+ arguments = {}
+ arguments["iface"] = iface
+ elif "conf-get" in command:
+ try:
+ [cmd, variable] = command.split(' ', 1)
+ except:
+ raise SuricataCommandException("Unable to split command '%s'" % (command))
+ if cmd != "conf-get":
+ raise SuricataCommandException("Invalid command '%s'" % (command))
+ else:
+ arguments = {}
+ arguments["variable"] = variable
+ elif "unregister-tenant-handler" in command:
+ try:
+ parts = command.split(' ')
+ except:
+ raise SuricataCommandException("Arguments to command '%s' is missing" % (command))
+ cmd, tenantid, htype = parts[0], parts[1], parts[2]
+ hargs = None
+ if len(parts) > 3:
+ hargs = parts[3]
+ if cmd != "unregister-tenant-handler":
+ raise SuricataCommandException("Invalid command '%s'" % (command))
+ else:
+ arguments = {}
+ arguments["id"] = int(tenantid)
+ arguments["htype"] = htype
+ if hargs != None:
+ arguments["hargs"] = int(hargs)
+ elif "register-tenant-handler" in command:
+ try:
+ parts = command.split(' ')
+ except:
+ raise SuricataCommandException("Arguments to command '%s' is missing" % (command))
+ cmd, tenantid, htype = parts[0], parts[1], parts[2]
+ hargs = None
+ if len(parts) > 3:
+ hargs = parts[3]
+ if cmd != "register-tenant-handler":
+ raise SuricataCommandException("Invalid command '%s'" % (command))
+ else:
+ arguments = {}
+ arguments["id"] = int(tenantid)
+ arguments["htype"] = htype
+ if hargs != None:
+ arguments["hargs"] = int(hargs)
+ elif "unregister-tenant" in command:
+ try:
+ [cmd, tenantid] = command.split(' ', 1)
+ except:
+ raise SuricataCommandException("Unable to split command '%s'" % (command))
+ if cmd != "unregister-tenant":
+ raise SuricataCommandException("Invalid command '%s'" % (command))
+ else:
+ arguments = {}
+ arguments["id"] = int(tenantid)
+ elif "register-tenant" in command:
+ try:
+ [cmd, tenantid, filename] = command.split(' ', 2)
+ except:
+ raise SuricataCommandException("Arguments to command '%s' is missing" % (command))
+ if cmd != "register-tenant":
+ raise SuricataCommandException("Invalid command '%s'" % (command))
+ else:
+ arguments = {}
+ arguments["id"] = int(tenantid)
+ arguments["filename"] = filename
+ elif "reload-tenant" in command:
+ try:
+ [cmd, tenantid, filename] = command.split(' ', 2)
+ except:
+ raise SuricataCommandException("Arguments to command '%s' is missing" % (command))
+ if cmd != "reload-tenant":
+ raise SuricataCommandException("Invalid command '%s'" % (command))
+ else:
+ arguments = {}
+ arguments["id"] = int(tenantid)
+ arguments["filename"] = filename
+ else:
+ cmd = command
+ else:
+ raise SuricataCommandException("Unknown command '%s'" % (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;
+ try:
+ (cmd, arguments) = self.parse_command(command)
+ except SuricataCommandException as err:
+ print(err)
+ continue
+ cmdret = self.send_command(cmd, arguments)
+ #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")
diff --git a/framework/src/suricata/scripts/suricatasc/suricatasc.in b/framework/src/suricata/scripts/suricatasc/suricatasc.in
new file mode 100755
index 00000000..63b4ebfa
--- /dev/null
+++ b/framework/src/suricata/scripts/suricatasc/suricatasc.in
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+# Copyright(C) 2013 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+from __future__ import print_function
+import sys
+import argparse
+from suricatasc import *
+
+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 connnect to', default=None)
+args = parser.parse_args()
+
+if args.socket != None:
+ SOCKET_PATH = args.socket
+else:
+ SOCKET_PATH = "@e_localstatedir@/suricata-command.socket"
+
+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:
+ (command, arguments) = sc.parse_command(args.command)
+ res = sc.send_command(command, arguments)
+ 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()