Commit 35664759 authored by Julien Muchembled's avatar Julien Muchembled

master: fix crashes in identification due to buggy nodes

- check address conflicts
- on invalid values, reject peer instead of dying
parent 54e819ff
...@@ -18,7 +18,7 @@ from neo.lib import logging ...@@ -18,7 +18,7 @@ from neo.lib import logging
from neo.lib.exception import StoppedOperation from neo.lib.exception import StoppedOperation
from neo.lib.handler import EventHandler from neo.lib.handler import EventHandler
from neo.lib.protocol import (uuid_str, NodeTypes, NodeStates, Packets, from neo.lib.protocol import (uuid_str, NodeTypes, NodeStates, Packets,
BrokenNodeDisallowedError, BrokenNodeDisallowedError, ProtocolError,
) )
class MasterHandler(EventHandler): class MasterHandler(EventHandler):
...@@ -33,12 +33,11 @@ class MasterHandler(EventHandler): ...@@ -33,12 +33,11 @@ class MasterHandler(EventHandler):
app = self.app app = self.app
node = app.nm.getByUUID(uuid) node = app.nm.getByUUID(uuid)
if node: if node:
assert node_type is not NodeTypes.MASTER or node.getAddress() in ( if node_type is NodeTypes.MASTER and not (
address, None), (node, address) None != address == node.getAddress()):
raise ProtocolError
if node.isBroken(): if node.isBroken():
raise BrokenNodeDisallowedError raise BrokenNodeDisallowedError
else:
node = app.nm.getByAddress(address)
peer_uuid = self._setupNode(conn, node_type, uuid, address, node) peer_uuid = self._setupNode(conn, node_type, uuid, address, node)
if app.primary: if app.primary:
primary_address = app.server primary_address = app.server
......
...@@ -126,8 +126,8 @@ class ServerElectionHandler(BaseElectionHandler, MasterHandler): ...@@ -126,8 +126,8 @@ class ServerElectionHandler(BaseElectionHandler, MasterHandler):
logging.info('reject a connection from a non-master') logging.info('reject a connection from a non-master')
raise NotReadyError raise NotReadyError
if node is None: if node is None is app.nm.getByAddress(address):
node = app.nm.createMaster(address=address) app.nm.createMaster(address=address)
self.elect(conn, address) self.elect(conn, address)
return uuid return uuid
......
...@@ -30,18 +30,32 @@ class IdentificationHandler(MasterHandler): ...@@ -30,18 +30,32 @@ class IdentificationHandler(MasterHandler):
def _setupNode(self, conn, node_type, uuid, address, node): def _setupNode(self, conn, node_type, uuid, address, node):
app = self.app app = self.app
if node: by_addr = address and app.nm.getByAddress(address)
if node.isRunning(): while 1:
if uuid > 0: if by_addr:
# cloned/evil/buggy node connecting to us if not by_addr.isConnected():
raise ProtocolError('already connected') if node is by_addr:
break
if not node or uuid < 0:
# In case of address conflict for a peer with temporary
# ids, we'll generate a new id.
node = by_addr
break
elif node:
if node.isConnected():
if uuid < 0:
# The peer wants a temporary id that's already assigned. # The peer wants a temporary id that's already assigned.
# Let's give it another one. # Let's give it another one.
node = uuid = None node = uuid = None
break
else: else:
assert not node.isConnected()
node.setAddress(address) node.setAddress(address)
node.setRunning() break
# Id conflict for a storage node.
else:
break
# cloned/evil/buggy node connecting to us
raise ProtocolError('already connected')
state = NodeStates.RUNNING state = NodeStates.RUNNING
if node_type == NodeTypes.CLIENT: if node_type == NodeTypes.CLIENT:
...@@ -68,13 +82,14 @@ class IdentificationHandler(MasterHandler): ...@@ -68,13 +82,14 @@ class IdentificationHandler(MasterHandler):
handler = app.administration_handler handler = app.administration_handler
human_readable_node_type = 'n admin ' human_readable_node_type = 'n admin '
else: else:
raise NotImplementedError(node_type) raise ProtocolError
uuid = app.getNewUUID(uuid, address, node_type) uuid = app.getNewUUID(uuid, address, node_type)
logging.info('Accept a' + human_readable_node_type + uuid_str(uuid)) logging.info('Accept a' + human_readable_node_type + uuid_str(uuid))
if node is None: if node is None:
node = app.nm.createFromNodeType(node_type, node = app.nm.createFromNodeType(node_type,
uuid=uuid, address=address) uuid=uuid, address=address)
else:
node.setUUID(uuid) node.setUUID(uuid)
node.setState(state) node.setState(state)
node.setConnection(conn) node.setConnection(conn)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment