aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjahoti <jahoti@tilde.team>2021-08-17 00:00:00 +0000
committerjahoti <jahoti@tilde.team>2021-08-17 00:00:00 +0000
commite9b7f4d7bf624ccb0ed503f20b85288a575d020d (patch)
tree0c7ce1539a7a62592dd8303b940bbe96ff8ac69c
parent5b7c9edbbb46074436b819435feb80ebbd9ab4ad (diff)
downloadbrowser-extension-e9b7f4d7bf624ccb0ed503f20b85288a575d020d.tar.gz
browser-extension-e9b7f4d7bf624ccb0ed503f20b85288a575d020d.zip
Enable the hijacking proxy in the test suite to serve responses
-rw-r--r--copyright4
-rw-r--r--test/proxy_core.py26
-rw-r--r--test/server.py106
3 files changed, 112 insertions, 24 deletions
diff --git a/copyright b/copyright
index 083c6a2..11a8e4f 100644
--- a/copyright
+++ b/copyright
@@ -85,6 +85,10 @@ License: BSD-3
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+Files: test/server.py
+Copyright: 2021 jahoti <jahoti@tilde.team>
+License: AGPL-3+
+
Files: licenses/*
Copyright: 2001, 2002, 2011-2013 Creative Commons
License: CC-BY-4.0
diff --git a/test/proxy_core.py b/test/proxy_core.py
index 6b214cf..5a23278 100644
--- a/test/proxy_core.py
+++ b/test/proxy_core.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python3
-#
# Copyright (c) 2015, inaz2
# Copyright (C) 2021 jahoti <jahoti@tilde.team>
# Licensing information is collated in the `copyright` file
@@ -38,7 +36,7 @@ class ProxyRequestHandler(BaseHTTPRequestHandler):
p1 = Popen((gen_cert_req % hostname).split(' '), stdout=PIPE).stdout
Popen((sign_cert_req % (time.time() * 1000, certpath)).split(' '), stdin=p1, stderr=PIPE).communicate()
- self.wfile.write('HTTP/1.1 200 Connection Established\r\n')
+ self.send_response(200)
self.end_headers()
self.connection = ssl.wrap_socket(self.connection, keyfile='cert.key', certfile=certpath, server_side=True)
@@ -48,18 +46,6 @@ class ProxyRequestHandler(BaseHTTPRequestHandler):
self.close_connection = int(self.headers.get('Proxy-Connection', '').lower() == 'close')
def proxy(self):
- if self.path == 'http://hachette.test/':
- with open('ca.crt', 'rb') as f:
- data = f.read()
-
- self.wfile.write('HTTP/1.1 200 OK\r\n')
- self.send_header('Content-Type', 'application/x-x509-ca-cert')
- self.send_header('Content-Length', len(data))
- self.send_header('Connection', 'close')
- self.end_headers()
- self.wfile.write(data)
- return
-
content_length = int(self.headers.get('Content-Length', 0))
req_body = self.rfile.read(content_length) if content_length else None
@@ -79,18 +65,10 @@ class ProxyRequestHandler(BaseHTTPRequestHandler):
class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
"""The actual proxy server"""
- address_family, daemon_threads, handler = socket.AF_INET6, True, ProxyRequestHandler
+ address_family, daemon_threads = socket.AF_INET6, True
def handle_error(self, request, client_address):
# suppress socket/ssl related errors
cls, e = sys.exc_info()[:2]
if not (cls is socket.error or cls is ssl.SSLError):
return HTTPServer.handle_error(self, request, client_address)
-
-
-def start(server_class, port=1337):
- """Start up the proxy/server"""
-
- print('Serving HTTP Proxy')
- httpd = server_class(('::1', port), ProxyRequestHandler)
- httpd.serve_forever()
diff --git a/test/server.py b/test/server.py
new file mode 100644
index 0000000..d396495
--- /dev/null
+++ b/test/server.py
@@ -0,0 +1,106 @@
+# Copyright (C) 2021 jahoti <jahoti@tilde.team>
+# Licensing information is collated in the `copyright` file
+
+"""
+A modular "virtual network" proxy,
+wrapping the classes in proxy_core.py
+"""
+
+from proxy_core import *
+from urllib.parse import parse_qs
+
+internet = {} # Add info here later
+mime_types = {
+ "7z": "application/x-7z-compressed", "oga": "audio/ogg",
+ "abw": "application/x-abiword", "ogv": "video/ogg",
+ "arc": "application/x-freearc", "ogx": "application/ogg",
+ "bin": "application/octet-stream", "opus": "audio/opus",
+ "bz": "application/x-bzip", "otf": "font/otf",
+ "bz2": "application/x-bzip2", "pdf": "application/pdf",
+ "css": "text/css", "png": "image/png",
+ "csv": "text/csv", "sh": "application/x-sh",
+ "gif": "image/gif", "svg": "image/svg+xml",
+ "gz": "application/gzip", "tar": "application/x-tar",
+ "htm": "text/html", "ts": "video/mp2t",
+ "html": "text/html", "ttf": "font/ttf",
+ "ico": "image/vnd.microsoft.icon", "txt": "text/plain",
+ "js": "text/javascript", "wav": "audio/wav",
+ "jpeg": "image/jpeg", "weba": "audio/webm",
+ "jpg": "image/jpeg", "webm": "video/webm",
+ "json": "application/json", "woff": "font/woff",
+ "mjs": "text/javascript", "woff2": "font/woff2",
+ "mp3": "audio/mpeg", "xhtml": "application/xhtml+xml",
+ "mp4": "video/mp4", "zip": "application/zip",
+ "mpeg": "video/mpeg",
+ "odp": "application/vnd.oasis.opendocument.presentation",
+ "ods": "application/vnd.oasis.opendocument.spreadsheet",
+ "odt": "application/vnd.oasis.opendocument.text",
+ "xml": "application/xml" # text/xml if readable from casual users
+}
+
+class RequestHijacker(ProxyRequestHandler):
+ def handle_request(self, req_body):
+ path_components = self.path.split('?', maxsplit=1)
+ path = path_components[0]
+ try:
+ # Response format: (status_code, headers (dict. of strings),
+ # body as bytes or filename containing body as string)
+ if path in internet:
+ info = internet[path]
+ if type(info) == tuple:
+ status_code, headers, body_file = info
+ if type(body_file) == str:
+ if 'Content-Type' not in headers and '.' in body_file:
+ ext = body_file.rsplit('.', maxsplit=1)[-1]
+ if ext in mime_types:
+ headers['Content-Type'] = mime_types[ext]
+
+ with open(body_file, mode='rb') as f:
+ body_file = f.read()
+
+ else:
+ # A function to evaluate to get the response
+ get_params, post_params = {}, {}
+ if len(path_components) == 2:
+ get_params = parse_qs(path_components[1])
+
+ # Parse POST parameters; currently only supports
+ # application/x-www-form-urlencoded
+ if req_body:
+ post_params = parse_qs(req_body.encode())
+
+ status_code, headers, body_file = info(self.command, get_params, post_params)
+ if type(body_file) == str:
+ body_file = body_file.encode()
+
+ if type(status_code) != int or status_code <= 0:
+ raise Exception('Invalid status code %r' % status_code)
+
+ for header, header_value in headers.items():
+ if type(header) != str:
+ raise Exception('Invalid header key %r' % header)
+
+ elif type(header_value) != str:
+ raise Exception('Invalid header value %r' % header_value)
+ else:
+ status_code, headers = 404, {'Content-Type': 'text/plain'}
+ body_file = b'Handler for this URL not found.'
+
+ except Exception as e:
+ status_code, headers, body_file = 500, {'Content-Type': 'text/plain'}, b'Internal Error:\n' + repr(e).encode()
+
+ headers['Content-Length'] = str(len(body_file))
+ self.send_response(status_code)
+ for header, header_value in headers.items():
+ self.send_header(header, header_value)
+
+ self.end_headers()
+ self.wfile.write(body_file)
+
+
+
+def do_an_internet(port=1337):
+ """Start up the proxy/server"""
+
+ httpd = ThreadingHTTPServer(('', port), RequestHijacker)
+ httpd.serve_forever()