Beispiel #1
0
    def do_contscan(self, directory_argument):
        directory = os.path.abspath(
            directory_argument) if directory_argument else ''
        if not directory or not os.path.exists(directory):
            logger.error(
                "Cannot handle CONTSCAN command with argument '%s' (path does not exist)",
                directory)
            self.send_response("ERROR: Wrong argument '%s'" % directory)
            return

        responses = ["AmavisVTd scan results:"]
        avt = AmavisVT(self.config)
        for resource, scan_result in avt.run(directory):
            if scan_result is None:
                responses.append("%s: Not scanned by virustotal" % resource)
            elif isinstance(scan_result, Exception):
                responses.append("%s: Error (%s)" % (resource, scan_result))
            else:
                if scan_result.infected:
                    matches = [
                        v['result'] for _, v in scan_result.scans.items()
                        if v['detected']
                    ][:3]
                    responses.append(
                        "%s: Detected as %s (%s of %s)" %
                        (resource, ', '.join(set(matches)),
                         scan_result.positives, scan_result.total))
                else:
                    responses.append("%s: Clean" % resource)
        payload = '\n'.join(responses)
        self.request.sendall(payload.encode('utf-8'))
Beispiel #2
0
    def test_is_included_by_extension(self):
        avt = AmavisVT(AmavisVTConfigurationParser())

        for ext in [
            ".exe",
            ".com",
            ".bat",
            ".cmd",
            ".tar.gz",
            ".zip",
            ".tar.bz2",
            ".tar.7z",
            ".doc",
            ".docx",
            ".docm",
            ".xls",
            ".xlsa",
            ".xlsx",
            ".xlsm",
            ".ppt",
            ".ppta",
            ".pptx",
            ".pptm",
            ".pdf",
            ".js",
            ".rtf",
            ".ttf",
            ".htm",
            ".html",
            ".vbs",
            ".wsf",
            "",
        ]:
            assert avt.is_included(DummyResource("/tmp/foo%s" % ext)), "Extension '%s' should be included" % ext
Beispiel #3
0
 def test_report_to_vt_pretend(self, requests_post):
     avt = AmavisVT(
         AmavisVTConfigurationParser(
             {"database-path": ":memory:", "api-key": "my-api-key", "pretend": "true"}, path="/dev/null"
         )
     )
     avt.report_to_vt(DummyResource("file1", "application/zip"))
     assert not requests_post.called
Beispiel #4
0
    def test_check_vt_pretend(self, requests_post):
        avt = AmavisVT(
            AmavisVTConfigurationParser(
                {"database-path": ":memory:", "api-key": "my-api-key", "pretend": "true"}, path="/dev/null"
            )
        )

        result = list(avt.check_vt(None))
        assert not requests_post.called
        assert not result
Beispiel #5
0
    def do_report(self, filename_argument):
        filename = os.path.abspath(filename_argument)
        if not (os.path.exists(filename) and os.path.isfile(filename) and os.access(filename, os.R_OK)):
            logger.error("File does not exist or is inaccessible: '%s'", filename)
            self.send_response("ERROR: File does not exist or is inaccessible: '%s'" % filename)
            return

        avt = AmavisVT(self.config)
        result = avt.report_to_vt(Resource(filename, cleanup=False, no_unpack=True))
        self.send_response(str(result) if result else "No response")
Beispiel #6
0
 def test_report_to_vt_pretend(self, requests_post):
     avt = AmavisVT(
         AmavisVTConfigurationParser(
             {
                 'database-path': ':memory:',
                 'api-key': 'my-api-key',
                 'pretend': 'true'
             },
             path='/dev/null'))
     avt.report_to_vt(DummyResource('file1', 'application/zip'))
     assert not requests_post.called
Beispiel #7
0
    def test_is_included_by_extension(self):
        avt = AmavisVT(AmavisVTConfigurationParser())

        for ext in [
                '.exe', '.com', '.bat', '.cmd', '.tar.gz', '.zip', '.tar.bz2',
                '.tar.7z', '.doc', '.docx', '.docm', '.xls', '.xlsa', '.xlsx',
                '.xlsm', '.ppt', '.ppta', '.pptx', '.pptm', '.pdf', '.js',
                '.rtf', '.ttf', '.htm', '.html', '.vbs', '.wsf', ''
        ]:
            assert avt.is_included(DummyResource(
                '/tmp/foo%s' % ext)), "Extension '%s' should be included" % ext
Beispiel #8
0
    def test_check_vt_pretend(self, requests_post):
        avt = AmavisVT(
            AmavisVTConfigurationParser(
                {
                    'database-path': ':memory:',
                    'api-key': 'my-api-key',
                    'pretend': 'true'
                },
                path='/dev/null'))

        result = list(avt.check_vt(None))
        assert not requests_post.called
        assert not result
Beispiel #9
0
    def do_report(self, filename_argument):
        filename = os.path.abspath(filename_argument)
        if not (os.path.exists(filename) and os.path.isfile(filename)
                and os.access(filename, os.R_OK)):
            logger.error("File does not exist or is inaccessible: '%s'",
                         filename)
            self.send_response(
                "ERROR: File does not exist or is inaccessible: '%s'" %
                filename)
            return

        avt = AmavisVT(self.config)
        result = avt.report_to_vt(
            Resource(filename, cleanup=False, no_unpack=True))
        self.send_response(str(result) if result else "No response")
Beispiel #10
0
    def test_run_with_filename_pattern_detection_match_with_autoreport(
        self, database_mock, memcached_get_mock, memcached_set_mock, requests_mock
    ):
        memcached_get_mock.return_value = None
        database_mock.filename_pattern_match = mock.MagicMock()
        database_mock.filename_pattern_match.return_value = True

        avt = AmavisVT(
            AmavisVTConfigurationParser(
                {
                    "database-path": ":memory:",
                    "api-key": "my-api-key",
                    "filename-pattern-detection": "true",
                    "auto-report": "true",
                },
                path="/dev/null",
            )
        )
        avt.database = database_mock

        mail = os.path.join(os.path.dirname(__file__), "samples/mail_with_attachment.eml")
        result = avt.run(mail)

        assert database_mock.filename_pattern_match.called
        call_result = database_mock.filename_pattern_match.call_args
        assert len(call_result) == 2  # resource and localpart
        call_args, call_kwargs = call_result

        # assert that one arg and one kwarg are passed
        assert len(call_args) == 1
        assert len(call_kwargs) == 1

        # the first arg must be our resource
        assert isinstance(call_args[0], Resource)
        assert call_args[0].filename == "textfile.zip"

        # the localpart kwarg should be 'alice'
        assert call_kwargs["localpart"] == "alice"

        assert requests_mock.called
        assert requests_mock.call_count == 2  # once for scan report and once for submitting

        assert len(result) == 1
        resource, response = result[0]
        assert resource.filename == "textfile.zip"
        assert response.infected

        assert not any([os.path.exists(p) for p in avt.clean_paths])
Beispiel #11
0
    def test_run_with_filename_pattern_detection_match_with_autoreport(
            self, database_mock, memcached_get_mock, memcached_set_mock,
            requests_mock):
        memcached_get_mock.return_value = None
        database_mock.filename_pattern_match = mock.MagicMock()
        database_mock.filename_pattern_match.return_value = True

        avt = AmavisVT(
            AmavisVTConfigurationParser(
                {
                    'database-path': ':memory:',
                    'api-key': 'my-api-key',
                    'filename-pattern-detection': 'true',
                    'auto-report': 'true'
                },
                path='/dev/null'))
        avt.database = database_mock

        mail = os.path.join(os.path.dirname(__file__),
                            'samples/mail_with_attachment.eml')
        result = avt.run(mail)

        assert database_mock.filename_pattern_match.called
        call_result = database_mock.filename_pattern_match.call_args
        assert len(call_result) == 2  # resource and localpart
        call_args, call_kwargs = call_result

        # assert that one arg and one kwarg are passed
        assert len(call_args) == 1
        assert len(call_kwargs) == 1

        # the first arg must be our resource
        assert isinstance(call_args[0], Resource)
        assert call_args[0].filename == 'textfile.zip'

        # the localpart kwarg should be 'alice'
        assert call_kwargs['localpart'] == 'alice'

        assert requests_mock.called
        assert requests_mock.call_count == 2  # once for scan report and once for submitting

        assert len(result) == 1
        resource, response = result[0]
        assert resource.filename == 'textfile.zip'
        assert response.infected

        assert not any([os.path.exists(p) for p in avt.clean_paths])
Beispiel #12
0
def avt():
    return AmavisVT(
        AmavisVTConfigurationParser(
            {
                'database-path': ':memory:',
                'api-key': 'my-api-key'
            },
            path='/dev/null'))
Beispiel #13
0
    def test_is_included_by_mime_type(self):
        avt = AmavisVT(AmavisVTConfigurationParser())

        assert avt.is_included(DummyResource(filename="foo.bar", mime_type="application/octet-stream"))
        assert avt.is_included(DummyResource(filename="foo.bar", mime_type="application/foobar"))
        assert avt.is_included(DummyResource(filename="foo.bar", mime_type="text/x-shellscript"))
        assert avt.is_included(DummyResource(filename="foo.bar", mime_type="text/x-perl"))
        assert avt.is_included(DummyResource(filename="foo.bar", mime_type="text/x-ruby"))
        assert avt.is_included(DummyResource(filename="foo.bar", mime_type="text/x-python"))

        assert not avt.is_included(DummyResource(filename="foo.bar", mime_type="text/plain"))
        assert not avt.is_included(DummyResource(filename="foo.bar", mime_type="message/rfc822"))
        assert not avt.is_included(DummyResource(filename="foo.bar", mime_type="image/png"))
Beispiel #14
0
    def do_contscan(self, directory_argument):
        directory = os.path.abspath(directory_argument) if directory_argument else ""
        if not directory or not os.path.exists(directory):
            logger.error("Cannot handle CONTSCAN command with argument '%s' (path does not exist)", directory)
            self.send_response("ERROR: Wrong argument '%s'" % directory)
            return

        responses = ["AmavisVTd scan results:"]
        avt = AmavisVT(self.config)
        for resource, scan_result in avt.run(directory):
            if scan_result is None:
                responses.append("%s: Not scanned by virustotal" % resource)
            elif isinstance(scan_result, Exception):
                responses.append("%s: Error (%s)" % (resource, scan_result))
            else:
                if scan_result.infected:
                    matches = [v["result"] for _, v in scan_result.scans.items() if v["detected"]][:3]
                    responses.append(
                        "%s: Detected as %s (%s of %s)"
                        % (resource, ", ".join(set(matches)), scan_result.positives, scan_result.total)
                    )
                else:
                    responses.append("%s: Clean" % resource)
        self.request.sendall("\n".join(responses))
Beispiel #15
0
    def test_is_included_by_mime_type(self):
        avt = AmavisVT(AmavisVTConfigurationParser())

        assert avt.is_included(
            DummyResource(filename='foo.bar',
                          mime_type='application/octet-stream'))
        assert avt.is_included(
            DummyResource(filename='foo.bar', mime_type='application/foobar'))
        assert avt.is_included(
            DummyResource(filename='foo.bar', mime_type='text/x-shellscript'))
        assert avt.is_included(
            DummyResource(filename='foo.bar', mime_type='text/x-perl'))
        assert avt.is_included(
            DummyResource(filename='foo.bar', mime_type='text/x-ruby'))
        assert avt.is_included(
            DummyResource(filename='foo.bar', mime_type='text/x-python'))

        assert not avt.is_included(
            DummyResource(filename='foo.bar', mime_type='text/plain'))
        assert not avt.is_included(
            DummyResource(filename='foo.bar', mime_type='message/rfc822'))
        assert not avt.is_included(
            DummyResource(filename='foo.bar', mime_type='image/png'))