Example #1
0
    def handle(self, connection_id, message_content):
        """
        When the validator receives an AuthorizationChallengeSubmit message, it
        will verify the public key against the signature. If the public key is
        verified, the requested roles will be checked against the stored roles
        to see if the public key is included in the policy. If the node’s
        response is accepted, the node’s public key will be stored and the
        requester may start sending messages for the approved roles.

        If the requester wanted a role that is either not available on the
        endpoint, the requester does not have access to one of the roles
        requested, or the previous message was not an
        AuthorizationChallengeRequest, the challenge will be rejected and the
        connection will be closed.
        """
        if self._network.get_connection_status(connection_id) != \
                ConnectionStatus.AUTH_CHALLENGE_REQUEST:
            LOGGER.debug(
                "Connection's previous message was not a"
                " AuthorizationChallengeRequest, Remove connection to"
                "%s", connection_id)
            return AuthorizationChallengeSubmitHandler \
                ._network_violation_result()

        auth_challenge_submit = AuthorizationChallengeSubmit()
        auth_challenge_submit.ParseFromString(message_content)

        try:
            payload = self._challenge_payload_cache[connection_id]
        except KeyError:
            LOGGER.debug(
                "Connection's challenge payload expired before a"
                "response was received. %s", connection_id)
            return AuthorizationChallengeSubmitHandler \
                ._network_violation_result()

        context = create_context('secp256k1')
        try:
            public_key = Secp256k1PublicKey.from_hex(
                auth_challenge_submit.public_key)
        except ParseError:
            LOGGER.warning(
                'Authorization Challenge Request cannot be '
                'verified. Invalid public key %s',
                auth_challenge_submit.public_key)
            return AuthorizationChallengeSubmitHandler \
                ._network_violation_result()

        if not context.verify(auth_challenge_submit.signature, payload,
                              public_key):
            LOGGER.warning(
                "Signature was not able to be verifed. Remove "
                "connection to %s", connection_id)
            return AuthorizationChallengeSubmitHandler \
                ._network_violation_result()

        roles = self._network.roles
        for role in auth_challenge_submit.roles:
            if role == RoleType.Value("NETWORK") or role == \
                    RoleType.Value("ALL"):
                permitted = False
                if "network" in roles:
                    permitted = self._permission_verifier.check_network_role(
                        auth_challenge_submit.public_key)
                if not permitted:
                    return AuthorizationChallengeSubmitHandler \
                            ._network_violation_result()

        self._network.update_connection_public_key(
            connection_id, auth_challenge_submit.public_key)

        if RoleType.Value("NETWORK") in auth_challenge_submit.roles:
            # Need to send ConnectionRequest to authorize ourself with the
            # connection if they initialized the connection
            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:
                self._network.send_connect_request(connection_id)
            else:
                # If this is an outbound connection, authorization is complete
                # for both connections and peering/topology build out can
                # begin.
                self._gossip.connect_success(connection_id)

        auth_challenge_result = AuthorizationChallengeResult(
            roles=[RoleType.Value("NETWORK")])

        LOGGER.debug("Connection: %s is approved", connection_id)
        self._network.update_connection_status(connection_id,
                                               ConnectionStatus.CONNECTED)
        return HandlerResult(
            HandlerStatus.RETURN,
            message_out=auth_challenge_result,
            message_type=validator_pb2.Message.AUTHORIZATION_CHALLENGE_RESULT)
Example #2
0
    def handle(self, connection_id, message_content):
        """
        When the validator receives an AuthorizationChallengeSubmit message, it
        will verify the public key against the signature. If the public key is
        verified, the requested roles will be checked against the stored roles
        to see if the public key is included in the policy. If the node’s
        response is accepted, the node’s public key will be stored and the
        requester may start sending messages for the approved roles.

        If the requester wanted a role that is either not available on the
        endpoint, the requester does not have access to one of the roles
        requested, or the previous message was not an
        AuthorizationChallengeRequest, the challenge will be rejected and the
        connection will be closed.
        """
        if self._network.get_connection_status(connection_id) != \
                ConnectionStatus.AUTH_CHALLENGE_REQUEST:
            LOGGER.debug(
                "Connection's previous message was not a"
                " AuthorizationChallengeRequest, Remove connection to"
                "%s", connection_id)
            violation = AuthorizationViolation(
                violation=RoleType.Value("NETWORK"))
            return HandlerResult(
                HandlerStatus.RETURN_AND_CLOSE,
                message_out=violation,
                message_type=validator_pb2.Message.AUTHORIZATION_VIOLATION)

        auth_challenge_submit = AuthorizationChallengeSubmit()
        auth_challenge_submit.ParseFromString(message_content)

        if not signing.verify(auth_challenge_submit.payload,
                              auth_challenge_submit.signature,
                              auth_challenge_submit.public_key):
            LOGGER.warning(
                "Signature was not able to be verifed. Remove "
                "connection to %s", connection_id)
            violation = AuthorizationViolation(
                violation=RoleType.Value("NETWORK"))
            return HandlerResult(
                HandlerStatus.RETURN_AND_CLOSE,
                message_out=violation,
                message_type=validator_pb2.Message.AUTHORIZATION_VIOLATION)

        roles = self._network.roles
        for role in auth_challenge_submit.roles:
            if role == RoleType.Value("NETWORK") or role == \
                    RoleType.Value("ALL"):
                permitted = False
                if "network" in roles:
                    permitted = self._permission_verifier.check_network_role(
                        auth_challenge_submit.public_key)
                if not permitted:
                    violation = AuthorizationViolation(
                        violation=RoleType.Value("NETWORK"))
                    return HandlerResult(HandlerStatus.RETURN_AND_CLOSE,
                                         message_out=violation,
                                         message_type=validator_pb2.Message.
                                         AUTHORIZATION_VIOLATION)
        self._network.update_connection_public_key(
            connection_id, auth_challenge_submit.public_key)

        if RoleType.Value("NETWORK") in auth_challenge_submit.roles:
            # Need to send ConnectionRequest to authorize ourself with the
            # connection if they initialized the connection
            if not self._network.is_outbound_connection(connection_id):
                self._network.send_connect_request(connection_id)
            else:
                # If this is an outbound connection, authorization is complete
                # for both connections and peering/topology build out can
                # begin.
                self._gossip.connect_success(connection_id)

        auth_challenge_result = AuthorizationChallengeResult(
            roles=[RoleType.Value("NETWORK")])

        LOGGER.debug("Connection: %s is approved", connection_id)
        self._network.update_connection_status(connection_id,
                                               ConnectionStatus.CONNECTED)
        return HandlerResult(
            HandlerStatus.RETURN,
            message_out=auth_challenge_result,
            message_type=validator_pb2.Message.AUTHORIZATION_CHALLENGE_RESULT)