Allow bypassing unnecessary validation in C-S API

This commit is contained in:
Tulir Asokan 2023-02-12 14:51:56 +02:00
parent ab635c80a7
commit 9eb9372eb4
5 changed files with 31 additions and 31 deletions

View File

@ -64,7 +64,7 @@ class EventValidator:
event: The event to validate. event: The event to validate.
config: The homeserver's configuration. config: The homeserver's configuration.
""" """
self.validate_builder(event) self.validate_builder(event, config)
if event.format_version == EventFormatVersions.ROOM_V1_V2: if event.format_version == EventFormatVersions.ROOM_V1_V2:
EventID.from_string(event.event_id) EventID.from_string(event.event_id)
@ -95,6 +95,12 @@ class EventValidator:
# Note that only the client controlled portion of the event is # Note that only the client controlled portion of the event is
# checked, since we trust the portions of the event we created. # checked, since we trust the portions of the event we created.
validate_canonicaljson(event.content) validate_canonicaljson(event.content)
if not 0 < event.origin_server_ts < 2**53:
raise SynapseError(400, "Event timestamp is out of range")
# meow: allow specific users to send potentially dangerous events.
if event.sender in config.meow.validation_override:
return
if event.type == EventTypes.Aliases: if event.type == EventTypes.Aliases:
if "aliases" in event.content: if "aliases" in event.content:
@ -193,7 +199,9 @@ class EventValidator:
errcode=Codes.BAD_JSON, errcode=Codes.BAD_JSON,
) )
def validate_builder(self, event: Union[EventBase, EventBuilder]) -> None: def validate_builder(
self, event: Union[EventBase, EventBuilder], config: HomeServerConfig
) -> None:
"""Validates that the builder/event has roughly the right format. Only """Validates that the builder/event has roughly the right format. Only
checks values that we expect a proto event to have, rather than all the checks values that we expect a proto event to have, rather than all the
fields an event would have fields an event would have
@ -211,6 +219,10 @@ class EventValidator:
RoomID.from_string(event.room_id) RoomID.from_string(event.room_id)
UserID.from_string(event.sender) UserID.from_string(event.sender)
# meow: allow specific users to send so-called invalid events
if event.sender in config.meow.validation_override:
return
if event.type == EventTypes.Message: if event.type == EventTypes.Message:
strings = ["body", "msgtype"] strings = ["body", "msgtype"]

View File

@ -80,9 +80,11 @@ class DirectoryHandler:
) -> None: ) -> None:
# general association creation for both human users and app services # general association creation for both human users and app services
for wchar in string.whitespace: # meow: allow specific users to include anything in room aliases
if wchar in room_alias.localpart: if creator not in self.config.meow.validation_override:
raise SynapseError(400, "Invalid characters in room alias") for wchar in string.whitespace:
if wchar in room_alias.localpart:
raise SynapseError(400, "Invalid characters in room alias")
if ":" in room_alias.localpart: if ":" in room_alias.localpart:
raise SynapseError(400, "Invalid character in room alias localpart: ':'.") raise SynapseError(400, "Invalid character in room alias localpart: ':'.")
@ -127,7 +129,10 @@ class DirectoryHandler:
user_id = requester.user.to_string() user_id = requester.user.to_string()
room_alias_str = room_alias.to_string() room_alias_str = room_alias.to_string()
if len(room_alias_str) > MAX_ALIAS_LENGTH: if (
user_id not in self.hs.config.meow.validation_override
and len(room_alias_str) > MAX_ALIAS_LENGTH
):
raise SynapseError( raise SynapseError(
400, 400,
"Can't create aliases longer than %s characters" % MAX_ALIAS_LENGTH, "Can't create aliases longer than %s characters" % MAX_ALIAS_LENGTH,

View File

@ -1452,7 +1452,7 @@ class FederationHandler:
room_version_obj, event_dict room_version_obj, event_dict
) )
EventValidator().validate_builder(builder) EventValidator().validate_builder(builder, self.hs.config)
# Try several times, it could fail with PartialStateConflictError # Try several times, it could fail with PartialStateConflictError
# in send_membership_event, cf comment in except block. # in send_membership_event, cf comment in except block.
@ -1617,7 +1617,7 @@ class FederationHandler:
builder = self.event_builder_factory.for_room_version( builder = self.event_builder_factory.for_room_version(
room_version_obj, event_dict room_version_obj, event_dict
) )
EventValidator().validate_builder(builder) EventValidator().validate_builder(builder, self.hs.config)
( (
event, event,

View File

@ -669,7 +669,7 @@ class EventCreationHandler:
room_version_obj, event_dict room_version_obj, event_dict
) )
self.validator.validate_builder(builder) self.validator.validate_builder(builder, self.config)
if builder.type == EventTypes.Member: if builder.type == EventTypes.Member:
membership = builder.content.get("membership", None) membership = builder.content.get("membership", None)
@ -1339,6 +1339,8 @@ class EventCreationHandler:
Raises: Raises:
SynapseError if the event is invalid. SynapseError if the event is invalid.
""" """
if event.sender in self.config.meow.validation_override:
return
relation = relation_from_event(event) relation = relation_from_event(event)
if not relation: if not relation:
@ -1757,7 +1759,8 @@ class EventCreationHandler:
await self._maybe_kick_guest_users(event, context) await self._maybe_kick_guest_users(event, context)
if event.type == EventTypes.CanonicalAlias: validation_override = event.sender in self.config.meow.validation_override
if event.type == EventTypes.CanonicalAlias and not validation_override:
# Validate a newly added alias or newly added alt_aliases. # Validate a newly added alias or newly added alt_aliases.
original_alias = None original_alias = None
@ -2112,7 +2115,7 @@ class EventCreationHandler:
builder = self.event_builder_factory.for_room_version( builder = self.event_builder_factory.for_room_version(
original_event.room_version, third_party_result original_event.room_version, third_party_result
) )
self.validator.validate_builder(builder) self.validator.validate_builder(builder, self.config)
except SynapseError as e: except SynapseError as e:
raise Exception( raise Exception(
"Third party rules module created an invalid event: " + e.msg, "Third party rules module created an invalid event: " + e.msg,

View File

@ -754,26 +754,6 @@ class RoomMemberHandler(metaclass=abc.ABCMeta):
content.pop("displayname", None) content.pop("displayname", None)
content.pop("avatar_url", None) content.pop("avatar_url", None)
if len(content.get("displayname") or "") > MAX_DISPLAYNAME_LEN:
raise SynapseError(
400,
f"Displayname is too long (max {MAX_DISPLAYNAME_LEN})",
errcode=Codes.BAD_JSON,
)
if len(content.get("avatar_url") or "") > MAX_AVATAR_URL_LEN:
raise SynapseError(
400,
f"Avatar URL is too long (max {MAX_AVATAR_URL_LEN})",
errcode=Codes.BAD_JSON,
)
if "avatar_url" in content and content.get("avatar_url") is not None:
if not await self.profile_handler.check_avatar_size_and_mime_type(
content["avatar_url"],
):
raise SynapseError(403, "This avatar is not allowed", Codes.FORBIDDEN)
# The event content should *not* include the authorising user as # The event content should *not* include the authorising user as
# it won't be properly signed. Strip it out since it might come # it won't be properly signed. Strip it out since it might come
# back from a client updating a display name / avatar. # back from a client updating a display name / avatar.