diff options
Diffstat (limited to 'libmproxy')
-rw-r--r-- | libmproxy/flow.py | 25 | ||||
-rw-r--r-- | libmproxy/protocol/http.py | 69 | ||||
-rw-r--r-- | libmproxy/proxy/server.py | 2 |
3 files changed, 59 insertions, 37 deletions
diff --git a/libmproxy/flow.py b/libmproxy/flow.py index d4aa1805..dd897115 100644 --- a/libmproxy/flow.py +++ b/libmproxy/flow.py @@ -668,7 +668,7 @@ class FlowMaster(controller.Master): f.response = None f.error = None self.process_new_request(f) - rt = RequestReplayThread( + rt = http.RequestReplayThread( self.server.config, f, self.masterq, @@ -811,26 +811,3 @@ class FilteredFlowWriter: return d = f._get_state() tnetstring.dump(d, self.fo) - - -class RequestReplayThread(threading.Thread): - name = "RequestReplayThread" - - def __init__(self, config, flow, masterq, should_exit): - self.config, self.flow, self.channel = config, flow, controller.Channel(masterq, should_exit) - threading.Thread.__init__(self) - - def run(self): - try: - r = self.flow.request - server = ServerConnection(self.flow.server_conn.address(), None) - server.connect() - if self.flow.server_conn.ssl_established: - server.establish_ssl(self.config.clientcerts, - self.flow.server_conn.sni) - server.send(r._assemble()) - self.flow.response = http.HTTPResponse.from_stream(server.rfile, r.method, body_size_limit=self.config.body_size_limit) - self.channel.ask("response", self.flow.response) - except (ProxyError, netlib.http.HttpError, tcp.NetLibError), v: - self.flow.error = protocol.primitives.Error(str(v)) - self.channel.ask("error", self.flow.error)
\ No newline at end of file diff --git a/libmproxy/protocol/http.py b/libmproxy/protocol/http.py index 7c4d9cbb..b8372d5a 100644 --- a/libmproxy/protocol/http.py +++ b/libmproxy/protocol/http.py @@ -1,6 +1,7 @@ from __future__ import absolute_import import Cookie, urllib, urlparse, time, copy from email.utils import parsedate_tz, formatdate, mktime_tz +import threading from netlib import http, tcp, http_status import netlib.utils from netlib.odict import ODict, ODictCaseless @@ -24,6 +25,19 @@ def get_line(fp): return line +def send_connect_request(conn, host, port): + upstream_request = HTTPRequest("authority", "CONNECT", None, host, port, None, + (1, 1), ODictCaseless(), "") + conn.send(upstream_request._assemble()) + resp = HTTPResponse.from_stream(conn.rfile, upstream_request.method) + if resp.code != 200: + raise proxy.ProxyError(resp.code, + "Cannot establish SSL " + + "connection with upstream proxy: \r\n" + + str(resp._assemble())) + return resp + + class decoded(object): """ A context manager that decodes a request or response, and then @@ -462,7 +476,7 @@ class HTTPRequest(HTTPMessage): host = self.host else: for s in self.flow.server_conn.state: - if s[0] == "http" and s[1].get("state") == "connect": + if s[0] == "http" and s[1]["state"] == "connect": host = s[1]["host"] break if not host: @@ -476,6 +490,8 @@ class HTTPRequest(HTTPMessage): """ if self.scheme: return self.scheme + if self.form_out == "authority": # On SSLed connections, the original CONNECT request is still unencrypted. + return "http" return "https" if self.flow.server_conn.ssl_established else "http" def get_port(self): @@ -992,7 +1008,6 @@ class HTTPHandler(ProtocolHandler, TemporaryServerChangeMixin): "port": flow.request.port})) self.ssl_upgrade() - # If the user has changed the target server on this connection, # restore the original target server self.restore_server() @@ -1004,16 +1019,7 @@ class HTTPHandler(ProtocolHandler, TemporaryServerChangeMixin): def handle_server_reconnect(self, state): if state["state"] == "connect": - upstream_request = HTTPRequest("authority", "CONNECT", None, state["host"], state["port"], None, - (1, 1), ODictCaseless(), "") - self.c.server_conn.send(upstream_request._assemble()) - resp = HTTPResponse.from_stream(self.c.server_conn.rfile, upstream_request.method) - if resp.code != 200: - raise proxy.ProxyError(resp.code, - "Cannot reestablish SSL " + - "connection with upstream proxy: \r\n" + - str(resp._assemble())) - return + send_connect_request(self.c.server_conn, state["host"], state["port"]) else: # pragma: nocover raise RuntimeError("Unknown State: %s" % state["state"]) @@ -1117,3 +1123,42 @@ class HTTPHandler(ProtocolHandler, TemporaryServerChangeMixin): raise HttpAuthenticationError( self.c.config.authenticator.auth_challenge_headers()) return request.headers + + +class RequestReplayThread(threading.Thread): + name = "RequestReplayThread" + + def __init__(self, config, flow, masterq, should_exit): + self.config, self.flow, self.channel = config, flow, controller.Channel(masterq, should_exit) + threading.Thread.__init__(self) + + def run(self): + try: + r = self.flow.request + + server_address, server_ssl = False, False + if self.config.get_upstream_server: + try: + upstream_info = self.config.get_upstream_server(self.flow.client_conn) + server_ssl = upstream_info[1] + server_address = upstream_info[2:] + except proxy.ProxyError: # this will fail in transparent mode + pass + if not server_address: + server_address = self.flow.server_conn.address() + + server = ServerConnection(server_address, None) + server.connect() + + if server_ssl or r.get_scheme() == "https": + if self.config.http_form_out == "absolute": + send_connect_request(server, r.get_host(), r.get_port()) + server.establish_ssl(self.config.clientcerts, + self.flow.server_conn.sni) + server.send(r._assemble()) + self.flow.response = HTTPResponse.from_stream(server.rfile, r.method, + body_size_limit=self.config.body_size_limit) + self.channel.ask("response", self.flow.response) + except (proxy.ProxyError, http.HttpError, tcp.NetLibError), v: + self.flow.error = Error(repr(v)) + self.channel.ask("error", self.flow.error)
\ No newline at end of file diff --git a/libmproxy/proxy/server.py b/libmproxy/proxy/server.py index c3f1e048..345e1507 100644 --- a/libmproxy/proxy/server.py +++ b/libmproxy/proxy/server.py @@ -37,7 +37,7 @@ class ProxyServer(tcp.TCPServer): try: tcp.TCPServer.__init__(self, (host, port)) except socket.error, v: - raise ProxyServerError('Error starting proxy server: ' + v.strerror) + raise ProxyServerError('Error starting proxy server: ' + repr(v)) self.channel = None def start_slave(self, klass, channel): |