diff options
author | Greg Bowser <topnotcher@gmail.com> | 2017-01-24 11:38:55 -0500 |
---|---|---|
committer | Paul Kehrer <paul.l.kehrer@gmail.com> | 2017-01-25 00:38:55 +0800 |
commit | 36eb2de167e3c3c00908ca0dbb22c1f6c9c74e74 (patch) | |
tree | 613afba60bc41caba6a4aebc174c955a8f6b3c13 | |
parent | 7be83a50ad9c3a0eb004eef7f85b352612b314f5 (diff) | |
download | pyopenssl-36eb2de167e3c3c00908ca0dbb22c1f6c9c74e74.tar.gz |
Prevent _PassphraseHelper.raise_if_problem() from eating exceptions (#581)
* Modify tests to detect empty crypto.Errors from load_privatekey
This reproduces #119 and #456.
* Prevent _PassphraseHelper.raise_if_problem() from eating exceptions.
This resolves #119, resolves #456.
`_PassphraseHelper.raise_if_problem()` always flushes the OpenSSL
exception queue, but does not always raise an exception. In some cases,
other code attempts to raise an error from OpenSSL after
`raise_if_problem()` has flushed the queue, thus causing an empty
exception to be raised (i.e. `raise Error([])`).
This commit modifies `_PassphraseHelper.raise_if_problem` to flush the
OpenSSL error queue only if it has en exception to raise. Subsequent
code that detects an error should now be able to raise an non-empty
exception.
* Add CHANGELOG entry for #581.
-rw-r--r-- | CHANGELOG.rst | 2 | ||||
-rw-r--r-- | src/OpenSSL/SSL.py | 9 | ||||
-rw-r--r-- | src/OpenSSL/crypto.py | 14 | ||||
-rw-r--r-- | tests/test_crypto.py | 6 |
4 files changed, 18 insertions, 13 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f76f64c..6ef6f7b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -36,6 +36,8 @@ Changes: `#578 <https://github.com/pyca/pyopenssl/pull/578>`_ - Automatically set ``SSL_CTX_set_ecdh_auto()`` on ``OpenSSL.SSL.Context``. `#575 <https://github.com/pyca/pyopenssl/pull/575>`_ +- Fix empty exceptions from ``OpenSSL.crypto.load_privatekey()``. + `#581 <https://github.com/pyca/pyopenssl/pull/581>`_ ---- diff --git a/src/OpenSSL/SSL.py b/src/OpenSSL/SSL.py index 003ed43..d4158d4 100644 --- a/src/OpenSSL/SSL.py +++ b/src/OpenSSL/SSL.py @@ -771,11 +771,10 @@ class Context(object): _raise_current_error() def _raise_passphrase_exception(self): - if self._passphrase_helper is None: - _raise_current_error() - exception = self._passphrase_helper.raise_if_problem(Error) - if exception is not None: - raise exception + if self._passphrase_helper is not None: + self._passphrase_helper.raise_if_problem(Error) + + _raise_current_error() def use_privatekey_file(self, keyfile, filetype=_UNSPECIFIED): """ diff --git a/src/OpenSSL/crypto.py b/src/OpenSSL/crypto.py index 7bb0cfa..4b86b95 100644 --- a/src/OpenSSL/crypto.py +++ b/src/OpenSSL/crypto.py @@ -2523,13 +2523,15 @@ class _PassphraseHelper(object): ) def raise_if_problem(self, exceptionType=Error): - try: - _exception_from_error_queue(exceptionType) - except exceptionType as e: - from_queue = e if self._problems: - raise self._problems[0] - return from_queue + + # Flush the OpenSSL error queue + try: + _exception_from_error_queue(exceptionType) + except exceptionType: + pass + + raise self._problems.pop(0) def _read_passphrase(self, buf, size, rwflag, userdata): try: diff --git a/tests/test_crypto.py b/tests/test_crypto.py index 6b55702..8d644de 100644 --- a/tests/test_crypto.py +++ b/tests/test_crypto.py @@ -2595,9 +2595,10 @@ class FunctionTests(TestCase): :py:obj:`load_privatekey` raises :py:obj:`OpenSSL.crypto.Error` when it is passed an encrypted PEM and an incorrect passphrase. """ - self.assertRaises( + exc = self.assertRaises( Error, load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, b"quack") + self.assertNotEqual(exc.args[0], []) def test_load_privatekey_passphraseWrongType(self): """ @@ -2642,10 +2643,11 @@ class FunctionTests(TestCase): def cb(*a): called.append(None) return b"quack" - self.assertRaises( + exc = self.assertRaises( Error, load_privatekey, FILETYPE_PEM, encryptedPrivateKeyPEM, cb) self.assertTrue(called) + self.assertNotEqual(exc.args[0], []) def test_load_privatekey_passphraseCallback(self): """ |