Skip to content

Commit b31622b

Browse files
authored
add Connection.set_verify, fix #255 (#1073)
* add `Connection.set_verify`, fix #255 * show that it works with cryptography main * Revert "show that it works with cryptography main" This reverts commit fb0136a. * make it black
1 parent 3e4d61a commit b31622b

File tree

3 files changed

+79
-0
lines changed

3 files changed

+79
-0
lines changed

CHANGELOG.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ Deprecations:
1919
Changes:
2020
^^^^^^^^
2121

22+
- Add ``OpenSSL.SSL.Connection.set_verify`` and ``OpenSSL.SSL.Connection.get_verify_mode``
23+
to override the context object's verification flags.
24+
`#1073 <https://github.com/pyca/pyopenssl/pull/1073>`_
25+
2226
22.0.0 (2022-01-29)
2327
-------------------
2428

src/OpenSSL/SSL.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,6 +1745,35 @@ def get_servername(self):
17451745

17461746
return _ffi.string(name)
17471747

1748+
def set_verify(self, mode, callback=None):
1749+
"""
1750+
Override the Context object's verification flags for this specific
1751+
connection. See :py:meth:`Context.set_verify` for details.
1752+
"""
1753+
if not isinstance(mode, int):
1754+
raise TypeError("mode must be an integer")
1755+
1756+
if callback is None:
1757+
self._verify_helper = None
1758+
self._verify_callback = None
1759+
_lib.SSL_set_verify(self._ssl, mode, _ffi.NULL)
1760+
else:
1761+
if not callable(callback):
1762+
raise TypeError("callback must be callable")
1763+
1764+
self._verify_helper = _VerifyHelper(callback)
1765+
self._verify_callback = self._verify_helper.callback
1766+
_lib.SSL_set_verify(self._ssl, mode, self._verify_callback)
1767+
1768+
def get_verify_mode(self):
1769+
"""
1770+
Retrieve the Connection object's verify mode, as set by
1771+
:meth:`set_verify`.
1772+
1773+
:return: The verify mode
1774+
"""
1775+
return _lib.SSL_get_verify_mode(self._ssl)
1776+
17481777
def set_ciphertext_mtu(self, mtu):
17491778
"""
17501779
For DTLS, set the maximum UDP payload size (*not* including IP/UDP

tests/test_ssl.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2630,6 +2630,52 @@ def test_get_verified_chain_unconnected(self):
26302630
server = Connection(ctx, None)
26312631
assert None is server.get_verified_chain()
26322632

2633+
def test_set_verify_overrides_context(self):
2634+
context = Context(SSLv23_METHOD)
2635+
context.set_verify(VERIFY_PEER)
2636+
conn = Connection(context, None)
2637+
conn.set_verify(VERIFY_NONE)
2638+
2639+
assert context.get_verify_mode() == VERIFY_PEER
2640+
assert conn.get_verify_mode() == VERIFY_NONE
2641+
2642+
with pytest.raises(TypeError):
2643+
conn.set_verify(None)
2644+
2645+
with pytest.raises(TypeError):
2646+
conn.set_verify(VERIFY_PEER, "not a callable")
2647+
2648+
def test_set_verify_callback_reference(self):
2649+
"""
2650+
The callback for certificate verification should only be forgotten if
2651+
the context and all connections created by it do not use it anymore.
2652+
"""
2653+
2654+
def callback(conn, cert, errnum, depth, ok): # pragma: no cover
2655+
return ok
2656+
2657+
tracker = ref(callback)
2658+
2659+
context = Context(SSLv23_METHOD)
2660+
context.set_verify(VERIFY_PEER, callback)
2661+
del callback
2662+
2663+
conn = Connection(context, None)
2664+
context.set_verify(VERIFY_NONE)
2665+
2666+
collect()
2667+
collect()
2668+
assert tracker()
2669+
2670+
conn.set_verify(VERIFY_PEER, lambda conn, cert, errnum, depth, ok: ok)
2671+
collect()
2672+
collect()
2673+
callback = tracker()
2674+
if callback is not None: # pragma: nocover
2675+
referrers = get_referrers(callback)
2676+
if len(referrers) > 1:
2677+
pytest.fail("Some references remain: %r" % (referrers,))
2678+
26332679
def test_get_session_unconnected(self):
26342680
"""
26352681
`Connection.get_session` returns `None` when used with an object

0 commit comments

Comments
 (0)