From ba674ad5514c5f30315fc688a07fdac634d94dfc Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Fri, 1 Mar 2013 09:05:39 +1300 Subject: New SNI handling mechanism. --- test/test_server.py | 62 ++++++++++++++++++++++++++--------------------------- test/tservers.py | 33 +++++++++++++++++++--------- 2 files changed, 54 insertions(+), 41 deletions(-) (limited to 'test') diff --git a/test/test_server.py b/test/test_server.py index 034fab41..466c0f94 100644 --- a/test/test_server.py +++ b/test/test_server.py @@ -13,11 +13,7 @@ from libmproxy import flow, proxy for a 200 response. """ -class SanityMixin: - def test_http(self): - assert self.pathod("304").status_code == 304 - assert self.master.state.view - +class CommonMixin: def test_large(self): assert len(self.pathod("200:b@50k").content) == 1024*50 @@ -40,19 +36,23 @@ class SanityMixin: self.master.replay_request(l, block=True) assert l.error + def test_http(self): + f = self.pathod("304") + assert f.status_code == 304 -class TestHTTP(tservers.HTTPProxTest, SanityMixin): - def test_app(self): - p = self.pathoc() - ret = p.request("get:'http://testapp/'") - assert ret[1] == 200 - assert ret[4] == "testapp" + l = self.master.state.view[0] + assert l.request.client_conn.address + assert "host" in l.request.headers + assert l.response.code == 304 + + +class TestHTTP(tservers.HTTPProxTest, CommonMixin): def test_app_err(self): p = self.pathoc() ret = p.request("get:'http://errapp/'") - assert ret[1] == 500 - assert "ValueError" in ret[4] + assert ret.status_code == 500 + assert "ValueError" in ret.content def test_invalid_http(self): t = tcp.TCPClient("127.0.0.1", self.proxy.port) @@ -71,16 +71,7 @@ class TestHTTP(tservers.HTTPProxTest, SanityMixin): def test_upstream_ssl_error(self): p = self.pathoc() ret = p.request("get:'https://localhost:%s/'"%self.server.port) - assert ret[1] == 400 - - def test_http(self): - f = self.pathod("304") - assert f.status_code == 304 - - l = self.master.state.view[0] - assert l.request.client_conn.address - assert "host" in l.request.headers - assert l.response.code == 304 + assert ret.status_code == 400 def test_connection_close(self): # Add a body, so we have a content-length header, which combined with @@ -116,7 +107,7 @@ class TestHTTP(tservers.HTTPProxTest, SanityMixin): # within our read loop. with mock.patch("libmproxy.proxy.ProxyHandler.read_request") as m: m.side_effect = IOError("error!") - tutils.raises("empty reply", self.pathod, "304") + tutils.raises("server disconnect", self.pathod, "304") def test_get_connection_switching(self): def switched(l): @@ -132,30 +123,39 @@ class TestHTTP(tservers.HTTPProxTest, SanityMixin): def test_get_connection_err(self): p = self.pathoc() ret = p.request("get:'http://localhost:0'") - assert ret[1] == 502 + assert ret.status_code == 502 -class TestHTTPS(tservers.HTTPProxTest, SanityMixin): +class TestHTTPS(tservers.HTTPProxTest, CommonMixin): ssl = True clientcerts = True def test_clientcert(self): f = self.pathod("304") assert self.server.last_log()["request"]["clientcert"]["keyinfo"] + def test_sni(self): + pass + -class TestHTTPSCertfile(tservers.HTTPProxTest, SanityMixin): +class TestHTTPSCertfile(tservers.HTTPProxTest, CommonMixin): ssl = True certfile = True def test_certfile(self): assert self.pathod("304") -class TestReverse(tservers.ReverseProxTest, SanityMixin): +class TestReverse(tservers.ReverseProxTest, CommonMixin): reverse = True -class TestTransparent(tservers.TransparentProxTest, SanityMixin): +class TestTransparent(tservers.TransparentProxTest, CommonMixin): + transparent = True + ssl = False + + +class TestTransparentSSL(tservers.TransparentProxTest, CommonMixin): transparent = True + ssl = True class TestProxy(tservers.HTTPProxTest): @@ -232,7 +232,7 @@ class TestKillRequest(tservers.HTTPProxTest): masterclass = MasterKillRequest def test_kill(self): p = self.pathoc() - tutils.raises("empty reply", self.pathod, "200") + tutils.raises("server disconnect", self.pathod, "200") # Nothing should have hit the server assert not self.server.last_log() @@ -246,7 +246,7 @@ class TestKillResponse(tservers.HTTPProxTest): masterclass = MasterKillResponse def test_kill(self): p = self.pathoc() - tutils.raises("empty reply", self.pathod, "200") + tutils.raises("server disconnect", self.pathod, "200") # The server should have seen a request assert self.server.last_log() diff --git a/test/tservers.py b/test/tservers.py index 998ad6c6..c8bc7100 100644 --- a/test/tservers.py +++ b/test/tservers.py @@ -126,20 +126,21 @@ class HTTPProxTest(ProxTestBase): """ Returns a connected Pathoc instance. """ - p = libpathod.pathoc.Pathoc("localhost", self.proxy.port) + p = libpathod.pathoc.Pathoc("localhost", self.proxy.port, ssl=self.ssl) p.connect(connect_to) return p def pathod(self, spec): """ - Constructs a pathod request, with the appropriate base and proxy. + Constructs a pathod GET request, with the appropriate base and proxy. """ - return hurl.get( - self.server.urlbase + "/p/" + spec, - proxy=self.proxies, - validate_cert=False, - #debug=hurl.utils.stdout_debug - ) + if self.ssl: + p = self.pathoc(("127.0.0.1", self.server.port)) + q = "get:'/p/%s'"%spec + else: + p = self.pathoc() + q = "get:'%s/p/%s'"%(self.server.urlbase, spec) + return p.request(q) class TResolver: @@ -155,9 +156,13 @@ class TransparentProxTest(ProxTestBase): @classmethod def get_proxy_config(cls): d = ProxTestBase.get_proxy_config() + if cls.ssl: + ports = [cls.server.port, cls.server2.port] + else: + ports = [] d["transparent_proxy"] = dict( resolver = TResolver(cls.server.port), - sslports = [] + sslports = ports ) return d @@ -166,12 +171,20 @@ class TransparentProxTest(ProxTestBase): Constructs a pathod request, with the appropriate base and proxy. """ r = hurl.get( - "http://127.0.0.1:%s"%self.proxy.port + "/p/" + spec, + "%s://127.0.0.1:%s"%(self.scheme, self.proxy.port) + "/p/" + spec, validate_cert=False, #debug=hurl.utils.stdout_debug ) return r + def pathoc(self, connect= None): + """ + Returns a connected Pathoc instance. + """ + p = libpathod.pathoc.Pathoc("localhost", self.proxy.port) + p.connect(connect_to) + return p + class ReverseProxTest(ProxTestBase): ssl = None -- cgit v1.2.3 From 10db82e9a030235ab884e70d1809ad6d673c2d13 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sat, 2 Mar 2013 14:52:05 +1300 Subject: Test SNI for ordinary proxy connections. --- test/test_server.py | 6 +++++- test/tservers.py | 16 +++++++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/test/test_server.py b/test/test_server.py index 466c0f94..244f972f 100644 --- a/test/test_server.py +++ b/test/test_server.py @@ -131,10 +131,14 @@ class TestHTTPS(tservers.HTTPProxTest, CommonMixin): clientcerts = True def test_clientcert(self): f = self.pathod("304") + assert f.status_code == 304 assert self.server.last_log()["request"]["clientcert"]["keyinfo"] def test_sni(self): - pass + f = self.pathod("304", sni="testserver.com") + assert f.status_code == 304 + l = self.server.last_log() + assert self.server.last_log()["request"]["sni"] == "testserver.com" class TestHTTPSCertfile(tservers.HTTPProxTest, CommonMixin): diff --git a/test/tservers.py b/test/tservers.py index c8bc7100..d1878f7a 100644 --- a/test/tservers.py +++ b/test/tservers.py @@ -28,7 +28,7 @@ class TestMaster(flow.FlowMaster): state = flow.State() flow.FlowMaster.__init__(self, s, state) self.testq = testq - self.log = [] + self.clear_log() def handle_request(self, m): flow.FlowMaster.handle_request(self, m) @@ -38,6 +38,9 @@ class TestMaster(flow.FlowMaster): flow.FlowMaster.handle_response(self, m) m.reply() + def clear_log(self): + self.log = [] + def handle_log(self, l): self.log.append(l.msg) l.reply() @@ -96,7 +99,10 @@ class ProxTestBase: cls.server2.shutdown() def setUp(self): + self.master.clear_log() self.master.state.clear() + self.server.clear_log() + self.server2.clear_log() @property def scheme(self): @@ -122,20 +128,20 @@ class ProxTestBase: class HTTPProxTest(ProxTestBase): - def pathoc(self, connect_to = None): + def pathoc(self, connect_to = None, sni=None): """ Returns a connected Pathoc instance. """ - p = libpathod.pathoc.Pathoc("localhost", self.proxy.port, ssl=self.ssl) + p = libpathod.pathoc.Pathoc("localhost", self.proxy.port, ssl=self.ssl, sni=sni) p.connect(connect_to) return p - def pathod(self, spec): + def pathod(self, spec, sni=None): """ Constructs a pathod GET request, with the appropriate base and proxy. """ if self.ssl: - p = self.pathoc(("127.0.0.1", self.server.port)) + p = self.pathoc(("127.0.0.1", self.server.port), sni=sni) q = "get:'/p/%s'"%spec else: p = self.pathoc() -- cgit v1.2.3 From a95d78438c7197b0b6643a61899914083de70da9 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sat, 2 Mar 2013 15:06:49 +1300 Subject: Test SNI for transparent mode. --- test/test_server.py | 6 ++++++ test/tservers.py | 23 ++++++++++++----------- 2 files changed, 18 insertions(+), 11 deletions(-) (limited to 'test') diff --git a/test/test_server.py b/test/test_server.py index 244f972f..47bd56b1 100644 --- a/test/test_server.py +++ b/test/test_server.py @@ -160,6 +160,12 @@ class TestTransparent(tservers.TransparentProxTest, CommonMixin): class TestTransparentSSL(tservers.TransparentProxTest, CommonMixin): transparent = True ssl = True + def test_sni(self): + f = self.pathod("304", sni="testserver.com") + assert f.status_code == 304 + l = self.server.last_log() + assert self.server.last_log()["request"]["sni"] == "testserver.com" + class TestProxy(tservers.HTTPProxTest): diff --git a/test/tservers.py b/test/tservers.py index d1878f7a..12692369 100644 --- a/test/tservers.py +++ b/test/tservers.py @@ -172,23 +172,24 @@ class TransparentProxTest(ProxTestBase): ) return d - def pathod(self, spec): + def pathod(self, spec, sni=None): """ - Constructs a pathod request, with the appropriate base and proxy. + Constructs a pathod GET request, with the appropriate base and proxy. """ - r = hurl.get( - "%s://127.0.0.1:%s"%(self.scheme, self.proxy.port) + "/p/" + spec, - validate_cert=False, - #debug=hurl.utils.stdout_debug - ) - return r + if self.ssl: + p = self.pathoc(sni=sni) + q = "get:'/p/%s'"%spec + else: + p = self.pathoc() + q = "get:'/p/%s'"%spec + return p.request(q) - def pathoc(self, connect= None): + def pathoc(self, sni=None): """ Returns a connected Pathoc instance. """ - p = libpathod.pathoc.Pathoc("localhost", self.proxy.port) - p.connect(connect_to) + p = libpathod.pathoc.Pathoc("localhost", self.proxy.port, ssl=self.ssl, sni=sni) + p.connect() return p -- cgit v1.2.3 From 09c73019c562eeb9dd4297b481c11d8078c888ff Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sat, 2 Mar 2013 15:09:22 +1300 Subject: Remove human_curl requirement for the test suite - it's pathoc all the way, baby. --- test/tservers.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'test') diff --git a/test/tservers.py b/test/tservers.py index 12692369..d405e745 100644 --- a/test/tservers.py +++ b/test/tservers.py @@ -1,6 +1,5 @@ import threading, Queue import flask -import human_curl as hurl import libpathod.test, libpathod.pathoc from libmproxy import proxy, flow, controller import tutils @@ -205,14 +204,23 @@ class ReverseProxTest(ProxTestBase): ) return d - def pathod(self, spec): + def pathoc(self, sni=None): """ - Constructs a pathod request, with the appropriate base and proxy. + Returns a connected Pathoc instance. """ - r = hurl.get( - "http://127.0.0.1:%s"%self.proxy.port + "/p/" + spec, - validate_cert=False, - #debug=hurl.utils.stdout_debug - ) - return r + p = libpathod.pathoc.Pathoc("localhost", self.proxy.port, ssl=self.ssl, sni=sni) + p.connect() + return p + + def pathod(self, spec, sni=None): + """ + Constructs a pathod GET request, with the appropriate base and proxy. + """ + if self.ssl: + p = self.pathoc(sni=sni) + q = "get:'/p/%s'"%spec + else: + p = self.pathoc() + q = "get:'/p/%s'"%spec + return p.request(q) -- cgit v1.2.3 From 415844511c19b17743b42a5833590d1d683427d2 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sat, 2 Mar 2013 16:59:16 +1300 Subject: Test cert generation errors. --- test/test_proxy.py | 1 - test/test_server.py | 13 ++++++++++--- test/tservers.py | 15 +++++++++++---- 3 files changed, 21 insertions(+), 8 deletions(-) (limited to 'test') diff --git a/test/test_proxy.py b/test/test_proxy.py index 3995b393..0788edbf 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -22,7 +22,6 @@ def test_app_registry(): r.port = 81 assert not ar.get(r) - r = tutils.treq() r.host = "domain2" r.port = 80 diff --git a/test/test_server.py b/test/test_server.py index 47bd56b1..86a75452 100644 --- a/test/test_server.py +++ b/test/test_server.py @@ -141,6 +141,16 @@ class TestHTTPS(tservers.HTTPProxTest, CommonMixin): assert self.server.last_log()["request"]["sni"] == "testserver.com" +class TestHTTPSNoUpstream(tservers.HTTPProxTest, CommonMixin): + ssl = True + no_upstream_cert = True + def test_cert_gen_error(self): + f = self.pathoc_raw() + f.connect((u"\u2102\u0001".encode("utf8"), 0)) + f.request("get:/") + assert "dummy cert" in "".join(self.proxy.log) + + class TestHTTPSCertfile(tservers.HTTPProxTest, CommonMixin): ssl = True certfile = True @@ -227,7 +237,6 @@ class MasterFakeResponse(tservers.TestMaster): class TestFakeResponse(tservers.HTTPProxTest): masterclass = MasterFakeResponse def test_kill(self): - p = self.pathoc() f = self.pathod("200") assert "header_response" in f.headers.keys() @@ -241,7 +250,6 @@ class MasterKillRequest(tservers.TestMaster): class TestKillRequest(tservers.HTTPProxTest): masterclass = MasterKillRequest def test_kill(self): - p = self.pathoc() tutils.raises("server disconnect", self.pathod, "200") # Nothing should have hit the server assert not self.server.last_log() @@ -255,7 +263,6 @@ class MasterKillResponse(tservers.TestMaster): class TestKillResponse(tservers.HTTPProxTest): masterclass = MasterKillResponse def test_kill(self): - p = self.pathoc() tutils.raises("server disconnect", self.pathod, "200") # The server should have seen a request assert self.server.last_log() diff --git a/test/tservers.py b/test/tservers.py index d405e745..4efed7e2 100644 --- a/test/tservers.py +++ b/test/tservers.py @@ -71,6 +71,7 @@ class ProxTestBase: ssl = None clientcerts = False certfile = None + no_upstream_cert = False masterclass = TestMaster @classmethod @@ -80,6 +81,7 @@ class ProxTestBase: cls.server2 = libpathod.test.Daemon(ssl=cls.ssl) pconf = cls.get_proxy_config() config = proxy.ProxyConfig( + no_upstream_cert = cls.no_upstream_cert, cacert = tutils.test_data.path("data/serverkey.pem"), **pconf ) @@ -127,23 +129,28 @@ class ProxTestBase: class HTTPProxTest(ProxTestBase): - def pathoc(self, connect_to = None, sni=None): + def pathoc_raw(self): + return libpathod.pathoc.Pathoc("127.0.0.1", self.proxy.port) + + def pathoc(self, sni=None): """ Returns a connected Pathoc instance. """ p = libpathod.pathoc.Pathoc("localhost", self.proxy.port, ssl=self.ssl, sni=sni) - p.connect(connect_to) + if self.ssl: + p.connect(("127.0.0.1", self.server.port)) + else: + p.connect() return p def pathod(self, spec, sni=None): """ Constructs a pathod GET request, with the appropriate base and proxy. """ + p = self.pathoc(sni=sni) if self.ssl: - p = self.pathoc(("127.0.0.1", self.server.port), sni=sni) q = "get:'/p/%s'"%spec else: - p = self.pathoc() q = "get:'%s/p/%s'"%(self.server.urlbase, spec) return p.request(q) -- cgit v1.2.3 From c20d1d7d32ea2ab1d1c4dd9a34724a8732c23338 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sat, 2 Mar 2013 22:42:36 +1300 Subject: Extend unit tests for proxy.py to some tricky cases. --- test/test_server.py | 59 +++++++++++++++++++++++++++++++++++++++++++++-------- test/tservers.py | 6 ++++-- 2 files changed, 54 insertions(+), 11 deletions(-) (limited to 'test') diff --git a/test/test_server.py b/test/test_server.py index 86a75452..3a1b019f 100644 --- a/test/test_server.py +++ b/test/test_server.py @@ -45,6 +45,12 @@ class CommonMixin: assert "host" in l.request.headers assert l.response.code == 304 + def test_invalid_http(self): + t = tcp.TCPClient("127.0.0.1", self.proxy.port) + t.connect() + t.wfile.write("invalid\r\n\r\n") + t.wfile.flush() + assert "Bad Request" in t.rfile.readline() class TestHTTP(tservers.HTTPProxTest, CommonMixin): @@ -54,13 +60,6 @@ class TestHTTP(tservers.HTTPProxTest, CommonMixin): assert ret.status_code == 500 assert "ValueError" in ret.content - def test_invalid_http(self): - t = tcp.TCPClient("127.0.0.1", self.proxy.port) - t.connect() - t.wfile.write("invalid\n\n") - t.wfile.flush() - assert "Bad Request" in t.rfile.readline() - def test_invalid_connect(self): t = tcp.TCPClient("127.0.0.1", self.proxy.port) t.connect() @@ -125,6 +124,25 @@ class TestHTTP(tservers.HTTPProxTest, CommonMixin): ret = p.request("get:'http://localhost:0'") assert ret.status_code == 502 + def test_blank_leading_line(self): + p = self.pathoc() + req = "get:'%s/p/201':i0,'\r\n'" + assert p.request(req%self.server.urlbase).status_code == 201 + + def test_invalid_headers(self): + p = self.pathoc() + req = p.request("get:'http://foo':h':foo'='bar'") + print req + + +class TestHTTPConnectSSLError(tservers.HTTPProxTest): + certfile = True + def test_go(self): + p = self.pathoc() + req = "connect:'localhost:%s'"%self.proxy.port + assert p.request(req).status_code == 200 + assert p.request(req).status_code == 400 + class TestHTTPS(tservers.HTTPProxTest, CommonMixin): ssl = True @@ -140,6 +158,11 @@ class TestHTTPS(tservers.HTTPProxTest, CommonMixin): l = self.server.last_log() assert self.server.last_log()["request"]["sni"] == "testserver.com" + def test_error_post_connect(self): + p = self.pathoc() + assert p.request("get:/:i0,'invalid\r\n\r\n'").status_code == 400 + + class TestHTTPSNoUpstream(tservers.HTTPProxTest, CommonMixin): ssl = True @@ -163,12 +186,10 @@ class TestReverse(tservers.ReverseProxTest, CommonMixin): class TestTransparent(tservers.TransparentProxTest, CommonMixin): - transparent = True ssl = False class TestTransparentSSL(tservers.TransparentProxTest, CommonMixin): - transparent = True ssl = True def test_sni(self): f = self.pathod("304", sni="testserver.com") @@ -176,6 +197,10 @@ class TestTransparentSSL(tservers.TransparentProxTest, CommonMixin): l = self.server.last_log() assert self.server.last_log()["request"]["sni"] == "testserver.com" + def test_sslerr(self): + p = pathoc.Pathoc("localhost", self.proxy.port) + p.connect() + assert p.request("get:/").status_code == 400 class TestProxy(tservers.HTTPProxTest): @@ -267,3 +292,19 @@ class TestKillResponse(tservers.HTTPProxTest): # The server should have seen a request assert self.server.last_log() + +class EResolver(tservers.TResolver): + def original_addr(self, sock): + return None + + +class TestTransparentResolveError(tservers.TransparentProxTest): + resolver = EResolver + def test_resolve_error(self): + assert self.pathod("304").status_code == 502 + + + + + + diff --git a/test/tservers.py b/test/tservers.py index 4efed7e2..7672f34a 100644 --- a/test/tservers.py +++ b/test/tservers.py @@ -131,7 +131,7 @@ class ProxTestBase: class HTTPProxTest(ProxTestBase): def pathoc_raw(self): return libpathod.pathoc.Pathoc("127.0.0.1", self.proxy.port) - + def pathoc(self, sni=None): """ Returns a connected Pathoc instance. @@ -148,6 +148,7 @@ class HTTPProxTest(ProxTestBase): Constructs a pathod GET request, with the appropriate base and proxy. """ p = self.pathoc(sni=sni) + spec = spec.encode("string_escape") if self.ssl: q = "get:'/p/%s'"%spec else: @@ -165,6 +166,7 @@ class TResolver: class TransparentProxTest(ProxTestBase): ssl = None + resolver = TResolver @classmethod def get_proxy_config(cls): d = ProxTestBase.get_proxy_config() @@ -173,7 +175,7 @@ class TransparentProxTest(ProxTestBase): else: ports = [] d["transparent_proxy"] = dict( - resolver = TResolver(cls.server.port), + resolver = cls.resolver(cls.server.port), sslports = ports ) return d -- cgit v1.2.3 From bbdb59b9f94e4c0fa887e4ddb4cf3df3413f27fe Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 3 Mar 2013 09:33:22 +1300 Subject: Test controller message default reply. --- test/test_controller.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 test/test_controller.py (limited to 'test') diff --git a/test/test_controller.py b/test/test_controller.py new file mode 100644 index 00000000..f6d6b5eb --- /dev/null +++ b/test/test_controller.py @@ -0,0 +1,12 @@ +import mock +from libmproxy import controller + + +class TestMaster: + def test_default_handler(self): + m = controller.Master(None) + msg = mock.MagicMock() + m.handle(msg) + assert msg.reply.call_count == 1 + + -- cgit v1.2.3 From 5c6587d4a80cc45b23154237ca94858da60c7da5 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 3 Mar 2013 10:37:06 +1300 Subject: Move HTTP auth module to netlib. --- test/test_authentication.py | 58 --------------------------------------------- test/test_proxy.py | 8 +++++++ test/test_server.py | 2 +- 3 files changed, 9 insertions(+), 59 deletions(-) delete mode 100644 test/test_authentication.py (limited to 'test') diff --git a/test/test_authentication.py b/test/test_authentication.py deleted file mode 100644 index f7a5ecd3..00000000 --- a/test/test_authentication.py +++ /dev/null @@ -1,58 +0,0 @@ -import binascii -from libmproxy import authentication -from netlib import odict -import tutils - - -class TestNullProxyAuth: - def test_simple(self): - na = authentication.NullProxyAuth(authentication.PermissivePasswordManager()) - assert not na.auth_challenge_headers() - assert na.authenticate("foo") - na.clean({}) - - -class TestBasicProxyAuth: - def test_simple(self): - ba = authentication.BasicProxyAuth(authentication.PermissivePasswordManager(), "test") - h = odict.ODictCaseless() - assert ba.auth_challenge_headers() - assert not ba.authenticate(h) - - def test_parse_auth_value(self): - ba = authentication.BasicProxyAuth(authentication.PermissivePasswordManager(), "test") - vals = ("basic", "foo", "bar") - assert ba.parse_auth_value(ba.unparse_auth_value(*vals)) == vals - tutils.raises(ValueError, ba.parse_auth_value, "") - tutils.raises(ValueError, ba.parse_auth_value, "foo bar") - - v = "basic " + binascii.b2a_base64("foo") - tutils.raises(ValueError, ba.parse_auth_value, v) - - def test_authenticate_clean(self): - ba = authentication.BasicProxyAuth(authentication.PermissivePasswordManager(), "test") - - hdrs = odict.ODictCaseless() - vals = ("basic", "foo", "bar") - hdrs[ba.AUTH_HEADER] = [ba.unparse_auth_value(*vals)] - assert ba.authenticate(hdrs) - - ba.clean(hdrs) - assert not ba.AUTH_HEADER in hdrs - - - hdrs[ba.AUTH_HEADER] = [""] - assert not ba.authenticate(hdrs) - - hdrs[ba.AUTH_HEADER] = ["foo"] - assert not ba.authenticate(hdrs) - - vals = ("foo", "foo", "bar") - hdrs[ba.AUTH_HEADER] = [ba.unparse_auth_value(*vals)] - assert not ba.authenticate(hdrs) - - ba = authentication.BasicProxyAuth(authentication.PasswordManager(), "test") - vals = ("basic", "foo", "bar") - hdrs[ba.AUTH_HEADER] = [ba.unparse_auth_value(*vals)] - assert not ba.authenticate(hdrs) - diff --git a/test/test_proxy.py b/test/test_proxy.py index 0788edbf..2babe51c 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -58,3 +58,11 @@ class TestServerConnection: sc.connection.close = mock.Mock(side_effect=IOError) sc.terminate() + +class TestProcessOptions: + def test_auth(self): + parser = mock.MagicMock() + + + + diff --git a/test/test_server.py b/test/test_server.py index 3a1b019f..0af4bae8 100644 --- a/test/test_server.py +++ b/test/test_server.py @@ -132,7 +132,7 @@ class TestHTTP(tservers.HTTPProxTest, CommonMixin): def test_invalid_headers(self): p = self.pathoc() req = p.request("get:'http://foo':h':foo'='bar'") - print req + assert req.status_code == 400 class TestHTTPConnectSSLError(tservers.HTTPProxTest): -- cgit v1.2.3 From 33cdd5d0836b706a9d06c332fa5381bbeb4fa69f Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 3 Mar 2013 11:04:33 +1300 Subject: Unit test proxy auth. --- test/test_server.py | 25 ++++++++++++++++++------- test/tservers.py | 3 ++- 2 files changed, 20 insertions(+), 8 deletions(-) (limited to 'test') diff --git a/test/test_server.py b/test/test_server.py index 0af4bae8..8a6228ad 100644 --- a/test/test_server.py +++ b/test/test_server.py @@ -1,6 +1,6 @@ import socket, time import mock -from netlib import tcp +from netlib import tcp, http_auth, http from libpathod import pathoc import tutils, tservers from libmproxy import flow, proxy @@ -135,6 +135,23 @@ class TestHTTP(tservers.HTTPProxTest, CommonMixin): assert req.status_code == 400 +class TestHTTPAuth(tservers.HTTPProxTest): + authenticator = http_auth.BasicProxyAuth(http_auth.PassManSingleUser("test", "test"), "realm") + def test_auth(self): + assert self.pathod("202").status_code == 407 + p = self.pathoc() + ret = p.request(""" + get + 'http://localhost:%s/p/202' + h'%s'='%s' + """%( + self.server.port, + http_auth.BasicProxyAuth.AUTH_HEADER, + http.assemble_http_basic_auth("basic", "test", "test") + )) + assert ret.status_code == 202 + + class TestHTTPConnectSSLError(tservers.HTTPProxTest): certfile = True def test_go(self): @@ -163,7 +180,6 @@ class TestHTTPS(tservers.HTTPProxTest, CommonMixin): assert p.request("get:/:i0,'invalid\r\n\r\n'").status_code == 400 - class TestHTTPSNoUpstream(tservers.HTTPProxTest, CommonMixin): ssl = True no_upstream_cert = True @@ -303,8 +319,3 @@ class TestTransparentResolveError(tservers.TransparentProxTest): def test_resolve_error(self): assert self.pathod("304").status_code == 502 - - - - - diff --git a/test/tservers.py b/test/tservers.py index 7672f34a..0c2f8c2f 100644 --- a/test/tservers.py +++ b/test/tservers.py @@ -72,7 +72,7 @@ class ProxTestBase: clientcerts = False certfile = None no_upstream_cert = False - + authenticator = None masterclass = TestMaster @classmethod def setupAll(cls): @@ -83,6 +83,7 @@ class ProxTestBase: config = proxy.ProxyConfig( no_upstream_cert = cls.no_upstream_cert, cacert = tutils.test_data.path("data/serverkey.pem"), + authenticator = cls.authenticator, **pconf ) tmaster = cls.masterclass(cls.tqueue, config) -- cgit v1.2.3 From d5876a12ed09940df77da823bf857437f7496524 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 3 Mar 2013 11:58:57 +1300 Subject: Unit test proxy option parsing. --- test/data/htpasswd | 1 + test/data/htpasswd.invalid | 1 + test/test_proxy.py | 75 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 test/data/htpasswd create mode 100644 test/data/htpasswd.invalid (limited to 'test') diff --git a/test/data/htpasswd b/test/data/htpasswd new file mode 100644 index 00000000..54c95b8c --- /dev/null +++ b/test/data/htpasswd @@ -0,0 +1 @@ +test:$apr1$/LkYxy3x$WI4.YbiJlu537jLGEW2eu1 diff --git a/test/data/htpasswd.invalid b/test/data/htpasswd.invalid new file mode 100644 index 00000000..257cc564 --- /dev/null +++ b/test/data/htpasswd.invalid @@ -0,0 +1 @@ +foo diff --git a/test/test_proxy.py b/test/test_proxy.py index 2babe51c..098a8d63 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -1,4 +1,5 @@ -from libmproxy import proxy, flow +import argparse +from libmproxy import proxy, flow, cmdline import tutils from libpathod import test from netlib import http, tcp @@ -59,10 +60,76 @@ class TestServerConnection: sc.terminate() -class TestProcessOptions: - def test_auth(self): - parser = mock.MagicMock() +class MockParser: + def __init__(self): + self.err = None + + def error(self, e): + self.err = e + + def __repr__(self): + return "ParseError(%s)"%self.err +class TestProcessProxyOptions: + def p(self, *args): + parser = argparse.ArgumentParser() + cmdline.common_options(parser) + opts = parser.parse_args(args=args) + m = MockParser() + return m, proxy.process_proxy_options(m, opts) + + def assert_err(self, err, *args): + m, p = self.p(*args) + assert err.lower() in m.err.lower() + + def assert_noerr(self, *args): + m, p = self.p(*args) + assert p + return p + + def test_simple(self): + assert self.p() + + def test_cert(self): + self.assert_noerr("--cert", tutils.test_data.path("data/testkey.pem")) + self.assert_err("does not exist", "--cert", "nonexistent") + + def test_confdir(self): + with tutils.tmpdir() as confdir: + self.assert_noerr("--confdir", confdir) + + @mock.patch("libmproxy.platform.resolver", None) + def test_no_transparent(self): + self.assert_err("transparent mode not supported", "-T") + + @mock.patch("libmproxy.platform.resolver") + def test_transparent_reverse(self, o): + self.assert_err("can't set both", "-P", "reverse", "-T") + self.assert_noerr("-T") + assert o.call_count == 1 + self.assert_err("invalid reverse proxy", "-P", "reverse") + self.assert_noerr("-P", "http://localhost") + + def test_certs(self): + with tutils.tmpdir() as confdir: + self.assert_noerr("--client-certs", confdir) + self.assert_err("directory does not exist", "--client-certs", "nonexistent") + + self.assert_noerr("--dummy-certs", confdir) + self.assert_err("directory does not exist", "--dummy-certs", "nonexistent") + + def test_auth(self): + p = self.assert_noerr("--nonanonymous") + assert p.authenticator + + p = self.assert_noerr("--htpasswd", tutils.test_data.path("data/htpasswd")) + assert p.authenticator + self.assert_err("invalid htpasswd file", "--htpasswd", tutils.test_data.path("data/htpasswd.invalid")) + + p = self.assert_noerr("--singleuser", "test:test") + assert p.authenticator + self.assert_err("invalid single-user specification", "--singleuser", "test") + -- cgit v1.2.3 From 2465b8a376a7eb04eef6a1cce46dd11a8f1830d8 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 3 Mar 2013 12:13:33 +1300 Subject: 100% unit test coverage on proxy.py. Hallelujah! --- test/test_proxy.py | 16 +++++++++++++++- test/test_server.py | 18 +++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/test_proxy.py b/test/test_proxy.py index 098a8d63..13feaead 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -69,7 +69,7 @@ class MockParser: def __repr__(self): return "ParseError(%s)"%self.err - + class TestProcessProxyOptions: def p(self, *args): @@ -132,4 +132,18 @@ class TestProcessProxyOptions: self.assert_err("invalid single-user specification", "--singleuser", "test") +class TestProxyServer: + def test_err(self): + parser = argparse.ArgumentParser() + cmdline.common_options(parser) + opts = parser.parse_args(args=[]) + tutils.raises("error starting proxy server", proxy.ProxyServer, opts, 1) + + +class TestDummyServer: + def test_simple(self): + d = proxy.DummyServer(None) + d.start_slave() + d.shutdown() + diff --git a/test/test_server.py b/test/test_server.py index 8a6228ad..cc1fa8ce 100644 --- a/test/test_server.py +++ b/test/test_server.py @@ -277,7 +277,7 @@ class MasterFakeResponse(tservers.TestMaster): class TestFakeResponse(tservers.HTTPProxTest): masterclass = MasterFakeResponse - def test_kill(self): + def test_fake(self): f = self.pathod("200") assert "header_response" in f.headers.keys() @@ -319,3 +319,19 @@ class TestTransparentResolveError(tservers.TransparentProxTest): def test_resolve_error(self): assert self.pathod("304").status_code == 502 + + +class MasterIncomplete(tservers.TestMaster): + def handle_request(self, m): + resp = tutils.tresp() + resp.content = flow.CONTENT_MISSING + m.reply(resp) + + +class TestIncompleteResponse(tservers.HTTPProxTest): + masterclass = MasterIncomplete + def test_incomplete(self): + assert self.pathod("200").status_code == 502 + + + -- cgit v1.2.3 From e608d10f455550b8afd09217f0ecf344a0bdc814 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 3 Mar 2013 12:26:20 +1300 Subject: Remove __slots__ to make it possible to inherit from Options classes. --- test/test_dump.py | 1 - test/test_proxy.py | 1 - 2 files changed, 2 deletions(-) (limited to 'test') diff --git a/test/test_dump.py b/test/test_dump.py index 5d3f9133..1b434f81 100644 --- a/test/test_dump.py +++ b/test/test_dump.py @@ -101,7 +101,6 @@ class TestDumpMaster: def test_options(self): o = dump.Options(verbosity = 2) assert o.verbosity == 2 - libpry.raises(AttributeError, dump.Options, nonexistent = 2) def test_filter(self): assert not "GET" in self._dummy_cycle(1, "~u foo", "", verbosity=1) diff --git a/test/test_proxy.py b/test/test_proxy.py index 13feaead..5828d077 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -146,4 +146,3 @@ class TestDummyServer: d.start_slave() d.shutdown() - -- cgit v1.2.3 From 7835e0c2c7be0e45262a06b5e2ec2399ae019977 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 3 Mar 2013 14:56:56 +1300 Subject: Begin some simple fuzzing with pathod. Finally doing what I started writing pathod for in the first place... --- test/fuzzing/go_proxy | 9 +++++++++ test/test_fuzzing.py | 12 ++++++++++++ 2 files changed, 21 insertions(+) create mode 100755 test/fuzzing/go_proxy create mode 100644 test/test_fuzzing.py (limited to 'test') diff --git a/test/fuzzing/go_proxy b/test/fuzzing/go_proxy new file mode 100755 index 00000000..1e6bbaef --- /dev/null +++ b/test/fuzzing/go_proxy @@ -0,0 +1,9 @@ +#!/bin/sh +# Assuming: +# mitmproxy/mitmdump is running on port 8080 in straight proxy mode. +# pathod is running on port 9999 + +BASE="/Users/aldo/git/public/pathod/venv/bin/pathoc -eo -I 200,400,502 -p 8080 localhost " +$BASE -n 1000 "get:'http://localhost:9999':ir,@1" + + diff --git a/test/test_fuzzing.py b/test/test_fuzzing.py new file mode 100644 index 00000000..4b4253d8 --- /dev/null +++ b/test/test_fuzzing.py @@ -0,0 +1,12 @@ +import tservers + +""" + A collection of errors turned up by fuzzing. +""" + +class TestFuzzy(tservers.HTTPProxTest): + def test_idna_err(self): + req = r'get:"http://localhost:%s":i10,"\xc6"' + p = self.pathoc() + assert p.request(req%self.server.port).status_code == 400 + -- cgit v1.2.3 From 8216801728ea2af82614025ca309a3b5db2ad982 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 3 Mar 2013 15:14:49 +1300 Subject: Three more errors turned up with fuzzing. These are fixed in netlib, regression tests added here. --- test/fuzzing/go_proxy | 4 ++-- test/test_fuzzing.py | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/fuzzing/go_proxy b/test/fuzzing/go_proxy index 1e6bbaef..5960d081 100755 --- a/test/fuzzing/go_proxy +++ b/test/fuzzing/go_proxy @@ -3,7 +3,7 @@ # mitmproxy/mitmdump is running on port 8080 in straight proxy mode. # pathod is running on port 9999 -BASE="/Users/aldo/git/public/pathod/venv/bin/pathoc -eo -I 200,400,502 -p 8080 localhost " -$BASE -n 1000 "get:'http://localhost:9999':ir,@1" +BASE="/Users/aldo/git/public/pathod/venv/bin/pathoc -eo -I 200,400,405,502 -p 8080 localhost " +$BASE -n 10000 "get:'http://localhost:9999':ir,@1" diff --git a/test/test_fuzzing.py b/test/test_fuzzing.py index 4b4253d8..857a2b10 100644 --- a/test/test_fuzzing.py +++ b/test/test_fuzzing.py @@ -1,7 +1,8 @@ import tservers """ - A collection of errors turned up by fuzzing. + A collection of errors turned up by fuzzing. Errors are integrated here + after being fixed to check for regressions. """ class TestFuzzy(tservers.HTTPProxTest): @@ -10,3 +11,17 @@ class TestFuzzy(tservers.HTTPProxTest): p = self.pathoc() assert p.request(req%self.server.port).status_code == 400 + def test_nullbytes(self): + req = r'get:"http://localhost:%s":i19,"\x00"' + p = self.pathoc() + assert p.request(req%self.server.port).status_code == 400 + + def test_invalid_ports(self): + req = 'get:"http://localhost:999999"' + p = self.pathoc() + assert p.request(req).status_code == 400 + + def test_invalid_ipv6_url(self): + req = 'get:"http://localhost:%s":i13,"["' + p = self.pathoc() + assert p.request(req%self.server.port).status_code == 400 -- cgit v1.2.3 From cde66cd58470cd68a76a9d8b1022a45e99a5cd8d Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 3 Mar 2013 22:03:27 +1300 Subject: Fuzzing, and fixes for errors found with fuzzing. --- test/fuzzing/go_proxy | 15 +++++++++++++-- test/test_dump.py | 11 +++++------ test/test_fuzzing.py | 12 ++++++++++++ test/test_server.py | 2 +- 4 files changed, 31 insertions(+), 9 deletions(-) (limited to 'test') diff --git a/test/fuzzing/go_proxy b/test/fuzzing/go_proxy index 5960d081..50588049 100755 --- a/test/fuzzing/go_proxy +++ b/test/fuzzing/go_proxy @@ -3,7 +3,18 @@ # mitmproxy/mitmdump is running on port 8080 in straight proxy mode. # pathod is running on port 9999 -BASE="/Users/aldo/git/public/pathod/venv/bin/pathoc -eo -I 200,400,405,502 -p 8080 localhost " -$BASE -n 10000 "get:'http://localhost:9999':ir,@1" +BASE_HTTP="/Users/aldo/git/public/pathod/pathoc -Tt 1 -eo -I 200,400,405,502 -p 8080 localhost " +#$BASE_HTTP -n 10000 "get:'http://localhost:9999':ir,@1" +#$BASE_HTTP -n 100 "get:'http://localhost:9999':dr" +#$BASE_HTTP -n 10000 "get:'http://localhost:9999/p/200:ir,@300.0 +# Assuming: +# mitmproxy/mitmdump is running on port 8080 in straight proxy mode. +# pathod with SSL enabled is running on port 9999 + +BASE_HTTPS="/Users/aldo/git/public/pathod/pathoc -sc localhost:9999 -Tt 1 -eo -I 200,400,404,405,502,800 -p 8080 localhost " +$BASE_HTTPS -en 10000 "get:/p/200:ir,@1" +#$BASE_HTTP -n 100 "get:/p/'200:dr'" +#$BASE_HTTPS -n 10000 "get:'/p/200:ir,@3000'" +#$BASE_HTTPS -n 10000 "get:'/p/200:ir,\"\ \n \"'" diff --git a/test/test_dump.py b/test/test_dump.py index 1b434f81..7992f78e 100644 --- a/test/test_dump.py +++ b/test/test_dump.py @@ -1,6 +1,5 @@ import os from cStringIO import StringIO -import libpry from libmproxy import dump, flow, proxy import tutils import mock @@ -65,7 +64,7 @@ class TestDumpMaster: cs = StringIO() o = dump.Options(server_replay="nonexistent", kill=True) - libpry.raises(dump.DumpError, dump.DumpMaster, None, o, None, outfile=cs) + tutils.raises(dump.DumpError, dump.DumpMaster, None, o, None, outfile=cs) with tutils.tmpdir() as t: p = os.path.join(t, "rep") @@ -90,7 +89,7 @@ class TestDumpMaster: self._flowfile(p) assert "GET" in self._dummy_cycle(0, None, "", verbosity=1, rfile=p) - libpry.raises( + tutils.raises( dump.DumpError, self._dummy_cycle, 0, None, "", verbosity=1, rfile="/nonexistent" ) @@ -130,7 +129,7 @@ class TestDumpMaster: assert len(list(flow.FlowReader(open(p)).stream())) == 1 def test_write_err(self): - libpry.raises( + tutils.raises( dump.DumpError, self._dummy_cycle, 1, @@ -148,11 +147,11 @@ class TestDumpMaster: assert "XREQUEST" in ret assert "XRESPONSE" in ret assert "XCLIENTDISCONNECT" in ret - libpry.raises( + tutils.raises( dump.DumpError, self._dummy_cycle, 1, None, "", script="nonexistent" ) - libpry.raises( + tutils.raises( dump.DumpError, self._dummy_cycle, 1, None, "", script="starterr.py" ) diff --git a/test/test_fuzzing.py b/test/test_fuzzing.py index 857a2b10..ba7b751c 100644 --- a/test/test_fuzzing.py +++ b/test/test_fuzzing.py @@ -25,3 +25,15 @@ class TestFuzzy(tservers.HTTPProxTest): req = 'get:"http://localhost:%s":i13,"["' p = self.pathoc() assert p.request(req%self.server.port).status_code == 400 + + def test_invalid_upstream(self): + req = r"get:'http://localhost:%s/p/200:i10,\'+\''" + p = self.pathoc() + assert p.request(req%self.server.port).status_code == 502 + + def test_upstream_disconnect(self): + req = r'200:d0:h"Date"="Sun, 03 Mar 2013 04:00:00 GMT"' + p = self.pathod(req) + assert p.status_code == 400 + + diff --git a/test/test_server.py b/test/test_server.py index cc1fa8ce..f12fbcee 100644 --- a/test/test_server.py +++ b/test/test_server.py @@ -185,7 +185,7 @@ class TestHTTPSNoUpstream(tservers.HTTPProxTest, CommonMixin): no_upstream_cert = True def test_cert_gen_error(self): f = self.pathoc_raw() - f.connect((u"\u2102\u0001".encode("utf8"), 0)) + f.connect((u"foo..bar".encode("utf8"), 0)) f.request("get:/") assert "dummy cert" in "".join(self.proxy.log) -- cgit v1.2.3 From 8a850dc8e608686a09b02de98dd3b664947c71f3 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 3 Mar 2013 22:39:26 +1300 Subject: Few more fuzzing commands, exclude console app from coverage. --- test/fuzzing/go_proxy | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/fuzzing/go_proxy b/test/fuzzing/go_proxy index 50588049..c9b6aef6 100755 --- a/test/fuzzing/go_proxy +++ b/test/fuzzing/go_proxy @@ -14,7 +14,9 @@ BASE_HTTP="/Users/aldo/git/public/pathod/pathoc -Tt 1 -eo -I 200,400,405,502 -p # pathod with SSL enabled is running on port 9999 BASE_HTTPS="/Users/aldo/git/public/pathod/pathoc -sc localhost:9999 -Tt 1 -eo -I 200,400,404,405,502,800 -p 8080 localhost " -$BASE_HTTPS -en 10000 "get:/p/200:ir,@1" -#$BASE_HTTP -n 100 "get:/p/'200:dr'" +$BASE_HTTPS -en 10000 "get:'/p/200:b@10:ir,@1'" +#$BASE_HTTPS -en 10000 "get:'/p/200:ir,@1'" + +#$BASE_HTTPS -n 100 "get:'/p/200:dr'" #$BASE_HTTPS -n 10000 "get:'/p/200:ir,@3000'" -#$BASE_HTTPS -n 10000 "get:'/p/200:ir,\"\ \n \"'" +#$BASE_HTTPS -n 10000 "get:'/p/200:ir,\"\\n\"'" -- cgit v1.2.3 From cfb5ba89ce96594b2f8d51f27c9b2ee41ecf18e5 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Thu, 14 Mar 2013 09:19:43 +1300 Subject: Introduce a filtered flow writer, and use it in dump.py Fixes #104 --- test/test_flow.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/test_flow.py b/test/test_flow.py index 6aa898ad..c1ae1a9f 100644 --- a/test/test_flow.py +++ b/test/test_flow.py @@ -497,6 +497,23 @@ class TestSerialize: fm = flow.FlowMaster(None, s) fm.load_flows(r) assert len(s._flow_list) == 6 + + def test_filter(self): + sio = StringIO() + fl = filt.parse("~c 200") + w = flow.FilteredFlowWriter(sio, fl) + + f = tutils.tflow_full() + f.response.code = 200 + w.add(f) + + f = tutils.tflow_full() + f.response.code = 201 + w.add(f) + + sio.seek(0) + r = flow.FlowReader(sio) + assert len(list(r.stream())) def test_error(self): @@ -723,7 +740,7 @@ class TestFlowMaster: fm = flow.FlowMaster(None, s) tf = tutils.tflow_full() - fm.start_stream(file(p, "ab")) + fm.start_stream(file(p, "ab"), None) fm.handle_request(tf.request) fm.handle_response(tf.response) fm.stop_stream() @@ -731,7 +748,7 @@ class TestFlowMaster: assert r()[0].response tf = tutils.tflow_full() - fm.start_stream(file(p, "ab")) + fm.start_stream(file(p, "ab"), None) fm.handle_request(tf.request) fm.shutdown() -- cgit v1.2.3 From 0e993bec6f7fa77e73a08053f4558ff1fc36d022 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 17 Mar 2013 17:31:35 +1300 Subject: Add the --host option, which uses the value in the Host header for dispaly URLs. - Can be toggled with "o" then "h" in mitmproxy - Useful for transparent mode --- test/test_console_common.py | 10 ++++++++++ test/test_flow.py | 13 ++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 test/test_console_common.py (limited to 'test') diff --git a/test/test_console_common.py b/test/test_console_common.py new file mode 100644 index 00000000..29bf7b84 --- /dev/null +++ b/test/test_console_common.py @@ -0,0 +1,10 @@ +import libmproxy.console.common as common +from libmproxy import utils, flow, encoding +import tutils + + +def test_format_flow(): + f = tutils.tflow_full() + assert common.format_flow(f, True) + assert common.format_flow(f, True, hostheader=True) + assert common.format_flow(f, True, extended=True) diff --git a/test/test_flow.py b/test/test_flow.py index c1ae1a9f..fce4e98a 100644 --- a/test/test_flow.py +++ b/test/test_flow.py @@ -497,7 +497,7 @@ class TestSerialize: fm = flow.FlowMaster(None, s) fm.load_flows(r) assert len(s._flow_list) == 6 - + def test_filter(self): sio = StringIO() fl = filt.parse("~c 200") @@ -783,6 +783,17 @@ class TestRequest: r.content = flow.CONTENT_MISSING assert not r._assemble() + def test_get_url(self): + h = flow.ODictCaseless() + h["test"] = ["test"] + c = flow.ClientConnect(("addr", 2222)) + r = flow.Request(c, (1, 1), "host", 22, "https", "GET", "/", h, "content") + assert r.get_url() == "https://host:22/" + assert r.get_url(hostheader=True) == "https://host:22/" + r.headers["Host"] = ["foo.com"] + assert r.get_url() == "https://host:22/" + assert r.get_url(hostheader=True) == "https://foo.com:22/" + def test_path_components(self): h = flow.ODictCaseless() c = flow.ClientConnect(("addr", 2222)) -- cgit v1.2.3 From d2d3eb6490a6b342f8d205e26d04c913b8e2a5f7 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Sun, 17 Mar 2013 17:53:39 +1300 Subject: Un-break unit tests. Tsk tsk. --- test/test_dump.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/test_dump.py b/test/test_dump.py index 7992f78e..94d0b195 100644 --- a/test/test_dump.py +++ b/test/test_dump.py @@ -12,8 +12,10 @@ def test_strfuncs(): t = tutils.treq() t.client_conn = None t.stickycookie = True - assert "stickycookie" in dump.str_request(t) - assert "replay" in dump.str_request(t) + assert "stickycookie" in dump.str_request(t, False) + assert "stickycookie" in dump.str_request(t, True) + assert "replay" in dump.str_request(t, False) + assert "replay" in dump.str_request(t, True) class TestDumpMaster: -- cgit v1.2.3