From b23a1aa4a4dd9f09fc199d03f546a8fafc8b27b8 Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Thu, 4 Sep 2014 19:08:54 +0200 Subject: [PATCH] much tests. so tcp. very wow. --- libmproxy/flow.py | 3 ++- libmproxy/stateobject.py | 3 +++ test/test_protocol_http.py | 3 +++ test/test_protocol_tcp.py | 21 ----------------- test/test_proxy.py | 9 ++++++++ test/test_server.py | 47 ++++++++++++++++++++++++++++++++++---- test/tservers.py | 23 ------------------- 7 files changed, 59 insertions(+), 50 deletions(-) delete mode 100644 test/test_protocol_tcp.py diff --git a/libmproxy/flow.py b/libmproxy/flow.py index eeb53e81a..086710bc5 100644 --- a/libmproxy/flow.py +++ b/libmproxy/flow.py @@ -612,6 +612,7 @@ class FlowMaster(controller.Master): if f.request: self.handle_request(f) if f.response: + self.handle_responseheaders(f) self.handle_response(f) if f.error: self.handle_error(f) @@ -668,7 +669,7 @@ class FlowMaster(controller.Master): self.masterq, self.should_exit ) - rt.start() # pragma: no cover + rt.start() # pragma: no cover if block: rt.join() diff --git a/libmproxy/stateobject.py b/libmproxy/stateobject.py index 3437b90ec..6fb73c24b 100644 --- a/libmproxy/stateobject.py +++ b/libmproxy/stateobject.py @@ -21,6 +21,9 @@ class StateObject(object): except AttributeError: # we may compare with something that's not a StateObject return False + def __ne__(self, other): + return not self.__eq__(other) + class SimpleStateObject(StateObject): """ diff --git a/test/test_protocol_http.py b/test/test_protocol_http.py index bcbdd5d02..3ca590f1b 100644 --- a/test/test_protocol_http.py +++ b/test/test_protocol_http.py @@ -49,6 +49,9 @@ class TestHTTPRequest: raw = r._assemble_headers() assert "Host" in raw + assert not "Host" in r.headers + r.update_host_header() + assert "Host" in r.headers def test_authority_form(self): diff --git a/test/test_protocol_tcp.py b/test/test_protocol_tcp.py deleted file mode 100644 index 8b6bb68d7..000000000 --- a/test/test_protocol_tcp.py +++ /dev/null @@ -1,21 +0,0 @@ -import tservers -from netlib.certutils import SSLCert - -class TestTcp(tservers.IgnoreProxTest): - ignore = [] - - def test_simple(self): - # i = ignore (tcp passthrough), n = normal - pi, pn = self.pathocs() - i = pi.request("get:'/p/304'") - i2 = pi.request("get:'/p/304'") - n = pn.request("get:'/p/304'") - - assert i.status_code == i2.status_code == n.status_code == 304 - - i_cert = SSLCert(i.sslinfo.certchain[0]) - i2_cert = SSLCert(i2.sslinfo.certchain[0]) - n_cert = SSLCert(n.sslinfo.certchain[0]) - - assert i_cert == i2_cert - assert not i_cert == n_cert \ No newline at end of file diff --git a/test/test_proxy.py b/test/test_proxy.py index f762e6100..e65841f44 100644 --- a/test/test_proxy.py +++ b/test/test_proxy.py @@ -42,6 +42,15 @@ class TestServerConnection: sc.connection.flush = mock.Mock(side_effect=tcp.NetLibDisconnect) sc.finish() + def test_repr(self): + sc = tutils.tserver_conn() + assert "address:22" in repr(sc) + assert "ssl" not in repr(sc) + sc.ssl_established = True + assert "ssl" in repr(sc) + sc.sni = "foo" + assert "foo" in repr(sc) + class TestProcessProxyOptions: def p(self, *args): diff --git a/test/test_server.py b/test/test_server.py index ed5133cb1..a3fff0f16 100644 --- a/test/test_server.py +++ b/test/test_server.py @@ -1,7 +1,9 @@ import socket, time import mock +from libmproxy.proxy.config import ProxyConfig from netlib import tcp, http_auth, http from libpathod import pathoc, pathod +from netlib.certutils import SSLCert import tutils, tservers from libmproxy import flow from libmproxy.protocol import KILL @@ -55,6 +57,42 @@ class CommonMixin: line = t.rfile.readline() assert ("Bad Request" in line) or ("Bad Gateway" in line) +class TcpMixin: + def _ignore_on(self): + conf = ProxyConfig(ignore=[".+:%s" % self.server.port]) + self.config.ignore.append(conf.ignore[0]) + + def _ignore_off(self): + self.config.ignore.pop() + + def test_ignore(self): + spec = '304:h"Alternate-Protocol"="mitmproxy-will-remove-this"' + n = self.pathod(spec) + self._ignore_on() + i = self.pathod(spec) + i2 = self.pathod(spec) + self._ignore_off() + + assert i.status_code == i2.status_code == n.status_code == 304 + assert "Alternate-Protocol" in i.headers + assert "Alternate-Protocol" in i2.headers + assert "Alternate-Protocol" not in n.headers + + # Test that we get the original SSL cert + if self.ssl: + i_cert = SSLCert(i.sslinfo.certchain[0]) + i2_cert = SSLCert(i2.sslinfo.certchain[0]) + n_cert = SSLCert(n.sslinfo.certchain[0]) + + assert i_cert == i2_cert + assert i_cert != n_cert + + # Test Non-HTTP traffic + spec = "200:i0,@100:d0" # this results in just 100 random bytes + assert self.pathod(spec).status_code == 502 # mitmproxy responds with bad gateway + self._ignore_on() + tutils.raises("invalid server response", self.pathod, spec) # pathoc tries to parse answer as HTTP + self._ignore_off() class AppMixin: @@ -64,7 +102,6 @@ class AppMixin: assert "mitmproxy" in ret.content - class TestHTTP(tservers.HTTPProxTest, CommonMixin, AppMixin): def test_app_err(self): p = self.pathoc() @@ -175,7 +212,7 @@ class TestHTTPConnectSSLError(tservers.HTTPProxTest): tutils.raises("502 - Bad Gateway", p.http_connect, dst) -class TestHTTPS(tservers.HTTPProxTest, CommonMixin): +class TestHTTPS(tservers.HTTPProxTest, CommonMixin, TcpMixin): ssl = True ssloptions = pathod.SSLOptions(request_client_cert=True) clientcerts = True @@ -217,15 +254,15 @@ class TestHTTPSNoCommonName(tservers.HTTPProxTest): assert f.sslinfo.certchain[0].get_subject().CN == "127.0.0.1" -class TestReverse(tservers.ReverseProxTest, CommonMixin): +class TestReverse(tservers.ReverseProxTest, CommonMixin, TcpMixin): reverse = True -class TestTransparent(tservers.TransparentProxTest, CommonMixin): +class TestTransparent(tservers.TransparentProxTest, CommonMixin, TcpMixin): ssl = False -class TestTransparentSSL(tservers.TransparentProxTest, CommonMixin): +class TestTransparentSSL(tservers.TransparentProxTest, CommonMixin, TcpMixin): ssl = True def test_sni(self): f = self.pathod("304", sni="testserver.com") diff --git a/test/tservers.py b/test/tservers.py index 91743903e..9f2abbe1a 100644 --- a/test/tservers.py +++ b/test/tservers.py @@ -263,29 +263,6 @@ class ReverseProxTest(ProxTestBase): return p.request(q) -class IgnoreProxTest(ProxTestBase): - ssl = True - - @classmethod - def get_proxy_config(cls): - d = super(IgnoreProxTest, cls).get_proxy_config() - d["ignore"] = [".+:%s" % cls.server.port] # ignore by port - return d - - def pathoc_raw(self): - return libpathod.pathoc.Pathoc(("127.0.0.1", self.proxy.port), ssl=self.ssl) - - def pathocs(self): - """ - Returns a (pathod_ignore, pathoc_normal) tuple. - """ - p_ignore = self.pathoc_raw() - p_ignore.connect(("127.0.0.1", self.server.port)) - p_normal = self.pathoc_raw() - p_normal.connect(("127.0.0.1", self.server2.port)) - return p_ignore, p_normal - - class ChainProxTest(ProxTestBase): """ Chain n instances of mitmproxy in a row - because we can.