aboutsummaryrefslogtreecommitdiff
path: root/federationsender
diff options
context:
space:
mode:
authorKegsay <kegan@matrix.org>2020-10-10 00:21:15 +0100
committerGitHub <noreply@github.com>2020-10-10 00:21:15 +0100
commit9096bfcee8b22b99b4ddd1f1f56ee7aa59280268 (patch)
tree18978e4487d1dabefa8216dc17bd60fe695aa475 /federationsender
parentfe5d1400bf426d1fea8a6c833088d1e491e9dddc (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.go58
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
+}