diff options
author | Stephen Holsapple <sholsapp@gmail.com> | 2015-02-12 14:45:43 -0800 |
---|---|---|
committer | Stephen Holsapple <sholsapp@gmail.com> | 2015-02-12 14:45:43 -0800 |
commit | 46a092529bdd38313c64bd01d6866ef64477ec81 (patch) | |
tree | b31b09cdde759010047060391e6ae27f0aab67cd | |
parent | 95a46658350b229cfaa10d5a376942d4832d5032 (diff) | |
download | pyopenssl-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.py | 18 | ||||
-rw-r--r-- | OpenSSL/test/test_crypto.py | 18 |
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): """ |