diff --git a/api/client-server/admin.yaml b/api/client-server/admin.yaml index 09942a10..8794a65c 100644 --- a/api/client-server/admin.yaml +++ b/api/client-server/admin.yaml @@ -82,7 +82,7 @@ paths: devices: type: object description: |- - Each key is an identitfier for one of the user's devices. + Each key is an identifier for one of the user's devices. additionalProperties: type: object title: DeviceInfo diff --git a/api/client-server/create_room.yaml b/api/client-server/create_room.yaml index 2487707e..446d8aef 100644 --- a/api/client-server/create_room.yaml +++ b/api/client-server/create_room.yaml @@ -38,20 +38,26 @@ paths: the new room, including checking power levels for each event. It MUST apply the events implied by the request in the following order: - 0. A default ``m.room.power_levels`` event, giving the room creator + 1. The ``m.room.create`` event itself. Must be the first event in the + room. + + 2. An ``m.room.member`` event for the creator to join the room. This is + needed so the remaining events can be sent. + + 3. A default ``m.room.power_levels`` event, giving the room creator (and not other members) permission to send state events. Overridden by the ``power_level_content_override`` parameter. - 1. Events set by the ``preset``. Currently these are the ``m.room.join_rules``, + 4. Events set by the ``preset``. Currently these are the ``m.room.join_rules``, ``m.room.history_visibility``, and ``m.room.guest_access`` state events. - 2. Events listed in ``initial_state``, in the order that they are + 5. Events listed in ``initial_state``, in the order that they are listed. - 3. Events implied by ``name`` and ``topic`` (``m.room.name`` and ``m.room.topic`` + 6. Events implied by ``name`` and ``topic`` (``m.room.name`` and ``m.room.topic`` state events). - 4. Invite events implied by ``invite`` and ``invite_3pid`` (``m.room.member`` with + 7. Invite events implied by ``invite`` and ``invite_3pid`` (``m.room.member`` with ``membership: invite`` and ``m.room.third_party_invite``). The available presets do the following with respect to room state: diff --git a/api/client-server/definitions/device_keys.yaml b/api/client-server/definitions/device_keys.yaml index 41504aba..4f7cffe7 100644 --- a/api/client-server/definitions/device_keys.yaml +++ b/api/client-server/definitions/device_keys.yaml @@ -47,6 +47,7 @@ properties: "ed25519:JLAFKJWSCS": "lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI" signatures: type: object + title: Signatures description: |- Signatures for the device key object. A map from user ID, to a map from ``:`` to the signature. diff --git a/api/client-server/definitions/third_party_signed.yaml b/api/client-server/definitions/third_party_signed.yaml index c9c761a1..7ce1a1d1 100644 --- a/api/client-server/definitions/third_party_signed.yaml +++ b/api/client-server/definitions/third_party_signed.yaml @@ -33,6 +33,10 @@ properties: type: object description: A signatures object containing a signature of the entire signed object. title: Signatures + additionalProperties: + type: object + additionalProperties: + type: string example: { "example.org": { "ed25519:0": "some9signature" diff --git a/api/client-server/directory.yaml b/api/client-server/directory.yaml index 2c7c8386..7a08faf2 100644 --- a/api/client-server/directory.yaml +++ b/api/client-server/directory.yaml @@ -19,7 +19,7 @@ host: localhost:8008 schemes: - https - http -basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%/directory +basePath: /_matrix/client/%CLIENT_MAJOR_VERSION% consumes: - application/json produces: @@ -27,7 +27,7 @@ produces: securityDefinitions: $ref: definitions/security.yaml paths: - "/room/{roomAlias}": + "/directory/room/{roomAlias}": put: summary: Create a new mapping from room alias to room ID. operationId: setRoomAlias @@ -129,7 +129,16 @@ paths: description: |- Remove a mapping of room alias to room ID. - Servers may choose to implement additional access control checks here, for instance that room aliases can only be deleted by their creator or a server administrator. + Servers may choose to implement additional access control checks here, for instance that + room aliases can only be deleted by their creator or a server administrator. + + .. Note:: + Servers may choose to update the ``alt_aliases`` for the ``m.room.canonical_alias`` + state event in the room when an alias is removed. Servers which choose to update the + canonical alias event are recommended to, in addition to their other relevant permission + checks, delete the alias and return a successful response even if the user does not + have permission to update the ``m.room.canonical_alias`` event. + operationId: deleteRoomAlias security: - accessToken: [] @@ -159,3 +168,70 @@ paths: "$ref": "definitions/errors/error.yaml" tags: - Room directory + "/rooms/{roomId}/aliases": + get: + summary: Get a list of local aliases on a given room. + description: |- + Get a list of aliases maintained by the local server for the + given room. + + This endpoint can be called by users who are in the room (external + users receive an ``M_FORBIDDEN`` error response). If the room's + ``m.room.history_visibility`` maps to ``world_readable``, any + user can call this endpoint. + + Servers may choose to implement additional access control checks here, + such as allowing server administrators to view aliases regardless of + membership. + + .. Note:: + Clients are recommended not to display this list of aliases prominently + as they are not curated, unlike those listed in the ``m.room.canonical_alias`` + state event. + + operationId: getLocalAliases + security: + - accessToken: [] + parameters: + - in: path + type: string + name: roomId + description: The room ID to find local aliases of. + required: true + x-example: "!abc123:example.org" + responses: + 200: + description: |- + The list of local aliases for the room. + examples: + application/json: { + "aliases": [ + "#somewhere:example.com", + "#another:example.com", + "#hat_trick:example.com" + ] + } + schema: + type: object + properties: + aliases: + type: array + description: The server's local aliases on the room. Can be empty. + items: + type: string + required: ['aliases'] + 403: + description: The user is not permitted to retrieve the list of local aliases for the room. + examples: + application/json: { + "errcode": "M_FORBIDDEN", + "error": "You are not a member of the room." + } + schema: + "$ref": "definitions/errors/error.yaml" + 429: + description: This request was rate-limited. + schema: + "$ref": "definitions/errors/rate_limited.yaml" + tags: + - Room directory diff --git a/api/client-server/keys.yaml b/api/client-server/keys.yaml index b4b19854..7b5e9875 100644 --- a/api/client-server/keys.yaml +++ b/api/client-server/keys.yaml @@ -102,7 +102,7 @@ paths: responses: 200: description: - The provided keys were sucessfully uploaded. + The provided keys were successfully uploaded. schema: type: object properties: diff --git a/api/client-server/registration.yaml b/api/client-server/registration.yaml index 8114299e..bab9139c 100644 --- a/api/client-server/registration.yaml +++ b/api/client-server/registration.yaml @@ -328,8 +328,8 @@ paths: The homeserver may change the flows available depending on whether a valid access token is provided. The homeserver SHOULD NOT revoke the - access token provided in the request, however all other access tokens - for the user should be revoked if the request succeeds. + access token provided in the request. Whether other access tokens for + the user are revoked depends on the request parameters. security: - accessToken: [] operationId: changePassword @@ -343,6 +343,15 @@ paths: type: string description: The new password for the account. example: "ihatebananas" + logout_devices: + type: boolean + description: |- + Whether the user's other access tokens, and their associated devices, should be + revoked if the request succeeds. Defaults to true. + + When ``false``, the server can still take advantage of `the soft logout method <#soft-logout>`_ + for the user's remaining devices. + example: true auth: description: |- Additional authentication information for the user-interactive authentication API. diff --git a/api/client-server/room_send.yaml b/api/client-server/room_send.yaml index 6963f76c..fc8f3339 100644 --- a/api/client-server/room_send.yaml +++ b/api/client-server/room_send.yaml @@ -85,5 +85,7 @@ paths: type: string description: |- A unique identifier for the event. + required: + - event_id tags: - Room participation diff --git a/api/client-server/room_state.yaml b/api/client-server/room_state.yaml index 62168f26..20b9c1fd 100644 --- a/api/client-server/room_state.yaml +++ b/api/client-server/room_state.yaml @@ -45,6 +45,12 @@ paths: The body of the request should be the content object of the event; the fields in this object will vary depending on the type of event. See `Room Events`_ for the ``m.`` event specification. + + If the event type being sent is ``m.room.canonical_alias`` servers + SHOULD ensure that any new aliases being listed in the event are valid + per their grammar/syntax and that they point to the room ID where the + state event is to be sent. Servers do not validate aliases which are + being removed or are already present in the state event. operationId: setRoomStateWithKey security: - accessToken: [] @@ -92,6 +98,8 @@ paths: type: string description: |- A unique identifier for the event. + required: + - event_id 403: description: |- The sender doesn't have permission to send the event into the room. @@ -102,5 +110,23 @@ paths: "errcode": "M_FORBIDDEN", "error": "You do not have permission to send the event." } + 400: + description: |- + The sender's request is malformed. + + Some example error codes include: + + * ``M_INVALID_PARAMETER``: One or more aliases within the ``m.room.canonical_alias`` + event have invalid syntax. + + * ``M_BAD_ALIAS``: One or more aliases within the ``m.room.canonical_alias`` event + do not point to the room ID for which the state event is to be sent to. + schema: + $ref: "definitions/errors/error.yaml" + examples: + application/json: { + "errcode": "M_BAD_ALIAS", + "error": "The alias '#hello:example.org' does not point to this room." + } tags: - Room participation diff --git a/api/openapi_extensions.md b/api/openapi_extensions.md index 339452ba..fced21fc 100644 --- a/api/openapi_extensions.md +++ b/api/openapi_extensions.md @@ -43,3 +43,11 @@ doesn't work, as in the following example: properties: ... ``` + +## OpenAPI 3's "2xx" format for response codes + + + +In some cases, the schema will have HTTP response code definitions like +`2xx`, `3xx`, and `4xx`. These indicate that a response code within those +ranges (`2xx` = `200` to `299`) is valid for the schema. diff --git a/api/server-server/backfill.yaml b/api/server-server/backfill.yaml index 2ed6298c..4bf62663 100644 --- a/api/server-server/backfill.yaml +++ b/api/server-server/backfill.yaml @@ -32,8 +32,8 @@ paths: summary: Retrieves the events which precede the given event description: |- Retrieves a sliding-window history of previous PDUs that occurred in the given room. - Starting from the PDU ID(s) given in the ``v`` argument, the PDUs that preceded it - are retrieved, up to the total number given by the ``limit``. + Starting from the PDU ID(s) given in the ``v`` argument, the PDUs given in ``v`` and + the PDUs that preceded them are retrieved, up to the total number given by the ``limit``. operationId: backfillRoom security: - signedRequest: [] @@ -63,6 +63,14 @@ paths: description: |- A transaction containing the PDUs that preceded the given event(s), including the given event(s), up to the given limit. + + .. Note:: + Though the PDU definitions require that ``prev_events`` and ``auth_events`` be limited + in number, the response of backfill MUST NOT be validated on these specific restrictions. + + Due to historical reasons, it is possible that events which were previously accepted + would now be rejected by these limitations. The events should be rejected per usual by + the ``/send``, ``/get_missing_events``, and remaining endpoints. schema: $ref: "definitions/unlimited_pdu_transaction.yaml" "/get_missing_events/{roomId}": diff --git a/api/server-server/definitions/keys.yaml b/api/server-server/definitions/keys.yaml index 8bc6c563..306d4d00 100644 --- a/api/server-server/definitions/keys.yaml +++ b/api/server-server/definitions/keys.yaml @@ -20,7 +20,6 @@ properties: server_name: type: string description: DNS name of the homeserver. - required: true example: "example.org" verify_keys: type: object @@ -31,7 +30,6 @@ properties: algorithm and ``abc123`` being the version in the example below). Together, this forms the Key ID. The version must have characters matching the regular expression ``[a-zA-Z0-9_]``. - required: true additionalProperties: type: object title: Verify Key @@ -44,8 +42,8 @@ properties: key: type: string description: The `Unpadded Base64`_ encoded key. - required: true example: "VGhpcyBzaG91bGQgYmUgYSByZWFsIGVkMjU1MTkgcGF5bG9hZA" + required: ["key"] old_verify_keys: type: object description: |- @@ -69,27 +67,24 @@ properties: type: integer format: int64 description: POSIX timestamp in milliseconds for when this key expired. - required: true example: 1532645052628 key: type: string description: The `Unpadded Base64`_ encoded key. - required: true example: "VGhpcyBzaG91bGQgYmUgeW91ciBvbGQga2V5J3MgZWQyNTUxOSBwYXlsb2FkLg" + required: ["expired_ts", "key"] signatures: type: object - description: Digital signatures for this object signed using the ``verify_keys``. + description: |- + Digital signatures for this object signed using the ``verify_keys``. + + The signature is calculated using the process described at `Signing + JSON`_. + title: Signatures additionalProperties: type: object - title: Signed Server - example: { - "example.org": { - "ad25519:abc123": "VGhpcyBzaG91bGQgYWN0dWFsbHkgYmUgYSBzaWduYXR1cmU" - } - } additionalProperties: type: string - name: Encoded Signature Verification Key valid_until_ts: type: integer format: int64 @@ -103,3 +98,4 @@ properties: publishes a key which is valid for a significant amount of time without a way for the homeserver owner to revoke it. example: 1052262000000 +required: ["server_name", "verify_keys"] diff --git a/api/server-server/definitions/pdu_v3.yaml b/api/server-server/definitions/pdu_v3.yaml index 38105098..3e69d941 100644 --- a/api/server-server/definitions/pdu_v3.yaml +++ b/api/server-server/definitions/pdu_v3.yaml @@ -32,6 +32,10 @@ allOf: description: |- Event IDs for the authorization events that would allow this event to be in the room. + + Must contain less than or equal to 10 events. Note that if the relevant + auth event selection rules are used, this restriction should never be + encountered. example: ["$base64EncodedHash", "$AnotherEvent"] prev_events: type: array @@ -41,6 +45,8 @@ allOf: description: |- Event IDs for the most recent events in the room that the homeserver was aware of when it made this event. + + Must contain less than or equal to 20 events. example: ["$base64EncodedHash", "$AnotherEvent"] hashes: type: object diff --git a/api/server-server/definitions/pdu_v4.yaml b/api/server-server/definitions/pdu_v4.yaml index a045e657..d22956c6 100644 --- a/api/server-server/definitions/pdu_v4.yaml +++ b/api/server-server/definitions/pdu_v4.yaml @@ -32,6 +32,10 @@ allOf: description: |- Event IDs for the authorization events that would allow this event to be in the room. + + Must contain less than or equal to 10 events. Note that if the relevant + auth event selection rules are used, this restriction should never be + encountered. example: ["$URLsafe-base64EncodedHash", "$Another_Event"] prev_events: type: array @@ -41,6 +45,8 @@ allOf: description: |- Event IDs for the most recent events in the room that the homeserver was aware of when it made this event. + + Must contain less than or equal to 20 events. example: ["$URLsafe-base64EncodedHash", "$Another_Event"] required: - auth_events diff --git a/api/server-server/definitions/send_join_response.yaml b/api/server-server/definitions/send_join_response.yaml new file mode 100644 index 00000000..2837556b --- /dev/null +++ b/api/server-server/definitions/send_join_response.yaml @@ -0,0 +1,58 @@ +# Copyright 2018 New Vector Ltd +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +type: object +title: Room State +description: The state for the room. +properties: + origin: + type: string + description: The resident server's DNS name. + auth_chain: + type: array + description: |- + The auth chain for the entire current room state prior to the join event. + + Note that events have a different format depending on the room version - check the + `room version specification`_ for precise event formats. + items: + type: object + title: PDU + description: |- + The `PDUs <#pdus>`_ that make up the auth chain. The event format varies depending + on the room version - check the `room version specification`_ for precise event formats. + schema: + type: object + properties: [] + example: + $ref: "../examples/minimal_pdu.json" + state: + type: array + description: |- + The resolved current room state prior to the join event. + + The event format varies depending on the room version - check the `room version specification`_ + for precise event formats. + items: + type: object + title: PDU + description: |- + The `PDUs <#pdus>`_ for the fully resolved state of the room. The event format varies depending + on the room version - check the `room version specification`_ for precise event formats. + schema: + type: object + properties: [] + example: + $ref: "../examples/minimal_pdu.json" +required: ["auth_chain", "state", "origin"] diff --git a/api/server-server/definitions/unsigned_pdu_base.yaml b/api/server-server/definitions/unsigned_pdu_base.yaml index 283e4fed..f1485b55 100644 --- a/api/server-server/definitions/unsigned_pdu_base.yaml +++ b/api/server-server/definitions/unsigned_pdu_base.yaml @@ -53,6 +53,8 @@ properties: description: |- Event IDs and reference hashes for the most recent events in the room that the homeserver was aware of when it made this event. + + Must contain less than or equal to 20 events. items: type: array maxItems: 2 @@ -84,6 +86,10 @@ properties: description: |- Event IDs and reference hashes for the authorization events that would allow this event to be in the room. + + Must contain less than or equal to 10 events. Note that if the relevant + auth event selection rules are used, this restriction should never be + encountered. items: type: array maxItems: 2 diff --git a/api/server-server/joins.yaml b/api/server-server/joins-v1.yaml similarity index 80% rename from api/server-server/joins.yaml rename to api/server-server/joins-v1.yaml index 1b5f4632..18c88db0 100644 --- a/api/server-server/joins.yaml +++ b/api/server-server/joins-v1.yaml @@ -1,4 +1,5 @@ # Copyright 2018 New Vector Ltd +# Copyright 2020 The Matrix.org Foundation C.I.C. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -62,7 +63,7 @@ paths: 200: description: |- A template to be used for the rest of the `Joining Rooms`_ handshake. Note that - events have a different format depending on the room version - check the + events have a different format depending on the room version - check the `room version specification`_ for precise event formats. **The response body here describes the common event fields in more detail and may be missing other required fields for a PDU.** @@ -165,14 +166,18 @@ paths: put: summary: Submit a signed join event to a resident server description: |- + .. Note:: + Servers should instead prefer to use the v2 ``/send_join`` + endpoint. + Submits a signed join event to the resident server for it to accept it into the room's graph. Note that events have - a different format depending on the room version - check + a different format depending on the room version - check the `room version specification`_ for precise event formats. - **The request and response body here describes the common + **The request and response body here describe the common event fields in more detail and may be missing other required fields for a PDU.** - operationId: sendJoin + operationId: sendJoinV1 security: - signedRequest: [] parameters: @@ -257,47 +262,7 @@ paths: - type: integer description: The value ``200``. example: 200 - - type: object - title: Room State - description: The state for the room. - properties: - origin: - type: string - description: The resident server's DNS name. - auth_chain: - type: array - description: |- - The auth chain. Note that events have a different format depending on - the room version - check the `room version specification`_ for precise - event formats. - items: - type: object - title: PDU - description: |- - The `PDUs <#pdus>`_ that make up the auth chain. The event format varies depending - on the room version - check the `room version specification`_ for precise event formats. - schema: - type: object - properties: [] - example: - $ref: "examples/minimal_pdu.json" - state: - type: array - description: |- - The room state. The event format varies depending on the room version - - check the `room version specification`_ for precise event formats. - items: - type: object - title: PDU - description: |- - The `PDUs <#pdus>`_ for the fully resolved state of the room. The event format varies depending - on the room version - check the `room version specification`_ for precise event formats. - schema: - type: object - properties: [] - example: - $ref: "examples/minimal_pdu.json" - required: ["auth_chain", "state", "origin"] + - $ref: "./definitions/send_join_response.yaml" examples: application/json: [ 200, diff --git a/api/server-server/joins-v2.yaml b/api/server-server/joins-v2.yaml new file mode 100644 index 00000000..b5a1544c --- /dev/null +++ b/api/server-server/joins-v2.yaml @@ -0,0 +1,136 @@ +# Copyright 2018 New Vector Ltd +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +swagger: '2.0' +info: + title: "Matrix Federation Join Room API" + version: "1.0.0" +host: localhost:8448 +schemes: + - https +basePath: /_matrix/federation/v2 +consumes: + - application/json +produces: + - application/json +securityDefinitions: + $ref: definitions/security.yaml +paths: + # Note: there is no v2 of make_join (yet) + "/send_join/{roomId}/{eventId}": + put: + summary: Submit a signed join event to a resident server + description: |- + .. Note:: + This API is nearly identical to the v1 API with the + exception of the response format being fixed. + + This endpoint is preferred over the v1 API as it provides + a more standarised response format. Senders which receive + a 400, 404, or other status code which indicates this endpoint + is not available should retry using the v1 API instead. + + Submits a signed join event to the resident server for it + to accept it into the room's graph. Note that events have + a different format depending on the room version - check + the `room version specification`_ for precise event formats. + **The request and response body here describe the common + event fields in more detail and may be missing other required + fields for a PDU.** + operationId: sendJoinV2 + security: + - signedRequest: [] + parameters: + - in: path + name: roomId + type: string + description: The room ID that is about to be joined. + required: true + x-example: "!abc123:matrix.org" + - in: path + name: eventId + type: string + description: The event ID for the join event. + required: true + x-example: "$abc123:example.org" + - in: body + name: body + type: object + required: true + schema: + type: object + properties: + sender: + type: string + description: The user ID of the joining member. + example: "@someone:example.org" + origin: + type: string + description: The name of the joining homeserver. + example: "matrix.org" + origin_server_ts: + type: integer + format: int64 + description: A timestamp added by the joining homeserver. + example: 1234567890 + type: + type: string + description: The value ``m.room.member``. + example: "m.room.member" + state_key: + type: string + description: The user ID of the joining member. + example: "@someone:example.org" + content: + type: object + title: Membership Event Content + description: The content of the event. + example: {"membership": "join"} + properties: + membership: + type: string + description: The value ``join``. + example: "join" + required: ['membership'] + required: + - state_key + - sender + - origin + - origin_server_ts + - type + - content + example: { + "$ref": "examples/minimal_pdu.json", + "type": "m.room.member", + "state_key": "@someone:example.org", + "origin": "example.org", + "origin_server_ts": 1549041175876, + "sender": "@someone:example.org", + "content": { + "membership": "join" + } + } + responses: + 200: + description: |- + The full state for the room, having accepted the join event. + schema: + $ref: "./definitions/send_join_response.yaml" + examples: + application/json: { + "origin": "matrix.org", + "auth_chain": [{"$ref": "examples/minimal_pdu.json"}], + "state": [{"$ref": "examples/minimal_pdu.json"}] + } diff --git a/api/server-server/keys_server.yaml b/api/server-server/keys_server.yaml index 465bb294..81b98b1e 100644 --- a/api/server-server/keys_server.yaml +++ b/api/server-server/keys_server.yaml @@ -34,7 +34,7 @@ paths: Intermediate notary servers should cache a response for half of its lifetime to avoid serving a stale response. Originating servers should avoid returning responses that expire in less than an hour to avoid - repeated reqests for a certificate that is about to expire. Requesting + repeated requests for a certificate that is about to expire. Requesting servers should limit how frequently they query for certificates to avoid flooding a server with requests. diff --git a/api/server-server/leaving.yaml b/api/server-server/leaving-v1.yaml similarity index 95% rename from api/server-server/leaving.yaml rename to api/server-server/leaving-v1.yaml index e0882fe8..c92b7920 100644 --- a/api/server-server/leaving.yaml +++ b/api/server-server/leaving-v1.yaml @@ -1,4 +1,5 @@ # Copyright 2018 New Vector Ltd +# Copyright 2020 The Matrix.org Foundation C.I.C. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -53,7 +54,7 @@ paths: 200: description: |- A template to be used to call ``/send_leave``. Note that - events have a different format depending on the room version - check the + events have a different format depending on the room version - check the `room version specification`_ for precise event formats. **The response body here describes the common event fields in more detail and may be missing other required fields for a PDU.** @@ -142,14 +143,18 @@ paths: put: summary: Submit a signed leave event to a resident server description: |- + .. Note:: + Servers should instead prefer to use the v2 ``/send_leave`` + endpoint. + Submits a signed leave event to the resident server for it to accept it into the room's graph. Note that events have - a different format depending on the room version - check + a different format depending on the room version - check the `room version specification`_ for precise event formats. - **The request and response body here describes the common + **The request and response body here describe the common event fields in more detail and may be missing other required fields for a PDU.** - operationId: sendLeave + operationId: sendLeaveV1 security: - signedRequest: [] parameters: diff --git a/api/server-server/leaving-v2.yaml b/api/server-server/leaving-v2.yaml new file mode 100644 index 00000000..3e82c414 --- /dev/null +++ b/api/server-server/leaving-v2.yaml @@ -0,0 +1,140 @@ +# Copyright 2018 New Vector Ltd +# Copyright 2020 The Matrix.org Foundation C.I.C. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +swagger: '2.0' +info: + title: "Matrix Federation Leave Room API" + version: "1.0.0" +host: localhost:8448 +schemes: + - https +basePath: /_matrix/federation/v2 +consumes: + - application/json +produces: + - application/json +securityDefinitions: + $ref: definitions/security.yaml +paths: + # Note: there is no v2 of make_leave (yet) + "/send_leave/{roomId}/{eventId}": + put: + summary: Submit a signed leave event to a resident server + description: |- + .. Note:: + This API is nearly identical to the v1 API with the + exception of the response format being fixed. + + This endpoint is preferred over the v1 API as it provides + a more standarised response format. Senders which receive + a 400, 404, or other status code which indicates this endpoint + is not available should retry using the v1 API instead. + + Submits a signed leave event to the resident server for it + to accept it into the room's graph. Note that events have + a different format depending on the room version - check + the `room version specification`_ for precise event formats. + **The request and response body here describe the common + event fields in more detail and may be missing other required + fields for a PDU.** + operationId: sendLeaveV2 + security: + - signedRequest: [] + parameters: + - in: path + name: roomId + type: string + description: The room ID that is about to be left. + required: true + x-example: "!abc123:matrix.org" + - in: path + name: eventId + type: string + description: The event ID for the leave event. + required: true + x-example: "$abc123:example.org" + - in: body + name: body + type: object + required: true + schema: + type: object + properties: + sender: + type: string + description: The user ID of the leaving member. + example: "@someone:example.org" + origin: + type: string + description: The name of the leaving homeserver. + example: "matrix.org" + origin_server_ts: + type: integer + format: int64 + description: A timestamp added by the leaving homeserver. + example: 1234567890 + type: + type: string + description: The value ``m.room.member``. + example: "m.room.member" + state_key: + type: string + description: The user ID of the leaving member. + example: "@someone:example.org" + content: + type: object + title: Membership Event Content + description: The content of the event. + example: {"membership": "leave"} + properties: + membership: + type: string + description: The value ``leave``. + example: "leave" + required: ['membership'] + depth: + type: integer + description: This field must be present but is ignored; it may be 0. + example: 12 + required: + - state_key + - sender + - origin + - origin_server_ts + - type + - depth + - content + example: { + "$ref": "examples/minimal_pdu.json", + "type": "m.room.member", + "state_key": "@someone:example.org", + "origin": "example.org", + "origin_server_ts": 1549041175876, + "sender": "@someone:example.org", + "content": { + "membership": "leave" + } + } + responses: + 200: + description: |- + An empty response to indicate the event was accepted into the graph by + the receiving homeserver. + schema: + type: object + title: Empty Object + description: An empty object. + examples: + application/json: {} diff --git a/api/server-server/third_party_invite.yaml b/api/server-server/third_party_invite.yaml index 0b7aac5b..fbd2a9d9 100644 --- a/api/server-server/third_party_invite.yaml +++ b/api/server-server/third_party_invite.yaml @@ -102,12 +102,16 @@ paths: properties: signatures: type: object - description: The server signatures for this event. + title: Signatures additionalProperties: type: object - title: Server Signatures additionalProperties: type: string + description: |- + The server signatures for this event. + + The signature is calculated using the process + described at `Signing JSON`_. example: { "magic.forest": { "ed25519:3": "fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg" diff --git a/api/server-server/transactions.yaml b/api/server-server/transactions.yaml index 9cc8be75..a6348e13 100644 --- a/api/server-server/transactions.yaml +++ b/api/server-server/transactions.yaml @@ -38,7 +38,7 @@ paths: The sending server must wait and retry for a 200 OK response before sending a transaction with a different ``txnId`` to the receiving server. - Note that events have a different format depending on the room version - check + Note that events have a different format depending on the room version - check the `room version specification`_ for precise event formats. operationId: sendTransaction security: @@ -77,43 +77,33 @@ paths: The result of processing the transaction. The server is to use this response even in the event of one or more PDUs failing to be processed. schema: - type: array - minItems: 2 - maxItems: 2 - items: - - type: integer - description: The value ``200``. - example: 200 - - type: object - title: PDU Processing Results - description: The results for the processing of each PDU in the transaction. - properties: - pdus: - type: object - description: |- - The PDUs from the original transaction. The string key represents the ID of the - PDU (event) that was processed. - additionalProperties: - type: object - title: PDU Processing Result - description: Information about how the PDU was handled. - properties: - error: - type: string - description: |- - A human readable description about what went wrong in processing this PDU. - If no error is present, the PDU can be considered successfully handled. - example: "You are not allowed to send a message to this room." - required: ['pdus'] + type: object + title: PDU Processing Results + description: The results for the processing of each PDU in the transaction. + properties: + pdus: + type: object + description: |- + The PDUs from the original transaction. The string key represents the ID of the + PDU (event) that was processed. + additionalProperties: + type: object + title: PDU Processing Result + description: Information about how the PDU was handled. + properties: + error: + type: string + description: |- + A human readable description about what went wrong in processing this PDU. + If no error is present, the PDU can be considered successfully handled. + example: "You are not allowed to send a message to this room." + required: ['pdus'] examples: - application/json: [ - 200, - { - "pdus": { - "$successful_event:example.org": {}, - "$failed_event:example.org": { - "error": "You are not allowed to send a message to this room." - } + application/json: { + "pdus": { + "$successful_event:example.org": {}, + "$failed_event:example.org": { + "error": "You are not allowed to send a message to this room." } } - ] + } diff --git a/api/server-server/user_keys.yaml b/api/server-server/user_keys.yaml index 9c11ca84..ae8ccd7e 100644 --- a/api/server-server/user_keys.yaml +++ b/api/server-server/user_keys.yaml @@ -74,7 +74,7 @@ paths: One-time keys for the queried devices. A map from user ID, to a map from devices to a map from ``:`` to the key object. - See the Client-Server Key Algorithms section for more information on + See the `Client-Server Key Algorithms`_ section for more information on the Key Object format. additionalProperties: type: object @@ -89,10 +89,16 @@ paths: description: The key, encoded using unpadded base64. signatures: type: object - description: |- - Signature for the device. Mapped from user ID to signature object. + title: Signatures additionalProperties: - type: string + type: object + additionalProperties: + type: string + description: |- + Signature of the key object. + + The signature is calculated using the process described at `Signing + JSON`_. required: ['key', 'signatures'] example: { "@alice:example.com": { diff --git a/changelogs/client_server.rst b/changelogs/client_server.rst index bc12da5c..6f8aee1c 100644 --- a/changelogs/client_server.rst +++ b/changelogs/client_server.rst @@ -1,3 +1,40 @@ +r0.6.1 +====== + +New Endpoints +------------- + +- Added ``/rooms/{roomId}/aliases`` for retrieving local aliases for a room. (`#2562 `_) + + +Backwards Compatible Changes +---------------------------- + +- Added data structures for defining moderation policies in rooms per `MSC2313 `_. (`#2434 `_) +- Optionally invalidate other access tokens during password modification per `MSC2457 `_. (`#2523 `_) +- Add User-Interactive Authentication for SSO-backed homeserver per `MSC2454 `_. (`#2532 `_) +- Add soft-logout support per `MSC1466 `_. (`#2546 `_) +- Replaced legacy room alias handling with a more sustainable solution per `MSC2432 `_. (`#2562 `_) + + +Spec Clarifications +------------------- + +- List available enum values for the room versions capability. (`#2245 `_) +- Fix various spelling errors throughout the specification. (`#2351 `_, `#2415 `_, `#2453 `_, `#2524 `_, `#2553 `_, `#2569 `_) +- Minor clarifications to token-based User-Interactive Authentication. (`#2369 `_) +- Minor clarification for what the user directory searches. (`#2381 `_) +- Fix key export format example to match the specification. (`#2430 `_) +- Clarify the IV data type for encrypted files. (`#2492 `_) +- Fix the ``.m.rule.contains_user_name`` default push rule to set the highlight tweak. (`#2519 `_) +- Clarify that an ``event_id`` is returned when sending events. (`#2525 `_) +- Fix some numbers in the specification to match their explanation text. (`#2554 `_) +- Move redaction algorithm into the room version specifications. (`#2563 `_) +- Clarify signature object structures for encryption. (`#2566 `_) +- Clarify which events are created as part of ``/createRoom``. (`#2571 `_) +- Remove claims that the homeserver is exclusively responsible for profile information in membership events. (`#2574 `_) + + r0.6.0 ====== diff --git a/changelogs/client_server/newsfragments/2245.clarification b/changelogs/client_server/newsfragments/2245.clarification deleted file mode 100644 index 31e5c2df..00000000 --- a/changelogs/client_server/newsfragments/2245.clarification +++ /dev/null @@ -1 +0,0 @@ -List available enum values for the room versions capability. diff --git a/changelogs/client_server/newsfragments/2351.clarification b/changelogs/client_server/newsfragments/2351.clarification deleted file mode 100644 index 902a9c3f..00000000 --- a/changelogs/client_server/newsfragments/2351.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix various spelling errors throughout the specification. diff --git a/changelogs/client_server/newsfragments/2369.clarification b/changelogs/client_server/newsfragments/2369.clarification deleted file mode 100644 index c7fd0fd9..00000000 --- a/changelogs/client_server/newsfragments/2369.clarification +++ /dev/null @@ -1 +0,0 @@ -Minor clarifications to token-based User-Interactive Authentication. diff --git a/changelogs/client_server/newsfragments/2381.clarification b/changelogs/client_server/newsfragments/2381.clarification deleted file mode 100644 index 70bd6d18..00000000 --- a/changelogs/client_server/newsfragments/2381.clarification +++ /dev/null @@ -1 +0,0 @@ -Minor clarification for what the user directory searches. diff --git a/changelogs/client_server/newsfragments/2415.clarification b/changelogs/client_server/newsfragments/2415.clarification deleted file mode 100644 index 902a9c3f..00000000 --- a/changelogs/client_server/newsfragments/2415.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix various spelling errors throughout the specification. diff --git a/changelogs/client_server/newsfragments/2430.clarification b/changelogs/client_server/newsfragments/2430.clarification deleted file mode 100644 index 56be0c1a..00000000 --- a/changelogs/client_server/newsfragments/2430.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix key export format example to match the specification. diff --git a/changelogs/client_server/newsfragments/2434.feature b/changelogs/client_server/newsfragments/2434.feature deleted file mode 100644 index 2b8f36f5..00000000 --- a/changelogs/client_server/newsfragments/2434.feature +++ /dev/null @@ -1 +0,0 @@ -Added data structures for defining moderation policies in rooms per `MSC2313 `_. diff --git a/changelogs/client_server/newsfragments/2453.clarification b/changelogs/client_server/newsfragments/2453.clarification deleted file mode 100644 index 902a9c3f..00000000 --- a/changelogs/client_server/newsfragments/2453.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix various spelling errors throughout the specification. diff --git a/changelogs/client_server/newsfragments/2492.clarification b/changelogs/client_server/newsfragments/2492.clarification deleted file mode 100644 index 88c478ec..00000000 --- a/changelogs/client_server/newsfragments/2492.clarification +++ /dev/null @@ -1 +0,0 @@ -Clarify the IV data type for encrypted files. diff --git a/changelogs/client_server/newsfragments/2519.clarification b/changelogs/client_server/newsfragments/2519.clarification deleted file mode 100644 index 4b32da1e..00000000 --- a/changelogs/client_server/newsfragments/2519.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix the ``.m.rule.contains_user_name`` default push rule to set the highlight tweak. diff --git a/changelogs/server_server.rst b/changelogs/server_server.rst index 22da543c..367fb092 100644 --- a/changelogs/server_server.rst +++ b/changelogs/server_server.rst @@ -1,3 +1,34 @@ +r0.1.4 +====== + +New Endpoints +------------- + +- Add new ``POST /publicRooms`` endpoint for filtering the room directory. (`#2305 `_) +- Add new v2 ``/send_join`` and ``/send_leave`` endpoints per `MSC1802 `_. (`#2547 `_) + + +Removed Endpoints +----------------- + +- Remove the unused ``query_auth`` API per `MSC2451 `_. (`#2470 `_) + + +Spec Clarifications +------------------- + +- Move auth event selection to a more obvious location. (`#2392 `_) +- Fix typo in Request Authentication python example. (`#2510 `_) +- Clarify which fields are required on the key server endpoints. (`#2527 `_) +- Clarify the limits of ``prev_events`` and ``auth_events`` for PDUs. (`#2538 `_) +- Clarify which events are targeted by backfill. (`#2559 `_) +- Fix the response format of the ``/send`` endpoint. (`#2560 `_) +- Clarify signature object structures for encryption. (`#2566 `_) +- Clarify the server names to use when signing requests. (`#2570 `_) +- Clarify the state/auth chain requirements for ``/send_join``. (`#2575 `_) +- Fix various spelling errors throughout the specification. (`#2577 `_) + + r0.1.3 ====== diff --git a/changelogs/server_server/newsfragments/2035.new b/changelogs/server_server/newsfragments/2035.new deleted file mode 100644 index 6794c4ea..00000000 --- a/changelogs/server_server/newsfragments/2035.new +++ /dev/null @@ -1 +0,0 @@ -Add new ``POST /publicRooms`` endpoint for filtering the room directory. diff --git a/changelogs/server_server/newsfragments/2392.clarification b/changelogs/server_server/newsfragments/2392.clarification deleted file mode 100644 index b09420e4..00000000 --- a/changelogs/server_server/newsfragments/2392.clarification +++ /dev/null @@ -1 +0,0 @@ -Move auth event selection to a more obvious location. diff --git a/changelogs/server_server/newsfragments/2470.removal b/changelogs/server_server/newsfragments/2470.removal deleted file mode 100644 index 51cdadd4..00000000 --- a/changelogs/server_server/newsfragments/2470.removal +++ /dev/null @@ -1 +0,0 @@ -Remove the unused ``query_auth`` API per `MSC2451 `_. diff --git a/changelogs/server_server/newsfragments/2510.clarification b/changelogs/server_server/newsfragments/2510.clarification deleted file mode 100644 index 9c96c5a5..00000000 --- a/changelogs/server_server/newsfragments/2510.clarification +++ /dev/null @@ -1 +0,0 @@ -Fix typo in Request Authentication python example. diff --git a/event-schemas/examples/m.room.aliases b/event-schemas/examples/m.room.aliases deleted file mode 100644 index 3e20332f..00000000 --- a/event-schemas/examples/m.room.aliases +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$ref": "core/state_event.json", - "state_key": "example.org", - "type": "m.room.aliases", - "content": { - "aliases": ["#somewhere:example.org", "#another:example.org"] - } -} diff --git a/event-schemas/examples/m.room.canonical_alias b/event-schemas/examples/m.room.canonical_alias index 06c3226c..698c11b8 100644 --- a/event-schemas/examples/m.room.canonical_alias +++ b/event-schemas/examples/m.room.canonical_alias @@ -3,6 +3,10 @@ "type": "m.room.canonical_alias", "state_key": "", "content": { - "alias": "#somewhere:localhost" + "alias": "#somewhere:localhost", + "alt_aliases": [ + "#somewhere:example.org", + "#myroom:example.com" + ] } } diff --git a/event-schemas/schema/m.room.aliases b/event-schemas/schema/m.room.aliases deleted file mode 100644 index 348d490d..00000000 --- a/event-schemas/schema/m.room.aliases +++ /dev/null @@ -1,24 +0,0 @@ ---- -allOf: - - $ref: core-event-schema/state_event.yaml -description: 'This event is sent by a homeserver directly to inform of changes to the list of aliases it knows about for that room. The ``state_key`` for this event is set to the homeserver which owns the room alias. The entire set of known aliases for the room is the union of all the ``m.room.aliases`` events, one for each homeserver. Clients **should** check the validity of any room alias given in this list before presenting it to the user as trusted fact. The lists given by this event should be considered simply as advice on which aliases might exist, for which the client can perform the lookup to confirm whether it receives the correct room ID.' -properties: - content: - properties: - aliases: - description: A list of room aliases. - items: - type: string - type: array - required: - - aliases - type: object - state_key: - description: The homeserver domain which owns these room aliases. - type: string - type: - enum: - - m.room.aliases - type: string -title: Informs the room about what room aliases it has been given. -type: object diff --git a/event-schemas/schema/m.room.canonical_alias b/event-schemas/schema/m.room.canonical_alias index 5e8e0524..f227871a 100644 --- a/event-schemas/schema/m.room.canonical_alias +++ b/event-schemas/schema/m.room.canonical_alias @@ -3,21 +3,25 @@ allOf: - $ref: core-event-schema/state_event.yaml description: |- This event is used to inform the room about which alias should be - considered the canonical one. This could be for display purposes or as - suggestion to users which alias to use to advertise the room. - - A room with an ``m.room.canonical_alias`` event with an absent, null, or - empty ``alias`` field should be treated the same as a room with no - ``m.room.canonical_alias`` event. + considered the canonical one, and which other aliases point to the room. + This could be for display purposes or as suggestion to users which alias + to use to advertise and access the room. properties: content: properties: alias: - description: The canonical alias. + description: | + The canonical alias for the room. If not present, null, or empty the + room should be considered to have no canonical alias. type: string + alt_aliases: + description: | + Alternative aliases the room advertises. This list can have aliases + despite the ``alias`` field being null, empty, or otherwise not present. + type: array + items: + type: string type: object - required: - - alias state_key: description: A zero-length string. pattern: '^$' diff --git a/event-schemas/schema/m.room.member b/event-schemas/schema/m.room.member index 1033c098..1ccf5ab3 100644 --- a/event-schemas/schema/m.room.member +++ b/event-schemas/schema/m.room.member @@ -48,10 +48,10 @@ properties: content: properties: avatar_url: - description: 'The avatar URL for this user, if any. This is added by the homeserver.' + description: 'The avatar URL for this user, if any.' type: string displayname: - description: 'The display name for this user, if any. This is added by the homeserver.' + description: 'The display name for this user, if any.' type: - "string" - "null" @@ -82,6 +82,10 @@ properties: description: 'A single signature from the verifying server, in the format specified by the Signing Events section of the server-server API.' title: Signatures type: object + additionalProperties: + type: object + additionalProperties: + type: string token: description: The token property of the containing third_party_invite object. type: string diff --git a/proposals/1779-open-governance.md b/proposals/1779-open-governance.md index bfe86eb8..d9a53c51 100644 --- a/proposals/1779-open-governance.md +++ b/proposals/1779-open-governance.md @@ -1,4 +1,11 @@ -# Proposal for Open Governance of Matrix.org +# Proposal for Open Governance of Matrix.org + +---- + +**For updated information on the Foundation, please see https://matrix.org/foundation/**. +This MSC exists for historical reference. + +---- This whole document is the proposed constitution proposal for Matrix.org, and will form the basis of the first full Articles of Association (AoA) for [The @@ -446,7 +453,7 @@ a high-level mission lock aligned with the above: The foundation was then converted into a Community Interest Company, formalising its non-profit status under the approval of the independent [Community Interest -Companies Regulator](https://www.gov.uk/government/organisations/office-of-the-regulator-of-community-interest-companies), +Companies Regulator](https://www.gov.uk/government/organisations/office-of-the-regulator-of-community-interest-companies), which took effect Jan 2019. We are currently planning to release r0 of the Matrix Spec at the end of Jan 2019, and diff --git a/proposals/1946-secure_server-side_storage.md b/proposals/1946-secure_server-side_storage.md index 3f386d5e..f62e345e 100644 --- a/proposals/1946-secure_server-side_storage.md +++ b/proposals/1946-secure_server-side_storage.md @@ -8,6 +8,12 @@ decryption key for the backups on the server, or cross-signing ([MSC1756](https://github.com/matrix-org/matrix-doc/pull/1756)) can store the signing keys. This proposal presents a standardized way of storing such data. +## Changes + +- [MSC2472](https://github.com/matrix-org/matrix-doc/pull/2472) changed the + encryption algorithm used from an asymmetric algorithm (Curve25519) to a + symmetric algorithm (AES). + ## Proposal Secrets are data that clients need to use and that are sent through or stored @@ -32,9 +38,8 @@ Each key has an ID, and the description of the key is stored in the user's account_data using the event type `m.secret_storage.key.[key ID]`. The contents of the account data for the key will include an `algorithm` property, which indicates the encryption algorithm used, as well as a `name` property, which is -a human-readable name. The contents will be signed as signed JSON using the -user's master cross-signing key. Other properties depend on the encryption -algorithm, and are described below. +a human-readable name. Other properties depend on the encryption algorithm, +and are described below. Example: @@ -43,7 +48,7 @@ A key with ID `abcdefg` is stored in `m.secret_storage.key.abcdefg` ```json { "name": "Some key", - "algorithm": "m.secret_storage.v1.curve25519-aes-sha2", + "algorithm": "m.secret_storage.v1.aes-hmac-sha2", // ... other properties according to algorithm } ``` @@ -55,13 +60,6 @@ secrets that the user would expect to be available on all their clients. Unless the user specifies otherwise, clients will try to use the default key to decrypt secrets. -Clients MUST ensure that the key is trusted before using it to encrypt secrets. -One way to do that is to have the client that creates the key sign the key -description (as signed JSON) using the user's master cross-signing key. -Another way to do that is to prompt the user to enter the passphrase used to -generate the encryption key and ensure that the generated private key -corresponds to the public key. - #### Secret storage Encrypted data is stored in the user's account_data using the event type @@ -106,7 +104,7 @@ and the key descriptions for the keys would be: ```json { "name": "Some key", - "algorithm": "m.secret_storage.v1.curve25519-aes-sha2", + "algorithm": "m.secret_storage.v1.aes-hmac-sha2", // ... other properties according to algorithm } ``` @@ -116,45 +114,50 @@ and the key descriptions for the keys would be: ```json { "name": "Some other key", - "algorithm": "m.secret_storage.v1.curve25519-aes-sha2", + "algorithm": "m.secret_storage.v1.aes-hmac-sha2", // ... other properties according to algorithm } ``` #### Encryption algorithms -##### `m.secret_storage.v1.curve25519-aes-sha2` +##### `m.secret_storage.v1.aes-hmac-sha2` -The public key is stored in the `pubkey` property of the `m.secret_storage.key.[key -ID]` account_data as a base64-encoded string. +Secrets are encrypted using AES-CTR-256 and MACed using HMAC-SHA-256. The data +is encrypted and MACed as follows: -The data is encrypted and MACed as follows: +1. Given the secret storage key, generate 64 bytes by performing an HKDF with + SHA-256 as the hash, a salt of 32 bytes of 0, and with the secret name as + the info. The first 32 bytes are used as the AES key, and the next 32 bytes + are used as the MAC key +2. Generate 16 random bytes, set bit 63 to 0 (in order to work around + differences in AES-CTR implementations), and use this as the AES + initialization vector. This becomes the `iv` property, encoded using base64. +3. Encrypt the data using AES-CTR-256 using the AES key generated above. This + encrypted data, encoded using base64, becomes the `ciphertext` property. +4. Pass the raw encrypted data (prior to base64 encoding) through HMAC-SHA-256 + using the MAC key generated above. The resulting MAC is base64-encoded and + becomes the `mac` property. -1. Generate an ephemeral curve25519 key, and perform an ECDH with the ephemeral - key and the public key to generate a shared secret. The public half of the - ephemeral key, encoded using base64, becomes the `ephemeral` property. -2. Using the shared secret, generate 80 bytes by performing an HKDF using - SHA-256 as the hash, with a salt of 32 bytes of 0, and with the empty string - as the info. The first 32 bytes are used as the AES key, the next 32 bytes - are used as the MAC key, and the last 16 bytes are used as the AES - initialization vector. -4. Encrypt the data using AES-CBC-256 with PKCS#7 padding. This encrypted - data, encoded using base64, becomes the `ciphertext` property. -5. Pass the raw encrypted data (prior to base64 encoding) through HMAC-SHA-256 - using the MAC key generated above. The first 8 bytes of the resulting MAC - are base64-encoded, and become the `mac` property. +(We use AES-CTR to match file encryption and key exports.) -(The key HKDF, AES, and HMAC steps are the same as what are used for encryption -in olm and megolm.) +For the purposes of allowing clients to check whether a user has correctly +entered the key, clients should: -For example, the `m.secret_storage.key.[key ID]` for a key using this algorithm + 1. encrypt and MAC a message consisting of 32 bytes of 0 as described above, + using the empty string as the info parameter to the HKDF in step 1. + 2. store the `iv` and `mac` in the `m.secret_storage.key.[key ID]` + account-data. + +For example, the `m.secret_storage.key.key_id` for a key using this algorithm could look like: ```json { "name": "m.default", - "algorithm": "m.secret_storage.v1.curve25519-aes-sha2", - "pubkey": "base64+public+key" + "algorithm": "m.secret_storage.v1.aes-hmac-sha2", + "iv": "random+data", + "mac": "mac+of+encrypted+zeros" } ``` @@ -164,8 +167,8 @@ and data encrypted using this algorithm could look like this: { "encrypted": { "key_id": { + "iv": "16+bytes+base64", "ciphertext": "base64+encoded+encrypted+data", - "ephemeral": "base64+ephemeral+key", "mac": "base64+encoded+mac" } } @@ -174,7 +177,7 @@ and data encrypted using this algorithm could look like this: ###### Keys -When a user is given a raw key for `m.secret_storage.v1.curve25519-aes-sha2`, +When a user is given a raw key for `m.secret_storage.v1.aes-hmac-sha2`, it will be encoded as follows (this is the same as what is proposed in MSC1703): * prepend the two bytes 0x8b and 0x01 to the key @@ -200,7 +203,8 @@ ID]` account-data: "passphrase": { "algorithm": "m.pbkdf2", "salt": "MmMsAlty", - "iterations": 100000 + "iterations": 100000, + "bits": 256 }, ... } @@ -209,7 +213,9 @@ ID]` account-data: **`m.pbkdf2`** The key is generated using PBKDF2 using the salt given in the `salt` parameter, -and the number of iterations given in the `iterations` parameter. +and the number of iterations given in the `iterations` parameter. The key size +that is generated is given by the `bits` parameter, or 256 bits if no `bits` +parameter is given. ### Sharing diff --git a/proposals/2209-auth-rules-other-keys-in-m.room.power.levels.md b/proposals/2209-auth-rules-other-keys-in-m.room.power.levels.md new file mode 100644 index 00000000..594c0b99 --- /dev/null +++ b/proposals/2209-auth-rules-other-keys-in-m.room.power.levels.md @@ -0,0 +1,77 @@ +# Update auth rules to check notifications key in m.room.power_levels + +## Introduction + +The key `notifications` was added to the `m.room.power_levels` event after the +finalisation of the auth rules specified in room version 1. This leads to the +fact, that this dictionary is not subject to the same validation as other +dictionaries in the event, such as `users` or `events`. This especially means +that Alice is able to alter any entry within the dictionary including ones, +that are above her own power level, which is inconsistent with the behaviour +for the other two dictionaries. + +[m.room.power_levels](https://matrix.org/docs/spec/client_server/r0.5.0#m-room-power-levels) +[room version 1](https://matrix.org/docs/spec/rooms/v1) + +## Proposal + +The auth rules regarding `m.room.power_levels` have been established in room +version 1. The general idea here was that creators of a new `m.room.power_levels` +event are only able to make changes to something that is equal to or lower than +their own power level. +So, assuming a room with Alice (50), Bob (100), `m.room.power_levels` at 50, +`m.room.name` at 75 and `m.room.topic` at 25 would mean the following: + +* Alice CAN alter `m.room.topic` to any power level up to her own, in this case 50 +* Alice is NOT able to alter `m.room.name` since the current value is higher than +her own (75 > 50) +* Alice is NOT able to alter the power level of Bob, since his current value is +higher than her own (100 > 50) +* Alice is free to set the level for anything that has not been defined such as +`org.alice.message` up to a maximum of 50 + +Later on the key `notifications` was added to the `m.room.power_levels` event. +It contains a mapping of notification keys to a power level, that is required +for a user to trigger the specific notification. The most famous notification +type is the `@room` notification. + +Going back to the original example because this key was added later on, the auth +rules make no mention of it, which enables the following behaviour. *It is assumed +that `@room` is at 75* + +* Alice can add any key to the dictionary and set the value to any value she wants, +including ones higher than her own. +* Alice can alter the value for `@room` to any value she wants, including ones that +are higher than her own, even though her own value is lower. + +The proposed solution is to alter the auth rules and add the `notifications` dictionary +to the same rules that handle `events` and `users`. + +So the rule [10.d](https://matrix.org/docs/spec/rooms/v1.html) of the auth rules in +room version 1 would be updated in a new room version to: + + +> For each entry being added, changed or removed in events, users __and notifications__ +>keys: + + +## Tradeoffs + +The proposed solution would be a breaking change with current room versions and +the alternative would be to leave the `notifications` key without any checks. + +## Security considerations + +This is likely to improve security because it prevents malicious users that were +only given the right to emit `m.room.power_levels` so that they could alter a very +specific key, such as `invite`, from altering the rules established for triggering +notifications. + +## Conclusion + +The current spec conform behaviour regarding `notifications` is inconsistent with +behaviour shown by the other dictionaries and room administrators are very likely +expecting the `notifications` to work the same as them. The required change is minimal +is and also in line with the general spirit of the auth rules regarding the +`m.room.power_levels` event. A new room version is, however, required. This can be +done with other pending changes. diff --git a/proposals/2240-rooms-v6.md b/proposals/2240-rooms-v6.md new file mode 100644 index 00000000..2b3f1163 --- /dev/null +++ b/proposals/2240-rooms-v6.md @@ -0,0 +1,14 @@ +# MSC2240: Room Version 6 + +A new room version, `6`, is proposed using [room version 5](https://matrix.org/docs/spec/rooms/v5.html) as a base +and incorporating the following MSCs: + +* [MSC2209](https://github.com/matrix-org/matrix-doc/pull/2209) - Including notifications in power level auth rules. +* [MSC2432](https://github.com/matrix-org/matrix-doc/pull/2432) - Alias event authorisation and redaction. +* [MSC2540](https://github.com/matrix-org/matrix-doc/pull/2540) - Integers in canonical JSON compliance. + +Though other MSCs are capable of being included in this version, they do not have sufficient implementation to be +considered stable enough for v6 rooms. A future room version may still include them. + +Room version 6 upon being added to the specification shall be considered stable. No other room versions are affected +by this MSC. diff --git a/proposals/2454-ui-interactive-auth-for-sso.md b/proposals/2454-ui-interactive-auth-for-sso.md new file mode 100644 index 00000000..18112c5f --- /dev/null +++ b/proposals/2454-ui-interactive-auth-for-sso.md @@ -0,0 +1,230 @@ +# User-Interactive Authentication for SSO-backed homeserver + +Certain endpoints, such as `DELETE /_matrix/client/r0/devices/{deviceId}` and +`POST /_matrix/client/r0/account/3pid/add`, require the user to reconfirm their +identity, as a guard against a leaked access token being used to take over an +entire account. + +On a normal homeserver, this is done by prompting the user to enter their +password. However, on a homeserver where users authenticate via a single-sign-on +system, the user doesn't have a password registered with the homeserver. Instead +we need to delegate that check to the SSO system. + +At the protocol level, this means adding support for SSO to the +[user-interactive authentication API](https://matrix.org/docs/spec/client_server/r0.6.0#user-interactive-authentication-api). + +In theory, once SSO is added as a possible flow for authentication, any clients +that already implement the [fallback process for unknown authentication types](https://matrix.org/docs/spec/client_server/r0.6.0#fallback) +will work fine without modification. It is unknown whether this is widely +supported among clients. + +## Proposal + +An [additional authentication type](https://matrix.org/docs/spec/client_server/r0.6.0#authentication-types) +of `m.login.sso` is added to the user-interactive authentication specification. + +There are no additional parameters as part of this authentication type. As per +the user-interactive authentication specification, the only parameter included in +the `auth` dictionary should be the session ID from the homeserver, e.g.: + +```json +{ + "auth": { + "session": "" + } +} +``` + +### Detailed fallback authentication flow: + +The following is a re-iteration of the [fallback authentication flow](https://matrix.org/docs/spec/client_server/r0.6.0#fallback), +but with details filled in for the proposed new authentication type. + +When choosing this authentication flow, the following should occur: + +1. If the client wants to complete authentication using SSO, it opens a browser + window for `/_matrix/client/r0/auth/m.login.sso/fallback/web?session=<...>` + with session set to the UI-Auth session id (from the "auth" dict). + + The homeserver returns a page which asks for the user's confirmation before + proceeding. See the security considerations section below for why this is + necessary. For example, the page could say words to the effect of: + + > A client is trying to remove a device/add an email address/take over your + > account. To confirm this action, **re-authenticate with single sign-on**. + > If you did not expect this, your account may be compromised! +2. The link, once the user clicks on it, goes to the SSO provider's page. +3. The SSO provider validates the user, and redirects the browser back to the + homeserver. +4. The homeserver validates the response from the SSO provider, updates the + user-interactive auth session to show that the SSO has completed, and + [serves the fallback auth completion page as specced](https://matrix.org/docs/spec/client_server/r0.6.0#fallback). +5. The client resubmits its original request, with its original session id, + which now should complete. + +Note that the post-SSO URL on the homeserver is left up to the homeserver +implementation rather than forming part of the specification, choices might be +limited by the chosen SSO implementation, for example: + +* SAML2 servers typically only support one URL per service provider, so in + practice it will need to be the same as that already used for the login flow + (for synapse, it's `/_matrix/saml2/authn_response`) - and the server needs to + be able to figure out if it's doing SSO for a login attempt or an SSO + attempt. +* CAS doesn't have the same restriction. + +### Example flow: + +A more complete example is provided below in which a user attempts to delete +a device and is pushed into the user interactive authentication process with +SSO being the only possible flow. + +0. Client submits the request, which the server says requires SSO: + + ``` + POST /_matrix/client/r0/delete_devices HTTP/1.1 + Content-Type: application/json + Authorization: Bearer xyzzy + + { + "devices": ["FSVVTZRRAA"] + } + + HTTP/1.1 401 Unauthorized + Content-Type: application/json + + { + "flows": [ + { + "stages": [ + "m.login.sso" + ] + } + ], + "params": {}, + "session": "dTKfsLHSAJeAhqfxUsvrIVJd" + } + ``` + +1. Client opens a browser window for the fallback endpoint: + + ``` + GET /_matrix/client/r0/auth/m.login.sso/fallback/web + ?session=dTKfsLHSAJeAhqfxUsvrIVJd HTTP/1.1 + + HTTP/1.1 200 OK + + + A client is trying to remove a device from your account. To confirm this + action, re-authenticate with single sign-on. + If you did not expect this, your account may be compromised! + + ``` + +2. The user clicks the confirmation link which goes to the SSO provider's site: + + ``` + GET https://sso_provider/validate?SAMLRequest= HTTP/1.1 + + + ``` + +3. The SSO provider validates the user and ends up redirecting the browser back + to the homeserver. The example below shows a 302 for simplicity, this might + vary based on SSO implementation. + + ``` + HTTP/1.1 302 Moved + Location: https://homeserver/_matrix/saml2/authn_response? + SAMLResponse= + ``` + +4. The browser sends the SSO response to the homeserver, which validates it and + shows the fallback auth completion page: + + ``` + GET /_matrix/saml2/authn_response?SAMLResponse= + + + HTTP/1.1 200 OK + + + +

Thank you.

+

You may now close this window and return to the application.

+ ``` + +5. The client closes the browser popup if it is still open, and resubmits its + original request, which now succeeds: + + ``` + POST /_matrix/client/r0/delete_devices HTTP/1.1 + Content-Type: application/json + Authorization: Bearer xyzzy + + { + "auth": { + "session": "dTKfsLHSAJeAhqfxUsvrIVJd" + } + } + + HTTP/1.1 200 OK + Content-Type: application/json + + {} + ``` + +## Alternatives + +An alternative client flow where the fallback auth ends up redirecting to a +given URI, instead of doing JavaScript `postMessage` foo could be considered. +This is probably an orthogonal change to the fallback auth though. + +## Security considerations + +### Why we need user to confirm before the SSO flow + +Recall that the thing we are trying to guard against here is a single leaked +access-token being used to take over an entire account. So let's assume the +attacker has got hold of an access token for your account. What happens if the +confirmation step is skipped? + +The attacker, who has your access token, starts a UI Authentication session to +add their email address to your account. + +They then sends you a link "hey, check out this cool video!"; the link leads (via +an innocent-looking URL shortener or some other phishing technique) to +`/_matrix/client/r0/auth/m.login.sso/fallback/web?session=<...>`, with the ID of +the session that he just created. + +Since there is no confirmation step, the server redirects directly to the SSO +provider. + +It's common for SSO providers to redirect straight back to the app if you've +recently authenticated with them; even in the best case, the SSO provider shows +an innocent message along the lines of "Confirm that you want to sign in to +\". + +After redirecting back to the homeserver, the SSO is completed and the +attacker's session is validated. They are now able to make their malicious +change to your account. + +This problem can be mitigated by clearly telling the user what is about to happen. + +### Reusing User Interactive Authentication sessions + +The security of this relies on User Interactive Authentication sessions only +being used for the same request as they were initiated for. This security is not +only a concern for the proposed SSO authentication type. It is not believed +that this is currently enforced in implementations. + +## Unstable prefix + +A vendor prefix of `org.matrix.login.sso` is proposed (instead of `m.login.sso`) +until this is part of the specification. diff --git a/proposals/2457-password-modification-invalidating-devices.md b/proposals/2457-password-modification-invalidating-devices.md new file mode 100644 index 00000000..ccde2ac6 --- /dev/null +++ b/proposals/2457-password-modification-invalidating-devices.md @@ -0,0 +1,56 @@ +# Invalidating devices during password modification + +There are multiple use cases for why a user might want to modify their password: + +* Adopting a password manager (to use a unique password or more secure password). +* Password rotation. +* Re-secure a compromised account. +* ... probably tons of others ... + +These can be summarized into two groups: + +1. "My account has been compromised and I need to re-secure it." +2. "I just want to change my password." + +The [current Matrix specification](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-password) +does not provide a way to differentiate between these use cases. It currently +specifies behavior that fits well into the first use-case above: that the +sessions except the current session should be revoked. + +It is reasonable for a client to want to specify this behavior to offer two +different workflows: + +1. Modify a password and log all other devices out (for use when an account has + been compromised). +2. Modify a password and do not touch any session data (for use in a + non-malicious situations). + +Alternately a client may default to whichever workflow is best for their users. + +## Proposal + +An optional field is added to the JSON body of the [password reset endpoint](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-password) +called `logout_devices`. This is a boolean flag (defaulting to `true`) that +signals to whether other devices and sessions should be invalidated after +modifying the password. + +## Potential issues + +The specification states: + +> The homeserver SHOULD NOT revoke the access token provided in the request, +> however all other access tokens for the user should be revoked if the request +> succeeds. + +Defaulting `logout_devices` to `true` should be backwards compatible. + +## Alternatives + +A new endpoint could be provided in a future version of the specification that +supports an additional field (as described above). + +## Security considerations + +By defaulting to invalidating devices and sessions the security considerations +of this endpoint should remain intact. A client will need to be modified to +choose to keep other devices active. diff --git a/proposals/2472-symmetric-ssss.md b/proposals/2472-symmetric-ssss.md new file mode 100644 index 00000000..7fe9f179 --- /dev/null +++ b/proposals/2472-symmetric-ssss.md @@ -0,0 +1,88 @@ +# Symmetric SSSS + +[MSC1946 (Secure Secret Storage and +Sharing)](https://github.com/matrix-org/matrix-doc/pull/1946) proposed a way of +storing encrypted secrets on the server. In the proposal, secrets were +encrypted using a Curve25519 key, which was chosen to allow easier migration +from key backups that we created before the backup key was stored using it. + +However this does not provide any guarantees that data stored using the +proposal came from a trusted source. To remedy this, we propose to change the +encryption to use AES with a MAC to ensure that only someone who knows the key +is able to store data. + +## Proposal + +* The `m.secret_storage.v1.curve25519-aes-sha2` method proposed in MSC1946 is + removed. + +* A new method, `m.secret_storage.v1.aes-hmac-sha2`, is added. With this + method, the Secret Storage key may be any size (though 256 bits is + recommended), and data is encrypted as follows: + + 1. Given the secret storage key, generate 64 bytes by performing an HKDF with + SHA-256 as the hash, a salt of 32 bytes of 0, and with the secret name as + the info. The first 32 bytes are used as the AES key, and the next 32 bytes + are used as the MAC key + 2. Generate 16 random bytes, set bit 63 to 0 (in order to work around + differences in AES-CTR implementations), and use this as the AES + initialization vector. This becomes the `iv` property, encoded using base64. + 3. Encrypt the data using AES-CTR-256 using the AES key generated above. This + encrypted data, encoded using base64, becomes the `ciphertext` property. + 4. Pass the raw encrypted data (prior to base64 encoding) through HMAC-SHA-256 + using the MAC key generated above. The resulting MAC is base64-encoded and + becomes the `mac` property. + + (We use AES-CTR to match file encryption and key exports.) + + If the key Secret Storage key is generated from a passphrase, information + about how to generate the key is stored in the `passphrase` property of the + key's account-data in a similar manner to what was done with the original + `m.secret_storage.v1.curve25519-aes-sha2` method, except that there is an + optional `bits` parameter that defaults to 256, and indicates the number of + bits that should be generated from PBKDF2 (in other words, the size of the + key). + +* For the purposes of allowing clients to check whether a user has correctly + entered the key, clients should: + + 1. encrypt and MAC a message consisting of 32 bytes of 0 as described above, + using the empty string as the info parameter to the HKDF in step 1. + 2. store the `iv` and `mac` in the `m.secret_storage.key.[key ID]` + account-data. + +* The `passthrough` property specified in the "Enconding the recovery key for + server-side storage via MSC1946" section of MSC1219 is removed. The primary + purpose of that property was to allow easy migration of pre-MSC1946 backups, + so that users could reuse the backup recovery key as the Secret Storage key + without needing to re-enter the recovery key. However, since we are now + using a symmetric encryption algorithm, the client needs to know the key that + is used to encrypt, so the purpose of the field cannot be fulfilled. + +* Signing the Secret Storage key with the user's master cross-signing key is no + longer required. The key is trusted on the basis of the user entering the + key/passphrase. + + +## Potential issues + +Users who have data stored using the old encryption algorithm will need their +data migrated. Clients that support the old algorithm but not the new +algorithm will not be able to use the migrated secrets until they are updated +with the new algorithms. This should not be a major problem because the only +clients that are known to have implemented the old algorithm are Riot +Web/Android/iOS, and they have been upgraded to implement the new algorithm. + + +## Alternatives + +Rather than switching to a symmetric encryption algorithm, we could stay with +an asymmetric encryption algorithm, and add on a method to authenticate the +data. However, it is much safer to use well-known cryptographic methods rather +than trying to invent something new. Since the main reason for using an +asymmetric scheme was to ease migration from older key backups without +requiring the user to re-enter the key, but this is no longer possible due to +the need to authenticate the data using the Secret Storage key, there is no +reason to stay with an asymmetric algorithm. It is also better to use +cryptographic methods already used in Matrix where possible, rather than +introducing something new. diff --git a/proposals/2526-add-delete-backup.md b/proposals/2526-add-delete-backup.md new file mode 100644 index 00000000..b41fe5a3 --- /dev/null +++ b/proposals/2526-add-delete-backup.md @@ -0,0 +1,14 @@ +# MSC2526: Add ability to delete key backups + +[MSC1219](https://github.com/matrix-org/matrix-doc/issues/1219) defined a +mechanism for key backups. However, it inadvertently omitted the endpoint to +delete an entire key backup. This proposal adds the endpoint. + +## Proposal + +An endpoint is added, `DELETE /room_keys/version/{version}`, that deletes a +backup version. Both the information about the key backup, as well as all keys +associated with the backup should be deleted. If the specified version was +previously deleted, the endpoint succeeds, returning an HTTP code of 200. If +the specified version never existed, the endpoint returns an HTTP code of 404 +with a Matrix `errcode` of `M_NOT_FOUND`. diff --git a/proposals/2540-stricter-event-validation.md b/proposals/2540-stricter-event-validation.md new file mode 100644 index 00000000..31c4c39b --- /dev/null +++ b/proposals/2540-stricter-event-validation.md @@ -0,0 +1,65 @@ +# MSC2540: Stricter event validation: JSON compliance + +## Background + +There has been [prior discussions](https://github.com/matrix-org/matrix-doc/issues/1646) +about validating events more strictly. This MSC proposes fixing a small piece of +this: JSON compliance. + +The [Canonical JSON](https://matrix.org/docs/spec/appendices#canonical-json) +specification requires that numbers that are serialized in JSON are integers in +the inclusive range of `[-(2^53) + 1, (2^53) - 1]`, which matches the requirements of +[section 6 of RFC 7159](https://tools.ietf.org/html/rfc7159). Note that it is +not explicit, but all floats are invalid. + +It is worth mentioning that there are common extensions to JSON which produce +invalid JSON according to the Matrix specification; some programming langauges +even support these by default. One common additional feature is handling +"special" float values: `Infinity`, `-Infinity`, and `NaN`. + + +## Proposal + +In a future room version, homeserver implementations are to strictly enforce +the JSON compliance of the Canonical JSON specification for events. +Non-compliant events should be treated like any other malformed event, +for example by rejecting the request with an HTTP 400 error with `M_BAD_JSON`, +or by discarding the event. + +The rationale for doing this in a future room version is to avoid a split brain +room -- where some federated servers believe an event is valid and others reject +it as invalid. Rooms will be able to opt into this behavior as part of a room +version upgrade. + +Homeserver implementations are not to strictly enforce this JSON compliance in +[room versions 1, 2, 3, 4, and 5](https://matrix.org/docs/spec/#complete-list-of-room-versions). +The rationale is essentially the same as why a future room version is necessary: +this ensures that all federated servers treat the same events as valid. + + +## Potential issues + +Homeserver implementations might include JSON parsers which are stricter than +others. It may not be worthwhile or reasonable to loosen those restrictions for +stable room versions. + + +## Alternatives + +It could be argued that this MSC is unnecessary since it does not add any new +requirements for handling of JSON data. Unfortunately starting to enforce these +requirements in current rooms could cause federation to break as homeservers +will disagree on whether events are valid. + + +## Security considerations + +N/A + + +## Unstable prefix + +A room version of `org.matrix.strict_canonicaljson` until a future room version +is available. This room version will use +[room version 5](https://matrix.org/docs/spec/rooms/v5) as base and include the +above modifications. diff --git a/scripts/css/pygments.css b/scripts/css/pygments.css new file mode 100644 index 00000000..a212151a --- /dev/null +++ b/scripts/css/pygments.css @@ -0,0 +1,83 @@ +/* +Original styles generated from: + pygmentize -f html -S colorful -a pre.code > ./scripts/css/pygments.css + +Rules for which we don't want the syntax highlighter to kick in are commented +out at the bottom. + +Windows users: if you regenerate this file, you'll need to re-save it as utf-8 +to make docutils happy. +*/ + +/* DIFFS */ +pre.code .gd { color: #A00000 } /* Generic.Deleted */ +pre.code .gi { color: #00A000 } /* Generic.Inserted */ + +/* UNUSED */ +/*pre.code .hll { background-color: #ffffcc }*/ +/*pre.code { background: #ffffff; }*/ +/*pre.code .c { color: #888888 } !* Comment *!*/ +/*pre.code .err { color: #FF0000; background-color: #FFAAAA } !* Error *!*/ +/*pre.code .k { color: #008800; font-weight: bold } !* Keyword *!*/ +/*pre.code .o { color: #333333 } !* Operator *!*/ +/*pre.code .ch { color: #888888 } !* Comment.Hashbang *!*/ +/*pre.code .cm { color: #888888 } !* Comment.Multiline *!*/ +/*pre.code .cp { color: #557799 } !* Comment.Preproc *!*/ +/*pre.code .cpf { color: #888888 } !* Comment.PreprocFile *!*/ +/*pre.code .c1 { color: #888888 } !* Comment.Single *!*/ +/*pre.code .cs { color: #cc0000; font-weight: bold } !* Comment.Special *!*/ +/*pre.code .ge { font-style: italic } !* Generic.Emph *!*/ +/*pre.code .gr { color: #FF0000 } !* Generic.Error *!*/ +/*pre.code .gh { color: #000080; font-weight: bold } !* Generic.Heading *!*/ +/*pre.code .go { color: #888888 } !* Generic.Output *!*/ +/*pre.code .gp { color: #c65d09; font-weight: bold } !* Generic.Prompt *!*/ +/*pre.code .gs { font-weight: bold } !* Generic.Strong *!*/ +/*pre.code .gu { color: #800080; font-weight: bold } !* Generic.Subheading *!*/ +/*pre.code .gt { color: #0044DD } !* Generic.Traceback *!*/ +/*pre.code .kc { color: #008800; font-weight: bold } !* Keyword.Constant *!*/ +/*pre.code .kd { color: #008800; font-weight: bold } !* Keyword.Declaration *!*/ +/*pre.code .kn { color: #008800; font-weight: bold } !* Keyword.Namespace *!*/ +/*pre.code .kp { color: #003388; font-weight: bold } !* Keyword.Pseudo *!*/ +/*pre.code .kr { color: #008800; font-weight: bold } !* Keyword.Reserved *!*/ +/*pre.code .kt { color: #333399; font-weight: bold } !* Keyword.Type *!*/ +/*pre.code .m { color: #6600EE; font-weight: bold } !* Literal.Number *!*/ +/*pre.code .s { background-color: #fff0f0 } !* Literal.String *!*/ +/*pre.code .na { color: #0000CC } !* Name.Attribute *!*/ +/*pre.code .nb { color: #007020 } !* Name.Builtin *!*/ +/*pre.code .nc { color: #BB0066; font-weight: bold } !* Name.Class *!*/ +/*pre.code .no { color: #003366; font-weight: bold } !* Name.Constant *!*/ +/*pre.code .nd { color: #555555; font-weight: bold } !* Name.Decorator *!*/ +/*pre.code .ni { color: #880000; font-weight: bold } !* Name.Entity *!*/ +/*pre.code .ne { color: #FF0000; font-weight: bold } !* Name.Exception *!*/ +/*pre.code .nf { color: #0066BB; font-weight: bold } !* Name.Function *!*/ +/*pre.code .nl { color: #997700; font-weight: bold } !* Name.Label *!*/ +/*pre.code .nn { color: #0e84b5; font-weight: bold } !* Name.Namespace *!*/ +/*pre.code .nt { color: #007700 } !* Name.Tag *!*/ +/*pre.code .nv { color: #996633 } !* Name.Variable *!*/ +/*pre.code .ow { color: #000000; font-weight: bold } !* Operator.Word *!*/ +/*pre.code .w { color: #bbbbbb } !* Text.Whitespace *!*/ +/*pre.code .mb { color: #6600EE; font-weight: bold } !* Literal.Number.Bin *!*/ +/*pre.code .mf { color: #6600EE; font-weight: bold } !* Literal.Number.Float *!*/ +/*pre.code .mh { color: #005588; font-weight: bold } !* Literal.Number.Hex *!*/ +/*pre.code .mi { color: #0000DD; font-weight: bold } !* Literal.Number.Integer *!*/ +/*pre.code .mo { color: #4400EE; font-weight: bold } !* Literal.Number.Oct *!*/ +/*pre.code .sa { background-color: #fff0f0 } !* Literal.String.Affix *!*/ +/*pre.code .sb { background-color: #fff0f0 } !* Literal.String.Backtick *!*/ +/*pre.code .sc { color: #0044DD } !* Literal.String.Char *!*/ +/*pre.code .dl { background-color: #fff0f0 } !* Literal.String.Delimiter *!*/ +/*pre.code .sd { color: #DD4422 } !* Literal.String.Doc *!*/ +/*pre.code .s2 { background-color: #fff0f0 } !* Literal.String.Double *!*/ +/*pre.code .se { color: #666666; font-weight: bold; background-color: #fff0f0 } !* Literal.String.Escape *!*/ +/*pre.code .sh { background-color: #fff0f0 } !* Literal.String.Heredoc *!*/ +/*pre.code .si { background-color: #eeeeee } !* Literal.String.Interpol *!*/ +/*pre.code .sx { color: #DD2200; background-color: #fff0f0 } !* Literal.String.Other *!*/ +/*pre.code .sr { color: #000000; background-color: #fff0ff } !* Literal.String.Regex *!*/ +/*pre.code .s1 { background-color: #fff0f0 } !* Literal.String.Single *!*/ +/*pre.code .ss { color: #AA6600 } !* Literal.String.Symbol *!*/ +/*pre.code .bp { color: #007020 } !* Name.Builtin.Pseudo *!*/ +/*pre.code .fm { color: #0066BB; font-weight: bold } !* Name.Function.Magic *!*/ +/*pre.code .vc { color: #336699 } !* Name.Variable.Class *!*/ +/*pre.code .vg { color: #dd7700; font-weight: bold } !* Name.Variable.Global *!*/ +/*pre.code .vi { color: #3333BB } !* Name.Variable.Instance *!*/ +/*pre.code .vm { color: #996633 } !* Name.Variable.Magic *!*/ +/*pre.code .il { color: #0000DD; font-weight: bold } !* Literal.Number.Integer.Long *!*/ diff --git a/scripts/gendoc.py b/scripts/gendoc.py index 72e3047c..7e68ccd7 100755 --- a/scripts/gendoc.py +++ b/scripts/gendoc.py @@ -273,6 +273,7 @@ def rst2html(i, o, stylesheets): writer_name="html", settings_overrides={ "stylesheet_path": stylesheets, + "syntax_highlight": "short", }, ) diff --git a/scripts/templating/matrix_templates/units.py b/scripts/templating/matrix_templates/units.py index 9d2c69f2..5a7ff94e 100644 --- a/scripts/templating/matrix_templates/units.py +++ b/scripts/templating/matrix_templates/units.py @@ -213,6 +213,7 @@ def get_json_schema_object_fields(obj, enforce_title=False): res = process_data_type(additionalProps) tables = res["tables"] val_title = res["title"] + gen_title = "{%s: %s}" % (key_type, val_title) if res.get("enum_desc") and val_title != "enum": # A map to enum needs another table with enum description tables.append(TypeTable( @@ -220,7 +221,7 @@ def get_json_schema_object_fields(obj, enforce_title=False): rows=[TypeTableRow(key="(mapped value)", title="enum", desc=res["desc"])] )) return { - "title": "{%s: %s}" % (key_type, val_title), + "title": obj_title if obj_title else gen_title, "tables": tables, } diff --git a/specification/appendices/identifier_grammar.rst b/specification/appendices/identifier_grammar.rst index 4cce1f90..95c22fb1 100644 --- a/specification/appendices/identifier_grammar.rst +++ b/specification/appendices/identifier_grammar.rst @@ -45,7 +45,7 @@ following grammar:: IPv6char = DIGIT / %x41-46 / %x61-66 / ":" / "." ; 0-9, A-F, a-f, :, . - dns-name = *255dns-char + dns-name = 1*255dns-char dns-char = DIGIT / ALPHA / "-" / "." diff --git a/specification/appendices/signing_json.rst b/specification/appendices/signing_json.rst index 8036950e..fbeb0010 100644 --- a/specification/appendices/signing_json.rst +++ b/specification/appendices/signing_json.rst @@ -39,6 +39,17 @@ range where they can be accurately represented using IEEE double precision floating point numbers since a number of JSON libraries represent all numbers using this representation. +.. WARNING:: + Events in room versions 1, 2, 3, 4, and 5 might not be fully compliant with + these restrictions. Servers SHOULD be capable of handling JSON which is considered + invalid by these restrictions where possible. + + The most notable consideration is that integers might not be in the range + specified above. + +.. Note:: + Float values are not permitted by this encoding. + .. code:: python import json diff --git a/specification/client_server_api.rst b/specification/client_server_api.rst index eb32d3b4..574999be 100644 --- a/specification/client_server_api.rst +++ b/specification/client_server_api.rst @@ -45,6 +45,7 @@ Other versions of this specification The following other versions are also available, in reverse chronological order: - `HEAD `_: Includes all changes since the latest versioned release. +- `r0.6.1 `_ - `r0.6.0 `_ - `r0.5.0 `_ - `r0.4.0 `_ @@ -123,6 +124,10 @@ The common error codes are: :``M_UNKNOWN_TOKEN``: The access token specified was not recognised. + An additional response parameter, ``soft_logout``, might be present on the response + for 401 HTTP status codes. See `the soft logout section <#soft-logout>`_ for more + information. + :``M_MISSING_TOKEN``: No access token was specified for the request. @@ -404,6 +409,22 @@ should pass the ``device_id`` in the request body. If the client sets the to that device. There is therefore at most one active access token assigned to each device at any one time. +Soft logout +~~~~~~~~~~~ + +When a request fails due to a 401 status code per above, the server can +include an extra response parameter, ``soft_logout``, to indicate if the client's +persisted information can be retained. This defaults to ``false``, indicating +that the server has destroyed the session. Any persisted state held by the client, +such as encryption keys and device information, must not be reused and must be discarded. + +When ``soft_logout`` is true, the client can acquire a new access token by +specifying the device ID it is already using to the login API. In most cases +a ``soft_logout: true`` response indicates that the user's session has expired +on the server-side and the user simply needs to provide their credentials again. + +In either case, the client's previously known access token will no longer function. + User-Interactive Authentication API ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -643,6 +664,7 @@ This specification defines the following auth types: - ``m.login.password`` - ``m.login.recaptcha`` - ``m.login.oauth2`` + - ``m.login.sso`` - ``m.login.email.identity`` - ``m.login.msisdn`` - ``m.login.token`` @@ -782,6 +804,38 @@ the auth code. Homeservers can choose any path for the ``redirect URI``. Once the OAuth flow has completed, the client retries the request with the session only, as above. +Single Sign-On +<<<<<<<<<<<<<< +:Type: + ``m.login.sso`` +:Description: + Authentication is supported by authorising with an external single sign-on + provider. + +A client wanting to complete authentication using SSO should use the +`Fallback`_ authentication flow by opening a browser window for +``/_matrix/client/r0/auth/m.login.sso/fallback/web?session=<...>`` with the +session parameter set to the session ID provided by the server. + +The homeserver should return a page which asks for the user's confirmation +before proceeding. For example, the page could say words to the effect of: + + A client is trying to remove a device/add an email address/take over your + account. To confirm this action, re-authenticate with single sign-on. If you + did not expect this, your account may be compromised! + +Once the user has confirmed they should be redirected to the single sign-on +provider's login page. Once the provider has validated the user, the browser is +redirected back to the homeserver. + +The homeserver then validates the response from the single sign-on provider and +updates the user-interactive authentication session to mark the single sign-on +stage has been completed. The browser is shown the fallback authentication +completion page. + +Once the flow has completed, the client retries the request with the session +only, as above. + Email-based (identity / homeserver) <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< :Type: @@ -1561,8 +1615,6 @@ Room Events This specification outlines several standard event types, all of which are prefixed with ``m.`` -{{m_room_aliases_event}} - {{m_room_canonical_alias_event}} {{m_room_create_event}} @@ -1575,6 +1627,15 @@ prefixed with ``m.`` {{m_room_redaction_event}} +Historical events ++++++++++++++++++ + +Some events within the ``m.`` namespace might appear in rooms, however they +serve no significant meaning in this version of the specification. They are: + +* ``m.room.aliases`` + +Previous versions of the specification have more information on these events. Syncing ~~~~~~~ @@ -1746,39 +1807,7 @@ redacted include a ``redacted_because`` key whose value is the event that caused it to be redacted, which may include a reason. -Upon receipt of a redaction event, the server should strip off any keys not in -the following list: - -- ``event_id`` -- ``type`` -- ``room_id`` -- ``sender`` -- ``state_key`` -- ``content`` -- ``hashes`` -- ``signatures`` -- ``depth`` -- ``prev_events`` -- ``prev_state`` -- ``auth_events`` -- ``origin`` -- ``origin_server_ts`` -- ``membership`` - -.. Note: - Some of the keys, such as ``hashes``, will appear on the federation-formatted - event and therefore the client may not be aware of them. - -The content object should also be stripped of all keys, unless it is one of -one of the following event types: - -- ``m.room.member`` allows key ``membership``. -- ``m.room.create`` allows key ``creator``. -- ``m.room.join_rules`` allows key ``join_rule``. -- ``m.room.power_levels`` allows keys ``ban``, ``events``, ``events_default``, - ``kick``, ``redact``, ``state_default``, ``users``, ``users_default``. -- ``m.room.aliases`` allows key ``aliases``. -- ``m.room.history_visibility`` allows key ``history_visibility``. +The exact algorithm to apply against an event is defined in the `room version specification`_. The server should add the event causing the redaction to the ``unsigned`` property of the redacted event, under the ``redacted_because`` key. When a @@ -1838,15 +1867,15 @@ send update requests to other servers. However, homeservers MUST handle ``GET`` requests to resolve aliases on other servers; they should do this using the federation API if necessary. -Rooms store a *partial* list of room aliases via the ``m.room.aliases`` state -event. This alias list is partial because it cannot guarantee that the alias -list is in any way accurate or up-to-date, as room aliases can point to -different room IDs over time. Crucially, the aliases in this event are -**purely informational** and SHOULD NOT be treated as accurate. They SHOULD -be checked before they are used or shared with another user. If a room -appears to have a room alias of ``#alias:example.com``, this SHOULD be checked -to make sure that the room's ID matches the ``room_id`` returned from the -request. +Rooms do not store a list of all aliases present on a room, though members +of the room with relevant permissions may publish preferred aliases through +the ``m.room.canonical_alias`` state event. The aliases in the state event +should point to the room ID they are published within, however room aliases +can and do drift to other room IDs over time. Clients SHOULD NOT treat the +aliases as accurate. They SHOULD be checked before they are used or shared +with another user. If a room appears to have a room alias of ``#alias:example.com``, +this SHOULD be checked to make sure that the room's ID matches the ``room_id`` +returned from the request. {{directory_cs_http_api}} diff --git a/specification/index.rst b/specification/index.rst index 728383ab..aa8a4641 100644 --- a/specification/index.rst +++ b/specification/index.rst @@ -550,6 +550,7 @@ The available room versions are: * `Version 3 `_ - **Stable**. Introduces events whose IDs are the event's hash. * `Version 4 `_ - **Stable**. Builds on v3 by using URL-safe base64 for event IDs. * `Version 5 `_ - **Stable**. Introduces enforcement of signing key validity periods. +* `Version 6 `_ - **Stable**. Alters several authorization rules for events. Specification Versions ---------------------- diff --git a/specification/modules/end_to_end_encryption.rst b/specification/modules/end_to_end_encryption.rst index 1dda3375..acd05411 100644 --- a/specification/modules/end_to_end_encryption.rst +++ b/specification/modules/end_to_end_encryption.rst @@ -83,9 +83,23 @@ Base64`_. Example: "JGLn/yafz74HB2AbPLYJWIVGnKAtqECOBf11yyXac2Y" The name ``signed_curve25519`` also corresponds to the Curve25519 algorithm, -but keys using this algorithm are objects with the properties ``key`` (giving -the Base64-encoded 32-byte Curve25519 public key), and ``signatures`` (giving a -signature for the key object, as described in `Signing JSON`_). Example: +but a key using this algorithm is represented by an object with a the following +properties: + +``KeyObject`` + +========== ================ ===================================================== +Parameter Type Description +========== ================ ===================================================== +key string **Required.** The unpadded Base64-encoded 32-byte + Curve25519 public key. +signatures Signatures **Required.** Signatures of the key object. + + The signature is calculated using the process described + at `Signing JSON`_. +========== ================ ===================================================== + +Example: .. code:: json @@ -513,7 +527,7 @@ received the other party's part. Thus an attacker essentially only has one attem attack the Diffie-Hellman exchange, and hence we can verify fewer bits while still achieving a high degree of security: if we verify n bits, then an attacker has a 1 in 2\ :sup:`n` chance of success. For example, if we verify 40 bits, then an attacker has -a 1 in 1,099,511,627,776 chance (or less than 1 in 1012 chance) of success. A failed +a 1 in 1,099,511,627,776 chance (or less than 1 in 10\ :sup:`12` chance) of success. A failed attack would result in a mismatched Short Authentication String, alerting users to the attack. @@ -565,9 +579,9 @@ The process between Alice and Bob verifying each other would be: they match or not. #. Assuming they match, Alice and Bob's devices calculate the HMAC of their own device keys and a comma-separated sorted list of of the key IDs that they wish the other user - to verify, using SHA-256 as the hash function. HMAC is defined in [RFC 2104](https://tools.ietf.org/html/rfc2104). + to verify, using SHA-256 as the hash function. HMAC is defined in `RFC 2104 `_. The key for the HMAC is different for each item and is calculated by generating - 32 bytes (256 bits) using `the key verification HKDF <#SAS-HKDF>`_. + 32 bytes (256 bits) using `the key verification HKDF <#sas-hkdf>`_. #. Alice's device sends Bob's device a ``m.key.verification.mac`` message containing the MAC of Alice's device keys and the MAC of her key IDs to be verified. Bob's device does the same for Bob's device keys and key IDs concurrently with Alice. @@ -653,14 +667,14 @@ are used in addition to those already specified: {{m_key_verification_mac_event}} -.. _`SAS-HKDF`: +.. _sas-hkdf: HKDF calculation <<<<<<<<<<<<<<<< -In all of the SAS methods, HKDF is as defined in [RFC 5869](https://tools.ietf.org/html/rfc5869) +In all of the SAS methods, HKDF is as defined in `RFC 5869 `_ and uses the previously agreed-upon hash function for the hash function. The shared -secret is supplied as the input keying material. No salt is used, and the input +secret is supplied as the input keying material. No salt is used, and the info parameter is the concatenation of: * The string ``MATRIX_KEY_VERIFICATION_SAS``. @@ -677,7 +691,7 @@ parameter is the concatenation of: For verification of each party's device keys, HKDF is as defined in RFC 5869 and uses SHA-256 as the hash function. The shared secret is supplied as the input keying -material. No salt is used, and in the input parameter is the concatenation of: +material. No salt is used, and in the info parameter is the concatenation of: * The string ``MATRIX_KEY_VERIFICATION_MAC``. * The Matrix ID of the user whose key is being MAC-ed. @@ -691,7 +705,7 @@ material. No salt is used, and in the input parameter is the concatenation of: SAS method: ``decimal`` <<<<<<<<<<<<<<<<<<<<<<< -Generate 5 bytes using `HKDF <#SAS-HKDF>`_ then take sequences of 13 bits to +Generate 5 bytes using `HKDF <#sas-hkdf>`_ then take sequences of 13 bits to convert to decimal numbers (resulting in 3 numbers between 0 and 8191 inclusive each). Add 1000 to each calculated number. @@ -708,7 +722,7 @@ such as dashes, or with the numbers on individual lines. SAS method: ``emoji`` <<<<<<<<<<<<<<<<<<<<< -Generate 6 bytes using `HKDF <#SAS-HKDF>`_ then split the first 42 bits into +Generate 6 bytes using `HKDF <#sas-hkdf>`_ then split the first 42 bits into 7 groups of 6 bits, similar to how one would base64 encode something. Convert each group of 6 bits to a number and use the following table to get the corresponding emoji: diff --git a/specification/modules/instant_messaging.rst b/specification/modules/instant_messaging.rst index 679eabdc..705fd2d9 100644 --- a/specification/modules/instant_messaging.rst +++ b/specification/modules/instant_messaging.rst @@ -275,13 +275,9 @@ choose a name: 1. If the room has an `m.room.name`_ state event with a non-empty ``name`` field, use the name given by that field. -#. If the room has an `m.room.canonical_alias`_ state event with a non-empty - ``alias`` field, use the alias given by that field as the name. - -#. If neither of the above conditions are met, the client can optionally guess - an alias from the ``m.room.alias`` events in the room. This is a temporary - measure while clients do not promote canonical aliases as prominently. This - step may be removed in a future version of the specification. +#. If the room has an `m.room.canonical_alias`_ state event with a valid + ``alias`` field, use the alias given by that field as the name. Note that + clients should avoid using ``alt_aliases`` when calculating the room name. #. If none of the above conditions are met, a name should be composed based on the members of the room. Clients should consider `m.room.member`_ events diff --git a/specification/modules/read_markers.rst b/specification/modules/read_markers.rst index a77f2013..be06d037 100644 --- a/specification/modules/read_markers.rst +++ b/specification/modules/read_markers.rst @@ -47,7 +47,7 @@ The read markers API can additionally update the user's read receipt (``m.read`` location in the same operation as setting the fully read marker location. This is because read receipts and read markers are commonly updated at the same time, and therefore the client might wish to save an extra HTTP call. Providing an -``m.read`` location performs the same task as a request to ``/receipts/m.read/$event:example.org``. +``m.read`` location performs the same task as a request to ``/receipt/m.read/$event:example.org``. {{read_markers_cs_http_api}} @@ -56,7 +56,7 @@ Server behaviour The server MUST prevent clients from setting ``m.fully_read`` directly in room account data. The server must additionally ensure that it treats the presence of ``m.read`` in the ``/read_markers`` request the same as how it -would for a request to ``/receipts/m.read/$event:example.org``. +would for a request to ``/receipt/m.read/$event:example.org``. Upon updating the ``m.fully_read`` event due to a request to ``/read_markers``, the server MUST send the updated account data event through to the client via diff --git a/specification/modules/tags.rst b/specification/modules/tags.rst index 9d0cd554..a5e23770 100644 --- a/specification/modules/tags.rst +++ b/specification/modules/tags.rst @@ -55,7 +55,7 @@ The tag namespace is defined as follows: display name directly). These non-namespaced tags are supported for historical reasons. New tags should use one of the defined namespaces above. -Two special names are listed in the specification: +Several special names are listed in the specification: The following tags are defined in the ``m.*`` namespace: * ``m.favourite``: The user's favourite rooms. These should be shown with higher precedence than other rooms. diff --git a/specification/proposals_intro.rst b/specification/proposals_intro.rst index 771d2d6a..6d8dc8a9 100644 --- a/specification/proposals_intro.rst +++ b/specification/proposals_intro.rst @@ -230,7 +230,8 @@ follows: comments and in relevant rooms on Matrix. Discussion outside of GitHub should be summarised in a comment on the PR. - When a member of the Spec Core Team believes that no new discussion points are - being made, they will propose a motion for a final comment period (FCP), + being made, and the proposal has suitable evidence of working (see `implementing a + proposal`_ below), they will propose a motion for a final comment period (FCP), along with a *disposition* of either merge, close or postpone. This FCP is provided to allow a short period of time for any invested party to provide a final objection before a major decision is made. If sufficient reasoning is @@ -371,6 +372,100 @@ though that can always change as priorities evolve. We still encourage that MSCs opened, even if not the focus for the time being, as they can still make progress and even be merged without the Spec Core Team focusing on them specifically. +Implementing a proposal +----------------------- + +As part of the proposal process the spec core team will require evidence of the MSC +working in order for it to move into FCP. This can usually be a branch/pull request +to whichever implementation of choice that proves the MSC works in practice, though +in some cases the MSC itself will be small enough to be considered proven. Where it's +unclear if a MSC will require an implementation proof, ask in `#matrix-spec:matrix.org +`_. + +Early release of a MSC/idea +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To help facilitate early releases of software dependent on a spec release, implementations +are required to use the following process to ensure that the official Matrix namespace +is not cluttered with development or testing data. + +.. Note:: + Unreleased implementations (including proofs-of-concept demonstrating that a + particular MSC works) do not have to follow this process. + +1. Have an idea for a feature. +2. Implement the feature using unstable endpoints, vendor prefixes, and unstable + feature flags as appropriate. + + * When using unstable endpoints, they MUST include a vendor prefix. For example: + ``/_matrix/client/unstable/com.example/login``. Vendor prefixes throughout Matrix + always use the Java package naming convention. The MSC for the feature should + identify which preferred vendor prefix is to be used by early adopters. + * Note that unstable namespaces do not automatically inherit endpoints from stable + namespaces: for example, the fact that ``/_matrix/client/r0/sync`` exists does + not imply that ``/_matrix/client/unstable/com.example/sync`` exists. + * If the client needs to be sure the server supports the feature, an unstable + feature flag that MUST be vendor prefixed is to be used. This kind of flag shows + up in the ``unstable_features`` section of ``/versions`` as, for example, + ``com.example.new_login``. The MSC for the feature should identify which preferred + feature flag is to be used by early adopters. + * When using this approach correctly, the implementation can ship/release the + feature at any time, so long as the implementation is able to accept the technical + debt that results from needing to provide adequate backwards and forwards + compatibility. The implementation MUST support the flag (and server-side implementation) disappearing and be + generally safe for users. Note that implementations early in the MSC review + process may also be required to provide backwards compatibility with earlier + editions of the proposal. + * If the implementation cannot support the technical debt (or if it's impossible + to provide forwards/backwards compatibility - e.g. a user authentication change + which can't be safely rolled back), the implementation should not attempt to + implement the feature and should instead wait for a spec release. + * If at any point after early release, the idea changes in a backwards-incompatible way, the feature flag should also change so that + implementations can adapt as needed. + +3. In parallel, or ahead of implementation, open an MSC and solicit review per above. +4. Before FCP can be called, the Spec Core Team will require evidence of the MSC + working as proposed. A typical example of this is an implementation of the MSC, + though the implementation does not need to be shipped anywhere and can therefore + avoid the forwards/backwards compatibility concerns mentioned here. +5. The FCP process is completed, and assuming nothing is flagged the MSC lands. +6. A spec PR is written to incorporate the changes into Matrix. +7. A spec release happens. +8. Implementations switch to using stable prefixes (e.g.: ``/r0``) if the server + supports the specification version released. If the server doesn't advertise the + specification version, but does have the feature flag, unstable prefixes should + still be used. +9. A transition period of about 2 months starts immediately after the spec release, + before implementations start to encourage other implementations to switch + to stable endpoints. For example, a server implementation should start asking + client implementations to support the stable endpoints 2 months after the spec + release, if they haven't already. The same applies in the reverse: if clients + cannot switch to stable prefixes because server implementations haven't started + supporting the new spec release, some noise should be raised in the general direction + of the implementation. + +.. Note:: + MSCs MUST still describe what the stable endpoints/feature looks like with a note + towards the bottom for what the unstable feature flag/prefixes are. For example, + a MSC would propose `/_matrix/client/r0/new/endpoint`, not `/_matrix/client/unstable/ + com.example/new/endpoint`. + +In summary: + +* Implementations MUST NOT use stable endpoints before the MSC is in the spec. This + includes NOT using stable endpoints in the period between completion of FCP and release of the spec. + passed. +* Implementations are able to ship features that are exposed to users by default before + an MSC has been merged to the spec, provided they follow the process above. +* Implementations SHOULD be wary of the technical debt they are incurring by moving faster + than the spec. +* The vendor prefix is chosen by the developer of the feature, using the Java package + naming convention. The foundation's preferred vendor prefix is `org.matrix`. +* The vendor prefixes, unstable feature flags, and unstable endpoints should be included + in the MSC, though the MSC MUST be written in a way that proposes new stable endpoints. + Typically this is solved by a small table at the bottom mapping the various values + from stable to unstable. + Proposal Tracking ----------------- diff --git a/specification/rooms/v1.rst b/specification/rooms/v1.rst index 10eee54d..a71bdfb4 100644 --- a/specification/rooms/v1.rst +++ b/specification/rooms/v1.rst @@ -1,4 +1,5 @@ .. Copyright 2017,2019 New Vector Ltd +.. Copyright 2020 The Matrix.org Foundation C.I.C. .. .. Licensed under the Apache License, Version 2.0 (the "License"); .. you may not use this file except in compliance with the License. @@ -21,13 +22,57 @@ blocks for other room versions. .. contents:: Table of Contents .. sectnum:: +Client considerations +--------------------- + +Clients may need to consider some algorithms performed by the server for their own +implementation. + +Redactions +~~~~~~~~~~ + +Upon receipt of a redaction event, the server must strip off any keys not in +the following list: + +- ``event_id`` +- ``type`` +- ``room_id`` +- ``sender`` +- ``state_key`` +- ``content`` +- ``hashes`` +- ``signatures`` +- ``depth`` +- ``prev_events`` +- ``prev_state`` +- ``auth_events`` +- ``origin`` +- ``origin_server_ts`` +- ``membership`` + +.. Note: + Some of the keys, such as ``hashes``, will appear on the federation-formatted + event and therefore the client may not be aware of them. + +The content object must also be stripped of all keys, unless it is one of +one of the following event types: + +- ``m.room.member`` allows key ``membership``. +- ``m.room.create`` allows key ``creator``. +- ``m.room.join_rules`` allows key ``join_rule``. +- ``m.room.power_levels`` allows keys ``ban``, ``events``, ``events_default``, + ``kick``, ``redact``, ``state_default``, ``users``, ``users_default``. +- ``m.room.aliases`` allows key ``aliases``. +- ``m.room.history_visibility`` allows key ``history_visibility``. + Server implementation components -------------------------------- .. WARNING:: The information contained in this section is strictly for server implementors. Applications which use the Client-Server API are generally unaffected by the - details contained here, and can safely ignore their presence. + intricacies contained here. The section above regarding client considerations + is the resource that Client-Server API use cases should reference. The algorithms defined here should only apply to version 1 rooms. Other algorithms @@ -112,7 +157,7 @@ The types of state events that affect authorization are: .. NOTE:: Power levels are inferred from defaults when not explicitly supplied. - For example, mentions of the ``sender``'s power level can also refer + For example, mentions of the ``sender``'s power level can also refer to the default power level for users in the room. The rules are as follows: @@ -250,7 +295,7 @@ The rules are as follows: #. If there is no previous ``m.room.power_levels`` event in the room, allow. #. For the keys ``users_default``, ``events_default``, - ``state_default``, ``ban``, ``redact``, ``kick``, ``invite`` check if they + ``state_default``, ``ban``, ``redact``, ``kick``, ``invite`` check if they were added, changed or removed. For each found alteration: i. If the current value is higher than the ``sender``'s current power level, @@ -258,13 +303,13 @@ The rules are as follows: #. If the new value is higher than the ``sender``'s current power level, reject. - - #. For each entry being added, changed or removed in both the ``events`` and + + #. For each entry being added, changed or removed in both the ``events`` and ``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. @@ -307,6 +352,12 @@ Events in version 1 rooms have the following structure: {{definition_ss_pdu}} +Canonical JSON +~~~~~~~~~~~~~~ + +Servers MUST NOT strictly enforce the JSON format specified in the +`appendices <../appendices.html#canonical-json>`_ for the reasons described there. + .. _`auth events selection`: ../server_server/%SERVER_RELEASE_LABEL%.html#auth-events-selection .. _`Signing Events`: ../server_server/%SERVER_RELEASE_LABEL%.html#signing-events diff --git a/specification/rooms/v6.rst b/specification/rooms/v6.rst new file mode 100644 index 00000000..e5378d0e --- /dev/null +++ b/specification/rooms/v6.rst @@ -0,0 +1,100 @@ +.. Copyright 2020 The Matrix.org Foundation C.I.C. +.. +.. Licensed under the Apache License, Version 2.0 (the "License"); +.. you may not use this file except in compliance with the License. +.. You may obtain a copy of the License at +.. +.. http://www.apache.org/licenses/LICENSE-2.0 +.. +.. Unless required by applicable law or agreed to in writing, software +.. distributed under the License is distributed on an "AS IS" BASIS, +.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +.. See the License for the specific language governing permissions and +.. limitations under the License. + +Room Version 6 +============== + +This room version builds on `version 5 `_ while changing various +authorization rules performed on events. + +.. contents:: Table of Contents +.. sectnum:: + + +Client considerations +--------------------- + +The redaction algorithm has changed from `room version 1 `_ to remove +all rules against events of type ``m.room.aliases``. Room versions 2, 3, 4, and +5 all use v1's redaction algorithm. The algorithm is otherwise unchanged. + + +Server implementation components +-------------------------------- + +.. WARNING:: + The information contained in this section is strictly for server implementors. + Applications which use the Client-Server API are generally unaffected by the + intricacies contained here. The section above regarding client considerations + is the resource that Client-Server API use cases should reference. + + +Room version 6 makes the following alterations to algorithms described in `room version 5 `_. + +Redactions +~~~~~~~~~~ + +As mentioned in the client considerations portion of this specification, all +special meaning has been removed for events of type ``m.room.aliases``. The +algorithm is otherwise unchanged. + +Authorization rules for events +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Like redactions, all rules relating specifically to events of type ``m.room.aliases`` +are removed. They must still pass authorization checks relating to state events. + +Additionally, the authorization rules for events of type ``m.room.power_levels`` +now include the content key ``notifications``. This new rule takes the place of the +rule which checks the ``events`` and ``users`` keys. + +For completeness, the changes to the auth rules can be represented as follows: + +.. code:: diff + + ... + + -If type is `m.room.aliases`: + - + - a. If event has no `state_key`, reject. + - b. If sender's domain doesn't matches `state_key`, reject. + - c. Otherwise, allow. + + ... + + If type is `m.room.power_levels`: + + ... + + - * For each entry being added, changed or removed in both the `events` and `users` keys: + + * For each entry being added, changed or removed in the `events`, `users`, and `notifications` keys: + + i. If the current value is higher than the `sender`'s current power level, reject. + + ii. If the new value is higher than the `sender`'s current power level, reject. + + ... + + +The remaining rules are the same as in `room version 3 `_ +(the last inherited room version to specify the authorization rules). + +Canonical JSON +~~~~~~~~~~~~~~ + +Servers MUST strictly enforce the JSON format specified in the +`appendices <../appendices.html#canonical-json>`_. This translates to a 400 ``M_BAD_JSON`` error +on most endpoints, or discarding of events over federation. For example, the Federation API's +``/send`` endpoint would discard the event whereas the Client Server API's ``/send/{eventType}`` +endpoint would return a ``M_BAD_JSON`` error. diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 61308a09..f9fe4703 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -80,6 +80,8 @@ Other versions of this specification The following other versions are also available, in reverse chronological order: - `HEAD `_: Includes all changes since the latest versioned release. +- `r0.1.4 `_ +- `r0.1.3 `_ - `r0.1.2 `_ - `r0.1.1 `_ - `r0.1.0 `_ @@ -291,6 +293,11 @@ Step 1 sign JSON: } } +The server names in the JSON above are the server names for each homeserver involved. Delegation from +the `server name resolution section <#resolving-server-names>`_ above do not affect +these - the server names from before delegation would take place are used. This +same condition applies throughout the request signing process. + Step 2 add Authorization header: .. code:: @@ -780,7 +787,9 @@ and responds to the joining server with the full set of state for the newly-joined room. The resident server must also send the event to other servers participating in the room. -{{joins_ss_http_api}} +{{joins_v1_ss_http_api}} + +{{joins_v2_ss_http_api}} .. TODO-spec - (paul) I don't really understand why the full auth_chain events are given @@ -817,7 +826,9 @@ signs the event and replaces the ``event_id`` with it's own. This is then sent t the resident server via ``/send_leave``. The resident server will then send the event to other servers in the room. -{{leaving_ss_http_api}} +{{leaving_v1_ss_http_api}} + +{{leaving_v2_ss_http_api}} Third-party invites ------------------- @@ -1073,8 +1084,11 @@ The following endpoint prefixes MUST be protected: * ``/_matrix/federation/v1/make_join`` * ``/_matrix/federation/v1/make_leave`` * ``/_matrix/federation/v1/send_join`` +* ``/_matrix/federation/v2/send_join`` * ``/_matrix/federation/v1/send_leave`` +* ``/_matrix/federation/v2/send_leave`` * ``/_matrix/federation/v1/invite`` +* ``/_matrix/federation/v2/invite`` * ``/_matrix/federation/v1/state`` * ``/_matrix/federation/v1/state_ids`` * ``/_matrix/federation/v1/backfill`` @@ -1252,3 +1266,4 @@ issue. .. _`Device Management module`: ../client_server/%CLIENT_RELEASE_LABEL%.html#device-management .. _`End-to-End Encryption module`: ../client_server/%CLIENT_RELEASE_LABEL%.html#end-to-end-encryption .. _`room version specification`: ../index.html#room-versions +.. _`Client-Server Key Algorithms`: ../client_server/%CLIENT_RELEASE_LABEL%.html#key-algorithms diff --git a/specification/targets.yaml b/specification/targets.yaml index 4e0b068d..5f0e32cc 100644 --- a/specification/targets.yaml +++ b/specification/targets.yaml @@ -45,6 +45,10 @@ targets: files: - rooms/v5.rst version_label: v5 + rooms@v6: # this is translated to be rooms/v6.html + files: + - rooms/v6.rst + version_label: v6 appendices: files: - appendices.rst