From 79f464bc78faadcc3a913a395d9cb28f9d5f676c Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Tue, 19 Oct 2021 13:25:22 +0200 Subject: [PATCH] ignore superfluous newlines after HTTP CONNECT, fix #4870 (#4871) --- mitmproxy/proxy/layers/http/__init__.py | 4 ++-- mitmproxy/proxy/layers/http/_http1.py | 5 ++++- test/mitmproxy/proxy/layers/http/test_http.py | 20 +++++++++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/mitmproxy/proxy/layers/http/__init__.py b/mitmproxy/proxy/layers/http/__init__.py index af631fe5d..319b394e8 100644 --- a/mitmproxy/proxy/layers/http/__init__.py +++ b/mitmproxy/proxy/layers/http/__init__.py @@ -592,11 +592,11 @@ class HttpStream(layer.Layer): ) if 200 <= self.flow.response.status_code < 300: - yield SendHttp(ResponseHeaders(self.stream_id, self.flow.response, True), self.context.client) - yield SendHttp(ResponseEndOfMessage(self.stream_id), self.context.client) self.child_layer = self.child_layer or layer.NextLayer(self.context) yield from self.child_layer.handle_event(events.Start()) self._handle_event = self.passthrough + yield SendHttp(ResponseHeaders(self.stream_id, self.flow.response, True), self.context.client) + yield SendHttp(ResponseEndOfMessage(self.stream_id), self.context.client) else: yield from self.send_response() diff --git a/mitmproxy/proxy/layers/http/_http1.py b/mitmproxy/proxy/layers/http/_http1.py index 50cfd7fd3..3fff8faea 100644 --- a/mitmproxy/proxy/layers/http/_http1.py +++ b/mitmproxy/proxy/layers/http/_http1.py @@ -122,7 +122,10 @@ class Http1Connection(HttpConnection, metaclass=abc.ABCMeta): self.state = self.passthrough if self.buf: already_received = self.buf.maybe_extract_at_most(len(self.buf)) - yield from self.state(events.DataReceived(self.conn, already_received)) + # Some clients send superfluous newlines after CONNECT, we want to eat those. + already_received = already_received.lstrip(b"\r\n") + if already_received: + yield from self.state(events.DataReceived(self.conn, already_received)) def passthrough(self, event: events.Event) -> layer.CommandGenerator[None]: assert self.stream_id diff --git a/test/mitmproxy/proxy/layers/http/test_http.py b/test/mitmproxy/proxy/layers/http/test_http.py index 4077b196c..619ced6d6 100644 --- a/test/mitmproxy/proxy/layers/http/test_http.py +++ b/test/mitmproxy/proxy/layers/http/test_http.py @@ -1324,3 +1324,23 @@ def test_chunked_and_content_length_set_by_addon(tctx): b"Transfer-Encoding: chunked\r\n\r\n" b"0\r\n\r\n") ) + + +def test_connect_more_newlines(tctx): + """Ignore superfluous \r\n in CONNECT request, https://github.com/mitmproxy/mitmproxy/issues/4870""" + server = Placeholder(Server) + playbook = Playbook(http.HttpLayer(tctx, HTTPMode.regular)) + nl = Placeholder(layer.NextLayer) + + assert ( + playbook + >> DataReceived(tctx.client, b"CONNECT example.com:80 HTTP/1.1\r\n\r\n\r\n") + << http.HttpConnectHook(Placeholder()) + >> reply() + << OpenConnection(server) + >> reply(None) + << SendData(tctx.client, b'HTTP/1.1 200 Connection established\r\n\r\n') + >> DataReceived(tctx.client, b"\x16\x03\x03\x00\xb3\x01\x00\x00\xaf\x03\x03") + << layer.NextLayerHook(nl) + ) + assert nl().data_client() == b"\x16\x03\x03\x00\xb3\x01\x00\x00\xaf\x03\x03"