aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaximilian Hils <git@maximilianhils.com>2016-05-10 12:17:25 -0600
committerMaximilian Hils <git@maximilianhils.com>2016-05-10 12:17:25 -0600
commitf315dc1eb9f4701548fd57bbb38de1e9caa34e40 (patch)
treee4888dc4c413ce86cbb66d1b5822303b25571ea4
parent595a01de4e141eb494c2f698e3177c24071ca461 (diff)
downloadmitmproxy-f315dc1eb9f4701548fd57bbb38de1e9caa34e40.tar.gz
mitmproxy-f315dc1eb9f4701548fd57bbb38de1e9caa34e40.tar.bz2
mitmproxy-f315dc1eb9f4701548fd57bbb38de1e9caa34e40.zip
fix tests
-rw-r--r--mitmproxy/flow.py50
-rw-r--r--mitmproxy/models/__init__.py5
-rw-r--r--mitmproxy/models/flow.py9
-rw-r--r--mitmproxy/models/http.py6
-rw-r--r--mitmproxy/protocol/rawtcp.py61
-rw-r--r--mitmproxy/proxy/root_context.py2
-rw-r--r--test/netlib/http/test_request.py4
7 files changed, 84 insertions, 53 deletions
diff --git a/mitmproxy/flow.py b/mitmproxy/flow.py
index 9292e76a..9e6d3f89 100644
--- a/mitmproxy/flow.py
+++ b/mitmproxy/flow.py
@@ -16,12 +16,13 @@ import re
from netlib import wsgi
from netlib.exceptions import HttpException
from netlib.http import Headers, http1
+from netlib.utils import clean_bin
from . import controller, tnetstring, filt, script, version, flow_format_compat
from .onboarding import app
from .proxy.config import HostMatcher
from .protocol.http_replay import RequestReplayThread
from .exceptions import Kill, FlowReadException
-from .models import ClientConnection, ServerConnection, HTTPFlow, HTTPRequest, FLOW_TYPES
+from .models import ClientConnection, ServerConnection, HTTPFlow, HTTPRequest, FLOW_TYPES, TCPFlow
from collections import defaultdict
@@ -892,6 +893,17 @@ class FlowMaster(controller.ServerMaster):
self.handle_response(f)
if f.error:
self.handle_error(f)
+ elif isinstance(f, TCPFlow):
+ messages = f.messages
+ f.messages = []
+ f.reply = controller.DummyReply()
+ self.handle_tcp_open(f)
+ while messages:
+ f.messages.append(messages.pop(0))
+ self.handle_tcp_message(f)
+ if f.error:
+ self.handle_tcp_error(f)
+ self.handle_tcp_close(f)
else:
raise NotImplementedError()
@@ -1079,9 +1091,39 @@ class FlowMaster(controller.ServerMaster):
self.add_event('"{}" reloaded.'.format(s.filename), 'info')
return ok
- def handle_tcp_message(self, m):
- self.run_script_hook("tcp_message", m)
- m.reply()
+ def handle_tcp_open(self, flow):
+ self.state.add_flow(flow)
+ self.run_script_hook("tcp_open", flow)
+ flow.reply()
+
+ def handle_tcp_message(self, flow):
+ self.run_script_hook("tcp_message", flow)
+ message = flow.messages[-1]
+ direction = "->" if message.from_client else "<-"
+ self.add_event("{client} {direction} tcp {direction} {server}".format(
+ client=repr(flow.client_conn.address),
+ server=repr(flow.server_conn.address),
+ direction=direction,
+ ), "info")
+ self.add_event(clean_bin(message.content), "debug")
+ flow.reply()
+
+ def handle_tcp_error(self, flow):
+ if self.stream:
+ self.stream.add(flow)
+ self.add_event("Error in TCP connection to {}: {}".format(
+ repr(flow.server_conn.address),
+ flow.error
+ ), "info")
+ self.run_script_hook("tcp_error", flow)
+ flow.reply()
+
+ def handle_tcp_close(self, flow):
+ self.state.delete_flow(flow)
+ if self.stream:
+ self.stream.add(flow)
+ self.run_script_hook("tcp_close", flow)
+ flow.reply()
def shutdown(self):
super(FlowMaster, self).shutdown()
diff --git a/mitmproxy/models/__init__.py b/mitmproxy/models/__init__.py
index df86eff4..3d9d9dae 100644
--- a/mitmproxy/models/__init__.py
+++ b/mitmproxy/models/__init__.py
@@ -7,9 +7,11 @@ from .http import (
from netlib.http import decoded
from .connections import ClientConnection, ServerConnection
from .flow import Flow, Error
+from .tcp import TCPFlow
FLOW_TYPES = dict(
- http=HTTPFlow
+ http=HTTPFlow,
+ tcp=TCPFlow,
)
__all__ = [
@@ -18,5 +20,6 @@ __all__ = [
"make_connect_response", "expect_continue_response",
"ClientConnection", "ServerConnection",
"Flow", "Error",
+ "TCPFlow"
"FLOW_TYPES"
]
diff --git a/mitmproxy/models/flow.py b/mitmproxy/models/flow.py
index 594147ec..1019c9fb 100644
--- a/mitmproxy/models/flow.py
+++ b/mitmproxy/models/flow.py
@@ -40,6 +40,9 @@ class Error(stateobject.StateObject):
def __str__(self):
return self.msg
+ def __repr__(self):
+ return self.msg
+
@classmethod
def from_state(cls, state):
# the default implementation assumes an empty constructor. Override
@@ -99,6 +102,12 @@ class Flow(stateobject.StateObject):
self._backup = state.pop("backup")
super(Flow, self).set_state(state)
+ @classmethod
+ def from_state(cls, state):
+ f = cls(None, None)
+ f.set_state(state)
+ return f
+
def copy(self):
f = copy.copy(self)
diff --git a/mitmproxy/models/http.py b/mitmproxy/models/http.py
index 77a809cf..75ffbfd0 100644
--- a/mitmproxy/models/http.py
+++ b/mitmproxy/models/http.py
@@ -191,12 +191,6 @@ class HTTPFlow(Flow):
response=HTTPResponse
)
- @classmethod
- def from_state(cls, state):
- f = cls(None, None)
- f.set_state(state)
- return f
-
def __repr__(self):
s = "<HTTPFlow"
for a in ("request", "response", "error", "client_conn", "server_conn"):
diff --git a/mitmproxy/protocol/rawtcp.py b/mitmproxy/protocol/rawtcp.py
index 7d18025e..5f6fca75 100644
--- a/mitmproxy/protocol/rawtcp.py
+++ b/mitmproxy/protocol/rawtcp.py
@@ -9,29 +9,26 @@ from netlib.exceptions import TcpException
from netlib.tcp import ssl_read_select
from netlib.utils import clean_bin
from ..exceptions import ProtocolException
-from .base import Layer
-
+from ..models import Error
+from ..models.tcp import TCPFlow, TCPMessage
-class TcpMessage(object):
-
- def __init__(self, client_conn, server_conn, sender, receiver, message):
- self.client_conn = client_conn
- self.server_conn = server_conn
- self.sender = sender
- self.receiver = receiver
- self.message = message
+from .base import Layer
class RawTCPLayer(Layer):
chunk_size = 4096
- def __init__(self, ctx, logging=True):
- self.logging = logging
+ def __init__(self, ctx, ignore=False):
+ self.ignore = ignore
super(RawTCPLayer, self).__init__(ctx)
def __call__(self):
self.connect()
+ if not self.ignore:
+ flow = TCPFlow(self.client_conn, self.server_conn, self)
+ self.channel.ask("tcp_open", flow)
+
buf = memoryview(bytearray(self.chunk_size))
client = self.client_conn.connection
@@ -51,38 +48,24 @@ class RawTCPLayer(Layer):
if isinstance(conn, SSL.Connection):
# We can't half-close a connection, so we just close everything here.
# Sockets will be cleaned up on a higher level.
- return
+ break
else:
dst.shutdown(socket.SHUT_WR)
if len(conns) == 0:
- return
+ break
continue
- tcp_message = TcpMessage(
- self.client_conn, self.server_conn,
- self.client_conn if dst == server else self.server_conn,
- self.server_conn if dst == server else self.client_conn,
- buf[:size].tobytes())
- self.channel.ask("tcp_message", tcp_message)
- dst.sendall(tcp_message.message)
-
- if self.logging:
- # log messages are prepended with the client address,
- # hence the "weird" direction string.
- if dst == server:
- direction = "-> tcp -> {}".format(repr(self.server_conn.address))
- else:
- direction = "<- tcp <- {}".format(repr(self.server_conn.address))
- data = clean_bin(tcp_message.message)
- self.log(
- "{}\r\n{}".format(direction, data),
- "info"
- )
+ tcp_message = TCPMessage(dst == server, buf[:size].tobytes())
+ if not self.ignore:
+ flow.messages.append(tcp_message)
+ self.channel.ask("tcp_message", flow)
+ dst.sendall(tcp_message.content)
except (socket.error, TcpException, SSL.Error) as e:
- six.reraise(
- ProtocolException,
- ProtocolException("TCP connection closed unexpectedly: {}".format(repr(e))),
- sys.exc_info()[2]
- )
+ if not self.ignore:
+ flow.error = Error("TCP connection closed unexpectedly: {}".format(repr(e)))
+ self.channel.tell("tcp_error", flow)
+ finally:
+ if not self.ignore:
+ self.channel.tell("tcp_close", flow)
diff --git a/mitmproxy/proxy/root_context.py b/mitmproxy/proxy/root_context.py
index 9caae02a..21478dfd 100644
--- a/mitmproxy/proxy/root_context.py
+++ b/mitmproxy/proxy/root_context.py
@@ -65,7 +65,7 @@ class RootContext(object):
else:
ignore = self.config.check_ignore((client_hello.client_sni, 443))
if ignore:
- return RawTCPLayer(top_layer, logging=False)
+ return RawTCPLayer(top_layer, ignore=True)
# 2. Always insert a TLS layer, even if there's neither client nor server tls.
# An inline script may upgrade from http to https,
diff --git a/test/netlib/http/test_request.py b/test/netlib/http/test_request.py
index 91fd8ce3..d57dca13 100644
--- a/test/netlib/http/test_request.py
+++ b/test/netlib/http/test_request.py
@@ -108,7 +108,7 @@ class TestRequestUtils(object):
request.url = "not-a-url"
def test_url_options(self):
- request = treq(method="OPTIONS", path="*")
+ request = treq(method=b"OPTIONS", path=b"*")
assert request.url == "http://address:22"
def test_url_authority(self):
@@ -149,7 +149,7 @@ class TestRequestUtils(object):
assert request.pretty_url == "http://address:22/path"
def test_pretty_url_options(self):
- request = treq(method="OPTIONS", path="*")
+ request = treq(method=b"OPTIONS", path=b"*")
assert request.pretty_url == "http://address:22"
def test_pretty_url_authority(self):