diff options
author | Till <2353100+S7evinK@users.noreply.github.com> | 2022-06-09 18:38:07 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-09 18:38:07 +0200 |
commit | 660f7839f52f319a205dc61b96e43c730e5cb91a (patch) | |
tree | 9d29e228927d5d730c7ab2f4bb7ac653c57d1f25 | |
parent | 83797573be87616bea0644918b82e2b20e8b78ca (diff) |
Correctly redact events over federation (#2526)
* Ensure we check powerlevel/origin before redacting an event
* Add passing test
* Use pl.UserLevel
* Make check more readable, also check for the sender
-rw-r--r-- | roomserver/storage/shared/storage.go | 30 | ||||
-rw-r--r-- | sytest-whitelist | 1 |
2 files changed, 29 insertions, 2 deletions
diff --git a/roomserver/storage/shared/storage.go b/roomserver/storage/shared/storage.go index cc4a9fff..67dcfdf3 100644 --- a/roomserver/storage/shared/storage.go +++ b/roomserver/storage/shared/storage.go @@ -823,13 +823,39 @@ func (d *Database) handleRedactions( return nil, "", nil } + // Get the power level from the database, so we can verify the user is allowed to redact the event + powerLevels, err := d.GetStateEvent(ctx, event.RoomID(), gomatrixserverlib.MRoomPowerLevels, "") + if err != nil { + return nil, "", fmt.Errorf("d.GetStateEvent: %w", err) + } + pl, err := powerLevels.PowerLevels() + if err != nil { + return nil, "", fmt.Errorf("unable to get powerlevels for room: %w", err) + } + + redactUser := pl.UserLevel(redactionEvent.Sender()) + switch { + case redactUser >= pl.Redact: + // The power level of the redaction event’s sender is greater than or equal to the redact level. + case redactedEvent.Origin() == redactionEvent.Origin() && redactedEvent.Sender() == redactionEvent.Sender(): + // The domain of the redaction event’s sender matches that of the original event’s sender. + default: + return nil, "", nil + } + // mark the event as redacted + if redactionsArePermanent { + redactedEvent.Event = redactedEvent.Redact() + } + err = redactedEvent.SetUnsignedField("redacted_because", redactionEvent) if err != nil { return nil, "", fmt.Errorf("redactedEvent.SetUnsignedField: %w", err) } - if redactionsArePermanent { - redactedEvent.Event = redactedEvent.Redact() + // NOTSPEC: sytest relies on this unspecced field existing :( + err = redactedEvent.SetUnsignedField("redacted_by", redactionEvent.EventID()) + if err != nil { + return nil, "", fmt.Errorf("redactedEvent.SetUnsignedField: %w", err) } // overwrite the eventJSON table err = d.EventJSONTable.InsertEventJSON(ctx, txn, redactedEvent.EventNID, redactedEvent.JSON()) diff --git a/sytest-whitelist b/sytest-whitelist index 21bbc396..60a3b73f 100644 --- a/sytest-whitelist +++ b/sytest-whitelist @@ -720,3 +720,4 @@ registration is idempotent, with username specified Setting state twice is idempotent Joining room twice is idempotent Inbound federation can return missing events for shared visibility +Inbound federation ignores redactions from invalid servers room > v3
\ No newline at end of file |