From 90e2bbc8038b882de54c79be57705b9d18e6f07f Mon Sep 17 00:00:00 2001 From: zit-hb Date: Sat, 6 Feb 2021 11:55:46 +0000 Subject: [PATCH 1/4] Update to Python 3 --- setup.py | 4 ++-- shadowd/cgi_connector.py | 7 ++++--- shadowd/connector.py | 21 +++++++++++++-------- shadowd/django_connector.py | 3 ++- shadowd/flask_connector.py | 3 ++- shadowd/tests/__init__.py | 3 ++- shadowd/tests/test_cgi_connector.py | 3 ++- shadowd/tests/test_connector.py | 3 ++- shadowd/tests/test_django_connector.py | 3 ++- shadowd/tests/test_werkzeug_connector.py | 3 ++- shadowd/werkzeug_connector.py | 3 ++- 11 files changed, 35 insertions(+), 21 deletions(-) diff --git a/setup.py b/setup.py index 600dda5..9c68778 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ # # Shadow Daemon -- Web Application Firewall # -# Copyright (C) 2014-2016 Hendrik Buchwald +# Copyright (C) 2014-2021 Hendrik Buchwald # # This file is part of Shadow Daemon. Shadow Daemon is free software: you can # redistribute it and/or modify it under the terms of the GNU General Public @@ -24,7 +24,7 @@ setup( name='shadowd', - version='2.0.0', + version='3.0.0', description='Python connector for the Shadow Daemon web application firewall', long_description=long_description, url='http://github.com/zecure/shadowd_python', diff --git a/shadowd/cgi_connector.py b/shadowd/cgi_connector.py index 519f6cc..bef2b61 100644 --- a/shadowd/cgi_connector.py +++ b/shadowd/cgi_connector.py @@ -1,6 +1,6 @@ # Shadow Daemon -- Web Application Firewall # -# Copyright (C) 2014-2016 Hendrik Buchwald +# Copyright (C) 2014-2021 Hendrik Buchwald # # This file is part of Shadow Daemon. Shadow Daemon is free software: you can # redistribute it and/or modify it under the terms of the GNU General Public @@ -23,6 +23,7 @@ from .connector import Input, Output, Connector + class InputCGI(Input): def get_client_ip(self): return os.environ.get(self.config.get('client_ip', default='REMOTE_ADDR')) @@ -135,8 +136,8 @@ def gather_hashes(self): class OutputCGI(Output): def error(self): - print 'Status: 500 Internal Server Error\r\n\r\n' - print '

500 Internal Server Error

' + print('Status: 500 Internal Server Error\r\n\r\n') + print('

500 Internal Server Error

') return None diff --git a/shadowd/connector.py b/shadowd/connector.py index afb3c88..b330c5c 100644 --- a/shadowd/connector.py +++ b/shadowd/connector.py @@ -1,6 +1,6 @@ # Shadow Daemon -- Web Application Firewall # -# Copyright (C) 2014-2016 Hendrik Buchwald +# Copyright (C) 2014-2021 Hendrik Buchwald # # This file is part of Shadow Daemon. Shadow Daemon is free software: you can # redistribute it and/or modify it under the terms of the GNU General Public @@ -17,7 +17,7 @@ import os import time import traceback -import ConfigParser +import configparser import re import socket import ssl @@ -25,7 +25,8 @@ import hmac import hashlib -SHADOWD_CONNECTOR_VERSION = '2.0.0-python' + +SHADOWD_CONNECTOR_VERSION = '3.0.0-python' SHADOWD_CONNECTOR_CONFIG = '/etc/shadowd/connectors.ini' SHADOWD_CONNECTOR_CONFIG_SECTION = 'shadowd_python' STATUS_OK = 1 @@ -35,6 +36,7 @@ STATUS_ATTACK = 5 STATUS_CRITICAL_ATTACK = 6 + class Config: def __init__(self): if os.environ.get('SHADOWD_CONNECTOR_CONFIG'): @@ -42,7 +44,7 @@ def __init__(self): else: self.file = SHADOWD_CONNECTOR_CONFIG - self.config = ConfigParser.ConfigParser() + self.config = configparser.ConfigParser() self.config.read(self.file) if os.environ.get('SHADOWD_CONNECTOR_CONFIG_SECTION'): @@ -53,7 +55,7 @@ def __init__(self): def get(self, key, required = False, default = None): try: return self.config.get(self.section, key) - except ConfigParser.NoOptionError: + except configparser.NoOptionError: if required: raise Exception(key + ' in config missing') else: @@ -189,7 +191,8 @@ def send(self, input, host, port, profile, key, ssl_cert): json_data = json.dumps(input_data) json_hmac = self.sign(key, json_data) - connection.sendall(str(profile) + "\n" + json_hmac + "\n" + json_data + "\n") + data_bytes = bytes(str(profile) + "\n" + json_hmac + "\n" + json_data + "\n", 'utf-8') + connection.sendall(data_bytes) output = '' @@ -199,7 +202,7 @@ def send(self, input, host, port, profile, key, ssl_cert): if not new_output: break - output += new_output + output += new_output.decode("utf-8") connection.close() @@ -233,7 +236,9 @@ def parse_output(self, output): raise Exception('processing error') def sign(self, key, json): - return hmac.new(key, json, hashlib.sha256).hexdigest() + key_bytes = bytes(key , 'utf-8') + json_bytes = bytes(json, 'utf-8') + return hmac.new(key_bytes, json_bytes, hashlib.sha256).hexdigest() class Connector: def start(self, input, output): diff --git a/shadowd/django_connector.py b/shadowd/django_connector.py index 8fc8849..26f5677 100644 --- a/shadowd/django_connector.py +++ b/shadowd/django_connector.py @@ -1,6 +1,6 @@ # Shadow Daemon -- Web Application Firewall # -# Copyright (C) 2014-2016 Hendrik Buchwald +# Copyright (C) 2014-2021 Hendrik Buchwald # # This file is part of Shadow Daemon. Shadow Daemon is free software: you can # redistribute it and/or modify it under the terms of the GNU General Public @@ -17,6 +17,7 @@ from .connector import Input, Output, Connector from django.http import HttpResponseServerError + class InputDjango(Input): def __init__(self, request): self.request = request diff --git a/shadowd/flask_connector.py b/shadowd/flask_connector.py index ee304e6..0b2abb7 100644 --- a/shadowd/flask_connector.py +++ b/shadowd/flask_connector.py @@ -1,6 +1,6 @@ # Shadow Daemon -- Web Application Firewall # -# Copyright (C) 2014-2016 Hendrik Buchwald +# Copyright (C) 2014-2021 Hendrik Buchwald # # This file is part of Shadow Daemon. Shadow Daemon is free software: you can # redistribute it and/or modify it under the terms of the GNU General Public @@ -17,6 +17,7 @@ from .werkzeug_connector import InputWerkzeug, Output, Connector from flask import abort + class InputFlask(InputWerkzeug): pass diff --git a/shadowd/tests/__init__.py b/shadowd/tests/__init__.py index e433704..10304c2 100644 --- a/shadowd/tests/__init__.py +++ b/shadowd/tests/__init__.py @@ -1,6 +1,6 @@ # Shadow Daemon -- Web Application Firewall # -# Copyright (C) 2014-2016 Hendrik Buchwald +# Copyright (C) 2014-2021 Hendrik Buchwald # # This file is part of Shadow Daemon. Shadow Daemon is free software: you can # redistribute it and/or modify it under the terms of the GNU General Public @@ -16,6 +16,7 @@ import unittest + def test_all(): return unittest.TestLoader().loadTestsFromNames([ 'shadowd.tests.test_connector', diff --git a/shadowd/tests/test_cgi_connector.py b/shadowd/tests/test_cgi_connector.py index df02460..257fe24 100644 --- a/shadowd/tests/test_cgi_connector.py +++ b/shadowd/tests/test_cgi_connector.py @@ -1,6 +1,6 @@ # Shadow Daemon -- Web Application Firewall # -# Copyright (C) 2014-2016 Hendrik Buchwald +# Copyright (C) 2014-2021 Hendrik Buchwald # # This file is part of Shadow Daemon. Shadow Daemon is free software: you can # redistribute it and/or modify it under the terms of the GNU General Public @@ -20,6 +20,7 @@ os.environ['SHADOWD_NO_AUTOLOAD'] = '1' import shadowd.cgi_connector + class TestCgiConnector(unittest.TestCase): def test_get_input(self): os.environ['REQUEST_METHOD'] = 'GET' diff --git a/shadowd/tests/test_connector.py b/shadowd/tests/test_connector.py index 402e76c..a303672 100644 --- a/shadowd/tests/test_connector.py +++ b/shadowd/tests/test_connector.py @@ -1,6 +1,6 @@ # Shadow Daemon -- Web Application Firewall # -# Copyright (C) 2014-2016 Hendrik Buchwald +# Copyright (C) 2014-2021 Hendrik Buchwald # # This file is part of Shadow Daemon. Shadow Daemon is free software: you can # redistribute it and/or modify it under the terms of the GNU General Public @@ -17,6 +17,7 @@ import unittest import shadowd.connector + class TestConnector(unittest.TestCase): def test_escape_key(self): i = shadowd.connector.Input() diff --git a/shadowd/tests/test_django_connector.py b/shadowd/tests/test_django_connector.py index c7825ee..011547d 100644 --- a/shadowd/tests/test_django_connector.py +++ b/shadowd/tests/test_django_connector.py @@ -1,6 +1,6 @@ # Shadow Daemon -- Web Application Firewall # -# Copyright (C) 2014-2016 Hendrik Buchwald +# Copyright (C) 2014-2021 Hendrik Buchwald # # This file is part of Shadow Daemon. Shadow Daemon is free software: you can # redistribute it and/or modify it under the terms of the GNU General Public @@ -19,6 +19,7 @@ import django.http import django.conf + class TestDjangoConnector(unittest.TestCase): @classmethod def setUpClass(self): diff --git a/shadowd/tests/test_werkzeug_connector.py b/shadowd/tests/test_werkzeug_connector.py index 631463c..5d1f7a4 100644 --- a/shadowd/tests/test_werkzeug_connector.py +++ b/shadowd/tests/test_werkzeug_connector.py @@ -1,6 +1,6 @@ # Shadow Daemon -- Web Application Firewall # -# Copyright (C) 2014-2016 Hendrik Buchwald +# Copyright (C) 2014-2021 Hendrik Buchwald # # This file is part of Shadow Daemon. Shadow Daemon is free software: you can # redistribute it and/or modify it under the terms of the GNU General Public @@ -20,6 +20,7 @@ import werkzeug.wrappers import werkzeug.datastructures + class TestWerkzeugConnector(unittest.TestCase): def test_get_input(self): environ = { diff --git a/shadowd/werkzeug_connector.py b/shadowd/werkzeug_connector.py index f528923..a8c69c0 100644 --- a/shadowd/werkzeug_connector.py +++ b/shadowd/werkzeug_connector.py @@ -1,6 +1,6 @@ # Shadow Daemon -- Web Application Firewall # -# Copyright (C) 2014-2016 Hendrik Buchwald +# Copyright (C) 2014-2021 Hendrik Buchwald # # This file is part of Shadow Daemon. Shadow Daemon is free software: you can # redistribute it and/or modify it under the terms of the GNU General Public @@ -17,6 +17,7 @@ from .connector import Input, Output, Connector from werkzeug.datastructures import ImmutableMultiDict + class InputWerkzeug(Input): def __init__(self, request): self.request = request From 818b3fe2c1a4fc21150afb82128ab05b60fffca6 Mon Sep 17 00:00:00 2001 From: zit-hb Date: Sat, 6 Feb 2021 11:58:55 +0000 Subject: [PATCH 2/4] Use Python 3.6 for Travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 46c997c..0cf60f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: python python: - - "2.7" + - "3.6" script: - python setup.py test From c0f42f2f8cde8cb080d5d0db369a6933c77a042e Mon Sep 17 00:00:00 2001 From: zit-hb Date: Sat, 6 Feb 2021 12:06:42 +0000 Subject: [PATCH 3/4] Update CGI connector to Python 3 --- shadowd/cgi_connector.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shadowd/cgi_connector.py b/shadowd/cgi_connector.py index bef2b61..54d9cff 100644 --- a/shadowd/cgi_connector.py +++ b/shadowd/cgi_connector.py @@ -17,9 +17,9 @@ import os import sys import cgi -import Cookie import urllib import hashlib +import http from .connector import Input, Output, Connector @@ -56,7 +56,7 @@ def gather_input(self): # Save cookies in input. cookie_string = os.environ.get('HTTP_COOKIE') if cookie_string: - cookie = Cookie.SimpleCookie() + cookie = http.cookies.SimpleCookie() cookie.load(cookie_string) for key in cookie: @@ -80,7 +80,7 @@ def defuse_input(self, threats): cookie_string = os.environ.get('HTTP_COOKIE') if cookie_string: - cookie = Cookie.SimpleCookie() + cookie = http.cookies.SimpleCookie() cookie.load(cookie_string) for key in cookie: @@ -109,7 +109,7 @@ def defuse_input(self, threats): parameters[key][0] = '' # Generate new env from the dicts. - os.environ['QUERY_STRING'] = urllib.urlencode(parameters, True) + os.environ['QUERY_STRING'] = urllib.parse.urlencode(parameters, True) if cookie_string: new_cookie_string = '' From ac96d292d7264151897eac03a1ad77cbef93c581 Mon Sep 17 00:00:00 2001 From: zit-hb Date: Sat, 6 Feb 2021 12:11:03 +0000 Subject: [PATCH 4/4] Increment verison to 3.0.1 --- setup.py | 2 +- shadowd/connector.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 9c68778..e3bb65a 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ setup( name='shadowd', - version='3.0.0', + version='3.0.1', description='Python connector for the Shadow Daemon web application firewall', long_description=long_description, url='http://github.com/zecure/shadowd_python', diff --git a/shadowd/connector.py b/shadowd/connector.py index b330c5c..567a34b 100644 --- a/shadowd/connector.py +++ b/shadowd/connector.py @@ -26,7 +26,7 @@ import hashlib -SHADOWD_CONNECTOR_VERSION = '3.0.0-python' +SHADOWD_CONNECTOR_VERSION = '3.0.1-python' SHADOWD_CONNECTOR_CONFIG = '/etc/shadowd/connectors.ini' SHADOWD_CONNECTOR_CONFIG_SECTION = 'shadowd_python' STATUS_OK = 1