Skip to content

Commit 65ca53a

Browse files
authored
Make X509StoreContextError's message friendlier (#1133)
* OpenSSL/crypto: make X509StoreContextError's message friendlier Closes #1132. Signed-off-by: William Woodruff <[email protected]> * tests: update exception tests Signed-off-by: William Woodruff <[email protected]> * OpenSSL/crypto: blacken Signed-off-by: William Woodruff <[email protected]> * CHANGELOG: record changes Signed-off-by: William Woodruff <[email protected]>
1 parent 02db1a0 commit 65ca53a

File tree

3 files changed

+23
-16
lines changed

3 files changed

+23
-16
lines changed

CHANGELOG.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ Backward-incompatible changes:
1212

1313
- Remove support for SSLv2 and SSLv3.
1414
- The minimum ``cryptography`` version is now 37.0.2.
15+
- The ``OpenSSL.crypto.X509StoreContextError`` exception has been refactored,
16+
changing its internal attributes.
17+
`#1133 <https://github.com/pyca/pyopenssl/pull/1133>`_
1518

1619
Deprecations:
1720
^^^^^^^^^^^^^

src/OpenSSL/crypto.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,8 +1776,11 @@ class X509StoreContextError(Exception):
17761776
:type certificate: :class:`X509`
17771777
"""
17781778

1779-
def __init__(self, message: Any, certificate: X509) -> None:
1779+
def __init__(
1780+
self, message: str, errors: List[Any], certificate: X509
1781+
) -> None:
17801782
super(X509StoreContextError, self).__init__(message)
1783+
self.errors = errors
17811784
self.certificate = certificate
17821785

17831786

@@ -1878,21 +1881,22 @@ def _exception_from_context(self) -> X509StoreContextError:
18781881
When a call to native OpenSSL X509_verify_cert fails, additional
18791882
information about the failure can be obtained from the store context.
18801883
"""
1884+
message = _ffi.string(
1885+
_lib.X509_verify_cert_error_string(
1886+
_lib.X509_STORE_CTX_get_error(self._store_ctx)
1887+
)
1888+
).decode("utf-8")
18811889
errors = [
18821890
_lib.X509_STORE_CTX_get_error(self._store_ctx),
18831891
_lib.X509_STORE_CTX_get_error_depth(self._store_ctx),
1884-
_ffi.string(
1885-
_lib.X509_verify_cert_error_string(
1886-
_lib.X509_STORE_CTX_get_error(self._store_ctx)
1887-
)
1888-
).decode("utf-8"),
1892+
message,
18891893
]
18901894
# A context error should always be associated with a certificate, so we
18911895
# expect this call to never return :class:`None`.
18921896
_x509 = _lib.X509_STORE_CTX_get_current_cert(self._store_ctx)
18931897
_cert = _lib.X509_dup(_x509)
18941898
pycert = X509._from_raw_x509_ptr(_cert)
1895-
return X509StoreContextError(errors, pycert)
1899+
return X509StoreContextError(message, errors, pycert)
18961900

18971901
def set_store(self, store: X509Store) -> None:
18981902
"""

tests/test_crypto.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3874,7 +3874,7 @@ def test_verify_with_revoked(self):
38743874
store_ctx = X509StoreContext(store, self.intermediate_server_cert)
38753875
with pytest.raises(X509StoreContextError) as err:
38763876
store_ctx.verify_certificate()
3877-
assert err.value.args[0][2] == "certificate revoked"
3877+
assert str(err.value) == "certificate revoked"
38783878

38793879
def test_verify_with_missing_crl(self):
38803880
"""
@@ -3894,7 +3894,7 @@ def test_verify_with_missing_crl(self):
38943894
store_ctx = X509StoreContext(store, self.intermediate_server_cert)
38953895
with pytest.raises(X509StoreContextError) as err:
38963896
store_ctx.verify_certificate()
3897-
assert err.value.args[0][2] == "unable to get certificate CRL"
3897+
assert str(err.value) == "unable to get certificate CRL"
38983898
assert err.value.certificate.get_subject().CN == "intermediate-service"
38993899

39003900
def test_convert_from_cryptography(self):
@@ -4106,7 +4106,7 @@ def test_untrusted_self_signed(self):
41064106
store_ctx.verify_certificate()
41074107

41084108
# OpenSSL 1.1.x and 3.0.x have different error messages
4109-
assert exc.value.args[0][2] in [
4109+
assert str(exc.value) in [
41104110
"self signed certificate",
41114111
"self-signed certificate",
41124112
]
@@ -4124,7 +4124,7 @@ def test_invalid_chain_no_root(self):
41244124
with pytest.raises(X509StoreContextError) as exc:
41254125
store_ctx.verify_certificate()
41264126

4127-
assert exc.value.args[0][2] == "unable to get issuer certificate"
4127+
assert str(exc.value) == "unable to get issuer certificate"
41284128
assert exc.value.certificate.get_subject().CN == "intermediate"
41294129

41304130
def test_invalid_chain_no_intermediate(self):
@@ -4139,7 +4139,7 @@ def test_invalid_chain_no_intermediate(self):
41394139
with pytest.raises(X509StoreContextError) as exc:
41404140
store_ctx.verify_certificate()
41414141

4142-
assert exc.value.args[0][2] == "unable to get local issuer certificate"
4142+
assert str(exc.value) == "unable to get local issuer certificate"
41434143
assert exc.value.certificate.get_subject().CN == "intermediate-service"
41444144

41454145
def test_modification_pre_verify(self):
@@ -4157,7 +4157,7 @@ def test_modification_pre_verify(self):
41574157
with pytest.raises(X509StoreContextError) as exc:
41584158
store_ctx.verify_certificate()
41594159

4160-
assert exc.value.args[0][2] == "unable to get issuer certificate"
4160+
assert str(exc.value) == "unable to get issuer certificate"
41614161
assert exc.value.certificate.get_subject().CN == "intermediate"
41624162

41634163
store_ctx.set_store(store_good)
@@ -4182,7 +4182,7 @@ def test_verify_with_time(self):
41824182
with pytest.raises(X509StoreContextError) as exc:
41834183
store_ctx.verify_certificate()
41844184

4185-
assert exc.value.args[0][2] == "certificate has expired"
4185+
assert str(exc.value) == "certificate has expired"
41864186

41874187
def test_get_verified_chain(self):
41884188
"""
@@ -4216,7 +4216,7 @@ def test_get_verified_chain_invalid_chain_no_root(self):
42164216
with pytest.raises(X509StoreContextError) as exc:
42174217
store_ctx.get_verified_chain()
42184218

4219-
assert exc.value.args[0][2] == "unable to get issuer certificate"
4219+
assert str(exc.value) == "unable to get issuer certificate"
42204220
assert exc.value.certificate.get_subject().CN == "intermediate"
42214221

42224222
@pytest.fixture
@@ -4281,7 +4281,7 @@ def test_verify_failure_with_empty_ca_directory(self, tmpdir):
42814281
with pytest.raises(X509StoreContextError) as exc:
42824282
store_ctx.verify_certificate()
42834283

4284-
assert exc.value.args[0][2] == "unable to get local issuer certificate"
4284+
assert str(exc.value) == "unable to get local issuer certificate"
42854285

42864286

42874287
class TestSignVerify:

0 commit comments

Comments
 (0)