Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document the event auth rules #1027

Merged
merged 7 commits into from
Oct 20, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 0 additions & 90 deletions drafts/erikj_federation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,96 +3,6 @@ Federation
.. sectnum::
.. contents:: Table of Contents

Authorization
-------------

When receiving new events from remote servers, or creating new events, a server
must know whether that event is allowed by the authorization rules. These rules
depend solely on the state at that event. The types of state events that affect
authorization are:

- ``m.room.create``
- ``m.room.member``
- ``m.room.join_rules``
- ``m.room.power_levels``

Servers should not create new events that reference unauthorized events.
However, any event that does reference an unauthorized event is not itself
automatically considered unauthorized.

Unauthorized events that appear in the event graph do *not* have any effect on
the state of the graph.

.. Note:: This is in contrast to redacted events which can still affect the
state of the graph. For example, a redacted *"join"* event will still
result in the user being considered joined.


Rules
~~~~~

The following are the rules to determine if an event is authorized (this does
include validation).

**TODO**: What signatures do we expect?

1. If type is ``m.room.create`` allow if and only if it has no prev events.
#. If type is ``m.room.member``:

a. If ``membership`` is ``join``:

i. If the previous event is an ``m.room.create``, the depth is 1 and
the ``state_key`` is the creator, then allow.
#. If the ``state_key`` does not match ``sender`` key, reject.
#. If the current state has ``membership`` set to ``join``.
#. If the ``sender`` is in the ``m.room.may_join`` list. [Not currently
implemented]
#. If the ``join_rules`` is:

- ``public``: allow.
- ``invite``: allow if the current state has ``membership`` set to
``invite``
- ``knock``: **TODO**.
- ``private``: Reject.

#. Reject

#. If ``membership`` is ``invite`` then allow if ``sender`` is in room,
otherwise reject.
#. If ``membership`` is ``leave``:

i. If ``sender`` matches ``state_key`` allow.
#. If ``sender``'s power level is greater than the the ``kick_level``
given in the current ``m.room.power_levels`` state (defaults to 50),
and the ``state_key``'s power level is less than or equal to the
``sender``'s power level, then allow.
#. Reject.

#. If ``membership`` is ``ban``:

i. **TODO**.

#. Reject.

#. Reject the event if the event type's required power level is less that the
``sender``'s power level.
#. If the ``sender`` is not in the room, reject.
#. If the type is ``m.room.power_levels``:

a. **TODO**.

#. Allow.


Definitions
~~~~~~~~~~~

Required Power Level
A given event type has an associated *required power level*. This is given
by the current ``m.room.power_levels`` event, it is either listed explicitly
in the ``events`` section or given by either ``state_default`` or
``events_default`` depending on if the event type is a state event or not.


Auth events
~~~~~~~~~~~
Expand Down
170 changes: 160 additions & 10 deletions specification/server_server_api.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.. Copyright 2016 OpenMarket Ltd
.. Copyright 2017 New Vector Ltd
..
.. Licensed under the Apache License, Version 2.0 (the "License");
.. you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -442,24 +443,173 @@ keys exist to support this:
``state_key`` String Combined with the ``pdu_type`` this
identifies the which part of the room
state is updated
``required_power_level`` Integer The required power level needed to
replace this update.
``prev_state_id`` String The PDU id of the update this replaces.
``prev_state_origin`` String The homeserver of the update this
replaces.
``user_id`` String The user updating the state.
======================== ============ =========================================

.. code:: json
Authorization of PDUs
~~~~~~~~~~~~~~~~~~~~~

{...,
"is_state":true,
"state_key":TODO-doc
"required_power_level":TODO-doc
"prev_state_id":TODO-doc
"prev_state_origin":TODO-doc
}
Whenever a server receives an event from a remote server, the receiving server
must check that the event is allowed by the authorization rules. These rules
depend on the state of the room at that event.

Definitions
+++++++++++

Required Power Level
A given event type has an associated *required power level*. This is given by
the current ``m.room.power_levels`` event. The event type is either listed
explicitly in the ``events`` section or given by either ``state_default`` or
``events_default`` depending on if the event is a state event or not.

Invite Level, Kick Level, Ban Level, Redact Level
The levels given by the ``invite``, ``kick``, ``ban``, and ``redact``
properties in the current ``m.room.power_levels`` state. Each defaults to 50
if unspecified.

Target User
For an ``m.room.member`` state event, the user given by the ``state_key`` of
the event.



Rules
+++++

The rules governing whether an event is authorized depend solely on the
state of the room at the point in the room graph at which the new event is to
be inserted. The types of state events that affect authorization are:

- ``m.room.create``
- ``m.room.member``
- ``m.room.join_rules``
- ``m.room.power_levels``

Servers should not create new events that reference unauthorized events.
However, any event that does reference an unauthorized event is not itself
automatically considered unauthorized.

Unauthorized events that appear in the event graph do *not* have any effect on
the state of the room.

.. Note:: This is in contrast to redacted events which can still affect the
state of the room. For example, a redacted ``join`` event will still
result in the user being considered joined.

1. If type is ``m.room.create``, allow if and only if has depth 0 and it has no
previous events - *i.e.* it is the first event in the room.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's an assertion for that room_id domain matches sender domain

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah. I think there's a whole class of checks like this and the signatures which I want to keep separately from the auth rules, because they don't really play a part in state resolution. The line's a bit fuzzy, but I want to punt this one and the signatures to a separate section and a separate PR.


#. If type is ``m.room.member``:

a. If ``membership`` is ``join``:

i. If the previous event in the room graph is an ``m.room.create``, the
depth is 1 and the ``state_key`` is the creator, allow.

#. If the ``sender`` does not match ``state_key``, reject.

#. If the user's current membership state is ``invite`` or ``join``,
allow.

#. If the ``join_rule`` is ``public``, allow.

#. Otherwise, reject.

#. If ``membership`` is ``invite``:

i. If the ``sender``'s current membership state is not ``joined``, reject.

#. If *target user*'s current membership state is ``join`` or ``ban``,
reject.

#. If the ``sender``'s power level is greater than or equal to the *invite
level*, allow.

#. Otherwise, reject.

#. If ``membership`` is ``leave``:

i. If the ``sender`` matches ``state_key``, allow if and only if that user's
current membership state is ``invite`` or ``join``.

#. If the ``sender``'s current membership state is not ``joined``, reject.

#. If the *target user*'s current membership state is ``ban``, and the
``sender``'s power level is less than the *ban level*, reject.

#. If the ``sender``'s power level is greater than or equal to the *kick
level*, and the *target user*'s power level is less than the
``sender``'s power level, allow.

#. Otherwise, reject.

#. If ``membership`` is ``ban``:

i. If the ``sender``'s current membership state is not ``joined``, reject.

#. If the ``sender``'s power level is greater than or equal to the *ban
level*, and the *target user*'s power level is less than the
``sender``'s power level, allow.

#. Otherwise, reject.

#. Otherwise, the membership is unknown. Reject.

#. If the ``sender``'s current membership state is not ``joined``, reject.

#. If the event type's *required power level* is greater than the ``sender``'s power
level, reject.

#. If type is ``m.room.power_levels``:

a. For each of the keys ``users_default``, ``events_default``,
``state_default``, ``ban``, ``redact``, ``kick``, ``invite``, as well as
each entry being changed under the ``events`` or ``users`` keys:

i. If the current value is higher than the ``sender``'s current power level,
reject.

#. If the new value is higher than the ``sender``'s current power level,
reject.

#. For each entry being changed under the ``users`` key, other than the
``sender``'s own entry:

i. If the current value is equal to the ``sender``'s current power level,
reject.

#. Otherwise, allow.

#. If type is ``m.room.redact``:

#. If the ``sender``'s power level is greater than or equal to the *redact
level*, allow.

#. If the ``sender`` of the event being redacted is the same as the
``sender`` of the ``m.room.redact``, allow.

#. Otherwise, reject.

#. Otherwise, allow.

.. NOTE::

Some consequences of these rules:

* Unless you are a member of the room, the only permitted operations (apart
from the intial create/join) are: joining a public room; accepting or
rejecting an invitation to a room.

* To unban somebody, you must have power level greater than or equal to both
the kick *and* ban levels, *and* greater than the target user's power
level.

.. TODO-spec

I think there is some magic about 3pid invites too.

EDUs
----
Expand Down