From b2cea1f4663cc6bf4d4501b63eb10a9813e1d0b0 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 19 Sep 2017 13:22:53 +0100 Subject: [PATCH 1/3] Add a config option to block all room invites - allows sysadmins the ability to lock down their servers so that people can't send their users room invites. --- synapse/api/auth.py | 8 ++++++++ synapse/config/server.py | 10 ++++++++++ synapse/handlers/federation.py | 3 +++ synapse/handlers/room_member.py | 20 ++++++++++++++++++++ 4 files changed, 41 insertions(+) diff --git a/synapse/api/auth.py b/synapse/api/auth.py index e3da45b41669..72858cca1f9f 100644 --- a/synapse/api/auth.py +++ b/synapse/api/auth.py @@ -519,6 +519,14 @@ def get_appservice_by_req(self, request): ) def is_server_admin(self, user): + """ Check if the given user is a local server admin. + + Args: + user (str): mxid of user to check + + Returns: + bool: True if the user is an admin + """ return self.store.is_server_admin(user) @defer.inlineCallbacks diff --git a/synapse/config/server.py b/synapse/config/server.py index 89d61a0503bc..c9a1715f1ff3 100644 --- a/synapse/config/server.py +++ b/synapse/config/server.py @@ -43,6 +43,12 @@ def read_config(self, config): self.filter_timeline_limit = config.get("filter_timeline_limit", -1) + # Whether we should block invites sent to users on this server + # (other than those sent by local server admins) + self.block_non_admin_invites = config.get( + "block_non_admin_invites", False, + ) + if self.public_baseurl is not None: if self.public_baseurl[-1] != '/': self.public_baseurl += '/' @@ -194,6 +200,10 @@ def default_config(self, server_name, **kwargs): # and sync operations. The default value is -1, means no upper limit. # filter_timeline_limit: 5000 + # Whether room invites to users on this server should be blocked + # (except those sent by local server admins). The default is False. + # block_non_admin_invites: True + # List of ports that Synapse should listen on, their purpose and their # configuration. listeners: diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py index 2637f41dcde2..18f87cad677a 100644 --- a/synapse/handlers/federation.py +++ b/synapse/handlers/federation.py @@ -1074,6 +1074,9 @@ def on_invite_request(self, origin, pdu): if is_blocked: raise SynapseError(403, "This room has been blocked on this server") + if self.hs.config.block_non_admin_invites: + raise SynapseError(403, "This server does not accept room invites") + membership = event.content.get("membership") if event.type != EventTypes.Member or membership != Membership.INVITE: raise SynapseError(400, "The event was not an m.room.member invite event") diff --git a/synapse/handlers/room_member.py b/synapse/handlers/room_member.py index b3f979b246bf..644e76d950a7 100644 --- a/synapse/handlers/room_member.py +++ b/synapse/handlers/room_member.py @@ -191,6 +191,8 @@ def _update_membership( if action in ["kick", "unban"]: effective_membership_state = "leave" + # if this is a join with a 3pid signature, we may need to turn a 3pid + # invite into a normal invite before we can handle the join. if third_party_signed is not None: replication = self.hs.get_replication_layer() yield replication.exchange_third_party_invite( @@ -208,6 +210,15 @@ def _update_membership( if is_blocked: raise SynapseError(403, "This room has been blocked on this server") + if (effective_membership_state == "invite" and + self.hs.config.block_non_admin_invites): + is_requester_admin = \ + yield self.auth.is_server_admin(requester.user) + if not is_requester_admin: + raise SynapseError( + 403, "Invites have been disabled on this server", + ) + latest_event_ids = yield self.store.get_latest_event_ids_in_room(room_id) current_state_ids = yield self.state_handler.get_current_state_ids( room_id, latest_event_ids=latest_event_ids, @@ -471,6 +482,15 @@ def do_3pid_invite( requester, txn_id ): + if self.hs.config.block_non_admin_invites: + is_requester_admin = \ + yield self.auth.is_server_admin(requester.user) + if not is_requester_admin: + raise SynapseError( + 403, "Invites have been disabled on this server", + Codes.FORBIDDEN, + ) + invitee = yield self._lookup_3pid( id_server, medium, address ) From 60661ab1fdcc1432c4ea54bdf7c75fd904c756f5 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 19 Sep 2017 14:11:20 +0100 Subject: [PATCH 2/3] Fix up the tests --- tests/utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/utils.py b/tests/utils.py index 4f7e32b3ab37..3c81a3e16dba 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -56,6 +56,7 @@ def setup_test_homeserver(name="test", datastore=None, config=None, **kargs): config.worker_replication_url = "" config.worker_app = None config.email_enable_notifs = False + config.block_non_admin_invites = False config.use_frozen_dicts = True config.database_config = {"name": "sqlite3"} From aad78bcbb97da0c647991ac32bae73f0fb40c007 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 19 Sep 2017 14:12:37 +0100 Subject: [PATCH 3/3] unbackslashify --- synapse/handlers/room_member.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/synapse/handlers/room_member.py b/synapse/handlers/room_member.py index 644e76d950a7..9a498c2d3ef2 100644 --- a/synapse/handlers/room_member.py +++ b/synapse/handlers/room_member.py @@ -212,8 +212,9 @@ def _update_membership( if (effective_membership_state == "invite" and self.hs.config.block_non_admin_invites): - is_requester_admin = \ - yield self.auth.is_server_admin(requester.user) + is_requester_admin = yield self.auth.is_server_admin( + requester.user, + ) if not is_requester_admin: raise SynapseError( 403, "Invites have been disabled on this server", @@ -483,8 +484,9 @@ def do_3pid_invite( txn_id ): if self.hs.config.block_non_admin_invites: - is_requester_admin = \ - yield self.auth.is_server_admin(requester.user) + is_requester_admin = yield self.auth.is_server_admin( + requester.user, + ) if not is_requester_admin: raise SynapseError( 403, "Invites have been disabled on this server",