diff options
author | Kegsay <kegan@matrix.org> | 2020-10-10 00:21:15 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-10 00:21:15 +0100 |
commit | 9096bfcee8b22b99b4ddd1f1f56ee7aa59280268 (patch) | |
tree | 18978e4487d1dabefa8216dc17bd60fe695aa475 /federationsender | |
parent | fe5d1400bf426d1fea8a6c833088d1e491e9dddc (diff) |
Validate m.room.create events in send_join responses (#1505)
* Validate m.room.create events in send_join responses
For sytest compliance, refs #1315 and #1317
Fixes #1317
* Linting
Diffstat (limited to 'federationsender')
-rw-r--r-- | federationsender/internal/perform.go | 58 |
1 files changed, 57 insertions, 1 deletions
diff --git a/federationsender/internal/perform.go b/federationsender/internal/perform.go index d014ca5c..bff6833c 100644 --- a/federationsender/internal/perform.go +++ b/federationsender/internal/perform.go @@ -2,6 +2,7 @@ package internal import ( "context" + "encoding/json" "errors" "fmt" "time" @@ -174,8 +175,10 @@ func (r *FederationSenderInternalAPI) performJoinUsingServer( // Work out if we support the room version that has been supplied in // the make_join response. + // "If not provided, the room version is assumed to be either "1" or "2"." + // https://matrix.org/docs/spec/server_server/unstable#get-matrix-federation-v1-make-join-roomid-userid if respMakeJoin.RoomVersion == "" { - respMakeJoin.RoomVersion = gomatrixserverlib.RoomVersionV1 + respMakeJoin.RoomVersion = setDefaultRoomVersionFromJoinEvent(respMakeJoin.JoinEvent) } if _, err = respMakeJoin.RoomVersion.EventFormat(); err != nil { return fmt.Errorf("respMakeJoin.RoomVersion.EventFormat: %w", err) @@ -205,6 +208,9 @@ func (r *FederationSenderInternalAPI) performJoinUsingServer( return fmt.Errorf("r.federation.SendJoin: %w", err) } r.statistics.ForServer(serverName).Success() + if err := sanityCheckSendJoinResponse(respSendJoin); err != nil { + return err + } // Process the join response in a goroutine. The idea here is // that we'll try and wait for as long as possible for the work @@ -424,3 +430,53 @@ func (r *FederationSenderInternalAPI) PerformBroadcastEDU( return nil } + +func sanityCheckSendJoinResponse(respSendJoin gomatrixserverlib.RespSendJoin) error { + // sanity check we have a create event and it has a known room version + for _, ev := range respSendJoin.AuthEvents { + if ev.Type() == gomatrixserverlib.MRoomCreate && ev.StateKeyEquals("") { + // make sure the room version is known + content := ev.Content() + verBody := struct { + Version string `json:"room_version"` + }{} + err := json.Unmarshal(content, &verBody) + if err != nil { + return err + } + if verBody.Version == "" { + // https://matrix.org/docs/spec/client_server/r0.6.0#m-room-create + // The version of the room. Defaults to "1" if the key does not exist. + verBody.Version = "1" + } + knownVersions := gomatrixserverlib.RoomVersions() + if _, ok := knownVersions[gomatrixserverlib.RoomVersion(verBody.Version)]; !ok { + return fmt.Errorf("send_join m.room.create event has an unknown room version: %s", verBody.Version) + } + return nil + } + } + return fmt.Errorf("send_join response is missing m.room.create event") +} + +func setDefaultRoomVersionFromJoinEvent(joinEvent gomatrixserverlib.EventBuilder) gomatrixserverlib.RoomVersion { + // if auth events are not event references we know it must be v3+ + // we have to do these shenanigans to satisfy sytest, specifically for: + // "Outbound federation rejects m.room.create events with an unknown room version" + hasEventRefs := true + authEvents, ok := joinEvent.AuthEvents.([]interface{}) + if ok { + if len(authEvents) > 0 { + _, ok = authEvents[0].(string) + if ok { + // event refs are objects, not strings, so we know we must be dealing with a v3+ room. + hasEventRefs = false + } + } + } + + if hasEventRefs { + return gomatrixserverlib.RoomVersionV1 + } + return gomatrixserverlib.RoomVersionV4 +} |