summary refs log tree commit diff
path: root/synapse/handlers
diff options
context:
space:
mode:
authorDavid Teller <d.o.teller+github@gmail.com>2022-05-11 10:32:27 +0200
committerDavid Teller <d.o.teller+github@gmail.com>2022-05-11 10:32:30 +0200
commitae66c672fe8b5fbfe497888d03b2cbd68381de76 (patch)
tree4c837eb8b98c8b6bd1a0fa910100df30dea7161f /synapse/handlers
parentFix `/messages` throwing a 500 when querying for non-existent room (#12683) (diff)
downloadsynapse-ts/spam-errors.tar.xz
Uniformize spam-checker API: github/ts/spam-errors ts/spam-errors
- Some callbacks should return `True` to allow, `False` to deny, while others should return `True` to deny and `False` to allow. With this PR, all callbacks return `ALLOW` to allow or a `Codes` (typically `Codes.FORBIDDEN`) to deny.
- Similarly, some methods returned `True` to allow, `False` to deny, while others returned `True` to deny and `False` to allow. They now all return `ALLOW` to allow or a `Codes` to deny.
- Spam-checker implementations may now return an explicit code, e.g. to differentiate between "User account has been suspended" (which is in practice required by law in some countries, including UK) and "This message looks like spam".
Diffstat (limited to '')
-rw-r--r--synapse/handlers/directory.py17
-rw-r--r--synapse/handlers/federation.py10
-rw-r--r--synapse/handlers/message.py11
-rw-r--r--synapse/handlers/room.py6
-rw-r--r--synapse/handlers/room_member.py35
-rw-r--r--synapse/handlers/user_directory.py3
6 files changed, 51 insertions, 31 deletions
diff --git a/synapse/handlers/directory.py b/synapse/handlers/directory.py

index 33d827a45b..fbbb667cd4 100644 --- a/synapse/handlers/directory.py +++ b/synapse/handlers/directory.py
@@ -16,6 +16,7 @@ import logging import string from typing import TYPE_CHECKING, Iterable, List, Optional +import synapse from synapse.api.constants import MAX_ALIAS_LENGTH, EventTypes from synapse.api.errors import ( AuthError, @@ -137,10 +138,13 @@ class DirectoryHandler: 403, "You must be in the room to create an alias for it" ) - if not await self.spam_checker.user_may_create_room_alias( + spam_check = await self.spam_checker.user_may_create_room_alias( user_id, room_alias - ): - raise AuthError(403, "This user is not permitted to create this alias") + ) + if spam_check is not synapse.spam_checker_api.ALLOW: + raise AuthError( + 403, "This alias creation request has been rejected", spam_check + ) if not self.config.roomdirectory.is_alias_creation_allowed( user_id, room_id, room_alias_str @@ -426,9 +430,12 @@ class DirectoryHandler: """ user_id = requester.user.to_string() - if not await self.spam_checker.user_may_publish_room(user_id, room_id): + spam_check = await self.spam_checker.user_may_publish_room(user_id, room_id) + if spam_check is not synapse.spam_checker_api.ALLOW: raise AuthError( - 403, "This user is not permitted to publish rooms to the room list" + 403, + "This request to publish a room to the room list has been rejected", + spam_check, ) if requester.is_guest: diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py
index be5099b507..aa3be099a5 100644 --- a/synapse/handlers/federation.py +++ b/synapse/handlers/federation.py
@@ -27,6 +27,7 @@ from signedjson.key import decode_verify_key_bytes from signedjson.sign import verify_signed_json from unpaddedbase64 import decode_base64 +import synapse from synapse import event_auth from synapse.api.constants import EventContentFields, EventTypes, Membership from synapse.api.errors import ( @@ -799,11 +800,14 @@ class FederationHandler: if self.hs.config.server.block_non_admin_invites: raise SynapseError(403, "This server does not accept room invites") - if not await self.spam_checker.user_may_invite( + spam_check = await self.spam_checker.user_may_invite( event.sender, event.state_key, event.room_id - ): + ) + if spam_check is not synapse.spam_checker_api.ALLOW: raise SynapseError( - 403, "This user is not permitted to send invites to this server/user" + 403, + "This user is not permitted to send invites to this server/user", + spam_check, ) membership = event.content.get("membership") diff --git a/synapse/handlers/message.py b/synapse/handlers/message.py
index e47799e7f9..9f51212e4e 100644 --- a/synapse/handlers/message.py +++ b/synapse/handlers/message.py
@@ -23,6 +23,7 @@ from canonicaljson import encode_canonical_json from twisted.internet.interfaces import IDelayedCall +import synapse from synapse import event_auth from synapse.api.constants import ( EventContentFields, @@ -881,11 +882,11 @@ class EventCreationHandler: event.sender, ) - spam_error = await self.spam_checker.check_event_for_spam(event) - if spam_error: - if not isinstance(spam_error, str): - spam_error = "Spam is not permitted here" - raise SynapseError(403, spam_error, Codes.FORBIDDEN) + spam_check = await self.spam_checker.check_event_for_spam(event) + if spam_check is not synapse.spam_checker_api.ALLOW: + raise SynapseError( + 403, "This message had been rejected as probable spam", spam_check + ) ev = await self.handle_new_client_event( requester=requester, diff --git a/synapse/handlers/room.py b/synapse/handlers/room.py
index 604eb6ec15..53a2a5df46 100644 --- a/synapse/handlers/room.py +++ b/synapse/handlers/room.py
@@ -33,6 +33,7 @@ from typing import ( import attr from typing_extensions import TypedDict +import synapse from synapse.api.constants import ( EventContentFields, EventTypes, @@ -407,9 +408,10 @@ class RoomCreationHandler: """ user_id = requester.user.to_string() - if not await self.spam_checker.user_may_create_room(user_id): + spam_check = await self.spam_checker.user_may_create_room(user_id) + if spam_check is not synapse.spam_checker_api.ALLOW: raise SynapseError( - 403, "You are not permitted to create rooms", Codes.FORBIDDEN + 403, "This room creation request has been rejected", spam_check ) creation_content: JsonDict = { diff --git a/synapse/handlers/room_member.py b/synapse/handlers/room_member.py
index 802e57c4d0..d3ef6a05ca 100644 --- a/synapse/handlers/room_member.py +++ b/synapse/handlers/room_member.py
@@ -18,6 +18,7 @@ import random from http import HTTPStatus from typing import TYPE_CHECKING, Iterable, List, Optional, Set, Tuple +import synapse from synapse import types from synapse.api.constants import ( AccountDataTypes, @@ -679,8 +680,6 @@ class RoomMemberHandler(metaclass=abc.ABCMeta): if target_id == self._server_notices_mxid: raise SynapseError(HTTPStatus.FORBIDDEN, "Cannot invite this user") - block_invite = False - if ( self._server_notices_mxid is not None and requester.user.to_string() == self._server_notices_mxid @@ -697,16 +696,18 @@ class RoomMemberHandler(metaclass=abc.ABCMeta): "Blocking invite: user is not admin and non-admin " "invites disabled" ) - block_invite = True + raise SynapseError(403, "Invites have been disabled on this server") - if not await self.spam_checker.user_may_invite( + spam_check = await self.spam_checker.user_may_invite( requester.user.to_string(), target_id, room_id - ): + ) + if spam_check is not synapse.spam_checker_api.ALLOW: logger.info("Blocking invite due to spam checker") - block_invite = True - - if block_invite: - raise SynapseError(403, "Invites have been disabled on this server") + raise SynapseError( + 403, + "This invite has been rejected as probable spam", + spam_check, + ) # An empty prev_events list is allowed as long as the auth_event_ids are present if prev_event_ids is not None: @@ -814,11 +815,14 @@ class RoomMemberHandler(metaclass=abc.ABCMeta): # We assume that if the spam checker allowed the user to create # a room then they're allowed to join it. and not new_room - and not await self.spam_checker.user_may_join_room( + ): + spam_check = await self.spam_checker.user_may_join_room( target.to_string(), room_id, is_invited=inviter is not None ) - ): - raise SynapseError(403, "Not allowed to join this room") + if spam_check is not synapse.spam_checker_api.ALLOW: + raise SynapseError( + 403, "This request to join room has been rejected", spam_check + ) # Check if a remote join should be performed. remote_join, remote_room_hosts = await self._should_perform_remote_join( @@ -1372,13 +1376,14 @@ class RoomMemberHandler(metaclass=abc.ABCMeta): ) else: # Check if the spamchecker(s) allow this invite to go through. - if not await self.spam_checker.user_may_send_3pid_invite( + spam_check = await self.spam_checker.user_may_send_3pid_invite( inviter_userid=requester.user.to_string(), medium=medium, address=address, room_id=room_id, - ): - raise SynapseError(403, "Cannot send threepid invite") + ) + if spam_check is not synapse.spam_checker_api.ALLOW: + raise SynapseError(403, "Cannot send threepid invite", spam_check) stream_id = await self._make_and_store_3pid_invite( requester, diff --git a/synapse/handlers/user_directory.py b/synapse/handlers/user_directory.py
index 74f7fdfe6c..b7ece32958 100644 --- a/synapse/handlers/user_directory.py +++ b/synapse/handlers/user_directory.py
@@ -100,7 +100,8 @@ class UserDirectoryHandler(StateDeltasHandler): # Remove any spammy users from the results. non_spammy_users = [] for user in results["results"]: - if not await self.spam_checker.check_username_for_spam(user): + spam_check = await self.spam_checker.check_username_for_spam(user) + if spam_check is synapse.spam_checker_api.ALLOW: non_spammy_users.append(user) results["results"] = non_spammy_users