From 750774b32876d5dee407f88b336abeae39dca39d Mon Sep 17 00:00:00 2001 From: Anant Prakash Date: Fri, 22 Jun 2018 20:32:42 +0530 Subject: [PATCH] Check that events are viewable by the server --- .../federationapi/routing/missingevents.go | 15 ++-- .../dendrite/roomserver/api/query.go | 2 + .../dendrite/roomserver/auth/auth.go | 47 +++++++++++ .../dendrite/roomserver/query/query.go | 79 +++++++------------ 4 files changed, 89 insertions(+), 54 deletions(-) create mode 100644 src/github.com/matrix-org/dendrite/roomserver/auth/auth.go diff --git a/src/github.com/matrix-org/dendrite/federationapi/routing/missingevents.go b/src/github.com/matrix-org/dendrite/federationapi/routing/missingevents.go index e2c439f18..b62e9919e 100644 --- a/src/github.com/matrix-org/dendrite/federationapi/routing/missingevents.go +++ b/src/github.com/matrix-org/dendrite/federationapi/routing/missingevents.go @@ -24,8 +24,10 @@ import ( ) type getMissingEventRequest struct { - api.QueryMissingEventsRequest - MinDepth int64 `json:"min_depth"` + EarliestEvents []string `json:"earliest_events"` + LatestEvents []string `json:"latest_events"` + Limit int `json:"limit"` + MinDepth int64 `json:"min_depth"` } // GetMissingEvents returns missing event between earliest_events & latest_events. @@ -50,23 +52,26 @@ func GetMissingEvents( EarliestEvents: gme.EarliestEvents, LatestEvents: gme.LatestEvents, Limit: gme.Limit, + ServerName: request.Origin(), }, &eventsResponse, ); err != nil { return httputil.LogThenError(httpReq, err) } - eventsResponse.Events = filterEvents(eventsResponse.Events, gme.MinDepth) + eventsResponse.Events = filterEvents(eventsResponse.Events, gme.MinDepth, roomID) return util.JSONResponse{ Code: http.StatusOK, JSON: eventsResponse, } } -func filterEvents(events []gomatrixserverlib.Event, minDepth int64) []gomatrixserverlib.Event { +func filterEvents( + events []gomatrixserverlib.Event, minDepth int64, roomID string, +) []gomatrixserverlib.Event { ref := events[:0] for _, ev := range events { - if ev.Depth() >= minDepth { + if ev.Depth() >= minDepth && ev.RoomID() == roomID { ref = append(ref, ev) } } diff --git a/src/github.com/matrix-org/dendrite/roomserver/api/query.go b/src/github.com/matrix-org/dendrite/roomserver/api/query.go index a95495239..f0a1d3a1c 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/api/query.go +++ b/src/github.com/matrix-org/dendrite/roomserver/api/query.go @@ -162,6 +162,8 @@ type QueryMissingEventsRequest struct { LatestEvents []string `json:"latest_events"` // Limit the number of events this query returns. Limit int `json:"limit"` + // The server interested in the event + ServerName gomatrixserverlib.ServerName `json:"server_name"` } // QueryMissingEventsResponse is response to QueryMissingEvents diff --git a/src/github.com/matrix-org/dendrite/roomserver/auth/auth.go b/src/github.com/matrix-org/dendrite/roomserver/auth/auth.go new file mode 100644 index 000000000..7d6697726 --- /dev/null +++ b/src/github.com/matrix-org/dendrite/roomserver/auth/auth.go @@ -0,0 +1,47 @@ +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package auth + +import "github.com/matrix-org/gomatrixserverlib" + +// IsServerAllowed checks if a server has a client as member in authEvents +func IsServerAllowed( + serverName gomatrixserverlib.ServerName, + authEvents []gomatrixserverlib.Event, +) bool { + isInRoom := false + for _, ev := range authEvents { + membership, err := ev.Membership() + if err != nil || membership != "join" { + continue + } + + stateKey := ev.StateKey() + if stateKey == nil { + continue + } + + _, domain, err := gomatrixserverlib.SplitID('@', *stateKey) + if err != nil { + continue + } + + if domain == serverName { + isInRoom = true + break + } + } + + // TODO: Check if history visibility is shared and if the server is currently in the room + return isInRoom +} diff --git a/src/github.com/matrix-org/dendrite/roomserver/query/query.go b/src/github.com/matrix-org/dendrite/roomserver/query/query.go index 7a03f543c..de0b43ffe 100644 --- a/src/github.com/matrix-org/dendrite/roomserver/query/query.go +++ b/src/github.com/matrix-org/dendrite/roomserver/query/query.go @@ -21,6 +21,7 @@ import ( "github.com/matrix-org/dendrite/common" "github.com/matrix-org/dendrite/roomserver/api" + "github.com/matrix-org/dendrite/roomserver/auth" "github.com/matrix-org/dendrite/roomserver/state" "github.com/matrix-org/dendrite/roomserver/types" "github.com/matrix-org/gomatrixserverlib" @@ -374,58 +375,29 @@ func (r *RoomserverQueryAPI) QueryServerAllowedToSeeEvent( ctx context.Context, request *api.QueryServerAllowedToSeeEventRequest, response *api.QueryServerAllowedToSeeEventResponse, -) error { - stateEntries, err := state.LoadStateAtEvent(ctx, r.DB, request.EventID) +) (err error) { + response.AllowedToSeeEvent, err = r.checkServerAllowedToSeeEvent( + ctx, request.EventID, request.ServerName, + ) + return +} + +func (r *RoomserverQueryAPI) checkServerAllowedToSeeEvent( + ctx context.Context, eventID string, serverName gomatrixserverlib.ServerName, +) (bool, error) { + stateEntries, err := state.LoadStateAtEvent(ctx, r.DB, eventID) if err != nil { - return err + return false, err } // TODO: We probably want to make it so that we don't have to pull // out all the state if possible. stateAtEvent, err := r.loadStateEvents(ctx, stateEntries) if err != nil { - return err + return false, err } - // TODO: Should this be lifted out of here to a more general set of - // auth functions? - - isInRoom := false - for _, ev := range stateAtEvent { - membership, err := ev.Membership() - if err != nil { - continue - } - - if membership != "join" { - continue - } - - stateKey := ev.StateKey() - if stateKey == nil { - continue - } - - _, domain, err := gomatrixserverlib.SplitID('@', *stateKey) - if err != nil { - continue - } - - if domain == request.ServerName { - isInRoom = true - break - } - } - - if isInRoom { - response.AllowedToSeeEvent = true - return nil - } - - // TODO: Check if history visibility is shared and if the server is currently in the room - - response.AllowedToSeeEvent = false - return nil + return auth.IsServerAllowed(serverName, stateAtEvent), nil } // QueryMissingEvents implements api.RoomserverQueryAPI @@ -434,7 +406,7 @@ func (r *RoomserverQueryAPI) QueryMissingEvents( request *api.QueryMissingEventsRequest, response *api.QueryMissingEventsResponse, ) error { - resultIDs := make([]types.EventNID, 0, request.Limit) + resultNIDs := make([]types.EventNID, 0, request.Limit) var front []string visited := make(map[string]bool, request.Limit) // request.Limit acts as a hint to size. for _, id := range request.EarliestEvents { @@ -448,7 +420,7 @@ func (r *RoomserverQueryAPI) QueryMissingEvents( } BFSLoop: - for len(front) > 0 && len(resultIDs) <= request.Limit { + for len(front) > 0 { var next []string events, err := r.DB.EventsFromIDs(ctx, front) if err != nil { @@ -456,14 +428,23 @@ BFSLoop: } for _, ev := range events { - if len(resultIDs) > request.Limit { + if len(resultNIDs) > request.Limit { break BFSLoop } - resultIDs = append(resultIDs, ev.EventNID) + resultNIDs = append(resultNIDs, ev.EventNID) for _, pre := range ev.PrevEventIDs() { if !visited[pre] { visited[pre] = true - next = append(next, pre) + allowed, err := r.checkServerAllowedToSeeEvent( + ctx, ev.EventID(), request.ServerName, + ) + if err != nil { + return err + } + + if allowed { + next = append(next, pre) + } } } } @@ -471,7 +452,7 @@ BFSLoop: } var err error - response.Events, err = r.loadEvents(ctx, resultIDs) + response.Events, err = r.loadEvents(ctx, resultNIDs) return err }