Skip to content

Commit

Permalink
Initial stab at documenting soft fail (#1641)
Browse files Browse the repository at this point in the history
  • Loading branch information
erikjohnston authored Oct 26, 2018
1 parent f288fac commit 4271391
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 0 deletions.
5 changes: 5 additions & 0 deletions scripts/css/nature.css
Original file line number Diff line number Diff line change
Expand Up @@ -285,3 +285,8 @@ div.admonition-rationale {
border: 1px solid #ccc;
}

div.admonition-example {
background-color: #eef;
border: 1px solid #ccc;
}

117 changes: 117 additions & 0 deletions specification/server_server_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,123 @@ transaction request to be responded to with an error response.
result in the user being considered joined.


Soft failure
++++++++++++

.. admonition:: Rationale

It is important that we prevent users from evading bans (or other power
restrictions) by creating events which reference old parts of the DAG. For
example, a banned user could continue to send messages to a room by having
their server send events which reference the event before they were banned.
Note that such events are entirely valid, and we cannot simply reject them, as
it is impossible to distinguish such an event from a legitimate one which has
been delayed. We must therefore accept such events and let them participate in
state resolution and the federation protocol as normal. However, servers may
choose not to send such events on to their clients, so that end users won't
actually see the events.

When this happens it is often fairly obvious to servers, as they can see that
the new event doesn't actually pass auth based on the "current state" (i.e.
the resolved state across all forward extremities). While the event is
technically valid, the server can choose to not notify clients about the new
event.

This discourages servers from sending events that evade bans etc. in this way,
as end users won't actually see the events.


When the homeserver receives a new event over federation it should also check
whether the event passes auth checks based on the current state of the room (as
well as based on the state at the event). If the event does not pass the auth
checks based on the *current state* of the room (but does pass the auth checks
based on the state at that event) it should be "soft failed".

When an event is "soft failed" it should not be relayed to the client nor be
referenced by new events created by the homeserver (i.e. they should not be
added to the server's list of forward extremities of the room). Soft failed
events are otherwise handled as usual.


.. NOTE::

Soft failed events participate in state resolution as normal if further events
are received which reference it. It is the job of the state resolution
algorithm to ensure that malicious events cannot be injected into the room
state via this mechanism.


.. NOTE::

Because soft failed state events participate in state resolution as normal, it
is possible for such events to appear in the current state of the room. In
that case the client should be told about the soft failed event in the usual
way (e.g. by sending it down in the ``state`` section of a sync response).


.. NOTE::

A soft failed event should be returned in response to federation requests
where appropriate (e.g. in ``/event/<event_id>``). Note that soft failed
events are returned in ``/backfill`` and ``/get_missing_events`` responses
only if the requests include events referencing the soft failed events.


.. admonition:: Example

As an example consider the event graph::

A
/
B

where ``B`` is a ban of a user ``X``. If the user ``X`` tries to set the topic
by sending an event ``C`` while evading the ban::

A
/ \
B C

servers that receive ``C`` after ``B`` should soft fail event ``C``, and so
will neither relay ``C`` to its clients nor send any events referencing ``C``.

If later another server sends an event ``D`` that references both ``B`` and
``C`` (this can happen if it received ``C`` before ``B``)::

A
/ \
B C
\ /
D

then servers will handle ``D`` as normal. ``D`` is sent to the servers'
clients (assuming ``D`` passes auth checks). The state at ``D`` may resolve to
a state that includes ``C``, in which case clients should also to be told that
the state has changed to include ``C``. (*Note*: This depends on the exact
state resolution algorithm used. In the original version of the algorithm
``C`` would be in the resolved state, whereas in latter versions the algorithm
tries to prioritise the ban over the topic change.)

Note that this is essentially equivalent to the situation where one server
doesn't receive ``C`` at all, and so asks another server for the state of the
``C`` branch.

Let's go back to the graph before ``D`` was sent::

A
/ \
B C

If all the servers in the room saw ``B`` before ``C`` and so soft fail ``C``,
then any new event ``D'`` will not reference ``C``::

A
/ \
B C
|
D


Retrieving event authorization information
++++++++++++++++++++++++++++++++++++++++++

Expand Down

0 comments on commit 4271391

Please sign in to comment.