def iterate(f): if isinstance(f, http.HTTPFlow): if f.request: yield "requestheaders", f yield "request", f if f.response: yield "responseheaders", f yield "response", f if f.error: yield "error", f elif isinstance(f, websocket.WebSocketFlow): messages = f.messages f.messages = [] f.reply = controller.DummyReply() yield "websocket_start", f while messages: f.messages.append(messages.pop(0)) yield "websocket_message", f if f.error: yield "websocket_error", f yield "websocket_end", f elif isinstance(f, tcp.TCPFlow): messages = f.messages f.messages = [] f.reply = controller.DummyReply() yield "tcp_start", f while messages: f.messages.append(messages.pop(0)) yield "tcp_message", f if f.error: yield "tcp_error", f yield "tcp_end", f else: raise TypeError()
def load_flow(self, f): """ Loads a flow """ if isinstance(f, models.HTTPFlow): if self.server and self.options.mode == "reverse": f.request.host = self.server.config.upstream_server.address.host f.request.port = self.server.config.upstream_server.address.port f.request.scheme = self.server.config.upstream_server.scheme f.reply = controller.DummyReply() if f.request: self.request(f) if f.response: self.responseheaders(f) self.response(f) if f.error: self.error(f) elif isinstance(f, models.TCPFlow): messages = f.messages f.messages = [] f.reply = controller.DummyReply() self.tcp_open(f) while messages: f.messages.append(messages.pop(0)) self.tcp_message(f) if f.error: self.tcp_error(f) self.tcp_close(f) else: raise NotImplementedError()
def log(self, message: str, level: str = "info") -> None: x = log.LogEntry(self.log_prefix + message, level) x.reply = controller.DummyReply() # type: ignore asyncio_utils.create_task( self.master.addons.handle_lifecycle("log", x), name="ProxyConnectionHandler.log" )
def tflow( *, client_conn: Optional[connection.Client] = None, server_conn: Optional[connection.Server] = None, req: Optional[http.Request] = None, resp: Union[bool, http.Response] = False, err: Union[bool, flow.Error] = False, ws: Union[bool, websocket.WebSocketData] = False, ) -> http.HTTPFlow: """Create a flow for testing.""" if client_conn is None: client_conn = tclient_conn() if server_conn is None: server_conn = tserver_conn() if req is None: req = treq() if resp is True: resp = tresp() if err is True: err = terr() if ws is True: ws = twebsocket() assert resp is False or isinstance(resp, http.Response) assert err is False or isinstance(err, flow.Error) assert ws is False or isinstance(ws, websocket.WebSocketData) f = http.HTTPFlow(client_conn, server_conn) f.request = req f.response = resp or None f.error = err or None f.websocket = ws or None f.reply = controller.DummyReply() return f
def tserver_conn() -> compat.Server: c = compat.Server.from_state( dict( id=str(uuid.uuid4()), address=("address", 22), source_address=("address", 22), ip_address=("192.168.0.1", 22), timestamp_start=946681202, timestamp_tcp_setup=946681203, timestamp_tls_setup=946681204, timestamp_end=946681205, tls_established=True, sni="address", alpn_proto_negotiated=None, tls_version="TLSv1.2", via=None, state=0, error=None, tls=False, certificate_list=[], alpn_offers=[], cipher_name=None, cipher_list=[], via2=None, )) c.reply = controller.DummyReply() c.rfile = io.BytesIO() c.wfile = io.BytesIO() return c
def tflow(client_conn=True, server_conn=True, req=True, resp=None, err=None): """ @type client_conn: bool | None | mitmproxy.proxy.connection.ClientConnection @type server_conn: bool | None | mitmproxy.proxy.connection.ServerConnection @type req: bool | None | mitmproxy.protocol.http.HTTPRequest @type resp: bool | None | mitmproxy.protocol.http.HTTPResponse @type err: bool | None | mitmproxy.protocol.primitives.Error @return: mitmproxy.protocol.http.HTTPFlow """ if client_conn is True: client_conn = tclient_conn() if server_conn is True: server_conn = tserver_conn() if req is True: req = netlib.tutils.treq() if resp is True: resp = netlib.tutils.tresp() if err is True: err = terr() if req: req = HTTPRequest.wrap(req) if resp: resp = HTTPResponse.wrap(resp) f = HTTPFlow(client_conn, server_conn) f.request = req f.response = resp f.error = err f.reply = controller.DummyReply() return f
def tclient_conn() -> compat.Client: c = compat.Client.from_state( dict( id=str(uuid.uuid4()), address=("127.0.0.1", 22), mitmcert=None, tls_established=True, timestamp_start=946681200, timestamp_tls_setup=946681201, timestamp_end=946681206, sni="address", cipher_name="cipher", alpn_proto_negotiated=b"http/1.1", tls_version="TLSv1.2", tls_extensions=[(0x00, bytes.fromhex("000e00000b6578616d"))], state=0, sockname=("", 0), error=None, tls=False, certificate_list=[], alpn_offers=[], cipher_list=[], )) c.reply = controller.DummyReply() if not compat.new_proxy_core: c.rfile = io.BytesIO() c.wfile = io.BytesIO() return c
def copy(self): """Make a copy of this flow.""" f = super().copy() f.live = False if self.reply is not None: f.reply = controller.DummyReply() return f
def tserver_conn(): """ @return: mitmproxy.proxy.connection.ServerConnection """ c = connections.ServerConnection.from_state( dict( id=str(uuid.uuid4()), address=("address", 22), source_address=("address", 22), ip_address=("192.168.0.1", 22), cert=None, timestamp_start=946681202, timestamp_tcp_setup=946681203, timestamp_tls_setup=946681204, timestamp_end=946681205, tls_established=False, sni="address", alpn_proto_negotiated=None, tls_version="TLSv1.2", via=None, )) c.reply = controller.DummyReply() c.rfile = io.BytesIO() c.wfile = io.BytesIO() return c
async def load_flow(self, f): """ Loads a flow and links websocket & handshake flows """ if isinstance(f, http.HTTPFlow): self._change_reverse_host(f) if 'websocket' in f.metadata: self.waiting_flows.append(f) if isinstance(f, websocket.WebSocketFlow): hfs = [ hf for hf in self.waiting_flows if hf.id == f.metadata['websocket_handshake'] ] if hfs: hf = hfs[0] f.handshake_flow = hf self.waiting_flows.remove(hf) self._change_reverse_host(f.handshake_flow) else: # this will fail - but at least it will load the remaining flows f.handshake_flow = http.HTTPFlow(None, None) f.reply = controller.DummyReply() for e, o in eventsequence.iterate(f): await self.addons.handle_lifecycle(e, o)
def twebsocketflow(client_conn=True, server_conn=True, messages=True, err=None, handshake_flow=True): if client_conn is True: client_conn = tclient_conn() if server_conn is True: server_conn = tserver_conn() if handshake_flow is True: req = http.HTTPRequest("relative", "GET", "http", "example.com", "80", "/ws", "HTTP/1.1", headers=net_http.Headers( connection="upgrade", upgrade="websocket", sec_websocket_version="13", sec_websocket_key="1234", ), content=b'') resp = http.HTTPResponse( "HTTP/1.1", 101, reason=net_http.status_codes.RESPONSES.get(101), headers=net_http.Headers( connection='upgrade', upgrade='websocket', sec_websocket_accept=b'', ), content=b'', ) handshake_flow = http.HTTPFlow(client_conn, server_conn) handshake_flow.request = req handshake_flow.response = resp f = websocket.WebSocketFlow(client_conn, server_conn, handshake_flow) handshake_flow.metadata['websocket_flow'] = f if messages is True: messages = [ websocket.WebSocketMessage(websockets.OPCODE.BINARY, True, b"hello binary"), websocket.WebSocketMessage(websockets.OPCODE.TEXT, True, "hello text".encode()), websocket.WebSocketMessage(websockets.OPCODE.TEXT, False, "it's me".encode()), ] if err is True: err = terr() f.messages = messages f.error = err f.reply = controller.DummyReply() return f
def test_simple(self): reply = controller.DummyReply() for _ in range(2): reply.take() reply.commit() reply.mark_reset() reply.reset() assert reply.state == "start"
def test_reset(self): reply = controller.DummyReply() reply.ack() reply.take() reply.commit() reply.mark_reset() assert reply.state == "committed" reply.reset() assert reply.state == "start"
def tick(self, master): if self.flows and not self.current: self.current = self.flows.pop(0).copy() if not self.testing: master.replay_request(self.current) else: self.current.reply = controller.DummyReply() master.request(self.current) if self.current.response: master.response(self.current)
def test_reset(self): reply = controller.DummyReply() reply.take() with pytest.raises(ControlException): reply.mark_reset() reply.commit() reply.mark_reset() assert reply.state == "committed" reply.reset() assert reply.state == "start"
async def cycle(self, master, content): f = tflow.tflow(req=tutils.treq(content=content)) layer = mock.Mock("mitmproxy.proxy.protocol.base.Layer") layer.client_conn = f.client_conn layer.reply = controller.DummyReply() await master.addons.handle_lifecycle("clientconnect", layer) for i in eventsequence.iterate(f): await master.addons.handle_lifecycle(*i) await master.addons.handle_lifecycle("clientdisconnect", layer) return f
def twebsocketflow(messages=True, err=None, close_code=None, close_reason='') -> http.HTTPFlow: flow = http.HTTPFlow(tclient_conn(), tserver_conn()) flow.request = http.Request( "example.com", 80, b"GET", b"http", b"example.com", b"/ws", b"HTTP/1.1", headers=http.Headers( connection="upgrade", upgrade="websocket", sec_websocket_version="13", sec_websocket_key="1234", ), content=b'', trailers=None, timestamp_start=946681200, timestamp_end=946681201, ) flow.response = http.Response( b"HTTP/1.1", 101, reason=b"Switching Protocols", headers=http.Headers( connection='upgrade', upgrade='websocket', sec_websocket_accept=b'', ), content=b'', trailers=None, timestamp_start=946681202, timestamp_end=946681203, ) flow.websocket = twebsocket() flow.websocket.close_reason = close_reason if close_code is not None: flow.websocket.close_code = close_code else: if err is True: # ABNORMAL_CLOSURE flow.websocket.close_code = 1006 else: # NORMAL_CLOSURE flow.websocket.close_code = 1000 flow.reply = controller.DummyReply() return flow
def _iterate_tcp(f: tcp.TCPFlow) -> TEventGenerator: messages = f.messages f.messages = [] f.reply = controller.DummyReply() yield "tcp_start", f while messages: f.messages.append(messages.pop(0)) yield "tcp_message", f if f.error: yield "tcp_error", f yield "tcp_end", f
def _iterate_websocket(f: websocket.WebSocketFlow) -> TEventGenerator: messages = f.messages f.messages = [] f.reply = controller.DummyReply() yield "websocket_start", f while messages: f.messages.append(messages.pop(0)) yield "websocket_message", f if f.error: yield "websocket_error", f yield "websocket_end", f
async def load_flow(self, f): """ Loads a flow """ if isinstance(f, http.HTTPFlow): self._change_reverse_host(f) f.reply = controller.DummyReply() for e in eventsequence.iterate(f): await self.addons.handle_lifecycle(e)
def load_flow(self, f): """ Loads a flow """ if isinstance(f, http.HTTPFlow): if self.options.mode.startswith("reverse:"): _, upstream_spec = server_spec.parse_with_mode(self.options.mode) f.request.host, f.request.port = upstream_spec.address f.request.scheme = upstream_spec.scheme f.reply = controller.DummyReply() for e, o in eventsequence.iterate(f): self.addons.handle_lifecycle(e, o)
def load_flow(self, f): """ Loads a flow """ if isinstance(f, http.HTTPFlow): if self.server and self.options.mode.startswith("reverse:"): f.request.host = self.server.config.upstream_server.address[0] f.request.port = self.server.config.upstream_server.address[1] f.request.scheme = self.server.config.upstream_server.scheme f.reply = controller.DummyReply() for e, o in eventsequence.iterate(f): self.addons.handle_lifecycle(e, o)
def load_flow(self, f): """ Loads a flow """ if isinstance(f, models.HTTPFlow): if self.server and self.options.mode == "reverse": f.request.host = self.server.config.upstream_server.address.host f.request.port = self.server.config.upstream_server.address.port f.request.scheme = self.server.config.upstream_server.scheme f.reply = controller.DummyReply() for e, o in event_sequence(f): getattr(self, e)(o)
async def cycle(self, master, content): f = tflow.tflow(req=tutils.treq(content=content)) layer = mock.Mock("mitmproxy.proxy.protocol.base.Layer") layer.client_conn = f.client_conn layer.reply = controller.DummyReply() await master.addons.handle_lifecycle( server_hooks.ClientConnectedHook(layer)) for e in eventsequence.iterate(f): await master.addons.handle_lifecycle(e) await master.addons.handle_lifecycle( server_hooks.ClientDisconnectedHook(layer)) return f
def _iterate_tcp(f: tcp.TCPFlow) -> TEventGenerator: messages = f.messages f.messages = [] f.reply = controller.DummyReply() yield layers.tcp.TcpStartHook(f) while messages: f.messages.append(messages.pop(0)) yield layers.tcp.TcpMessageHook(f) if f.error: yield layers.tcp.TcpErrorHook(f) else: yield layers.tcp.TcpEndHook(f)
def _iterate_websocket(f: websocket.WebSocketFlow) -> TEventGenerator: messages = f.messages f.messages = [] f.reply = controller.DummyReply() yield layers.websocket.WebsocketStartHook(f) while messages: f.messages.append(messages.pop(0)) yield layers.websocket.WebsocketMessageHook(f) if f.error: yield layers.websocket.WebsocketErrorHook(f) else: yield layers.websocket.WebsocketEndHook(f)
def tdummyflow(client_conn=True, server_conn=True, err=None): if client_conn is True: client_conn = tclient_conn() if server_conn is True: server_conn = tserver_conn() if err is True: err = terr() f = DummyFlow(client_conn, server_conn) f.error = err f.reply = controller.DummyReply() return f
def cycle(self, master, content): f = tutils.tflow(req=netlib.tutils.treq(content=content)) l = proxy.Log("connect") l.reply = controller.DummyReply() master.log(l) master.clientconnect(f.client_conn) master.serverconnect(f.server_conn) master.request(f) if not f.error: f.response = models.HTTPResponse.wrap(netlib.tutils.tresp(content=content)) master.response(f) master.clientdisconnect(f) return f
def test_simple(self): class tAddon: def log(self, _): ctx.master.should_exit.set() with taddons.context() as ctx: ctx.master.addons.add(tAddon()) assert not ctx.master.should_exit.is_set() msg = TMsg() msg.reply = controller.DummyReply() ctx.master.event_queue.put(("log", msg)) ctx.master.run() assert ctx.master.should_exit.is_set()
def twebsocketflow(messages=True, err=None) -> http.HTTPFlow: flow = http.HTTPFlow(tclient_conn(), tserver_conn()) flow.request = http.Request( "example.com", 80, b"GET", b"http", b"example.com", b"/ws", b"HTTP/1.1", headers=http.Headers( connection="upgrade", upgrade="websocket", sec_websocket_version="13", sec_websocket_key="1234", ), content=b'', trailers=None, timestamp_start=946681200, timestamp_end=946681201, ) flow.response = http.Response( b"HTTP/1.1", 101, reason=b"Switching Protocols", headers=http.Headers( connection='upgrade', upgrade='websocket', sec_websocket_accept=b'', ), content=b'', trailers=None, timestamp_start=946681202, timestamp_end=946681203, ) flow.websocket = websocket.WebSocketData() if messages is True: flow.websocket.messages = [ websocket.WebSocketMessage(Opcode.BINARY, True, b"hello binary", 946681203), websocket.WebSocketMessage(Opcode.TEXT, True, b"hello text", 946681204), websocket.WebSocketMessage(Opcode.TEXT, False, b"it's me", 946681205), ] if err is True: flow.error = terr() flow.reply = controller.DummyReply() return flow