Ejemplo n.º 1
0
    def add_outbound_connection(self, uri):
        """Adds an outbound connection to the network.

        Args:
            uri (str): The zmq-style (e.g. tcp://hostname:port) uri
                to attempt to connect to.
        """
        LOGGER.debug("Adding connection to %s", uri)
        conn = OutboundConnection(
            connections=self._connections,
            endpoint=uri,
            dispatcher=self._dispatcher,
            zmq_identity=self._zmq_identity,
            secured=self._secured,
            server_public_key=self._server_public_key,
            server_private_key=self._server_private_key,
            future_callback_threadpool=self._future_callback_threadpool,
            heartbeat=True,
            connection_timeout=self._connection_timeout,
            metrics_registry=self._metrics_registry)

        self.outbound_connections[uri] = conn
        conn.start()

        self._add_connection(conn, uri)

        connect_message = ConnectionRequest(endpoint=self._public_endpoint)
        conn.send(validator_pb2.Message.NETWORK_CONNECT,
                  connect_message.SerializeToString(),
                  callback=partial(
                      self._connect_callback,
                      connection=conn,
                  ))

        return conn
def do_connect():
    connect_message = ConnectionRequest(endpoint="endpoint")
    roles = {"network": AuthorizationType.TRUST}
    network = MockNetwork(roles)
    handler = ConnectHandler(network)
    handler_status = handler.handle("connection_id",
                                    connect_message.SerializeToString())
    return handler_status
Ejemplo n.º 3
0
 def send_connect_request(self, connection_id):
     """
     Send ConnectionRequest to an inbound connection. This allows
     the validator to be authorized by the incoming connection.
     """
     connect_message = ConnectionRequest(endpoint=self._public_endpoint)
     self.send(validator_pb2.Message.NETWORK_CONNECT,
               connect_message.SerializeToString(),
               connection_id,
               callback=partial(self._inbound_connection_request_callback,
                                connection=connection_id))
Ejemplo n.º 4
0
 def test_connect_bad_endpoint(self):
     """
     Test the ConnectHandler correctly responds to a ConnectionRequest.
     """
     connect_message = ConnectionRequest(endpoint="tcp://0.0.0.0:8800")
     roles = {"network": AuthorizationType.TRUST}
     network = MockNetwork(roles)
     handler = ConnectHandler(network)
     handler_status = handler.handle("connection_id",
                                     connect_message.SerializeToString())
     self.assertEqual(handler_status.status, HandlerStatus.RETURN_AND_CLOSE)
     self.assertEqual(
         handler_status.message_type,
         validator_pb2.Message.AUTHORIZATION_CONNECTION_RESPONSE)
Ejemplo n.º 5
0
 def test_connect_bad_role_type(self):
     """
     Test the ConnectHandler closes the connection if the role has an
     unsupported role type.
     """
     connect_message = ConnectionRequest(endpoint="endpoint")
     roles = {"network": "other"}
     network = MockNetwork(roles)
     handler = ConnectHandler(network)
     handler_status = handler.handle("connection_id",
                                     connect_message.SerializeToString())
     self.assertEqual(handler_status.status, HandlerStatus.RETURN_AND_CLOSE)
     self.assertEqual(
         handler_status.message_type,
         validator_pb2.Message.AUTHORIZATION_CONNECTION_RESPONSE)
Ejemplo n.º 6
0
 def test_connect_not_allowing_incoming_connections(self):
     """
     Test the ConnectHandler closes a connection if we are not accepting
     incoming connections
     """
     connect_message = ConnectionRequest(endpoint="endpoint")
     roles = {"network": AuthorizationType.TRUST}
     network = MockNetwork(roles, allow_inbound=False)
     handler = ConnectHandler(network)
     handler_status = handler.handle("connection_id",
                                     connect_message.SerializeToString())
     self.assertEqual(handler_status.status, HandlerStatus.RETURN_AND_CLOSE)
     self.assertEqual(
         handler_status.message_type,
         validator_pb2.Message.AUTHORIZATION_CONNECTION_RESPONSE)
Ejemplo n.º 7
0
 def test_connect_wrong_previous_message(self):
     """
     Test the ConnectHandler closes a connection if any authorization
     message has been recieved before this connection request.
     """
     connect_message = ConnectionRequest(endpoint="endpoint")
     roles = {"network": AuthorizationType.TRUST}
     network = MockNetwork(roles,
                           connection_status={"connection_id": "other"})
     handler = ConnectHandler(network)
     handler_status = handler.handle("connection_id",
                                     connect_message.SerializeToString())
     self.assertEqual(handler_status.status, HandlerStatus.RETURN_AND_CLOSE)
     self.assertEqual(
         handler_status.message_type,
         validator_pb2.Message.AUTHORIZATION_CONNECTION_RESPONSE)
Ejemplo n.º 8
0
    def handle(self, connection_id, message_content):
        """
        A connection must use one of the supported authorization types
        to prove their identity. If a requester deviates
        from the procedure in any way, the requester will be rejected and the
        connection will be closed. The same is true if the requester sends
        multiple ConnectionRequests or multiple of any authorization-type
        message. The validator receiving a new connection will receive a
        ConnectionRequest. The validator will respond with a ConnectionResponse
        message. The ConnectionResponse message will contain a list of
        RoleEntry messages and an AuthorizationType. Role entries are
        the accepted type of connections that are supported on the endpoint
        that the ConnectionRequest was sent to. AuthorizationType describes the
        procedure required to gain access to that role. If the validator is not
        accepting connections or does not support the listed authorization
        type, return an ConnectionResponse.ERROR and close the connection.
        """
        message = ConnectionRequest()
        message.ParseFromString(message_content)
        LOGGER.debug("got connect message from %s. sending ack", connection_id)

        # Need to use join here to get the string "0.0.0.0". Otherwise,
        # bandit thinks we are binding to all interfaces and returns a
        # Medium security risk.
        interfaces = ["*", ".".join(["0", "0", "0", "0"])]
        interfaces += netifaces.interfaces()
        for interface in interfaces:
            if interface in message.endpoint:
                LOGGER.debug("Endpoint cannot include '%s': %s", interface,
                             message.endpoint)

                connection_response = ConnectionResponse(
                    status=ConnectionResponse.ERROR)
                return HandlerResult(HandlerStatus.RETURN_AND_CLOSE,
                                     message_out=connection_response,
                                     message_type=validator_pb2.Message.
                                     AUTHORIZATION_CONNECTION_RESPONSE)

        LOGGER.debug("Endpoint of connecting node is %s", message.endpoint)
        self._network.update_connection_endpoint(connection_id,
                                                 message.endpoint)

        # Get what AuthorizationType the network role requires
        roles = self._network.roles
        auth_type = roles.get("network")
        if auth_type == AuthorizationType.TRUST:
            role_type = ConnectionResponse.RoleEntry(
                role=RoleType.Value("NETWORK"),
                auth_type=ConnectionResponse.TRUST)
            connection_response = ConnectionResponse(roles=[role_type])
        elif auth_type == AuthorizationType.CHALLENGE:
            role_type = ConnectionResponse.RoleEntry(
                role=RoleType.Value("NETWORK"),
                auth_type=ConnectionResponse.CHALLENGE)
            connection_response = ConnectionResponse(roles=[role_type])
        else:
            LOGGER.warning(
                "Network role is set to an unsupported"
                "Authorization Type: %s", auth_type)
            connection_response = ConnectionResponse(
                status=ConnectionResponse.ERROR)
            return HandlerResult(HandlerStatus.RETURN_AND_CLOSE,
                                 message_out=connection_response,
                                 message_type=validator_pb2.Message.
                                 AUTHORIZATION_CONNECTION_RESPONSE)

        try:
            is_outbound_connection = self._network.is_outbound_connection(
                connection_id)
        except KeyError:
            # Connection has gone away, drop message
            return HandlerResult(HandlerStatus.DROP)

        if not is_outbound_connection:
            if self._network.allow_inbound_connection():
                LOGGER.debug("Allowing incoming connection: %s", connection_id)
                connection_response.status = connection_response.OK
            else:
                connection_response.status = connection_response.ERROR
                return HandlerResult(HandlerStatus.RETURN_AND_CLOSE,
                                     message_out=connection_response,
                                     message_type=validator_pb2.Message.
                                     AUTHORIZATION_CONNECTION_RESPONSE)

        if self._network.get_connection_status(connection_id) is not None:
            LOGGER.debug(
                "Connection has already sent ConnectionRequest:"
                " %s, Remove connection.", connection_id)
            connection_response.status = connection_response.ERROR
            return HandlerResult(HandlerStatus.RETURN_AND_CLOSE,
                                 message_out=connection_response,
                                 message_type=validator_pb2.Message.
                                 AUTHORIZATION_CONNECTION_RESPONSE)

        self._network.update_connection_status(
            connection_id, ConnectionStatus.CONNECTION_REQUEST)

        return HandlerResult(HandlerStatus.RETURN,
                             message_out=connection_response,
                             message_type=validator_pb2.Message.
                             AUTHORIZATION_CONNECTION_RESPONSE)