summaryrefslogtreecommitdiff
path: root/src/leap/bitmask/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/leap/bitmask/backend')
-rw-r--r--src/leap/bitmask/backend/backend.py31
-rw-r--r--src/leap/bitmask/backend/backend_proxy.py18
-rw-r--r--src/leap/bitmask/backend/signaler.py18
-rw-r--r--src/leap/bitmask/backend/signaler_qt.py29
-rw-r--r--src/leap/bitmask/backend/utils.py54
5 files changed, 107 insertions, 43 deletions
diff --git a/src/leap/bitmask/backend/backend.py b/src/leap/bitmask/backend/backend.py
index 75eff8a9..32f5c953 100644
--- a/src/leap/bitmask/backend/backend.py
+++ b/src/leap/bitmask/backend/backend.py
@@ -28,10 +28,14 @@ import psutil
from twisted.internet import defer, reactor, threads
import zmq
-from zmq.auth.thread import ThreadAuthenticator
+try:
+ from zmq.auth.thread import ThreadAuthenticator
+except ImportError:
+ pass
from leap.bitmask.backend.api import API, PING_REQUEST
from leap.bitmask.backend.utils import get_backend_certificates
+from leap.bitmask.config import flags
from leap.bitmask.backend.signaler import Signaler
import logging
@@ -73,18 +77,19 @@ class Backend(object):
context = zmq.Context()
socket = context.socket(zmq.REP)
- # Start an authenticator for this context.
- auth = ThreadAuthenticator(context)
- auth.start()
- # XXX do not hardcode this here.
- auth.allow('127.0.0.1')
-
- # Tell authenticator to use the certificate in a directory
- auth.configure_curve(domain='*', location=zmq.auth.CURVE_ALLOW_ANY)
- public, secret = get_backend_certificates()
- socket.curve_publickey = public
- socket.curve_secretkey = secret
- socket.curve_server = True # must come before bind
+ if flags.ZMQ_HAS_CURVE:
+ # Start an authenticator for this context.
+ auth = ThreadAuthenticator(context)
+ auth.start()
+ # XXX do not hardcode this here.
+ auth.allow('127.0.0.1')
+
+ # Tell authenticator to use the certificate in a directory
+ auth.configure_curve(domain='*', location=zmq.auth.CURVE_ALLOW_ANY)
+ public, secret = get_backend_certificates()
+ socket.curve_publickey = public
+ socket.curve_secretkey = secret
+ socket.curve_server = True # must come before bind
socket.bind(self.BIND_ADDR)
diff --git a/src/leap/bitmask/backend/backend_proxy.py b/src/leap/bitmask/backend/backend_proxy.py
index 3e79289f..06e6d840 100644
--- a/src/leap/bitmask/backend/backend_proxy.py
+++ b/src/leap/bitmask/backend/backend_proxy.py
@@ -30,6 +30,7 @@ import zmq
from leap.bitmask.backend.api import API, STOP_REQUEST, PING_REQUEST
from leap.bitmask.backend.utils import generate_zmq_certificates_if_needed
from leap.bitmask.backend.utils import get_backend_certificates
+from leap.bitmask.config import flags
import logging
logger = logging.getLogger(__name__)
@@ -59,15 +60,16 @@ class BackendProxy(object):
logger.debug("Connecting to server...")
socket = context.socket(zmq.REQ)
- # public, secret = zmq.curve_keypair()
- client_keys = zmq.curve_keypair()
- socket.curve_publickey = client_keys[0]
- socket.curve_secretkey = client_keys[1]
+ if flags.ZMQ_HAS_CURVE:
+ # public, secret = zmq.curve_keypair()
+ client_keys = zmq.curve_keypair()
+ socket.curve_publickey = client_keys[0]
+ socket.curve_secretkey = client_keys[1]
- # The client must know the server's public key to make a CURVE
- # connection.
- public, _ = get_backend_certificates()
- socket.curve_serverkey = public
+ # The client must know the server's public key to make a CURVE
+ # connection.
+ public, _ = get_backend_certificates()
+ socket.curve_serverkey = public
socket.setsockopt(zmq.RCVTIMEO, 1000)
socket.setsockopt(zmq.LINGER, 0) # Terminate early
diff --git a/src/leap/bitmask/backend/signaler.py b/src/leap/bitmask/backend/signaler.py
index 43cba994..a8498d11 100644
--- a/src/leap/bitmask/backend/signaler.py
+++ b/src/leap/bitmask/backend/signaler.py
@@ -26,6 +26,7 @@ import zmq
from leap.bitmask.backend.api import SIGNALS
from leap.bitmask.backend.utils import get_frontend_certificates
+from leap.bitmask.config import flags
import logging
logger = logging.getLogger(__name__)
@@ -49,15 +50,16 @@ class Signaler(object):
logger.debug("Connecting to signaling server...")
socket = context.socket(zmq.REQ)
- # public, secret = zmq.curve_keypair()
- client_keys = zmq.curve_keypair()
- socket.curve_publickey = client_keys[0]
- socket.curve_secretkey = client_keys[1]
+ if flags.ZMQ_HAS_CURVE:
+ # public, secret = zmq.curve_keypair()
+ client_keys = zmq.curve_keypair()
+ socket.curve_publickey = client_keys[0]
+ socket.curve_secretkey = client_keys[1]
- # The client must know the server's public key to make a CURVE
- # connection.
- public, _ = get_frontend_certificates()
- socket.curve_serverkey = public
+ # The client must know the server's public key to make a CURVE
+ # connection.
+ public, _ = get_frontend_certificates()
+ socket.curve_serverkey = public
socket.setsockopt(zmq.RCVTIMEO, 1000)
socket.setsockopt(zmq.LINGER, 0) # Terminate early
diff --git a/src/leap/bitmask/backend/signaler_qt.py b/src/leap/bitmask/backend/signaler_qt.py
index 433f18ed..94c24648 100644
--- a/src/leap/bitmask/backend/signaler_qt.py
+++ b/src/leap/bitmask/backend/signaler_qt.py
@@ -24,10 +24,14 @@ import time
from PySide import QtCore
import zmq
-from zmq.auth.thread import ThreadAuthenticator
+try:
+ from zmq.auth.thread import ThreadAuthenticator
+except ImportError:
+ pass
from leap.bitmask.backend.api import SIGNALS
from leap.bitmask.backend.utils import get_frontend_certificates
+from leap.bitmask.config import flags
import logging
logger = logging.getLogger(__name__)
@@ -67,17 +71,18 @@ class SignalerQt(QtCore.QObject):
context = zmq.Context()
socket = context.socket(zmq.REP)
- # Start an authenticator for this context.
- auth = ThreadAuthenticator(context)
- auth.start()
- auth.allow('127.0.0.1')
-
- # Tell authenticator to use the certificate in a directory
- auth.configure_curve(domain='*', location=zmq.auth.CURVE_ALLOW_ANY)
- public, secret = get_frontend_certificates()
- socket.curve_publickey = public
- socket.curve_secretkey = secret
- socket.curve_server = True # must come before bind
+ if flags.ZMQ_HAS_CURVE:
+ # Start an authenticator for this context.
+ auth = ThreadAuthenticator(context)
+ auth.start()
+ auth.allow('127.0.0.1')
+
+ # Tell authenticator to use the certificate in a directory
+ auth.configure_curve(domain='*', location=zmq.auth.CURVE_ALLOW_ANY)
+ public, secret = get_frontend_certificates()
+ socket.curve_publickey = public
+ socket.curve_secretkey = secret
+ socket.curve_server = True # must come before bind
socket.bind(self.BIND_ADDR)
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()