summaryrefslogtreecommitdiff
path: root/src/OpenSSL/crypto.py
diff options
context:
space:
mode:
authorShane Harvey <shane.harvey@mongodb.com>2020-08-05 16:48:51 -0700
committerGitHub <noreply@github.com>2020-08-05 18:48:51 -0500
commit33c5499ce34f5e1c7c2630c6a1446353eee31755 (patch)
tree45f4871892c7b5e29e46fca2009e5cf77dc9eaa8 /src/OpenSSL/crypto.py
parentbb971ae935059b73830ea2abe3f66391125b2bfb (diff)
downloadpyopenssl-33c5499ce34f5e1c7c2630c6a1446353eee31755.tar.gz
Allow accessing a connection's verfied certificate chain (#894)
* Allow accessing a connection's verfied certificate chain Add X509StoreContext.get_verified_chain using X509_STORE_CTX_get1_chain. Add Connection.get_verified_chain using SSL_get0_verified_chain if available (ie OpenSSL 1.1+) and X509StoreContext.get_verified_chain otherwise. Fixes #740. * TLSv1_METHOD -> SSLv23_METHOD * Use X509_up_ref instead of X509_dup * Add _openssl_assert where appropriate * SSL_get_peer_cert_chain should not be null * Reformat with black * Fix <OpenSSL.crypto.X509 object at 0x7fdbb59e8050> != <OpenSSL.crypto.X509 object at 0x7fdbb59daad0> * Add Changelog entry * Remove _add_chain
Diffstat (limited to 'src/OpenSSL/crypto.py')
-rw-r--r--src/OpenSSL/crypto.py42
1 files changed, 41 insertions, 1 deletions
diff --git a/src/OpenSSL/crypto.py b/src/OpenSSL/crypto.py
index 1b1e93e..79307b8 100644
--- a/src/OpenSSL/crypto.py
+++ b/src/OpenSSL/crypto.py
@@ -1712,6 +1712,7 @@ class X509StoreContext(object):
self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
self._store = store
self._cert = certificate
+ self._chain = _ffi.NULL
# Make the store context available for use after instantiating this
# class by initializing it now. Per testing, subsequent calls to
# :meth:`_init` have no adverse affect.
@@ -1725,7 +1726,7 @@ class X509StoreContext(object):
:meth:`_cleanup` will leak memory.
"""
ret = _lib.X509_STORE_CTX_init(
- self._store_ctx, self._store._store, self._cert._x509, _ffi.NULL
+ self._store_ctx, self._store._store, self._cert._x509, self._chain
)
if ret <= 0:
_raise_current_error()
@@ -1797,6 +1798,45 @@ class X509StoreContext(object):
if ret <= 0:
raise self._exception_from_context()
+ def get_verified_chain(self):
+ """
+ Verify a certificate in a context and return the complete validated
+ chain.
+
+ :raises X509StoreContextError: If an error occurred when validating a
+ certificate in the context. Sets ``certificate`` attribute to
+ indicate which certificate caused the error.
+
+ .. versionadded:: 20.0
+ """
+ # Always re-initialize the store context in case
+ # :meth:`verify_certificate` is called multiple times.
+ #
+ # :meth:`_init` is called in :meth:`__init__` so _cleanup is called
+ # before _init to ensure memory is not leaked.
+ self._cleanup()
+ self._init()
+ ret = _lib.X509_verify_cert(self._store_ctx)
+ if ret <= 0:
+ self._cleanup()
+ raise self._exception_from_context()
+
+ # Note: X509_STORE_CTX_get1_chain returns a deep copy of the chain.
+ cert_stack = _lib.X509_STORE_CTX_get1_chain(self._store_ctx)
+ _openssl_assert(cert_stack != _ffi.NULL)
+
+ result = []
+ for i in range(_lib.sk_X509_num(cert_stack)):
+ cert = _lib.sk_X509_value(cert_stack, i)
+ _openssl_assert(cert != _ffi.NULL)
+ pycert = X509._from_raw_x509_ptr(cert)
+ result.append(pycert)
+
+ # Free the stack but not the members which are freed by the X509 class.
+ _lib.sk_X509_free(cert_stack)
+ self._cleanup()
+ return result
+
def load_certificate(type, buffer):
"""