diff options
Diffstat (limited to 'src/cryptography/hazmat/bindings/openssl/binding.py')
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/binding.py | 108 |
1 files changed, 53 insertions, 55 deletions
diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index 0824ea88c..7a84a340e 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -7,8 +7,8 @@ from __future__ import absolute_import, division, print_function import collections import threading import types -import warnings +import cryptography from cryptography import utils from cryptography.exceptions import InternalError from cryptography.hazmat.bindings._openssl import ffi, lib @@ -51,20 +51,31 @@ def _consume_errors(lib): return errors -def _openssl_assert(lib, ok): - if not ok: - errors = _consume_errors(lib) - errors_with_text = [] - for err in errors: - buf = ffi.new("char[]", 256) - lib.ERR_error_string_n(err.code, buf, len(buf)) - err_text_reason = ffi.string(buf) - - errors_with_text.append( - _OpenSSLErrorWithText( - err.code, err.lib, err.func, err.reason, err_text_reason - ) +def _errors_with_text(errors): + errors_with_text = [] + for err in errors: + buf = ffi.new("char[]", 256) + lib.ERR_error_string_n(err.code, buf, len(buf)) + err_text_reason = ffi.string(buf) + + errors_with_text.append( + _OpenSSLErrorWithText( + err.code, err.lib, err.func, err.reason, err_text_reason ) + ) + + return errors_with_text + + +def _consume_errors_with_text(lib): + return _errors_with_text(_consume_errors(lib)) + + +def _openssl_assert(lib, ok, errors=None): + if not ok: + if errors is None: + errors = _consume_errors(lib) + errors_with_text = _errors_with_text(errors) raise InternalError( "Unknown OpenSSL error. This error is commonly encountered when " @@ -74,7 +85,7 @@ def _openssl_assert(lib, ok): "please file an issue at https://github.com/pyca/cryptography/" "issues with information on how to reproduce " "this. ({0!r})".format(errors_with_text), - errors_with_text + errors_with_text, ) @@ -97,11 +108,11 @@ class Binding(object): """ OpenSSL API wrapper. """ + lib = None ffi = ffi _lib_loaded = False _init_lock = threading.Lock() - _lock_init_lock = threading.Lock() def __init__(self): self._ensure_ffi_initialized() @@ -114,10 +125,9 @@ class Binding(object): # reliably clear the error queue. Once we clear it here we will # error on any subsequent unexpected item in the stack. cls.lib.ERR_clear_error() - cls._osrandom_engine_id = cls.lib.Cryptography_osrandom_engine_id - cls._osrandom_engine_name = cls.lib.Cryptography_osrandom_engine_name - result = cls.lib.Cryptography_add_osrandom_engine() - _openssl_assert(cls.lib, result in (1, 2)) + if cls.lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE: + result = cls.lib.Cryptography_add_osrandom_engine() + _openssl_assert(cls.lib, result in (1, 2)) @classmethod def _ensure_ffi_initialized(cls): @@ -129,46 +139,34 @@ class Binding(object): cls.lib.SSL_library_init() # adds all ciphers/digests for EVP cls.lib.OpenSSL_add_all_algorithms() - # loads error strings for libcrypto and libssl functions - cls.lib.SSL_load_error_strings() cls._register_osrandom_engine() @classmethod def init_static_locks(cls): - with cls._lock_init_lock: - cls._ensure_ffi_initialized() - # Use Python's implementation if available, importing _ssl triggers - # the setup for this. - __import__("_ssl") - - if (not cls.lib.Cryptography_HAS_LOCKING_CALLBACKS or - cls.lib.CRYPTO_get_locking_callback() != cls.ffi.NULL): - return - - # If nothing else has setup a locking callback already, we set up - # our own - res = lib.Cryptography_setup_ssl_threads() - _openssl_assert(cls.lib, res == 1) - - -def _verify_openssl_version(lib): - if ( - lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102 and - not lib.CRYPTOGRAPHY_IS_LIBRESSL - ): - warnings.warn( - "OpenSSL version 1.0.1 is no longer supported by the OpenSSL " - "project, please upgrade. A future version of cryptography will " - "drop support for it.", - utils.CryptographyDeprecationWarning + cls._ensure_ffi_initialized() + + +def _verify_package_version(version): + # Occasionally we run into situations where the version of the Python + # package does not match the version of the shared object that is loaded. + # This may occur in environments where multiple versions of cryptography + # are installed and available in the python path. To avoid errors cropping + # up later this code checks that the currently imported package and the + # shared object that were loaded have the same version and raise an + # ImportError if they do not + so_package_version = ffi.string(lib.CRYPTOGRAPHY_PACKAGE_VERSION) + if version.encode("ascii") != so_package_version: + raise ImportError( + "The version of cryptography does not match the loaded " + "shared object. This can happen if you have multiple copies of " + "cryptography installed in your Python path. Please try creating " + "a new virtual environment to resolve this issue. " + "Loaded python version: {}, shared object version: {}".format( + version, so_package_version + ) ) -# OpenSSL is not thread safe until the locks are initialized. We call this -# method in module scope so that it executes with the import lock. On -# Pythons < 3.4 this import lock is a global lock, which can prevent a race -# condition registering the OpenSSL locks. On Python 3.4+ the import lock -# is per module so this approach will not work. -Binding.init_static_locks() +_verify_package_version(cryptography.__version__) -_verify_openssl_version(Binding.lib) +Binding.init_static_locks() |