diff options
author | Maximilian Hils <git@maximilianhils.com> | 2016-02-18 13:03:40 +0100 |
---|---|---|
committer | Maximilian Hils <git@maximilianhils.com> | 2016-02-18 13:03:40 +0100 |
commit | d33d3663ecb166461d9cb5a78a29b44ee7a8fbb7 (patch) | |
tree | fe8856f65d1dafa946150c5acbaf6e942ba3c026 /pathod/protocols | |
parent | 294774d6f0dee95b02a93307ec493b111b7f171e (diff) | |
download | mitmproxy-d33d3663ecb166461d9cb5a78a29b44ee7a8fbb7.tar.gz mitmproxy-d33d3663ecb166461d9cb5a78a29b44ee7a8fbb7.tar.bz2 mitmproxy-d33d3663ecb166461d9cb5a78a29b44ee7a8fbb7.zip |
combine projects
Diffstat (limited to 'pathod/protocols')
-rw-r--r-- | pathod/protocols/__init__.py | 1 | ||||
-rw-r--r-- | pathod/protocols/http.py | 71 | ||||
-rw-r--r-- | pathod/protocols/http2.py | 20 | ||||
-rw-r--r-- | pathod/protocols/websockets.py | 56 |
4 files changed, 148 insertions, 0 deletions
diff --git a/pathod/protocols/__init__.py b/pathod/protocols/__init__.py new file mode 100644 index 00000000..1a8c7dab --- /dev/null +++ b/pathod/protocols/__init__.py @@ -0,0 +1 @@ +from . import http, http2, websockets diff --git a/pathod/protocols/http.py b/pathod/protocols/http.py new file mode 100644 index 00000000..1f1765cb --- /dev/null +++ b/pathod/protocols/http.py @@ -0,0 +1,71 @@ +from netlib import tcp, wsgi +from netlib.exceptions import HttpReadDisconnect, TlsException +from netlib.http import http1, Request +from .. import version, language + + +class HTTPProtocol(object): + def __init__(self, pathod_handler): + self.pathod_handler = pathod_handler + + def make_error_response(self, reason, body): + return language.http.make_error_response(reason, body) + + def handle_http_app(self, method, path, headers, body, lg): + """ + Handle a request to the built-in app. + """ + if self.pathod_handler.server.noweb: + crafted = self.pathod_handler.make_http_error_response("Access Denied") + language.serve(crafted, self.pathod_handler.wfile, self.pathod_handler.settings) + return None, dict( + type="error", + msg="Access denied: web interface disabled" + ) + lg("app: %s %s" % (method, path)) + req = wsgi.Request("http", method, path, b"HTTP/1.1", headers, body) + flow = wsgi.Flow(self.pathod_handler.address, req) + sn = self.pathod_handler.connection.getsockname() + a = wsgi.WSGIAdaptor( + self.pathod_handler.server.app, + sn[0], + self.pathod_handler.server.address.port, + version.NAMEVERSION + ) + a.serve(flow, self.pathod_handler.wfile) + return self.pathod_handler.handle_http_request, None + + def handle_http_connect(self, connect, lg): + """ + Handle a CONNECT request. + """ + + self.pathod_handler.wfile.write( + 'HTTP/1.1 200 Connection established\r\n' + + ('Proxy-agent: %s\r\n' % version.NAMEVERSION) + + '\r\n' + ) + self.pathod_handler.wfile.flush() + if not self.pathod_handler.server.ssloptions.not_after_connect: + try: + cert, key, chain_file_ = self.pathod_handler.server.ssloptions.get_cert( + connect[0] + ) + self.pathod_handler.convert_to_ssl( + cert, + key, + handle_sni=self.pathod_handler.handle_sni, + request_client_cert=self.pathod_handler.server.ssloptions.request_client_cert, + cipher_list=self.pathod_handler.server.ssloptions.ciphers, + method=self.pathod_handler.server.ssloptions.ssl_version, + options=self.pathod_handler.server.ssloptions.ssl_options, + alpn_select=self.pathod_handler.server.ssloptions.alpn_select, + ) + except TlsException as v: + s = str(v) + lg(s) + return None, dict(type="error", msg=s) + return self.pathod_handler.handle_http_request, None + + def read_request(self, lg=None): + return http1.read_request(self.pathod_handler.rfile) diff --git a/pathod/protocols/http2.py b/pathod/protocols/http2.py new file mode 100644 index 00000000..a098a14e --- /dev/null +++ b/pathod/protocols/http2.py @@ -0,0 +1,20 @@ +from netlib.http import http2 +from .. import version, app, language, utils, log + +class HTTP2Protocol: + + def __init__(self, pathod_handler): + self.pathod_handler = pathod_handler + self.wire_protocol = http2.HTTP2Protocol( + self.pathod_handler, is_server=True, dump_frames=self.pathod_handler.http2_framedump + ) + + def make_error_response(self, reason, body): + return language.http2.make_error_response(reason, body) + + def read_request(self, lg=None): + self.wire_protocol.perform_server_connection_preface() + return self.wire_protocol.read_request(self.pathod_handler.rfile) + + def assemble(self, message): + return self.wire_protocol.assemble(message) diff --git a/pathod/protocols/websockets.py b/pathod/protocols/websockets.py new file mode 100644 index 00000000..134d27bc --- /dev/null +++ b/pathod/protocols/websockets.py @@ -0,0 +1,56 @@ +import time + +from netlib import websockets +from .. import language +from netlib.exceptions import NetlibException + + +class WebsocketsProtocol: + + def __init__(self, pathod_handler): + self.pathod_handler = pathod_handler + + def handle_websocket(self, logger): + while True: + with logger.ctx() as lg: + started = time.time() + try: + frm = websockets.Frame.from_file(self.pathod_handler.rfile) + except NetlibException as e: + lg("Error reading websocket frame: %s" % e) + break + ended = time.time() + lg(frm.human_readable()) + retlog = dict( + type="inbound", + protocol="websockets", + started=started, + duration=ended - started, + frame=dict( + ), + cipher=None, + ) + if self.pathod_handler.ssl_established: + retlog["cipher"] = self.pathod_handler.get_current_cipher() + self.pathod_handler.addlog(retlog) + ld = language.websockets.NESTED_LEADER + if frm.payload.startswith(ld): + nest = frm.payload[len(ld):] + try: + wf_gen = language.parse_websocket_frame(nest) + except language.exceptions.ParseException as v: + logger.write( + "Parse error in reflected frame specifcation:" + " %s" % v.msg + ) + return None, None + for frm in wf_gen: + with logger.ctx() as lg: + frame_log = language.serve( + frm, + self.pathod_handler.wfile, + self.pathod_handler.settings + ) + lg("crafting websocket spec: %s" % frame_log["spec"]) + self.pathod_handler.addlog(frame_log) + return self.handle_websocket, None |