1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2013, 2014 LEAP
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 Utilities to handle ZMQ certificates.
32 from leap.common.files import mkdir_p
33 from leap.common.check import leap_assert
35 logger = logging.getLogger(__name__)
38 KEYS_PREFIX = "zmq_certificates"
39 PUBLIC_KEYS_PREFIX = os.path.join(KEYS_PREFIX, "public_keys")
40 PRIVATE_KEYS_PREFIX = os.path.join(KEYS_PREFIX, "private_keys")
45 Return whether the current ZMQ has support for auth and CurveZMQ security.
50 `zmq.curve_keypair()` is new in version 14.0, new in version libzmq-4.0.
51 Requires libzmq (>= 4.0) to have been linked with libsodium.
52 `zmq.auth` module is new in version 14.1
53 `zmq.has()` is new in version 14.1, new in version libzmq-4.1.
55 zmq_version = zmq.zmq_version_info()
56 pyzmq_version = zmq.pyzmq_version_info()
58 if pyzmq_version >= (14, 1, 0) and zmq_version >= (4, 1):
59 return zmq.has('curve')
61 if pyzmq_version < (14, 1, 0):
64 if zmq_version < (4, 0):
65 # security is new in libzmq 4.0
70 except zmq.error.ZMQError:
71 # security requires libzmq to be linked against libsodium
77 def assert_zmq_has_curve():
78 leap_assert(zmq_has_curve, "CurveZMQ not supported!")
81 def maybe_create_and_get_certificates(basedir, name):
83 Generate the needed ZMQ certificates for backend/frontend communication if
86 assert_zmq_has_curve()
87 private_keys_dir = os.path.join(basedir, PRIVATE_KEYS_PREFIX)
88 private_key = os.path.join(
89 private_keys_dir, name + ".key_secret")
90 if not os.path.isfile(private_key):
91 mkdir_p(private_keys_dir)
92 zmq.auth.create_certificates(private_keys_dir, name)
93 # set permissions to: 0700 (U:rwx G:--- O:---)
94 os.chmod(private_key, stat.S_IRUSR | stat.S_IWUSR)
95 # move public key to public keys directory
96 public_keys_dir = os.path.join(basedir, PUBLIC_KEYS_PREFIX)
97 old_public_key = os.path.join(
98 private_keys_dir, name + ".key")
99 new_public_key = os.path.join(
100 public_keys_dir, name + ".key")
101 mkdir_p(public_keys_dir)
102 shutil.move(old_public_key, new_public_key)
103 return zmq.auth.load_certificate(private_key)