summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Holsapple <sholsapp@gmail.com>2015-02-12 14:45:43 -0800
committerStephen Holsapple <sholsapp@gmail.com>2015-02-12 14:45:43 -0800
commit46a092529bdd38313c64bd01d6866ef64477ec81 (patch)
treeb31b09cdde759010047060391e6ae27f0aab67cd
parent95a46658350b229cfaa10d5a376942d4832d5032 (diff)
downloadpyopenssl-46a092529bdd38313c64bd01d6866ef64477ec81.tar.gz
Initialize a context at instantiation time
To maintain a Pythonic API, we need to initialize the store context object at object instantiation time so that it is possible to modify the trust store (a legitable use case) after the object is created. As the store context implementation becomes more featureful, this will become more important. E.g., when we add support for `X509_STORE_CTX_get0_param` and X509_STORE_CTX_set0_param` to change verification parameters, we'll want to do this. This change also adds a very simple `set_store` method mostly to make the initialization and modification changes easier to test.
-rw-r--r--OpenSSL/crypto.py18
-rw-r--r--OpenSSL/test/test_crypto.py18
2 files changed, 35 insertions, 1 deletions
diff --git a/OpenSSL/crypto.py b/OpenSSL/crypto.py
index c3d4c9b..5093745 100644
--- a/OpenSSL/crypto.py
+++ b/OpenSSL/crypto.py
@@ -1404,6 +1404,10 @@ class X509StoreContext(object):
self._store_ctx = _ffi.gc(store_ctx, _lib.X509_STORE_CTX_free)
self._store = store
self._cert = certificate
+ # Make the store context available for use after instantiating this
+ # class by initializing it now. Per testing, subsequent calls to
+ # :py:meth:`_init` have no adverse affect.
+ self._init()
def _init(self):
@@ -1420,7 +1424,7 @@ class X509StoreContext(object):
Internally cleans up the store context.
The store context can then be reused with a new call to
- :py:meth:`init`.
+ :py:meth:`_init`.
"""
_lib.X509_STORE_CTX_cleanup(self._store_ctx)
@@ -1448,6 +1452,16 @@ class X509StoreContext(object):
return X509StoreContextError(errors, pycert)
+ def set_store(self, store):
+ """
+ Set the context's trust store.
+
+ :param X509Store store: The certificates which will be trusted for the
+ purposes of any *future* verifications.
+ """
+ self._store = store
+
+
def verify_certificate(self):
"""
Verify a certificate in a context.
@@ -1455,6 +1469,8 @@ class X509StoreContext(object):
:param store_ctx: The :py:class:`X509StoreContext` to verify.
:raises: Error
"""
+ # Always re-initialize the store context in case
+ # :py:meth:`verify_certificate` is called multiple times.
self._init()
ret = _lib.X509_verify_cert(self._store_ctx)
self._cleanup()
diff --git a/OpenSSL/test/test_crypto.py b/OpenSSL/test/test_crypto.py
index 0aac1e5..ca54176 100644
--- a/OpenSSL/test/test_crypto.py
+++ b/OpenSSL/test/test_crypto.py
@@ -3257,6 +3257,24 @@ class X509StoreContextTests(TestCase):
self.assertEqual(e.certificate.get_subject().CN, 'intermediate-service')
+ def test_modification_pre_verify(self):
+ """
+ :py:obj:`verify_certificate` can use a store context modified after
+ instantiation.
+ """
+ store_bad = X509Store()
+ store_bad.add_cert(self.intermediate_cert)
+ store_good = X509Store()
+ store_good.add_cert(self.root_cert)
+ store_good.add_cert(self.intermediate_cert)
+ store_ctx = X509StoreContext(store_bad, self.intermediate_server_cert)
+ e = self.assertRaises(X509StoreContextError, store_ctx.verify_certificate)
+ self.assertEqual(e.args[0][2], 'unable to get issuer certificate')
+ self.assertEqual(e.certificate.get_subject().CN, 'intermediate')
+ store_ctx.set_store(store_good)
+ self.assertEqual(store_ctx.verify_certificate(), None)
+
+
class SignVerifyTests(TestCase):
"""