more tests

This commit is contained in:
Tim Blume 2021-04-28 19:20:07 +02:00
parent c20ec945a1
commit 34f7d960c2
2 changed files with 450 additions and 199 deletions

View file

@ -71,11 +71,13 @@ class bRequest:
self.timestamp_end = flow["request"]["timestamp_end"]
self.headers = []
for k, v in flow["request"]["headers"]:
for k, v in flow["request"].get("headers", {}):
self.headers.append(bHeader(str(k), str(v)))
def json(self) -> dict:
return {}
state = vars(self).copy()
state["headers"] = {h.key: h.value for h in self.headers}
return state
@dataclass
@ -99,11 +101,13 @@ class bResponse:
self.timestamp_end = flow["response"]["timestamp_end"]
self.headers = []
for k, v in flow["response"]["headers"]:
for k, v in flow["response"].get("headers", {}):
self.headers.append(bHeader(k, v))
def json(self) -> dict:
return {}
state = vars(self).copy()
state["headers"] = [{h.key: h.value} for h in self.headers]
return state
@dataclass
@ -133,18 +137,13 @@ class bPacket:
flowid: str
data: str
def __init__(self, json: Dict):
self.ptype = json["type"]
self.flowid = str(json["id"])
self.data = json["data"]
@dataclass
class FlowItem:
state: bFlowState
flow: Flow
time: float = 0
retries_left: int = 5
retries: int = 5
"""
@ -187,7 +186,7 @@ class NetworkThread(threading.Thread):
# get new self.flows that may occured
i, flowitem = self.q.get(block=False)
if self.flows.get(i, None):
print(f"flow {i} doubled? ignoring...")
raise ValueError(f"flow {i} doubled? ignoring...")
continue
else:
self.flows[i] = flowitem
@ -199,40 +198,63 @@ class NetworkThread(threading.Thread):
msg = {"type": pkg.ptype, "id": pkg.flowid, "data": pkg.data}
self.send(msg)
def send_http_request(self, id: int, request: bRequest):
pkg = bPacket(bPacketType.HTTP_REQUEST, request.json())
self.send_packet(pkg)
self.flows[id].state = bFlowState.SENT_HTTP_REQUEST
self.flows[id].time = time.monotonic()
def send_http_response(self, id: int, response: bResponse):
pkg = bPacket(bPacketType.HTTP_RESPONSE, response.json())
self.send_packet(pkg)
self.flows[id].state = bFlowState.SENT_HTTP_RESPONSE
self.flows[id].time = time.monotonic()
# update all current self.flows
# handles the state machine for each flow
def update_flows(self):
for id, flow in self.flows.items():
# force copy of item list, so we can remove dict items in the loop
for id, flow in list(self.flows.items()):
if self.flows[id].retries <= 0:
self.flows[id].flow.kill()
if self.flows[id].flow:
self.flows[id].flow.kill()
print(f"http flow {id} timed out! flow killed.")
del self.flows[id]
delta = time.monotonic() - self.flows[id].time
if flow.state == bFlowState.UNSENT_HTTP_REQUEST or \
flow.state == bFlowState.SENT_HTTP_REQUEST and delta > 5:
self.send_http_request(id, bRequest(flow.flow))
pkg = bPacket(bPacketType.HTTP_REQUEST, id, bRequest(flow.flow.get_state()).json())
self.send_packet(pkg)
self.flows[id].time = time.monotonic()
self.flows[id].state = bFlowState.SENT_HTTP_REQUEST
self.flows[id].retries -= 1
if flow.state == bFlowState.UNSENT_HTTP_RESPONSE or \
elif flow.state == bFlowState.UNSENT_HTTP_RESPONSE or \
flow.state == bFlowState.SENT_HTTP_RESPONSE and delta > 5:
self.send_http_response(id, bResponse(flow.flow))
pkg = bPacket(bPacketType.HTTP_RESPONSE, id, bResponse(flow.flow.get_state()).json())
self.send_packet(pkg)
self.flows[id].time = time.monotonic()
self.flows[id].state = bFlowState.SENT_HTTP_RESPONSE
self.flows[id].retries -= 1
elif flow.state == bFlowState.ERROR:
if flow.state == bFlowState.ERROR:
print(f"error in flow {id}!")
del self.flows[id]
def handle_packet(self, pkg):
flow = self.flows.get(pkg.flowid, None)
# flow ACKed
if pkg.ptype == bPacketType.ACK:
if flow and flow.flow:
flow.flow.resume()
else:
raise ValueError("unknown flow")
# flow killed
elif pkg.ptype == bPacketType.KILL:
if flow and flow.flow:
flow.flow.kill()
else:
raise ValueError("unknown flow")
if flow:
del self.flows[pkg.flowid]
else:
print(f"got unexpected message {pkg.ptype}")
# handle incoming packets / update the statemachine
def handle_packets(self):
@ -242,14 +264,7 @@ class NetworkThread(threading.Thread):
if msg:
result = json.loads(str(msg))
pkg = bPacket(json=result)
# flow ACKed
if pkg.ptype == bPacketType.ACK:
continue
# flow killed
elif pkg.ptype == bPacketType.KILL:
continue
else:
print(f"got unexpected message {pkg.ptype}")
self.handle_packet(pkg)
except json.JSONDecodeError:
print(f"malformed message received {msg}")

View file

@ -2,8 +2,10 @@
import pdb
import queue
import uuid
import pytest
from mitmproxy.http import HTTPFlow, HTTPRequest, HTTPResponse
from mitmproxy.connections import ClientConnection, ServerConnection
from networkthread import bPacket, bRequest, bResponse, bHeader, NetworkThread, FlowItem, bFlowState
import os
import tempfile
@ -13,22 +15,64 @@ import zmq
from deepdiff import DeepDiff
@pytest.fixture
def flowstate_clientconn():
return dict(
id=str(uuid.uuid4()),
address=("address", 22),
source_address=("address", 22),
ip_address=("192.168.0.1", 22),
timestamp_start=946681202,
timestamp_tcp_setup=946681203,
timestamp_tls_setup=946681204,
timestamp_end=946681205,
tls_established=True,
sni="address",
alpn=None,
tls_version="TLSv1.2",
via=None,
state=0,
error=None,
tls=False,
certificate_list=[],
alpn_offers=[],
cipher_name=None,
cipher_list=[],
via2=None,
)
@pytest.fixture
def flowstate_serverconn():
return dict(
id=str(uuid.uuid4()),
address=("address", 22),
source_address=("address", 22),
ip_address=("192.168.0.1", 22),
timestamp_start=946681202,
timestamp_tcp_setup=946681203,
timestamp_tls_setup=946681204,
timestamp_end=946681205,
tls_established=True,
sni="address",
alpn=None,
tls_version="TLSv1.2",
via=None,
state=0,
error=None,
tls=False,
certificate_list=[],
alpn_offers=[],
cipher_name=None,
cipher_list=[],
via2=None,
)
# usual flow state of the request with some big parts removed
@pytest.fixture
def flowstate_request():
return {'client_conn': {'address': ('::ffff:127.0.0.1', 60630, 0, 0),
'alpn_proto_negotiated': b'http/1.1',
'cipher_name': 'TLS_AES_256_GCM_SHA384',
'clientcert': None,
'id': '5dde7ef8-9b1a-4b60-9d15-d308442a27ea',
'mitmcert': '',
'sni': 'yolo.jetzt',
'timestamp_end': None,
'timestamp_start': 1619390481.8003347,
'timestamp_tls_setup': 1619390482.6879823,
'tls_established': True,
'tls_extensions': [],
'tls_version': 'TLSv1.3'},
def flowstate_request(flowstate_clientconn, flowstate_serverconn):
return {'client_conn': flowstate_clientconn,
'error': None,
'id': '51215b69-c76f-4ac2-afcb-da3b823d9f88',
'intercepted': False,
@ -36,8 +80,7 @@ def flowstate_request():
'marked': False,
'metadata': {},
'mode': 'transparent',
'request': {'authority': b'',
'content': b'',
'request': {'content': b'',
'headers': ((b'Host', b'yolo.jetzt'),
(b'User-Agent', b'curl/7.75.0'),
(b'Accept', b'*/*')),
@ -49,156 +92,138 @@ def flowstate_request():
'scheme': b'https',
'timestamp_end': 1619390482.69,
'timestamp_start': 1619390482.6886377,
'trailers': None},
'authority': '',
'trailers': '',
},
'response': None,
'server_conn': {'address': ('yolo.jetzt', 443),
'alpn_proto_negotiated': b'http/1.1',
'cert': '',
'id': 'ecc4cd3b-7e35-4815-b618-5931fe64729b',
'ip_address': ('95.156.226.69', 443),
'sni': 'yolo.jetzt',
'source_address': ('192.168.42.182', 51514),
'timestamp_end': None,
'timestamp_start': 1619390481.8154442,
'timestamp_tcp_setup': 1619390481.994565,
'timestamp_tls_setup': 1619390482.6819758,
'tls_established': True,
'tls_version': 'TLSv1.2',
'via': None},
"server_conn": flowstate_serverconn,
'type': 'http',
'version': 9}
@pytest.fixture
def flow_request(flowstate_request):
c = ClientConnection.make_dummy("192.168.0.2")
s = ServerConnection.make_dummy("192.168.0.1")
flow = HTTPFlow(c, s)
flow.request = HTTPRequest.from_state(flowstate_request["request"])
return flow
@pytest.fixture()
def flowstate_response():
return {'client_conn': {'address': ('::ffff:127.0.0.1', 30190, 0, 0),
'alpn_proto_negotiated': b'http/1.1',
'cipher_name': 'TLS_AES_256_GCM_SHA384',
'clientcert': None,
'id': '2507e6ce-3132-4394-9432-f55fb5f55b05',
'mitmcert': '',
'sni': 'yolo.jetzt',
'timestamp_end': None,
'timestamp_start': 1619461916.6160116,
'timestamp_tls_setup': 1619461916.7581937,
'tls_established': True,
'tls_extensions': [],
'tls_version': 'TLSv1.3'},
'error': None,
'id': '449d1a87-744f-4a18-9a5d-f085f99a5c62',
'intercepted': True,
'is_replay': None,
'marked': False,
'metadata': {},
'mode': 'transparent',
'request': {'authority': b'',
'content': b'',
'headers': ((b'Host', b'yolo.jetzt'),
(b'User-Agent', b'curl/7.75.0'),
(b'Accept', b'*/*')),
'host': 'yolo.jetzt',
'http_version': b'HTTP/1.1',
'method': b'GET',
'path': b'/',
'port': 443,
'scheme': b'https',
'timestamp_end': 1619461916.7603076,
'timestamp_start': 1619461916.7588415,
'trailers': None},
'response': {'content': b'<!DOCTYPE html">\n<html>\n<head> \n<meta http-equi'
b'v="content-type" content="text/html;charset=ISO-8859'
b'-1">\n<title>todays yolo - 3026</title> \n<style '
b'type="text/css" media="screen">\n<!--\nbody \n{\ncol'
b'or: white;\nbackground-color: #003;\nmargin: 0px\n}'
b'\n\n.yolo\n{\nfont-family: Verdana, Geneva, Arial, s'
b'ans-serif;\nfont-weight: bold;\nfont-size: 3em;\n}\n'
b'\na:visited {\n\tcolor: blue\n}\n\n#content '
b' \n{\nfont-family: Verdana, Geneva, Arial, sans-se'
b'rif;\ncolor: white;\nbackground-color: transparent'
b';\ntext-align: center;\nfont-size: 2em;\nposition: '
b'absolute;\ntop: 50%;\nleft: 50%;\n-webkit-transform'
b': translateX(-50%) translateY(-50%);\n-moz-transf'
b'orm: translateX(-50%) translateY(-50%);\n-ms-tran'
b'sform: translateX(-50%) translateY(-50%);\ntransf'
b'orm: translateX(-50%) translateY(-50%);\noverflow'
b': visible;\nvisibility: visible;\ndisplay: block\n}'
b'\n\n#sponsors \n{\nfont-family: Verdana, Gene'
b'va, Arial, sans-serif;\ncolor: white;\nbackground-'
b'color: transparent;\ntext-align: center;\nfont-siz'
b'e: 1em;\nposition: absolute;\ntop: 90%;\nleft: 50%;'
b'\n-webkit-transform: translateX(-50%) translateY('
b'-50%);\n-moz-transform: translateX(-50%) translat'
b'eY(-50%);\n-ms-transform: translateX(-50%) transl'
b'ateY(-50%);\ntransform: translateX(-50%) translat'
b'eY(-50%);\noverflow: visible;\nvisibility: visible'
b';\ndisplay: block\n}\n\n#progress\n{\n\tbackground-'
b'color: #f08;\n\tposition: absolute;\n\tleft: 0px'
b';\n\ttop: 0px;\n\theight: 10px;\n}\n\n-->\n</sty'
b'le>\n</head>\n<body>\n<div id="progress" class="pro'
b'gressBarDiv"></div>\n<div id="content">\nthe yolo '
b'for today is<br>\n<span class="yolo" id="yoloValu'
b'e" title="YOLOVALUE">3026</span><br>\n<br>\n</div>'
b'\n<div id="sponsors">\n\t<a href="https://cat.yolo.'
b'jetzt">Cat</a>\n\t<br>\n\tRegulation (EU) 2016/679 c'
b'ompliant\n</div>\n<script type="text/javascript">\n'
b'var currentYoloTS = 1619388000000; //Multiply by 100'
b'0 the YOLO way\nvar tDiff = Date.now() - currentY'
b'oloTS;\n\nvar dayMS = 24 * 60 * 60 * 1000;\n\nconsol'
b'e.debug(currentYoloTS);\nconsole.debug(Date.now()'
b' - currentYoloTS);\nfunction checkTimestamps()\n{\n'
b'\ttDiff = Date.now() - currentYoloTS;\n\tupdateUi()'
b';\n\tif(tDiff > dayMS)\n\t{\n\t\tclearInterval(upda'
b'teInterval);\n\t\tlocation.reload();\t\n\t}\n}\n'
b'\nfunction updateUi()\n{\n\tvalPercent = tDiff / day'
b'MS * 100;\n\tif(valPercent > 100) valPercent = 100'
b';\n\tdocument.getElementById("progress").style = "'
b'width: " + valPercent + "%;";\n\tif(tDiff > dayMS)'
b'\n\t{\n\t\tdocument.getElementById("yoloValue").i'
b'nnerHTML = "&#xfffd;";\n\t}\n}\n\nupdateUi();\nvar'
b' updateInterval = setInterval(checkTimestamps, 5000)'
b';\n\n//YOLODATE\n</script>\n</body>\n</html>\n',
'headers': ((b'Server', b'nginx'),
(b'Date', b'Mon, 26 Apr 2021 18:31:56 GMT'),
(b'Content-Type', b'text/html'),
(b'Content-Length', b'2460'),
(b'Last-Modified', b'Sun, 25 Apr 2021 22:00:00 GMT'),
(b'Connection', b'keep-alive'),
(b'ETag', b'"6085e660-99c"'),
(b'Strict-Transport-Security',
b'max-age=31536000; includeSubDomains; preload'),
(b'X-Xss-Protection', b'1; mode=block'),
(b'X-Content-Type-Options', b'nosniff'),
(b'Content-Security-Policy',
b"default-src 'self'; script-src 'self' 'unsafe-in"
b"line'; connect-src 'self'; img-src 'self'; style"
b"-src 'self' 'unsafe-inline';"),
(b'X-Frame-Options', b'SAMEORIGIN'),
(b'Referrer-Policy', b'no-referrer'),
(b'Accept-Ranges', b'bytes')),
'http_version': b'HTTP/1.1',
'reason': b'OK',
'status_code': 200,
'timestamp_end': 1619461916.7979567,
'timestamp_start': 1619461916.7935555,
'trailers': None},
'server_conn': {'address': ('yolo.jetzt', 443),
'alpn_proto_negotiated': b'http/1.1',
'cert': '',
'id': '64c838e2-ab74-49c4-9ebe-70e8d17e9081',
'ip_address': ('95.156.226.69', 443),
'sni': 'yolo.jetzt',
'source_address': ('10.23.42.102', 43399),
'timestamp_end': None,
'timestamp_start': 1619461916.63117,
'timestamp_tcp_setup': 1619461916.6659565,
'timestamp_tls_setup': 1619461916.7522914,
'tls_established': True,
'tls_version': 'TLSv1.2',
'via': None},
'type': 'http',
'version': 9}
def flowstate_response(flowstate_clientconn, flowstate_serverconn):
return {
"client_conn": flowstate_clientconn,
'error': None,
'id': '449d1a87-744f-4a18-9a5d-f085f99a5c62',
'intercepted': True,
'is_replay': None,
'marked': False,
'metadata': {},
'mode': 'transparent',
'request': {'authority': b'',
'content': b'',
'headers': ((b'Host', b'yolo.jetzt'),
(b'User-Agent', b'curl/7.75.0'),
(b'Accept', b'*/*')),
'host': 'yolo.jetzt',
'http_version': b'HTTP/1.1',
'method': b'GET',
'path': b'/',
'port': 443,
'scheme': b'https',
'timestamp_end': 1619461916.7603076,
'timestamp_start': 1619461916.7588415,
'trailers': None},
'response': {'content': b'<!DOCTYPE html">\n<html>\n<head> \n<meta http-equi'
b'v="content-type" content="text/html;charset=ISO-8859'
b'-1">\n<title>todays yolo - 3026</title> \n<style '
b'type="text/css" media="screen">\n<!--\nbody \n{\ncol'
b'or: white;\nbackground-color: #003;\nmargin: 0px\n}'
b'\n\n.yolo\n{\nfont-family: Verdana, Geneva, Arial, s'
b'ans-serif;\nfont-weight: bold;\nfont-size: 3em;\n}\n'
b'\na:visited {\n\tcolor: blue\n}\n\n#content '
b' \n{\nfont-family: Verdana, Geneva, Arial, sans-se'
b'rif;\ncolor: white;\nbackground-color: transparent'
b';\ntext-align: center;\nfont-size: 2em;\nposition: '
b'absolute;\ntop: 50%;\nleft: 50%;\n-webkit-transform'
b': translateX(-50%) translateY(-50%);\n-moz-transf'
b'orm: translateX(-50%) translateY(-50%);\n-ms-tran'
b'sform: translateX(-50%) translateY(-50%);\ntransf'
b'orm: translateX(-50%) translateY(-50%);\noverflow'
b': visible;\nvisibility: visible;\ndisplay: block\n}'
b'\n\n#sponsors \n{\nfont-family: Verdana, Gene'
b'va, Arial, sans-serif;\ncolor: white;\nbackground-'
b'color: transparent;\ntext-align: center;\nfont-siz'
b'e: 1em;\nposition: absolute;\ntop: 90%;\nleft: 50%;'
b'\n-webkit-transform: translateX(-50%) translateY('
b'-50%);\n-moz-transform: translateX(-50%) translat'
b'eY(-50%);\n-ms-transform: translateX(-50%) transl'
b'ateY(-50%);\ntransform: translateX(-50%) translat'
b'eY(-50%);\noverflow: visible;\nvisibility: visible'
b';\ndisplay: block\n}\n\n#progress\n{\n\tbackground-'
b'color: #f08;\n\tposition: absolute;\n\tleft: 0px'
b';\n\ttop: 0px;\n\theight: 10px;\n}\n\n-->\n</sty'
b'le>\n</head>\n<body>\n<div id="progress" class="pro'
b'gressBarDiv"></div>\n<div id="content">\nthe yolo '
b'for today is<br>\n<span class="yolo" id="yoloValu'
b'e" title="YOLOVALUE">3026</span><br>\n<br>\n</div>'
b'\n<div id="sponsors">\n\t<a href="https://cat.yolo.'
b'jetzt">Cat</a>\n\t<br>\n\tRegulation (EU) 2016/679 c'
b'ompliant\n</div>\n<script type="text/javascript">\n'
b'var currentYoloTS = 1619388000000; //Multiply by 100'
b'0 the YOLO way\nvar tDiff = Date.now() - currentY'
b'oloTS;\n\nvar dayMS = 24 * 60 * 60 * 1000;\n\nconsol'
b'e.debug(currentYoloTS);\nconsole.debug(Date.now()'
b' - currentYoloTS);\nfunction checkTimestamps()\n{\n'
b'\ttDiff = Date.now() - currentYoloTS;\n\tupdateUi()'
b';\n\tif(tDiff > dayMS)\n\t{\n\t\tclearInterval(upda'
b'teInterval);\n\t\tlocation.reload();\t\n\t}\n}\n'
b'\nfunction updateUi()\n{\n\tvalPercent = tDiff / day'
b'MS * 100;\n\tif(valPercent > 100) valPercent = 100'
b';\n\tdocument.getElementById("progress").style = "'
b'width: " + valPercent + "%;";\n\tif(tDiff > dayMS)'
b'\n\t{\n\t\tdocument.getElementById("yoloValue").i'
b'nnerHTML = "&#xfffd;";\n\t}\n}\n\nupdateUi();\nvar'
b' updateInterval = setInterval(checkTimestamps, 5000)'
b';\n\n//YOLODATE\n</script>\n</body>\n</html>\n',
'headers': ((b'Server', b'nginx'),
(b'Date', b'Mon, 26 Apr 2021 18:31:56 GMT'),
(b'Content-Type', b'text/html'),
(b'Content-Length', b'2460'),
(b'Last-Modified', b'Sun, 25 Apr 2021 22:00:00 GMT'),
(b'Connection', b'keep-alive'),
(b'ETag', b'"6085e660-99c"'),
(b'Strict-Transport-Security',
b'max-age=31536000; includeSubDomains; preload'),
(b'X-Xss-Protection', b'1; mode=block'),
(b'X-Content-Type-Options', b'nosniff'),
(b'Content-Security-Policy',
b"default-src 'self'; script-src 'self' 'unsafe-in"
b"line'; connect-src 'self'; img-src 'self'; style"
b"-src 'self' 'unsafe-inline';"),
(b'X-Frame-Options', b'SAMEORIGIN'),
(b'Referrer-Policy', b'no-referrer'),
(b'Accept-Ranges', b'bytes')),
'http_version': b'HTTP/1.1',
'reason': b'OK',
'status_code': 200,
'timestamp_end': 1619461916.7979567,
'timestamp_start': 1619461916.7935555,
'trailers': None},
'server_conn': flowstate_serverconn,
'type': 'http',
'version': 9}
@pytest.fixture
def flow_response(flowstate_request, flowstate_response):
c = ClientConnection.make_dummy("192.168.0.2")
s = ServerConnection.make_dummy("192.168.0.1")
flow = HTTPFlow(c, s)
flow.request = HTTPRequest.from_state(flowstate_request["request"])
flow.response = HTTPResponse.from_state(flowstate_response["response"])
return flow
class MitmAddonTestServer:
def __init__(self, queue, path: str):
self.queue = queue
@ -235,6 +260,15 @@ def client_server():
server.disconnect()
@pytest.fixture
def client_no_start():
queue = Queue()
sock = os.path.join(tempfile.mkdtemp(), "bigsnitchtest.sock")
sock = f"ipc://{sock}"
client = NetworkThread(name="testthread",queue=queue,path=sock)
return queue, client
class TestBigSnitchWrapper:
def test_request_convert(self, flowstate_request):
req = bRequest(flow=flowstate_request)
@ -247,7 +281,7 @@ class TestBigSnitchWrapper:
'method': 'GET',
'port': 443,
'scheme': 'https',
'server_ip_address': '95.156.226.69',
'server_ip_address': '192.168.0.1',
'timestamp_end': 1619390482.69,
'timestamp_start': 1619390482.6886377,
'tls': True}
@ -405,6 +439,179 @@ class TestBigSnitchWrapper:
assert not DeepDiff(res.__dict__, d)
def test_convert_request_to_json(self, flowstate_request):
j = bRequest(flowstate_request).json()
d = {'content': '',
'headers': {'Accept': '*/*',
'Host': 'yolo.jetzt',
'User-Agent': 'curl/7.75.0'},
'host': 'yolo.jetzt',
'http_version': 'HTTP/1.1',
'method': 'GET',
'port': 443,
'scheme': 'https',
'server_ip_address': '192.168.0.1',
'timestamp_end': 1619390482.69,
'timestamp_start': 1619390482.6886377,
'tls': True}
assert not DeepDiff(j, d)
def test_convert_response_to_json(self, flowstate_response):
j = bResponse(flowstate_response).json()
d = {'content': '<!DOCTYPE html">\n'
'<html>\n'
'<head> \n'
'<meta http-equiv="content-type" '
'content="text/html;charset=ISO-8859-1">\n'
'<title>todays yolo - 3026</title> \n'
'<style type="text/css" media="screen">\n'
'<!--\n'
'body \n'
'{\n'
'color: white;\n'
'background-color: #003;\n'
'margin: 0px\n'
'}\n'
'\n'
'.yolo\n'
'{\n'
'font-family: Verdana, Geneva, Arial, sans-serif;\n'
'font-weight: bold;\n'
'font-size: 3em;\n'
'}\n'
'\n'
'a:visited {\n'
'\tcolor: blue\n'
'}\n'
'\n'
'#content \n'
'{\n'
'font-family: Verdana, Geneva, Arial, sans-serif;\n'
'color: white;\n'
'background-color: transparent;\n'
'text-align: center;\n'
'font-size: 2em;\n'
'position: absolute;\n'
'top: 50%;\n'
'left: 50%;\n'
'-webkit-transform: translateX(-50%) translateY(-50%);\n'
'-moz-transform: translateX(-50%) translateY(-50%);\n'
'-ms-transform: translateX(-50%) translateY(-50%);\n'
'transform: translateX(-50%) translateY(-50%);\n'
'overflow: visible;\n'
'visibility: visible;\n'
'display: block\n'
'}\n'
'\n'
'#sponsors \n'
'{\n'
'font-family: Verdana, Geneva, Arial, sans-serif;\n'
'color: white;\n'
'background-color: transparent;\n'
'text-align: center;\n'
'font-size: 1em;\n'
'position: absolute;\n'
'top: 90%;\n'
'left: 50%;\n'
'-webkit-transform: translateX(-50%) translateY(-50%);\n'
'-moz-transform: translateX(-50%) translateY(-50%);\n'
'-ms-transform: translateX(-50%) translateY(-50%);\n'
'transform: translateX(-50%) translateY(-50%);\n'
'overflow: visible;\n'
'visibility: visible;\n'
'display: block\n'
'}\n'
'\n'
'#progress\n'
'{\n'
'\tbackground-color: #f08;\n'
'\tposition: absolute;\n'
'\tleft: 0px;\n'
'\ttop: 0px;\n'
'\theight: 10px;\n'
'}\n'
'\n'
'-->\n'
'</style>\n'
'</head>\n'
'<body>\n'
'<div id="progress" class="progressBarDiv"></div>\n'
'<div id="content">\n'
'the yolo for today is<br>\n'
'<span class="yolo" id="yoloValue" '
'title="YOLOVALUE">3026</span><br>\n'
'<br>\n'
'</div>\n'
'<div id="sponsors">\n'
'\t<a href="https://cat.yolo.jetzt">Cat</a>\n'
'\t<br>\n'
'\tRegulation (EU) 2016/679 compliant\n'
'</div>\n'
'<script type="text/javascript">\n'
'var currentYoloTS = 1619388000000; //Multiply by 1000 the YOLO '
'way\n'
'var tDiff = Date.now() - currentYoloTS;\n'
'\n'
'var dayMS = 24 * 60 * 60 * 1000;\n'
'\n'
'console.debug(currentYoloTS);\n'
'console.debug(Date.now() - currentYoloTS);\n'
'function checkTimestamps()\n'
'{\n'
'\ttDiff = Date.now() - currentYoloTS;\n'
'\tupdateUi();\n'
'\tif(tDiff > dayMS)\n'
'\t{\n'
'\t\tclearInterval(updateInterval);\n'
'\t\tlocation.reload();\t\n'
'\t}\n'
'}\n'
'\n'
'function updateUi()\n'
'{\n'
'\tvalPercent = tDiff / dayMS * 100;\n'
'\tif(valPercent > 100) valPercent = 100;\n'
'\tdocument.getElementById("progress").style = "width: " + '
'valPercent + "%;";\n'
'\tif(tDiff > dayMS)\n'
'\t{\n'
'\t\tdocument.getElementById("yoloValue").innerHTML = "&#xfffd;";\n'
'\t}\n'
'}\n'
'\n'
'updateUi();\n'
'var updateInterval = setInterval(checkTimestamps, 5000);\n'
'\n'
'//YOLODATE\n'
'</script>\n'
'</body>\n'
'</html>\n',
'headers': [{'Server': 'nginx'},
{'Date': 'Mon, 26 Apr 2021 18:31:56 GMT'},
{'Content-Type': 'text/html'},
{'Content-Length': '2460'},
{'Last-Modified': 'Sun, 25 Apr 2021 22:00:00 GMT'},
{'Connection': 'keep-alive'},
{'ETag': '"6085e660-99c"'},
{'Strict-Transport-Security': 'max-age=31536000; '
'includeSubDomains; preload'},
{'X-Xss-Protection': '1; mode=block'},
{'X-Content-Type-Options': 'nosniff'},
{'Content-Security-Policy': "default-src 'self'; script-src "
"'self' 'unsafe-inline'; connect-src "
"'self'; img-src 'self'; style-src "
"'self' 'unsafe-inline';"},
{'X-Frame-Options': 'SAMEORIGIN'},
{'Referrer-Policy': 'no-referrer'},
{'Accept-Ranges': 'bytes'}],
'http_version': 'HTTP/1.1',
'reason': 'OK',
'status_code': 200,
'timestamp_end': 1619461916.7979567,
'timestamp_start': 1619461916.7935555}
assert not DeepDiff(j, d)
class TestMitmAddon:
def test_get_new_flows_empty(self, client_server):
@ -419,8 +626,37 @@ class TestMitmAddon:
assert queue.empty()
assert not len(client.flows)
def test_get_new_flows_single(self, client_server):
queue, client, server = client_server
def test_get_new_flows_single(self, client_no_start, flow_request):
queue, client = client_no_start
flowitem = FlowItem(bFlowState.UNSENT_HTTP_REQUEST, flow_request)
queue.put_nowait((flow_request.id, flowitem))
client.get_new_flows()
assert queue.empty()
assert len(client.flows) == 1
assert flow_request.id in client.flows.keys()
assert not DeepDiff(flowitem, client.flows[flow_request.id])
def test_get_new_flows_double(self, client_no_start, flow_request, flow_response):
queue, client = client_no_start
flowitem = FlowItem(bFlowState.UNSENT_HTTP_REQUEST, flow_request)
queue.put_nowait((flow_request.id, flowitem))
flowitem2 = FlowItem(bFlowState.UNSENT_HTTP_RESPONSE, flow_response)
queue.put_nowait((flow_response.id, flowitem2))
client.get_new_flows()
assert queue.empty()
assert len(client.flows) == 2
assert flow_request.id in client.flows.keys()
assert not DeepDiff(flowitem, client.flows[flow_request.id])
assert flow_response.id in client.flows.keys()
assert not DeepDiff(flowitem2, client.flows[flow_response.id])
def test_request(self, client_server):
queue, client, server = client_server