Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test on OpenSSL 1.1.0 with travis. Fixes #524 #526

Merged
merged 19 commits into from
Sep 24, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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