Files
synapse/tests/federation
Kegan DougalandClaude Fable 5.1 e01562f1e0 B3: Verify and authorise events in MSC4430 member key rooms
In a room whose members are MSC4430 member keys, the `sender` of every event
and the `state_key` of every membership event is a per-room Ed25519 key, and
the event is signed by that key rather than by the sender's server. This
change teaches the two places every received event must pass, signature
verification and the auth rules, to work on keys. The member key room
version is not registered, so none of it is reachable; it is the acceptance
boundary every server has to agree on, so it depends on nothing but the
event.

Signatures (`_check_sigs_on_pdu`): in a member key room the event must carry a
valid signature under the entity `sender` by the key decoded from its `sender`,
with key ID `ed25519:1`, over the redacted event as for server signatures; a
restricted join must additionally carry a valid signature by the member key
named in `join_authorised_via_users_server`, under that member key string. No
server signature is required and no key is fetched, so every server reaches
the same verdict. The sender and the authoriser are parsed strictly: a
non-canonical base64 encoding of a key is not that key (otherwise one public
key would have two identities), and a user ID is rejected. A server
co-signature on a membership event's linkage information is not checked here,
on purpose: the MSC makes it decide whether the member's link is verified, not
whether the event is accepted, and some membership events legitimately carry
no linkage information at all. Hash checking, redaction on a hash mismatch,
the policy server and the spam checker are unchanged.

Auth rules (`event_auth`): `validate_event_for_room_version` checks that the
sender is a canonical member key and has signed the event, that a membership
event's `state_key` is a canonical member key, and that a restricted join
names a canonical member key as authoriser and carries its signature. The
`m.federate` domain comparison is skipped in member key rooms, in both the
general and the membership rule: keys have no domain, so it cannot be
evaluated, and in such rooms `m.federate: false` means no federation at all.
Power level `users` and `additional_creators` must be member keys;
`check_valid_additional_creators` therefore takes the room version, and the
room upgrade servlet passes the new one. Third-party invites need no rule
change: the rule compares `signed.mxid` with the `state_key` and verifies
`signed` with the key published in the inviter's `m.room.third_party_invite`
event, so an identity server that signs the member key produces an
acceptable invite; how it learns the key is unspecified. Everything else in
the rules already works on opaque identities: membership lookups, power
levels, creator power and the restricted-join authoriser are all compared as
strings. A membership event with no `membership` in its content is handled
without raising on both new paths (the legacy paths have the same latent
`KeyError`).

Redactions: in room versions since v3 a redaction by a sender without redact
power is applied only if both senders are from the same server, a check
deferred until the redacted event is known and made in three places (the event
cache, the read path, and persistence of an existing redaction). Those three
now share `redaction_sender_matches`, which keeps the server comparison for
every other room version and, in member key rooms where senders have no
server, applies only when the two senders are the very same key. That is
stricter than before (a server's other users can no longer redact a member's
events without power), and the only rule that needs no network.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-15 09:22:38 +02:00
..
2018-07-04 19:06:20 +01:00