Example #1
0
    def test_dbrules(self):
        """Test if db rules correctly override defaults"""

        testdata = u"""
        INSERT INTO attachmentrules(scope,checktype,action,regex,description,prio) VALUES
        ('*****@*****.**','contenttype','allow','application/x-executable','this user likes exe',1)
        """
        self.session.execute(testdata)
        # copy file rules
        tmpfile = tempfile.NamedTemporaryFile(
            suffix='virus', prefix='fuglu-unittest', dir='/tmp')
        shutil.copy(TESTDATADIR + '/binaryattachment.eml', tmpfile.name)
        suspect = Suspect(
            '*****@*****.**', '*****@*****.**', tmpfile.name)

        result = self.candidate.examine(suspect)
        resstr = actioncode_to_string(result)
        self.assertEqual(resstr, "DUNNO")

        # another recipient should still get the block
        suspect = Suspect(
            '*****@*****.**', '*****@*****.**', tmpfile.name)

        result = self.candidate.examine(suspect)
        if type(result) is tuple:
            result, message = result
        resstr = actioncode_to_string(result)
        self.assertEqual(resstr, "DELETE")
        tmpfile.close()
    def test_dbrules(self):
        """Test if db rules correctly override defaults"""

        testdata = u"""
        INSERT INTO attachmentrules(scope,checktype,action,regex,description,prio) VALUES
        ('*****@*****.**','contenttype','allow','application/x-executable','this user likes exe',1)
        """
        self.session.execute(testdata)
        # copy file rules
        tempfilename = tempfile.mktemp(suffix='virus',
                                       prefix='fuglu-unittest',
                                       dir='/tmp')
        shutil.copy(TESTDATADIR + '/binaryattachment.eml', tempfilename)
        suspect = Suspect('*****@*****.**',
                          '*****@*****.**', tempfilename)

        result = self.candidate.examine(suspect)
        resstr = actioncode_to_string(result)
        self.assertEquals(resstr, "DUNNO")

        # another recipient should still get the block
        suspect = Suspect('*****@*****.**',
                          '*****@*****.**', tempfilename)

        result = self.candidate.examine(suspect)
        if type(result) is tuple:
            result, message = result
        resstr = actioncode_to_string(result)
        self.assertEquals(resstr, "DELETE")
        os.remove(tempfilename)
Example #3
0
    def test_result(self):
        """Test if EICAR virus is detected and message deleted"""

        suspect = Suspect('*****@*****.**',
                          '*****@*****.**', '/dev/null')
        stream = """Date: Mon, 08 Sep 2008 17:33:54 +0200
To: [email protected]
From: [email protected]
Subject: test eicar attachment
X-Mailer: swaks v20061116.0 jetmore.org/john/code/#swaks
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="----=_MIME_BOUNDARY_000_12140"

------=_MIME_BOUNDARY_000_12140
Content-Type: text/plain

Eicar test
------=_MIME_BOUNDARY_000_12140
Content-Type: application/octet-stream
Content-Transfer-Encoding: BASE64
Content-Disposition: attachment

UEsDBAoAAAAAAGQ7WyUjS4psRgAAAEYAAAAJAAAAZWljYXIuY29tWDVPIVAlQEFQWzRcUFpYNTQo
UF4pN0NDKTd9JEVJQ0FSLVNUQU5EQVJELUFOVElWSVJVUy1URVNULUZJTEUhJEgrSCoNClBLAQIU
AAoAAAAAAGQ7WyUjS4psRgAAAEYAAAAJAAAAAAAAAAEAIAD/gQAAAABlaWNhci5jb21QSwUGAAAA
AAEAAQA3AAAAbQAAAAAA

------=_MIME_BOUNDARY_000_12140--"""

        suspect.setMessageRep(email.message_from_string(stream))
        result = self.candidate.examine(suspect)
        if type(result) is tuple:
            result, message = result
        strresult = actioncode_to_string(result)
        self.assertEqual(strresult, "DELETE")
Example #4
0
    def test_result(self):
        """Test if EICAR virus is detected and message deleted"""

        suspect = Suspect(
            '*****@*****.**', '*****@*****.**', '/dev/null')
        stream = """Date: Mon, 08 Sep 2008 17:33:54 +0200
To: [email protected]
From: [email protected]
Subject: test eicar attachment
X-Mailer: swaks v20061116.0 jetmore.org/john/code/#swaks
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="----=_MIME_BOUNDARY_000_12140"

------=_MIME_BOUNDARY_000_12140
Content-Type: text/plain

Eicar test
------=_MIME_BOUNDARY_000_12140
Content-Type: application/octet-stream
Content-Transfer-Encoding: BASE64
Content-Disposition: attachment

UEsDBAoAAAAAAGQ7WyUjS4psRgAAAEYAAAAJAAAAZWljYXIuY29tWDVPIVAlQEFQWzRcUFpYNTQo
UF4pN0NDKTd9JEVJQ0FSLVNUQU5EQVJELUFOVElWSVJVUy1URVNULUZJTEUhJEgrSCoNClBLAQIU
AAoAAAAAAGQ7WyUjS4psRgAAAEYAAAAJAAAAAAAAAAEAIAD/gQAAAABlaWNhci5jb21QSwUGAAAA
AAEAAQA3AAAAbQAAAAAA

------=_MIME_BOUNDARY_000_12140--"""

        suspect.setMessageRep(email.message_from_string(stream))
        result = self.candidate.examine(suspect)
        if type(result) is tuple:
            result, message = result
        strresult = actioncode_to_string(result)
        self.assertEqual(strresult, "DELETE")
Example #5
0
 def test_defaultcodes(self):
     """test actioncode<->string conversion"""
     conf = ConfigParser()
     conf.add_section('spam')
     conf.add_section('virus')
     conf.set('spam', 'defaultlowspamaction', 'REJEcT')
     conf.set('spam', 'defaulthighspamaction', 'REjECT')
     conf.set('virus', 'defaultvirusaction', 'rejeCt')
     self.assertEqual(string_to_actioncode('defaultlowspamaction', conf),
                      REJECT)
     self.assertEqual(string_to_actioncode('defaulthighspamaction', conf),
                      REJECT)
     self.assertEqual(string_to_actioncode('defaultvirusaction', conf),
                      REJECT)
     self.assertEqual(string_to_actioncode('nonexistingstuff'), None)
     self.assertEqual(actioncode_to_string(REJECT), 'REJECT')
     self.assertEqual(actioncode_to_string(string_to_actioncode('discard')),
                      'DELETE')
Example #6
0
 def test_defaultcodes(self):
     """test actioncode<->string conversion"""
     conf = ConfigParser()
     conf.add_section('spam')
     conf.add_section('virus')
     conf.set('spam', 'defaultlowspamaction', 'REJEcT')
     conf.set('spam', 'defaulthighspamaction', 'REjECT')
     conf.set('virus', 'defaultvirusaction', 'rejeCt')
     self.assertEqual(
         string_to_actioncode('defaultlowspamaction', conf), REJECT)
     self.assertEqual(
         string_to_actioncode('defaulthighspamaction', conf), REJECT)
     self.assertEqual(
         string_to_actioncode('defaultvirusaction', conf), REJECT)
     self.assertEqual(string_to_actioncode('nonexistingstuff'), None)
     self.assertEqual(actioncode_to_string(REJECT), 'REJECT')
     self.assertEqual(
         actioncode_to_string(string_to_actioncode('discard')), 'DELETE')
Example #7
0
 def lint(self):
     viract = self.config.get(self.section, 'virusaction')
     print("Virusaction: %s" % actioncode_to_string(
         string_to_actioncode(viract, self.config)))
     allok = self.checkConfig() and self.lint_ping() and self.lint_eicar()
     
     if self.config.getboolean(self.section, 'clamscanfallback'):
         print('WARNING: Fallback to clamscan enabled')
         starttime = time.time()
         allok = self.lint_eicar('shell')
         if allok:
             runtime = time.time()-starttime
             print('clamscan scan time: %.2fs' % runtime)
     
     return allok
Example #8
0
    def lint(self):
        viract = self.config.get(self.section, 'virusaction')
        print("Virusaction: %s" %
              actioncode_to_string(string_to_actioncode(viract, self.config)))
        allok = self.checkConfig() and self.lint_ping() and self.lint_eicar()

        if self.config.getboolean(self.section, 'clamscanfallback'):
            print('WARNING: Fallback to clamscan enabled')
            starttime = time.time()
            allok = self.lint_eicar('shell')
            if allok:
                runtime = time.time() - starttime
                print('clamscan scan time: %.2fs' % runtime)

        return allok
Example #9
0
    def examine(self, suspect):
        scripts = self.get_scripts()
        retaction = DUNNO
        retmessage = ''
        for script in scripts:
            self.logger.debug("Executing script %s" % script)
            suspect.debug("Executing script %s" % script)
            sstart = time.time()
            action, message = self.exec_script(suspect, script)
            send = time.time()
            self.logger.debug("Script %s done in %.4fs result: %s %s" % (
                script, send - sstart, actioncode_to_string(action), message))
            if action != DUNNO:
                retaction = action
                retmessage = message
                break

        return retaction, retmessage
Example #10
0
    def process(self, suspect, decision):
        buffer = "%s.fuglu.decision.%s:1|c\n" % (
            self.nodename, actioncode_to_string(decision))
        if self.sock == None:
            self.sock = socket(AF_INET, SOCK_DGRAM)

        if suspect.is_virus():
            buffer = "%s%s.fuglu.message.virus:1|c\n" % (buffer, self.nodename)
        elif suspect.is_highspam():
            buffer = "%s%s.fuglu.message.highspam:1|c\n" % (buffer,
                                                            self.nodename)
        elif suspect.is_spam():
            buffer = "%s%s.fuglu.message.spam:1|c\n" % (buffer, self.nodename)
        else:
            buffer = "%s%s.fuglu.message.clean:1|c\n" % (buffer, self.nodename)

        addr = self.config.get(self.section, 'host'), self.config.getint(
            self.section, 'port')
        self.sock.sendto(buffer.encode('utf-8'), addr)
Example #11
0
    def examine(self, suspect):
        scripts = self.get_scripts()
        retaction = DUNNO
        retmessage = ''
        for script in scripts:
            self.logger.debug("Executing script %s" % script)
            suspect.debug("Executing script %s" % script)
            sstart = time.time()
            action, message = self.exec_script(suspect, script)
            send = time.time()
            self.logger.debug(
                "Script %s done in %.4fs result: %s %s" %
                (script, send - sstart, actioncode_to_string(action), message))
            if action != DUNNO:
                retaction = action
                retmessage = message
                break

        return retaction, retmessage
Example #12
0
    def process(self, suspect, decision):
        buffer = "%s.fuglu.decision.%s:1|c\n" % (
            self.nodename, actioncode_to_string(decision))
        if self.sock == None:
            self.sock = socket(AF_INET, SOCK_DGRAM)

        if suspect.is_virus():
            buffer = "%s%s.fuglu.message.virus:1|c\n" % (buffer, self.nodename)
        elif suspect.is_highspam():
            buffer = "%s%s.fuglu.message.highspam:1|c\n" % (
                buffer, self.nodename)
        elif suspect.is_spam():
            buffer = "%s%s.fuglu.message.spam:1|c\n" % (buffer, self.nodename)
        else:
            buffer = "%s%s.fuglu.message.clean:1|c\n" % (buffer, self.nodename)

        addr = self.config.get(self.section, 'host'), self.config.getint(
            self.section, 'port')
        self.sock.sendto(buffer.encode('utf-8'), addr)
Example #13
0
    def process(self, suspect, decision):
        if not SQL_EXTENSION_ENABLED:
            self.logger.error("Fuglu SQL Extensions not enabled")
            return

        connstring = self.config.get(self.section, 'dbconnectstring')
        session = get_session(connstring)
        if session is None:
            self.logger.error("Could not create database session")
            return

        try:
            conn = session.connection()
            conn.connect()
        except Exception as e:
            self.logger.error("Database Connection failed: %s" % e)
            return

        statementlist = self.get_statements()
        for statement in statementlist:
            self.logger.debug("Template: %s" % statement)
            addvalues = {
                'action': actioncode_to_string(decision),
            }
            from_header = suspect.get_message_rep()['from']
            try:
                addvalues['header_from'] = self.stripAddress(from_header)
            except Exception:
                #use full from header
                addvalues['header_from'] = from_header

            replaced = apply_template(statement,
                                      suspect,
                                      values=addvalues,
                                      valuesfunction=self.sqlfix)
            self.logger.debug("Statement: %s" % replaced)
            try:
                result = session.execute(replaced)
            except Exception as e:
                self.logger.error("Statement failed: statement=%s , error=%s" %
                                  (replaced, str(e)))
        session.remove()
Example #14
0
    def process(self, suspect, decision):
        buffer = "%s.fuglu.decision.%s:1|c\n" % (
            self.nodename, actioncode_to_string(decision))

        host = self.config.get(self.section, 'host')
        port = int(self.config.get(self.section, 'port'))

        if self.sock is None:
            addr_f = socket.getaddrinfo(host, 0)[0][0]
            self.sock = socket.socket(addr_f, socket.SOCK_DGRAM)

        if suspect.is_virus():
            buffer = "%s%s.fuglu.message.virus:1|c\n" % (buffer, self.nodename)
        elif suspect.is_highspam():
            buffer = "%s%s.fuglu.message.highspam:1|c\n" % (buffer,
                                                            self.nodename)
        elif suspect.is_spam():
            buffer = "%s%s.fuglu.message.spam:1|c\n" % (buffer, self.nodename)
        else:
            buffer = "%s%s.fuglu.message.clean:1|c\n" % (buffer, self.nodename)

        self.sock.sendto(force_bString(buffer), (host, port))
Example #15
0
 def lint(self):
     viract = self.config.get(self.section, 'virusaction')
     print("Virusaction: %s" % actioncode_to_string(string_to_actioncode(viract, self.config)))
     allok = (self.checkConfig() and self.lint_eicar())
     return allok
Example #16
0
class SQLRunner(AppenderPlugin):
    """Run SQL statements after message scan is complete"""
    def __init__(self, config, section):
        AppenderPlugin.__init__(self, config, section)
        self.logger = self._logger()

        self.requiredvars = {
            'dbconnectstring': {
                'default': 'mysql://root@localhost/test',
                'description': 'sqlalchemy connectstring',
            },
            'statementseparator': {
                'default': ';',
                'description':
                'Separator used to separate mutliple statements',
            },
            'statements': {
                'description':
                """SQL statements to run, can containt standard variables as described in http://gryphius.github.io/fuglu/plugins-index.html#template-variables
                \n ${action} contains the action as string, eg. DUNNO """,
                'default': "",
            },
        }

    def sqlfix(self, values):
        for k, v in values.copy().iteritems():
            if type(v) == str:
                values[k] = re.sub("""['";]""", "", v)
        return values

    def process(self, suspect, decision):
        if not fuglu.extensions.sql.ENABLED:
            self.logger.error("Fuglu SQL Extensions not enabled")
            return

        connstring = self.config.get(self.section, 'dbconnectstring')
        session = fuglu.extensions.sql.get_session(connstring)
        if session == None:
            self.logger.error("Could not create database session")
            return

        try:
            conn = session.connection()
            conn.connect()
        except Exception, e:
            self.logger.error("Database Connection failed: %s" % e)
            return

        statementlist = self.get_statements()
        for statement in statementlist:
            self.logger.debug("Template: %s" % statement)
            addvalues = {
                'action': actioncode_to_string(decision),
            }
            from_header = suspect.get_message_rep()['from']
            try:

                addvalues['header_from'] = self.stripAddress(from_header)
            except Exception, e:
                #use full from header
                addvalues['header_from'] = from_header

            replaced = apply_template(statement,
                                      suspect,
                                      values=addvalues,
                                      valuesfunction=self.sqlfix)
            self.logger.debug("Statement: %s" % replaced)
            try:
                result = session.execute(replaced)
            except Exception, e:
                self.logger.error("Statement failed: statement=%s , error=%s" %
                                  (replaced, str(e)))
Example #17
0
 def lint(self):
     viract = self.config.get(self.section, 'virusaction')
     print "Virusaction: %s" % actioncode_to_string(
         string_to_actioncode(viract, self.config))
     allok = (self.checkConfig() and self.lint_eicar())
     return allok
Example #18
0
            scannerlist = resultset
            logging.info("Scanner plugin list is now: %s" % scannerlist)

    for pluginstance in scannerlist:
        logging.info("*** Running plugin: %s ***" % pluginstance)
        ans = pluginstance.examine(suspect)
        message = ""
        if type(ans) is tuple:
            result, message = ans
        else:
            result = ans

        if result == None:
            result = DUNNO

        logging.info("Result: %s %s", actioncode_to_string(result), message)
        suspect.tags['decisions'].append((pluginstance.section, result))
        logging.info(suspect)

    for pluginstance in mc.appenders:
        logging.info("*** Running appender: %s ***" % pluginstance)
        pluginstance.process(suspect, DUNNO)
        message = ""
        logging.info(suspect)

    if suspect.is_modified():
        outfilename = '/tmp/fuglu_dummy_message_out.eml'
        out = open(outfilename, 'wb')
        out.write(suspect.get_source())
        out.close()
        logging.info(
Example #19
0
            scannerlist = resultset
            logging.info("Scanner plugin list is now: %s" % scannerlist)

    for pluginstance in scannerlist:
        logging.info("*** Running plugin: %s ***" % pluginstance)
        ans = pluginstance.examine(suspect)
        message = ""
        if type(ans) is tuple:
            result, message = ans
        else:
            result = ans

        if result == None:
            result = DUNNO

        logging.info("Result: %s %s", actioncode_to_string(result), message)
        suspect.tags['decisions'].append((pluginstance.section, result))
        logging.info(suspect)

    for pluginstance in mc.appenders:
        logging.info("*** Running appender: %s ***" % pluginstance)
        pluginstance.process(suspect, DUNNO)
        message = ""
        logging.info(suspect)

    if suspect.is_modified():
        outfilename = '/tmp/fuglu_dummy_message_out.eml'
        out = open(outfilename, 'wb')
        out.write(suspect.get_source())
        out.close()
        logging.info(