Skip to content

Commit e059599

Browse files
committed
add Connection.set_verify, fix pyca#255
1 parent 5a30471 commit e059599

File tree

5 files changed

+79
-2
lines changed

5 files changed

+79
-2
lines changed

CHANGELOG.rst

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ Deprecations:
3434
Changes:
3535
^^^^^^^^
3636

37+
- Add ``OpenSSL.SSL.Connection.set_verify`` and ``OpenSSL.SSL.Connection.get_verify_mode``
38+
to override the context object's verification flags.
39+
`#1073 <https://github.com/pyca/pyopenssl/pull/1073>`_
3740
- Expose wrappers for some `DTLS
3841
<https://en.wikipedia.org/wiki/Datagram_Transport_Layer_Security>`_
3942
primitives. `#1026 <https://github.com/pyca/pyopenssl/pull/1026>`_

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ def find_meta(meta):
9696
package_dir={"": "src"},
9797
install_requires=[
9898
# Fix cryptographyMinimum in tox.ini when changing this!
99-
"cryptography>=35.0",
99+
"cryptography>=37.0",
100100
],
101101
extras_require={
102102
"test": ["flaky", "pretend", "pytest>=3.0.1"],

src/OpenSSL/SSL.py

+29
Original file line numberDiff line numberDiff line change
@@ -1727,6 +1727,35 @@ def get_servername(self):
17271727

17281728
return _ffi.string(name)
17291729

1730+
def set_verify(self, mode, callback=None):
1731+
"""
1732+
Override the Context object's verification flags for this specific
1733+
connection. See :py:meth:`Context.set_verify` for details.
1734+
"""
1735+
if not isinstance(mode, int):
1736+
raise TypeError("mode must be an integer")
1737+
1738+
if callback is None:
1739+
self._verify_helper = None
1740+
self._verify_callback = None
1741+
_lib.SSL_set_verify(self._ssl, mode, _ffi.NULL)
1742+
else:
1743+
if not callable(callback):
1744+
raise TypeError("callback must be callable")
1745+
1746+
self._verify_helper = _VerifyHelper(callback)
1747+
self._verify_callback = self._verify_helper.callback
1748+
_lib.SSL_set_verify(self._ssl, mode, self._verify_callback)
1749+
1750+
def get_verify_mode(self):
1751+
"""
1752+
Retrieve the Connection object's verify mode, as set by
1753+
:meth:`set_verify`.
1754+
1755+
:return: The verify mode
1756+
"""
1757+
return _lib.SSL_get_verify_mode(self._ssl)
1758+
17301759
def set_ciphertext_mtu(self, mtu):
17311760
"""
17321761
For DTLS, set the maximum UDP payload size (*not* including IP/UDP

tests/test_ssl.py

+45
Original file line numberDiff line numberDiff line change
@@ -2618,6 +2618,51 @@ def test_get_verified_chain_unconnected(self):
26182618
server = Connection(ctx, None)
26192619
assert None is server.get_verified_chain()
26202620

2621+
def test_set_verify_overrides_context(self):
2622+
context = Context(SSLv23_METHOD)
2623+
context.set_verify(VERIFY_PEER)
2624+
conn = Connection(context, None)
2625+
conn.set_verify(VERIFY_NONE)
2626+
2627+
assert context.get_verify_mode() == VERIFY_PEER
2628+
assert conn.get_verify_mode() == VERIFY_NONE
2629+
2630+
with pytest.raises(TypeError):
2631+
conn.set_verify(None)
2632+
2633+
with pytest.raises(TypeError):
2634+
conn.set_verify(VERIFY_PEER, "not a callable")
2635+
2636+
def test_set_verify_callback_reference(self):
2637+
"""
2638+
The callback for certificate verification should only be forgotten if the context and all connections
2639+
created by it do not use it anymore.
2640+
"""
2641+
def callback(conn, cert, errnum, depth, ok): # pragma: no cover
2642+
return ok
2643+
2644+
tracker = ref(callback)
2645+
2646+
context = Context(SSLv23_METHOD)
2647+
context.set_verify(VERIFY_PEER, callback)
2648+
del callback
2649+
2650+
conn = Connection(context, None)
2651+
context.set_verify(VERIFY_NONE)
2652+
2653+
collect()
2654+
collect()
2655+
assert tracker()
2656+
2657+
conn.set_verify(VERIFY_PEER, lambda conn, cert, errnum, depth, ok: ok)
2658+
collect()
2659+
collect()
2660+
callback = tracker()
2661+
if callback is not None: # pragma: nocover
2662+
referrers = get_referrers(callback)
2663+
if len(referrers) > 1:
2664+
pytest.fail("Some references remain: %r" % (referrers,))
2665+
26212666
def test_get_session_unconnected(self):
26222667
"""
26232668
`Connection.get_session` returns `None` when used with an object

tox.ini

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ extras =
1010
deps =
1111
coverage>=4.2
1212
cryptographyMain: git+https://github.com/pyca/cryptography.git
13-
cryptographyMinimum: cryptography==35.0
13+
cryptographyMinimum: cryptography==37.0
1414
randomorder: pytest-randomly
1515
setenv =
1616
# Do not allow the executing environment to pollute the test environment

0 commit comments

Comments
 (0)