This commit is contained in:
Maximilian Hils 2014-07-26 12:02:18 +02:00
parent a73ad1d945
commit e9c834a30d
6 changed files with 16 additions and 12 deletions

View File

@ -672,12 +672,7 @@ class FlowMaster(controller.Master):
self.run_script_hook("clientdisconnect", r) self.run_script_hook("clientdisconnect", r)
r.reply() r.reply()
def handle_serverconnection(self, sc): def handle_serverconnect(self, sc):
# To unify the mitmproxy script API, we call the script hook
# "serverconnect" rather than "serverconnection". As things are handled
# differently in libmproxy (ClientConnect + ClientDisconnect vs
# ServerConnection class), there is no "serverdisonnect" event at the
# moment.
self.run_script_hook("serverconnect", sc) self.run_script_hook("serverconnect", sc)
sc.reply() sc.reply()
@ -791,7 +786,7 @@ class FilteredFlowWriter:
class RequestReplayThread(threading.Thread): class RequestReplayThread(threading.Thread):
name="RequestReplayThread" name = "RequestReplayThread"
def __init__(self, config, flow, masterq, should_exit): def __init__(self, config, flow, masterq, should_exit):
self.config, self.flow, self.channel = config, flow, controller.Channel(masterq, should_exit) self.config, self.flow, self.channel = config, flow, controller.Channel(masterq, should_exit)

View File

@ -1035,12 +1035,14 @@ class HTTPHandler(ProtocolHandler, TemporaryServerChangeMixin):
if not self.c.config.get_upstream_server: if not self.c.config.get_upstream_server:
self.c.set_server_address((request.host, request.port), self.c.set_server_address((request.host, request.port),
proxy.AddressPriority.FROM_PROTOCOL) proxy.AddressPriority.FROM_PROTOCOL)
self.c.establish_server_connection()
flow.server_conn = self.c.server_conn # Update server_conn attribute on the flow flow.server_conn = self.c.server_conn # Update server_conn attribute on the flow
self.c.client_conn.send( self.c.client_conn.send(
'HTTP/1.1 200 Connection established\r\n' + 'HTTP/1.1 200 Connection established\r\n' +
('Proxy-agent: %s\r\n' % self.c.server_version) + ('Proxy-agent: %s\r\n' % self.c.server_version) +
'\r\n' '\r\n'
) )
self.ssl_upgrade() self.ssl_upgrade()
self.skip_authentication = True self.skip_authentication = True
return False return False

View File

@ -181,6 +181,7 @@ class TemporaryServerChangeMixin(object):
self.c.del_server_connection() self.c.del_server_connection()
self.c.set_server_address(address, priority) self.c.set_server_address(address, priority)
self.c.establish_server_connection(ask=False)
if ssl: if ssl:
self.c.establish_ssl(server=True) self.c.establish_ssl(server=True)

View File

@ -146,15 +146,20 @@ class ConnectionHandler:
self.log("Set new server address: %s:%s" % (address.host, address.port), "debug") self.log("Set new server address: %s:%s" % (address.host, address.port), "debug")
self.server_conn = ServerConnection(address, priority) self.server_conn = ServerConnection(address, priority)
def establish_server_connection(self): def establish_server_connection(self, ask=True):
""" """
Establishes a new server connection. Establishes a new server connection.
If there is already an existing server connection, the function returns immediately. If there is already an existing server connection, the function returns immediately.
By default, this function ".ask"s the proxy master. This is deadly if this function is already called from the
master (e.g. via change_server), because this navigates us in a simple deadlock (the master is single-threaded).
In these scenarios, ask=False can be passed to suppress the call to the master.
""" """
if self.server_conn.connection: if self.server_conn.connection:
return return
self.log("serverconnect", "debug", ["%s:%s" % self.server_conn.address()[:2]]) self.log("serverconnect", "debug", ["%s:%s" % self.server_conn.address()[:2]])
self.channel.tell("serverconnect", self) if ask:
self.channel.ask("serverconnect", self)
try: try:
self.server_conn.connect() self.server_conn.connect()
except tcp.NetLibError, v: except tcp.NetLibError, v:
@ -185,9 +190,10 @@ class ConnectionHandler:
self.log("Establish SSL", "debug", subs) self.log("Establish SSL", "debug", subs)
if server: if server:
if not self.server_conn or not self.server_conn.connection:
raise ProxyError(502, "No server connection.")
if self.server_conn.ssl_established: if self.server_conn.ssl_established:
raise ProxyError(502, "SSL to Server already established.") raise ProxyError(502, "SSL to Server already established.")
self.establish_server_connection() # make sure there is a server connection.
self.server_conn.establish_ssl(self.config.clientcerts, self.sni) self.server_conn.establish_ssl(self.config.clientcerts, self.sni)
if client: if client:
if self.client_conn.ssl_established: if self.client_conn.ssl_established:

View File

@ -30,7 +30,7 @@ class TestDumpMaster:
m.handle_clientconnect(cc) m.handle_clientconnect(cc)
sc = proxy.connection.ServerConnection((req.get_host(), req.get_port()), None) sc = proxy.connection.ServerConnection((req.get_host(), req.get_port()), None)
sc.reply = mock.MagicMock() sc.reply = mock.MagicMock()
m.handle_serverconnection(sc) m.handle_serverconnect(sc)
m.handle_request(req) m.handle_request(req)
resp = tutils.tresp(req, content=content) resp = tutils.tresp(req, content=content)
f = m.handle_response(resp) f = m.handle_response(resp)

View File

@ -589,7 +589,7 @@ class TestFlowMaster:
assert fm.scripts[0].ns["log"][-1] == "clientconnect" assert fm.scripts[0].ns["log"][-1] == "clientconnect"
sc = ServerConnection((req.get_host(), req.get_port()), None) sc = ServerConnection((req.get_host(), req.get_port()), None)
sc.reply = controller.DummyReply() sc.reply = controller.DummyReply()
fm.handle_serverconnection(sc) fm.handle_serverconnect(sc)
assert fm.scripts[0].ns["log"][-1] == "serverconnect" assert fm.scripts[0].ns["log"][-1] == "serverconnect"
f = fm.handle_request(req) f = fm.handle_request(req)
assert fm.scripts[0].ns["log"][-1] == "request" assert fm.scripts[0].ns["log"][-1] == "request"