Permalink
Browse files

simplify ALPN and OpenSSL on macOS

  • Loading branch information...
1 parent 741c2b7 commit 1a36efbb6a2d689aaf05c6d7dd614072fd7d6c1c @Kriechi Kriechi committed Dec 1, 2016
View
@@ -1,15 +1,6 @@
sudo: false
language: python
-addons:
- apt:
- sources:
- # Debian sid currently holds OpenSSL 1.0.2
- # change this with future releases!
- - debian-sid
- packages:
- - libssl-dev
-
env:
global:
- CI_DEPS=codecov>=2.0.5
@@ -25,9 +16,21 @@ matrix:
language: generic
env: TOXENV=py35 BDIST=1
- python: 3.5
- env: TOXENV=py35 BDIST=1
+ env: TOXENV=py35 OPENSSL_OLD
+ addons:
+ apt:
+ packages:
+ - libssl-dev
- python: 3.5
- env: TOXENV=py35 NO_ALPN=1
+ env: TOXENV=py35 BDIST=1 OPENSSL_ALPN
+ addons:
+ apt:
+ sources:
+ # Debian sid currently holds OpenSSL 1.1.0
+ # change this with future releases!
+ - debian-sid
+ packages:
+ - libssl-dev
- python: 3.5
env: TOXENV=docs
git:
@@ -39,10 +42,8 @@ install:
- |
if [[ $TRAVIS_OS_NAME == "osx" ]]
then
- brew update || brew update # try again if it fails
- brew upgrade
- brew reinstall openssl
- brew reinstall pyenv
+ brew update || brew update
+ brew outdated pyenv || brew upgrade pyenv
eval "$(pyenv init -)"
env PYTHON_CONFIGURE_OPTS="--enable-framework" pyenv install --skip-existing 3.5.2
pyenv global 3.5.2
@@ -52,8 +53,8 @@ install:
- pip install tox
script:
+ - tox -- --cov mitmproxy --cov pathod -v
- |
- tox -- --cov mitmproxy --cov pathod -v
if [[ $BDIST == "1" ]]
then
git fetch --unshallow --tags
@@ -80,3 +81,4 @@ cache:
directories:
- $HOME/.pyenv
- $HOME/.cache/pip
+ # - $HOME/build/mitmproxy/mitmproxy/.tox
@@ -30,10 +30,7 @@
socket_fileobject = socket.SocketIO
EINTR = 4
-if os.environ.get("NO_ALPN"):
- HAS_ALPN = False
-else:
- HAS_ALPN = SSL._lib.Cryptography_HAS_ALPN
+HAS_ALPN = SSL._lib.Cryptography_HAS_ALPN
# To enable all SSL methods use: SSLv23
# then add options to disable certain methods
View
@@ -0,0 +1,14 @@
+import pytest
+import OpenSSL
+import mitmproxy.net.tcp
+
+
+requires_alpn = pytest.mark.skipif(
+ not mitmproxy.net.tcp.HAS_ALPN,
+ reason='requires OpenSSL with ALPN support')
+
+
+@pytest.fixture()
+def disable_alpn(monkeypatch):
+ monkeypatch.setattr(mitmproxy.net.tcp, 'HAS_ALPN', False)
+ monkeypatch.setattr(OpenSSL.SSL._lib, 'Cryptography_HAS_ALPN', False)
@@ -6,7 +6,7 @@
import os
import threading
import mock
-
+import pytest
from OpenSSL import SSL
from mitmproxy import certs
@@ -15,6 +15,7 @@
from mitmproxy import exceptions
from . import tservers
+from ...conftest import requires_alpn
class EchoHandler(tcp.BaseHandler):
@@ -526,40 +527,47 @@ def test_timeout(self):
tutils.raises(exceptions.TcpTimeout, c.rfile.read, 10)
+class TestCryptographyALPN:
+
+ def test_has_alpn(self):
+ if 'OPENSSL_ALPN' in os.environ:
+ assert tcp.HAS_ALPN
+ assert SSL._lib.Cryptography_HAS_ALPN
+ elif 'OPENSSL_OLD' in os.environ:
+ assert not tcp.HAS_ALPN
+ assert not SSL._lib.Cryptography_HAS_ALPN
+
+
class TestALPNClient(tservers.ServerTestBase):
handler = ALPNHandler
ssl = dict(
alpn_select=b"bar"
)
- if tcp.HAS_ALPN:
- def test_alpn(self):
- c = tcp.TCPClient(("127.0.0.1", self.port))
- with c.connect():
- c.convert_to_ssl(alpn_protos=[b"foo", b"bar", b"fasel"])
- assert c.get_alpn_proto_negotiated() == b"bar"
- assert c.rfile.readline().strip() == b"bar"
-
- def test_no_alpn(self):
- c = tcp.TCPClient(("127.0.0.1", self.port))
- with c.connect():
- c.convert_to_ssl()
- assert c.get_alpn_proto_negotiated() == b""
- assert c.rfile.readline().strip() == b"NONE"
+ @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'),
+ ])
+ 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)
- else:
- def test_none_alpn(self):
- c = tcp.TCPClient(("127.0.0.1", self.port))
- with c.connect():
- c.convert_to_ssl(alpn_protos=[b"foo", b"bar", b"fasel"])
- assert c.get_alpn_proto_negotiated() == b""
- assert c.rfile.readline() == b"NONE"
+ c = tcp.TCPClient(("127.0.0.1", self.port))
+ with c.connect():
+ c.convert_to_ssl(alpn_protos=alpn_protos)
+ assert c.get_alpn_proto_negotiated() == expected_negotiated
+ assert c.rfile.readline().strip() == expected_response
class TestNoSSLNoALPNClient(tservers.ServerTestBase):
handler = ALPNHandler
- def test_no_ssl_no_alpn(self):
+ def test_no_ssl_no_alpn(self, disable_alpn):
c = tcp.TCPClient(("127.0.0.1", self.port))
with c.connect():
assert c.get_alpn_proto_negotiated() == b""
@@ -1,7 +1,6 @@
# coding=utf-8
-import pytest
import os
import tempfile
import traceback
@@ -17,6 +16,7 @@
from mitmproxy.net.http import http1, http2
from .. import tservers
+from ...conftest import requires_alpn
import logging
logging.getLogger("hyper.packages.hpack.hpack").setLevel(logging.WARNING)
@@ -27,11 +27,6 @@
logging.getLogger("PIL.PngImagePlugin").setLevel(logging.WARNING)
-requires_alpn = pytest.mark.skipif(
- not mitmproxy.net.tcp.HAS_ALPN,
- reason='requires OpenSSL with ALPN support')
-
-
# inspect the log:
# for msg in self.proxy.tmaster.tlog:
# print(msg)
@@ -51,28 +51,28 @@ def test_error(self):
assert "error" in o.tfile.getvalue()
def test_replay(self):
- o = dump.Options(server_replay=["nonexistent"], replay_kill_extra=True)
+ o = dump.Options(http2=False, server_replay=["nonexistent"], replay_kill_extra=True)
tutils.raises(exceptions.OptionsError, dump.DumpMaster, o, proxy.DummyServer())
with tutils.tmpdir() as t:
p = os.path.join(t, "rep")
self.flowfile(p)
- o = dump.Options(server_replay=[p], replay_kill_extra=True)
+ o = dump.Options(http2=False, server_replay=[p], replay_kill_extra=True)
o.verbosity = 0
o.flow_detail = 0
m = dump.DumpMaster(o, proxy.DummyServer())
self.cycle(m, b"content")
self.cycle(m, b"content")
- o = dump.Options(server_replay=[p], replay_kill_extra=False)
+ o = dump.Options(http2=False, server_replay=[p], replay_kill_extra=False)
o.verbosity = 0
o.flow_detail = 0
m = dump.DumpMaster(o, proxy.DummyServer())
self.cycle(m, b"nonexistent")
- o = dump.Options(client_replay=[p], replay_kill_extra=False)
+ o = dump.Options(http2=False, client_replay=[p], replay_kill_extra=False)
o.verbosity = 0
o.flow_detail = 0
m = dump.DumpMaster(o, proxy.DummyServer())
@@ -1,8 +1,8 @@
import io
from mock import Mock
+import pytest
from mitmproxy.net import http
-from mitmproxy.net import tcp
from mitmproxy.net.http import http1
from mitmproxy import exceptions
@@ -11,6 +11,7 @@
from mitmproxy.test import tutils
from . import tservers
+from ..conftest import requires_alpn
def test_response():
@@ -211,45 +212,57 @@ class TestDaemonHTTP2(PathocTestDaemon):
ssl = True
explain = False
- if tcp.HAS_ALPN:
-
- def test_http2(self):
- c = pathoc.Pathoc(
- ("127.0.0.1", self.d.port),
- fp=None,
- ssl=True,
- use_http2=True,
- )
- assert isinstance(c.protocol, HTTP2StateProtocol)
-
- c = pathoc.Pathoc(
- ("127.0.0.1", self.d.port),
- )
- assert c.protocol == http1
-
- def test_http2_alpn(self):
- c = pathoc.Pathoc(
- ("127.0.0.1", self.d.port),
- fp=None,
- ssl=True,
- use_http2=True,
- http2_skip_connection_preface=True,
- )
-
- tmp_convert_to_ssl = c.convert_to_ssl
- c.convert_to_ssl = Mock()
- c.convert_to_ssl.side_effect = tmp_convert_to_ssl
- with c.connect():
- _, kwargs = c.convert_to_ssl.call_args
- assert set(kwargs['alpn_protos']) == set([b'http/1.1', b'h2'])
-
- def test_request(self):
- c = pathoc.Pathoc(
- ("127.0.0.1", self.d.port),
- fp=None,
- ssl=True,
- use_http2=True,
- )
+ @requires_alpn
+ def test_http2(self):
+ c = pathoc.Pathoc(
+ ("127.0.0.1", self.d.port),
+ fp=None,
+ ssl=True,
+ use_http2=True,
+ )
+ assert isinstance(c.protocol, HTTP2StateProtocol)
+
+ c = pathoc.Pathoc(
+ ("127.0.0.1", self.d.port),
+ )
+ assert c.protocol == http1
+
+ @requires_alpn
+ def test_http2_alpn(self):
+ c = pathoc.Pathoc(
+ ("127.0.0.1", self.d.port),
+ fp=None,
+ ssl=True,
+ use_http2=True,
+ http2_skip_connection_preface=True,
+ )
+
+ tmp_convert_to_ssl = c.convert_to_ssl
+ c.convert_to_ssl = Mock()
+ c.convert_to_ssl.side_effect = tmp_convert_to_ssl
+ with c.connect():
+ _, 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),
+ fp=None,
+ ssl=True,
+ use_http2=True,
+ )
+ 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():
- resp = c.request("get:/p/200")
- assert resp.status_code == 200
+ c.request("get:/p/200")
@@ -1,11 +1,14 @@
import io
+import pytest
+
from pathod import pathod
from mitmproxy.net import tcp
from mitmproxy import exceptions
from mitmproxy.test import tutils
from . import tservers
+from ..conftest import requires_alpn
class TestPathod:
@@ -257,8 +260,11 @@ class TestHTTP2(tservers.DaemonTests):
ssl = True
nohang = True
- if tcp.HAS_ALPN:
+ @requires_alpn
+ def test_http2(self):
+ r, _ = self.pathoc(["GET:/"], ssl=True, use_http2=True)
+ assert r[0].status_code == 800
- def test_http2(self):
+ def test_no_http2(self, disable_alpn):
+ with pytest.raises(NotImplementedError):
r, _ = self.pathoc(["GET:/"], ssl=True, use_http2=True)
- assert r[0].status_code == 800
Oops, something went wrong.

0 comments on commit 1a36efb

Please sign in to comment.