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
main
Kegsay 2020-10-10 00:21:15 +01:00 committed by GitHub
parent fe5d1400bf
commit 9096bfcee8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 1 deletions

View File

@ -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
}

View File

@ -68,6 +68,8 @@ Request to logout with invalid an access token is rejected
Request to logout without an access token is rejected
Room creation reports m.room.create to myself
Room creation reports m.room.member to myself
Outbound federation rejects send_join responses with no m.room.create event
Outbound federation rejects m.room.create events with an unknown room version
Invited user can see room metadata
# Blacklisted because these tests call /r0/events which we don't implement
# New room members see their own join event