diff options
-rw-r--r-- | mitmproxy/addons/__init__.py | 2 | ||||
-rw-r--r-- | mitmproxy/addons/check_alpn.py | 17 | ||||
-rw-r--r-- | mitmproxy/net/tcp.py | 47 | ||||
-rw-r--r-- | mitmproxy/tools/main.py | 2 | ||||
-rw-r--r-- | mitmproxy/utils/version_check.py | 42 | ||||
-rw-r--r-- | pathod/pathoc.py | 8 | ||||
-rw-r--r-- | test/conftest.py | 13 | ||||
-rw-r--r-- | test/mitmproxy/addons/test_check_alpn.py | 23 | ||||
-rw-r--r-- | test/mitmproxy/net/test_tcp.py | 41 | ||||
-rw-r--r-- | test/mitmproxy/proxy/protocol/test_http2.py | 12 | ||||
-rw-r--r-- | test/mitmproxy/utils/test_version_check.py | 25 | ||||
-rw-r--r-- | test/pathod/protocols/test_http2.py | 4 | ||||
-rw-r--r-- | test/pathod/test_pathoc.py | 15 | ||||
-rw-r--r-- | test/pathod/test_pathod.py | 6 |
14 files changed, 29 insertions, 228 deletions
diff --git a/mitmproxy/addons/__init__.py b/mitmproxy/addons/__init__.py index 24cf2270..62135765 100644 --- a/mitmproxy/addons/__init__.py +++ b/mitmproxy/addons/__init__.py @@ -1,7 +1,6 @@ from mitmproxy.addons import allowremote from mitmproxy.addons import anticache from mitmproxy.addons import anticomp -from mitmproxy.addons import check_alpn from mitmproxy.addons import check_ca from mitmproxy.addons import clientplayback from mitmproxy.addons import core_option_validation @@ -29,7 +28,6 @@ def default_addons(): allowremote.AllowRemote(), anticache.AntiCache(), anticomp.AntiComp(), - check_alpn.CheckALPN(), check_ca.CheckCA(), clientplayback.ClientPlayback(), cut.Cut(), diff --git a/mitmproxy/addons/check_alpn.py b/mitmproxy/addons/check_alpn.py deleted file mode 100644 index 193159b2..00000000 --- a/mitmproxy/addons/check_alpn.py +++ /dev/null @@ -1,17 +0,0 @@ -import mitmproxy -from mitmproxy.net import tcp -from mitmproxy import ctx - - -class CheckALPN: - def __init__(self): - self.failed = False - - def configure(self, updated): - self.failed = mitmproxy.ctx.master.options.http2 and not tcp.HAS_ALPN - if self.failed: - ctx.log.warn( - "HTTP/2 is disabled because ALPN support missing!\n" - "OpenSSL 1.0.2+ required to support HTTP/2 connections.\n" - "Use --no-http2 to silence this warning." - ) diff --git a/mitmproxy/net/tcp.py b/mitmproxy/net/tcp.py index fce0b744..0c2f0e28 100644 --- a/mitmproxy/net/tcp.py +++ b/mitmproxy/net/tcp.py @@ -14,18 +14,12 @@ from typing import Optional # noqa from mitmproxy.utils import strutils import certifi -import OpenSSL from OpenSSL import SSL from mitmproxy import certs -from mitmproxy.utils import version_check from mitmproxy import exceptions from mitmproxy.types import basethread -# This is a rather hackish way to make sure that -# the latest version of pyOpenSSL is actually installed. -version_check.check_pyopenssl_version() - socket_fileobject = socket.SocketIO # workaround for https://bugs.python.org/issue29515 @@ -33,7 +27,6 @@ socket_fileobject = socket.SocketIO IPPROTO_IPV6 = getattr(socket, "IPPROTO_IPV6", 41) EINTR = 4 -HAS_ALPN = SSL._lib.Cryptography_HAS_ALPN # To enable all SSL methods use: SSLv23 # then add options to disable certain methods @@ -503,7 +496,6 @@ class _Connection: if cipher_list: try: context.set_cipher_list(cipher_list.encode()) - context.set_tmp_ecdh(OpenSSL.crypto.get_elliptic_curve('prime256v1')) except SSL.Error as v: raise exceptions.TlsException("SSL cipher specification error: %s" % str(v)) @@ -511,24 +503,23 @@ class _Connection: if log_ssl_key: context.set_info_callback(log_ssl_key) - if HAS_ALPN: # pragma: openssl-old no cover - if alpn_protos is not None: - # advertise application layer protocols - context.set_alpn_protos(alpn_protos) - elif alpn_select is not None and alpn_select_callback is None: - # select application layer protocol - def alpn_select_callback(conn_, options): - if alpn_select in options: - return bytes(alpn_select) - else: # pragma: no cover - return options[0] - context.set_alpn_select_callback(alpn_select_callback) - elif alpn_select_callback is not None and alpn_select is None: - if not callable(alpn_select_callback): - raise exceptions.TlsException("ALPN error: alpn_select_callback must be a function.") - context.set_alpn_select_callback(alpn_select_callback) - elif alpn_select_callback is not None and alpn_select is not None: - raise exceptions.TlsException("ALPN error: only define alpn_select (string) OR alpn_select_callback (function).") + if alpn_protos is not None: + # advertise application layer protocols + context.set_alpn_protos(alpn_protos) + elif alpn_select is not None and alpn_select_callback is None: + # select application layer protocol + def alpn_select_callback(conn_, options): + if alpn_select in options: + return bytes(alpn_select) + else: # pragma: no cover + return options[0] + context.set_alpn_select_callback(alpn_select_callback) + elif alpn_select_callback is not None and alpn_select is None: + if not callable(alpn_select_callback): + raise exceptions.TlsException("ALPN error: alpn_select_callback must be a function.") + context.set_alpn_select_callback(alpn_select_callback) + elif alpn_select_callback is not None and alpn_select is not None: + raise exceptions.TlsException("ALPN error: only define alpn_select (string) OR alpn_select_callback (function).") return context @@ -720,7 +711,7 @@ class TCPClient(_Connection): return self.connection.gettimeout() def get_alpn_proto_negotiated(self): - if HAS_ALPN and self.ssl_established: # pragma: openssl-old no cover + if self.ssl_established: return self.connection.get_alpn_proto_negotiated() else: return b"" @@ -827,7 +818,7 @@ class BaseHandler(_Connection): self.connection.settimeout(n) def get_alpn_proto_negotiated(self): - if HAS_ALPN and self.ssl_established: # pragma: openssl-old no cover + if self.ssl_established: return self.connection.get_alpn_proto_negotiated() else: return b"" diff --git a/mitmproxy/tools/main.py b/mitmproxy/tools/main.py index 7debb3e0..58900d29 100644 --- a/mitmproxy/tools/main.py +++ b/mitmproxy/tools/main.py @@ -16,7 +16,6 @@ from mitmproxy import exceptions # noqa from mitmproxy import options # noqa from mitmproxy import optmanager # noqa from mitmproxy import proxy # noqa -from mitmproxy.utils import version_check # noqa from mitmproxy.utils import debug # noqa @@ -58,7 +57,6 @@ def run(MasterKlass, args, extra=None): # pragma: no cover extra: Extra argument processing callable which returns a dict of options. """ - version_check.check_pyopenssl_version() debug.register_info_dumpers() opts = options.Options() diff --git a/mitmproxy/utils/version_check.py b/mitmproxy/utils/version_check.py deleted file mode 100644 index 22d6d75c..00000000 --- a/mitmproxy/utils/version_check.py +++ /dev/null @@ -1,42 +0,0 @@ -""" -Having installed a wrong version of pyOpenSSL is unfortunately a very common -source of error. Check before every start that both versions are somewhat okay. -""" -import sys -import inspect -import os.path - -import OpenSSL - -PYOPENSSL_MIN_VERSION = (16, 0) - - -def check_pyopenssl_version(min_version=PYOPENSSL_MIN_VERSION, fp=sys.stderr): - min_version_str = ".".join(str(x) for x in min_version) - try: - v = tuple(int(x) for x in OpenSSL.__version__.split(".")[:2]) - except ValueError: - print( - "Cannot parse pyOpenSSL version: {}" - "mitmproxy requires pyOpenSSL {} or greater.".format( - OpenSSL.__version__, min_version_str - ), - file=fp - ) - return - if v < min_version: - print( - "You are using an outdated version of pyOpenSSL: " - "mitmproxy requires pyOpenSSL {} or greater.".format(min_version_str), - file=fp - ) - # Some users apparently have multiple versions of pyOpenSSL installed. - # Report which one we got. - pyopenssl_path = os.path.dirname(inspect.getfile(OpenSSL)) - print( - "Your pyOpenSSL {} installation is located at {}".format( - OpenSSL.__version__, pyopenssl_path - ), - file=fp - ) - sys.exit(1) diff --git a/pathod/pathoc.py b/pathod/pathoc.py index 4a613349..63a15b55 100644 --- a/pathod/pathoc.py +++ b/pathod/pathoc.py @@ -223,14 +223,6 @@ class Pathoc(tcp.TCPClient): self.ws_framereader = None if self.use_http2: - if not tcp.HAS_ALPN: # pragma: no cover - log.write_raw( - self.fp, - "HTTP/2 requires ALPN support. " - "Please use OpenSSL >= 1.0.2. " - "Pathoc might not be working as expected without ALPN.", - timestamp=False - ) self.protocol = http2.HTTP2StateProtocol(self, dump_frames=self.http2_framedump) else: self.protocol = net_http.http1 diff --git a/test/conftest.py b/test/conftest.py index bb913548..b0842bc3 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,15 +1,8 @@ import os import pytest -import OpenSSL - -import mitmproxy.net.tcp pytest_plugins = ('test.full_coverage_plugin',) -requires_alpn = pytest.mark.skipif( - not mitmproxy.net.tcp.HAS_ALPN, - reason='requires OpenSSL with ALPN support') - skip_windows = pytest.mark.skipif( os.name == "nt", reason='Skipping due to Windows' @@ -24,9 +17,3 @@ skip_appveyor = pytest.mark.skipif( "APPVEYOR" in os.environ, reason='Skipping due to Appveyor' ) - - -@pytest.fixture() -def disable_alpn(monkeypatch): - monkeypatch.setattr(mitmproxy.net.tcp, 'HAS_ALPN', False) - monkeypatch.setattr(OpenSSL.SSL._lib, 'Cryptography_HAS_ALPN', False) diff --git a/test/mitmproxy/addons/test_check_alpn.py b/test/mitmproxy/addons/test_check_alpn.py deleted file mode 100644 index 2b1d6058..00000000 --- a/test/mitmproxy/addons/test_check_alpn.py +++ /dev/null @@ -1,23 +0,0 @@ -from mitmproxy.addons import check_alpn -from mitmproxy.test import taddons -from ...conftest import requires_alpn - - -class TestCheckALPN: - - @requires_alpn - def test_check_alpn(self): - msg = 'ALPN support missing' - - with taddons.context() as tctx: - a = check_alpn.CheckALPN() - tctx.configure(a) - assert not tctx.master.has_log(msg) - - def test_check_no_alpn(self, disable_alpn): - msg = 'ALPN support missing' - - with taddons.context() as tctx: - a = check_alpn.CheckALPN() - tctx.configure(a) - assert tctx.master.has_log(msg) diff --git a/test/mitmproxy/net/test_tcp.py b/test/mitmproxy/net/test_tcp.py index 73de0879..3345840e 100644 --- a/test/mitmproxy/net/test_tcp.py +++ b/test/mitmproxy/net/test_tcp.py @@ -3,7 +3,6 @@ import queue import time import socket import random -import os import threading import pytest from unittest import mock @@ -15,7 +14,6 @@ from mitmproxy import exceptions from mitmproxy.test import tutils from . import tservers -from ...conftest import requires_alpn class EchoHandler(tcp.BaseHandler): @@ -534,36 +532,18 @@ class TestTimeOut(tservers.ServerTestBase): c.rfile.read(10) -class TestCryptographyALPN: - - def test_has_alpn(self): - if os.environ.get("OPENSSL") == "with-alpn": - assert tcp.HAS_ALPN - assert SSL._lib.Cryptography_HAS_ALPN - elif os.environ.get("OPENSSL") == "old": - assert not tcp.HAS_ALPN - assert not SSL._lib.Cryptography_HAS_ALPN - - class TestALPNClient(tservers.ServerTestBase): handler = ALPNHandler ssl = dict( alpn_select=b"bar" ) - @requires_alpn - @pytest.mark.parametrize('has_alpn,alpn_protos, expected_negotiated, expected_response', [ - (True, [b"foo", b"bar", b"fasel"], b'bar', b'bar'), - (True, [], b'', b'NONE'), - (True, None, b'', b'NONE'), - (False, [b"foo", b"bar", b"fasel"], b'', b'NONE'), - (False, [], b'', b'NONE'), - (False, None, b'', b'NONE'), + @pytest.mark.parametrize('alpn_protos, expected_negotiated, expected_response', [ + ([b"foo", b"bar", b"fasel"], b'bar', b'bar'), + ([], b'', b'NONE'), + (None, b'', b'NONE'), ]) - def test_alpn(self, monkeypatch, has_alpn, alpn_protos, expected_negotiated, expected_response): - monkeypatch.setattr(tcp, 'HAS_ALPN', has_alpn) - monkeypatch.setattr(SSL._lib, 'Cryptography_HAS_ALPN', has_alpn) - + def test_alpn(self, monkeypatch, alpn_protos, expected_negotiated, expected_response): c = tcp.TCPClient(("127.0.0.1", self.port)) with c.connect(): c.convert_to_ssl(alpn_protos=alpn_protos) @@ -574,7 +554,7 @@ class TestALPNClient(tservers.ServerTestBase): class TestNoSSLNoALPNClient(tservers.ServerTestBase): handler = ALPNHandler - def test_no_ssl_no_alpn(self, disable_alpn): + def test_no_ssl_no_alpn(self): c = tcp.TCPClient(("127.0.0.1", self.port)) with c.connect(): assert c.get_alpn_proto_negotiated() == b"" @@ -857,9 +837,8 @@ class TestSSLInvalid(tservers.ServerTestBase): def test_alpn_error(self): c = tcp.TCPClient(("127.0.0.1", self.port)) with c.connect(): - if tcp.HAS_ALPN: - with pytest.raises(exceptions.TlsException, match="must be a function"): - c.create_ssl_context(alpn_select_callback="foo") + with pytest.raises(exceptions.TlsException, match="must be a function"): + c.create_ssl_context(alpn_select_callback="foo") - with pytest.raises(exceptions.TlsException, match="ALPN error"): - c.create_ssl_context(alpn_select="foo", alpn_select_callback="bar") + with pytest.raises(exceptions.TlsException, match="ALPN error"): + c.create_ssl_context(alpn_select="foo", alpn_select_callback="bar") diff --git a/test/mitmproxy/proxy/protocol/test_http2.py b/test/mitmproxy/proxy/protocol/test_http2.py index 487d8890..583e6e27 100644 --- a/test/mitmproxy/proxy/protocol/test_http2.py +++ b/test/mitmproxy/proxy/protocol/test_http2.py @@ -17,7 +17,6 @@ from mitmproxy.net.http import http1, http2 from pathod.language import generators from ... import tservers -from ....conftest import requires_alpn import logging logging.getLogger("hyper.packages.hpack.hpack").setLevel(logging.WARNING) @@ -203,7 +202,6 @@ class _Http2Test(_Http2TestBase, _Http2ServerBase): _Http2ServerBase.teardown_class() -@requires_alpn class TestSimple(_Http2Test): request_body_buffer = b'' @@ -286,7 +284,6 @@ class TestSimple(_Http2Test): assert response_body_buffer == b'response body' -@requires_alpn class TestRequestWithPriority(_Http2Test): @classmethod @@ -368,7 +365,6 @@ class TestRequestWithPriority(_Http2Test): assert resp.headers.get('priority_weight', None) == expected_priority[2] -@requires_alpn class TestPriority(_Http2Test): @classmethod @@ -453,7 +449,6 @@ class TestPriority(_Http2Test): assert self.priority_data == expected_priority -@requires_alpn class TestStreamResetFromServer(_Http2Test): @classmethod @@ -504,7 +499,6 @@ class TestStreamResetFromServer(_Http2Test): assert self.master.state.flows[0].response is None -@requires_alpn class TestBodySizeLimit(_Http2Test): @classmethod @@ -554,7 +548,6 @@ class TestBodySizeLimit(_Http2Test): assert len(self.master.state.flows) == 0 -@requires_alpn class TestPushPromise(_Http2Test): @classmethod @@ -723,7 +716,6 @@ class TestPushPromise(_Http2Test): # the other two bodies might not be transmitted before the reset -@requires_alpn class TestConnectionLost(_Http2Test): @classmethod @@ -765,7 +757,6 @@ class TestConnectionLost(_Http2Test): assert self.master.state.flows[0].response is None -@requires_alpn class TestMaxConcurrentStreams(_Http2Test): @classmethod @@ -826,7 +817,6 @@ class TestMaxConcurrentStreams(_Http2Test): assert b"Stream-ID " in flow.response.content -@requires_alpn class TestConnectionTerminated(_Http2Test): @classmethod @@ -867,7 +857,6 @@ class TestConnectionTerminated(_Http2Test): assert connection_terminated_event.additional_data == b'foobar' -@requires_alpn class TestRequestStreaming(_Http2Test): @classmethod @@ -926,7 +915,6 @@ class TestRequestStreaming(_Http2Test): assert connection_terminated_event is None -@requires_alpn class TestResponseStreaming(_Http2Test): @classmethod diff --git a/test/mitmproxy/utils/test_version_check.py b/test/mitmproxy/utils/test_version_check.py deleted file mode 100644 index d7929378..00000000 --- a/test/mitmproxy/utils/test_version_check.py +++ /dev/null @@ -1,25 +0,0 @@ -import io -from unittest import mock -from mitmproxy.utils import version_check - - -@mock.patch("sys.exit") -def test_check_pyopenssl_version(sexit): - fp = io.StringIO() - version_check.check_pyopenssl_version(fp=fp) - assert not fp.getvalue() - assert not sexit.called - - version_check.check_pyopenssl_version((9999,), fp=fp) - assert "outdated" in fp.getvalue() - assert sexit.called - - -@mock.patch("sys.exit") -@mock.patch("OpenSSL.__version__") -def test_unparseable_pyopenssl_version(version, sexit): - version.split.return_value = ["foo", "bar"] - fp = io.StringIO() - version_check.check_pyopenssl_version(fp=fp) - assert "Cannot parse" in fp.getvalue() - assert not sexit.called diff --git a/test/pathod/protocols/test_http2.py b/test/pathod/protocols/test_http2.py index c16a6d40..b1eebc73 100644 --- a/test/pathod/protocols/test_http2.py +++ b/test/pathod/protocols/test_http2.py @@ -11,8 +11,6 @@ from ...mitmproxy.net import tservers as net_tservers from pathod.protocols.http2 import HTTP2StateProtocol, TCPHandler -from ...conftest import requires_alpn - class TestTCPHandlerWrapper: def test_wrapped(self): @@ -68,7 +66,6 @@ class TestProtocol: assert mock_server_method.called -@requires_alpn class TestCheckALPNMatch(net_tservers.ServerTestBase): handler = EchoHandler ssl = dict( @@ -83,7 +80,6 @@ class TestCheckALPNMatch(net_tservers.ServerTestBase): assert protocol.check_alpn() -@requires_alpn class TestCheckALPNMismatch(net_tservers.ServerTestBase): handler = EchoHandler ssl = dict( diff --git a/test/pathod/test_pathoc.py b/test/pathod/test_pathoc.py index 2dd29e20..4b50e2a7 100644 --- a/test/pathod/test_pathoc.py +++ b/test/pathod/test_pathoc.py @@ -11,7 +11,6 @@ from pathod.protocols.http2 import HTTP2StateProtocol from mitmproxy.test import tutils from . import tservers -from ..conftest import requires_alpn def test_response(): @@ -216,7 +215,6 @@ class TestDaemonHTTP2(PathocTestDaemon): ssl = True explain = False - @requires_alpn def test_http2(self): c = pathoc.Pathoc( ("127.0.0.1", self.d.port), @@ -231,7 +229,6 @@ class TestDaemonHTTP2(PathocTestDaemon): ) assert c.protocol == http1 - @requires_alpn def test_http2_alpn(self): c = pathoc.Pathoc( ("127.0.0.1", self.d.port), @@ -248,7 +245,6 @@ class TestDaemonHTTP2(PathocTestDaemon): _, kwargs = c.convert_to_ssl.call_args assert set(kwargs['alpn_protos']) == set([b'http/1.1', b'h2']) - @requires_alpn def test_request(self): c = pathoc.Pathoc( ("127.0.0.1", self.d.port), @@ -259,14 +255,3 @@ class TestDaemonHTTP2(PathocTestDaemon): with c.connect(): resp = c.request("get:/p/200") assert resp.status_code == 200 - - def test_failing_request(self, disable_alpn): - c = pathoc.Pathoc( - ("127.0.0.1", self.d.port), - fp=None, - ssl=True, - use_http2=True, - ) - with pytest.raises(NotImplementedError): - with c.connect(): - c.request("get:/p/200") diff --git a/test/pathod/test_pathod.py b/test/pathod/test_pathod.py index 88480a59..5f191c0d 100644 --- a/test/pathod/test_pathod.py +++ b/test/pathod/test_pathod.py @@ -8,7 +8,6 @@ from mitmproxy import exceptions from mitmproxy.test import tutils from . import tservers -from ..conftest import requires_alpn class TestPathod: @@ -257,11 +256,6 @@ class TestHTTP2(tservers.DaemonTests): ssl = True nohang = True - @requires_alpn def test_http2(self): r, _ = self.pathoc(["GET:/"], ssl=True, use_http2=True) assert r[0].status_code == 800 - - def test_no_http2(self, disable_alpn): - with pytest.raises(NotImplementedError): - r, _ = self.pathoc(["GET:/"], ssl=True, use_http2=True) |