Skip to content

Commit 79b9c79

Browse files
authored
Context.set_verify: allow omission of callback (#933)
* Context.set_verify: allow omission of callback * squeeze to 80 chars * make it clear that default callback is used
1 parent 33c5499 commit 79b9c79

File tree

3 files changed

+46
-16
lines changed

3 files changed

+46
-16
lines changed

CHANGELOG.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ Changes:
2929
- Added ``OpenSSL.SSL.Connection.get_verified_chain`` to retrieve the
3030
verified certificate chain of the peer.
3131
`#894 <https://github.com/pyca/pyopenssl/pull/894>`_.
32+
- Make verification callback optional in ``Context.set_verify``.
33+
If omitted, OpenSSL's default verification is used.
34+
`#933 <https://github.com/pyca/pyopenssl/pull/933>`_
3235

3336

3437
19.1.0 (2019-11-18)

src/OpenSSL/SSL.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,7 +1003,7 @@ def get_session_cache_mode(self):
10031003
"""
10041004
return _lib.SSL_CTX_get_session_cache_mode(self._context)
10051005

1006-
def set_verify(self, mode, callback):
1006+
def set_verify(self, mode, callback=None):
10071007
"""
10081008
et the verification flags for this Context object to *mode* and specify
10091009
that *callback* should be used for verification callbacks.
@@ -1013,24 +1013,30 @@ def set_verify(self, mode, callback):
10131013
:const:`VERIFY_PEER` is used, *mode* can be OR:ed with
10141014
:const:`VERIFY_FAIL_IF_NO_PEER_CERT` and
10151015
:const:`VERIFY_CLIENT_ONCE` to further control the behaviour.
1016-
:param callback: The Python callback to use. This should take five
1017-
arguments: A Connection object, an X509 object, and three integer
1018-
variables, which are in turn potential error number, error depth
1019-
and return code. *callback* should return True if verification
1020-
passes and False otherwise.
1016+
:param callback: The optional Python verification callback to use.
1017+
This should take five arguments: A Connection object, an X509
1018+
object, and three integer variables, which are in turn potential
1019+
error number, error depth and return code. *callback* should
1020+
return True if verification passes and False otherwise.
1021+
If omitted, OpenSSL's default verification is used.
10211022
:return: None
10221023
10231024
See SSL_CTX_set_verify(3SSL) for further details.
10241025
"""
10251026
if not isinstance(mode, integer_types):
10261027
raise TypeError("mode must be an integer")
10271028

1028-
if not callable(callback):
1029-
raise TypeError("callback must be callable")
1029+
if callback is None:
1030+
self._verify_helper = None
1031+
self._verify_callback = None
1032+
_lib.SSL_CTX_set_verify(self._context, mode, _ffi.NULL)
1033+
else:
1034+
if not callable(callback):
1035+
raise TypeError("callback must be callable")
10301036

1031-
self._verify_helper = _VerifyHelper(callback)
1032-
self._verify_callback = self._verify_helper.callback
1033-
_lib.SSL_CTX_set_verify(self._context, mode, self._verify_callback)
1037+
self._verify_helper = _VerifyHelper(callback)
1038+
self._verify_callback = self._verify_helper.callback
1039+
_lib.SSL_CTX_set_verify(self._context, mode, self._verify_callback)
10341040

10351041
def set_verify_depth(self, depth):
10361042
"""

tests/test_ssl.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,6 +1378,29 @@ def verify_callback(*args):
13781378

13791379
assert "silly verify failure" == str(exc.value)
13801380

1381+
@pytest.mark.parametrize("mode", [SSL.VERIFY_PEER, SSL.VERIFY_NONE])
1382+
def test_set_verify_default_callback(self, mode):
1383+
"""
1384+
If the verify callback is omitted, the preverify value is used.
1385+
"""
1386+
serverContext = Context(TLSv1_2_METHOD)
1387+
serverContext.use_privatekey(
1388+
load_privatekey(FILETYPE_PEM, root_key_pem)
1389+
)
1390+
serverContext.use_certificate(
1391+
load_certificate(FILETYPE_PEM, root_cert_pem)
1392+
)
1393+
1394+
clientContext = Context(TLSv1_2_METHOD)
1395+
clientContext.set_verify(mode, None)
1396+
1397+
if mode == SSL.VERIFY_PEER:
1398+
with pytest.raises(Exception) as exc:
1399+
self._handshake_test(serverContext, clientContext)
1400+
assert "certificate verify failed" in str(exc.value)
1401+
else:
1402+
self._handshake_test(serverContext, clientContext)
1403+
13811404
def test_add_extra_chain_cert(self, tmpdir):
13821405
"""
13831406
`Context.add_extra_chain_cert` accepts an `X509`
@@ -1509,9 +1532,7 @@ def test_set_verify_mode(self):
15091532
"""
15101533
context = Context(SSLv23_METHOD)
15111534
assert context.get_verify_mode() == 0
1512-
context.set_verify(
1513-
VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None
1514-
)
1535+
context.set_verify(VERIFY_PEER | VERIFY_CLIENT_ONCE)
15151536
assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
15161537

15171538
@pytest.mark.parametrize("mode", [None, 1.0, object(), "mode"])
@@ -1522,9 +1543,9 @@ def test_set_verify_wrong_mode_arg(self, mode):
15221543
"""
15231544
context = Context(SSLv23_METHOD)
15241545
with pytest.raises(TypeError):
1525-
context.set_verify(mode=mode, callback=lambda *args: None)
1546+
context.set_verify(mode=mode)
15261547

1527-
@pytest.mark.parametrize("callback", [None, 1.0, "mode", ("foo", "bar")])
1548+
@pytest.mark.parametrize("callback", [1.0, "mode", ("foo", "bar")])
15281549
def test_set_verify_wrong_callable_arg(self, callback):
15291550
"""
15301551
`Context.set_verify` raises `TypeError` if the second argument

0 commit comments

Comments
 (0)