summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Bowser <topnotcher@gmail.com>2017-01-24 11:38:55 -0500
committerPaul Kehrer <paul.l.kehrer@gmail.com>2017-01-25 00:38:55 +0800
commit36eb2de167e3c3c00908ca0dbb22c1f6c9c74e74 (patch)
tree613afba60bc41caba6a4aebc174c955a8f6b3c13
parent7be83a50ad9c3a0eb004eef7f85b352612b314f5 (diff)
downloadpyopenssl-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.rst2
-rw-r--r--src/OpenSSL/SSL.py9
-rw-r--r--src/OpenSSL/crypto.py14
-rw-r--r--tests/test_crypto.py6
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):
"""