This was missed in the initial fix in 9a50c244 ("validate event type and
membership for create_join and create_invite"), but significantly less
impactful than the original vulnerability because it only affects
invite/join events that are able to pass auth/signature checks with our
server's signature. You could use this to forge invite events from a
local user, but not much else.
This fixes a vulnerability where an attacker with a a malicious remote
server and a user on the local server can trick the local server into
signing arbitrary events. The attacker issue a remote leave as the local
user to a room on the malicious server. Without any validation of the
make_leave response, the local server would sign the attacker-controlled
event and pass it back to the malicious server with send_leave.
The join endpoints is also fixed in this commit, but is less useful for
exploitation because the local server replaces the "content" field
returned by the remote server. Remote invites are unaffected because we
already check that the event returned from /invite has the same event ID
as the event passed to it.
Both of these endpoints sign the received event so without the
validation a malicious server can use these endpoints to trick our
server into signing effectively arbitrary forged events from local
users.
Rebased from a continuwuity patch by nex. The create_join changes were
not present in the continuwuity version because these checks were
already present there.
Co-authored-by: Olivia Lee <olivia@computer.surgery>
<https://github.com/ruma/ruma/pull/2050>
We could just set None now, but the ruma changelog states that
> Servers are encouraged to keep sending it for compatibility with
> clients that required it.
The only change to the internal interface for this one is removing the
current_third_party_invite argument from state_res::auth_check. Ruma now
fetches the event using the fetch_state closure. This is convenient for
us, because we previously didn't bother to implement it.
The significant change is 26edd40a704040e7104161da81c9bae91b7ddcaa,
which removes the global compat feature, so that each compat feature
must now be enabled individually. We're using the slightly later
1387667d because it has a bugfix that ruma needs to compile.
There are a few ruma compat features that were not previously part of
the global compat feature:
- compat-arbitrary-length-ids
- compat-upload-signature
- compat-encrypted-stickers
I have not enabled these here, to avoid a behavior change.
Previously we were mashing everything together as RoomAccountDataEvent,
even the global events. This technically worked, because of the hidden
custom fields on the ruma event types, but it's confusing and easy to
mess up. Separate methods with appropriate types are preferable.
Previously, read receipts would only be forwarded via federation
incidentally when some PDU was later sent to the destination server.
Trigger a send without any event to collect EDUs and get read receipts
out directly.
Previously we required every alias in a canonical alias event sent by a
client to be valid, and would only validate local aliases. This
prevented clients from adding/removing canonical aliases if there were
existing remote or invalid aliases.
Previously, we would only attempt to validate the aliases in the event
content if we were able to parse the event, and would silently allow it
otherwise.
The previous logic would increment the backoff counter both when a
request actually fails and when we do not make a request because the
server was already in backoff. This lead to a positive feedback loop
where every request made while a server is in backoff increases the
backoff delay, making it impossible to recover from backoff unless the
entire backoff delay elapses with zero requests.
Failing to reset the backoff state resulted in a monotonically
increasing backoff delay. If a remote server was temporarily
unavailable, we would have a persistently increased rate of key query
failures until the backoff state was reset by a server restart. If
enough key queries were attempted while the remote was unavailable, it
can accumulate an arbitrarily long backoff delay and effectively block
all future key queries to this server.
This is pure code-motion, with no behavior changes. The new structure
will make it easier to fix the backoff behavior, and makes the code
somewhat less of a nightmare to follow.
This became a problem because #foundation-office:matrix.org has a
malformed create event with its `predecessor` set to a string instead of
a map.
The solution to this is, unfortunately, to do more shotgun parsing to
extract only the desired fields rather than trying to parse the entire
content every time. To prevent this kind of problem from happening
again, `RoomCreateEventContent` must only be used for creating new PDUs,
existing PDUs must be shotgun-parsed.
If all join requests to resident servers fail or if the joining server
is the only resident server (i.e. the room is local-only), we would
previously send a 500 error, even if the more correct response would be
M_UNAUTHORIZED (e.g. if the user tries to join an invite-only room).
To fix this, we now return the error generated by attempting the join
locally, which correctly informs the client about why their request
failed.
Fixes a set of bugs introduced by 00b77144c1,
where we replaced explicit `RoomVersionId` matches with `version < V11`
comparisons. The `Ord` impl on `RoomVersionId` does not work like that,
and is in fact a lexicographic string comparison[1]. The most visible
effect of these bugs is that incoming redaction events would sometimes
be ignored.
Instead of reverting to the explicit matches, which were quite verbose,
I implemented a `RoomVersion` struct that has flags for each property
that we care about. This is similar to the approach used by ruma[2] and
synapse[3].
[1]: 7cfa3be0c6/crates/ruma-common/src/identifiers/room_version_id.rs (L136)
[2]: 7cfa3be0c6/crates/ruma-state-res/src/room_version.rs
[3]: c856ae4724/synapse/api/room_versions.py
For HTTP/1 requests, an inbound Request's URI contains only the path and
query parameters, since there's no way to synthesize the authority part.
This is exactly what we need for the X-Matrix "uri" field.
HTTP/2 requests however can contain the :authority pseudo-header, which
is used to populate the Request's URI. Using a URL that includes an
authority breaks the signature check.
Largely inspired by conduit MR !631
(https://gitlab.com/famedly/conduit/-/merge_requests/631).
Co-authored-by: strawberry <strawberry@puppygock.gay>
The previous code used `server_name` as a fallback but in reality there
is no real relationship between `server_name` and the location clients
are supposed to make requests to.
Additionally, the `insecure` option is gone, because we now allow users
to control the entire URL, so they're free to choose the scheme.