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

Check return code of SSL_[CTX_]set_alpn_protos #993

Merged
merged 3 commits into from
Feb 17, 2021
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
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ Deprecations:
Changes:
^^^^^^^^

- Raise an error when an invalid ALPN value is set.
`#993 <https://github.com/pyca/pyopenssl/pull/993>`_

20.0.1 (2020-12-15)
-------------------

Expand Down
21 changes: 19 additions & 2 deletions src/OpenSSL/SSL.py
Original file line number Diff line number Diff line change
Expand Up @@ -1375,7 +1375,17 @@ def set_alpn_protos(self, protos):
# Build a C string from the list. We don't need to save this off
# because OpenSSL immediately copies the data out.
input_str = _ffi.new("unsigned char[]", protostr)
_lib.SSL_CTX_set_alpn_protos(self._context, input_str, len(protostr))

# https://www.openssl.org/docs/man1.1.0/man3/SSL_CTX_set_alpn_protos.html:
# SSL_CTX_set_alpn_protos() and SSL_set_alpn_protos()
# return 0 on success, and non-0 on failure.
# WARNING: these functions reverse the return value convention.
_openssl_assert(
_lib.SSL_CTX_set_alpn_protos(
self._context, input_str, len(protostr)
)
== 0
)

@_requires_alpn
def set_alpn_select_callback(self, callback):
Expand Down Expand Up @@ -2393,7 +2403,14 @@ def set_alpn_protos(self, protos):
# Build a C string from the list. We don't need to save this off
# because OpenSSL immediately copies the data out.
input_str = _ffi.new("unsigned char[]", protostr)
_lib.SSL_set_alpn_protos(self._ssl, input_str, len(protostr))

# https://www.openssl.org/docs/man1.1.0/man3/SSL_CTX_set_alpn_protos.html:
# SSL_CTX_set_alpn_protos() and SSL_set_alpn_protos()
# return 0 on success, and non-0 on failure.
# WARNING: these functions reverse the return value convention.
_openssl_assert(
_lib.SSL_set_alpn_protos(self._ssl, input_str, len(protostr)) == 0
)

@_requires_alpn
def get_alpn_proto_negotiated(self):
Expand Down
9 changes: 9 additions & 0 deletions tests/test_ssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -1888,6 +1888,15 @@ def select(conn, options):
assert server.get_alpn_proto_negotiated() == b"spdy/2"
assert client.get_alpn_proto_negotiated() == b"spdy/2"

def test_alpn_call_failure(self):
"""
SSL_CTX_set_alpn_protos does not like to be called with an empty
protocols list. Ensure that we produce a user-visible error.
"""
context = Context(SSLv23_METHOD)
with pytest.raises(Error):
context.set_alpn_protos([])

def test_alpn_set_on_connection(self):
"""
The same as test_alpn_success, but setting the ALPN protocols on
Expand Down