Skip to content
This repository has been archived by the owner on Jul 23, 2023. It is now read-only.

Commit

Permalink
Merge pull request #10 from zecure/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
zit-hb committed Feb 6, 2021
2 parents c0c655d + ac96d29 commit e12fec2
Show file tree
Hide file tree
Showing 12 changed files with 40 additions and 26 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
@@ -1,5 +1,5 @@
language: python
python:
- "2.7"
- "3.6"
script:
- python setup.py test
4 changes: 2 additions & 2 deletions setup.py
Expand Up @@ -2,7 +2,7 @@
#
# Shadow Daemon -- Web Application Firewall
#
# Copyright (C) 2014-2016 Hendrik Buchwald <hb@zecure.org>
# Copyright (C) 2014-2021 Hendrik Buchwald <hb@zecure.org>
#
# 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
Expand All @@ -24,7 +24,7 @@

setup(
name='shadowd',
version='2.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',
Expand Down
15 changes: 8 additions & 7 deletions shadowd/cgi_connector.py
@@ -1,6 +1,6 @@
# Shadow Daemon -- Web Application Firewall
#
# Copyright (C) 2014-2016 Hendrik Buchwald <hb@zecure.org>
# Copyright (C) 2014-2021 Hendrik Buchwald <hb@zecure.org>
#
# 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
Expand All @@ -17,12 +17,13 @@
import os
import sys
import cgi
import Cookie
import urllib
import hashlib
import http

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'))
Expand Down Expand Up @@ -55,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:
Expand All @@ -79,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:
Expand Down Expand Up @@ -108,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 = ''
Expand All @@ -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 '<h1>500 Internal Server Error</h1>'
print('Status: 500 Internal Server Error\r\n\r\n')
print('<h1>500 Internal Server Error</h1>')

return None

Expand Down
21 changes: 13 additions & 8 deletions shadowd/connector.py
@@ -1,6 +1,6 @@
# Shadow Daemon -- Web Application Firewall
#
# Copyright (C) 2014-2016 Hendrik Buchwald <hb@zecure.org>
# Copyright (C) 2014-2021 Hendrik Buchwald <hb@zecure.org>
#
# 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
Expand All @@ -17,15 +17,16 @@
import os
import time
import traceback
import ConfigParser
import configparser
import re
import socket
import ssl
import json
import hmac
import hashlib

SHADOWD_CONNECTOR_VERSION = '2.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
Expand All @@ -35,14 +36,15 @@
STATUS_ATTACK = 5
STATUS_CRITICAL_ATTACK = 6


class Config:
def __init__(self):
if os.environ.get('SHADOWD_CONNECTOR_CONFIG'):
self.file = os.environ.get('SHADOWD_CONNECTOR_CONFIG')
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'):
Expand All @@ -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:
Expand Down Expand Up @@ -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 = ''

Expand All @@ -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()

Expand Down Expand Up @@ -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):
Expand Down
3 changes: 2 additions & 1 deletion shadowd/django_connector.py
@@ -1,6 +1,6 @@
# Shadow Daemon -- Web Application Firewall
#
# Copyright (C) 2014-2016 Hendrik Buchwald <hb@zecure.org>
# Copyright (C) 2014-2021 Hendrik Buchwald <hb@zecure.org>
#
# 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
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion shadowd/flask_connector.py
@@ -1,6 +1,6 @@
# Shadow Daemon -- Web Application Firewall
#
# Copyright (C) 2014-2016 Hendrik Buchwald <hb@zecure.org>
# Copyright (C) 2014-2021 Hendrik Buchwald <hb@zecure.org>
#
# 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
Expand All @@ -17,6 +17,7 @@
from .werkzeug_connector import InputWerkzeug, Output, Connector
from flask import abort


class InputFlask(InputWerkzeug):
pass

Expand Down
3 changes: 2 additions & 1 deletion shadowd/tests/__init__.py
@@ -1,6 +1,6 @@
# Shadow Daemon -- Web Application Firewall
#
# Copyright (C) 2014-2016 Hendrik Buchwald <hb@zecure.org>
# Copyright (C) 2014-2021 Hendrik Buchwald <hb@zecure.org>
#
# 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
Expand All @@ -16,6 +16,7 @@

import unittest


def test_all():
return unittest.TestLoader().loadTestsFromNames([
'shadowd.tests.test_connector',
Expand Down
3 changes: 2 additions & 1 deletion shadowd/tests/test_cgi_connector.py
@@ -1,6 +1,6 @@
# Shadow Daemon -- Web Application Firewall
#
# Copyright (C) 2014-2016 Hendrik Buchwald <hb@zecure.org>
# Copyright (C) 2014-2021 Hendrik Buchwald <hb@zecure.org>
#
# 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
Expand All @@ -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'
Expand Down
3 changes: 2 additions & 1 deletion shadowd/tests/test_connector.py
@@ -1,6 +1,6 @@
# Shadow Daemon -- Web Application Firewall
#
# Copyright (C) 2014-2016 Hendrik Buchwald <hb@zecure.org>
# Copyright (C) 2014-2021 Hendrik Buchwald <hb@zecure.org>
#
# 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
Expand All @@ -17,6 +17,7 @@
import unittest
import shadowd.connector


class TestConnector(unittest.TestCase):
def test_escape_key(self):
i = shadowd.connector.Input()
Expand Down
3 changes: 2 additions & 1 deletion shadowd/tests/test_django_connector.py
@@ -1,6 +1,6 @@
# Shadow Daemon -- Web Application Firewall
#
# Copyright (C) 2014-2016 Hendrik Buchwald <hb@zecure.org>
# Copyright (C) 2014-2021 Hendrik Buchwald <hb@zecure.org>
#
# 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
Expand All @@ -19,6 +19,7 @@
import django.http
import django.conf


class TestDjangoConnector(unittest.TestCase):
@classmethod
def setUpClass(self):
Expand Down
3 changes: 2 additions & 1 deletion shadowd/tests/test_werkzeug_connector.py
@@ -1,6 +1,6 @@
# Shadow Daemon -- Web Application Firewall
#
# Copyright (C) 2014-2016 Hendrik Buchwald <hb@zecure.org>
# Copyright (C) 2014-2021 Hendrik Buchwald <hb@zecure.org>
#
# 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
Expand All @@ -20,6 +20,7 @@
import werkzeug.wrappers
import werkzeug.datastructures


class TestWerkzeugConnector(unittest.TestCase):
def test_get_input(self):
environ = {
Expand Down
3 changes: 2 additions & 1 deletion shadowd/werkzeug_connector.py
@@ -1,6 +1,6 @@
# Shadow Daemon -- Web Application Firewall
#
# Copyright (C) 2014-2016 Hendrik Buchwald <hb@zecure.org>
# Copyright (C) 2014-2021 Hendrik Buchwald <hb@zecure.org>
#
# 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
Expand All @@ -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
Expand Down

0 comments on commit e12fec2

Please sign in to comment.