sans-io adjustments

This commit is contained in:
Maximilian Hils 2020-12-11 13:47:47 +01:00
parent 39b0b6c110
commit 01f57346ee
9 changed files with 73 additions and 36 deletions

View File

@ -2,6 +2,7 @@ import os
import time import time
import typing import typing
import uuid import uuid
import warnings
from mitmproxy import certs from mitmproxy import certs
from mitmproxy import exceptions from mitmproxy import exceptions
@ -19,7 +20,6 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
Attributes: Attributes:
address: Remote address address: Remote address
tls_established: True if TLS is established, False otherwise tls_established: True if TLS is established, False otherwise
clientcert: The TLS client certificate
mitmcert: The MITM'ed TLS server certificate presented to the client mitmcert: The MITM'ed TLS server certificate presented to the client
timestamp_start: Connection start timestamp timestamp_start: Connection start timestamp
timestamp_tls_setup: TLS established timestamp timestamp_tls_setup: TLS established timestamp
@ -42,7 +42,6 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
self.wfile = None self.wfile = None
self.rfile = None self.rfile = None
self.address = None self.address = None
self.clientcert = None
self.tls_established = None self.tls_established = None
self.id = str(uuid.uuid4()) self.id = str(uuid.uuid4())
@ -91,7 +90,7 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
sockname = ("", 0) sockname = ("", 0)
error = None error = None
tls = None tls = None
certificate_list = None certificate_list = ()
alpn_offers = None alpn_offers = None
cipher_list = None cipher_list = None
@ -99,7 +98,6 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
id=str, id=str,
address=tuple, address=tuple,
tls_established=bool, tls_established=bool,
clientcert=certs.Cert,
mitmcert=certs.Cert, mitmcert=certs.Cert,
timestamp_start=float, timestamp_start=float,
timestamp_tls_setup=float, timestamp_tls_setup=float,
@ -119,6 +117,22 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
cipher_list=typing.List[str], cipher_list=typing.List[str],
) )
@property
def clientcert(self) -> typing.Optional[certs.Cert]: # pragma: no cover
warnings.warn(".clientcert is deprecated, use .certificate_list instead.", PendingDeprecationWarning)
if self.certificate_list:
return self.certificate_list[0]
else:
return None
@clientcert.setter
def clientcert(self, val): # pragma: no cover
warnings.warn(".clientcert is deprecated, use .certificate_list instead.", PendingDeprecationWarning)
if val:
self.certificate_list = [val]
else:
self.certificate_list = []
def send(self, message): def send(self, message):
if isinstance(message, list): if isinstance(message, list):
message = b''.join(message) message = b''.join(message)
@ -136,7 +150,6 @@ class ClientConnection(tcp.BaseHandler, stateobject.StateObject):
return cls.from_state(dict( return cls.from_state(dict(
id=str(uuid.uuid4()), id=str(uuid.uuid4()),
address=address, address=address,
clientcert=None,
mitmcert=None, mitmcert=None,
tls_established=False, tls_established=False,
timestamp_start=None, timestamp_start=None,
@ -192,7 +205,6 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
ip_address: Resolved remote IP address. ip_address: Resolved remote IP address.
source_address: Local IP address or client's source IP address. source_address: Local IP address or client's source IP address.
tls_established: True if TLS is established, False otherwise tls_established: True if TLS is established, False otherwise
cert: The certificate presented by the remote during the TLS handshake
sni: Server Name Indication sent by the proxy during the TLS handshake sni: Server Name Indication sent by the proxy during the TLS handshake
alpn_proto_negotiated: The negotiated application protocol alpn_proto_negotiated: The negotiated application protocol
tls_version: TLS version tls_version: TLS version
@ -249,7 +261,7 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
state = 0 state = 0
error = None error = None
tls = None tls = None
certificate_list = None certificate_list = ()
alpn_offers = None alpn_offers = None
cipher_name = None cipher_name = None
cipher_list = None cipher_list = None
@ -261,7 +273,6 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
ip_address=tuple, ip_address=tuple,
source_address=tuple, source_address=tuple,
tls_established=bool, tls_established=bool,
cert=certs.Cert,
sni=str, sni=str,
alpn_proto_negotiated=bytes, alpn_proto_negotiated=bytes,
tls_version=str, tls_version=str,
@ -280,6 +291,22 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
via2=None, via2=None,
) )
@property
def cert(self) -> typing.Optional[certs.Cert]: # pragma: no cover
warnings.warn(".cert is deprecated, use .certificate_list instead.", PendingDeprecationWarning)
if self.certificate_list:
return self.certificate_list[0]
else:
return None
@cert.setter
def cert(self, val): # pragma: no cover
warnings.warn(".cert is deprecated, use .certificate_list instead.", PendingDeprecationWarning)
if val:
self.certificate_list = [val]
else:
self.certificate_list = []
@classmethod @classmethod
def from_state(cls, state): def from_state(cls, state):
f = cls(tuple()) f = cls(tuple())
@ -292,7 +319,6 @@ class ServerConnection(tcp.TCPClient, stateobject.StateObject):
id=str(uuid.uuid4()), id=str(uuid.uuid4()),
address=address, address=address,
ip_address=address, ip_address=address,
cert=None,
sni=address[0], sni=address[0],
alpn_proto_negotiated=None, alpn_proto_negotiated=None,
tls_version=None, tls_version=None,

View File

@ -211,13 +211,13 @@ def convert_9_10(data):
def conv_cconn(conn): def conv_cconn(conn):
conn["sockname"] = ("", 0) conn["sockname"] = ("", 0)
cc = conn["clientcert"] cc = conn.pop("clientcert", None)
conn["certificate_list"] = [cc] if cc else None conn["certificate_list"] = [cc] if cc else []
conv_conn(conn) conv_conn(conn)
def conv_sconn(conn): def conv_sconn(conn):
crt = conn["cert"] crt = conn.pop("cert", None)
conn["certificate_list"] = [crt] if crt else None conn["certificate_list"] = [crt] if crt else []
conn["cipher_name"] = None conn["cipher_name"] = None
conn["via2"] = None conn["via2"] = None
conv_conn(conn) conv_conn(conn)

View File

@ -6,9 +6,9 @@ from mitmproxy import tcp
from mitmproxy import websocket from mitmproxy import websocket
from mitmproxy import controller from mitmproxy import controller
from mitmproxy import http from mitmproxy import http
from mitmproxy import connections
from mitmproxy import flow from mitmproxy import flow
from mitmproxy.net import http as net_http from mitmproxy.net import http as net_http
from mitmproxy.utils import compat
from wsproto.frame_protocol import Opcode from wsproto.frame_protocol import Opcode
@ -147,16 +147,12 @@ def tdummyflow(client_conn=True, server_conn=True, err=None):
return f return f
def tclient_conn(): def tclient_conn() -> compat.Client:
""" c = compat.Client.from_state(dict(
@return: mitmproxy.proxy.connection.ClientConnection
"""
c = connections.ClientConnection.from_state(dict(
id=str(uuid.uuid4()), id=str(uuid.uuid4()),
address=("127.0.0.1", 22), address=("127.0.0.1", 22),
clientcert=None,
mitmcert=None, mitmcert=None,
tls_established=False, tls_established=True,
timestamp_start=946681200, timestamp_start=946681200,
timestamp_tls_setup=946681201, timestamp_tls_setup=946681201,
timestamp_end=946681206, timestamp_end=946681206,
@ -179,21 +175,17 @@ def tclient_conn():
return c return c
def tserver_conn(): def tserver_conn() -> compat.Server:
""" c = compat.Server.from_state(dict(
@return: mitmproxy.proxy.connection.ServerConnection
"""
c = connections.ServerConnection.from_state(dict(
id=str(uuid.uuid4()), id=str(uuid.uuid4()),
address=("address", 22), address=("address", 22),
source_address=("address", 22), source_address=("address", 22),
ip_address=("192.168.0.1", 22), ip_address=("192.168.0.1", 22),
cert=None,
timestamp_start=946681202, timestamp_start=946681202,
timestamp_tcp_setup=946681203, timestamp_tcp_setup=946681203,
timestamp_tls_setup=946681204, timestamp_tls_setup=946681204,
timestamp_end=946681205, timestamp_end=946681205,
tls_established=False, tls_established=True,
sni="address", sni="address",
alpn_proto_negotiated=None, alpn_proto_negotiated=None,
tls_version="TLSv1.2", tls_version="TLSv1.2",

View File

@ -1,7 +1,7 @@
import os import os
import socket import socket
from mitmproxy.utils import data from mitmproxy.utils import data, compat
import pytest import pytest
@ -22,6 +22,11 @@ skip_appveyor = pytest.mark.skipif(
reason='Skipping due to Appveyor' reason='Skipping due to Appveyor'
) )
skip_new_proxy_core = pytest.mark.skipif(
compat.new_proxy_core,
reason='Skipping legacy test for old proxy core'
)
try: try:
s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
s.bind(("::1", 0)) s.bind(("::1", 0))

View File

@ -10,6 +10,7 @@ from mitmproxy.addons import clientplayback
from mitmproxy.test import taddons from mitmproxy.test import taddons
from .. import tservers from .. import tservers
from ...conftest import skip_new_proxy_core
def tdump(path, flows): def tdump(path, flows):
@ -48,6 +49,7 @@ class TBase(tservers.HTTPProxyTest):
def addons(self): def addons(self):
return [clientplayback.ClientPlayback()] return [clientplayback.ClientPlayback()]
@skip_new_proxy_core
def test_replay(self): def test_replay(self):
cr = self.master.addons.get("clientplayback") cr = self.master.addons.get("clientplayback")
@ -164,6 +166,7 @@ class TestClientPlayback:
assert cp.count() == 0 assert cp.count() == 0
await ctx.master.await_log("live") await ctx.master.await_log("live")
@skip_new_proxy_core
def test_http2(self): def test_http2(self):
cp = clientplayback.ClientPlayback() cp = clientplayback.ClientPlayback()
with taddons.context(cp): with taddons.context(cp):

View File

@ -39,14 +39,14 @@ def test_extract(tdata):
["client_conn.address.host", "127.0.0.1"], ["client_conn.address.host", "127.0.0.1"],
["client_conn.tls_version", "TLSv1.2"], ["client_conn.tls_version", "TLSv1.2"],
["client_conn.sni", "address"], ["client_conn.sni", "address"],
["client_conn.tls_established", "false"], ["client_conn.tls_established", "true"],
["server_conn.address.port", "22"], ["server_conn.address.port", "22"],
["server_conn.address.host", "address"], ["server_conn.address.host", "address"],
["server_conn.ip_address.host", "192.168.0.1"], ["server_conn.ip_address.host", "192.168.0.1"],
["server_conn.tls_version", "TLSv1.2"], ["server_conn.tls_version", "TLSv1.2"],
["server_conn.sni", "address"], ["server_conn.sni", "address"],
["server_conn.tls_established", "false"], ["server_conn.tls_established", "true"],
] ]
for spec, expected in tests: for spec, expected in tests:
ret = cut.extract(spec, tf) ret = cut.extract(spec, tf)

View File

@ -12,10 +12,12 @@ from mitmproxy.net.http import http1
from mitmproxy.test import tflow from mitmproxy.test import tflow
from .net import tservers from .net import tservers
from pathod import test from pathod import test
from ..conftest import skip_new_proxy_core
class TestClientConnection: class TestClientConnection:
@skip_new_proxy_core
def test_send(self): def test_send(self):
c = tflow.tclient_conn() c = tflow.tclient_conn()
c.send(b'foobar') c.send(b'foobar')
@ -26,20 +28,22 @@ class TestClientConnection:
c.send(['string', 'not']) c.send(['string', 'not'])
assert c.wfile.getvalue() == b'foobarfoobar' assert c.wfile.getvalue() == b'foobarfoobar'
@skip_new_proxy_core
def test_repr(self): def test_repr(self):
c = tflow.tclient_conn() c = tflow.tclient_conn()
assert '127.0.0.1:22' in repr(c) assert '127.0.0.1:22' in repr(c)
assert 'ALPN' in repr(c) assert 'ALPN' in repr(c)
assert 'TLS' not in repr(c) assert 'TLS' in repr(c)
c.alpn_proto_negotiated = None c.alpn_proto_negotiated = None
c.tls_established = True c.tls_established = False
assert 'ALPN' not in repr(c) assert 'ALPN' not in repr(c)
assert 'TLS' in repr(c) assert 'TLS' not in repr(c)
c.address = None c.address = None
assert repr(c) assert repr(c)
@skip_new_proxy_core
def test_tls_established_property(self): def test_tls_established_property(self):
c = tflow.tclient_conn() c = tflow.tclient_conn()
c.tls_established = True c.tls_established = True
@ -82,6 +86,7 @@ class TestClientConnection:
class TestServerConnection: class TestServerConnection:
@skip_new_proxy_core
def test_send(self): def test_send(self):
c = tflow.tserver_conn() c = tflow.tserver_conn()
c.send(b'foobar') c.send(b'foobar')
@ -92,6 +97,7 @@ class TestServerConnection:
c.send(['string', 'not']) c.send(['string', 'not'])
assert c.wfile.getvalue() == b'foobarfoobar' assert c.wfile.getvalue() == b'foobarfoobar'
@skip_new_proxy_core
def test_repr(self): def test_repr(self):
c = tflow.tserver_conn() c = tflow.tserver_conn()
@ -115,6 +121,7 @@ class TestServerConnection:
c.address = None c.address = None
assert repr(c) assert repr(c)
@skip_new_proxy_core
def test_tls_established_property(self): def test_tls_established_property(self):
c = tflow.tserver_conn() c = tflow.tserver_conn()
c.tls_established = True c.tls_established = True

View File

@ -10,7 +10,7 @@ from mitmproxy.proxy import config
from mitmproxy.proxy.server import ConnectionHandler, DummyServer, ProxyServer from mitmproxy.proxy.server import ConnectionHandler, DummyServer, ProxyServer
from mitmproxy.tools import cmdline from mitmproxy.tools import cmdline
from mitmproxy.tools import main from mitmproxy.tools import main
from ..conftest import skip_windows from ..conftest import skip_windows, skip_new_proxy_core
class MockParser(argparse.ArgumentParser): class MockParser(argparse.ArgumentParser):
@ -74,6 +74,7 @@ class TestDummyServer:
class TestConnectionHandler: class TestConnectionHandler:
@skip_new_proxy_core
def test_fatal_error(self, capsys): def test_fatal_error(self, capsys):
opts = options.Options() opts = options.Options()
pconf = config.ProxyConfig(opts) pconf = config.ProxyConfig(opts)

View File

@ -1,10 +1,12 @@
import io import io
import pytest import pytest
from mitmproxy.io import tnetstring
from mitmproxy import flowfilter from mitmproxy import flowfilter
from mitmproxy.exceptions import Kill, ControlException from mitmproxy.exceptions import Kill, ControlException
from mitmproxy.io import tnetstring
from mitmproxy.test import tflow from mitmproxy.test import tflow
from ..conftest import skip_new_proxy_core
class TestWebSocketFlow: class TestWebSocketFlow:
@ -87,6 +89,7 @@ class TestWebSocketFlow:
tnetstring.dump(d, b) tnetstring.dump(d, b)
assert b.getvalue() assert b.getvalue()
@skip_new_proxy_core
def test_message_kill(self): def test_message_kill(self):
f = tflow.twebsocketflow() f = tflow.twebsocketflow()
assert not f.messages[-1].killed assert not f.messages[-1].killed