diff --git a/drafts/erikj_federation.rst b/drafts/erikj_federation.rst index ce089def7c5..381228d0f91 100644 --- a/drafts/erikj_federation.rst +++ b/drafts/erikj_federation.rst @@ -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 ~~~~~~~~~~~ diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 11c57e61e95..b3e802c05a0 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -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. @@ -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. + +#. 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 ----