diff options
Diffstat (limited to 'libmproxy')
-rw-r--r-- | libmproxy/protocol/http.py | 60 | ||||
-rw-r--r-- | libmproxy/protocol/primitives.py | 3 | ||||
-rw-r--r-- | libmproxy/proxy.py | 4 |
3 files changed, 36 insertions, 31 deletions
diff --git a/libmproxy/protocol/http.py b/libmproxy/protocol/http.py index 8dcc21d7..95de6606 100644 --- a/libmproxy/protocol/http.py +++ b/libmproxy/protocol/http.py @@ -883,8 +883,7 @@ class HTTPHandler(ProtocolHandler, TemporaryServerChangeMixin): self.process_request(flow.request) request_reply = self.c.channel.ask("request", flow.request) - flow.server_conn = self.c.server_conn # no further manipulation of self.c.server_conn beyond this point. - # we can safely set it as the final attribute valueh here. + flow.server_conn = self.c.server_conn if request_reply is None or request_reply == KILL: return False @@ -894,14 +893,15 @@ class HTTPHandler(ProtocolHandler, TemporaryServerChangeMixin): else: flow.response = self.get_response_from_server(flow.request) + flow.server_conn = self.c.server_conn # no further manipulation of self.c.server_conn beyond this point + # we can safely set it as the final attribute value here. + self.c.log("response", [flow.response._assemble_first_line()]) response_reply = self.c.channel.ask("response", flow.response) if response_reply is None or response_reply == KILL: return False - raw = flow.response._assemble() - self.c.client_conn.wfile.write(raw) - self.c.client_conn.wfile.flush() + self.c.client_conn.send(flow.response._assemble()) flow.timestamp_end = utils.timestamp() if (http.connection_close(flow.request.httpversion, flow.request.headers) or @@ -909,7 +909,7 @@ class HTTPHandler(ProtocolHandler, TemporaryServerChangeMixin): return False if flow.request.form_in == "authority": - self.ssl_upgrade(flow.request) + self.ssl_upgrade() self.restore_server() # If the user has changed the target server on this connection, # restore the original target server @@ -968,7 +968,27 @@ class HTTPHandler(ProtocolHandler, TemporaryServerChangeMixin): self.c.client_conn.wfile.write(html_content) self.c.client_conn.wfile.flush() - def ssl_upgrade(self, upstream_request=None): + def hook_reconnect(self, upstream_request): + self.c.log("Hook reconnect function") + original_reconnect_func = self.c.server_reconnect + + def reconnect_http_proxy(): + self.c.log("Hooked reconnect function") + self.c.log("Hook: Run original reconnect") + original_reconnect_func(no_ssl=True) + self.c.log("Hook: Write CONNECT request to upstream proxy", [upstream_request._assemble_first_line()]) + self.c.server_conn.send(upstream_request._assemble()) + self.c.log("Hook: Read answer to CONNECT request from proxy") + resp = HTTPResponse.from_stream(self.c.server_conn.rfile, upstream_request.method) + if resp.code != 200: + raise ProxyError(resp.code, + "Cannot reestablish SSL connection with upstream proxy: \r\n" + str(resp.headers)) + self.c.log("Hook: Establish SSL with upstream proxy") + self.c.establish_ssl(server=True) + + self.c.server_reconnect = reconnect_http_proxy + + def ssl_upgrade(self): """ Upgrade the connection to SSL after an authority (CONNECT) request has been made. If the authority request has been forwarded upstream (because we have another proxy server there), @@ -981,28 +1001,6 @@ class HTTPHandler(ProtocolHandler, TemporaryServerChangeMixin): self.c.mode = "transparent" self.c.determine_conntype() self.c.establish_ssl(server=True, client=True) - - if upstream_request: - self.c.log("Hook reconnect function") - original_reconnect_func = self.c.server_reconnect - - def reconnect_http_proxy(): - self.c.log("Hooked reconnect function") - self.c.log("Hook: Run original reconnect") - original_reconnect_func(no_ssl=True) - self.c.log("Hook: Write CONNECT request to upstream proxy", [upstream_request._assemble_first_line()]) - self.c.server_conn.wfile.write(upstream_request._assemble()) - self.c.server_conn.wfile.flush() - self.c.log("Hook: Read answer to CONNECT request from proxy") - resp = HTTPResponse.from_stream(self.c.server_conn.rfile, upstream_request.method) - if resp.code != 200: - raise ProxyError(resp.code, - "Cannot reestablish SSL connection with upstream proxy: \r\n" + str(resp.headers)) - self.c.log("Hook: Establish SSL with upstream proxy") - self.c.establish_ssl(server=True) - - self.c.server_reconnect = reconnect_http_proxy - self.c.log("Upgrade to SSL completed.") raise ConnectionTypeChange @@ -1028,7 +1026,7 @@ class HTTPHandler(ProtocolHandler, TemporaryServerChangeMixin): if self.c.mode == "regular": if request.form_in == "authority": # forward mode - pass + self.hook_reconnect(request) elif request.form_in == "absolute": if request.scheme != "http": raise http.HttpError(400, "Invalid Request") @@ -1037,7 +1035,7 @@ class HTTPHandler(ProtocolHandler, TemporaryServerChangeMixin): self.c.set_server_address((request.host, request.port), AddressPriority.FROM_PROTOCOL) request.flow.server_conn = self.c.server_conn # Update server_conn attribute on the flow else: - raise http.HttpError(400, "Invalid Request") + raise http.HttpError(400, "Invalid request form (absolute-form or authority-form required)") def authenticate(self, request): if self.c.config.authenticator: diff --git a/libmproxy/protocol/primitives.py b/libmproxy/protocol/primitives.py index 673628bc..90191eeb 100644 --- a/libmproxy/protocol/primitives.py +++ b/libmproxy/protocol/primitives.py @@ -50,6 +50,9 @@ class Error(stateobject.SimpleStateObject): timestamp=float ) + def __str__(self): + return self.msg + @classmethod def _from_state(cls, state): f = cls(None) # the default implementation assumes an empty constructor. Override accordingly. diff --git a/libmproxy/proxy.py b/libmproxy/proxy.py index 5526e102..b6480822 100644 --- a/libmproxy/proxy.py +++ b/libmproxy/proxy.py @@ -89,6 +89,10 @@ class ClientConnection(tcp.BaseHandler, stateobject.SimpleStateObject): def copy(self): return copy.copy(self) + def send(self, message): + self.wfile.write(message) + self.wfile.flush() + @classmethod def _from_state(cls, state): f = cls(None, tuple(), None) |