From aa5c3b88dea207410461820ee480b002d185aa54 Mon Sep 17 00:00:00 2001 From: kegsay Date: Wed, 9 Feb 2022 20:31:24 +0000 Subject: [PATCH] Unmarshal events at the Dendrite level not GMSL level (#2164) * Use new event json types in gmsl * Fix EventJSON to actually unmarshal events * Update GMSL * Bump GMSL and improve error messages * Send back the correct RespState * Update GMSL --- federationapi/internal/perform.go | 20 ++++-- federationapi/inthttp/client.go | 9 +-- federationapi/routing/eventauth.go | 2 +- federationapi/routing/invite.go | 4 +- federationapi/routing/join.go | 4 +- federationapi/routing/missingevents.go | 2 +- federationapi/routing/peek.go | 4 +- federationapi/routing/state.go | 32 ++++----- federationapi/routing/threepid.go | 7 +- go.mod | 8 +-- go.sum | 16 ++--- roomserver/api/wrapper.go | 9 +-- roomserver/internal/input/input_events.go | 2 +- roomserver/internal/input/input_missing.go | 79 ++++++++++++++-------- setup/mscs/msc2836/msc2836.go | 67 +++++++++++------- 15 files changed, 158 insertions(+), 107 deletions(-) diff --git a/federationapi/internal/perform.go b/federationapi/internal/perform.go index 7850f206..c51ecf14 100644 --- a/federationapi/internal/perform.go +++ b/federationapi/internal/perform.go @@ -201,7 +201,6 @@ func (r *FederationInternalAPI) performJoinUsingServer( context.Background(), serverName, event, - respMakeJoin.RoomVersion, ) if err != nil { r.statistics.ForServer(serverName).Failure() @@ -209,9 +208,11 @@ func (r *FederationInternalAPI) performJoinUsingServer( } r.statistics.ForServer(serverName).Success() + authEvents := respSendJoin.AuthEvents.UntrustedEvents(respMakeJoin.RoomVersion) + // Sanity-check the join response to ensure that it has a create // event, that the room version is known, etc. - if err = sanityCheckAuthChain(respSendJoin.AuthEvents); err != nil { + if err = sanityCheckAuthChain(authEvents); err != nil { return fmt.Errorf("sanityCheckAuthChain: %w", err) } @@ -225,6 +226,7 @@ func (r *FederationInternalAPI) performJoinUsingServer( var respState *gomatrixserverlib.RespState respState, err = respSendJoin.Check( context.Background(), + respMakeJoin.RoomVersion, r.keyRing, event, federatedAuthProvider(ctx, r.federation, r.keyRing, serverName), @@ -392,12 +394,13 @@ func (r *FederationInternalAPI) performOutboundPeekUsingServer( ctx = context.Background() respState := respPeek.ToRespState() + authEvents := respState.AuthEvents.UntrustedEvents(respPeek.RoomVersion) // authenticate the state returned (check its auth events etc) // the equivalent of CheckSendJoinResponse() - if err = sanityCheckAuthChain(respState.AuthEvents); err != nil { + if err = sanityCheckAuthChain(authEvents); err != nil { return fmt.Errorf("sanityCheckAuthChain: %w", err) } - if err = respState.Check(ctx, r.keyRing, federatedAuthProvider(ctx, r.federation, r.keyRing, serverName)); err != nil { + if err = respState.Check(ctx, respPeek.RoomVersion, r.keyRing, federatedAuthProvider(ctx, r.federation, r.keyRing, serverName)); err != nil { return fmt.Errorf("error checking state returned from peeking: %w", err) } @@ -549,10 +552,15 @@ func (r *FederationInternalAPI) PerformInvite( inviteRes, err := r.federation.SendInviteV2(ctx, destination, inviteReq) if err != nil { - return fmt.Errorf("r.federation.SendInviteV2: %w", err) + return fmt.Errorf("r.federation.SendInviteV2: failed to send invite: %w", err) } + logrus.Infof("GOT INVITE RESPONSE %s", string(inviteRes.Event)) - response.Event = inviteRes.Event.Headered(request.RoomVersion) + inviteEvent, err := inviteRes.Event.UntrustedEvent(request.RoomVersion) + if err != nil { + return fmt.Errorf("r.federation.SendInviteV2 failed to decode event response: %w", err) + } + response.Event = inviteEvent.Headered(request.RoomVersion) return nil } diff --git a/federationapi/inthttp/client.go b/federationapi/inthttp/client.go index a65df906..f9b2a33d 100644 --- a/federationapi/inthttp/client.go +++ b/federationapi/inthttp/client.go @@ -387,14 +387,7 @@ func (h *httpFederationInternalAPI) LookupMissingEvents( if request.Err != nil { return res, request.Err } - res.Events = make([]*gomatrixserverlib.Event, 0, len(request.Res.Events)) - for _, js := range request.Res.Events { - ev, err := gomatrixserverlib.NewEventFromUntrustedJSON(js, roomVersion) - if err != nil { - return res, err - } - res.Events = append(res.Events, ev) - } + res.Events = request.Res.Events return res, nil } diff --git a/federationapi/routing/eventauth.go b/federationapi/routing/eventauth.go index d92b66f4..0a03a0cb 100644 --- a/federationapi/routing/eventauth.go +++ b/federationapi/routing/eventauth.go @@ -65,7 +65,7 @@ func GetEventAuth( return util.JSONResponse{ Code: http.StatusOK, JSON: gomatrixserverlib.RespEventAuth{ - AuthEvents: gomatrixserverlib.UnwrapEventHeaders(response.AuthChainEvents), + AuthEvents: gomatrixserverlib.NewEventJSONsFromHeaderedEvents(response.AuthChainEvents), }, } } diff --git a/federationapi/routing/invite.go b/federationapi/routing/invite.go index 46865965..58bf99f4 100644 --- a/federationapi/routing/invite.go +++ b/federationapi/routing/invite.go @@ -178,12 +178,12 @@ func processInvite( if isInviteV2 { return util.JSONResponse{ Code: http.StatusOK, - JSON: gomatrixserverlib.RespInviteV2{Event: &signedEvent}, + JSON: gomatrixserverlib.RespInviteV2{Event: signedEvent.JSON()}, } } else { return util.JSONResponse{ Code: http.StatusOK, - JSON: gomatrixserverlib.RespInvite{Event: &signedEvent}, + JSON: gomatrixserverlib.RespInvite{Event: signedEvent.JSON()}, } } default: diff --git a/federationapi/routing/join.go b/federationapi/routing/join.go index 7f8d3150..495b8c91 100644 --- a/federationapi/routing/join.go +++ b/federationapi/routing/join.go @@ -351,8 +351,8 @@ func SendJoin( return util.JSONResponse{ Code: http.StatusOK, JSON: gomatrixserverlib.RespSendJoin{ - StateEvents: gomatrixserverlib.UnwrapEventHeaders(stateAndAuthChainResponse.StateEvents), - AuthEvents: gomatrixserverlib.UnwrapEventHeaders(stateAndAuthChainResponse.AuthChainEvents), + StateEvents: gomatrixserverlib.NewEventJSONsFromHeaderedEvents(stateAndAuthChainResponse.StateEvents), + AuthEvents: gomatrixserverlib.NewEventJSONsFromHeaderedEvents(stateAndAuthChainResponse.AuthChainEvents), Origin: cfg.Matrix.ServerName, }, } diff --git a/federationapi/routing/missingevents.go b/federationapi/routing/missingevents.go index f79a2d2d..dd3df7aa 100644 --- a/federationapi/routing/missingevents.go +++ b/federationapi/routing/missingevents.go @@ -62,7 +62,7 @@ func GetMissingEvents( eventsResponse.Events = filterEvents(eventsResponse.Events, roomID) resp := gomatrixserverlib.RespMissingEvents{ - Events: gomatrixserverlib.UnwrapEventHeaders(eventsResponse.Events), + Events: gomatrixserverlib.NewEventJSONsFromHeaderedEvents(eventsResponse.Events), } return util.JSONResponse{ diff --git a/federationapi/routing/peek.go b/federationapi/routing/peek.go index 51132999..827d1116 100644 --- a/federationapi/routing/peek.go +++ b/federationapi/routing/peek.go @@ -88,8 +88,8 @@ func Peek( } respPeek := gomatrixserverlib.RespPeek{ - StateEvents: gomatrixserverlib.UnwrapEventHeaders(response.StateEvents), - AuthEvents: gomatrixserverlib.UnwrapEventHeaders(response.AuthChainEvents), + StateEvents: gomatrixserverlib.NewEventJSONsFromHeaderedEvents(response.StateEvents), + AuthEvents: gomatrixserverlib.NewEventJSONsFromHeaderedEvents(response.AuthChainEvents), RoomVersion: response.RoomVersion, LatestEvent: response.LatestEvent.Unwrap(), RenewalInterval: renewalInterval, diff --git a/federationapi/routing/state.go b/federationapi/routing/state.go index 128df618..37cbb9d1 100644 --- a/federationapi/routing/state.go +++ b/federationapi/routing/state.go @@ -35,12 +35,15 @@ func GetState( return *err } - state, err := getState(ctx, request, rsAPI, roomID, eventID) + stateEvents, authChain, err := getState(ctx, request, rsAPI, roomID, eventID) if err != nil { return *err } - return util.JSONResponse{Code: http.StatusOK, JSON: state} + return util.JSONResponse{Code: http.StatusOK, JSON: &gomatrixserverlib.RespState{ + AuthEvents: gomatrixserverlib.NewEventJSONsFromHeaderedEvents(authChain), + StateEvents: gomatrixserverlib.NewEventJSONsFromHeaderedEvents(stateEvents), + }} } // GetStateIDs returns state event IDs & auth event IDs for the roomID, eventID @@ -55,13 +58,13 @@ func GetStateIDs( return *err } - state, err := getState(ctx, request, rsAPI, roomID, eventID) + stateEvents, authEvents, err := getState(ctx, request, rsAPI, roomID, eventID) if err != nil { return *err } - stateEventIDs := getIDsFromEvent(state.StateEvents) - authEventIDs := getIDsFromEvent(state.AuthEvents) + stateEventIDs := getIDsFromEvent(stateEvents) + authEventIDs := getIDsFromEvent(authEvents) return util.JSONResponse{Code: http.StatusOK, JSON: gomatrixserverlib.RespStateIDs{ StateEventIDs: stateEventIDs, @@ -97,18 +100,18 @@ func getState( rsAPI api.RoomserverInternalAPI, roomID string, eventID string, -) (*gomatrixserverlib.RespState, *util.JSONResponse) { +) (stateEvents, authEvents []*gomatrixserverlib.HeaderedEvent, errRes *util.JSONResponse) { event, resErr := fetchEvent(ctx, rsAPI, eventID) if resErr != nil { - return nil, resErr + return nil, nil, resErr } if event.RoomID() != roomID { - return nil, &util.JSONResponse{Code: http.StatusNotFound, JSON: jsonerror.NotFound("event does not belong to this room")} + return nil, nil, &util.JSONResponse{Code: http.StatusNotFound, JSON: jsonerror.NotFound("event does not belong to this room")} } resErr = allowedToSeeEvent(ctx, request.Origin(), rsAPI, eventID) if resErr != nil { - return nil, resErr + return nil, nil, resErr } var response api.QueryStateAndAuthChainResponse @@ -123,20 +126,17 @@ func getState( ) if err != nil { resErr := util.ErrorResponse(err) - return nil, &resErr + return nil, nil, &resErr } if !response.RoomExists { - return nil, &util.JSONResponse{Code: http.StatusNotFound, JSON: nil} + return nil, nil, &util.JSONResponse{Code: http.StatusNotFound, JSON: nil} } - return &gomatrixserverlib.RespState{ - StateEvents: gomatrixserverlib.UnwrapEventHeaders(response.StateEvents), - AuthEvents: gomatrixserverlib.UnwrapEventHeaders(response.AuthChainEvents), - }, nil + return response.StateEvents, response.AuthChainEvents, nil } -func getIDsFromEvent(events []*gomatrixserverlib.Event) []string { +func getIDsFromEvent(events []*gomatrixserverlib.HeaderedEvent) []string { IDs := make([]string, len(events)) for i := range events { IDs[i] = events[i].EventID() diff --git a/federationapi/routing/threepid.go b/federationapi/routing/threepid.go index b16c68d2..8ae7130c 100644 --- a/federationapi/routing/threepid.go +++ b/federationapi/routing/threepid.go @@ -170,13 +170,18 @@ func ExchangeThirdPartyInvite( util.GetLogger(httpReq.Context()).WithError(err).Error("federation.SendInvite failed") return jsonerror.InternalServerError() } + inviteEvent, err := signedEvent.Event.UntrustedEvent(verRes.RoomVersion) + if err != nil { + util.GetLogger(httpReq.Context()).WithError(err).Error("federation.SendInvite failed") + return jsonerror.InternalServerError() + } // Send the event to the roomserver if err = api.SendEvents( httpReq.Context(), rsAPI, api.KindNew, []*gomatrixserverlib.HeaderedEvent{ - signedEvent.Event.Headered(verRes.RoomVersion), + inviteEvent.Headered(verRes.RoomVersion), }, request.Origin(), cfg.Matrix.ServerName, diff --git a/go.mod b/go.mod index 4759ed29..a1dc0408 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( github.com/matrix-org/go-http-js-libp2p v0.0.0-20200518170932-783164aeeda4 github.com/matrix-org/go-sqlite3-js v0.0.0-20210709140738-b0d1ba599a6d github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16 - github.com/matrix-org/gomatrixserverlib v0.0.0-20220204112336-a05e156fd8a0 + github.com/matrix-org/gomatrixserverlib v0.0.0-20220209202448-9805ef634335 github.com/matrix-org/pinecone v0.0.0-20220121094951-351265543ddf github.com/matrix-org/util v0.0.0-20200807132607-55161520e1d4 github.com/mattn/go-sqlite3 v1.14.10 @@ -59,17 +59,17 @@ require ( github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect github.com/sirupsen/logrus v1.8.1 - github.com/tidwall/gjson v1.13.0 + github.com/tidwall/gjson v1.14.0 github.com/tidwall/sjson v1.2.4 github.com/uber/jaeger-client-go v2.30.0+incompatible github.com/uber/jaeger-lib v2.4.1+incompatible github.com/yggdrasil-network/yggdrasil-go v0.4.2 go.uber.org/atomic v1.9.0 - golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8 + golang.org/x/crypto v0.0.0-20220209195652-db638375bc3a golang.org/x/image v0.0.0-20211028202545-6944b10bf410 golang.org/x/mobile v0.0.0-20220112015953-858099ff7816 golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd - golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect + golang.org/x/sys v0.0.0-20220207234003-57398862261d // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 gopkg.in/h2non/bimg.v1 v1.1.5 gopkg.in/yaml.v2 v2.4.0 diff --git a/go.sum b/go.sum index 6d7da371..1483c792 100644 --- a/go.sum +++ b/go.sum @@ -983,8 +983,8 @@ github.com/matrix-org/go-sqlite3-js v0.0.0-20210709140738-b0d1ba599a6d/go.mod h1 github.com/matrix-org/gomatrix v0.0.0-20190528120928-7df988a63f26/go.mod h1:3fxX6gUjWyI/2Bt7J1OLhpCzOfO/bB3AiX0cJtEKud0= github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16 h1:ZtO5uywdd5dLDCud4r0r55eP4j9FuUNpl60Gmntcop4= github.com/matrix-org/gomatrix v0.0.0-20210324163249-be2af5ef2e16/go.mod h1:/gBX06Kw0exX1HrwmoBibFA98yBk/jxKpGVeyQbff+s= -github.com/matrix-org/gomatrixserverlib v0.0.0-20220204112336-a05e156fd8a0 h1:ZCD8xUM9ppUwW99SzXLOFwWLfdfYRKihj/CCDnMuYMw= -github.com/matrix-org/gomatrixserverlib v0.0.0-20220204112336-a05e156fd8a0/go.mod h1:qFvhfbQ5orQxlH9vCiFnP4dW27xxnWHdNUBKyj/fbiY= +github.com/matrix-org/gomatrixserverlib v0.0.0-20220209202448-9805ef634335 h1:xzK9Q9VGqsZNGx5ANFOCWkJ8R+W1J2BOguxsVZw6m8M= +github.com/matrix-org/gomatrixserverlib v0.0.0-20220209202448-9805ef634335/go.mod h1:qFvhfbQ5orQxlH9vCiFnP4dW27xxnWHdNUBKyj/fbiY= github.com/matrix-org/pinecone v0.0.0-20220121094951-351265543ddf h1:/nqfHUdQHr3WVdbZieaYFvHF1rin5pvDTa/NOZ/qCyE= github.com/matrix-org/pinecone v0.0.0-20220121094951-351265543ddf/go.mod h1:r6dsL+ylE0yXe/7zh8y/Bdh6aBYI1r+u4yZni9A4iyk= github.com/matrix-org/util v0.0.0-20190711121626-527ce5ddefc7/go.mod h1:vVQlW/emklohkZnOPwD3LrZUBqdfsbiyO3p1lNV8F6U= @@ -1363,8 +1363,8 @@ github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpP github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.13.0 h1:3TFY9yxOQShrvmjdM76K+jc66zJeT6D3/VFFYCGQf7M= -github.com/tidwall/gjson v1.13.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.14.0 h1:6aeJ0bzojgWLa82gDQHcx3S0Lr/O51I9bJ5nv6JFx5w= +github.com/tidwall/gjson v1.14.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= @@ -1509,8 +1509,8 @@ golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5 golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8 h1:kACShD3qhmr/3rLmg1yXyt+N4HcwutKyPRB93s54TIU= -golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220209195652-db638375bc3a h1:atOEWVSedO4ksXBe/UrlbSLVxQQ9RxM/tT2Jy10IaHo= +golang.org/x/crypto v0.0.0-20220209195652-db638375bc3a/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1734,8 +1734,8 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220207234003-57398862261d h1:Bm7BNOQt2Qv7ZqysjeLjgCBanX+88Z/OtdvsrEv1Djc= +golang.org/x/sys v0.0.0-20220207234003-57398862261d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= diff --git a/roomserver/api/wrapper.go b/roomserver/api/wrapper.go index e9b94e48..012094c6 100644 --- a/roomserver/api/wrapper.go +++ b/roomserver/api/wrapper.go @@ -51,7 +51,7 @@ func SendEventWithState( state *gomatrixserverlib.RespState, event *gomatrixserverlib.HeaderedEvent, origin gomatrixserverlib.ServerName, haveEventIDs map[string]bool, async bool, ) error { - outliers, err := state.Events() + outliers, err := state.Events(event.RoomVersion) if err != nil { return err } @@ -68,9 +68,10 @@ func SendEventWithState( }) } - stateEventIDs := make([]string, len(state.StateEvents)) - for i := range state.StateEvents { - stateEventIDs[i] = state.StateEvents[i].EventID() + stateEvents := state.StateEvents.UntrustedEvents(event.RoomVersion) + stateEventIDs := make([]string, len(stateEvents)) + for i := range stateEvents { + stateEventIDs[i] = stateEvents[i].EventID() } ires = append(ires, InputRoomEvent{ diff --git a/roomserver/internal/input/input_events.go b/roomserver/internal/input/input_events.go index bb35ade9..774e71dd 100644 --- a/roomserver/internal/input/input_events.go +++ b/roomserver/internal/input/input_events.go @@ -438,7 +438,7 @@ func (r *Inputer) fetchAuthEvents( isRejected := false nextAuthEvent: for _, authEvent := range gomatrixserverlib.ReverseTopologicalOrdering( - res.AuthEvents, + res.AuthEvents.UntrustedEvents(event.RoomVersion), gomatrixserverlib.TopologicalOrderByAuthEvents, ) { // If we already know about this event from the database then we don't diff --git a/roomserver/internal/input/input_missing.go b/roomserver/internal/input/input_missing.go index 7a72b038..497c049d 100644 --- a/roomserver/internal/input/input_missing.go +++ b/roomserver/internal/input/input_missing.go @@ -18,6 +18,11 @@ import ( "github.com/sirupsen/logrus" ) +type parsedRespState struct { + AuthEvents []*gomatrixserverlib.Event + StateEvents []*gomatrixserverlib.Event +} + type missingStateReq struct { origin gomatrixserverlib.ServerName db *shared.RoomUpdater @@ -98,7 +103,7 @@ func (t *missingStateReq) processEventWithMissingState( // That's because the state will have been through state resolution once // already in QueryStateAfterEvent. trustworthy bool - *gomatrixserverlib.RespState + *parsedRespState } // at this point we know we're going to have a gap: we need to work out the room state at the new backwards extremity. @@ -125,7 +130,7 @@ func (t *missingStateReq) processEventWithMissingState( // 1. Ensures that the state is deduplicated fully for each state-key tuple // 2. Ensures that we pick the latest events from both sets, in the case that // one of the prev_events is quite a bit older than the others - resolvedState := &gomatrixserverlib.RespState{} + resolvedState := &parsedRespState{} switch len(states) { case 0: extremityIsCreate := backwardsExtremity.Type() == gomatrixserverlib.MRoomCreate && backwardsExtremity.StateKeyEquals("") @@ -140,16 +145,16 @@ func (t *missingStateReq) processEventWithMissingState( // local state snapshot which will already have been through state res), // use it as-is. There's no point in resolving it again. if states[0].trustworthy { - resolvedState = states[0].RespState + resolvedState = states[0].parsedRespState break } // Otherwise, if it isn't trustworthy (came from federation), run it through // state resolution anyway for safety, in case there are duplicates. fallthrough default: - respStates := make([]*gomatrixserverlib.RespState, len(states)) + respStates := make([]*parsedRespState, len(states)) for i := range states { - respStates[i] = states[i].RespState + respStates[i] = states[i].parsedRespState } // There's more than one previous state - run them all through state res t.roomsMu.Lock(e.RoomID()) @@ -169,7 +174,7 @@ func (t *missingStateReq) processEventWithMissingState( t.hadEventsMutex.Unlock() // Send outliers first so we can send the new backwards extremity without causing errors - outliers, err := resolvedState.Events() + outliers, err := gomatrixserverlib.OrderAuthAndStateEvents(resolvedState.AuthEvents, resolvedState.StateEvents, roomVersion) if err != nil { return err } @@ -239,7 +244,7 @@ func (t *missingStateReq) processEventWithMissingState( // lookupStateAfterEvent returns the room state after `eventID`, which is the state before eventID with the state of `eventID` (if it's a state event) // added into the mix. -func (t *missingStateReq) lookupStateAfterEvent(ctx context.Context, roomVersion gomatrixserverlib.RoomVersion, roomID, eventID string) (*gomatrixserverlib.RespState, bool, error) { +func (t *missingStateReq) lookupStateAfterEvent(ctx context.Context, roomVersion gomatrixserverlib.RoomVersion, roomID, eventID string) (*parsedRespState, bool, error) { // try doing all this locally before we resort to querying federation respState := t.lookupStateAfterEventLocally(ctx, roomID, eventID) if respState != nil { @@ -290,7 +295,7 @@ func (t *missingStateReq) cacheAndReturn(ev *gomatrixserverlib.HeaderedEvent) *g return ev } -func (t *missingStateReq) lookupStateAfterEventLocally(ctx context.Context, roomID, eventID string) *gomatrixserverlib.RespState { +func (t *missingStateReq) lookupStateAfterEventLocally(ctx context.Context, roomID, eventID string) *parsedRespState { var res api.QueryStateAfterEventsResponse err := t.queryer.QueryStateAfterEvents(ctx, &api.QueryStateAfterEventsRequest{ RoomID: roomID, @@ -345,7 +350,7 @@ func (t *missingStateReq) lookupStateAfterEventLocally(ctx context.Context, room queryRes.Events = nil } - return &gomatrixserverlib.RespState{ + return &parsedRespState{ StateEvents: gomatrixserverlib.UnwrapEventHeaders(stateEvents), AuthEvents: authEvents, } @@ -354,13 +359,13 @@ func (t *missingStateReq) lookupStateAfterEventLocally(ctx context.Context, room // lookuptStateBeforeEvent returns the room state before the event e, which is just /state_ids and/or /state depending on what // the server supports. func (t *missingStateReq) lookupStateBeforeEvent(ctx context.Context, roomVersion gomatrixserverlib.RoomVersion, roomID, eventID string) ( - *gomatrixserverlib.RespState, error) { + *parsedRespState, error) { // Attempt to fetch the missing state using /state_ids and /events return t.lookupMissingStateViaStateIDs(ctx, roomID, eventID, roomVersion) } -func (t *missingStateReq) resolveStatesAndCheck(ctx context.Context, roomVersion gomatrixserverlib.RoomVersion, states []*gomatrixserverlib.RespState, backwardsExtremity *gomatrixserverlib.Event) (*gomatrixserverlib.RespState, error) { +func (t *missingStateReq) resolveStatesAndCheck(ctx context.Context, roomVersion gomatrixserverlib.RoomVersion, states []*parsedRespState, backwardsExtremity *gomatrixserverlib.Event) (*parsedRespState, error) { var authEventList []*gomatrixserverlib.Event var stateEventList []*gomatrixserverlib.Event for _, state := range states { @@ -379,7 +384,7 @@ retryAllowedState: h, err2 := t.lookupEvent(ctx, roomVersion, backwardsExtremity.RoomID(), missing.AuthEventID, true) switch err2.(type) { case verifySigError: - return &gomatrixserverlib.RespState{ + return &parsedRespState{ AuthEvents: authEventList, StateEvents: resolvedStateEvents, }, nil @@ -395,7 +400,7 @@ retryAllowedState: } return nil, err } - return &gomatrixserverlib.RespState{ + return &parsedRespState{ AuthEvents: authEventList, StateEvents: resolvedStateEvents, }, nil @@ -452,12 +457,21 @@ func (t *missingStateReq) getMissingEvents(ctx context.Context, e *gomatrixserve // Make sure events from the missingResp are using the cache - missing events // will be added and duplicates will be removed. logger.Debugf("get_missing_events returned %d events", len(missingResp.Events)) - for i, ev := range missingResp.Events { - missingResp.Events[i] = t.cacheAndReturn(ev.Headered(roomVersion)).Unwrap() + missingEvents := make([]*gomatrixserverlib.Event, len(missingResp.Events)) + for i, evJSON := range missingResp.Events { + ev, err := gomatrixserverlib.NewEventFromUntrustedJSON(evJSON, roomVersion) + if err != nil { + logger.WithError(err).WithField("event", string(evJSON)).Warn("NewEventFromUntrustedJSON: failed") + return nil, false, missingPrevEventsError{ + eventID: e.EventID(), + err: err, + } + } + missingEvents[i] = t.cacheAndReturn(ev.Headered(roomVersion)).Unwrap() } // topologically sort and sanity check that we are making forward progress - newEvents = gomatrixserverlib.ReverseTopologicalOrdering(missingResp.Events, gomatrixserverlib.TopologicalOrderByPrevEvents) + newEvents = gomatrixserverlib.ReverseTopologicalOrdering(missingEvents, gomatrixserverlib.TopologicalOrderByPrevEvents) shouldHaveSomeEventIDs := e.PrevEventIDs() hasPrevEvent := false Event: @@ -498,29 +512,37 @@ Event: return newEvents, true, nil } -func (t *missingStateReq) lookupMissingStateViaState(ctx context.Context, roomID, eventID string, roomVersion gomatrixserverlib.RoomVersion) ( - respState *gomatrixserverlib.RespState, err error) { +func (t *missingStateReq) lookupMissingStateViaState( + ctx context.Context, roomID, eventID string, roomVersion gomatrixserverlib.RoomVersion, +) (respState *parsedRespState, err error) { state, err := t.federation.LookupState(ctx, t.origin, roomID, eventID, roomVersion) if err != nil { return nil, err } // Check that the returned state is valid. - if err := state.Check(ctx, t.keys, nil); err != nil { + if err := state.Check(ctx, roomVersion, t.keys, nil); err != nil { return nil, err } + parsedState := &parsedRespState{ + AuthEvents: make([]*gomatrixserverlib.Event, len(state.AuthEvents)), + StateEvents: make([]*gomatrixserverlib.Event, len(state.StateEvents)), + } // Cache the results of this state lookup and deduplicate anything we already // have in the cache, freeing up memory. - for i, ev := range state.AuthEvents { - state.AuthEvents[i] = t.cacheAndReturn(ev.Headered(roomVersion)).Unwrap() + // We load these as trusted as we called state.Check before which loaded them as untrusted. + for i, evJSON := range state.AuthEvents { + ev, _ := gomatrixserverlib.NewEventFromTrustedJSON(evJSON, false, roomVersion) + parsedState.AuthEvents[i] = t.cacheAndReturn(ev.Headered(roomVersion)).Unwrap() } - for i, ev := range state.StateEvents { - state.StateEvents[i] = t.cacheAndReturn(ev.Headered(roomVersion)).Unwrap() + for i, evJSON := range state.StateEvents { + ev, _ := gomatrixserverlib.NewEventFromTrustedJSON(evJSON, false, roomVersion) + parsedState.StateEvents[i] = t.cacheAndReturn(ev.Headered(roomVersion)).Unwrap() } - return &state, nil + return parsedState, nil } func (t *missingStateReq) lookupMissingStateViaStateIDs(ctx context.Context, roomID, eventID string, roomVersion gomatrixserverlib.RoomVersion) ( - *gomatrixserverlib.RespState, error) { + *parsedRespState, error) { util.GetLogger(ctx).WithField("room_id", roomID).Infof("lookupMissingStateViaStateIDs %s", eventID) // fetch the state event IDs at the time of the event stateIDs, err := t.federation.LookupStateIDs(ctx, t.origin, roomID, eventID) @@ -652,13 +674,14 @@ func (t *missingStateReq) lookupMissingStateViaStateIDs(ctx context.Context, roo return resp, err } -func (t *missingStateReq) createRespStateFromStateIDs(stateIDs gomatrixserverlib.RespStateIDs) ( - *gomatrixserverlib.RespState, error) { // nolint:unparam +func (t *missingStateReq) createRespStateFromStateIDs( + stateIDs gomatrixserverlib.RespStateIDs, +) (*parsedRespState, error) { // nolint:unparam t.haveEventsMutex.Lock() defer t.haveEventsMutex.Unlock() // create a RespState response using the response to /state_ids as a guide - respState := gomatrixserverlib.RespState{} + respState := parsedRespState{} for i := range stateIDs.StateEventIDs { ev, ok := t.haveEvents[stateIDs.StateEventIDs[i]] diff --git a/setup/mscs/msc2836/msc2836.go b/setup/mscs/msc2836/msc2836.go index 8a35e414..0af22c19 100644 --- a/setup/mscs/msc2836/msc2836.go +++ b/setup/mscs/msc2836/msc2836.go @@ -82,9 +82,15 @@ type EventRelationshipResponse struct { Limited bool `json:"limited"` } -func toClientResponse(res *gomatrixserverlib.MSC2836EventRelationshipsResponse) *EventRelationshipResponse { +type MSC2836EventRelationshipsResponse struct { + gomatrixserverlib.MSC2836EventRelationshipsResponse + ParsedEvents []*gomatrixserverlib.Event + ParsedAuthChain []*gomatrixserverlib.Event +} + +func toClientResponse(res *MSC2836EventRelationshipsResponse) *EventRelationshipResponse { out := &EventRelationshipResponse{ - Events: gomatrixserverlib.ToClientEvents(res.Events, gomatrixserverlib.FormatAll), + Events: gomatrixserverlib.ToClientEvents(res.ParsedEvents, gomatrixserverlib.FormatAll), Limited: res.Limited, NextBatch: res.NextBatch, } @@ -210,7 +216,7 @@ func federatedEventRelationship( // add auth chain information requiredAuthEventsSet := make(map[string]bool) var requiredAuthEvents []string - for _, ev := range res.Events { + for _, ev := range res.ParsedEvents { for _, a := range ev.AuthEventIDs() { if requiredAuthEventsSet[a] { continue @@ -227,19 +233,24 @@ func federatedEventRelationship( // they may already have the auth events so don't fail this request util.GetLogger(ctx).WithError(err).Error("Failed to QueryAuthChain") } - res.AuthChain = make([]*gomatrixserverlib.Event, len(queryRes.AuthChain)) + res.AuthChain = make(gomatrixserverlib.EventJSONs, len(queryRes.AuthChain)) for i := range queryRes.AuthChain { - res.AuthChain[i] = queryRes.AuthChain[i].Unwrap() + res.AuthChain[i] = queryRes.AuthChain[i].JSON() + } + + res.Events = make(gomatrixserverlib.EventJSONs, len(res.ParsedEvents)) + for i := range res.ParsedEvents { + res.Events[i] = res.ParsedEvents[i].JSON() } return util.JSONResponse{ Code: 200, - JSON: res, + JSON: res.MSC2836EventRelationshipsResponse, } } -func (rc *reqCtx) process() (*gomatrixserverlib.MSC2836EventRelationshipsResponse, *util.JSONResponse) { - var res gomatrixserverlib.MSC2836EventRelationshipsResponse +func (rc *reqCtx) process() (*MSC2836EventRelationshipsResponse, *util.JSONResponse) { + var res MSC2836EventRelationshipsResponse var returnEvents []*gomatrixserverlib.HeaderedEvent // Can the user see (according to history visibility) event_id? If no, reject the request, else continue. event := rc.getLocalEvent(rc.req.EventID) @@ -290,11 +301,11 @@ func (rc *reqCtx) process() (*gomatrixserverlib.MSC2836EventRelationshipsRespons ) returnEvents = append(returnEvents, events...) } - res.Events = make([]*gomatrixserverlib.Event, len(returnEvents)) + res.ParsedEvents = make([]*gomatrixserverlib.Event, len(returnEvents)) for i, ev := range returnEvents { // for each event, extract the children_count | hash and add it as unsigned data. rc.addChildMetadata(ev) - res.Events[i] = ev.Unwrap() + res.ParsedEvents[i] = ev.Unwrap() } res.Limited = remaining == 0 || walkLimited return &res, nil @@ -357,7 +368,7 @@ func (rc *reqCtx) fetchUnknownEvent(eventID, roomID string) *gomatrixserverlib.H continue } rc.injectResponseToRoomserver(res) - for _, ev := range res.Events { + for _, ev := range res.ParsedEvents { if ev.EventID() == eventID { return ev.Headered(ev.Version()) } @@ -384,7 +395,7 @@ func (rc *reqCtx) includeChildren(db Database, parentID string, limit int, recen if rc.hasUnexploredChildren(parentID) { // we need to do a remote request to pull in the children as we are missing them locally. serversToQuery := rc.getServersForEventID(parentID) - var result *gomatrixserverlib.MSC2836EventRelationshipsResponse + var result *MSC2836EventRelationshipsResponse for _, srv := range serversToQuery { res, err := rc.fsAPI.MSC2836EventRelationships(rc.ctx, srv, gomatrixserverlib.MSC2836EventRelationshipsRequest{ EventID: parentID, @@ -397,7 +408,12 @@ func (rc *reqCtx) includeChildren(db Database, parentID string, limit int, recen if err != nil { util.GetLogger(rc.ctx).WithError(err).WithField("server", srv).Error("includeChildren: failed to call MSC2836EventRelationships") } else { - result = &res + mscRes := &MSC2836EventRelationshipsResponse{ + MSC2836EventRelationshipsResponse: res, + } + mscRes.ParsedEvents = res.Events.UntrustedEvents(rc.roomVersion) + mscRes.ParsedAuthChain = res.AuthChain.UntrustedEvents(rc.roomVersion) + result = mscRes break } } @@ -467,7 +483,7 @@ func walkThread( } // MSC2836EventRelationships performs an /event_relationships request to a remote server -func (rc *reqCtx) MSC2836EventRelationships(eventID string, srv gomatrixserverlib.ServerName, ver gomatrixserverlib.RoomVersion) (*gomatrixserverlib.MSC2836EventRelationshipsResponse, error) { +func (rc *reqCtx) MSC2836EventRelationships(eventID string, srv gomatrixserverlib.ServerName, ver gomatrixserverlib.RoomVersion) (*MSC2836EventRelationshipsResponse, error) { res, err := rc.fsAPI.MSC2836EventRelationships(rc.ctx, srv, gomatrixserverlib.MSC2836EventRelationshipsRequest{ EventID: eventID, DepthFirst: rc.req.DepthFirst, @@ -481,7 +497,12 @@ func (rc *reqCtx) MSC2836EventRelationships(eventID string, srv gomatrixserverli util.GetLogger(rc.ctx).WithError(err).Error("Failed to call MSC2836EventRelationships") return nil, err } - return &res, nil + mscRes := &MSC2836EventRelationshipsResponse{ + MSC2836EventRelationshipsResponse: res, + } + mscRes.ParsedEvents = res.Events.UntrustedEvents(ver) + mscRes.ParsedAuthChain = res.AuthChain.UntrustedEvents(ver) + return mscRes, nil } @@ -550,12 +571,12 @@ func (rc *reqCtx) getServersForEventID(eventID string) []gomatrixserverlib.Serve return serversToQuery } -func (rc *reqCtx) remoteEventRelationships(eventID string) *gomatrixserverlib.MSC2836EventRelationshipsResponse { +func (rc *reqCtx) remoteEventRelationships(eventID string) *MSC2836EventRelationshipsResponse { if rc.isFederatedRequest { return nil // we don't query remote servers for remote requests } serversToQuery := rc.getServersForEventID(eventID) - var res *gomatrixserverlib.MSC2836EventRelationshipsResponse + var res *MSC2836EventRelationshipsResponse var err error for _, srv := range serversToQuery { res, err = rc.MSC2836EventRelationships(eventID, srv, rc.roomVersion) @@ -577,7 +598,7 @@ func (rc *reqCtx) lookForEvent(eventID string) *gomatrixserverlib.HeaderedEvent if queryRes != nil { // inject all the events into the roomserver then return the event in question rc.injectResponseToRoomserver(queryRes) - for _, ev := range queryRes.Events { + for _, ev := range queryRes.ParsedEvents { if ev.EventID() == eventID && rc.req.RoomID == ev.RoomID() { return ev.Headered(ev.Version()) } @@ -619,12 +640,12 @@ func (rc *reqCtx) getLocalEvent(eventID string) *gomatrixserverlib.HeaderedEvent // injectResponseToRoomserver injects the events // into the roomserver as KindOutlier, with auth chains. -func (rc *reqCtx) injectResponseToRoomserver(res *gomatrixserverlib.MSC2836EventRelationshipsResponse) { - var stateEvents []*gomatrixserverlib.Event +func (rc *reqCtx) injectResponseToRoomserver(res *MSC2836EventRelationshipsResponse) { + var stateEvents gomatrixserverlib.EventJSONs var messageEvents []*gomatrixserverlib.Event - for _, ev := range res.Events { + for _, ev := range res.ParsedEvents { if ev.StateKey() != nil { - stateEvents = append(stateEvents, ev) + stateEvents = append(stateEvents, ev.JSON()) } else { messageEvents = append(messageEvents, ev) } @@ -633,7 +654,7 @@ func (rc *reqCtx) injectResponseToRoomserver(res *gomatrixserverlib.MSC2836Event AuthEvents: res.AuthChain, StateEvents: stateEvents, } - eventsInOrder, err := respState.Events() + eventsInOrder, err := respState.Events(rc.roomVersion) if err != nil { util.GetLogger(rc.ctx).WithError(err).Error("failed to calculate order to send events in MSC2836EventRelationshipsResponse") return