forked from OISF/suricata
-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
'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.
- Loading branch information
Showing
6 changed files
with
311 additions
and
230 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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', | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
|
||
from suricatasc import * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
#!/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" | ||
|
||
|
Oops, something went wrong.