def handle(self, connection_id, message_content): # check to see if there is a public key public_key = self._network.connection_id_to_public_key(connection_id) if public_key is None: LOGGER.debug( "No public key found, %s is not permitted. " "Close connection.", connection_id) violation = AuthorizationViolation( violation=RoleType.Value("NETWORK")) self._gossip.unregister_peer(connection_id) return HandlerResult( HandlerStatus.RETURN_AND_CLOSE, message_out=violation, message_type=validator_pb2.Message.AUTHORIZATION_VIOLATION) # check public key against network/default role permitted = self._permission_verifier.check_network_role(public_key) if not permitted: LOGGER.debug("Public key not permitted, %s is not permitted", connection_id) self._gossip.unregister_peer(connection_id) violation = AuthorizationViolation( violation=RoleType.Value("NETWORK")) return HandlerResult( HandlerStatus.RETURN_AND_CLOSE, message_out=violation, message_type=validator_pb2.Message.AUTHORIZATION_VIOLATION) # if allowed pass message return HandlerResult(HandlerStatus.PASS)
def handle(self, connection_id, message_content): """ If the connection wants to take on a role that requires a challenge to be signed, it will request the challenge by sending an AuthorizationChallengeRequest to the validator it wishes to connect to. The validator will send back a random payload that must be signed. If the connection has not sent a ConnectionRequest or the connection has already recieved an AuthorizationChallengeResponse, an AuthorizationViolation will be returned and the connection will be closed. """ if self._network.get_connection_status(connection_id) != \ ConnectionStatus.CONNECTION_REQUEST: LOGGER.debug( "Connection's previous message was not a" " ConnectionRequest, 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) random_payload = os.urandom(PAYLOAD_LENGTH) self._challenge_payload_cache[connection_id] = random_payload auth_challenge_response = AuthorizationChallengeResponse( payload=random_payload) self._network.update_connection_status( connection_id, ConnectionStatus.AUTH_CHALLENGE_REQUEST) return HandlerResult(HandlerStatus.RETURN, message_out=auth_challenge_response, message_type=validator_pb2.Message. AUTHORIZATION_CHALLENGE_RESPONSE)
def handle(self, connection_id, message_content): message = GossipMessage() message.ParseFromString(message_content) if message.content_type == "BLOCK": public_key = \ self._network.connection_id_to_public_key(connection_id) block = Block() block.ParseFromString(message.content) header = BlockHeader() header.ParseFromString(block.header) if header.signer_public_key == public_key: permitted = \ self._permission_verifier.check_network_consensus_role( public_key) if not permitted: LOGGER.debug( "Public key is not permitted to publish block, " "remove connection: %s", connection_id) self._gossip.unregister_peer(connection_id) violation = AuthorizationViolation( violation=RoleType.Value("NETWORK")) return HandlerResult(HandlerStatus.RETURN_AND_CLOSE, message_out=violation, message_type=validator_pb2.Message. AUTHORIZATION_VIOLATION) # if allowed pass message return HandlerResult(HandlerStatus.PASS)
def _network_violation_result(): violation = AuthorizationViolation( violation=RoleType.Value("NETWORK")) return HandlerResult( HandlerStatus.RETURN_AND_CLOSE, message_out=violation, message_type=validator_pb2.Message.AUTHORIZATION_VIOLATION)
def handle(self, connection_id, message_content): request = PingRequest() request.ParseFromString(message_content) ack = PingResponse() if self._network.get_connection_status(connection_id) == \ ConnectionStatus.CONNECTED: if connection_id in self._last_message: del self._last_message[connection_id] return HandlerResult( HandlerStatus.RETURN, message_out=ack, message_type=validator_pb2.Message.PING_RESPONSE) if connection_id in self._last_message: ping_frequency = time.time() - self._last_message[connection_id] if ping_frequency < self._allowed_frequency: LOGGER.warning("Too many Pings (%s) in %s seconds before " "authorization is complete: %s", ping_frequency, self._allowed_frequency, connection_id) violation = AuthorizationViolation( violation=RoleType.Value("NETWORK")) return HandlerResult( HandlerStatus.RETURN_AND_CLOSE, message_out=violation, message_type=validator_pb2.Message.AUTHORIZATION_VIOLATION) self._last_message[connection_id] = time.time() return HandlerResult( HandlerStatus.RETURN, message_out=ack, message_type=validator_pb2.Message.PING_RESPONSE)
def handle(self, connection_id, message_content): request = PingRequest() request.ParseFromString(message_content) #LOGGER.debug("PingHandler PingRequest %s(%s)",connection_id[:8],self._network.connection_id_to_endpoint(connection_id)) ack = PingResponse() if self._network.get_connection_status( connection_id) == ConnectionStatus.CONNECTED: if connection_id in self._last_message: del self._last_message[connection_id] """ Here we can ask SYNC with this peer -in case we have no sync yet """ #LOGGER.debug("PingRequest from CONNECTED %s(%s)",connection_id[:8],self._network.connection_id_to_endpoint(connection_id)) return HandlerResult( HandlerStatus.RETURN, message_out=ack, message_type=validator_pb2.Message.PING_RESPONSE) if connection_id in self._last_message: if time.time( ) - self._last_message[connection_id] < self._allowed_frequency: LOGGER.debug( "Too many Pings in %s seconds before authorization is complete: %s", self._allowed_frequency, connection_id) violation = AuthorizationViolation( violation=RoleType.Value("NETWORK")) return HandlerResult( HandlerStatus.RETURN_AND_CLOSE, message_out=violation, message_type=validator_pb2.Message.AUTHORIZATION_VIOLATION) self._last_message[connection_id] = time.time() return HandlerResult(HandlerStatus.RETURN, message_out=ack, message_type=validator_pb2.Message.PING_RESPONSE)
def handle(self, connection_id, message_content): request = PingRequest() request.ParseFromString(message_content) ack = NetworkAcknowledgement() ack.status = ack.OK if self._network.get_connection_status(connection_id) == \ ConnectionStatus.CONNECTED: if connection_id in self._last_message: del self._last_message[connection_id] return HandlerResult( HandlerStatus.RETURN, message_out=ack, message_type=validator_pb2.Message.NETWORK_ACK) if connection_id in self._last_message: if time.time() - self._last_message[connection_id] < \ self._allowed_frequency: LOGGER.debug( "Too many Pings in %s seconds before" "authorization is complete: %s", self._allowed_frequency, connection_id) violation = AuthorizationViolation( violation=RoleType.Value("NETWORK")) return HandlerResult( HandlerStatus.RETURN_AND_CLOSE, message_out=violation, message_type=validator_pb2.Message.AUTHORIZATION_VIOLATION) self._last_message[connection_id] = time.time() return HandlerResult(HandlerStatus.RETURN, message_out=ack, message_type=validator_pb2.Message.NETWORK_ACK)
def handle(self, connection_id, message_content): """ The simplest authorization type will be Trust. If Trust authorization is enabled, the validator will trust the connection and approve any roles requested that are available on that endpoint. If the requester wishes to gain access to every role it has permission to access, it can request access to the role ALL, and the validator will respond with all available roles. If the permission verifier deems the connection to not have access to a role, the connection has not sent a ConnectionRequest or a the connection has already recieved a AuthorizationTrustResponse, an AuthorizatinViolation will be returned and the connection will be closed. """ if self._network.get_connection_status(connection_id) != \ ConnectionStatus.CONNECTION_REQUEST: LOGGER.debug( "Connection's previous message was not a" " ConnectionRequest, 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) request = AuthorizationTrustRequest() request.ParseFromString(message_content) # Check that the connection's public key is allowed by the network role roles = self._network.roles for role in request.roles: if role == RoleType.Value("NETWORK") or role == \ RoleType.Value("ALL"): permitted = False if "network" in roles: permitted = self._permission_verifier.check_network_role( request.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, request.public_key) if RoleType.Value("NETWORK") in request.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 can begin. self._gossip.connect_success(connection_id) auth_trust_response = AuthorizationTrustResponse( 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_trust_response, message_type=validator_pb2.Message.AUTHORIZATION_TRUST_RESPONSE)
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 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)