summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArne Schwabe <arne@rfc2549.org>2020-11-27 19:29:49 +0100
committerGitHub <noreply@github.com>2020-11-27 12:29:49 -0600
commit3562df8732f66848342874526d0ce12392d7d62e (patch)
tree8ff18795804fd4a6fe4675d9dfacdd4bb6444d8b
parentf3667e95188e8c14458a7943c7efab3776b04711 (diff)
downloadpyopenssl-git-3562df8732f66848342874526d0ce12392d7d62e.tar.gz
Keep reference to SSL verify_call in Connection object (#956)
* Keep reference to SSL verify_call in Connection object If a set_verify is used on a context before and after a Connection the reference in the SSL* object still points to the old _verify_helper object. Since this object has no longer any references to it, the callback can result in a segfault. This commit fixes the issues by ensuring that as long as the Connection object/SSL* object lives a reference to the callback function is held. * Add Unit test for set_verify_callback deference
-rw-r--r--src/OpenSSL/SSL.py6
-rw-r--r--tests/test_ssl.py46
2 files changed, 52 insertions, 0 deletions
diff --git a/src/OpenSSL/SSL.py b/src/OpenSSL/SSL.py
index 3153426..230b403 100644
--- a/src/OpenSSL/SSL.py
+++ b/src/OpenSSL/SSL.py
@@ -1485,6 +1485,12 @@ class Connection(object):
# avoid them getting freed.
self._alpn_select_callback_args = None
+ # Reference the verify_callback of the Context. This ensures that if
+ # set_verify is called again after the SSL object has been created we
+ # do not point to a dangling reference
+ self._verify_helper = context._verify_helper
+ self._verify_callback = context._verify_callback
+
self._reverse_mapping[self._ssl] = self
if socket is None:
diff --git a/tests/test_ssl.py b/tests/test_ssl.py
index aed2367..8fdcae2 100644
--- a/tests/test_ssl.py
+++ b/tests/test_ssl.py
@@ -6,6 +6,7 @@ Unit tests for :mod:`OpenSSL.SSL`.
"""
import datetime
+import gc
import sys
import uuid
@@ -1389,6 +1390,51 @@ class TestContext(object):
assert "silly verify failure" == str(exc.value)
+ def test_set_verify_callback_reference(self):
+ """
+ If the verify callback passed to `Context.set_verify` is set multiple
+ times, the pointers to the old call functions should not be dangling
+ and trigger a segfault.
+ """
+ serverContext = Context(TLSv1_2_METHOD)
+ serverContext.use_privatekey(
+ load_privatekey(FILETYPE_PEM, root_key_pem)
+ )
+ serverContext.use_certificate(
+ load_certificate(FILETYPE_PEM, root_cert_pem)
+ )
+
+ clientContext = Context(TLSv1_2_METHOD)
+
+ clients = []
+
+ for i in range(5):
+
+ def verify_callback(*args):
+ return True
+
+ serverSocket, clientSocket = socket_pair()
+ client = Connection(clientContext, clientSocket)
+
+ clients.append((serverSocket, client))
+
+ clientContext.set_verify(VERIFY_PEER, verify_callback)
+
+ gc.collect()
+
+ # Make them talk to each other.
+ for serverSocket, client in clients:
+ server = Connection(serverContext, serverSocket)
+ server.set_accept_state()
+ client.set_connect_state()
+
+ for _ in range(5):
+ for s in [client, server]:
+ try:
+ s.do_handshake()
+ except WantReadError:
+ pass
+
@pytest.mark.parametrize("mode", [SSL.VERIFY_PEER, SSL.VERIFY_NONE])
def test_set_verify_default_callback(self, mode):
"""