]> git.ipfire.org Git - thirdparty/suricata.git/commitdiff
suricatasc: update python packaging
authorEric Leblond <eric@regit.org>
Tue, 22 Jan 2013 09:47:29 +0000 (10:47 +0100)
committerVictor Julien <victor@inliniac.net>
Tue, 26 Feb 2013 11:32:48 +0000 (12:32 +0100)
'make install' install now suricatasc script and Python module to
the system. The suricatasc client module can now be used in other
Python projects by using 'import suricatasc'.

A transformation was needed for distribution of a module and a script.
Module in src directory is now containing most of the code and the
script only handle argument parsing and the creation of a unix socket
client through 'suricatasc' module.

configure.ac
scripts/suricatasc/Makefile.am
scripts/suricatasc/setup.py [new file with mode: 0755]
scripts/suricatasc/src/__init__.py [new file with mode: 0644]
scripts/suricatasc/src/suricatasc.py [new file with mode: 0644]
scripts/suricatasc/suricatasc.in

index 4098172dbce4bdc98d0993345a13fc30f68e0c9a..b0893826403091b79a7eaba504d0bed7329dcd5d 100644 (file)
@@ -100,6 +100,19 @@ AC_INIT(configure.ac)
     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.
 
@@ -1521,6 +1534,8 @@ SURICATA_BUILD_CONF="Suricata Configuration:
   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}
index 9e93c4dc6687bf2d3879fc459afd471e0d34688a..b63a837b09da5c956c48ff46a554f9ea7e8e7100 100644 (file)
@@ -1 +1,18 @@
-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
diff --git a/scripts/suricatasc/setup.py b/scripts/suricatasc/setup.py
new file mode 100755 (executable)
index 0000000..2d37919
--- /dev/null
@@ -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/scripts/suricatasc/src/__init__.py b/scripts/suricatasc/src/__init__.py
new file mode 100644 (file)
index 0000000..1a61f42
--- /dev/null
@@ -0,0 +1,2 @@
+
+from suricatasc import *
diff --git a/scripts/suricatasc/src/suricatasc.py b/scripts/suricatasc/src/suricatasc.py
new file mode 100644 (file)
index 0000000..6f1d326
--- /dev/null
@@ -0,0 +1,218 @@
+#!/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"
index a153f2d77729e1c2ed77ea98bad6bd67d1475ae5..459e6fead18c1c262aaf9cb5024b9b8d4b23c286 100755 (executable)
@@ -1,5 +1,5 @@
 #!/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()