-
Notifications
You must be signed in to change notification settings - Fork 399
MSC4124: Simple Server Authorization #4124
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 9 commits
624d7cb
8b57646
d108559
9ee526c
88876e7
5d4adb8
05a6ed0
27fc414
9dc0fa2
eef34e0
8df2926
c55b098
d5439df
f10370d
74149b2
7585162
de8fbcd
4d81894
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,164 @@ | ||||||||||||||||||||||||||||
# MSC4124: Simple server authorization | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
This MSC proposes simple authorization rules that consider the origin | ||||||||||||||||||||||||||||
server of a given event, with the aim of replacing `m.room.server_acl`. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
This is a compromising MSC based on [MSC4099](https://github.com/matrix-org/matrix-spec-proposals/pull/4099) | ||||||||||||||||||||||||||||
that tries to use concepts even more inline current authorization events | ||||||||||||||||||||||||||||
This MSC was also created in reaction to [MSC2870](https://github.com/matrix-org/matrix-spec-proposals/pull/2870), | ||||||||||||||||||||||||||||
that describes itself as stop gap to cover what the MSC has described | ||||||||||||||||||||||||||||
short comings of `m.room.server_acl`. We also agree that MSC2870 is | ||||||||||||||||||||||||||||
a stop gap and that the `m.room.server_acl` has severe shortcomings, | ||||||||||||||||||||||||||||
but we take the view that after 4 years of proposed stop-gaping, | ||||||||||||||||||||||||||||
there is enough time to introduce a more complete solution. | ||||||||||||||||||||||||||||
Comment on lines
+8
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The language around MSC2870 here feels a bit strong. I'd suggest something along the lines of this:
Suggested change
|
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
Related issues: | ||||||||||||||||||||||||||||
- https://github.com/matrix-org/matrix-spec/issues/928 | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
## Proposal | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Overall I think some sequence diagrams and example events would be helpful here. It's not clear to me what causes a server to try knocking (is it based on user action? which actions?), or how the various events really interact with each other. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that's a really good idea, I'll try find the way other MSCs embed diagrams There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added diagrams for room creation and joining a room, are there any other scenarios you think will be helpful to show on a diagram? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The diagrams look like a great start, thank you! Could we get some examples of what the flows look like when the knock rule isn't Separately, some words on what Bob's user experience looks like would be good. This won't be a normative section, but helps ensure the proposal has considered user impact in its decisions. |
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
### The `m.server.knock` authorization rule | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
This rule is be inserted after rule 3 in version 11, the check | ||||||||||||||||||||||||||||
Gnuxie marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||
for `m.room.create`'s content field `m.federate`. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
1. If the type is `m.server.knock`: | ||||||||||||||||||||||||||||
1. If the `state_key` does not contain the server name for the | ||||||||||||||||||||||||||||
origin server, reject. | ||||||||||||||||||||||||||||
2. If there is existing state for the origin server's `m.server.knock`, reject. | ||||||||||||||||||||||||||||
Gnuxie marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||
3. If the origin server's current participation is `permitted`, allow. | ||||||||||||||||||||||||||||
4. If the `m.server.knock_rule` is `deny`, reject. | ||||||||||||||||||||||||||||
5. If the origin server's current participation is `deny`, reject. | ||||||||||||||||||||||||||||
6. Otherwise allow. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
The purpose of this rule is to allow a server to send a knock | ||||||||||||||||||||||||||||
event, even if the `sender` has no membership event. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
The purpose of rule 1.2 is to prevent denied servers from ever being | ||||||||||||||||||||||||||||
given the ability to craft any event whatsoever in a room that has always | ||||||||||||||||||||||||||||
had the `active` `m.server.knock_rule`. | ||||||||||||||||||||||||||||
This is because an `m.server.participation` event set to `deny` will | ||||||||||||||||||||||||||||
usually be topologically older than an `m.server.knock` due to the | ||||||||||||||||||||||||||||
`m.server.participation` usually referencing a recent | ||||||||||||||||||||||||||||
`m.room.power_levels` event. And so `m.server.knock` events could | ||||||||||||||||||||||||||||
be crafted by malicious servers without restriction without | ||||||||||||||||||||||||||||
rule 1.2. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
### The `m.server.participation` authorization rule | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
This rule is to be inserted before rule 4 in version 11, | ||||||||||||||||||||||||||||
Gnuxie marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||
the check for `m.room.member`, and after the `m.server.knock` rule | ||||||||||||||||||||||||||||
described in this proposal. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
1. If the origin server's current `participation` state is not `permitted`: | ||||||||||||||||||||||||||||
1. If the `participation` state is `deny`, reject. | ||||||||||||||||||||||||||||
2. If the `m.server.knock_rule` is `deny`, reject. | ||||||||||||||||||||||||||||
3. If the `m.server.knock_rule` is anything other than `passive`, reject. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
### The `m.server.participation` authorization event, `state_key: ${origin_server_name}` | ||||||||||||||||||||||||||||
Gnuxie marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
This is an authorization event that is used to authorize events | ||||||||||||||||||||||||||||
turt2live marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||
originating from the server named in the `state_key`. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
`participation` can be one of `permitted` or `deny`. | ||||||||||||||||||||||||||||
`participation` is protected from redaction. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
A denied server must not be sent a `m.server.participation` event unless | ||||||||||||||||||||||||||||
the targeted server is already present within the room, or it has | ||||||||||||||||||||||||||||
an existing `m.server.knock` event. | ||||||||||||||||||||||||||||
This is to prevent malicious servers being made aware of rooms that | ||||||||||||||||||||||||||||
they have not yet discovered. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
A `reason` field can be present alongside `participation` in order to | ||||||||||||||||||||||||||||
explain the reason why a server has been `denied`. | ||||||||||||||||||||||||||||
This reason is to be shown to a joining, or previously present | ||||||||||||||||||||||||||||
server, so that the server's users can understand why they are not | ||||||||||||||||||||||||||||
being allowed to participate. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
### The `m.server.knock_rule` event, `state_key: ''` | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
This event has one field, `rule` which can be one of the following: | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
- `deny`: Users are unable to send the `m.server.knock` event | ||||||||||||||||||||||||||||
unless there is an existing `m.server.participation` event for the | ||||||||||||||||||||||||||||
server. | ||||||||||||||||||||||||||||
- `passive`: Users can send the `m.server.knock` event without | ||||||||||||||||||||||||||||
corresponding membership or server participation. | ||||||||||||||||||||||||||||
- `active`: Users can send the `m.server.knock` event but | ||||||||||||||||||||||||||||
cannot send any other event without a corresponding | ||||||||||||||||||||||||||||
participation of `permitted`. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
`rule` is protected from redaction. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
The `passive` state allows for rooms to operate as they do today, | ||||||||||||||||||||||||||||
new servers can freely join a room and start sending events without | ||||||||||||||||||||||||||||
prior approval from the administrators | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
The `active` state allows for a much safer way to run public Matrix rooms, | ||||||||||||||||||||||||||||
new servers can join a room, send the `m.server.knock` event | ||||||||||||||||||||||||||||
but cannot do more until a room administrator permits the new joiner with | ||||||||||||||||||||||||||||
an `m.server.participation` event. We expect that in practice automated | ||||||||||||||||||||||||||||
tooling will perform a simple reputation check and immediately permit | ||||||||||||||||||||||||||||
a new server to participate. This is an essential part of the proposal | ||||||||||||||||||||||||||||
as the `active` mechanism eliminates a current shortfall that | ||||||||||||||||||||||||||||
`m.room.server_acl` is a purely reactive tool in a join wave attack. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
### The `m.server.knock` event, `state_key: ${origin_server_name}` | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
This event has no fields, because it can only be sent once, and | ||||||||||||||||||||||||||||
therefore cannot be edited if the wrong or malicious information | ||||||||||||||||||||||||||||
is provided. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
The intent of the event is to only let the room administrators | ||||||||||||||||||||||||||||
explicitly aware of the server's existence. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
### The `make_server_knock` handshake | ||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If someone can find a way to avoid the handshake, that would be great. The only reason why it is included is because we use the signing of the |
||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
This MSC requires a very simple clone of the `make_knock` handshake | ||||||||||||||||||||||||||||
for the purpose of signing and creating the `m.server.knock` event. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
The details of this handshake are left outside the scope of the MSC, | ||||||||||||||||||||||||||||
as it may be decided that an API providing an agnostic unification of | ||||||||||||||||||||||||||||
`make_knock` and `make_join` should be used instead that signs | ||||||||||||||||||||||||||||
both the membership event and the `m.server.knock` event templates. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
We believe that the open choice here should not alone be a reason | ||||||||||||||||||||||||||||
to block this MSC from consideration. But we will follow up | ||||||||||||||||||||||||||||
with a clone of the `make_knock` handshake if requested. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
## Potential issues | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
### Racing with `m.server.knock_rule`? | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
We will embed `m.server.knock_rule` in `m.room.create` if it | ||||||||||||||||||||||||||||
someone raises concerns about a potential race condition or other issue | ||||||||||||||||||||||||||||
about this conflicting with `m.server.participation`. However, stating | ||||||||||||||||||||||||||||
that there might be without elaboration is not helpful, I'd need to | ||||||||||||||||||||||||||||
know how the race works. If there is insistence, then we will embed | ||||||||||||||||||||||||||||
within the `m.room.create` event. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
### Soft failure of backfilled messages | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
Servers that had `participation` of `permitted` that are later | ||||||||||||||||||||||||||||
denied via `deny`, will have their historical messages soft failed by | ||||||||||||||||||||||||||||
servers which later join. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
This should be addressed with [MSC4104](https://github.com/matrix-org/matrix-spec-proposals/pull/4104). | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
## Alternatives | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
- [MSC4099](https://github.com/matrix-org/matrix-spec-proposals/pull/4099) Participation based authorization for servers in the Matrix DAG | ||||||||||||||||||||||||||||
- [MSC3953](https://github.com/matrix-org/matrix-spec-proposals/pull/3953) Server capability DAG | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
## Security considerations | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
None considered. | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
## Unstable prefix | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
`me.marewolf.msc4124.*` | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
## Dependencies | ||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||
No direct dependencies | ||||||||||||||||||||||||||||
See `make_server_knock` handshake. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could do with a paragraph or two before this one which describes how server ACLs work today, and why they're insufficient.
For example:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have now added a giant context section, but maybe this section should be moved to matrix-org/matrix-spec#928? what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that the section should be moved to the issue because it's independent to the proposal, but the proposal should be modified to keep referring back to it. But I want to hear from you before I do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Proposals should have enough context to be understood in isolation, as issues may be edited or mutated after the MSC is accepted. #4126 is an example for incorporating issue context into the proposal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, in that case I will add each point to the issue and make a shorter reference to them.