Skip to content

Commit

Permalink
Server refuses connections on unknown namespaces (Fixes #822)
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelgrinberg committed Apr 29, 2022
1 parent c45cfcb commit 4471501
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 4 deletions.
12 changes: 10 additions & 2 deletions src/socketio/asyncio_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,15 @@ async def _send_packet(self, eio_sid, pkt):
async def _handle_connect(self, eio_sid, namespace, data):
"""Handle a client connection request."""
namespace = namespace or '/'
sid = self.manager.connect(eio_sid, namespace)
sid = None
if namespace in self.handlers or namespace in self.namespace_handlers:
sid = self.manager.connect(eio_sid, namespace)
if sid is None:
self._send_packet(eio_sid, self.packet_class(
packet.CONNECT_ERROR, data='Unable to connect',
namespace=namespace))
return

if self.always_connect:
await self._send_packet(eio_sid, self.packet_class(
packet.CONNECT, {'sid': sid}, namespace=namespace))
Expand Down Expand Up @@ -547,7 +555,7 @@ async def _trigger_event(self, event, namespace, *args):
return ret

# or else, forward the event to a namepsace handler if one exists
elif namespace in self.namespace_handlers:
elif namespace in self.namespace_handlers: # pragma: no branch
return await self.namespace_handlers[namespace].trigger_event(
event, *args)

Expand Down
6 changes: 4 additions & 2 deletions src/socketio/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,9 @@ def _send_packet(self, eio_sid, pkt):
def _handle_connect(self, eio_sid, namespace, data):
"""Handle a client connection request."""
namespace = namespace or '/'
sid = self.manager.connect(eio_sid, namespace)
sid = None
if namespace in self.handlers or namespace in self.namespace_handlers:
sid = self.manager.connect(eio_sid, namespace)
if sid is None:
self._send_packet(eio_sid, self.packet_class(
packet.CONNECT_ERROR, data='Unable to connect',
Expand Down Expand Up @@ -748,7 +750,7 @@ def _trigger_event(self, event, namespace, *args):
return self.handlers[namespace]['*'](event, *args)

# or else, forward the event to a namespace handler if one exists
elif namespace in self.namespace_handlers:
elif namespace in self.namespace_handlers: # pragma: no branch
return self.namespace_handlers[namespace].trigger_event(
event, *args)

Expand Down
14 changes: 14 additions & 0 deletions tests/asyncio/test_asyncio_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,13 @@ def test_handle_connect_async(self, eio):
_run(s._handle_eio_message('456', '0'))
assert s.manager.initialize.call_count == 1

def test_handle_connect_with_bad_namespace(self, eio):
eio.return_value.send = AsyncMock()
s = asyncio_server.AsyncServer()
_run(s._handle_eio_connect('123', 'environ'))
_run(s._handle_eio_message('123', '0'))
assert not s.manager.is_connected('1', '/')

def test_handle_connect_namespace(self, eio):
eio.return_value.send = AsyncMock()
s = asyncio_server.AsyncServer()
Expand Down Expand Up @@ -752,6 +759,7 @@ def test_handle_invalid_packet(self, eio):
def test_send_with_ack(self, eio):
eio.return_value.send = AsyncMock()
s = asyncio_server.AsyncServer()
s.handlers['/'] = {}
_run(s._handle_eio_connect('123', 'environ'))
_run(s._handle_eio_message('123', '0'))
cb = mock.MagicMock()
Expand All @@ -765,6 +773,7 @@ def test_send_with_ack(self, eio):
def test_send_with_ack_namespace(self, eio):
eio.return_value.send = AsyncMock()
s = asyncio_server.AsyncServer()
s.handlers['/foo'] = {}
_run(s._handle_eio_connect('123', 'environ'))
_run(s._handle_eio_message('123', '0/foo,'))
cb = mock.MagicMock()
Expand All @@ -791,6 +800,8 @@ async def fake_save_session(eio_sid, session):

eio.return_value.send = AsyncMock()
s = asyncio_server.AsyncServer()
s.handlers['/'] = {}
s.handlers['/ns'] = {}
s.eio.get_session = fake_get_session
s.eio.save_session = fake_save_session

Expand Down Expand Up @@ -822,6 +833,7 @@ def test_disconnect(self, eio):
eio.return_value.send = AsyncMock()
eio.return_value.disconnect = AsyncMock()
s = asyncio_server.AsyncServer()
s.handlers['/'] = {}
_run(s._handle_eio_connect('123', 'environ'))
_run(s._handle_eio_message('123', '0'))
_run(s.disconnect('1'))
Expand All @@ -832,6 +844,7 @@ def test_disconnect_ignore_queue(self, eio):
eio.return_value.send = AsyncMock()
eio.return_value.disconnect = AsyncMock()
s = asyncio_server.AsyncServer()
s.handlers['/'] = {}
_run(s._handle_eio_connect('123', 'environ'))
_run(s._handle_eio_message('123', '0'))
_run(s.disconnect('1', ignore_queue=True))
Expand All @@ -842,6 +855,7 @@ def test_disconnect_namespace(self, eio):
eio.return_value.send = AsyncMock()
eio.return_value.disconnect = AsyncMock()
s = asyncio_server.AsyncServer()
s.handlers['/foo'] = {}
_run(s._handle_eio_connect('123', 'environ'))
_run(s._handle_eio_message('123', '0/foo,'))
_run(s.disconnect('1', namespace='/foo'))
Expand Down
14 changes: 14 additions & 0 deletions tests/common/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,12 @@ def test_handle_connect_with_auth_none(self, eio):
s._handle_eio_connect('456', 'environ')
assert s.manager.initialize.call_count == 1

def test_handle_connect_with_bad_namespace(self, eio):
s = server.Server()
s._handle_eio_connect('123', 'environ')
s._handle_eio_message('123', '0')
assert not s.manager.is_connected('1', '/')

def test_handle_connect_namespace(self, eio):
s = server.Server()
handler = mock.MagicMock()
Expand Down Expand Up @@ -663,6 +669,7 @@ def test_handle_invalid_packet(self, eio):

def test_send_with_ack(self, eio):
s = server.Server()
s.handlers['/'] = {}
s._handle_eio_connect('123', 'environ')
s._handle_eio_message('123', '0')
cb = mock.MagicMock()
Expand All @@ -675,6 +682,7 @@ def test_send_with_ack(self, eio):

def test_send_with_ack_namespace(self, eio):
s = server.Server()
s.handlers['/foo'] = {}
s._handle_eio_connect('123', 'environ')
s._handle_eio_message('123', '0/foo,')
cb = mock.MagicMock()
Expand All @@ -696,6 +704,8 @@ def fake_save_session(eio_sid, session):
fake_session = session

s = server.Server()
s.handlers['/'] = {}
s.handlers['/ns'] = {}
s.eio.get_session = fake_get_session
s.eio.save_session = fake_save_session
s._handle_eio_connect('123', 'environ')
Expand All @@ -721,20 +731,23 @@ def fake_save_session(eio_sid, session):

def test_disconnect(self, eio):
s = server.Server()
s.handlers['/'] = {}
s._handle_eio_connect('123', 'environ')
s._handle_eio_message('123', '0')
s.disconnect('1')
s.eio.send.assert_any_call('123', '1')

def test_disconnect_ignore_queue(self, eio):
s = server.Server()
s.handlers['/'] = {}
s._handle_eio_connect('123', 'environ')
s._handle_eio_message('123', '0')
s.disconnect('1', ignore_queue=True)
s.eio.send.assert_any_call('123', '1')

def test_disconnect_namespace(self, eio):
s = server.Server()
s.handlers['/foo'] = {}
s._handle_eio_connect('123', 'environ')
s._handle_eio_message('123', '0/foo,')
s.disconnect('1', namespace='/foo')
Expand Down Expand Up @@ -813,6 +826,7 @@ def is_asyncio_based(self):

def test_get_environ(self, eio):
s = server.Server()
s.handlers['/'] = {}
s._handle_eio_connect('123', 'environ')
s._handle_eio_message('123', '0')
sid = s.manager.sid_from_eio_sid('123', '/')
Expand Down

0 comments on commit 4471501

Please sign in to comment.