fi
AM_CONDITIONAL([HAVE_COCCINELLE], [test "$HAVE_COCCINELLE_CONFIG" != "no"])
+ AC_PATH_PROG(HAVE_PYTHON_CONFIG, python, "no")
+ if test "$HAVE_PYTHON_CONFIG" = "no"; then
+ echo
+ echo " Warning! python not found, you will not be "
+ echo " able to install surictasc unix socket client "
+ echo
+ enable_python="no"
+ else
+ enable_python="yes"
+ fi
+ AM_CONDITIONAL([HAVE_PYTHON], [test "$HAVE_PYTHON_CONFIG" != "no"])
+
+
# Checks for libraries.
Old barnyard2 support: ${enable_old_barnyard2}
CUDA enabled: ${enable_cuda}
+ Suricatasc install: ${enable_python}
+
Unit tests enabled: ${enable_unittests}
Debug output enabled: ${enable_debug}
Debug validation enabled: ${enable_debug_validation}
-bin_SCRIPTS = suricatasc
+EXTRA_DIST = setup.py suricatasc.in src/__init__.py src/suricatasc.py
+
+if HAVE_PYTHON
+all-local:
+ $(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
--- /dev/null
+#!/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',
+ ],
+ )
--- /dev/null
+
+from suricatasc import *
--- /dev/null
+#!/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.
+
+import simplejson as json
+import re
+import readline
+from socket import socket, AF_UNIX, error
+from time import sleep
+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 self.generator.next()
+ 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']
+ self.sck_path = sck_path
+ self.verbose = verbose
+
+ def json_recv(self):
+ cmdret = None
+ i = 0
+ data = ""
+ while i < 5:
+ i += 1
+ data += self.socket.recv(SIZE)
+ try:
+ cmdret = json.loads(data)
+ break
+ except json.decoder.JSONDecodeError:
+ 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)
+ self.socket.send(json.dumps(cmdmsg))
+ cmdret = self.json_recv()
+
+ 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, err:
+ raise SuricataNetException(err)
+
+ self.socket.settimeout(10)
+ #send version
+ if self.verbose:
+ print "SND: " + json.dumps({"version": VERSION})
+ self.socket.send(json.dumps({"version": VERSION}))
+
+ # get return
+ cmdret = self.json_recv()
+
+ 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 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:
+ command = raw_input(">>> ").strip()
+ arguments = None
+ if command.split(' ', 2)[0] in self.cmd_list:
+ if command == "quit":
+ break;
+ if "pcap-file " in command:
+ try:
+ [cmd, filename, output] = command.split(' ', 2)
+ except:
+ print "Error: arguments to command '%s' is missing" % (command)
+ continue
+ if cmd != "pcap-file":
+ print "Error: invalid command '%s'" % (command)
+ continue
+ else:
+ arguments = {}
+ arguments["filename"] = filename
+ arguments["output-dir"] = output
+ elif "iface-stat" in command:
+ try:
+ [cmd, iface] = command.split(' ', 1)
+ except:
+ print "Error: unable to split command '%s'" % (command)
+ continue
+ if cmd != "iface-stat":
+ print "Error: invalid command '%s'" % (command)
+ continue
+ else:
+ arguments = {}
+ arguments["iface"] = iface
+ elif "conf-get" in command:
+ try:
+ [cmd, variable] = command.split(' ', 1)
+ except:
+ print "Error: unable to split command '%s'" % (command)
+ continue
+ if cmd != "conf-get":
+ print "Error: invalid command '%s'" % (command)
+ continue
+ else:
+ arguments = {}
+ arguments["variable"] = variable
+ else:
+ cmd = command
+ else:
+ print "Error: unknown command '%s'" % (command)
+ 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"
#!/usr/bin/python
-# Copyright(C) 2012 Open Information Security Foundation
+# 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
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-import simplejson as json
-import re
-from socket import socket, AF_UNIX, error
-from time import sleep
-import sys
-VERSION = "0.1"
-SIZE = 4096
+import argparse
+from suricatasc import *
-class SuricataException(Exception):
- """
- Generic class for suricatasc exception
- """
- def __init__(self, value):
- self.value = value
+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('socket', metavar='socket', nargs='?', help='socket file to connnect to', default=None)
+args = parser.parse_args()
- def __str__(self):
- return str(self.value)
+if args.socket != None:
+ SOCKET_PATH = "@e_localstatedir@/" + args.socket[0]
+else:
+ SOCKET_PATH = "@e_localstatedir@/suricata-command.socket"
-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 self.generator.next()
- 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']
- self.sck_path = sck_path
- self.verbose = verbose
-
- def json_recv(self):
- cmdret = None
- i = 0
- data = ""
- while i < 5:
- i += 1
- data += self.socket.recv(SIZE)
- try:
- cmdret = json.loads(data)
- break
- except json.decoder.JSONDecodeError:
- 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)
- self.socket.send(json.dumps(cmdmsg))
- cmdret = self.json_recv()
-
- 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(SOCKET_PATH)
- except error, err:
- raise SuricataNetException(err)
-
- self.socket.settimeout(10)
- #send version
- if self.verbose:
- print "SND: " + json.dumps({"version": VERSION})
- self.socket.send(json.dumps({"version": VERSION}))
-
- # get return
- cmdret = self.json_recv()
-
- 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"]))
-
- def close(self):
- self.socket.close()
-
- def interactive(self):
- 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")
- 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:
- command = raw_input(">>> ").strip()
- arguments = None
- if command.split(' ', 2)[0] in self.cmd_list:
- if command == "quit":
- break;
- if "pcap-file " in command:
- try:
- [cmd, filename, output] = command.split(' ', 2)
- except:
- print "Error: arguments to command '%s' is missing" % (command)
- continue
- if cmd != "pcap-file":
- print "Error: invalid command '%s'" % (command)
- continue
- else:
- arguments = {}
- arguments["filename"] = filename
- arguments["output-dir"] = output
- elif "iface-stat" in command:
- try:
- [cmd, iface] = command.split(' ', 1)
- except:
- print "Error: unable to split command '%s'" % (command)
- continue
- if cmd != "iface-stat":
- print "Error: invalid command '%s'" % (command)
- continue
- else:
- arguments = {}
- arguments["iface"] = iface
- elif "conf-get" in command:
- try:
- [cmd, variable] = command.split(' ', 1)
- except:
- print "Error: unable to split command '%s'" % (command)
- continue
- if cmd != "conf-get":
- print "Error: invalid command '%s'" % (command)
- continue
- else:
- arguments = {}
- arguments["variable"] = variable
- else:
- cmd = command
- else:
- print "Error: unknown command '%s'" % (command)
- 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"
-
-if __name__ == '__main__':
- import readline
- import argparse
- 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('socket', metavar='socket', nargs='?', help='socket file to connnect to', default=None)
- args = parser.parse_args()
-
- if args.socket != None:
- SOCKET_PATH = "@e_localstatedir@/" + args.socket[0]
- else:
- SOCKET_PATH = "@e_localstatedir@/suricata-command.socket"
-
- sc = SuricataSC(SOCKET_PATH, verbose=args.verbose)
- try:
- sc.connect()
- except SuricataNetException, err:
- print "Unable to connect to socket %s: %s" % (SOCKET_PATH, err)
- sys.exit(1)
- except SuricataReturnException, err:
- print "Unable to negotiate version with server: %s" % (err)
- sys.exit(1)
- try:
- sc.interactive()
- except SuricataNetException, err:
- print "Communication error: %s" % (err)
- sys.exit(1)
- except SuricataReturnException, err:
- print "Invalid return from server: %s" % (err)
- sys.exit(1)
-
- print "[+] Quit command client"
+sc = SuricataSC(SOCKET_PATH, verbose=args.verbose)
+try:
+ sc.connect()
+except SuricataNetException, err:
+ print "Unable to connect to socket %s: %s" % (SOCKET_PATH, err)
+ sys.exit(1)
+except SuricataReturnException, err:
+ print "Unable to negotiate version with server: %s" % (err)
+ sys.exit(1)
+try:
+ sc.interactive()
+except SuricataNetException, err:
+ print "Communication error: %s" % (err)
+ sys.exit(1)
+except SuricataReturnException, err:
+ print "Invalid return from server: %s" % (err)
+ sys.exit(1)
- sc.close()
+print "[+] Quit command client"
- sys.exit(1)
+sc.close()