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 test_curve(self): """test CURVE encryption""" server = self.socket(zmq.DEALER) server.identity = b"IDENT" client = self.socket(zmq.DEALER) self.sockets.extend([server, client]) try: server.curve_server = True except zmq.ZMQError as e: # will raise EINVAL if not linked against libsodium if e.errno == zmq.EINVAL: raise SkipTest("CURVE unsupported") server_public, server_secret = zmq.curve_keypair() client_public, client_secret = zmq.curve_keypair() server.curve_secretkey = server_secret server.curve_publickey = server_public client.curve_serverkey = server_public client.curve_publickey = client_public client.curve_secretkey = client_secret self.assertEqual(server.mechanism, zmq.CURVE) self.assertEqual(client.mechanism, zmq.CURVE) self.assertEqual(server.get(zmq.CURVE_SERVER), True) self.assertEqual(client.get(zmq.CURVE_SERVER), False) self.start_zap() iface = "tcp://127.0.0.1" port = server.bind_to_random_port(iface) client.connect("%s:%i" % (iface, port)) self.bounce(server, client) self.stop_zap()
def test_curve(self): """test CURVE encryption""" server = self.socket(zmq.DEALER) server.identity = b'IDENT' client = self.socket(zmq.DEALER) self.sockets.extend([server, client]) try: server.curve_server = True except zmq.ZMQError as e: # will raise EINVAL if no CURVE support if e.errno == zmq.EINVAL: raise SkipTest("CURVE unsupported") server_public, server_secret = zmq.curve_keypair() client_public, client_secret = zmq.curve_keypair() server.curve_secretkey = server_secret server.curve_publickey = server_public client.curve_serverkey = server_public client.curve_publickey = client_public client.curve_secretkey = client_secret self.assertEqual(server.mechanism, zmq.CURVE) self.assertEqual(client.mechanism, zmq.CURVE) self.assertEqual(server.get(zmq.CURVE_SERVER), True) self.assertEqual(client.get(zmq.CURVE_SERVER), False) with self.zap(): iface = 'tcp://127.0.0.1' port = server.bind_to_random_port(iface) client.connect("%s:%i" % (iface, port)) self.bounce(server, client)
def setUp(self): if zmq.zmq_version_info() < (4,0): raise SkipTest("security is new in libzmq 4.0") try: zmq.curve_keypair() except zmq.ZMQError: raise SkipTest("security requires libzmq to be linked against libsodium") super(TestSecurity, self).setUp()
def setUp(self): if zmq.zmq_version_info() < (4, 0): raise SkipTest("security is new in libzmq 4.0") try: zmq.curve_keypair() except zmq.ZMQError: raise SkipTest("security requires libzmq to be linked against libsodium") super(TestSecurity, self).setUp()
def setUp(self): if zmq.zmq_version_info() < (4,0): raise SkipTest("security is new in libzmq 4.0") try: zmq.curve_keypair() except zmq.ZMQError: raise SkipTest("security requires libzmq to be built with CURVE support") super(TestSecurity, self).setUp()
def generate_shared_secret(): """Compute a new pair of random CurveZMQ secret keys, decode them from z85 encoding, and return the result as a base64 encoded unicode string as suitable for passing to SecureContext() or storing on disk. We use base64 because it is more compatible with Python config files than z85.""" _check_versions() _, client_secret = zmq.curve_keypair() _, server_secret = zmq.curve_keypair() return base64.b64encode( zmq.utils.z85.decode(client_secret) + zmq.utils.z85.decode(server_secret)).decode('utf8')
def test_untrusted_curve_with_allowed_password(self): from pseud import Client, Server from pseud.utils import register_rpc from pseud._tornado import async_sleep client_id = b'john' server_id = b'server' endpoint = b'tcp://127.0.0.1:8999' server_public, server_secret = zmq.curve_keypair() client_public, client_secret = zmq.curve_keypair() security_plugin = 'untrusted_curve' password = b's3cret!' client = Client(server_id, security_plugin=security_plugin, public_key=client_public, secret_key=client_secret, peer_public_key=server_public, user_id=client_id, password=password, io_loop=self.io_loop) server = Server(server_id, security_plugin=security_plugin, public_key=server_public, secret_key=server_secret, io_loop=self.io_loop) server.bind(endpoint) client.connect(endpoint) assert server.socket.mechanism == zmq.CURVE assert client.socket.mechanism == zmq.CURVE # configure manually authentication backend server.auth_backend.user_map[client_id] = password yield server.start() yield client.start() register_rpc(name='string.lower')(str.lower) future = client.string.lower('FOO') future2 = client.string.lower('FOO_JJ') yield async_sleep(self.io_loop, .01) future3 = server.send_to(client_id).string.lower('ABC') result = yield future result2 = yield future2 result3 = yield future3 assert result == 'foo' assert result2 == 'foo_jj' assert result3 == 'abc' server.stop() client.stop()
def test_untrusted_curve_with_allowed_password_and_client_disconnect(self): from pseud import Client, Server from pseud._tornado import async_sleep client_id = b'john' server_id = b'server' endpoint = b'tcp://127.0.0.1:8999' server_public, server_secret = zmq.curve_keypair() client_public, client_secret = zmq.curve_keypair() security_plugin = 'untrusted_curve' password = b's3cret!' client = Client(server_id, security_plugin=security_plugin, public_key=client_public, secret_key=client_secret, peer_public_key=server_public, user_id=client_id, password=password, timeout=1, io_loop=self.io_loop) server = Server(server_id, security_plugin=security_plugin, public_key=server_public, secret_key=server_secret, io_loop=self.io_loop) server.bind(endpoint) client.connect(endpoint) assert server.socket.mechanism == zmq.CURVE assert client.socket.mechanism == zmq.CURVE # configure manually authentication backend server.auth_backend.user_map[client_id] = password yield server.start() yield client.start() server.register_rpc(name='string.lower')(str.lower) result = yield client.string.lower('FOO') assert result == 'foo' # Simulate disconnection and reconnection with new identity client.disconnect(endpoint) client.connect(endpoint) yield async_sleep(self.io_loop, .15) result = yield client.string.lower('ABC') assert result == 'abc' server.stop() client.stop()
def configure(self): self.rpc.socket.curve_publickey = self.rpc.public_key self.rpc.socket.curve_secretkey = self.rpc.secret_key self.rpc.socket.curve_server = True assert self.rpc.socket.mechanism == zmq.CURVE assert self.rpc.socket.get(zmq.CURVE_SERVER) self.zap_socket = zap_socket = self.rpc.context.socket(zmq.ROUTER) zap_socket.linger = 1 zap_socket.bind(b'inproc://zeromq.zap.01') self.reader = self.rpc.read_forever(zap_socket, self._zap_handler, copy=True) self.known_identities = {b'bob': zmq.curve_keypair(), b'alice': zmq.curve_keypair()}
def test_untrusted_curve_with_allowed_password_and_client_disconnect(self): from pseud import Client, Server client_id = b'john' server_id = b'server' endpoint = b'tcp://127.0.0.1:8999' server_public, server_secret = zmq.curve_keypair() client_public, client_secret = zmq.curve_keypair() security_plugin = 'untrusted_curve' password = b's3cret!' client = Client(server_id, security_plugin=security_plugin, public_key=client_public, secret_key=client_secret, peer_public_key=server_public, user_id=client_id, password=password, timeout=1, io_loop=self.io_loop) server = Server(server_id, security_plugin=security_plugin, public_key=server_public, secret_key=server_secret, io_loop=self.io_loop) server.bind(endpoint) client.connect(endpoint) assert server.socket.mechanism == zmq.CURVE assert client.socket.mechanism == zmq.CURVE # configure manually authentication backend server.auth_backend.user_map[client_id] = password yield server.start() yield client.start() server.register_rpc(name='string.lower')(str.lower) result = yield client.string.lower('FOO') assert result == 'foo' # Simulate disconnection and reconnection with new identity client.disconnect(endpoint) client.connect(endpoint) result = yield client.string.lower('ABC') assert result == 'abc' server.stop() client.stop()
def bind(self, sock, bind_fn=None): """Extended zmq.Socket.bind() to include options in the address.""" if not self.domain: raise ValueError('Address domain must be set') sock.zap_domain = self.domain.encode("utf-8") or b'' self._set_sock_identity(sock) sock.ipv6 = self.ipv6 or False if self.server == 'CURVE': if not self.secretkey: raise ValueError('CURVE server used without secretkey') sock.curve_server = True sock.curve_secretkey = self.secretkey elif self.server == 'PLAIN': sock.plain_server = True else: sock.curve_server = False sock.plain_server = False if self.serverkey: sock.curve_serverkey = self.serverkey if not (self.publickey and self.secretkey): self.publickey, self.secretkey = curve_keypair() sock.curve_secretkey = self.secretkey sock.curve_publickey = self.publickey elif self.username: sock.plain_username = self.username sock.plain_password = self.password or b'' try: (bind_fn or sock.bind)(self.base) self.base = sock.last_endpoint.decode("utf-8") except ZMQError: message = 'Attempted to bind Volttron to already bound address {}, stopping' message = message.format(self.base) _log.error(message) print("\n" + message + "\n") sys.exit(1)
async def start(self): self.__ctx = zmq.asyncio.Context() self.__socket = self.__ctx.socket(zmq.SUB) # in compat mode; there is NO subscribe keypair data key_pair = self.cfg.get_zmq_subscribe_keypair() if key_pair is not None: self.__socket.curve_serverkey = key_pair.strip( ) # the first line is the public key # for the client socket, the curve key pair will be regenerated all the time # the important part for "authentication" is the server "public" key self.__socket.curve_publickey, self.__socket.curve_secretkey = zmq.curve_keypair( ) else: logger.info( "no ZMQ subscriber keypair exists; assuming compat mode") self.__socket.connect(get_zmq_broker_xsub_endpoint(self.cfg)) # Subscribe to all topics self.__socket.subscribe('') logger.info("filewave server event subscriber has started") asyncio.create_task(self.forward_events())
async def test_trusted_curve_with_wrong_peer_public_key( loop, unused_tcp_port_factory): from pseud import Client, Server from pseud.utils import register_rpc server_id = b'server' port = unused_tcp_port_factory() endpoint = f'tcp://127.0.0.1:{port}' server_public, server_secret = zmq.curve_keypair() server = Server(server_id, security_plugin='trusted_curve', public_key=server_public, secret_key=server_secret, loop=loop) server.bind(endpoint) alice_public, alice_secret = \ server.auth_backend.known_identities[b'alice'] client = Client(server_id, user_id=b'alice', security_plugin='trusted_curve', public_key=alice_public, secret_key=alice_secret, peer_public_key=z85.encode(b'R' * 32), timeout=.5, loop=loop) client.connect(endpoint) assert server.socket.mechanism == zmq.CURVE assert client.socket.mechanism == zmq.CURVE register_rpc(name='string.lower')(str.lower) async with server, client: with pytest.raises(asyncio.TimeoutError): await client.string.lower('BAR')
async def test_trusted_curve(loop, unused_tcp_port, trusted_curve_auth_backend): from pseud import Client, Server from pseud.utils import register_rpc server_id = b'server' endpoint = f'tcp://127.0.0.1:{unused_tcp_port}' server_public, server_secret = zmq.curve_keypair() security_plugin = 'trusted_curve' server = Server(server_id, security_plugin=security_plugin, public_key=server_public, secret_key=server_secret, loop=loop) server.bind(endpoint) bob_public, bob_secret = server.auth_backend.known_identities[b'bob'] client = Client(server_id, user_id=b'bob', security_plugin=security_plugin, public_key=bob_public, secret_key=bob_secret, peer_public_key=server_public, loop=loop) client.connect(endpoint) assert server.socket.mechanism == zmq.CURVE assert client.socket.mechanism == zmq.CURVE register_rpc(name='string.lower')(str.lower) async with server, client: result = await client.string.lower('FOO') assert result == 'foo'
def generate(self): """Generate new key pair""" public, secret = curve_keypair() self.store({ 'public': encode_key(public), 'secret': encode_key(secret) })
def __init__(self): generate_zmq_certificates_if_needed() self._socket = None # initialize ZMQ stuff: context = zmq.Context() logger.debug("Connecting to server...") socket = context.socket(zmq.REQ) 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 socket.setsockopt(zmq.RCVTIMEO, 1000) socket.setsockopt(zmq.LINGER, 0) # Terminate early socket.connect(self.SERVER) self._socket = socket self._ping_at = 0 self.online = False self._call_queue = Queue.Queue() self._worker_caller = threading.Thread(target=self._worker)
def reset(self, public_key=None, secret_key=None): """ Remove any existing state and reset as a new node. """ if not public_key: public_key, secret_key = zmq.curve_keypair() public_key = z85.decode(public_key) secret_key = z85.decode(secret_key) else: secret_key = z85.decode(secret_key) public_key = z85.decode(public_key) if public_key and HAS_NACL: computed_key = str(PrivateKey(secret_key).public_key) assert (computed_key == public_key) self.node = Node(self.addr, self.port, public_key, secret_key) self.hashtabe = {} if HAS_NACL: self.secret_key = PrivateKey(self.node.secret_key) self.nodetree = RoutingZone(self.node.node_id) # ensure we exist in own tree self.nodetree.add(self.node) self.txmap = transaction.TxMap() self.defrag = transport.DefragMap() self._dump_state()
def run(user_params): if len(user_params) < 4: print_usage() return -1 tcp_endpoint = user_params[1] server_key = user_params[2] context = zmq.Context.instance() dealer = context.socket(zmq.DEALER) # random key as the server doesn't check those client_public, client_secret = zmq.curve_keypair() dealer.curve_serverkey = server_key dealer.curve_publickey = client_public dealer.curve_secretkey = client_secret connect_str = "tcp://" + str(tcp_endpoint) dealer.connect(connect_str) print "Connected to " + connect_str ch = CommandHandler(dealer, user_params ); ret = ch.handle_command(user_params[3]) time.sleep(1) context.destroy(linger=5000) return ret
def bind(self, sock, bind_fn=None): '''Extended zmq.Socket.bind() to include options in the address.''' if not self.domain: raise ValueError('Address domain must be set') sock.zap_domain = self.domain or '' if self.identity: sock.identity = self.identity elif not sock.identity: sock.identity = self.identity = bytes(uuid.uuid4()) sock.ipv6 = self.ipv6 or False if self.server == 'CURVE': if not self.secretkey: raise ValueError('CURVE server used without secretkey') sock.curve_server = True sock.curve_secretkey = self.secretkey elif self.server == 'PLAIN': sock.plain_server = True else: sock.curve_server = False sock.plain_server = False if self.serverkey: sock.curve_serverkey = self.serverkey if not (self.publickey and self.secretkey): self.publickey, self.secretkey = curve_keypair() sock.curve_secretkey = self.secretkey sock.curve_publickey = self.publickey elif self.username: sock.plain_username = self.username sock.plain_password = self.password or b'' (bind_fn or sock.bind)(self.base) self.base = sock.last_endpoint
def __init__(self): self._socket = None # initialize ZMQ stuff: context = zmq.Context() 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] # 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.connect(self.SERVER) self._socket = socket self._call_queue = Queue.Queue() self._worker_caller = threading.Thread(target=self._worker) self._worker_caller.start()
def run(user_params): if len(user_params) < 4: print_usage() return -1 tcp_endpoint = user_params[1] server_key = user_params[2] context = zmq.Context.instance() dealer = context.socket(zmq.DEALER) # random key as the server doesn't check those client_public, client_secret = zmq.curve_keypair() dealer.curve_serverkey = server_key dealer.curve_publickey = client_public dealer.curve_secretkey = client_secret connect_str = "tcp://" + str(tcp_endpoint) dealer.connect(connect_str) print "Connected to " + connect_str ch = CommandHandler(dealer, user_params) ret = ch.handle_command(user_params[3]) time.sleep(1) context.destroy(linger=5000) return ret
def __init__(self): """ Initialize the ZMQ socket to talk to the signaling server. """ context = zmq.Context() 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] # 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.connect(self.SERVER) self._socket = socket self._signal_queue = Queue.Queue() self._do_work = threading.Event() # used to stop the worker thread. self._worker_signaler = threading.Thread(target=self._worker)
def __init__(self): """ Initialize the ZMQ socket to talk to the signaling server. """ context = zmq.Context() logger.debug("Connecting to signaling server...") socket = context.socket(zmq.REQ) 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 socket.setsockopt(zmq.RCVTIMEO, 1000) socket.setsockopt(zmq.LINGER, 0) # Terminate early socket.connect(self.SERVER) self._socket = socket self._signal_queue = Queue.Queue() self._do_work = threading.Event() # used to stop the worker thread. self._worker_signaler = threading.Thread(target=self._worker)
def __init__(self, url): context = get_context() import caffeine.keytools (zeromq_url, z85_public, z85_private, z85_server) = caffeine.keytools.parseURL(url) if z85_server: # In this case, we enable encryption and assume we're talking to a # ROUTER self.socket = context.socket(zmq.REQ) client_public, client_secret = zmq.curve_keypair() self.socket.curve_publickey = z85_public self.socket.curve_secretkey = z85_private self.socket.curve_serverkey = z85_server self.burned_ready = True # not required for router self.router_style_messages = True self.socket.connect(zeromq_url) else: # In this case, we handle direct mode self.burned_ready = False self.socket = context.socket(zmq.REP) self.router_style_messages = False self.socket.bind(zeromq_url) print(zeromq_url, z85_public, z85_private, z85_server) print("client connecting to URL %s" % url)
def _init_zmq(self): """ Configure the zmq components and connection. """ logger.debug("Setting up ZMQ connection to server...") context = zmq.Context() socket = context.socket(zmq.REQ) # we use zmq's eventloop in order to asynchronously send requests loop = ioloop.ZMQIOLoop.current() self._stream = zmqstream.ZMQStream(socket, loop) 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 socket.setsockopt(zmq.RCVTIMEO, 1000) socket.setsockopt(zmq.LINGER, 0) # Terminate early self._stream.on_recv(self._on_recv)
def configure(self): self.rpc.socket.curve_publickey = self.rpc.public_key self.rpc.socket.curve_secretkey = self.rpc.secret_key self.rpc.socket.curve_server = True assert self.rpc.socket.mechanism == zmq.CURVE assert self.rpc.socket.get(zmq.CURVE_SERVER) self.zap_socket = zap_socket = self.rpc.context.socket(zmq.ROUTER) zap_socket.linger = 1 zap_socket.bind(b'inproc://zeromq.zap.01') self.reader = self.rpc.read_forever(zap_socket, self._zap_handler, copy=True) self.known_identities = { b'bob': zmq.curve_keypair(), b'alice': zmq.curve_keypair() }
async def test_trusted_curve(loop, unused_tcp_port): from pseud import Client, Server from pseud.utils import register_rpc server_id = b'server' endpoint = f'tcp://127.0.0.1:{unused_tcp_port}' server_public, server_secret = zmq.curve_keypair() security_plugin = 'trusted_curve' server = Server(server_id, security_plugin=security_plugin, public_key=server_public, secret_key=server_secret, loop=loop) server.bind(endpoint) bob_public, bob_secret = server.auth_backend.known_identities[b'bob'] client = Client(server_id, user_id=b'bob', security_plugin=security_plugin, public_key=bob_public, secret_key=bob_secret, peer_public_key=server_public, loop=loop) client.connect(endpoint) assert server.socket.mechanism == zmq.CURVE assert client.socket.mechanism == zmq.CURVE register_rpc(name='string.lower')(str.lower) async with server, client: result = await client.string.lower('FOO') assert result == 'foo'
async def test_untrusted_curve_with_allowed_password_and_client_disconnect( loop, unused_tcp_port): from pseud import Client, Server client_id = b'john' server_id = b'server' endpoint = f'tcp://127.0.0.1:{unused_tcp_port}' server_public, server_secret = zmq.curve_keypair() client_public, client_secret = zmq.curve_keypair() security_plugin = 'untrusted_curve' password = b's3cret!' client = Client(server_id, security_plugin=security_plugin, public_key=client_public, secret_key=client_secret, peer_public_key=server_public, user_id=client_id, password=password, timeout=1, loop=loop) server = Server(server_id, security_plugin=security_plugin, public_key=server_public, secret_key=server_secret, loop=loop) server.bind(endpoint) client.connect(endpoint) assert server.socket.mechanism == zmq.CURVE assert client.socket.mechanism == zmq.CURVE # configure manually authentication backend server.auth_backend.user_map[client_id] = password server.register_rpc(name='string.lower')(str.lower) async with server, client: result = await client.string.lower('FOO') assert result == 'foo' # Simulate disconnection and reconnection with new identity client.disconnect(endpoint) client.connect(endpoint) await asyncio.sleep(.1) result = await client.string.lower('ABC') assert result == 'abc'
def test_untrusted_curve_with_wrong_password(self): from pseud import Client, Server from pseud.interfaces import UnauthorizedError from pseud.utils import register_rpc client_id = b'john' server_id = b'server' endpoint = b'tcp://127.0.0.1:8998' server_public, server_secret = zmq.curve_keypair() client_public, client_secret = zmq.curve_keypair() security_plugin = 'untrusted_curve' password = b's3cret!' client = Client(server_id, user_id=client_id, security_plugin=security_plugin, public_key=client_public, secret_key=client_secret, peer_public_key=server_public, password=password, io_loop=self.io_loop) server = Server(server_id, security_plugin=security_plugin, public_key=server_public, secret_key=server_secret, io_loop=self.io_loop) server.bind(endpoint) client.connect(endpoint) assert server.socket.mechanism == zmq.CURVE assert client.socket.mechanism == zmq.CURVE # configure manually authentication backend server.auth_backend.user_map[client_id] = password + b'Looser' yield server.start() yield client.start() register_rpc(name='string.lower')(str.lower) future = client.string.lower(b'IMSCREAMING') with pytest.raises(UnauthorizedError): yield future server.stop() client.stop()
def create_keypair(self): ''' Generate a new CURVE-25519 public-private keypair. ''' # NOTE: currently we rely on zmq for convenience, but we may use libnacl directly # if we want to isolate this module from zmq dependency. public_key, private_key = zmq.curve_keypair() return public_key, private_key
def setup(self, socket_type): """ :param socket_type: zmq.DEALER or zmq.ROUTER """ if self._secured: if self._server_public_key is None or \ self._server_private_key is None: raise LocalConfigurationError("Attempting to start socket " "in secure mode, but complete " "server keys were not provided") self._event_loop = zmq.asyncio.ZMQEventLoop() asyncio.set_event_loop(self._event_loop) self._context = zmq.asyncio.Context() self._socket = self._context.socket(socket_type) if socket_type == zmq.DEALER: self._socket.identity = "{}-{}".format( self._zmq_identity, hashlib.sha512(uuid.uuid4().hex.encode()).hexdigest() [:23]).encode('ascii') if self._secured: # Generate ephemeral certificates for this connection self._socket.curve_publickey, self._socket.curve_secretkey = \ zmq.curve_keypair() self._socket.curve_serverkey = self._server_public_key self._dispatcher.add_send_message(self._connection, self.send_message) self._socket.connect(self._address) elif socket_type == zmq.ROUTER: if self._secured: auth = AsyncioAuthenticator(self._context) auth.start() auth.configure_curve(domain='*', location=zmq.auth.CURVE_ALLOW_ANY) self._socket.curve_secretkey = self._server_private_key self._socket.curve_publickey = self._server_public_key self._socket.curve_server = True self._dispatcher.add_send_message(self._connection, self.send_message) self._socket.bind(self._address) self._recv_queue = asyncio.Queue() asyncio.ensure_future(self._receive_message(), loop=self._event_loop) if self._heartbeat: asyncio.ensure_future(self._send_heartbeat(), loop=self._event_loop) with self._condition: self._condition.notify_all() self._event_loop.run_forever()
async def test_untrusted_curve_with_allowed_password( loop, unused_tcp_port, untrusted_curve_auth_backend): from pseud import Client, Server from pseud.utils import register_rpc client_id = b'john' server_id = b'server' endpoint = f'tcp://127.0.0.1:{unused_tcp_port}' server_public, server_secret = zmq.curve_keypair() client_public, client_secret = zmq.curve_keypair() security_plugin = 'untrusted_curve' password = b's3cret!' client = Client(server_id, security_plugin=security_plugin, public_key=client_public, secret_key=client_secret, peer_public_key=server_public, user_id=client_id, password=password, loop=loop) server = Server(server_id, security_plugin=security_plugin, public_key=server_public, secret_key=server_secret, loop=loop) server.bind(endpoint) client.connect(endpoint) assert server.socket.mechanism == zmq.CURVE assert client.socket.mechanism == zmq.CURVE # configure manually authentication backend server.auth_backend.user_map[client_id] = password register_rpc(name='string.lower')(str.lower) async with server, client: result = await client.string.lower('FOO') result2 = await client.string.lower('FOO_JJ') result3 = await server.send_to(client_id).string.lower('ABC') assert result == 'foo' assert result2 == 'foo_jj' assert result3 == 'abc'
async def test_untrusted_curve_with_allowed_password(loop, unused_tcp_port): from pseud import Client, Server from pseud.utils import register_rpc client_id = b'john' server_id = b'server' endpoint = f'tcp://127.0.0.1:{unused_tcp_port}' server_public, server_secret = zmq.curve_keypair() client_public, client_secret = zmq.curve_keypair() security_plugin = 'untrusted_curve' password = b's3cret!' client = Client(server_id, security_plugin=security_plugin, public_key=client_public, secret_key=client_secret, peer_public_key=server_public, user_id=client_id, password=password, loop=loop) server = Server(server_id, security_plugin=security_plugin, public_key=server_public, secret_key=server_secret, loop=loop) server.bind(endpoint) client.connect(endpoint) assert server.socket.mechanism == zmq.CURVE assert client.socket.mechanism == zmq.CURVE # configure manually authentication backend server.auth_backend.user_map[client_id] = password register_rpc(name='string.lower')(str.lower) async with server, client: result = await client.string.lower('FOO') result2 = await client.string.lower('FOO_JJ') result3 = await server.send_to(client_id).string.lower('ABC') assert result == 'foo' assert result2 == 'foo_jj' assert result3 == 'abc'
def resolve(self, header): newCtx = zmq.Context() dealer = newCtx.socket(zmq.DEALER) if (dealer.closed): print("Dealer Closed") else: print("Dealer is Open") try: dealer.setsockopt_string(zmq.IDENTITY, header["payload"]) #dealer.identity = str(header["payload"]) except Exception as e: self.logger.error("Inside Resolve: Error setting identity - " + str(e.args)) serverKey = "" for i in range(len(header["options"])): if (header["options"][i]["number"] == 2048): serverKeyOption = header["options"][i] serverKey = serverKeyOption["value"] try: client_public, client_secret = zmq.curve_keypair() except Exception as e: self.logger.error("Inside Resolve: Error getting keypair - " + str(e.args)) try: dealer.curve_secretkey = client_secret dealer.curve_publickey = client_public except Exception as e: self.logger.error( "Inside Resolve: Error setting dealer Public/Private keys - " + str(e.args)) try: dealer.curve_serverkey = bytes(serverKey.encode('ascii')) except Exception as e: self.logger.error( "Inside Resolve: Error setting dealer Server key - " + str(e.args)) try: dealer.connect(self.dealer_endpoint) print("connected to dealer") except Exception as e: self.logger.error("Inside Resolve: Error connecting dealer - " + str(e.args)) try: message = dealer.recv(0) #print(message) except Exception as e: self.logger.error("Inside resolve: Didn't get reponse " + str(e.args)) parsed_response = self.handle_response(message, self.returnPayload) return parsed_response
def generate_zmq_keys(): """ Generates new public-private key pair for ZMQ encryption. Returns ------- str, str Public (first) and private (second) keys. """ key_public, key_private = zmq.curve_keypair() return key_public.decode("utf-8"), key_private.decode("utf-8")
def _set_curve_keypair(self, socket: zmq.Socket): """ Generate a client keypair using CURVE encryption mechanism, and set the server key for encryption. :param socket: (zmq.Socket) The socket to set CURVE key. """ client_public, client_secret = zmq.curve_keypair() socket.curve_publickey = client_public socket.curve_secretkey = client_secret socket.setsockopt_string(zmq.CURVE_SERVERKEY, self._SERVER_ZMQ_ENCRYPTION_KEY)
async def test_untrusted_curve_with_wrong_password(loop, unused_tcp_port): from pseud import Client, Server from pseud.interfaces import UnauthorizedError from pseud.utils import register_rpc client_id = b'john' server_id = b'server' endpoint = f'tcp://127.0.0.1:{unused_tcp_port}' server_public, server_secret = zmq.curve_keypair() client_public, client_secret = zmq.curve_keypair() security_plugin = 'untrusted_curve' password = b's3cret!' client = Client(server_id, user_id=client_id, security_plugin=security_plugin, public_key=client_public, secret_key=client_secret, peer_public_key=server_public, password=password, loop=loop) server = Server(server_id, security_plugin=security_plugin, public_key=server_public, secret_key=server_secret, loop=loop) server.bind(endpoint) client.connect(endpoint) assert server.socket.mechanism == zmq.CURVE assert client.socket.mechanism == zmq.CURVE # configure manually authentication backend server.auth_backend.user_map[client_id] = password + b'Looser' register_rpc(name='string.lower')(str.lower) async with server, client: with pytest.raises(UnauthorizedError): await client.string.lower(b'IMSCREAMING')
def generate_keypair_dict(): """Generate and return new keypair as dictionary""" public, secret = curve_keypair() encoded_public = encode_key(public) encoded_secret = encode_key(secret) attempts = 0 max_attempts = 3 done = False while not done and attempts < max_attempts: # Keys that start with '-' are hard to use and cause issues with the platform if encoded_secret.startswith('-') or encoded_public.startswith('-'): # try generating public and secret key again public, secret = curve_keypair() encoded_public = encode_key(public) encoded_secret = encode_key(secret) else: done = True return {'public': encoded_public, 'secret': encoded_secret}
def create_zmq_connection(node, sock_type): clientstack = node.clientstack sock = zmq.Context().socket(sock_type) l_pub_key, l_sec_key = zmq.curve_keypair() sock.setsockopt(zmq.IDENTITY, base64.encodebytes(l_pub_key)) sock.setsockopt(zmq.CURVE_PUBLICKEY, l_pub_key) sock.setsockopt(zmq.CURVE_SECRETKEY, l_sec_key) sock.setsockopt(zmq.TCP_KEEPALIVE, 1) sock.setsockopt(zmq.CURVE_SERVERKEY, clientstack.publicKey) sock.connect("tcp://{}:{}".format(clientstack.ha.host, clientstack.ha.port)) return sock
def add_auth(q): """Add CURVE auth to a monitored queue""" if not self.enable_curve: return False q.setsockopt_in(zmq.CURVE_SERVER, 1) q.setsockopt_in(zmq.CURVE_SECRETKEY, self.curve_secretkey) q.setsockopt_out(zmq.CURVE_SERVER, 1) q.setsockopt_out(zmq.CURVE_SECRETKEY, self.curve_secretkey) # monitor is a client pub, secret = zmq.curve_keypair() q.setsockopt_mon(zmq.CURVE_SERVERKEY, self.curve_publickey) q.setsockopt_mon(zmq.CURVE_SECRETKEY, secret) q.setsockopt_mon(zmq.CURVE_PUBLICKEY, pub)
def connect(self, sock, connect_fn=None): """Extended zmq.Socket.connect() to include options in the address.""" self._set_sock_identity(sock) sock.ipv6 = self.ipv6 or False if self.serverkey: sock.curve_serverkey = self.serverkey if not (self.publickey and self.secretkey): self.publickey, self.secretkey = curve_keypair() sock.curve_secretkey = self.secretkey sock.curve_publickey = self.publickey elif self.username and self.password is not None: sock.plain_username = self.username sock.plain_password = self.password (connect_fn or sock.connect)(self.base)
def test_roundtrip(self): import zmq import sys sys.path.append("..") import caffeine context = zmq.Context() socket = context.socket(zmq.REQ) client_public, client_secret = zmq.curve_keypair() socket.curve_publickey = client_public socket.curve_secretkey = client_secret socket.curve_serverkey = caffeine.well_known_public_key socket.connect("tcp://localhost:55555") socket.send_multipart([b'test1']) msg = socket.recv_multipart() print(msg) self.assertEquals(msg[1], b"worker says hello")
def connect(self, sock, connect_fn=None): '''Extended zmq.Socket.connect() to include options in the address.''' if self.identity: sock.identity = self.identity elif not sock.identity: sock.identity = self.identity = bytes(uuid.uuid4()) sock.ipv6 = self.ipv6 or False if self.serverkey: sock.curve_serverkey = self.serverkey if not (self.publickey and self.secretkey): self.publickey, self.secretkey = curve_keypair() sock.curve_secretkey = self.secretkey sock.curve_publickey = self.publickey elif self.username and self.password is not None: sock.plain_username = self.username sock.plain_password = self.password (connect_fn or sock.connect)(self.base)
def __init__(self, endpoint, public_key): """ Initialize the RemoteController. :param endpoint: The endpoint to connect to :param public_key: The remote host's public key. :return: """ self.zmq_context = zmq.Context.instance() self.tcp_socket = self.zmq_context.socket(zmq.DEALER) # Configure the various keys. client_public, client_secret = zmq.curve_keypair() self.tcp_socket.curve_serverkey = public_key.encode("utf-8") self.tcp_socket.curve_publickey = client_public self.tcp_socket.curve_secretkey = client_secret self.tcp_socket.connect("tcp://" + endpoint)
def test_keypair(self): """test curve_keypair""" try: public, secret = zmq.curve_keypair() except zmq.ZMQError: raise SkipTest("CURVE unsupported") self.assertEqual(type(secret), bytes) self.assertEqual(type(public), bytes) self.assertEqual(len(secret), 40) self.assertEqual(len(public), 40) # verify that it is indeed Z85 bsecret, bpublic = [z85.decode(key) for key in (public, secret)] self.assertEqual(type(bsecret), bytes) self.assertEqual(type(bpublic), bytes) self.assertEqual(len(bsecret), 32) self.assertEqual(len(bpublic), 32)
def test_client_can_reconnect(self): from pseud import Client, Server from pseud._tornado import async_sleep server_id = b'server' endpoint = b'tcp://127.0.0.1:8989' server_public, server_secret = zmq.curve_keypair() security_plugin = 'trusted_curve' server = Server(server_id, security_plugin=security_plugin, public_key=server_public, secret_key=server_secret, io_loop=self.io_loop) server.bind(endpoint) bob_public, bob_secret = server.auth_backend.known_identities[b'bob'] client = Client(server_id, user_id=b'bob', security_plugin=security_plugin, public_key=bob_public, secret_key=bob_secret, peer_public_key=server_public, io_loop=self.io_loop) client.connect(endpoint) assert server.socket.mechanism == zmq.CURVE assert client.socket.mechanism == zmq.CURVE yield server.start() yield client.start() server.register_rpc(name='string.upper')(str.upper) result = yield client.string.upper('hello') assert result == 'HELLO' client.disconnect(endpoint) client.connect(endpoint) yield async_sleep(self.io_loop, .1) result = yield client.string.upper('hello2') assert result == 'HELLO2' client.stop() server.stop()
def test_server_can_send_to_trustable_peer_identity(self): """ Uses internal metadata of zmq.Frame.get() to fetch identity of sender """ from pseud import Client, Server server_id = b'server' endpoint = b'tcp://127.0.0.1:8989' server_public, server_secret = zmq.curve_keypair() security_plugin = 'trusted_curve' server = Server(server_id, security_plugin=security_plugin, public_key=server_public, secret_key=server_secret, io_loop=self.io_loop) server.bind(endpoint) bob_public, bob_secret = server.auth_backend.known_identities[b'bob'] client = Client(server_id, user_id=b'bob', security_plugin=security_plugin, public_key=bob_public, secret_key=bob_secret, peer_public_key=server_public, io_loop=self.io_loop) client.connect(endpoint) assert server.socket.mechanism == zmq.CURVE assert client.socket.mechanism == zmq.CURVE yield server.start() yield client.start() @server.register_rpc(with_identity=True) def echo(peer_identity, message): return peer_identity, message result = yield client.echo(b'one') if zmq.zmq_version_info() >= (4, 1, 0): assert result == (b'bob', b'one') else: assert result == (b'', b'one') server.stop() client.stop()
def test_curve_public(self): """test curve_public""" try: public, secret = zmq.curve_keypair() except zmq.ZMQError: raise SkipTest("CURVE unsupported") if zmq.zmq_version_info() < (4,2): raise SkipTest("curve_public is new in libzmq 4.2") derived_public = zmq.curve_public(secret) self.assertEqual(type(derived_public), bytes) self.assertEqual(len(derived_public), 40) # verify that it is indeed Z85 bpublic = z85.decode(derived_public) self.assertEqual(type(bpublic), bytes) self.assertEqual(len(bpublic), 32) # verify that it is equal to the known public key self.assertEqual(derived_public, public)
async def test_client_can_reconnect(loop, unused_tcp_port_factory): from pseud import Client, Server port = unused_tcp_port_factory() server_id = b'server' endpoint = f'tcp://127.0.0.1:{port}' server_public, server_secret = zmq.curve_keypair() security_plugin = 'trusted_curve' server = Server(server_id, security_plugin=security_plugin, public_key=server_public, secret_key=server_secret, loop=loop) server.bind(endpoint) bob_public, bob_secret = server.auth_backend.known_identities[b'bob'] client = Client(server_id, user_id=b'bob', security_plugin=security_plugin, public_key=bob_public, secret_key=bob_secret, peer_public_key=server_public, loop=loop) client.connect(endpoint) assert server.socket.mechanism == zmq.CURVE assert client.socket.mechanism == zmq.CURVE server.register_rpc(name='string.upper')(str.upper) async with server, client: result = await client.string.upper('hello') assert result == 'HELLO' client.disconnect(endpoint) client.connect(endpoint) await asyncio.sleep(.01) result = await client.string.upper('hello2') assert result == 'HELLO2'
def create_certificates(key_dir, name, metadata=None): ''' Create zcert-esque public and private certificate files. Return the file paths to the public and secret certificate files. ''' public_key, secret_key = zmq.curve_keypair() base_filename = os.path.join(key_dir, name) secret_key_file = "{0}.key_secret".format(base_filename) public_key_file = "{0}.key".format(base_filename) now = datetime.datetime.now() _write_key_file(public_key_file, _cert_public_banner.format(now), public_key) _write_key_file(secret_key_file, _cert_secret_banner.format(now), public_key, secret_key=secret_key, metadata=metadata) return public_key_file, secret_key_file
def bind(self, sock, bind_fn=None): '''Extended zmq.Socket.bind() to include options in the address.''' if not self.domain: raise ValueError('Address domain must be set') sock.zap_domain = self.domain or '' if self.identity: sock.identity = self.identity elif not sock.identity: sock.identity = self.identity = bytes(uuid.uuid4()) sock.ipv6 = self.ipv6 or False if self.server == 'CURVE': if not self.secretkey: raise ValueError('CURVE server used without secretkey') sock.curve_server = True sock.curve_secretkey = self.secretkey elif self.server == 'PLAIN': sock.plain_server = True else: sock.curve_server = False sock.plain_server = False if self.serverkey: sock.curve_serverkey = self.serverkey if not (self.publickey and self.secretkey): self.publickey, self.secretkey = curve_keypair() sock.curve_secretkey = self.secretkey sock.curve_publickey = self.publickey elif self.username: sock.plain_username = self.username sock.plain_password = self.password or b'' try: (bind_fn or sock.bind)(self.base) self.base = sock.last_endpoint except ZMQError: message = 'Attempted to bind Volttron to already bound address {}, stopping' message = message.format(self.base) _log.error(message) print("\n" + message + "\n") sys.exit(1)