From 8c6742acb6fd31cf4016bbc7a86f8580253724f8 Mon Sep 17 00:00:00 2001
From: Wes Young <wes@barely3am.com>
Date: Sun, 13 Sep 2009 19:12:04 +0000
Subject: [PATCH] added spamhausdrop.py to plugins

---
 PreludeCorrelator/plugins/spamhausdrop.py    |  117 ++++++++++++++++++++++++++
 prelude_correlator.egg-info/SOURCES.txt      |    3 +-
 prelude_correlator.egg-info/entry_points.txt |    1 +
 setup.py                                     |   31 ++++---
 4 files changed, 138 insertions(+), 14 deletions(-)
 create mode 100644 PreludeCorrelator/plugins/spamhausdrop.py

diff --git a/PreludeCorrelator/plugins/spamhausdrop.py b/PreludeCorrelator/plugins/spamhausdrop.py
new file mode 100644
index 0000000..85f9bb5
--- /dev/null
+++ b/PreludeCorrelator/plugins/spamhausdrop.py
@@ -0,0 +1,117 @@
+# Copyright (C) 2009 PreludeIDS Technologies. All Rights Reserved.
+# Author: Yoann Vandoorselaere <yoann.v@prelude-ids.com>
+# Author: Wes Young <wes@barely3am.com>
+#
+# This file is part of the Prelude-Correlator program.
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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; see the file COPYING.  If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+import os, httplib, time
+from PreludeCorrelator import require
+from PreludeCorrelator.idmef import IDMEF
+from PreludeCorrelator.pluginmanager import Plugin
+from PreludeCorrelator.context import Context, Timer
+
+import netaddr
+
+if tuple(int(x) for x in netaddr.__version__.split(".")) >= (0, 7):
+    from netaddr import IPAddress, IPNetwork, IPSet
+else:
+    from netaddr import IP as IPAddress
+    from netaddr import CIDR as IPNetwork
+
+    class IPSet(list):
+        def __contains__(self, y):
+            for i in iter(self):
+                if y in i:
+                    return True
+
+            return False
+
+        def add(self, obj):
+            self.append(obj)
+
+
+class SpamhausDropPlugin(Plugin):
+    RELOAD = 7 * 24 * 60 * 60
+    SERVER = "www.spamhaus.org"
+    URI = "/drop/drop.lasso"
+    TIMEOUT = 10
+    FILENAME = require.get_data_filename(__name__, "spamhaus_drop.dat")
+
+    def __loadData(self, age=0):
+        for line in open(self.__filename, "r"):
+            if line[0] == ';':
+                continue
+
+            ip, sbl = line.split(';')
+            ip = IPNetwork(ip.strip())
+            self.__mynets.add(ip)
+
+        if self.__reload > 0:
+            Timer(self.__reload - age, self.__retrieveData).start()
+
+    def __downloadData(self):
+        self.info("Downloading host list, this might take some time...")
+
+        try:
+            con = httplib.HTTPConnection(self.__server, timeout=self.__timeout)
+        except TypeError:
+            con = httplib.HTTPConnection(self.__server)
+
+        con.request("GET", self.__uri)
+        r = con.getresponse()
+        if r.status != 200:
+            raise Exception, "Could not download spamhaus DROP list, error %d" % r.status
+
+        fd = open(self.__filename, "w")
+        fd.write(r.read())
+        fd.close()
+
+        self.info("Downloading done, processing data.")
+
+    def __retrieveData(self, timer=None):
+        try:
+            st = os.stat(self.__filename)
+            if self.__reload <= 0 or time.time() - st.st_mtime < self.__reload:
+                return self.__loadData(time.time() - st.st_mtime)
+        except OSError:
+            pass
+
+        self.__downloadData()
+        self.__loadData()
+
+
+    def __init__(self, env):
+        Plugin.__init__(self, env)
+
+        self.__mynets = IPSet()
+        self.__reload = self.getConfigValue("reload", self.RELOAD, type=int)
+        self.__filename = self.getConfigValue("filename", self.FILENAME)
+        self.__server = self.getConfigValue("server", self.SERVER)
+        self.__uri = self.getConfigValue("uri", self.URI)
+        self.__timeout = self.getConfigValue("timeout", self.TIMEOUT, type=float)
+        self.__retrieveData()
+
+    def run(self, idmef):
+        for source in idmef.Get("alert.source(*).node.address(*).address"):
+            if IPAddress(source) in self.__mynets:
+                ca = IDMEF()
+                ca.addAlertReference(idmef)
+                ca.Set("alert.classification.text", "IP source matching Spamhaus DROP dataset")
+                ca.Set("alert.correlation_alert.name", "IP source matching Spamhaus DROP dataset")
+                ca.Set("alert.assessment.impact.description", "Spamhaus gathered this IP address in their DROP list - %s" % (source))
+                ca.Set("alert.assessment.impact.severity", "medium")
+                ca.alert()
diff --git a/prelude_correlator.egg-info/SOURCES.txt b/prelude_correlator.egg-info/SOURCES.txt
index 026cbae..91cf472 100644
--- a/prelude_correlator.egg-info/SOURCES.txt
+++ b/prelude_correlator.egg-info/SOURCES.txt
@@ -24,10 +24,11 @@ PreludeCorrelator/plugins/dshield.py
 PreludeCorrelator/plugins/firewall.py
 PreludeCorrelator/plugins/opensshauth.py
 PreludeCorrelator/plugins/scan.py
+PreludeCorrelator/plugins/spamhausdrop.py
 PreludeCorrelator/plugins/worm.py
 prelude_correlator.egg-info/PKG-INFO
 prelude_correlator.egg-info/SOURCES.txt
 prelude_correlator.egg-info/dependency_links.txt
 prelude_correlator.egg-info/entry_points.txt
 prelude_correlator.egg-info/not-zip-safe
-prelude_correlator.egg-info/top_level.txt
\ No newline at end of file
+prelude_correlator.egg-info/top_level.txt
diff --git a/prelude_correlator.egg-info/entry_points.txt b/prelude_correlator.egg-info/entry_points.txt
index c1f83c7..c30c039 100644
--- a/prelude_correlator.egg-info/entry_points.txt
+++ b/prelude_correlator.egg-info/entry_points.txt
@@ -6,6 +6,7 @@ WormPlugin = PreludeCorrelator.plugins.worm:WormPlugin
 FirewallPlugin = PreludeCorrelator.plugins.firewall:FirewallPlugin
 BruteForcePlugin = PreludeCorrelator.plugins.bruteforce:BruteForcePlugin
 EventStormPlugin = PreludeCorrelator.plugins.scan:EventStormPlugin
+SpamhausDropPlugin = PreludeCorrelator.plugins.spamhausdrop:SpamhausDropPlugin
 DshieldPlugin = PreludeCorrelator.plugins.dshield:DshieldPlugin
 EventScanPlugin = PreludeCorrelator.plugins.scan:EventScanPlugin
 
diff --git a/setup.py b/setup.py
index 614e920..5c6e226 100644
--- a/setup.py
+++ b/setup.py
@@ -12,26 +12,30 @@ PRELUDE_CORRELATOR_VERSION = "0.9.0-beta6"
 
 
 class my_sdist(sdist):
-        def __init__(self, *args, **kwargs):
+        def _downloadDatabase(self, dname, server, url, filename):
                 import httplib
 
-                fin = os.popen('git log --summary --stat --no-merges --date=short', 'r')
-                fout = open('ChangeLog', 'w')
-                fout.write(fin.read())
-                fout.close()
-
-                print "Downloading DShield database, this might take a while..."
+                print "Downloading %s database, this might take a while..." % (dname)
 
-                con = httplib.HTTPConnection("www.dshield.org")
-                con.request("GET", "/ipsascii.html?limit=10000")
+                con = httplib.HTTPConnection(server)
+                con.request("GET", url)
                 r = con.getresponse()
                 if r.status != 200:
-                        raise Exception, "Could not download DShield host list, error %d" % r.status
+                        raise Exception, "Could not download %s host list, error %d" % (dname, r.status)
 
-                fd = open("PreludeCorrelator/plugins/dshield.dat", "w")
+                fd = open(filename, "w")
                 fd.write(r.read())
                 fd.close()
 
+        def __init__(self, *args, **kwargs):
+                fin = os.popen('git log --summary --stat --no-merges --date=short', 'r')
+                fout = open('ChangeLog', 'w')
+                fout.write(fin.read())
+                fout.close()
+
+                self._downloadDatabase("DShield", "www.dshield.org", "/ipsascii.html?limit=10000", "PreludeCorrelator/plugins/dshield.dat")
+                self._downloadDatabase("Spamhaus", "www.spamhaus.org", "/drop/drop.lasso", "PreludeCorrelator/plugins/spamhaus_drop.dat")
+
                 sdist.__init__(self, *args)
 
 
@@ -85,7 +89,7 @@ if is_egg:
 else:
         package_data = {}
         data_files = [ ("etc/prelude-correlator", ["prelude-correlator.conf"]),
-                       ("var/lib/prelude-correlator", ["PreludeCorrelator/plugins/dshield.dat"]) ]
+                       ("var/lib/prelude-correlator", ["PreludeCorrelator/plugins/dshield.dat", "PreludeCorrelator/plugins/spamhaus_drop.dat"]) ]
 
 setup(
         name="prelude-correlator",
@@ -137,7 +141,8 @@ suits your needs.
                         'EventScanPlugin = PreludeCorrelator.plugins.scan:EventScanPlugin',
                         'EventStormPlugin = PreludeCorrelator.plugins.scan:EventStormPlugin',
                         'EventSweepPlugin = PreludeCorrelator.plugins.scan:EventSweepPlugin',
-                        'WormPlugin = PreludeCorrelator.plugins.worm:WormPlugin'
+                        'WormPlugin = PreludeCorrelator.plugins.worm:WormPlugin',
+                        'SpamhausDropPlugin = PreludeCorrelator.plugins.spamhausdrop:SpamhausDropPlugin'
                 ]
         },
 
-- 
1.6.2.5

