diff options
Diffstat (limited to 'libmproxy/protocol2')
-rw-r--r-- | libmproxy/protocol2/__init__.py | 12 | ||||
-rw-r--r-- | libmproxy/protocol2/auto.py | 20 | ||||
-rw-r--r-- | libmproxy/protocol2/http.py | 90 | ||||
-rw-r--r-- | libmproxy/protocol2/http_protocol_mock.py | 13 | ||||
-rw-r--r-- | libmproxy/protocol2/http_proxy.py (renamed from libmproxy/protocol2/upstream_proxy.py) | 15 | ||||
-rw-r--r-- | libmproxy/protocol2/layer.py | 17 | ||||
-rw-r--r-- | libmproxy/protocol2/root_context.py | 32 | ||||
-rw-r--r-- | libmproxy/protocol2/socks_proxy.py (renamed from libmproxy/protocol2/socks.py) | 6 | ||||
-rw-r--r-- | libmproxy/protocol2/tls.py | 4 | ||||
-rw-r--r-- | libmproxy/protocol2/transparent_proxy.py | 3 |
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 |