aboutsummaryrefslogtreecommitdiffstats
path: root/libmproxy/protocol2
diff options
context:
space:
mode:
authorMaximilian Hils <git@maximilianhils.com>2015-08-11 20:27:34 +0200
committerMaximilian Hils <git@maximilianhils.com>2015-08-11 20:32:14 +0200
commitaef3b626a70de5f385c8f5496c2e49575b5c3e1c (patch)
tree868b8786906eb7bdc1a269b64494594c5831b54b /libmproxy/protocol2
parent026330a3b014f24f095b839b29186036854de3bc (diff)
downloadmitmproxy-aef3b626a70de5f385c8f5496c2e49575b5c3e1c.tar.gz
mitmproxy-aef3b626a70de5f385c8f5496c2e49575b5c3e1c.tar.bz2
mitmproxy-aef3b626a70de5f385c8f5496c2e49575b5c3e1c.zip
wip commit
Diffstat (limited to 'libmproxy/protocol2')
-rw-r--r--libmproxy/protocol2/__init__.py12
-rw-r--r--libmproxy/protocol2/auto.py20
-rw-r--r--libmproxy/protocol2/http.py90
-rw-r--r--libmproxy/protocol2/http_protocol_mock.py13
-rw-r--r--libmproxy/protocol2/http_proxy.py (renamed from libmproxy/protocol2/upstream_proxy.py)15
-rw-r--r--libmproxy/protocol2/layer.py17
-rw-r--r--libmproxy/protocol2/root_context.py32
-rw-r--r--libmproxy/protocol2/socks_proxy.py (renamed from libmproxy/protocol2/socks.py)6
-rw-r--r--libmproxy/protocol2/tls.py4
-rw-r--r--libmproxy/protocol2/transparent_proxy.py3
10 files changed, 158 insertions, 54 deletions
diff --git a/libmproxy/protocol2/__init__.py b/libmproxy/protocol2/__init__.py
index 0d232b13..e3f06ad7 100644
--- a/libmproxy/protocol2/__init__.py
+++ b/libmproxy/protocol2/__init__.py
@@ -1,8 +1,10 @@
from __future__ import (absolute_import, print_function, division)
-from .layer import RootContext
-from .socks import Socks5IncomingLayer
+from .root_context import RootContext
+from .socks_proxy import Socks5Proxy
from .reverse_proxy import ReverseProxy
-from .upstream_proxy import UpstreamProxy
+from .http_proxy import HttpProxy, HttpUpstreamProxy
from .rawtcp import TcpLayer
-from .auto import AutoLayer
-__all__ = ["Socks5IncomingLayer", "TcpLayer", "AutoLayer", "RootContext", "ReverseProxy", "UpstreamProxy"]
+
+__all__ = [
+ "Socks5Proxy", "TcpLayer", "RootContext", "ReverseProxy", "HttpProxy", "HttpUpstreamProxy"
+]
diff --git a/libmproxy/protocol2/auto.py b/libmproxy/protocol2/auto.py
deleted file mode 100644
index 4a930720..00000000
--- a/libmproxy/protocol2/auto.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from __future__ import (absolute_import, print_function, division)
-from .layer import Layer
-
-
-class AutoLayer(Layer):
- def __call__(self):
- d = self.client_conn.rfile.peek(1)
-
- if not d:
- return
- # TLS ClientHello magic, see http://www.moserware.com/2009/06/first-few-milliseconds-of-https.html#client-hello
- if d[0] == "\x16":
- layer = TlsLayer(self, True, True)
- else:
- layer = TcpLayer(self)
- for m in layer():
- yield m
-
-from .rawtcp import TcpLayer
-from .tls import TlsLayer
diff --git a/libmproxy/protocol2/http.py b/libmproxy/protocol2/http.py
new file mode 100644
index 00000000..54cc9dbc
--- /dev/null
+++ b/libmproxy/protocol2/http.py
@@ -0,0 +1,90 @@
+from __future__ import (absolute_import, print_function, division)
+
+from .layer import Layer, ServerConnectionMixin
+from libmproxy import version
+from libmproxy.exceptions import InvalidCredentials
+from libmproxy.protocol.http import HTTPFlow
+from libmproxy.protocol.http_wrappers import HTTPResponse
+from libmproxy.protocol2.http_protocol_mock import HTTP1
+from netlib import tcp
+from netlib.http import status_codes
+from netlib import odict
+
+
+def send_http_error_response(status_code, message, headers=odict.ODictCaseless()):
+ response = status_codes.RESPONSES.get(status_code, "Unknown")
+ body = """
+ <html>
+ <head>
+ <title>%d %s</title>
+ </head>
+ <body>%s</body>
+ </html>
+ """.strip() % (status_code, response, message)
+
+ headers["Server"] = [version.NAMEVERSION]
+ headers["Connection"] = ["close"]
+ headers["Content-Length"] = [len(body)]
+ headers["Content-Type"] = ["text/html"]
+
+ resp = HTTPResponse(
+ (1, 1), # if HTTP/2 is used, this value is ignored anyway
+ status_code,
+ response,
+ headers,
+ body,
+ )
+
+ protocol = self.c.client_conn.protocol or http1.HTTP1Protocol(self.c.client_conn)
+ self.c.client_conn.send(protocol.assemble(resp))
+
+class HttpLayer(Layer, ServerConnectionMixin):
+ """
+ HTTP 1 Layer
+ """
+
+ def __init__(self, ctx):
+ super(HttpLayer, self).__init__(ctx)
+ self.skip_authentication = False
+
+ def __call__(self):
+ while True:
+ flow = HTTPFlow(self.client_conn, self.server_conn)
+ try:
+ request = HTTP1.read_request(
+ self.client_conn,
+ body_size_limit=self.c.config.body_size_limit
+ )
+ except tcp.NetLibError:
+ # don't throw an error for disconnects that happen
+ # before/between requests.
+ return
+
+ self.c.log("request", "debug", [repr(request)])
+
+ self.check_authentication(request)
+
+ if self.mode == "regular" and request.form_in == "authority":
+ raise NotImplementedError
+
+
+
+ ret = self.process_request(flow, request)
+ if ret is True:
+ continue
+ if ret is False:
+ return
+
+ def check_authentication(self, request):
+ if self.config.authenticator:
+ if self.config.authenticator.authenticate(request.headers):
+ self.config.authenticator.clean(request.headers)
+ else:
+ self.send_error()
+ raise InvalidCredentials("Proxy Authentication Required")
+ raise http.HttpAuthenticationError(
+ self.c.config.authenticator.auth_challenge_headers())
+ return request.headers
+
+ def send_error(self, code, message, headers):
+ pass \ No newline at end of file
diff --git a/libmproxy/protocol2/http_protocol_mock.py b/libmproxy/protocol2/http_protocol_mock.py
new file mode 100644
index 00000000..962a76d6
--- /dev/null
+++ b/libmproxy/protocol2/http_protocol_mock.py
@@ -0,0 +1,13 @@
+"""
+Temporary mock to sort out API discrepancies
+"""
+from netlib.http.http1 import HTTP1Protocol
+
+
+class HTTP1(object):
+ @staticmethod
+ def read_request(connection, *args, **kwargs):
+ """
+ :type connection: object
+ """
+ return HTTP1Protocol(connection).read_request(*args, **kwargs) \ No newline at end of file
diff --git a/libmproxy/protocol2/upstream_proxy.py b/libmproxy/protocol2/http_proxy.py
index bd920309..6b3b6a82 100644
--- a/libmproxy/protocol2/upstream_proxy.py
+++ b/libmproxy/protocol2/http_proxy.py
@@ -1,18 +1,23 @@
from __future__ import (absolute_import, print_function, division)
from .layer import Layer, ServerConnectionMixin
-#from .http import HttpLayer
+from .http import HttpLayer
-class UpstreamProxy(Layer, ServerConnectionMixin):
+class HttpProxy(Layer):
+ def __call__(self):
+ layer = HttpLayer(self)
+ for message in layer():
+ yield message
+
+class HttpUpstreamProxy(Layer, ServerConnectionMixin):
def __init__(self, ctx, server_address):
- super(UpstreamProxy, self).__init__(ctx)
+ super(HttpUpstreamProxy, self).__init__(ctx)
self.server_address = server_address
def __call__(self):
- #layer = HttpLayer(self)
- layer = None
+ layer = HttpLayer(self)
for message in layer():
if not self._handle_server_message(message):
yield message
diff --git a/libmproxy/protocol2/layer.py b/libmproxy/protocol2/layer.py
index 8aede22e..0ae64c43 100644
--- a/libmproxy/protocol2/layer.py
+++ b/libmproxy/protocol2/layer.py
@@ -41,21 +41,6 @@ from .messages import Connect, Reconnect, ChangeServer
from ..exceptions import ProtocolException
-class RootContext(object):
- """
- The outmost context provided to the root layer.
- As a consequence, every layer has .client_conn, .channel and .config.
- """
-
- def __init__(self, client_conn, config, channel):
- self.client_conn = client_conn # Client Connection
- self.channel = channel # provides .ask() method to communicate with FlowMaster
- self.config = config # Proxy Configuration
-
- def next_layer(self):
- print(type(self))
-
-
class _LayerCodeCompletion(object):
"""
Dummy class that provides type hinting in PyCharm, which simplifies development a lot.
@@ -208,4 +193,4 @@ def yield_from_callback(fun):
self.yield_from_callback = None
- return wrapper
+ return wrapper \ No newline at end of file
diff --git a/libmproxy/protocol2/root_context.py b/libmproxy/protocol2/root_context.py
new file mode 100644
index 00000000..cbe596aa
--- /dev/null
+++ b/libmproxy/protocol2/root_context.py
@@ -0,0 +1,32 @@
+from .rawtcp import TcpLayer
+from .tls import TlsLayer
+
+
+class RootContext(object):
+ """
+ The outmost context provided to the root layer.
+ As a consequence, every layer has .client_conn, .channel, .next_layer() and .config.
+ """
+
+ def __init__(self, client_conn, config, channel):
+ self.client_conn = client_conn # Client Connection
+ self.channel = channel # provides .ask() method to communicate with FlowMaster
+ self.config = config # Proxy Configuration
+
+ def next_layer(self, top_layer):
+ """
+ This function determines the next layer in the protocol stack.
+ :param top_layer: the current top layer
+ :return: The next layer.
+ """
+
+ d = top_layer.client_conn.rfile.peek(1)
+
+ if not d:
+ return
+ # TLS ClientHello magic, see http://www.moserware.com/2009/06/first-few-milliseconds-of-https.html#client-hello
+ if d[0] == "\x16":
+ layer = TlsLayer(top_layer, True, True)
+ else:
+ layer = TcpLayer(top_layer)
+ return layer
diff --git a/libmproxy/protocol2/socks.py b/libmproxy/protocol2/socks_proxy.py
index 1222ef5c..c89477ca 100644
--- a/libmproxy/protocol2/socks.py
+++ b/libmproxy/protocol2/socks_proxy.py
@@ -3,9 +3,9 @@ from __future__ import (absolute_import, print_function, division)
from ..exceptions import ProtocolException
from ..proxy import ProxyError, Socks5ProxyMode
from .layer import Layer, ServerConnectionMixin
-from .auto import AutoLayer
-class Socks5IncomingLayer(Layer, ServerConnectionMixin):
+
+class Socks5Proxy(Layer, ServerConnectionMixin):
def __call__(self):
try:
s5mode = Socks5ProxyMode(self.config.ssl_ports)
@@ -16,7 +16,7 @@ class Socks5IncomingLayer(Layer, ServerConnectionMixin):
self.server_address = address
- layer = AutoLayer(self)
+ layer = self.ctx.next_layer(self)
for message in layer():
if not self._handle_server_message(message):
yield message
diff --git a/libmproxy/protocol2/tls.py b/libmproxy/protocol2/tls.py
index 2362b2b2..999cbea6 100644
--- a/libmproxy/protocol2/tls.py
+++ b/libmproxy/protocol2/tls.py
@@ -5,7 +5,6 @@ from netlib import tcp
from ..exceptions import ProtocolException
from .layer import Layer, yield_from_callback
from .messages import Connect, Reconnect, ChangeServer
-from .auto import AutoLayer
class TlsLayer(Layer):
@@ -55,8 +54,7 @@ class TlsLayer(Layer):
for m in self._establish_tls_with_client():
yield m
- self.next_layer()
- layer = AutoLayer(self)
+ layer = self.ctx.next_layer(self)
for message in layer():
if message != Connect or not self._connected:
yield message
diff --git a/libmproxy/protocol2/transparent_proxy.py b/libmproxy/protocol2/transparent_proxy.py
index 078954c2..f073e2f8 100644
--- a/libmproxy/protocol2/transparent_proxy.py
+++ b/libmproxy/protocol2/transparent_proxy.py
@@ -3,7 +3,6 @@ from __future__ import (absolute_import, print_function, division)
from ..exceptions import ProtocolException
from .. import platform
from .layer import Layer, ServerConnectionMixin
-from .auto import AutoLayer
class TransparentProxy(Layer, ServerConnectionMixin):
@@ -18,7 +17,7 @@ class TransparentProxy(Layer, ServerConnectionMixin):
except Exception as e:
raise ProtocolException("Transparent mode failure: %s" % repr(e), e)
- layer = AutoLayer(self)
+ layer = self.ctx.next_layer(self)
for message in layer():
if not self._handle_server_message(message):
yield message