From 00b8cbaa31d48326b36928228269ac14276fd5ee Mon Sep 17 00:00:00 2001 From: Ivan Alejandro Date: Thu, 19 Feb 2015 14:12:15 -0300 Subject: Fall back to plain ZMQ if Curve is not available. Use global flag for ZMQ_HAS_CURVE. Closes #6646 --- src/leap/bitmask/backend/utils.py | 54 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) (limited to 'src/leap/bitmask/backend/utils.py') diff --git a/src/leap/bitmask/backend/utils.py b/src/leap/bitmask/backend/utils.py index 18e70743..b2674330 100644 --- a/src/leap/bitmask/backend/utils.py +++ b/src/leap/bitmask/backend/utils.py @@ -22,20 +22,63 @@ import os import shutil import stat -import zmq.auth +import zmq +try: + import zmq.auth +except ImportError: + pass + +from leap.bitmask.config import flags from leap.bitmask.util import get_path_prefix from leap.common.files import mkdir_p +from leap.common.check import leap_assert logger = logging.getLogger(__name__) KEYS_DIR = os.path.join(get_path_prefix(), 'leap', 'zmq_certificates') +def _zmq_has_curve(): + """ + Return whether the current ZMQ has support for auth and CurveZMQ security. + + :rtype: bool + + Version notes: + `zmq.curve_keypair()` is new in version 14.0, new in version libzmq-4.0. + Requires libzmq (>= 4.0) to have been linked with libsodium. + `zmq.auth` module is new in version 14.1 + `zmq.has()` is new in version 14.1, new in version libzmq-4.1. + """ + zmq_version = zmq.zmq_version_info() + pyzmq_version = zmq.pyzmq_version_info() + + if pyzmq_version >= (14, 1, 0) and zmq_version >= (4, 1): + return zmq.has('curve') + + if pyzmq_version < (14, 1, 0): + return False + + if zmq_version < (4, 0): + # security is new in libzmq 4.0 + return False + + try: + zmq.curve_keypair() + except zmq.error.ZMQError: + # security requires libzmq to be linked against libsodium + return False + + return True + + def generate_zmq_certificates(): """ Generate client and server CURVE certificate files. """ + leap_assert(flags.ZMQ_HAS_CURVE, "CurveZMQ not supported!") + # Create directory for certificates, remove old content if necessary if os.path.exists(KEYS_DIR): shutil.rmtree(KEYS_DIR) @@ -53,6 +96,8 @@ def get_frontend_certificates(): """ Return the frontend's public and secret certificates. """ + leap_assert(flags.ZMQ_HAS_CURVE, "CurveZMQ not supported!") + frontend_secret_file = os.path.join(KEYS_DIR, "frontend.key_secret") public, secret = zmq.auth.load_certificate(frontend_secret_file) return public, secret @@ -62,6 +107,8 @@ def get_backend_certificates(base_dir='.'): """ Return the backend's public and secret certificates. """ + leap_assert(flags.ZMQ_HAS_CURVE, "CurveZMQ not supported!") + backend_secret_file = os.path.join(KEYS_DIR, "backend.key_secret") public, secret = zmq.auth.load_certificate(backend_secret_file) return public, secret @@ -84,5 +131,8 @@ def generate_zmq_certificates_if_needed(): Generate the needed ZMQ certificates for backend/frontend communication if needed. """ - if not _certificates_exist(): + if flags.ZMQ_HAS_CURVE and not _certificates_exist(): generate_zmq_certificates() + + +flags.ZMQ_HAS_CURVE = _zmq_has_curve() -- cgit v1.2.3