Exemple #1
0
    def test_authorization_challenge_submit_bad_last_message(self):
        """
        Test the AuthorizationChallengeSubmitHandler returns an
        AuthorizationViolation and closes the connection if the last message
        was not AuthorizaitonChallengeRequest.
        """
        context = create_context('secp256k1')
        private_key = context.new_random_private_key()
        crypto_factory = CryptoFactory(context)
        signer = crypto_factory.new_signer(private_key)

        payload = os.urandom(10)

        signature = signer.sign(payload)

        auth_challenge_submit = AuthorizationChallengeSubmit(
            public_key=signer.get_public_key().as_hex(),
            signature=signature,
            roles=[RoleType.Value("NETWORK")])

        roles = {"network": AuthorizationType.TRUST}

        network = MockNetwork(roles,
                              connection_status={"connection_id": "other"})
        permission_verifer = MockPermissionVerifier()
        gossip = MockGossip()
        handler = AuthorizationChallengeSubmitHandler(
            network, permission_verifer, gossip, {"connection_id": payload})
        handler_status = handler.handle(
            "connection_id", auth_challenge_submit.SerializeToString())
        self.assertEqual(handler_status.status, HandlerStatus.RETURN_AND_CLOSE)
        self.assertEqual(handler_status.message_type,
                         validator_pb2.Message.AUTHORIZATION_VIOLATION)
Exemple #2
0
    def test_authorization_challenge_submit(self):
        """
        Test the AuthorizationChallengeSubmitHandler returns an
        AuthorizationViolation and closes the connection if the permission
        verifier does not permit the public_key.
        """
        private_key = signing.generate_privkey()
        public_key = signing.generate_pubkey(private_key)
        payload = os.urandom(10)

        signature = signing.sign(payload, private_key)

        auth_challenge_submit = AuthorizationChallengeSubmit(
            public_key=public_key,
            payload=payload,
            signature=signature,
            roles=[RoleType.Value("NETWORK")])

        roles = {"network": AuthorizationType.TRUST}

        network = MockNetwork(roles,
                              connection_status={
                                  "connection_id":
                                  ConnectionStatus.AUTH_CHALLENGE_REQUEST
                              })
        permission_verifer = MockPermissionVerifier(allow=False)
        gossip = MockGossip()
        handler = AuthorizationChallengeSubmitHandler(network,
                                                      permission_verifer,
                                                      gossip)
        handler_status = handler.handle(
            "connection_id", auth_challenge_submit.SerializeToString())
        self.assertEqual(handler_status.status, HandlerStatus.RETURN_AND_CLOSE)
        self.assertEqual(handler_status.message_type,
                         validator_pb2.Message.AUTHORIZATION_VIOLATION)
    def _inbound_challenge_authorization_callback(self,
                                                  request,
                                                  result,
                                                  connection=None):
        if result.message_type != \
                validator_pb2.Message.AUTHORIZATION_CHALLENGE_RESPONSE:
            LOGGER.debug("Unable to complete Challenge Authorization.")
            return

        auth_challenge_response = AuthorizationChallengeResponse()
        auth_challenge_response.ParseFromString(result.content)
        payload = auth_challenge_response.payload
        signature = signing.sign(payload, self._priv_key)

        auth_challenge_submit = AuthorizationChallengeSubmit(
            public_key=self._public_key,
            payload=payload,
            signature=signature,
            roles=[RoleType.Value("NETWORK")])

        self.send(validator_pb2.Message.AUTHORIZATION_CHALLENGE_SUBMIT,
                  auth_challenge_submit.SerializeToString(), connection)
Exemple #4
0
    def test_authorization_challenge_submit(self):
        """
        Test the AuthorizationChallengeSubmitHandler returns an
        AuthorizationChallengeResult.
        """
        context = create_context('secp256k1')
        private_key = context.new_random_private_key()
        crypto_factory = CryptoFactory(context)
        signer = crypto_factory.new_signer(private_key)

        payload = os.urandom(10)

        signature = signer.sign(payload)

        auth_challenge_submit = AuthorizationChallengeSubmit(
            public_key=signer.get_public_key().as_hex(),
            signature=signature,
            roles=[RoleType.Value("NETWORK")])

        roles = {"network": AuthorizationType.TRUST}

        network = MockNetwork(roles,
                              connection_status={
                                  "connection_id":
                                  ConnectionStatus.AUTH_CHALLENGE_REQUEST
                              })
        permission_verifer = MockPermissionVerifier()
        gossip = MockGossip()
        handler = AuthorizationChallengeSubmitHandler(network,
                                                      permission_verifer,
                                                      gossip)
        handler_status = handler.handle(
            "connection_id", auth_challenge_submit.SerializeToString())
        self.assertEqual(handler_status.status, HandlerStatus.RETURN)
        self.assertEqual(handler_status.message_type,
                         validator_pb2.Message.AUTHORIZATION_CHALLENGE_RESULT)
Exemple #5
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)
Exemple #6
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)