Merge branch 'master' into travis/spec/MSC2320-identity-versions

This commit is contained in:
Travis Ralston 2021-05-02 00:12:26 -06:00 committed by Richard van der Hoff
commit fc6aa30000
62 changed files with 1858 additions and 261 deletions

View file

@ -232,6 +232,18 @@ reserved for events defined in the Matrix specification - for instance
`m.room.message` is the event type for instant messages. Events are
usually sent in the context of a "Room".
{{% boxes/warning %}}
Event bodies are considered untrusted data. This means that any application using
Matrix must validate that the event body is of the expected shape/schema
before using the contents verbatim.
**It is not safe to assume that an event body will have all the expected
fields of the expected types.**
See [MSC2801](https://github.com/matrix-org/matrix-doc/pull/2801) for more
detail on why this assumption is unsafe.
{{% /boxes/warning %}}
### Event Graphs
Events exchanged in the context of a room are stored in a directed
@ -315,12 +327,12 @@ sent to the room `!qporfwt:matrix.org`:
Federation maintains *shared data structures* per-room between multiple
homeservers. The data is split into `message events` and `state events`.
Message events:
Message events:
These describe transient 'once-off' activity in a room such as an
instant messages, VoIP call setups, file transfers, etc. They generally
describe communication activity.
State events:
State events:
These describe updates to a given piece of persistent information
('state') related to a room, such as the room's name, topic, membership,
participating servers, etc. State is modelled as a lookup table of
@ -493,7 +505,7 @@ stable and unstable periodically for a variety of reasons, including
discovered security vulnerabilities and age.
Clients should not ask room administrators to upgrade their rooms if the
room is running a stable version. Servers SHOULD use room version 6 as
room is running a stable version. Servers SHOULD use **room version 6** as
the default room version when creating new rooms.
The available room versions are:
@ -510,10 +522,11 @@ The available room versions are:
signing key validity periods.
- [Version 6](/rooms/v6) - **Stable**. Alters several
authorization rules for events.
- [Version 7](/rooms/v7) - **Stable**. Introduces knocking.
## Specification Versions
The specification for each API is versioned in the form `rX.Y.Z`.
The specification for each API is versioned in the form `rX.Y.Z`.
- A change to `X` reflects a breaking change: a client implemented
against `r1.0.0` may need changes to work with a server which
supports (only) `r2.0.0`.

View file

@ -68,118 +68,118 @@ request being made was invalid.
The common error codes are:
`M_FORBIDDEN`
`M_FORBIDDEN`
Forbidden access, e.g. joining a room without permission, failed login.
`M_UNKNOWN_TOKEN`
`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`
`M_MISSING_TOKEN`
No access token was specified for the request.
`M_BAD_JSON`
`M_BAD_JSON`
Request contained valid JSON, but it was malformed in some way, e.g.
missing required keys, invalid values for keys.
`M_NOT_JSON`
`M_NOT_JSON`
Request did not contain valid JSON.
`M_NOT_FOUND`
`M_NOT_FOUND`
No resource was found for this request.
`M_LIMIT_EXCEEDED`
`M_LIMIT_EXCEEDED`
Too many requests have been sent in a short period of time. Wait a while
then try again.
`M_UNKNOWN`
`M_UNKNOWN`
An unknown error has occurred.
Other error codes the client might encounter are:
`M_UNRECOGNIZED`
`M_UNRECOGNIZED`
The server did not understand the request.
`M_UNAUTHORIZED`
`M_UNAUTHORIZED`
The request was not correctly authorized. Usually due to login failures.
`M_USER_DEACTIVATED`
`M_USER_DEACTIVATED`
The user ID associated with the request has been deactivated. Typically
for endpoints that prove authentication, such as `/login`.
`M_USER_IN_USE`
`M_USER_IN_USE`
Encountered when trying to register a user ID which has been taken.
`M_INVALID_USERNAME`
`M_INVALID_USERNAME`
Encountered when trying to register a user ID which is not valid.
`M_ROOM_IN_USE`
`M_ROOM_IN_USE`
Sent when the room alias given to the `createRoom` API is already in
use.
`M_INVALID_ROOM_STATE`
`M_INVALID_ROOM_STATE`
Sent when the initial state given to the `createRoom` API is invalid.
`M_THREEPID_IN_USE`
`M_THREEPID_IN_USE`
Sent when a threepid given to an API cannot be used because the same
threepid is already in use.
`M_THREEPID_NOT_FOUND`
`M_THREEPID_NOT_FOUND`
Sent when a threepid given to an API cannot be used because no record
matching the threepid was found.
`M_THREEPID_AUTH_FAILED`
`M_THREEPID_AUTH_FAILED`
Authentication could not be performed on the third party identifier.
`M_THREEPID_DENIED`
`M_THREEPID_DENIED`
The server does not permit this third party identifier. This may happen
if the server only permits, for example, email addresses from a
particular domain.
`M_SERVER_NOT_TRUSTED`
`M_SERVER_NOT_TRUSTED`
The client's request used a third party server, e.g. identity server,
that this server does not trust.
`M_UNSUPPORTED_ROOM_VERSION`
`M_UNSUPPORTED_ROOM_VERSION`
The client's request to create a room used a room version that the
server does not support.
`M_INCOMPATIBLE_ROOM_VERSION`
`M_INCOMPATIBLE_ROOM_VERSION`
The client attempted to join a room that has a version the server does
not support. Inspect the `room_version` property of the error response
for the room's version.
`M_BAD_STATE`
`M_BAD_STATE`
The state change requested cannot be performed, such as attempting to
unban a user who is not banned.
`M_GUEST_ACCESS_FORBIDDEN`
`M_GUEST_ACCESS_FORBIDDEN`
The room or resource does not permit guests to access it.
`M_CAPTCHA_NEEDED`
`M_CAPTCHA_NEEDED`
A Captcha is required to complete the request.
`M_CAPTCHA_INVALID`
`M_CAPTCHA_INVALID`
The Captcha provided did not match what was expected.
`M_MISSING_PARAM`
`M_MISSING_PARAM`
A required parameter was missing from the request.
`M_INVALID_PARAM`
`M_INVALID_PARAM`
A parameter that was specified has the wrong value. For example, the
server expected an integer and instead received a string.
`M_TOO_LARGE`
`M_TOO_LARGE`
The request or entity was too large.
`M_EXCLUSIVE`
`M_EXCLUSIVE`
The resource being requested is reserved by an application service, or
the application service making the request has not created the resource.
`M_RESOURCE_LIMIT_EXCEEDED`
`M_RESOURCE_LIMIT_EXCEEDED`
The request cannot be completed because the homeserver has reached a
resource limit imposed on it. For example, a homeserver held in a shared
hosting environment may reach a resource limit if it starts using too
@ -189,7 +189,7 @@ Typically, this error will appear on routes which attempt to modify
state (e.g.: sending messages, account data, etc) and not routes which
only read state (e.g.: `/sync`, get account data, etc).
`M_CANNOT_LEAVE_SERVER_NOTICE_ROOM`
`M_CANNOT_LEAVE_SERVER_NOTICE_ROOM`
The user is unable to reject an invite to join the server notices room.
See the [Server Notices](#server-notices) module for more information.
@ -238,23 +238,23 @@ time.
In this section, the following terms are used with specific meanings:
`PROMPT`
`PROMPT`
Retrieve the specific piece of information from the user in a way which
fits within the existing client user experience, if the client is
inclined to do so. Failure can take place instead if no good user
experience for this is possible at this point.
`IGNORE`
`IGNORE`
Stop the current auto-discovery mechanism. If no more auto-discovery
mechanisms are available, then the client may use other methods of
determining the required parameters, such as prompting the user, or
using default values.
`FAIL_PROMPT`
`FAIL_PROMPT`
Inform the user that auto-discovery failed due to invalid/empty data and
`PROMPT` for the parameter.
`FAIL_ERROR`
`FAIL_ERROR`
Inform the user that auto-discovery did not return any usable URLs. Do
not continue further with the current login process. At this point,
valid data was obtained, but no server is available to serve the client.
@ -606,7 +606,7 @@ flow with three stages will resemble the following diagram:
#### Authentication types
This specification defines the following auth types:
This specification defines the following auth types:
- `m.login.password`
- `m.login.recaptcha`
- `m.login.sso`
@ -893,7 +893,7 @@ type of identifier being used, and depending on the type, has other
fields giving the information required to identify the user as described
below.
This specification defines the following identifier types:
This specification defines the following identifier types:
- `m.id.user`
- `m.id.thirdparty`
- `m.id.phone`
@ -1381,6 +1381,18 @@ opaque string. No changes should be required to support the currently
available room versions.
{{% /boxes/warning %}}
{{% boxes/warning %}}
Event bodies are considered untrusted data. This means that any application using
Matrix must validate that the event body is of the expected shape/schema
before using the contents verbatim.
**It is not safe to assume that an event body will have all the expected
fields of the expected types.**
See [MSC2801](https://github.com/matrix-org/matrix-doc/pull/2801) for more
detail on why this assumption is unsafe.
{{% /boxes/warning %}}
### Types of room events
Room events are split into two categories:
@ -1435,7 +1447,7 @@ following fields.
### Size limits
The complete event MUST NOT be larger than 65535 bytes, when formatted
The complete event MUST NOT be larger than 65536 bytes, when formatted
as a [PDU for the Server-Server
protocol](/server-server-api/#pdus), including any
signatures, and encoded as [Canonical
@ -1451,7 +1463,7 @@ There are additional restrictions on sizes per key:
Some event types have additional size restrictions which are specified
in the description of the event. Additional keys have no limit other
than that implied by the total 65 KB limit on events.
than that implied by the total 64 KiB limit on events.
### Room Events
@ -1700,7 +1712,7 @@ event also has a `creator` key which contains the user ID of the room
creator. It will also generate several other events in order to manage
permissions in this room. This includes:
- `m.room.power_levels` : Sets the power levels of users and required power
- `m.room.power_levels` : Sets the power levels of users and required power
levels for various actions within the room such as sending events.
- `m.room.join_rules` : Whether the room is "invite-only" or not.
@ -1766,57 +1778,44 @@ in that room. There are several states in which a user may be, in
relation to a room:
- Unrelated (the user cannot send or receive events in the room)
- Knocking (the user has requested to participate in the room, but has
not yet been allowed to)
- Invited (the user has been invited to participate in the room, but
is not yet participating)
- Joined (the user can send and receive events in the room)
- Banned (the user is not allowed to join the room)
There is an exception to the requirement that a user join a room before
sending events to it: users may send an `m.room.member` event to a room
with `content.membership` set to `leave` to reject an invitation if they
have currently been invited to a room but have not joined it.
There are a few notable exceptions which allow non-joined members of the
room to send events in the room:
- Users wishing to reject an invite would send `m.room.member` events with
`content.membership` of `leave`. They must have been invited first.
- If the room allows, users can send `m.room.member` events with `content.membership`
of `knock` to knock on the room. This is a request for an invite by the user.
- To retract a previous knock, a user would send a `leave` event similar to
rejecting an invite.
Some rooms require that users be invited to it before they can join;
others allow anyone to join. Whether a given room is an "invite-only"
room is determined by the room config key `m.room.join_rules`. It can
have one of the following values:
`public`
`public`
This room is free for anyone to join without an invite.
`invite`
`invite`
This room can only be joined if you were invited.
`knock`
This room can only be joined if you were invited, and allows anyone to
request an invite to the room. Note that this join rule is only available
to rooms based upon [room version 7](/rooms/v7).
The allowable state transitions of membership are:
```
/ban
+------------------------------------------------------+
| |
| +----------------+ +----------------+ |
| | /leave | | | |
| | v v | |
/invite +--------+ +-------+ | |
------------>| invite |<----------| leave |----+ | |
+--------+ /invite +-------+ | | |
| | ^ | | |
| | | | | |
/join | +---------------+ | | | |
| | /join if | | | |
| | join_rules | | /ban | /unban |
| | public /leave | | | |
v v or | | | |
+------+ /kick | | | |
------------>| join |-------------------+ | | |
/join +------+ v | |
if | +-----+ | |
join_rules +-------------------------->| ban |-----+ |
public /ban +-----+ |
^ ^ |
| | |
----------------------------------------------+ +----------------------+
/ban
```
![membership-flow-diagram](/diagrams/membership.png)
{{% http-api spec="client-server" api="list_joined_rooms" %}}
@ -1826,14 +1825,51 @@ The allowable state transitions of membership are:
{{% http-api spec="client-server" api="joining" %}}
##### Knocking on rooms
<!--
This section is here because it's most similar to being invited/joining a
room, though has added complexity which needs to be explained. Otherwise
this will have been just the API definition and nothing more (like invites).
-->
If the join rules allow, external users to the room can `/knock` on it to
request permission to join. Users with appropriate permissions within the
room can then approve (`/invite`) or deny (`/kick`, `/ban`, or otherwise
set membership to `leave`) the knock. Knocks can be retracted by calling
`/leave` or otherwise setting membership to `leave`.
Users who are currently in the room, already invited, or banned cannot
knock on the room.
To accept another user's knock, the user must have permission to invite
users to the room. To reject another user's knock, the user must have
permission to either kick or ban users (whichever is being performed).
Note that setting another user's membership to `leave` is kicking them.
The knocking homeserver should assume that an invite to the room means
that the knock was accepted, even if the invite is not explicitly related
to the knock.
Homeservers are permitted to automatically accept invites as a result of
knocks as they should be aware of the user's intent to join the room. If
the homeserver is not auto-accepting invites (or there was an unrecoverable
problem with accepting it), the invite is expected to be passed down normally
to the client to handle. Clients can expect to see the join event if the
server chose to auto-accept.
{{% http-api spec="client-server" api="knocking" %}}
#### Leaving rooms
A user can leave a room to stop receiving events for that room. A user
must have been invited to or have joined the room before they are
eligible to leave the room. Leaving a room to which the user has been
invited rejects the invite. Once a user leaves a room, it will no longer
appear in the response to the [`/sync`](/client-server-api/#get_matrixclientr0sync) API unless it is explicitly
requested via a filter with the `include_leave` field set to `true`.
invited rejects the invite, and can retract a knock. Once a user leaves
a room, it will no longer appear in the response to the
[`/sync`](/client-server-api/#get_matrixclientr0sync) API unless it is
explicitly requested via a filter with the `include_leave` field set
to `true`.
Whether or not they actually joined the room, if the room is an
"invite-only" room the user will need to be re-invited before they can
@ -1841,7 +1877,7 @@ re-join the room.
A user can also forget a room which they have left. Rooms which have
been forgotten will never appear the response to the [`/sync`](/client-server-api/#get_matrixclientr0sync) API,
until the user re-joins or is re-invited.
until the user re-joins, is re-invited, or knocks.
A user may wish to force another user to leave a room. This can be done
by 'kicking' the other user. To do so, the user performing the kick MUST

View file

@ -247,8 +247,7 @@ file type. The key is sent using the [JSON Web
Key](https://tools.ietf.org/html/rfc7517#appendix-A.3) format, with a
[W3C extension](https://w3c.github.io/webcrypto/#iana-section-jwk).
Extensions to `m.room.message` msgtypes
&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;
###### Extensions to `m.room.message` msgtypes
This module adds `file` and `thumbnail_file` properties, of type
`EncryptedFile`, to `m.room.message` msgtypes that reference files, such
@ -357,8 +356,8 @@ out-of-band channel: there is no way to do it within Matrix without
trusting the administrators of the homeservers.
In Matrix, verification works by Alice meeting Bob in person, or
contacting him via some other trusted medium, and use [SAS
Verification](#SAS Verification) to interactively verify Bob's devices.
contacting him via some other trusted medium, and using one of the
verification methods defined below to interactively verify Bob's devices.
Alice and Bob may also read aloud their unpadded base64 encoded Ed25519
public key, as returned by `/keys/query`.
@ -390,60 +389,70 @@ decrypted by such a device. For the Olm protocol, this is documented at
Verifying keys manually by reading out the Ed25519 key is not very
user-friendly, and can lead to errors. In order to help mitigate errors,
and to make the process easier for users, some verification methods are
supported by the specification. The methods all use a common framework
supported by the specification and use messages exchanged by the user's devices
to assist in the verification. The methods all use a common framework
for negotiating the key verification.
To use this framework, Alice's client would send
`m.key.verification.request` events to Bob's devices. All of the
`to_device` messages sent to Bob MUST have the same `transaction_id` to
indicate they are part of the same request. This allows Bob to reject
the request on one device, and have it apply to all of his devices.
Similarly, it allows Bob to process the verification on one device
without having to involve all of his devices.
Verification messages can be sent either in a room shared by the two parties,
which should be a [direct messaging](#direct-messaging) room between the two
parties, or by using [to-device](#send-to-device-messaging) messages sent
directly between the two devices involved. In both cases, the messages
exchanged are similar, with minor differences as detailed below. Verifying
between two different users should be performed using in-room messages, whereas
verifying two devices belonging to the same user should be performed using
to-device messages.
When Bob's device receives an `m.key.verification.request`, it should
prompt Bob to verify keys with Alice using one of the supported methods
in the request. If Bob's device does not understand any of the methods,
it should not cancel the request as one of his other devices may support
the request. Instead, Bob's device should tell Bob that an unsupported
method was used for starting key verification. The prompt for Bob to
accept/reject Alice's request (or the unsupported method prompt) should
be automatically dismissed 10 minutes after the `timestamp` field or 2
minutes after Bob's client receives the message, whichever comes first,
if Bob does not interact with the prompt. The prompt should additionally
be hidden if an appropriate `m.key.verification.cancel` message is
received.
A key verification session is identified by an ID that is established by the
first message sent in that session. For verifications using in-room messages,
the ID is the event ID of the initial message, and for verifications using
to-device messages, the first message contains a `transaction_id` field that is
shared by the other messages of that session.
If Bob rejects the request, Bob's client must send an
`m.key.verification.cancel` message to Alice's device. Upon receipt,
Alice's device should tell her that Bob does not want to verify her
device and send `m.key.verification.cancel` messages to all of Bob's
devices to notify them that the request was rejected.
In general, verification operates as follows:
If Bob accepts the request, Bob's device starts the key verification
process by sending an `m.key.verification.start` message to Alice's
device. Upon receipt of this message, Alice's device should send an
`m.key.verification.cancel` message to all of Bob's other devices to
indicate the process has been started. The start message must use the
same `transaction_id` from the original key verification request if it
is in response to the request. The start message can be sent
independently of any request.
- Alice requests a key verification with Bob by sending an
`m.key.verification.request` event. This event indicates the verification
methods that Alice's client supports. (Note that "Alice" and "Bob" may in
fact be the same user, in the case where a user is verifying their own
devices.)
- Bob's client prompts Bob to accept the key verification. When Bob accepts
the verification, Bob's client sends an `m.key.verification.ready` event.
This event indicates the verification methods, corresponding to the
verification methods supported by Alice's client, that Bob's client supports.
- Alice's or Bob's devices allow their users to select one of the verification
methods supported by both devices to use for verification. When Alice or Bob
selects a verification method, their device begins the verification by
sending an `m.key.verification.start` event, indicating the selected
verification method. Note that if there is only one verification method in
common between the devices then the receiver's device (Bob) can auto-select
it.
- Alice and Bob complete the verification as defined by the selected
verification method. This could involve their clients exchanging messages,
Alice and Bob exchanging information out-of-band, and/or Alice and Bob
interacting with their devices.
- Alice's and Bob's clients send `m.key.verification.done` events to indicate
that the verification was successful.
Individual verification methods may add additional steps, events, and
properties to the verification messages. Event types for methods defined
in this specification must be under the `m.key.verification` namespace
and any other event types must be namespaced according to the Java
package naming convention.
Verifications can be cancelled by either device at any time by sending an
`m.key.verification.cancel` event with a `code` field that indicates the reason
it was cancelled.
Any of Alice's or Bob's devices can cancel the key verification request
or process at any time with an `m.key.verification.cancel` message to
all applicable devices.
This framework yields the following handshake, assuming both Alice and
Bob each have 2 devices, Bob's first device accepts the key verification
request, and Alice's second device initiates the request. Note how
Alice's first device is not involved in the request or verification
process.
When using to-device messages, Alice may not know which of Bob's devices to
verify, or may not want to choose a specific device. In this case, Alice will
send `m.key.verification.request` events to all of Bob's devices. All of these
events will use the same transaction ID. When Bob accepts or declines the
verification on one of his devices (sending either an
`m.key.verification.ready` or `m.key.verification.cancel` event), Alice will
send an `m.key.verification.cancel` event to Bob's other devices with a `code`
of `m.accepted` in the case where Bob accepted the verification, or `m.user` in
the case where Bob rejected the verification. This yields the following
handshake when using to-device messages, assuming both Alice and Bob each have
2 devices, Bob's first device accepts the key verification request, and Alice's
second device initiates the request. Note how Alice's first device is not
involved in the request or verification process. Also note that, although in
this example, Bob's device sends the `m.key.verification.start`, Alice's device
could also send that message. As well, the order of the
`m.key.verification.done` messages could be reversed.
```
+---------------+ +---------------+ +-------------+ +-------------+
@ -456,20 +465,85 @@ process.
| | m.key.verification.request | |
| |-------------------------------------------------->|
| | | |
| | m.key.verification.start | |
| | m.key.verification.ready | |
| |<----------------------------------| |
| | | |
| | m.key.verification.cancel | |
| |-------------------------------------------------->|
| | | |
| | m.key.verification.start | |
| |<----------------------------------| |
| | | |
.
. (verification messages)
.
| | | |
| | m.key.verification.done | |
| |<----------------------------------| |
| | | |
| | m.key.verification.done | |
| |---------------------------------->| |
| | | |
```
After the handshake, the verification process begins.
When using in-room messages and the room has encryption enabled, clients should
ensure that encryption does not hinder the verification. For example, if the
verification messages are encrypted, clients must ensure that all the
recipient's unverified devices receive the keys necessary to decrypt the
messages, even if they would normally not be given the keys to decrypt messages
in the room. Alternatively, verification messages may be sent unencrypted,
though this is not encouraged.
Upon receipt of Alice's `m.key.verification.request` message, if Bob's device
does not understand any of the methods, it should not cancel the request as one
of his other devices may support the request. Instead, Bob's device should tell
Bob that no supported method was found, and allow him to manually reject the
request.
The prompt for Bob to accept/reject Alice's request (or the unsupported method
prompt) should be automatically dismissed 10 minutes after the `timestamp` (in
the case of to-device messages) or `origin_ts` (in the case of in-room
messages) field or 2 minutes after Bob's client receives the message, whichever
comes first, if Bob does not interact with the prompt. The prompt should
additionally be hidden if an appropriate `m.key.verification.cancel` message is
received.
If Bob rejects the request, Bob's client must send an
`m.key.verification.cancel` event with `code` set to `m.user`. Upon receipt,
Alice's device should tell her that Bob does not want to verify her device and,
if the request was sent as a to-device message, send
`m.key.verification.cancel` messages to all of Bob's devices to notify them
that the request was rejected.
If Alice's and Bob's clients both send an `m.key.verification.start` message,
and both specify the same verification method, then the
`m.key.verification.start` message sent by the user whose ID is the
lexicographically largest user ID should be ignored, and the situation should
be treated the same as if only the user with the lexicographically smallest
user ID had sent the `m.key.verification.start` message. In the case where the
user IDs are the same (that is, when a user is verifying their own device),
then the device IDs should be compared instead. If the two
`m.key.verification.start` messages do not specify the same verification
method, then the verification should be cancelled with a `code` of
`m.unexpected_message`.
An `m.key.verification.start` message can also be sent independently of any
request, specifying the verification method to use.
Individual verification methods may add additional steps, events, and
properties to the verification messages. Event types for methods defined
in this specification must be under the `m.key.verification` namespace
and any other event types must be namespaced according to the Java
package naming convention.
{{% event event="m.key.verification.request" %}}
{{% event event="m.key.verification.ready" %}}
{{% event event="m.key.verification.start" %}}
{{% event event="m.key.verification.done" %}}
{{% event event="m.key.verification.cancel" %}}
##### Short Authentication String (SAS) verification
@ -493,8 +567,11 @@ example, if we verify 40 bits, then an attacker has a 1 in
success. A failed attack would result in a mismatched Short
Authentication String, alerting users to the attack.
The verification process takes place over [to-device](#send-to-device-messaging) messages in two
phases:
To advertise support for this method, clients use the name `m.sas.v1` in the
`methods` fields of the `m.key.verification.request` and
`m.key.verification.ready` events.
The verification process takes place in two phases:
1. Key agreement phase (based on [ZRTP key
agreement](https://tools.ietf.org/html/rfc6189#section-4.4.1)).
@ -505,63 +582,62 @@ The process between Alice and Bob verifying each other would be:
1. Alice and Bob establish a secure out-of-band connection, such as
meeting in-person or a video call. "Secure" here means that either
party cannot be impersonated, not explicit secrecy.
2. Alice and Bob communicate which devices they'd like to verify with
each other.
3. Alice selects Bob's device from the device list and begins
verification.
4. Alice's client ensures it has a copy of Bob's device key.
5. Alice's device sends Bob's device an `m.key.verification.start`
message.
6. Bob's device receives the message and selects a key agreement
2. Alice and Bob begin a key verification using the key verification
framework as described above.
3. Alice's device sends Bob's device an `m.key.verification.start`
message. Alice's device ensures it has a copy of Bob's device key.
4. Bob's device receives the message and selects a key agreement
protocol, hash algorithm, message authentication code, and SAS
method supported by Alice's device.
7. Bob's device ensures it has a copy of Alice's device key.
8. Bob's device creates an ephemeral Curve25519 key pair
5. Bob's device ensures it has a copy of Alice's device key.
6. Bob's device creates an ephemeral Curve25519 key pair
(*K<sub>B</sub><sup>private</sup>*,*K<sub>B</sub><sup>public</sup>*),
and calculates the hash (using the chosen algorithm) of the public
key *K<sub>B</sub><sup>public</sup>*.
9. Bob's device replies to Alice's device with an
7. Bob's device replies to Alice's device with an
`m.key.verification.accept` message.
10. Alice's device receives Bob's message and stores the commitment hash
8. Alice's device receives Bob's message and stores the commitment hash
for later use.
11. Alice's device creates an ephemeral Curve25519 key pair
9. Alice's device creates an ephemeral Curve25519 key pair
(*K<sub>A</sub><sup>private</sup>*,*K<sub>A</sub><sup>public</sup>*)
and replies to Bob's device with an `m.key.verification.key`,
sending only the public key
*K<sub>A</sub><sup>public</sup>*.
12. Bob's device receives Alice's message and replies with its own
10. Bob's device receives Alice's message and replies with its own
`m.key.verification.key` message containing its public key
*K<sub>B</sub><sup>public</sup>*.
13. Alice's device receives Bob's message and verifies the commitment
11. Alice's device receives Bob's message and verifies the commitment
hash from earlier matches the hash of the key Bob's device just sent
and the content of Alice's `m.key.verification.start` message.
14. Both Alice and Bob's devices perform an Elliptic-curve
12. Both Alice and Bob's devices perform an Elliptic-curve
Diffie-Hellman
(*ECDH(K<sub>A</sub><sup>private</sup>*,*K<sub>B</sub><sup>public</sup>*)),
using the result as the shared secret.
15. Both Alice and Bob's devices display a SAS to their users, which is
13. Both Alice and Bob's devices display a SAS to their users, which is
derived from the shared key using one of the methods in this
section. If multiple SAS methods are available, clients should allow
the users to select a method.
16. Alice and Bob compare the strings shown by their devices, and tell
14. Alice and Bob compare the strings shown by their devices, and tell
their devices if they match or not.
17. Assuming they match, Alice and Bob's devices calculate the HMAC of
15. Assuming they match, Alice and Bob's devices calculate the HMAC of
their own device keys and a comma-separated sorted list 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). The key for the HMAC is
different for each item and is calculated by generating 32 bytes
(256 bits) using [the key verification HKDF](#hkdf-calculation).
18. Alice's device sends Bob's device an `m.key.verification.mac`
16. Alice's device sends Bob's device an `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.
19. When the other device receives the `m.key.verification.mac` message,
17. When the other device receives the `m.key.verification.mac` message,
the device calculates the HMAC of its copies of the other device's
keys given in the message, as well as the HMAC of the
comma-separated, sorted, list of key IDs in the message. The device
compares these with the HMAC values given in the message, and if
everything matches then the device keys are verified.
18. Alice and Bob's devices send `m.key.verification.done` messages to complete
the verification.
The wire protocol looks like the following between Alice and Bob's
devices:
@ -865,6 +941,13 @@ example, if Alice and Bob verify each other using SAS, Alice's
`mac` property. Servers therefore must ensure that device IDs will not
collide with cross-signing public keys.
The cross-signing private keys can be stored on the server or shared with other
devices using the [Secrets](#secrets) module. When doing so, the master,
user-signing, and self-signing keys are identified using the names
`m.cross_signing.master`, `m.cross_signing.user_signing`, and
`m.cross_signing.self_signing`, respectively, and the keys are base64-encoded
before being encrypted.
###### Key and signature security
A user's master key could allow an attacker to impersonate that user to
@ -907,6 +990,135 @@ user-signing keys.
{{% http-api spec="client-server" api="cross_signing" %}}
##### QR codes
Verifying by QR codes provides a quick way to verify when one of the parties
has a device capable of scanning a QR code. The QR code encodes both parties'
master signing keys as well as a random shared secret that is used to allow
bi-directional verification from a single scan.
To advertise the ability to show a QR code, clients use the names
`m.qr_code.show.v1` and `m.reciprocate.v1` in the `methods` fields of the
`m.key.verification.request` and `m.key.verification.ready` events. To
advertise the ability to scan a QR code, clients use the names
`m.qr_code.scan.v1` and `m.reciprocate.v1` in the `methods` fields of the
`m.key.verification.request` and `m.key.verification.ready` events.
Clients that support both showing and scanning QR codes would advertise
`m.qr_code.show.v1`, `m.qr_code.scan.v1`, and `m.reciprocate.v1` as
methods.
The process between Alice and Bob verifying each other would be:
1. Alice and Bob meet in person, and want to verify each other's keys.
2. Alice and Bob begin a key verification using the key verification
framework as described above.
3. Alice's client displays a QR code that Bob is able to scan if Bob's client
indicated the ability to scan, an option to scan Bob's QR code if her client
is able to scan. Bob's client prompts displays a QR code that Alice can
scan if Alice's client indicated the ability to scan, and an option to scan
Alice's QR code if his client is able to scan. The format for the QR code
is described below. Other options, like starting SAS Emoji verification,
can be presented alongside the QR code if the devices have appropriate
support.
5. Alice scans Bob's QR code.
6. Alice's device ensures that the keys encoded in the QR code match the
expected values for the keys. If not, Alice's device displays an error
message indicating that the code is incorrect, and sends a
`m.key.verification.cancel` message to Bob's device.
Otherwise, at this point:
- Alice's device has now verified Bob's key, and
- Alice's device knows that Bob has the correct key for her.
Thus for Bob to verify Alice's key, Alice needs to tell Bob that he has the
right key.
7. Alice's device displays a message saying that the verification was
successful because the QR code's keys will have matched the keys
expected for Bob. Bob's device hasn't had a chance to verify Alice's
keys yet so wouldn't show the same message. Bob will know that
he has the right key for Alice because Alice's device will have shown
this message, as otherwise the verification would be cancelled.
8. Alice's device sends an `m.key.verification.start` message with `method` set
to `m.reciprocate.v1` to Bob (see below). The message includes the shared
secret from the QR code. This signals to Bob's device that Alice has
scanned Bob's QR code.
This message is merely a signal for Bob's device to proceed to the next
step, and is not used for verification purposes.
9. Upon receipt of the `m.key.verification.start` message, Bob's device ensures
that the shared secret matches.
If the shared secret does not match, it should display an error message
indicating that an attack was attempted. (This does not affect Alice's
verification of Bob's keys.)
If the shared secret does match, it asks Bob to confirm that Alice
has scanned the QR code.
10. Bob sees Alice's device confirm that the key matches, and presses the button
on his device to indicate that Alice's key is verified.
Bob's verification of Alice's key hinges on Alice telling Bob the result of
her scan. Since the QR code includes what Bob thinks Alice's key is,
Alice's device can check whether Bob has the right key for her. Alice has
no motivation to lie about the result, as getting Bob to trust an incorrect
key would only affect communications between herself and Bob. Thus Alice
telling Bob that the code was scanned successfully is sufficient for Bob to
trust Alice's key, under the assumption that this communication is done
over a trusted medium (such as in-person).
11. Both devices send an `m.key.verification.done` message.
###### QR code format
The QR codes to be displayed and scanned using this format will encode binary
strings in the general form:
- the ASCII string `MATRIX`
- one byte indicating the QR code version (must be `0x02`)
- one byte indicating the QR code verification mode. Should be one of the
following values:
- `0x00` verifying another user with cross-signing
- `0x01` self-verifying in which the current device does trust the master key
- `0x02` self-verifying in which the current device does not yet trust the
master key
- the event ID or `transaction_id` of the associated verification
request event, encoded as:
- two bytes in network byte order (big-endian) indicating the length in
bytes of the ID as a UTF-8 string
- the ID as a UTF-8 string
- the first key, as 32 bytes. The key to use depends on the mode field:
- if `0x00` or `0x01`, then the current user's own master cross-signing public key
- if `0x02`, then the current device's device key
- the second key, as 32 bytes. The key to use depends on the mode field:
- if `0x00`, then what the device thinks the other user's master
cross-signing key is
- if `0x01`, then what the device thinks the other device's device key is
- if `0x02`, then what the device thinks the user's master cross-signing key
is
- a random shared secret, as a byte string. It is suggested to use a secret
that is about 8 bytes long. Note: as we do not share the length of the
secret, and it is not a fixed size, clients will just use the remainder of
binary string as the shared secret.
For example, if Alice displays a QR code encoding the following binary string:
```
"MATRIX" |ver|mode| len | event ID
4D 41 54 52 49 58 02 00 00 2D 21 41 42 43 44 ...
| user's cross-signing key | other user's cross-signing key | shared secret
00 01 02 03 04 05 06 07 ... 10 11 12 13 14 15 16 17 ... 20 21 22 23 24 25 26 27
```
this indicates that Alice is verifying another user (say Bob), in response to
the request from event "$ABCD...", her cross-signing key is
`0001020304050607...` (which is "AAECAwQFBg..." in base64), she thinks that
Bob's cross-signing key is `1011121314151617...` (which is "EBESExQVFh..." in
base64), and the shared secret is `2021222324252627` (which is "ICEiIyQlJic" in
base64).
###### Verification messages specific to QR codes
{{% event event="m.key.verification.start$m.reciprocate.v1" %}}
#### Sharing keys between devices
If Bob has an encrypted conversation with Alice on his computer, and
@ -1004,6 +1216,11 @@ as follows:
When reading in a recovery key, clients must disregard whitespace, and
perform the reverse of steps 1 through 3.
The recovery key can also be stored on the server or shared with other devices
using the [Secrets](#secrets) module. When doing so, it is identified using the
name `m.megolm_backup.v1`, and the key is base64-encoded before being
encrypted.
###### Backup algorithm: `m.megolm_backup.v1.curve25519-aes-sha2`
When a backup is created with the `algorithm` set to

View file

@ -53,7 +53,7 @@ tags to permit, denying the use and rendering of anything else, is:
`font`, `del`, `h1`, `h2`, `h3`, `h4`, `h5`, `h6`, `blockquote`, `p`,
`a`, `ul`, `ol`, `sup`, `sub`, `li`, `b`, `i`, `u`, `strong`, `em`,
`strike`, `code`, `hr`, `br`, `div`, `table`, `thead`, `tbody`, `tr`,
`th`, `td`, `caption`, `pre`, `span`, `img`.
`th`, `td`, `caption`, `pre`, `span`, `img`, `details`, `summary`.
Not all attributes on those tags should be permitted as they may be
avenues for other disruption attempts, such as adding `onclick` handlers
@ -63,10 +63,11 @@ are listed, clients should translate the value (a 6-character hex color
code) to the appropriate CSS/attributes for the tag.
`font`
`data-mx-bg-color`, `data-mx-color`
`data-mx-bg-color`, `data-mx-color`, `color`
`span`
`data-mx-bg-color`, `data-mx-color`
`data-mx-bg-color`, `data-mx-color`, `data-mx-spoiler` (see
[spoiler messages](#spoiler-messages))
`a`
`name`, `target`, `href` (provided the value is not relative and has a
@ -461,6 +462,52 @@ For `m.image`, the text should be `"sent an image."`. For `m.video`, the
text should be `"sent a video."`. For `m.audio`, the text should be
`"sent an audio file"`.
##### Spoiler messages
Parts of a message can be hidden visually from the user through use of spoilers.
This does not affect the server's representation of the event content - it
is simply a visual cue to the user that the message may reveal important
information about something, spoiling any relevant surprise.
To send spoilers clients MUST use the `formatted_body` and therefore the
`org.matrix.custom.html` format, described above. This makes spoilers valid on
any `msgtype` which can support this format appropriately.
Spoilers themselves are contained with `span` tags, with the reason (optionally)
being in the `data-mx-spoiler` attribute. Spoilers without a reason must at least
specify the attribute, though the value may be empty/undefined.
An example of a spoiler is:
```json
{
"msgtype": "m.text",
"format": "org.matrix.custom.html",
"body": "Alice [Spoiler](mxc://example.org/abc123) in the movie.",
"formatted_body": "Alice <span data-mx-spoiler>lived happily ever after</span> in the movie."
}
```
If a reason were to be supplied, it would look like:
```json
{
"msgtype": "m.text",
"format": "org.matrix.custom.html",
"body": "Alice [Spoiler for health of Alice](mxc://example.org/abc123) in the movie.",
"formatted_body": "Alice <span data-mx-spoiler='health of alice'>lived happily ever after</span> in the movie."
}
```
When sending a spoiler, clients SHOULD provide the plain text fallback in the `body`
as shown above (including the reason). The fallback SHOULD omit the spoiler text verbatim
since `body` might show up in text-only clients or in notifications. To prevent spoilers
showing up in such situations, clients are strongly encouraged to first upload the plaintext
to the media repository then reference the MXC URI in a markdown-style link, as shown above.
Clients SHOULD render spoilers differently with some sort of disclosure. For example, the
client could blur the actual text and ask the user to click on it for it to be revealed.
#### Server behaviour
Homeservers SHOULD reject `m.room.message` events which don't have a

View file

@ -42,7 +42,7 @@ passphrases](#deriving-keys-from-passphrases).
| Parameter | Type | Description
|------------|-----------|-------------------------------------------------------------------------------------------------------------------------------------|
| name | string | **Required.** The name of the key. |
| name | string | Optional. The name of the key. If not given, the client may use a generic name such as "Unnamed key", or "Default key" if the key is marked as the default key (see below). |
| algorithm | string | **Required.** The encryption algorithm to be used for this key. Currently, only `m.secret_storage.v1.aes-hmac-sha2` is supported. |
| passphrase | string | See [deriving keys from passphrases](#deriving-keys-from-passphrases) section for a description of this property. |
@ -56,6 +56,18 @@ will be used to encrypt all 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 that want to present a simplified interface to users by not supporting
multiple keys should use the default key if one is specified. If not default
key is specified, the client may behave as if there is no key is present at
all. When such a client creates a key, it should mark that key as being the
default key.
`DefaultKey`
| Parameter | Type | Description
|------------|-----------|------------------------------------------|
| key | string | **Required.** The ID of the default key. |
##### Secret storage
Encrypted data is stored in the user's account\_data using the event
@ -118,6 +130,16 @@ and the key descriptions for the keys would be:
}
```
If `key_id_1` is the default key, then we also have:
`m.secret_storage.default_key`:
```
{
"key": "key_id_1"
}
```
###### `m.secret_storage.v1.aes-hmac-sha2`
Secrets encrypted using the `m.secret_storage.v1.aes-hmac-sha2`

View file

@ -10,3 +10,4 @@ weight: 60
* [Room Version 4](v4)
* [Room Version 5](v5)
* [Room Version 6](v6)
* [Room Version 7](v7)

52
content/rooms/v7.md Normal file
View file

@ -0,0 +1,52 @@
---
title: Room Version 7
type: docs
weight: 60
---
This room version builds on [version 6](/rooms/v6) to introduce knocking
as a possible join rule and membership state.
## Client considerations
This is the first room version to support knocking completely. As such,
users will not be able to knock on rooms which are not based off v7.
## Server implementation components
{{% boxes/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.
{{% /boxes/warning %}}
Room version 7 adds new authorization rules for events to support knocking.
[Room version 6](/rooms/v6) has details of other authorization rule changes,
as do the versions v6 is based upon.
For checks perfomed upon `m.room.member` events, the following conditions
are added in context:
If type is `m.room.member`:
...
* If `membership` is `ban`:
...
* If `membership` is `knock`:
i. If the `join_rule` is anything other than `knock`, reject.
ii. If `sender` does not match `state_key`, reject.
iii. If the `sender`'s current membership is not `ban`, `invite`, or `join`, allow.
iv. Otherwise, reject.
...
The remaining rules are the same as in [room version 6](/rooms/v6#authorization-rules-for-events).

View file

@ -18,7 +18,7 @@ signatures in HTTP Authorization headers at the HTTP layer.
There are three main kinds of communication that occur between
homeservers:
Persisted Data Units (PDUs):
Persisted Data Units (PDUs):
These events are broadcast from one homeserver to any others that have
joined the same room (identified by Room ID). They are persisted in
long-term storage and record the history of messages and state for a
@ -29,12 +29,12 @@ to deliver that event to its recipient servers. However PDUs are signed
using the originating server's private key so that it is possible to
deliver them through third-party servers.
Ephemeral Data Units (EDUs):
Ephemeral Data Units (EDUs):
These events are pushed between pairs of homeservers. They are not
persisted and are not part of the history of a room, nor does the
receiving homeserver have to reply to them.
Queries:
Queries:
These are single request/response interactions between a given pair of
servers, initiated by one side sending an HTTPS GET request to obtain
some information, and responded by the other. They are not persisted and
@ -365,19 +365,19 @@ them.
#### Definitions
Required Power Level
Required Power Level
A given event type has an associated *required power level*. This is
given by the current `m.room.power_levels` event. The event type is
either listed explicitly in the `events` section or given by either
`state_default` or `events_default` depending on if the event is a state
event or not.
Invite Level, Kick Level, Ban Level, Redact Level
Invite Level, Kick Level, Ban Level, Redact Level
The levels given by the `invite`, `kick`, `ban`, and `redact` properties
in the current `m.room.power_levels` state. Each defaults to 50 if
unspecified.
Target User
Target User
For an `m.room.member` state event, the user given by the `state_key` of
the event.
@ -720,6 +720,24 @@ other servers participating in the room.
{{% http-api spec="server-server" api="joins-v2" %}}
## Knocking upon a room
Rooms can permit knocking through the join rules, and if permitted this
gives users a way to request to join (be invited) to the room. Users who
knock on a room where the server is already a resident of the room can
just send the knock event directly without using this process, however
much like [joining rooms](/server-server-api/#joining-rooms) the server
must handshake their way into having the knock sent on its behalf.
The handshake is largely the same as the joining rooms handshake, where
instead of a "joining server" there is a "knocking server", and the APIs
to be called are different (`/make_knock` and `/send_knock`).
Servers can retract knocks over federation by leaving the room, as described
below for rejecting invites.
{{% http-api spec="server-server" api="knocks" %}}
## Inviting to a room
When a user on a given homeserver invites another user on the same
@ -728,6 +746,10 @@ the process defined here. However, when a user invites another user on a
different homeserver, a request to that homeserver to have the event
signed and verified must be made.
Note that invites are used to indicate that knocks were accepted. As such,
receiving servers should be prepared to manually link up a previous knock
to an invite if the invite event does not directly reference the knock.
{{% http-api spec="server-server" api="invites-v1" %}}
{{% http-api spec="server-server" api="invites-v2" %}}
@ -735,10 +757,10 @@ signed and verified must be made.
## Leaving Rooms (Rejecting Invites)
Normally homeservers can send appropriate `m.room.member` events to have
users leave the room, or to reject local invites. Remote invites from
other homeservers do not involve the server in the graph and therefore
need another approach to reject the invite. Joining the room and
promptly leaving is not recommended as clients and servers will
users leave the room, to reject local invites, or to retract a knock.
Remote invites/knocks from other homeservers do not involve the server in the
graph and therefore need another approach to reject the invite. Joining
the room and promptly leaving is not recommended as clients and servers will
interpret that as accepting the invite, then leaving the room rather
than rejecting the invite.
@ -1009,6 +1031,8 @@ The following endpoint prefixes MUST be protected:
- `/_matrix/federation/v2/send_leave`
- `/_matrix/federation/v1/invite`
- `/_matrix/federation/v2/invite`
- `/_matrix/federation/v1/make_knock`
- `/_matrix/federation/v1/send_knock`
- `/_matrix/federation/v1/state`
- `/_matrix/federation/v1/state_ids`
- `/_matrix/federation/v1/backfill`