Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

PoC for filtering spammy events #2456

Merged
merged 1 commit into from
Sep 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions synapse/events/spamcheck.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
# Copyright 2017 New Vector Ltd.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


def check_event_for_spam(event):
"""Checks if a given event is considered "spammy" by this server.

If the server considers an event spammy, then it will be rejected if
sent by a local user. If it is sent by a user on another server, then
users

Args:
event (synapse.events.EventBase): the event to be checked

Returns:
bool: True if the event is spammy.
"""
if not hasattr(event, "content") or "body" not in event.content:
return False

# for example:
#
# if "the third flower is green" in event.content["body"]:
# return True

return False
40 changes: 24 additions & 16 deletions synapse/federation/federation_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,15 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


from twisted.internet import defer

from synapse.events.utils import prune_event

from synapse.crypto.event_signing import check_event_content_hash
import logging

from synapse.api.errors import SynapseError

from synapse.crypto.event_signing import check_event_content_hash
from synapse.events import spamcheck
from synapse.events.utils import prune_event
from synapse.util import unwrapFirstError
from synapse.util.logcontext import preserve_fn, preserve_context_over_deferred

import logging

from synapse.util.logcontext import preserve_context_over_deferred, preserve_fn
from twisted.internet import defer

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -117,12 +111,18 @@ def _check_sigs_and_hash(self, pdu):
return self._check_sigs_and_hashes([pdu])[0]

def _check_sigs_and_hashes(self, pdus):
"""Throws a SynapseError if a PDU does not have the correct
signatures.
"""Checks that each of the received events is correctly signed by the
sending server.

Args:
pdus (list[FrozenEvent]): the events to be checked

Returns:
FrozenEvent: Either the given event or it redacted if it failed the
content hash check.
list[Deferred]: for each input event, a deferred which:
* returns the original event if the checks pass
* returns a redacted version of the event (if the signature
matched but the hash did not)
* throws a SynapseError if the signature check failed.
"""

redacted_pdus = [
Expand All @@ -142,6 +142,14 @@ def callback(_, pdu, redacted):
pdu.event_id, pdu.get_pdu_json()
)
return redacted

if spamcheck.check_event_for_spam(pdu):
logger.warn(
"Event contains spam, redacting %s: %s",
pdu.event_id, pdu.get_pdu_json()
)
return redacted

return pdu

def errback(failure, pdu):
Expand Down
8 changes: 7 additions & 1 deletion synapse/handlers/message.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from synapse.events import spamcheck
from twisted.internet import defer

from synapse.api.constants import EventTypes, Membership
Expand Down Expand Up @@ -321,6 +321,12 @@ def create_and_send_nonmember_event(
token_id=requester.access_token_id,
txn_id=txn_id
)

if spamcheck.check_event_for_spam(event):
raise SynapseError(
403, "Spam is not permitted here", Codes.FORBIDDEN
)

yield self.send_nonmember_event(
requester,
event,
Expand Down