aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml6
-rw-r--r--mitmproxy/net/tcp.py21
-rw-r--r--pathod/protocols/http2.py8
-rw-r--r--setup.cfg6
-rw-r--r--setup.py2
-rw-r--r--test/full_coverage_plugin.py7
-rw-r--r--test/mitmproxy/contentviews/test_api.py15
-rw-r--r--test/mitmproxy/contentviews/test_xml_html.py8
-rw-r--r--test/mitmproxy/contentviews/test_xml_html_data/test-formatted.html44
-rw-r--r--test/mitmproxy/contentviews/test_xml_html_data/test.html14
-rw-r--r--test/mitmproxy/net/test_tcp.py43
-rw-r--r--test/mitmproxy/test_controller.py2
-rw-r--r--tox.ini2
13 files changed, 145 insertions, 33 deletions
diff --git a/.travis.yml b/.travis.yml
index d411ac0b..26894eee 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,13 +18,13 @@ matrix:
language: generic
env: TOXENV=py35 BDIST=1
- python: 3.5
- env: TOXENV=py35 OPENSSL_OLD
+ env: TOXENV=py35 OPENSSL=old
addons:
apt:
packages:
- libssl-dev
- python: 3.5
- env: TOXENV=py35 BDIST=1 OPENSSL_ALPN
+ env: TOXENV=py35 BDIST=1 OPENSSL=with-alpn
addons:
apt:
sources:
@@ -34,7 +34,7 @@ matrix:
packages:
- libssl-dev
- python: 3.6
- env: TOXENV=py36 OPENSSL_ALPN
+ env: TOXENV=py36 OPENSSL=with-alpn
addons:
apt:
sources:
diff --git a/mitmproxy/net/tcp.py b/mitmproxy/net/tcp.py
index 372329d9..81568d24 100644
--- a/mitmproxy/net/tcp.py
+++ b/mitmproxy/net/tcp.py
@@ -511,7 +511,7 @@ class _Connection:
if log_ssl_key:
context.set_info_callback(log_ssl_key)
- if HAS_ALPN:
+ if HAS_ALPN: # pragma: openssl-old no cover
if alpn_protos is not None:
# advertise application layer protocols
context.set_alpn_protos(alpn_protos)
@@ -520,13 +520,15 @@ class _Connection:
def alpn_select_callback(conn_, options):
if alpn_select in options:
return bytes(alpn_select)
- else: # pragma no cover
+ else: # pragma: no cover
return options[0]
context.set_alpn_select_callback(alpn_select_callback)
elif alpn_select_callback is not None and alpn_select is None:
+ if not callable(alpn_select_callback):
+ raise exceptions.TlsException("ALPN error: alpn_select_callback must be a function.")
context.set_alpn_select_callback(alpn_select_callback)
elif alpn_select_callback is not None and alpn_select is not None:
- raise exceptions.TlsException("ALPN error: only define alpn_select (string) OR alpn_select_callback (method).")
+ raise exceptions.TlsException("ALPN error: only define alpn_select (string) OR alpn_select_callback (function).")
return context
@@ -669,11 +671,11 @@ class TCPClient(_Connection):
if self.spoof_source_address:
try:
if not sock.getsockopt(socket.SOL_IP, socket.IP_TRANSPARENT):
- sock.setsockopt(socket.SOL_IP, socket.IP_TRANSPARENT, 1)
+ sock.setsockopt(socket.SOL_IP, socket.IP_TRANSPARENT, 1) # pragma: windows no cover pragma: osx no cover
except Exception as e:
# socket.IP_TRANSPARENT might not be available on every OS and Python version
raise exceptions.TcpException(
- "Failed to spoof the source address: " + e.strerror
+ "Failed to spoof the source address: " + str(e)
)
sock.connect(sa)
return sock
@@ -686,7 +688,7 @@ class TCPClient(_Connection):
if err is not None:
raise err
else:
- raise socket.error("getaddrinfo returns an empty list")
+ raise socket.error("getaddrinfo returns an empty list") # pragma: no cover
def connect(self):
try:
@@ -709,7 +711,7 @@ class TCPClient(_Connection):
return self.connection.gettimeout()
def get_alpn_proto_negotiated(self):
- if HAS_ALPN and self.ssl_established:
+ if HAS_ALPN and self.ssl_established: # pragma: openssl-old no cover
return self.connection.get_alpn_proto_negotiated()
else:
return b""
@@ -816,7 +818,7 @@ class BaseHandler(_Connection):
self.connection.settimeout(n)
def get_alpn_proto_negotiated(self):
- if HAS_ALPN and self.ssl_established:
+ if HAS_ALPN and self.ssl_established: # pragma: openssl-old no cover
return self.connection.get_alpn_proto_negotiated()
else:
return b""
@@ -847,9 +849,10 @@ class TCPServer:
def __init__(self, address):
self.address = address
self.__is_shut_down = threading.Event()
+ self.__is_shut_down.set()
self.__shutdown_request = False
- if self.address == 'localhost':
+ if self.address[0] == 'localhost':
raise socket.error("Binding to 'localhost' is prohibited. Please use '::1' or '127.0.0.1' directly.")
try:
diff --git a/pathod/protocols/http2.py b/pathod/protocols/http2.py
index 7c88c5c7..cfc71650 100644
--- a/pathod/protocols/http2.py
+++ b/pathod/protocols/http2.py
@@ -247,13 +247,13 @@ class HTTP2StateProtocol:
raw_bytes = frm.serialize()
self.tcp_handler.wfile.write(raw_bytes)
self.tcp_handler.wfile.flush()
- if not hide and self.dump_frames: # pragma no cover
+ if not hide and self.dump_frames: # pragma: no cover
print(">> " + repr(frm))
def read_frame(self, hide=False):
while True:
frm = http2.parse_frame(*http2.read_raw_frame(self.tcp_handler.rfile))
- if not hide and self.dump_frames: # pragma no cover
+ if not hide and self.dump_frames: # pragma: no cover
print("<< " + repr(frm))
if isinstance(frm, hyperframe.frame.PingFrame):
@@ -337,7 +337,7 @@ class HTTP2StateProtocol:
if end_stream:
frms[0].flags.add('END_STREAM')
- if self.dump_frames: # pragma no cover
+ if self.dump_frames: # pragma: no cover
for frm in frms:
print(">> ", repr(frm))
@@ -355,7 +355,7 @@ class HTTP2StateProtocol:
data=body[i:i + chunk_size]) for i in chunks]
frms[-1].flags.add('END_STREAM')
- if self.dump_frames: # pragma no cover
+ if self.dump_frames: # pragma: no cover
for frm in frms:
print(">> ", repr(frm))
diff --git a/setup.cfg b/setup.cfg
index ebe76efd..1721975e 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -21,17 +21,12 @@ exclude_lines =
[tool:full_coverage]
exclude =
- mitmproxy/contentviews/__init__.py
mitmproxy/contentviews/wbxml.py
- mitmproxy/contentviews/xml_html.py
- mitmproxy/net/tcp.py
- mitmproxy/net/http/encoding.py
mitmproxy/proxy/protocol/
mitmproxy/proxy/config.py
mitmproxy/proxy/root_context.py
mitmproxy/proxy/server.py
mitmproxy/tools/
- mitmproxy/controller.py
mitmproxy/flow.py
mitmproxy/master.py
pathod/pathoc.py
@@ -45,7 +40,6 @@ exclude =
mitmproxy/addons/termlog.py
mitmproxy/contentviews/base.py
mitmproxy/contentviews/wbxml.py
- mitmproxy/contentviews/xml_html.py
mitmproxy/controller.py
mitmproxy/ctx.py
mitmproxy/exceptions.py
diff --git a/setup.py b/setup.py
index 1466970b..a03d74fb 100644
--- a/setup.py
+++ b/setup.py
@@ -104,7 +104,7 @@ setup(
"pytest-timeout>=1.0.0, <2",
"pytest-xdist>=1.14, <2",
"pytest-faulthandler>=1.3.0, <2",
- "sphinx>=1.3.5, <1.6",
+ "sphinx>=1.3.5, <1.7",
"sphinx-autobuild>=0.5.2, <0.7",
"sphinxcontrib-documentedlist>=0.5.0, <0.7",
"sphinx_rtd_theme>=0.1.9, <0.3",
diff --git a/test/full_coverage_plugin.py b/test/full_coverage_plugin.py
index d98c29d6..ec30a9f9 100644
--- a/test/full_coverage_plugin.py
+++ b/test/full_coverage_plugin.py
@@ -1,6 +1,7 @@
import os
import configparser
import pytest
+import sys
here = os.path.abspath(os.path.dirname(__file__))
@@ -59,6 +60,12 @@ def pytest_runtestloop(session):
if os.name == 'nt':
cov.exclude('pragma: windows no cover')
+ if sys.platform == 'darwin':
+ cov.exclude('pragma: osx no cover')
+
+ if os.environ.get("OPENSSL") == "old":
+ cov.exclude('pragma: openssl-old no cover')
+
yield
coverage_values = dict([(name, 0) for name in pytest.config.option.full_cov])
diff --git a/test/mitmproxy/contentviews/test_api.py b/test/mitmproxy/contentviews/test_api.py
index 95d83af9..c072c86f 100644
--- a/test/mitmproxy/contentviews/test_api.py
+++ b/test/mitmproxy/contentviews/test_api.py
@@ -9,23 +9,28 @@ from mitmproxy.test import tutils
class TestContentView(contentviews.View):
name = "test"
- prompt = ("t", "test")
+ prompt = ("test", "t")
content_types = ["test/123"]
def test_add_remove():
tcv = TestContentView()
contentviews.add(tcv)
+ assert tcv in contentviews.views
# repeated addition causes exception
- with pytest.raises(ContentViewException):
+ with pytest.raises(ContentViewException, match="Duplicate view"):
contentviews.add(tcv)
+ tcv2 = TestContentView()
+ tcv2.name = "test2"
+ tcv2.prompt = ("test2", "t")
# Same shortcut doesn't work either.
- with pytest.raises(ContentViewException):
- contentviews.add(TestContentView())
+ with pytest.raises(ContentViewException, match="Duplicate view shortcut"):
+ contentviews.add(tcv2)
contentviews.remove(tcv)
+ assert tcv not in contentviews.views
def test_get_content_view():
@@ -43,6 +48,7 @@ def test_get_content_view():
headers=Headers(content_type="application/json")
)
assert desc == "JSON"
+ assert list(lines)
desc, lines, err = contentviews.get_content_view(
contentviews.get("JSON"),
@@ -84,3 +90,4 @@ def test_get_message_content_view():
def test_get_by_shortcut():
assert contentviews.get_by_shortcut("s")
+ assert not contentviews.get_by_shortcut("b")
diff --git a/test/mitmproxy/contentviews/test_xml_html.py b/test/mitmproxy/contentviews/test_xml_html.py
index 2b0aee4d..8148fd4c 100644
--- a/test/mitmproxy/contentviews/test_xml_html.py
+++ b/test/mitmproxy/contentviews/test_xml_html.py
@@ -11,6 +11,13 @@ def test_simple():
v = full_eval(xml_html.ViewXmlHtml())
assert v(b"foo") == ('XML', [[('text', 'foo')]])
assert v(b"<html></html>") == ('HTML', [[('text', '<html></html>')]])
+ assert v(b"<>") == ('XML', [[('text', '<>')]])
+ assert v(b"<p") == ('XML', [[('text', '<p')]])
+
+ with open(data.path("simple.html")) as f:
+ input = f.read()
+ tokens = xml_html.tokenize(input)
+ assert str(next(tokens)) == "Tag(<!DOCTYPE html>)"
@pytest.mark.parametrize("filename", [
@@ -18,6 +25,7 @@ def test_simple():
"cdata.xml",
"comment.xml",
"inline.html",
+ "test.html"
])
def test_format_xml(filename):
path = data.path(filename)
diff --git a/test/mitmproxy/contentviews/test_xml_html_data/test-formatted.html b/test/mitmproxy/contentviews/test_xml_html_data/test-formatted.html
new file mode 100644
index 00000000..0eb60004
--- /dev/null
+++ b/test/mitmproxy/contentviews/test_xml_html_data/test-formatted.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Title</title>
+</head>
+<body>
+ <p>
+ Lorem ipsum dolor
+ <p>
+ sit amet, consectetur
+ <p>
+ adipiscing elit, sed
+ <p>
+ do eiusmod tempor
+ <p>
+ incididunt ut
+ <p>
+ labore et dolore
+ <p>
+ magna aliqua.
+ <p>
+ Ut enim ad minim
+ <p>
+ veniam, quis nostrud
+ <p>
+ exercitation
+ <p>
+ ullamco laboris
+ <p>
+ nisi ut aliquip ex ea
+ <p>
+ commodo consequat.
+ <p>
+ Duis aute irure
+ <p>
+ dolor in reprehenderit
+ <p>
+ in voluptate velit
+ <p>
+ esse cillum dolore
+ <p>eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
+</body>
+</html>
diff --git a/test/mitmproxy/contentviews/test_xml_html_data/test.html b/test/mitmproxy/contentviews/test_xml_html_data/test.html
new file mode 100644
index 00000000..e74ac314
--- /dev/null
+++ b/test/mitmproxy/contentviews/test_xml_html_data/test.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Title</title>
+</head>
+<body>
+<p>Lorem ipsum dolor<p>sit amet, consectetur <p>adipiscing elit, sed<p>do eiusmod tempor<p> incididunt ut<p> labore et dolore<p> magna aliqua.
+ <p>Ut enim ad minim <p>veniam, quis nostrud <p>exercitation <p>ullamco laboris <p>
+ nisi ut aliquip ex ea <p>commodo consequat.<p>Duis aute irure <p>dolor in reprehenderit <p>in voluptate velit<p> esse cillum dolore <p>eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
+
+
+</body>
+</html> \ No newline at end of file
diff --git a/test/mitmproxy/net/test_tcp.py b/test/mitmproxy/net/test_tcp.py
index 8b26784a..81d51888 100644
--- a/test/mitmproxy/net/test_tcp.py
+++ b/test/mitmproxy/net/test_tcp.py
@@ -529,10 +529,10 @@ class TestTimeOut(tservers.ServerTestBase):
class TestCryptographyALPN:
def test_has_alpn(self):
- if 'OPENSSL_ALPN' in os.environ:
+ if os.environ.get("OPENSSL") == "with-alpn":
assert tcp.HAS_ALPN
assert SSL._lib.Cryptography_HAS_ALPN
- elif 'OPENSSL_OLD' in os.environ:
+ elif os.environ.get("OPENSSL") == "old":
assert not tcp.HAS_ALPN
assert not SSL._lib.Cryptography_HAS_ALPN
@@ -603,13 +603,36 @@ class TestDHParams(tservers.ServerTestBase):
assert ret[0] == "DHE-RSA-AES256-SHA"
-class TestTCPClient:
+class TestTCPClient(tservers.ServerTestBase):
def test_conerr(self):
c = tcp.TCPClient(("127.0.0.1", 0))
- with pytest.raises(exceptions.TcpException):
+ with pytest.raises(exceptions.TcpException, match="Error connecting"):
c.connect()
+ def test_timeout(self):
+ c = tcp.TCPClient(("127.0.0.1", self.port))
+ with c.create_connection(timeout=20) as conn:
+ assert conn.gettimeout() == 20
+
+ def test_spoof_address(self):
+ c = tcp.TCPClient(("127.0.0.1", self.port), spoof_source_address=("127.0.0.1", 0))
+ with pytest.raises(exceptions.TcpException, match="Failed to spoof"):
+ c.connect()
+
+
+class TestTCPServer:
+
+ def test_binderr(self):
+ with pytest.raises(socket.error, match="prohibited"):
+ tcp.TCPServer(("localhost", 8080))
+
+ def test_wait_for_silence(self):
+ s = tcp.TCPServer(("127.0.0.1", 0))
+ with s.handler_counter:
+ with pytest.raises(exceptions.Timeout):
+ s.wait_for_silence()
+
class TestFileLike:
@@ -811,7 +834,7 @@ class TestSSLKeyLogger(tservers.ServerTestBase):
assert not tcp.SSLKeyLogger.create_logfun(False)
-class TestSSLInvalidMethod(tservers.ServerTestBase):
+class TestSSLInvalid(tservers.ServerTestBase):
handler = EchoHandler
ssl = True
@@ -821,3 +844,13 @@ class TestSSLInvalidMethod(tservers.ServerTestBase):
with c.connect():
with pytest.raises(exceptions.TlsException):
c.convert_to_ssl(method=fake_ssl_method)
+
+ def test_alpn_error(self):
+ c = tcp.TCPClient(("127.0.0.1", self.port))
+ with c.connect():
+ if tcp.HAS_ALPN:
+ with pytest.raises(exceptions.TlsException, match="must be a function"):
+ c.create_ssl_context(alpn_select_callback="foo")
+
+ with pytest.raises(exceptions.TlsException, match="ALPN error"):
+ c.create_ssl_context(alpn_select="foo", alpn_select_callback="bar")
diff --git a/test/mitmproxy/test_controller.py b/test/mitmproxy/test_controller.py
index ccc8bf35..2e13d298 100644
--- a/test/mitmproxy/test_controller.py
+++ b/test/mitmproxy/test_controller.py
@@ -176,6 +176,8 @@ class TestDummyReply:
reply = controller.DummyReply()
reply.ack()
reply.take()
+ with pytest.raises(ControlException):
+ reply.mark_reset()
reply.commit()
reply.mark_reset()
assert reply.state == "committed"
diff --git a/tox.ini b/tox.ini
index 3f3240ae..c5e2d5fc 100644
--- a/tox.ini
+++ b/tox.ini
@@ -7,7 +7,7 @@ toxworkdir={env:TOX_WORK_DIR:.tox}
deps =
{env:CI_DEPS:}
-rrequirements.txt
-passenv = CODECOV_TOKEN CI CI_* TRAVIS TRAVIS_* APPVEYOR APPVEYOR_* SNAPSHOT_* OPENSSL_* RTOOL_*
+passenv = CODECOV_TOKEN CI CI_* TRAVIS TRAVIS_* APPVEYOR APPVEYOR_* SNAPSHOT_* OPENSSL RTOOL_*
setenv = HOME = {envtmpdir}
commands =
mitmdump --version