Skip to content

Commit

Permalink
Test on OpenSSL 1.1.0 with travis. Fixes #524 (#526)
Browse files Browse the repository at this point in the history
  • Loading branch information
alex authored and hynek committed Sep 24, 2016
1 parent 9f9113a commit 5af32d0
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 26 deletions.
21 changes: 17 additions & 4 deletions .travis.yml
Expand Up @@ -14,6 +14,9 @@ matrix:
- language: generic
os: osx
env: TOXENV=py27
- language: generic
os: osx
env: TOXENV=py27 OPENSSL=1.1.0
- python: "2.6" # these are just to make travis's UI a bit prettier
env: TOXENV=py26
- python: "2.7"
Expand Down Expand Up @@ -90,7 +93,11 @@ install:
- |
if [[ "$(uname -s)" == 'Darwin' ]]; then
brew update
brew upgrade openssl
if [[ "${OPENSSL}" == "1.1.0" ]]; then
brew install openssl@1.1
else
brew upgrade openssl
fi
curl -O https://bootstrap.pypa.io/get-pip.py
python get-pip.py --user
pip install --user virtualenv
Expand All @@ -114,9 +121,15 @@ script:
if [[ "$(uname -s)" == 'Darwin' ]]; then
# set our flags to use homebrew openssl
export ARCHFLAGS="-arch x86_64"
export LDFLAGS="-L/usr/local/opt/openssl/lib"
export CFLAGS="-I/usr/local/opt/openssl/include"
export PATH="/usr/local/opt/openssl/bin:$PATH"
if [[ "${OPENSSL}" == "1.1.0" ]]; then
export LDFLAGS="-L/usr/local/opt/openssl@1.1/lib"
export CFLAGS="-I/usr/local/opt/openssl@1.1/include"
export PATH="/usr/local/opt/openssl@1.1/bin:$PATH"
else
export LDFLAGS="-L/usr/local/opt/openssl/lib"
export CFLAGS="-I/usr/local/opt/openssl/include"
export PATH="/usr/local/opt/openssl/bin:$PATH"
fi
fi
# activate the pypy env we installed via our custom pyenv in the install stage
if [[ "${TOXENV}" == "pypy" ]]; then
Expand Down
16 changes: 9 additions & 7 deletions src/OpenSSL/SSL.py
Expand Up @@ -109,10 +109,11 @@ class _buffer(object):
SSL_ST_CONNECT = _lib.SSL_ST_CONNECT
SSL_ST_ACCEPT = _lib.SSL_ST_ACCEPT
SSL_ST_MASK = _lib.SSL_ST_MASK
SSL_ST_INIT = _lib.SSL_ST_INIT
SSL_ST_BEFORE = _lib.SSL_ST_BEFORE
SSL_ST_OK = _lib.SSL_ST_OK
SSL_ST_RENEGOTIATE = _lib.SSL_ST_RENEGOTIATE
if _lib.Cryptography_HAS_SSL_ST:
SSL_ST_INIT = _lib.SSL_ST_INIT
SSL_ST_BEFORE = _lib.SSL_ST_BEFORE
SSL_ST_OK = _lib.SSL_ST_OK
SSL_ST_RENEGOTIATE = _lib.SSL_ST_RENEGOTIATE

SSL_CB_LOOP = _lib.SSL_CB_LOOP
SSL_CB_EXIT = _lib.SSL_CB_EXIT
Expand Down Expand Up @@ -1160,9 +1161,10 @@ def _raise_ssl_error(self, ssl, result):
errno = _ffi.getwinerror()[0]
else:
errno = _ffi.errno
raise SysCallError(errno, errorcode.get(errno))
else:
raise SysCallError(-1, "Unexpected EOF")

if errno != 0:
raise SysCallError(errno, errorcode.get(errno))
raise SysCallError(-1, "Unexpected EOF")
else:
# TODO: This is untested.
_raise_current_error()
Expand Down
2 changes: 2 additions & 0 deletions src/OpenSSL/crypto.py
Expand Up @@ -820,6 +820,8 @@ class X509Req(object):
def __init__(self):
req = _lib.X509_REQ_new()
self._req = _ffi.gc(req, _lib.X509_REQ_free)
# Default to version 0.
self.set_version(0)

def set_pubkey(self, pkey):
"""
Expand Down
58 changes: 43 additions & 15 deletions tests/test_ssl.py
Expand Up @@ -68,13 +68,19 @@
OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None

from OpenSSL.SSL import (
SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
SSL_ST_OK, SSL_ST_RENEGOTIATE,
SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)

try:
from OpenSSL.SSL import (
SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
)
except ImportError:
SSL_ST_INIT = SSL_ST_BEFORE = SSL_ST_OK = SSL_ST_RENEGOTIATE = None

from .util import WARNING_TYPE_EXPECTED, NON_ASCII, TestCase
from .test_crypto import (
cleartextCertificatePEM, cleartextPrivateKeyPEM,
Expand Down Expand Up @@ -493,12 +499,11 @@ def test_method(self):
:py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
:py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
"""
methods = [
SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
methods = [SSLv23_METHOD, TLSv1_METHOD]
for meth in methods:
Context(meth)

maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
for meth in maybe:
try:
Context(meth)
Expand Down Expand Up @@ -2437,8 +2442,12 @@ def test_state_string(self):
server = self._loopbackServerFactory(server)
client = self._loopbackClientFactory(client)

assert b"before/accept initialization" == server.get_state_string()
assert b"before/connect initialization" == client.get_state_string()
assert server.get_state_string() in [
b"before/accept initialization", b"before SSL initialization"
]
assert client.get_state_string() in [
b"before/connect initialization", b"before SSL initialization"
]

def test_app_data_wrong_args(self):
"""
Expand Down Expand Up @@ -2633,9 +2642,19 @@ def test_set_session_wrong_method(self):
the :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
raised.
"""
# Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
# and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
# is a way to check for 1.1.0)
if SSL_ST_INIT is not None:
v1 = TLSv1_METHOD
v2 = SSLv3_METHOD
else:
v1 = TLSv1_2_METHOD
v2 = TLSv1_METHOD

key = load_privatekey(FILETYPE_PEM, server_key_pem)
cert = load_certificate(FILETYPE_PEM, server_cert_pem)
ctx = Context(TLSv1_METHOD)
ctx = Context(v1)
ctx.use_privatekey(key)
ctx.use_certificate(cert)
ctx.set_session_id("unity-test")
Expand All @@ -2645,13 +2664,18 @@ def makeServer(socket):
server.set_accept_state()
return server

def makeOriginalClient(socket):
client = Connection(Context(v1), socket)
client.set_connect_state()
return client

originalServer, originalClient = self._loopback(
serverFactory=makeServer)
serverFactory=makeServer, clientFactory=makeOriginalClient)
originalSession = originalClient.get_session()

def makeClient(socket):
# Intentionally use a different, incompatible method here.
client = Connection(Context(SSLv3_METHOD), socket)
client = Connection(Context(v2), socket)
client.set_connect_state()
client.set_session(originalSession)
return client
Expand Down Expand Up @@ -3032,7 +3056,6 @@ def test_bytearray_really_doesnt_overfill(self):
self._doesnt_overfill_test(bytearray)

def test_peek(self):

server, client = self._loopback()
server.send(b'xy')

Expand Down Expand Up @@ -3533,7 +3556,7 @@ def test_shutdown(self):
e = self.assertRaises(Error, server.recv, 1024)
# We don't want WantReadError or ZeroReturnError or anything - it's a
# handshake failure.
self.assertEquals(e.__class__, Error)
assert type(e) in [Error, SysCallError]

def test_unexpectedEndOfFile(self):
"""
Expand Down Expand Up @@ -3809,14 +3832,19 @@ def test_integers(self):
info callback matches up with the constant exposed by OpenSSL.SSL.
"""
for const in [
SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
]:
self.assertTrue(isinstance(const, int))
assert isinstance(const, int)

# These constants don't exist on OpenSSL 1.1.0
for const in [
SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
]:
assert const is None or isinstance(const, int)


class TestRequires(object):
Expand Down

0 comments on commit 5af32d0

Please sign in to comment.