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

Commit

Permalink
Merge branch 'shhs' of ssh://github.com/matrix-org/synapse into shhs
Browse files Browse the repository at this point in the history
  • Loading branch information
hawkowl committed Jul 26, 2019
2 parents b50d8a9 + 4a5fb54 commit 8d9a56e
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 65 deletions.
46 changes: 0 additions & 46 deletions .circleci/config.yml

This file was deleted.

28 changes: 27 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
Synapse 1.2.1 (2019-07-26)
==========================

Security update
---------------

This release includes *four* security fixes:

- Prevent an attack where a federated server could send redactions for arbitrary events in v1 and v2 rooms. ([\#5767](https://github.com/matrix-org/synapse/issues/5767))
- Prevent a denial-of-service attack where cycles of redaction events would make Synapse spin infinitely. Thanks to `@lrizika:matrix.org` for identifying and responsibly disclosing this issue. ([0f2ecb961](https://github.com/matrix-org/synapse/commit/0f2ecb961))
- Prevent an attack where users could be joined or parted from public rooms without their consent. Thanks to @Dylanger for identifying and responsibly disclosing this issue. ([\#5744](https://github.com/matrix-org/synapse/issues/5744))
- Fix a vulnerability where a federated server could spoof read-receipts from
users on other servers. Thanks to @Dylanger for identifying this issue too. ([\#5743](https://github.com/matrix-org/synapse/issues/5743))

Additionally, the following fix was in Synapse **1.2.0**, but was not correctly
identified during the original release:

- It was possible for a room moderator to send a redaction for an `m.room.create` event, which would downgrade the room to version 1. Thanks to `/dev/ponies` for identifying and responsibly disclosing this issue! ([\#5701](https://github.com/matrix-org/synapse/issues/5701))

Synapse 1.2.0 (2019-07-25)
==========================

Expand All @@ -16,6 +35,14 @@ Bugfixes
Synapse 1.2.0rc1 (2019-07-22)
=============================

Security fixes
--------------

This update included a security fix which was initially incorrectly flagged as
a regular bug fix.

- It was possible for a room moderator to send a redaction for an `m.room.create` event, which would downgrade the room to version 1. Thanks to `/dev/ponies` for identifying and responsibly disclosing this issue! ([\#5701](https://github.com/matrix-org/synapse/issues/5701))

Features
--------

Expand All @@ -41,7 +68,6 @@ Bugfixes
- Fix bug in #5626 that prevented the original_event field from actually having the contents of the original event in a call to `/relations`. ([\#5654](https://github.com/matrix-org/synapse/issues/5654))
- Fix 3PID bind requests being sent to identity servers as `application/x-form-www-urlencoded` data, which is deprecated. ([\#5658](https://github.com/matrix-org/synapse/issues/5658))
- Fix some problems with authenticating redactions in recent room versions. ([\#5699](https://github.com/matrix-org/synapse/issues/5699), [\#5700](https://github.com/matrix-org/synapse/issues/5700), [\#5707](https://github.com/matrix-org/synapse/issues/5707))
- Ignore redactions of m.room.create events. ([\#5701](https://github.com/matrix-org/synapse/issues/5701))


Updates to the Docker image
Expand Down
6 changes: 6 additions & 0 deletions debian/changelog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
matrix-synapse-py3 (1.2.1) stable; urgency=medium

* New synapse release 1.2.1.

-- Synapse Packaging team <packages@matrix.org> Fri, 26 Jul 2019 11:32:47 +0100

matrix-synapse-py3 (1.2.0) stable; urgency=medium

[ Amber Brown ]
Expand Down
2 changes: 1 addition & 1 deletion synapse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,4 @@
except ImportError:
pass

__version__ = "1.2.0"
__version__ = "1.2.1"
4 changes: 2 additions & 2 deletions synapse/federation/federation_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,7 @@ def on_make_join_request(self, origin, room_id, user_id, supported_versions):
logger.warn("Room version %s not in %s", room_version, supported_versions)
raise IncompatibleRoomVersionError(room_version=room_version)

pdu = yield self.handler.on_make_join_request(room_id, user_id)
pdu = yield self.handler.on_make_join_request(origin, room_id, user_id)
time_now = self._clock.time_msec()
defer.returnValue(
{"event": pdu.get_pdu_json(time_now), "room_version": room_version}
Expand Down Expand Up @@ -423,7 +423,7 @@ def on_send_join_request(self, origin, content, room_id):
def on_make_leave_request(self, origin, room_id, user_id):
origin_host, _ = parse_server_name(origin)
yield self.check_server_matches_acl(origin_host, room_id)
pdu = yield self.handler.on_make_leave_request(room_id, user_id)
pdu = yield self.handler.on_make_leave_request(origin, room_id, user_id)

room_version = yield self.store.get_room_version(room_id)

Expand Down
37 changes: 35 additions & 2 deletions synapse/handlers/federation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1204,11 +1204,28 @@ def _handle_queued_pdus(self, room_queue):

@defer.inlineCallbacks
@log_function
def on_make_join_request(self, room_id, user_id):
def on_make_join_request(self, origin, room_id, user_id):
""" We've received a /make_join/ request, so we create a partial
join event for the room and return that. We do *not* persist or
process it until the other server has signed it and sent it back.
Args:
origin (str): The (verified) server name of the requesting server.
room_id (str): Room to create join event in
user_id (str): The user to create the join for
Returns:
Deferred[FrozenEvent]
"""

if get_domain_from_id(user_id) != origin:
logger.info(
"Got /make_join request for user %r from different origin %s, ignoring",
user_id,
origin,
)
raise SynapseError(403, "User not from origin", Codes.FORBIDDEN)

event_content = {"membership": Membership.JOIN}

room_version = yield self.store.get_room_version(room_id)
Expand Down Expand Up @@ -1411,11 +1428,27 @@ def _make_and_verify_event(

@defer.inlineCallbacks
@log_function
def on_make_leave_request(self, room_id, user_id):
def on_make_leave_request(self, origin, room_id, user_id):
""" We've received a /make_leave/ request, so we create a partial
leave event for the room and return that. We do *not* persist or
process it until the other server has signed it and sent it back.
Args:
origin (str): The (verified) server name of the requesting server.
room_id (str): Room to create leave event in
user_id (str): The user to create the leave for
Returns:
Deferred[FrozenEvent]
"""
if get_domain_from_id(user_id) != origin:
logger.info(
"Got /make_leave request for user %r from different origin %s, ignoring",
user_id,
origin,
)
raise SynapseError(403, "User not from origin", Codes.FORBIDDEN)

room_version = yield self.store.get_room_version(room_id)
builder = self.event_builder_factory.new(
room_version,
Expand Down
35 changes: 22 additions & 13 deletions synapse/handlers/receipts.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from twisted.internet import defer

from synapse.handlers._base import BaseHandler
from synapse.types import ReadReceipt
from synapse.types import ReadReceipt, get_domain_from_id

logger = logging.getLogger(__name__)

Expand All @@ -40,18 +40,27 @@ def __init__(self, hs):
def _received_remote_receipt(self, origin, content):
"""Called when we receive an EDU of type m.receipt from a remote HS.
"""
receipts = [
ReadReceipt(
room_id=room_id,
receipt_type=receipt_type,
user_id=user_id,
event_ids=user_values["event_ids"],
data=user_values.get("data", {}),
)
for room_id, room_values in content.items()
for receipt_type, users in room_values.items()
for user_id, user_values in users.items()
]
receipts = []
for room_id, room_values in content.items():
for receipt_type, users in room_values.items():
for user_id, user_values in users.items():
if get_domain_from_id(user_id) != origin:
logger.info(
"Received receipt for user %r from server %s, ignoring",
user_id,
origin,
)
continue

receipts.append(
ReadReceipt(
room_id=room_id,
receipt_type=receipt_type,
user_id=user_id,
event_ids=user_values["event_ids"],
data=user_values.get("data", {}),
)
)

yield self._handle_new_receipts(receipts)

Expand Down
31 changes: 31 additions & 0 deletions synapse/storage/events_worker.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,14 @@ def get_events_as_list(
)
continue

if original_event.room_id != entry.event.room_id:
logger.info(
"Withholding redaction %s of event %s from a different room",
event_id,
redacted_event_id,
)
continue

if entry.event.internal_metadata.need_to_check_redaction():
original_domain = get_domain_from_id(original_event.sender)
redaction_domain = get_domain_from_id(entry.event.sender)
Expand Down Expand Up @@ -629,16 +637,32 @@ def _maybe_redact_event_row(self, original_ev, redactions):
# we choose to ignore redactions of m.room.create events.
return None

if original_ev.type == "m.room.redaction":
# ... and redaction events
return None

redaction_map = yield self._get_events_from_cache_or_db(redactions)

for redaction_id in redactions:
redaction_entry = redaction_map.get(redaction_id)
if not redaction_entry:
# we don't have the redaction event, or the redaction event was not
# authorized.
logger.debug(
"%s was redacted by %s but redaction not found/authed",
original_ev.event_id,
redaction_id,
)
continue

redaction_event = redaction_entry.event
if redaction_event.room_id != original_ev.room_id:
logger.debug(
"%s was redacted by %s but redaction was in a different room!",
original_ev.event_id,
redaction_id,
)
continue

# Starting in room version v3, some redactions need to be
# rechecked if we didn't have the redacted event at the
Expand All @@ -650,8 +674,15 @@ def _maybe_redact_event_row(self, original_ev, redactions):
redaction_event.internal_metadata.recheck_redaction = False
else:
# Senders don't match, so the event isn't actually redacted
logger.debug(
"%s was redacted by %s but the senders don't match",
original_ev.event_id,
redaction_id,
)
continue

logger.debug("Redacting %s due to %s", original_ev.event_id, redaction_id)

# we found a good redaction event. Redact!
redacted_event = prune_event(original_ev)
redacted_event.unsigned["redacted_by"] = redaction_id
Expand Down

0 comments on commit 8d9a56e

Please sign in to comment.