Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Specify validation for PDUs passed to and returned from federation membership endpoints.
6 changes: 4 additions & 2 deletions content/server-server-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -868,8 +868,10 @@ selecting a resident from the candidate list, and using the
enough information for the joining server to fill in the event.

The joining server is expected to add or replace the `origin`,
`origin_server_ts`, and `event_id` on the templated event received by
the resident server. This event is then signed by the joining server.
`origin_server_ts`, and `event_id` on the templated event received by the
resident server. The joining server MUST also verify that the `type`, `room_id`,
`sender`, `state_key` and `content.membership` fields have the expected values.
This event is then signed by the joining server.

To complete the join handshake, the joining server submits this new event
to the resident server it used for `GET /make_join`, using the `PUT /send_join`
Expand Down
45 changes: 25 additions & 20 deletions data/api/server-server/invites-v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,28 @@ paths:
Also note that if the remote homeserver is already in the room, it will receive the
invite event twice; once through this endpoint, and again through a [federation
transaction](/server-server-api/#transactions).

Servers MUST apply certain validation to ensure they don't accidentally sign non-invite
events from a malicious server. A specific error code is not mandated, but servers SHOULD
return `M_INVALID_PARAM` if:

* The invite event fails a [signature check](/server-server-api/#validating-hashes-and-signatures-on-received-events).
* The event type is not `m.room.member`.
* The `membership` field inside the event content is not `invite`.
* The event sender is not a user ID on the origin server.
* The `state_key` is not a user ID on the receiving server.

The `invite_room_state` has additional validation, which servers MAY apply to room versions
1 through 11 and SHOULD apply to all other room versions. As with the above errors, servers
SHOULD return `M_INVALID_PARAM` if:

* The `m.room.create` event is missing from `invite_room_state`.
* One or more entries in `invite_room_state` are not formatted according
to the room's version.
* One or more events fails a [signature check](/server-server-api/#validating-hashes-and-signatures-on-received-events).
* One or more events does not reside in the same room as the invite.
Note: Some room versions may require calculating the room ID for an
event rather than relying on the presence of `room_id`.
operationId: sendInviteV1
security:
- signedRequest: []
Expand Down Expand Up @@ -83,8 +105,7 @@ paths:
MUST additionally be formatted according to the room version specification.

Servers might need to apply validation to the `invite_room_state` depending
on room version. See the `400 M_MISSING_PARAM` error definition for more
information.
on room version. See endpoint description for more information.

Note that events have a different format depending on the room
version - check the [room version specification](/rooms) for
Expand Down Expand Up @@ -178,31 +199,15 @@ paths:
}
"400":
description: |-
The `M_MISSING_PARAM` error code is used to indicate one or more of
the following:

* The `m.room.create` event is missing from `invite_room_state`.
* One or more entries in `invite_room_state` are not formatted according
to the room's version.
* One or more events fails a [signature check](/server-server-api/#validating-hashes-and-signatures-on-received-events).
* One or more events does not reside in the same room as the invite.
Note: Some room versions may require calculating the room ID for an
event rather than relying on the presence of `room_id`.

Servers MAY apply the validation above to room versions 1 through 11,
and SHOULD apply the validation above to all other room versions.

If `M_MISSING_PARAM` is returned and the request is associated with a
Client-Server API request, the Client-Server API request SHOULD fail
with a 5xx error rather than being passed through.
The request is invalid in some way.
content:
application/json:
schema:
$ref: ../client-server/definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_MISSING_PARAM",
"errcode": "M_INVALID_PARAM",
"error": "Create event not among invite state entries."
}
servers:
Expand Down
43 changes: 25 additions & 18 deletions data/api/server-server/invites-v2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,28 @@ paths:
Also note that if the remote homeserver is already in the room, it will receive the
invite event twice; once through this endpoint, and again through a [federation
transaction](/server-server-api/#transactions).

Servers MUST apply certain validation to ensure they don't accidentally sign non-invite
events from a malicious server. A specific error code is not mandated, but servers SHOULD
return `M_INVALID_PARAM` if:

* The invite event fails a [signature check](/server-server-api/#validating-hashes-and-signatures-on-received-events).
* The event type is not `m.room.member`.
* The `membership` field inside the event content is not `invite`.
* The event sender is not a user ID on the origin server.
* The `state_key` is not a user ID on the receiving server.

The `invite_room_state` has additional validation, which servers MAY apply to room versions
1 through 11 and SHOULD apply to all other room versions. As with the above errors, servers
SHOULD return `M_INVALID_PARAM` if:

* The `m.room.create` event is missing from `invite_room_state`.
* One or more entries in `invite_room_state` are not formatted according
to the room's version.
* One or more events fails a [signature check](/server-server-api/#validating-hashes-and-signatures-on-received-events).
* One or more events does not reside in the same room as the invite.
Note: Some room versions may require calculating the room ID for an
event rather than relying on the presence of `room_id`.
Comment on lines +44 to +64

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I feel like we've gone in the wrong direction here in terms of the error code. M_MISSING_PARAM seems like a terrible choice for param that isn't missing.

Can we update both halves to use something more sensible like M_INVALID_PARAM? Or just leave the precise error code unspecified here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

If we want it to match implementations, probably just need to leave it unspecified. I guess it might be fine to specify something even if implementations don't match right now? Servers shouldn't be trying to catch and handle these errors anyway

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Servers shouldn't be trying to catch and handle these errors anyway

Except that, in the section about response codes, the spec does mandate trying to catch these errors and handle them differently, at least in the case of /v2/invite/{roomId}/{eventId}: it says that errors should be passed through to the client, except for M_MISSING_PARAM which should be turned into a 500 error.

Ugh, I don't really know how best to proceed here. Certainly the best solution would be an MSC to clarify things, but that's a bunch of time and effort.

Maybe we can just get away with saying something like "errors which indicate a faulty request such as M_MISSING_PARAM and M_INVALID_PARAM should be turned into 500 errors", and then leaving the exact error code to be returned under specific circumstances unspecified for now?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(or, leave the "response codes" section just talking about M_MISSING_PARAM, and if we decide we need better error handling, MSC the response codes later?)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I made that case say both M_MISSING_PARAM and M_INVALID_PARAM should be hidden from clients, I guess the wording could be even more relaxed rather than specifying just 2 error codes

operationId: sendInviteV2
security:
- signedRequest: []
Expand Down Expand Up @@ -84,8 +106,7 @@ paths:
MUST additionally be formatted according to the room version specification.

Servers might need to apply validation to the `invite_room_state` depending
on room version. See the `400 M_MISSING_PARAM` error definition for more
information.
on room version. See the endpoint description for more information.

Note that events have a different format depending on the room
version - check the [room version specification](/rooms) for
Expand Down Expand Up @@ -154,22 +175,8 @@ paths:
The error should be passed through to clients so that they
may give better feedback to users.

The `M_MISSING_PARAM` error code is used to indicate one or more of
the following:

* The `m.room.create` event is missing from `invite_room_state`.
* One or more entries in `invite_room_state` are not formatted according
to the room's version.
* One or more events fails a [signature check](/server-server-api/#validating-hashes-and-signatures-on-received-events).
* One or more events does not reside in the same room as the invite.
Note: Some room versions may require calculating the room ID for an
event rather than relying on the presence of `room_id`.

Servers MAY apply the validation above to room versions 1 through 11,
and SHOULD apply the validation above to all other room versions.

If `M_MISSING_PARAM` is returned and the request is associated with a
Client-Server API request, the Client-Server API request SHOULD fail
If `M_MISSING_PARAM` or `M_INVALID_PARAM` is returned and the request is associated
with a Client-Server API request, the Client-Server API request SHOULD fail
with a 5xx error rather than being passed through.
content:
application/json:
Expand Down
49 changes: 48 additions & 1 deletion data/api/server-server/joins-v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ paths:
description: |-
Asks the receiving server to return information that the sending
server will need to prepare a join event to get into the room.

Before signing the returned template and calling `/send_join`,
the sending server MUST verify that:

* the `room_id` is equal to the `roomId` path parameter.
* both the `sender` and `state_key` are equal to the `userId` path parameter.
* the `type` of the event is `m.room.member`.
* the `membership` field inside `content` is `join`.

In case any of the above checks fail, the response MUST be treated as malformed and
discarded. The caller MAY try to join through another server.
operationId: makeJoin
security:
- signedRequest: []
Expand All @@ -36,7 +47,7 @@ paths:
type: string
- in: path
name: userId
description: The user ID the join event will be for.
description: The user ID the join event will be for. This MUST be a user ID on the origin server.
required: true
example: "@someone:example.org"
schema:
Expand Down Expand Up @@ -238,6 +249,15 @@ paths:
**The request and response body here describe the common
event fields in more detail and may be missing other required
fields for a PDU.**

The receiving server MUST apply certain validation before accepting the event.
A specific error code is not mandated, but servers SHOULD return `M_INVALID_PARAM` if:

* The join event fails a [signature check](/server-server-api/#validating-hashes-and-signatures-on-received-events).
* The event type is not `m.room.member`.
* The `membership` field inside the event content is not `join`.
* The event sender is not a user ID on the origin server.
* The `state_key` is not equal to the `sender`.
operationId: sendJoinV1
security:
- signedRequest: []
Expand Down Expand Up @@ -388,6 +408,33 @@ paths:
}
}
]
"400":
description: |-
The request is invalid in some way.
content:
application/json:
schema:
$ref: ../client-server/definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_INVALID_PARAM",
"error": "Not a join event."
}
"403":
description: |-
The room that the joining server is attempting to join does not permit the user
to join.
content:
application/json:
schema:
$ref: ../client-server/definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_FORBIDDEN",
"error": "You are not invited to this room"
}
servers:
- url: "{protocol}://{hostname}{basePath}"
variables:
Expand Down
13 changes: 13 additions & 0 deletions data/api/server-server/joins-v2.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ paths:
**The request and response body here describe the common
event fields in more detail and may be missing other required
fields for a PDU.**

The receiving server MUST apply certain validation before accepting the event.
A specific error code is not mandated, but servers SHOULD return `M_INVALID_PARAM` if:

* The join event fails a [signature check](/server-server-api/#validating-hashes-and-signatures-on-received-events).
* The event type is not `m.room.member`.
* The `membership` field inside the event content is not `join`.
* The event sender is not a user ID on the origin server.
* The `state_key` is not equal to the `sender`.
operationId: sendJoinV2
security:
- signedRequest: []
Expand Down Expand Up @@ -247,6 +256,10 @@ paths:
The error should be passed through to clients so that they
may give better feedback to users.

If `M_MISSING_PARAM` or `M_INVALID_PARAM` is returned and the request is associated
with a Client-Server API request, the Client-Server API request SHOULD fail
with a 5xx error rather than being passed through.

New in `v1.2`, the following error conditions might happen:

If the room is [restricted](/client-server-api/#restricted-rooms)
Expand Down
35 changes: 34 additions & 1 deletion data/api/server-server/knocks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ paths:
description: |-
Asks the receiving server to return information that the sending
server will need to prepare a knock event for the room.

Before signing the returned template and calling `/send_knock`,
the sending server MUST verify that:

* the `room_id` is equal to the `roomId` path parameter.
* both the `sender` and `state_key` are equal to the `userId` path parameter.
* the `type` of the event is `m.room.member`.
* the `membership` field inside `content` is `knock`.

In case any of the above checks fail, the response MUST be treated as malformed and
discarded. The caller MAY try to knock through another server.
operationId: makeKnock
security:
- signedRequest: []
Expand All @@ -36,7 +47,7 @@ paths:
type: string
- in: path
name: userId
description: The user ID the knock event will be for.
description: The user ID the knock event will be for. This MUST be a user ID on the origin server.
required: true
example: "@someone:example.org"
schema:
Expand Down Expand Up @@ -204,6 +215,15 @@ paths:
**The request and response body here describe the common
event fields in more detail and may be missing other required
fields for a PDU.**

The receiving server MUST apply certain validation before accepting the event.
A specific error code is not mandated, but servers SHOULD return `M_INVALID_PARAM` if:

* The knock event fails a [signature check](/server-server-api/#validating-hashes-and-signatures-on-received-events).
* The event type is not `m.room.member`.
* The `membership` field inside the event content is not `knock`.
* The event sender is not a user ID on the origin server.
* The `state_key` is not equal to the `sender`.
operationId: sendKnock
security:
- signedRequest: []
Expand Down Expand Up @@ -330,6 +350,19 @@ paths:
"$ref": "./examples/invite_or_knock_state.json"
}
}
"400":
description: |-
The request is invalid in some way.
content:
application/json:
schema:
$ref: ../client-server/definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_INVALID_PARAM",
"error": "Not a knock event."
}
"403":
description: |-
The knocking server or user is not permitted to knock on the room, such as when the
Expand Down
35 changes: 34 additions & 1 deletion data/api/server-server/leaving-v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@ paths:
description: |-
Asks the receiving server to return information that the sending
server will need to prepare a leave event to get out of the room.

Before signing the returned template and calling `/send_leave`,
the sending server MUST verify that:

* the `room_id` is equal to the `roomId` path parameter.
* both the `sender` and `state_key` are equal to the `userId` path parameter.
* the `type` of the event is `m.room.member`.
* the `membership` field inside `content` is `leave`.

In case any of the above checks fail, the response MUST be treated as malformed and
discarded. The caller MAY try to leave through another server.
operationId: makeLeave
security:
- signedRequest: []
Expand All @@ -36,7 +47,7 @@ paths:
type: string
- in: path
name: userId
description: The user ID the leave event will be for.
description: The user ID the leave event will be for. This MUST be a user ID on the origin server.
required: true
example: "@someone:example.org"
schema:
Expand Down Expand Up @@ -153,6 +164,15 @@ paths:
**The request and response body here describe the common
event fields in more detail and may be missing other required
fields for a PDU.**

The receiving server MUST apply certain validation before accepting the event.
A specific error code is not mandated, but servers SHOULD return `M_INVALID_PARAM` if:

* The leave event fails a [signature check](/server-server-api/#validating-hashes-and-signatures-on-received-events).
* The event type is not `m.room.member`.
* The `membership` field inside the event content is not `leave`.
* The event sender is not a user ID on the origin server.
* The `state_key` is not equal to the `sender`.
operationId: sendLeaveV1
security:
- signedRequest: []
Expand Down Expand Up @@ -249,6 +269,19 @@ paths:
200,
{}
]
"400":
description: |-
The request is invalid in some way.
content:
application/json:
schema:
$ref: ../client-server/definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_INVALID_PARAM",
"error": "Not a leave event."
}
servers:
- url: "{protocol}://{hostname}{basePath}"
variables:
Expand Down
Loading