Allow bypassing unnecessary validation in C-S API

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

View File

@ -43,7 +43,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)
@ -74,6 +74,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:
@ -165,7 +171,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
@ -183,6 +191,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

@ -71,9 +71,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: ':'.")
@ -118,7 +120,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

@ -1397,7 +1397,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.
@ -1556,7 +1556,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, context = await self.event_creation_handler.create_new_client_event( event, context = await self.event_creation_handler.create_new_client_event(
builder=builder builder=builder
) )

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)
@ -1292,6 +1292,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:
@ -1701,7 +1703,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
@ -2092,7 +2095,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

@ -707,26 +707,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.