def test_proxy_client_factory_prepare_mangle_req(mocker, freeze): freeze.freeze(datetime.datetime(2015, 1, 1, 3, 30, 15, 50)) req = http.Request('GET / HTTP/1.1\r\n\r\n') mangreq = http.Request('BOOO / HTTP/1.1\r\n\r\n') def inc_day_mangle(x, y): freeze.delta(days=1) return mock_deferred((mangreq, True)) rsave = mocker.patch.object(pappyproxy.http.Request, 'async_deep_save', autospec=True, side_effect=mock_req_async_save) mocker.patch('pappyproxy.context.in_scope').return_value = True mocker.patch('pappyproxy.macros.mangle_request', side_effect=inc_day_mangle) cf = ProxyClientFactory(req, save_all=True, stream_response=False, return_transport=None) yield cf.prepare_request() assert cf.request == mangreq assert req.time_start == datetime.datetime(2015, 1, 1, 3, 30, 15, 50) assert cf.request.time_start == datetime.datetime(2015, 1, 2, 3, 30, 15, 50) assert cf.request.reqid is not None assert len(rsave.mock_calls) == 2
def update(dbpool): for query in update_queries: yield dbpool.runQuery(query) # Update metadata for each request reqrows = yield dbpool.runQuery( """ SELECT id, full_request FROM requests; """, ) # Create an object that will parse the host from the request for reqrow in reqrows: reqid = reqrow[0] fullreq = reqrow[1] r = http.Request(fullreq) host = r.host if r.host: yield dbpool.runQuery( """ UPDATE requests SET host=? WHERE id=?; """, (host, reqid)) yield dbpool.runQuery(""" UPDATE schema_meta SET version=4; """)
def mock_int_macro(modified_req=None, modified_rsp=None, drop_req=False, drop_rsp=False): macro = mock.MagicMock() if modified_req or drop_req: macro.async_req = True macro.intercept_requests = True if drop_req: newreq = None else: newreq = http.Request(modified_req) macro.async_mangle_request.return_value = mock_deferred(newreq) else: macro.intercept_requests = False if modified_rsp or drop_rsp: macro.async_rsp = True macro.intercept_responses = True if drop_rsp: newrsp = None else: newrsp = http.Response(modified_rsp) macro.async_mangle_response.return_value = mock_deferred(newrsp) else: macro.intercept_responses = False return macro
def async_mangle_request(request): # This function gets called to mangle/edit requests passed through the proxy retreq = request # Write original request to the temp file with tempfile.NamedTemporaryFile(delete=False) as tf: tfName = tf.name tf.write(request.full_request) # Have the console edit the file yield pappyproxy.console.edit_file(tfName) # Create new mangled request from edited file with open(tfName, 'r') as f: text = f.read() os.remove(tfName) # Check if dropped if text == '': pappyproxy.proxy.log('Request dropped!') defer.returnValue(None) mangled_req = http.Request(text, update_content_length=True) mangled_req.port = request.port mangled_req.is_ssl = request.is_ssl # Check if it changed if mangled_req.full_request != request.full_request: retreq = mangled_req defer.returnValue(retreq)
def test_proxy_client_factory_prepare_reqs_simple(mocker, freeze): import datetime freeze.freeze(datetime.datetime(2015, 1, 1, 3, 30, 15, 50)) req = http.Request('GET / HTTP/1.1\r\n\r\n') rsave = mocker.patch.object(pappyproxy.http.Request, 'async_deep_save', autospec=True, side_effect=mock_req_async_save) rsave.return_value = mock_deferred() mocker.patch('pappyproxy.context.in_scope').return_value = True mocker.patch( 'pappyproxy.macros.mangle_request').return_value = mock_deferred( (req, False)) cf = ProxyClientFactory(req, save_all=False, stream_response=False, return_transport=None) yield cf.prepare_request() assert req.time_start == datetime.datetime(2015, 1, 1, 3, 30, 15, 50) assert req.reqid is None assert not rsave.called assert len(rsave.mock_calls) == 0
def test_proxy_server_make_ssl_connection_socks_username_only(mocker): socks_config(mocker, {'host': '12345', 'port': 5555, 'username': '******'}) tls_wrap_class = mocker.patch("txsocksx.tls.TLSWrapClientEndpoint") tls_wrape = tls_wrap_class.return_value = mock.MagicMock() mtcpe_class = mocker.patch("twisted.internet.endpoints.TCP4ClientEndpoint") mtcpe_class.return_value = mtcpe = mock.MagicMock() socks_class = mocker.patch("txsocksx.client.SOCKS5ClientEndpoint") socks_class.return_value = sockse = mock.MagicMock() server_protocol = gen_server_protocol() server_protocol._client_factory = mock.MagicMock( ) # We already tested that this gets set up correctly req = http.Request("GET / HTTP/1.1\r\n\r\n") req.host = 'Foo.Bar.Brazzers' req.port = 80085 req.is_ssl = True server_protocol._request_obj = req yield server_protocol._make_remote_connection(req) sargs, skwargs = socks_class.call_args targs, tkwargs = mtcpe_class.call_args assert targs[1] == '12345' assert targs[2] == 5555 assert sargs[0] == 'Foo.Bar.Brazzers' assert sargs[1] == 80085 assert sargs[2] == mtcpe assert skwargs == {'methods': {'anonymous': ()}} assert not sockse.called tls_wrape.connect.assert_called_once_with(server_protocol._client_factory)
def update(dbpool): for query in update_queries: yield dbpool.runQuery(query) # Update metadata for each request reqrows = yield dbpool.runQuery( """ SELECT id, full_request FROM requests; """, ) # Create an object and get its port/is_ssl for reqrow in reqrows: reqid = reqrow[0] fullreq = reqrow[1] r = http.Request(fullreq) port = r.port is_ssl = r.is_ssl yield dbpool.runQuery( """ UPDATE requests SET port=?,is_ssl=? WHERE id=?; """, (port, is_ssl, reqid)) yield dbpool.runQuery(""" UPDATE schema_meta SET version=2; """)
def __init__(self, *args, **kwargs): global next_connection_id self.connection_id = get_next_connection_id() self._request_obj = http.Request() self._connect_response = False self._forward = True self._connect_uri = None
def full_request_received(self, *args, **kwargs): global cached_certs self.log('End of request', verbosity_level=3) if self._connect_response: self.log('Responding to browser CONNECT request', verbosity_level=3) okay_str = 'HTTP/1.1 200 Connection established\r\n\r\n' self.transport.write(okay_str) # Generate a cert for the hostname if not self._request_obj.host in cached_certs: log("Generating cert for '%s'" % self._request_obj.host, verbosity_level=3) (pkey, cert) = generate_cert(self._request_obj.host, config.CERT_DIR) cached_certs[self._request_obj.host] = (pkey, cert) else: log("Using cached cert for %s" % self._request_obj.host, verbosity_level=3) (pkey, cert) = cached_certs[self._request_obj.host] ctx = ServerTLSContext( private_key=pkey, certificate=cert, ) self.transport.startTLS(ctx, self.factory) if self._forward: self.log("Forwarding to %s on %d" % (self._request_obj.host, self._request_obj.port)) factory = ProxyClientFactory(self._request_obj, save_all=self.factory.save_all) factory.intercepting_macros = self.factory.intercepting_macros factory.connection_id = self.connection_id factory.data_defer.addCallback(self.send_response_back) if self._request_obj.is_ssl: self.log("Accessing over SSL...", verbosity_level=3) reactor.connectSSL(self._request_obj.host, self._request_obj.port, factory, ClientTLSContext()) else: self.log("Accessing over TCP...", verbosity_level=3) reactor.connectTCP(self._request_obj.host, self._request_obj.port, factory) # Reset per-request variables self.log("Resetting per-request data", verbosity_level=3) self._connect_response = False self._forward = True self._request_obj = http.Request() if self._connect_uri: self._request_obj.url = self._connect_uri self.setLineMode()
def test_proxy_client_simple(mocker): rsave = mocker.patch.object(pappyproxy.http.Request, 'async_deep_save', autospec=True, side_effect=mock_req_async_save) req = http.Request('GET / HTTP/1.1\r\n\r\n') client = gen_client_protocol(req, stream_response=False) assert client.transport.value() == 'GET / HTTP/1.1\r\n\r\n' client.transport.clear() rsp = 'HTTP/1.1 200 OKILE DOKELY\r\n\r\n' client.dataReceived(rsp) retpair = yield client.data_defer assert retpair.response.full_message == rsp
def _reset(self): # Reset per-request variables and have the request default to using # some parameters from the connect request self.log("Resetting per-request data", verbosity_level=3) self._connect_response = False self._request_obj = http.Request() if self._connect_uri: self._request_obj.url = self._connect_uri if self._connect_host: self._request_obj._host = self._connect_host if self._connect_ssl: self._request_obj.is_ssl = self._connect_ssl if self._connect_port: self._request_obj.port = self._connect_port self.setLineMode()
def test_proxy_client_nostream(mocker): rsave = mocker.patch.object(pappyproxy.http.Request, 'async_deep_save', autospec=True, side_effect=mock_req_async_save) req = http.Request('GET / HTTP/1.1\r\n\r\n') client = gen_client_protocol(req, stream_response=False) client.transport.clear() client.dataReceived('HTTP/1.1 404 GET FUCKE') assert client.factory.return_transport.value() == '' client.factory.return_transport.clear() client.dataReceived('D ASSHOLE\r\nContent-Length: 4\r\n\r\nABCD') assert client.factory.return_transport.value() == '' retpair = yield client.data_defer assert retpair.response.full_message == 'HTTP/1.1 404 GET F****D ASSHOLE\r\nContent-Length: 4\r\n\r\nABCD'
def gen_connection(send_data, new_req=False, new_rsp=False, drop_req=False, drop_rsp=False): factory = ProxyClientFactory(http.Request(send_data)) macro = gen_mangle_macro(new_req, new_rsp, drop_req, drop_rsp) factory.intercepting_macros['pappy_mangle'] = macro protocol = factory.buildProtocol(None) tr = FakeTransport(protocol, True) protocol.makeConnection(tr) sent = yield protocol.data_defer print sent defer.returnValue((protocol, sent, factory.data_defer))
def test_proxy_server_make_ssl_connection(mocker, server_protocol): mssle_class = mocker.patch("twisted.internet.endpoints.SSL4ClientEndpoint") mssle_class.return_value = mssle = mock.MagicMock() mssle.connect.return_value = mock_deferred() server_protocol._client_factory = mock.MagicMock( ) # We already tested that this gets set up correctly req = http.Request("GET / HTTP/1.1\r\n\r\n", is_ssl=True) req.host = 'Foo.Bar.Brazzers' req.port = 80085 server_protocol._request_obj = req yield server_protocol._make_remote_connection(req) targs, tkwargs = mssle_class.call_args assert targs[1] == 'Foo.Bar.Brazzers' assert targs[2] == 80085 assert tkwargs == {} mssle.connect.assert_called_once_with(server_protocol._client_factory)
def test_proxy_client_factory_prepare_reqs_360_noscope(mocker, freeze): import datetime freeze.freeze(datetime.datetime(2015, 1, 1, 3, 30, 15, 50)) req = http.Request('GET / HTTP/1.1\r\n\r\n') rsave = mocker.patch('pappyproxy.http.Request.async_deep_save') rsave.return_value = mock_deferred() mocker.patch('pappyproxy.context.in_scope').return_value = False mocker.patch('pappyproxy.macros.mangle_request', new=func_deleted) cf = ProxyClientFactory(req, save_all=True, stream_response=False, return_transport=None) yield cf.prepare_request() assert req.time_start == None assert req.reqid is None assert not rsave.called assert len(rsave.mock_calls) == 0
def req_mangler_change(request): req = http.Request('GET /mangled HTTP/1.1\r\n\r\n') d = mock_deferred(req) return d