From 2570418f4297a6183231e2a7cda494f55bab4dda Mon Sep 17 00:00:00 2001 From: Kegsay Date: Fri, 4 Sep 2020 10:40:58 +0100 Subject: [PATCH] Remove ServerACLs from the current state server (#1390) * Remove ServerACLs from the current state server Functionality moved to roomserver * Nothing to see here, move along --- currentstateserver/acls/acls.go | 164 --------------------- currentstateserver/acls/acls_test.go | 105 ------------- currentstateserver/api/api.go | 11 -- currentstateserver/api/wrapper.go | 14 -- currentstateserver/consumers/roomserver.go | 9 +- currentstateserver/currentstateserver.go | 7 +- currentstateserver/internal/api.go | 13 +- currentstateserver/inthttp/client.go | 21 +-- currentstateserver/inthttp/server.go | 13 -- federationapi/routing/routing.go | 28 ++-- federationapi/routing/send.go | 6 +- federationapi/routing/send_test.go | 45 +----- federationsender/federationsender.go | 2 +- federationsender/queue/queue.go | 12 +- roomserver/internal/api.go | 4 +- roomserver/internal/input/input.go | 6 + syncapi/internal/keychange_test.go | 4 - 17 files changed, 43 insertions(+), 421 deletions(-) delete mode 100644 currentstateserver/acls/acls.go delete mode 100644 currentstateserver/acls/acls_test.go diff --git a/currentstateserver/acls/acls.go b/currentstateserver/acls/acls.go deleted file mode 100644 index 775b6c73..00000000 --- a/currentstateserver/acls/acls.go +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2020 The Matrix.org Foundation C.I.C. -// -// 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 acls - -import ( - "context" - "encoding/json" - "fmt" - "net" - "regexp" - "strings" - "sync" - - "github.com/matrix-org/gomatrixserverlib" - "github.com/sirupsen/logrus" -) - -type ServerACLDatabase interface { - // GetKnownRooms returns a list of all rooms we know about. - GetKnownRooms(ctx context.Context) ([]string, error) - // GetStateEvent returns the state event of a given type for a given room with a given state key - // If no event could be found, returns nil - // If there was an issue during the retrieval, returns an error - GetStateEvent(ctx context.Context, roomID, evType, stateKey string) (*gomatrixserverlib.HeaderedEvent, error) -} - -type ServerACLs struct { - acls map[string]*serverACL // room ID -> ACL - aclsMutex sync.RWMutex // protects the above -} - -func NewServerACLs(db ServerACLDatabase) *ServerACLs { - ctx := context.TODO() - acls := &ServerACLs{ - acls: make(map[string]*serverACL), - } - // Look up all of the rooms that the current state server knows about. - rooms, err := db.GetKnownRooms(ctx) - if err != nil { - logrus.WithError(err).Fatalf("Failed to get known rooms") - } - // For each room, let's see if we have a server ACL state event. If we - // do then we'll process it into memory so that we have the regexes to - // hand. - for _, room := range rooms { - state, err := db.GetStateEvent(ctx, room, "m.room.server_acl", "") - if err != nil { - logrus.WithError(err).Errorf("Failed to get server ACLs for room %q", room) - continue - } - if state != nil { - acls.OnServerACLUpdate(&state.Event) - } - } - return acls -} - -type ServerACL struct { - Allowed []string `json:"allow"` - Denied []string `json:"deny"` - AllowIPLiterals bool `json:"allow_ip_literals"` -} - -type serverACL struct { - ServerACL - allowedRegexes []*regexp.Regexp - deniedRegexes []*regexp.Regexp -} - -func compileACLRegex(orig string) (*regexp.Regexp, error) { - escaped := regexp.QuoteMeta(orig) - escaped = strings.Replace(escaped, "\\?", ".", -1) - escaped = strings.Replace(escaped, "\\*", ".*", -1) - return regexp.Compile(escaped) -} - -func (s *ServerACLs) OnServerACLUpdate(state *gomatrixserverlib.Event) { - acls := &serverACL{} - if err := json.Unmarshal(state.Content(), &acls.ServerACL); err != nil { - logrus.WithError(err).Errorf("Failed to unmarshal state content for server ACLs") - return - } - // The spec calls only for * (zero or more chars) and ? (exactly one char) - // to be supported as wildcard components, so we will escape all of the regex - // special characters and then replace * and ? with their regex counterparts. - // https://matrix.org/docs/spec/client_server/r0.6.1#m-room-server-acl - for _, orig := range acls.Allowed { - if expr, err := compileACLRegex(orig); err != nil { - logrus.WithError(err).Errorf("Failed to compile allowed regex") - } else { - acls.allowedRegexes = append(acls.allowedRegexes, expr) - } - } - for _, orig := range acls.Denied { - if expr, err := compileACLRegex(orig); err != nil { - logrus.WithError(err).Errorf("Failed to compile denied regex") - } else { - acls.deniedRegexes = append(acls.deniedRegexes, expr) - } - } - logrus.WithFields(logrus.Fields{ - "allow_ip_literals": acls.AllowIPLiterals, - "num_allowed": len(acls.allowedRegexes), - "num_denied": len(acls.deniedRegexes), - }).Debugf("Updating server ACLs for %q", state.RoomID()) - s.aclsMutex.Lock() - defer s.aclsMutex.Unlock() - s.acls[state.RoomID()] = acls -} - -func (s *ServerACLs) IsServerBannedFromRoom(serverName gomatrixserverlib.ServerName, roomID string) bool { - s.aclsMutex.RLock() - // First of all check if we have an ACL for this room. If we don't then - // no servers are banned from the room. - acls, ok := s.acls[roomID] - if !ok { - s.aclsMutex.RUnlock() - return false - } - s.aclsMutex.RUnlock() - // Split the host and port apart. This is because the spec calls on us to - // validate the hostname only in cases where the port is also present. - if serverNameOnly, _, err := net.SplitHostPort(string(serverName)); err == nil { - serverName = gomatrixserverlib.ServerName(serverNameOnly) - } - // Check if the hostname is an IPv4 or IPv6 literal. We cheat here by adding - // a /0 prefix length just to trick ParseCIDR into working. If we find that - // the server is an IP literal and we don't allow those then stop straight - // away. - if _, _, err := net.ParseCIDR(fmt.Sprintf("%s/0", serverName)); err == nil { - if !acls.AllowIPLiterals { - return true - } - } - // Check if the hostname matches one of the denied regexes. If it does then - // the server is banned from the room. - for _, expr := range acls.deniedRegexes { - if expr.MatchString(string(serverName)) { - return true - } - } - // Check if the hostname matches one of the allowed regexes. If it does then - // the server is NOT banned from the room. - for _, expr := range acls.allowedRegexes { - if expr.MatchString(string(serverName)) { - return false - } - } - // If we've got to this point then we haven't matched any regexes or an IP - // hostname if disallowed. The spec calls for default-deny here. - return true -} diff --git a/currentstateserver/acls/acls_test.go b/currentstateserver/acls/acls_test.go deleted file mode 100644 index 9fb6a558..00000000 --- a/currentstateserver/acls/acls_test.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2020 The Matrix.org Foundation C.I.C. -// -// 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 acls - -import ( - "regexp" - "testing" -) - -func TestOpenACLsWithBlacklist(t *testing.T) { - roomID := "!test:test.com" - allowRegex, err := compileACLRegex("*") - if err != nil { - t.Fatalf(err.Error()) - } - denyRegex, err := compileACLRegex("foo.com") - if err != nil { - t.Fatalf(err.Error()) - } - - acls := ServerACLs{ - acls: make(map[string]*serverACL), - } - - acls.acls[roomID] = &serverACL{ - ServerACL: ServerACL{ - AllowIPLiterals: true, - }, - allowedRegexes: []*regexp.Regexp{allowRegex}, - deniedRegexes: []*regexp.Regexp{denyRegex}, - } - - if acls.IsServerBannedFromRoom("1.2.3.4", roomID) { - t.Fatal("Expected 1.2.3.4 to be allowed but wasn't") - } - if acls.IsServerBannedFromRoom("1.2.3.4:2345", roomID) { - t.Fatal("Expected 1.2.3.4:2345 to be allowed but wasn't") - } - if !acls.IsServerBannedFromRoom("foo.com", roomID) { - t.Fatal("Expected foo.com to be banned but wasn't") - } - if !acls.IsServerBannedFromRoom("foo.com:3456", roomID) { - t.Fatal("Expected foo.com:3456 to be banned but wasn't") - } - if acls.IsServerBannedFromRoom("bar.com", roomID) { - t.Fatal("Expected bar.com to be allowed but wasn't") - } - if acls.IsServerBannedFromRoom("bar.com:4567", roomID) { - t.Fatal("Expected bar.com:4567 to be allowed but wasn't") - } -} - -func TestDefaultACLsWithWhitelist(t *testing.T) { - roomID := "!test:test.com" - allowRegex, err := compileACLRegex("foo.com") - if err != nil { - t.Fatalf(err.Error()) - } - - acls := ServerACLs{ - acls: make(map[string]*serverACL), - } - - acls.acls[roomID] = &serverACL{ - ServerACL: ServerACL{ - AllowIPLiterals: false, - }, - allowedRegexes: []*regexp.Regexp{allowRegex}, - deniedRegexes: []*regexp.Regexp{}, - } - - if !acls.IsServerBannedFromRoom("1.2.3.4", roomID) { - t.Fatal("Expected 1.2.3.4 to be banned but wasn't") - } - if !acls.IsServerBannedFromRoom("1.2.3.4:2345", roomID) { - t.Fatal("Expected 1.2.3.4:2345 to be banned but wasn't") - } - if acls.IsServerBannedFromRoom("foo.com", roomID) { - t.Fatal("Expected foo.com to be allowed but wasn't") - } - if acls.IsServerBannedFromRoom("foo.com:3456", roomID) { - t.Fatal("Expected foo.com:3456 to be allowed but wasn't") - } - if !acls.IsServerBannedFromRoom("bar.com", roomID) { - t.Fatal("Expected bar.com to be allowed but wasn't") - } - if !acls.IsServerBannedFromRoom("baz.com", roomID) { - t.Fatal("Expected baz.com to be allowed but wasn't") - } - if !acls.IsServerBannedFromRoom("qux.com:4567", roomID) { - t.Fatal("Expected qux.com:4567 to be allowed but wasn't") - } -} diff --git a/currentstateserver/api/api.go b/currentstateserver/api/api.go index 5ae57bb9..4ebe2968 100644 --- a/currentstateserver/api/api.go +++ b/currentstateserver/api/api.go @@ -36,8 +36,6 @@ type CurrentStateInternalAPI interface { QuerySharedUsers(ctx context.Context, req *QuerySharedUsersRequest, res *QuerySharedUsersResponse) error // QueryKnownUsers returns a list of users that we know about from our joined rooms. QueryKnownUsers(ctx context.Context, req *QueryKnownUsersRequest, res *QueryKnownUsersResponse) error - // QueryServerBannedFromRoom returns whether a server is banned from a room by server ACLs. - QueryServerBannedFromRoom(ctx context.Context, req *QueryServerBannedFromRoomRequest, res *QueryServerBannedFromRoomResponse) error } type QuerySharedUsersRequest struct { @@ -103,15 +101,6 @@ type QueryKnownUsersResponse struct { Users []authtypes.FullyQualifiedProfile `json:"profiles"` } -type QueryServerBannedFromRoomRequest struct { - ServerName gomatrixserverlib.ServerName `json:"server_name"` - RoomID string `json:"room_id"` -} - -type QueryServerBannedFromRoomResponse struct { - Banned bool `json:"banned"` -} - // MarshalJSON stringifies the StateKeyTuple keys so they can be sent over the wire in HTTP API mode. func (r *QueryCurrentStateResponse) MarshalJSON() ([]byte, error) { se := make(map[string]*gomatrixserverlib.HeaderedEvent, len(r.StateEvents)) diff --git a/currentstateserver/api/wrapper.go b/currentstateserver/api/wrapper.go index 317fea43..146e50eb 100644 --- a/currentstateserver/api/wrapper.go +++ b/currentstateserver/api/wrapper.go @@ -39,20 +39,6 @@ func GetEvent(ctx context.Context, stateAPI CurrentStateInternalAPI, roomID stri return nil } -// IsServerBannedFromRoom returns whether the server is banned from a room by server ACLs. -func IsServerBannedFromRoom(ctx context.Context, stateAPI CurrentStateInternalAPI, roomID string, serverName gomatrixserverlib.ServerName) bool { - req := &QueryServerBannedFromRoomRequest{ - ServerName: serverName, - RoomID: roomID, - } - res := &QueryServerBannedFromRoomResponse{} - if err := stateAPI.QueryServerBannedFromRoom(ctx, req, res); err != nil { - util.GetLogger(ctx).WithError(err).Error("Failed to QueryServerBannedFromRoom") - return true - } - return res.Banned -} - // PopulatePublicRooms extracts PublicRoom information for all the provided room IDs. The IDs are not checked to see if they are visible in the // published room directory. // due to lots of switches diff --git a/currentstateserver/consumers/roomserver.go b/currentstateserver/consumers/roomserver.go index cb054481..beb13305 100644 --- a/currentstateserver/consumers/roomserver.go +++ b/currentstateserver/consumers/roomserver.go @@ -19,7 +19,6 @@ import ( "encoding/json" "github.com/Shopify/sarama" - "github.com/matrix-org/dendrite/currentstateserver/acls" "github.com/matrix-org/dendrite/currentstateserver/storage" "github.com/matrix-org/dendrite/internal" "github.com/matrix-org/dendrite/roomserver/api" @@ -31,10 +30,9 @@ import ( type OutputRoomEventConsumer struct { rsConsumer *internal.ContinualConsumer db storage.Database - acls *acls.ServerACLs } -func NewOutputRoomEventConsumer(topicName string, kafkaConsumer sarama.Consumer, store storage.Database, acls *acls.ServerACLs) *OutputRoomEventConsumer { +func NewOutputRoomEventConsumer(topicName string, kafkaConsumer sarama.Consumer, store storage.Database) *OutputRoomEventConsumer { consumer := &internal.ContinualConsumer{ ComponentName: "currentstateserver/roomserver", Topic: topicName, @@ -44,7 +42,6 @@ func NewOutputRoomEventConsumer(topicName string, kafkaConsumer sarama.Consumer, s := &OutputRoomEventConsumer{ rsConsumer: consumer, db: store, - acls: acls, } consumer.ProcessMessage = s.onMessage @@ -80,10 +77,6 @@ func (c *OutputRoomEventConsumer) onNewRoomEvent( ) error { ev := msg.Event - if ev.Type() == "m.room.server_acl" && ev.StateKeyEquals("") { - defer c.acls.OnServerACLUpdate(&ev.Event) - } - addsStateEvents := msg.AddsState() ev, err := c.updateStateEvent(ev) diff --git a/currentstateserver/currentstateserver.go b/currentstateserver/currentstateserver.go index 196434eb..f0dd4b88 100644 --- a/currentstateserver/currentstateserver.go +++ b/currentstateserver/currentstateserver.go @@ -17,7 +17,6 @@ package currentstateserver import ( "github.com/Shopify/sarama" "github.com/gorilla/mux" - "github.com/matrix-org/dendrite/currentstateserver/acls" "github.com/matrix-org/dendrite/currentstateserver/api" "github.com/matrix-org/dendrite/currentstateserver/consumers" "github.com/matrix-org/dendrite/currentstateserver/internal" @@ -40,15 +39,13 @@ func NewInternalAPI(cfg *config.CurrentStateServer, consumer sarama.Consumer) ap if err != nil { logrus.WithError(err).Panicf("failed to open database") } - serverACLs := acls.NewServerACLs(csDB) roomConsumer := consumers.NewOutputRoomEventConsumer( - cfg.Matrix.Kafka.TopicFor(config.TopicOutputRoomEvent), consumer, csDB, serverACLs, + cfg.Matrix.Kafka.TopicFor(config.TopicOutputRoomEvent), consumer, csDB, ) if err = roomConsumer.Start(); err != nil { logrus.WithError(err).Panicf("failed to start room server consumer") } return &internal.CurrentStateInternalAPI{ - DB: csDB, - ServerACLs: serverACLs, + DB: csDB, } } diff --git a/currentstateserver/internal/api.go b/currentstateserver/internal/api.go index 0a7e025e..dc255412 100644 --- a/currentstateserver/internal/api.go +++ b/currentstateserver/internal/api.go @@ -16,18 +16,15 @@ package internal import ( "context" - "errors" "github.com/matrix-org/dendrite/clientapi/auth/authtypes" - "github.com/matrix-org/dendrite/currentstateserver/acls" "github.com/matrix-org/dendrite/currentstateserver/api" "github.com/matrix-org/dendrite/currentstateserver/storage" "github.com/matrix-org/gomatrixserverlib" ) type CurrentStateInternalAPI struct { - DB storage.Database - ServerACLs *acls.ServerACLs + DB storage.Database } func (a *CurrentStateInternalAPI) QueryCurrentState(ctx context.Context, req *api.QueryCurrentStateRequest, res *api.QueryCurrentStateResponse) error { @@ -115,11 +112,3 @@ func (a *CurrentStateInternalAPI) QuerySharedUsers(ctx context.Context, req *api res.UserIDsToCount = users return nil } - -func (a *CurrentStateInternalAPI) QueryServerBannedFromRoom(ctx context.Context, req *api.QueryServerBannedFromRoomRequest, res *api.QueryServerBannedFromRoomResponse) error { - if a.ServerACLs == nil { - return errors.New("no server ACL tracking") - } - res.Banned = a.ServerACLs.IsServerBannedFromRoom(req.ServerName, req.RoomID) - return nil -} diff --git a/currentstateserver/inthttp/client.go b/currentstateserver/inthttp/client.go index 6d54f548..37d289ea 100644 --- a/currentstateserver/inthttp/client.go +++ b/currentstateserver/inthttp/client.go @@ -26,12 +26,11 @@ import ( // HTTP paths for the internal HTTP APIs const ( - QueryCurrentStatePath = "/currentstateserver/queryCurrentState" - QueryRoomsForUserPath = "/currentstateserver/queryRoomsForUser" - QueryBulkStateContentPath = "/currentstateserver/queryBulkStateContent" - QuerySharedUsersPath = "/currentstateserver/querySharedUsers" - QueryKnownUsersPath = "/currentstateserver/queryKnownUsers" - QueryServerBannedFromRoomPath = "/currentstateserver/queryServerBannedFromRoom" + QueryCurrentStatePath = "/currentstateserver/queryCurrentState" + QueryRoomsForUserPath = "/currentstateserver/queryRoomsForUser" + QueryBulkStateContentPath = "/currentstateserver/queryBulkStateContent" + QuerySharedUsersPath = "/currentstateserver/querySharedUsers" + QueryKnownUsersPath = "/currentstateserver/queryKnownUsers" ) // NewCurrentStateAPIClient creates a CurrentStateInternalAPI implemented by talking to a HTTP POST API. @@ -109,13 +108,3 @@ func (h *httpCurrentStateInternalAPI) QueryKnownUsers( apiURL := h.apiURL + QueryKnownUsersPath return httputil.PostJSON(ctx, span, h.httpClient, apiURL, req, res) } - -func (h *httpCurrentStateInternalAPI) QueryServerBannedFromRoom( - ctx context.Context, req *api.QueryServerBannedFromRoomRequest, res *api.QueryServerBannedFromRoomResponse, -) error { - span, ctx := opentracing.StartSpanFromContext(ctx, "QueryServerBannedFromRoom") - defer span.Finish() - - apiURL := h.apiURL + QueryServerBannedFromRoomPath - return httputil.PostJSON(ctx, span, h.httpClient, apiURL, req, res) -} diff --git a/currentstateserver/inthttp/server.go b/currentstateserver/inthttp/server.go index 1cf8cd2a..aee900e0 100644 --- a/currentstateserver/inthttp/server.go +++ b/currentstateserver/inthttp/server.go @@ -90,17 +90,4 @@ func AddRoutes(internalAPIMux *mux.Router, intAPI api.CurrentStateInternalAPI) { return util.JSONResponse{Code: http.StatusOK, JSON: &response} }), ) - internalAPIMux.Handle(QueryServerBannedFromRoomPath, - httputil.MakeInternalAPI("queryServerBannedFromRoom", func(req *http.Request) util.JSONResponse { - request := api.QueryServerBannedFromRoomRequest{} - response := api.QueryServerBannedFromRoomResponse{} - if err := json.NewDecoder(req.Body).Decode(&request); err != nil { - return util.MessageResponse(http.StatusBadRequest, err.Error()) - } - if err := intAPI.QueryServerBannedFromRoom(req.Context(), &request, &response); err != nil { - return util.ErrorResponse(err) - } - return util.JSONResponse{Code: http.StatusOK, JSON: &response} - }), - ) } diff --git a/federationapi/routing/routing.go b/federationapi/routing/routing.go index 5ea190a1..4c43be27 100644 --- a/federationapi/routing/routing.go +++ b/federationapi/routing/routing.go @@ -76,7 +76,7 @@ func Setup( func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { return Send( httpReq, request, gomatrixserverlib.TransactionID(vars["txnID"]), - cfg, rsAPI, eduAPI, keyAPI, stateAPI, keys, federation, + cfg, rsAPI, eduAPI, keyAPI, keys, federation, ) }, )).Methods(http.MethodPut, http.MethodOptions) @@ -84,7 +84,7 @@ func Setup( v1fedmux.Handle("/invite/{roomID}/{eventID}", httputil.MakeFedAPI( "federation_invite", cfg.Matrix.ServerName, keys, wakeup, func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { - if currentstateAPI.IsServerBannedFromRoom(httpReq.Context(), stateAPI, vars["roomID"], request.Origin()) { + if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { return util.JSONResponse{ Code: http.StatusForbidden, JSON: jsonerror.Forbidden("Forbidden by server ACLs"), @@ -100,7 +100,7 @@ func Setup( v2fedmux.Handle("/invite/{roomID}/{eventID}", httputil.MakeFedAPI( "federation_invite", cfg.Matrix.ServerName, keys, wakeup, func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { - if currentstateAPI.IsServerBannedFromRoom(httpReq.Context(), stateAPI, vars["roomID"], request.Origin()) { + if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { return util.JSONResponse{ Code: http.StatusForbidden, JSON: jsonerror.Forbidden("Forbidden by server ACLs"), @@ -140,7 +140,7 @@ func Setup( v1fedmux.Handle("/state/{roomID}", httputil.MakeFedAPI( "federation_get_state", cfg.Matrix.ServerName, keys, wakeup, func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { - if currentstateAPI.IsServerBannedFromRoom(httpReq.Context(), stateAPI, vars["roomID"], request.Origin()) { + if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { return util.JSONResponse{ Code: http.StatusForbidden, JSON: jsonerror.Forbidden("Forbidden by server ACLs"), @@ -155,7 +155,7 @@ func Setup( v1fedmux.Handle("/state_ids/{roomID}", httputil.MakeFedAPI( "federation_get_state_ids", cfg.Matrix.ServerName, keys, wakeup, func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { - if currentstateAPI.IsServerBannedFromRoom(httpReq.Context(), stateAPI, vars["roomID"], request.Origin()) { + if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { return util.JSONResponse{ Code: http.StatusForbidden, JSON: jsonerror.Forbidden("Forbidden by server ACLs"), @@ -170,7 +170,7 @@ func Setup( v1fedmux.Handle("/event_auth/{roomID}/{eventID}", httputil.MakeFedAPI( "federation_get_event_auth", cfg.Matrix.ServerName, keys, wakeup, func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { - if currentstateAPI.IsServerBannedFromRoom(httpReq.Context(), stateAPI, vars["roomID"], request.Origin()) { + if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { return util.JSONResponse{ Code: http.StatusForbidden, JSON: jsonerror.Forbidden("Forbidden by server ACLs"), @@ -212,7 +212,7 @@ func Setup( v1fedmux.Handle("/make_join/{roomID}/{eventID}", httputil.MakeFedAPI( "federation_make_join", cfg.Matrix.ServerName, keys, wakeup, func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { - if currentstateAPI.IsServerBannedFromRoom(httpReq.Context(), stateAPI, vars["roomID"], request.Origin()) { + if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { return util.JSONResponse{ Code: http.StatusForbidden, JSON: jsonerror.Forbidden("Forbidden by server ACLs"), @@ -243,7 +243,7 @@ func Setup( v1fedmux.Handle("/send_join/{roomID}/{eventID}", httputil.MakeFedAPI( "federation_send_join", cfg.Matrix.ServerName, keys, wakeup, func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { - if currentstateAPI.IsServerBannedFromRoom(httpReq.Context(), stateAPI, vars["roomID"], request.Origin()) { + if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { return util.JSONResponse{ Code: http.StatusForbidden, JSON: jsonerror.Forbidden("Forbidden by server ACLs"), @@ -275,7 +275,7 @@ func Setup( v2fedmux.Handle("/send_join/{roomID}/{eventID}", httputil.MakeFedAPI( "federation_send_join", cfg.Matrix.ServerName, keys, wakeup, func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { - if currentstateAPI.IsServerBannedFromRoom(httpReq.Context(), stateAPI, vars["roomID"], request.Origin()) { + if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { return util.JSONResponse{ Code: http.StatusForbidden, JSON: jsonerror.Forbidden("Forbidden by server ACLs"), @@ -292,7 +292,7 @@ func Setup( v1fedmux.Handle("/make_leave/{roomID}/{eventID}", httputil.MakeFedAPI( "federation_make_leave", cfg.Matrix.ServerName, keys, wakeup, func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { - if currentstateAPI.IsServerBannedFromRoom(httpReq.Context(), stateAPI, vars["roomID"], request.Origin()) { + if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { return util.JSONResponse{ Code: http.StatusForbidden, JSON: jsonerror.Forbidden("Forbidden by server ACLs"), @@ -309,7 +309,7 @@ func Setup( v1fedmux.Handle("/send_leave/{roomID}/{eventID}", httputil.MakeFedAPI( "federation_send_leave", cfg.Matrix.ServerName, keys, wakeup, func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { - if currentstateAPI.IsServerBannedFromRoom(httpReq.Context(), stateAPI, vars["roomID"], request.Origin()) { + if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { return util.JSONResponse{ Code: http.StatusForbidden, JSON: jsonerror.Forbidden("Forbidden by server ACLs"), @@ -341,7 +341,7 @@ func Setup( v2fedmux.Handle("/send_leave/{roomID}/{eventID}", httputil.MakeFedAPI( "federation_send_leave", cfg.Matrix.ServerName, keys, wakeup, func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { - if currentstateAPI.IsServerBannedFromRoom(httpReq.Context(), stateAPI, vars["roomID"], request.Origin()) { + if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { return util.JSONResponse{ Code: http.StatusForbidden, JSON: jsonerror.Forbidden("Forbidden by server ACLs"), @@ -365,7 +365,7 @@ func Setup( v1fedmux.Handle("/get_missing_events/{roomID}", httputil.MakeFedAPI( "federation_get_missing_events", cfg.Matrix.ServerName, keys, wakeup, func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { - if currentstateAPI.IsServerBannedFromRoom(httpReq.Context(), stateAPI, vars["roomID"], request.Origin()) { + if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { return util.JSONResponse{ Code: http.StatusForbidden, JSON: jsonerror.Forbidden("Forbidden by server ACLs"), @@ -378,7 +378,7 @@ func Setup( v1fedmux.Handle("/backfill/{roomID}", httputil.MakeFedAPI( "federation_backfill", cfg.Matrix.ServerName, keys, wakeup, func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { - if currentstateAPI.IsServerBannedFromRoom(httpReq.Context(), stateAPI, vars["roomID"], request.Origin()) { + if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { return util.JSONResponse{ Code: http.StatusForbidden, JSON: jsonerror.Forbidden("Forbidden by server ACLs"), diff --git a/federationapi/routing/send.go b/federationapi/routing/send.go index 570062ad..beb7d461 100644 --- a/federationapi/routing/send.go +++ b/federationapi/routing/send.go @@ -21,7 +21,6 @@ import ( "net/http" "github.com/matrix-org/dendrite/clientapi/jsonerror" - currentstateAPI "github.com/matrix-org/dendrite/currentstateserver/api" eduserverAPI "github.com/matrix-org/dendrite/eduserver/api" "github.com/matrix-org/dendrite/internal/config" keyapi "github.com/matrix-org/dendrite/keyserver/api" @@ -40,7 +39,6 @@ func Send( rsAPI api.RoomserverInternalAPI, eduAPI eduserverAPI.EDUServerInputAPI, keyAPI keyapi.KeyInternalAPI, - stateAPI currentstateAPI.CurrentStateInternalAPI, keys gomatrixserverlib.JSONVerifier, federation *gomatrixserverlib.FederationClient, ) util.JSONResponse { @@ -48,7 +46,6 @@ func Send( context: httpReq.Context(), rsAPI: rsAPI, eduAPI: eduAPI, - stateAPI: stateAPI, keys: keys, federation: federation, haveEvents: make(map[string]*gomatrixserverlib.HeaderedEvent), @@ -107,7 +104,6 @@ type txnReq struct { rsAPI api.RoomserverInternalAPI eduAPI eduserverAPI.EDUServerInputAPI keyAPI keyapi.KeyInternalAPI - stateAPI currentstateAPI.CurrentStateInternalAPI keys gomatrixserverlib.JSONVerifier federation txnFederationClient // local cache of events for auth checks, etc - this may include events @@ -168,7 +164,7 @@ func (t *txnReq) processTransaction() (*gomatrixserverlib.RespSend, *util.JSONRe util.GetLogger(t.context).WithError(err).Warnf("Transaction: Failed to parse event JSON of event %s", string(pdu)) continue } - if currentstateAPI.IsServerBannedFromRoom(t.context, t.stateAPI, event.RoomID(), t.Origin) { + if api.IsServerBannedFromRoom(t.context, t.rsAPI, event.RoomID(), t.Origin) { results[event.EventID()] = gomatrixserverlib.PDUResult{ Error: "Forbidden by server ACLs", } diff --git a/federationapi/routing/send_test.go b/federationapi/routing/send_test.go index 6dc8621b..f16fde0e 100644 --- a/federationapi/routing/send_test.go +++ b/federationapi/routing/send_test.go @@ -8,7 +8,6 @@ import ( "testing" "time" - currentstateAPI "github.com/matrix-org/dendrite/currentstateserver/api" eduAPI "github.com/matrix-org/dendrite/eduserver/api" fsAPI "github.com/matrix-org/dendrite/federationsender/api" "github.com/matrix-org/dendrite/internal/test" @@ -320,33 +319,6 @@ func (t *testRoomserverAPI) QueryServerBannedFromRoom(ctx context.Context, req * return nil } -type testStateAPI struct { -} - -func (t *testStateAPI) QueryCurrentState(ctx context.Context, req *currentstateAPI.QueryCurrentStateRequest, res *currentstateAPI.QueryCurrentStateResponse) error { - return nil -} - -func (t *testStateAPI) QueryRoomsForUser(ctx context.Context, req *currentstateAPI.QueryRoomsForUserRequest, res *currentstateAPI.QueryRoomsForUserResponse) error { - return fmt.Errorf("not implemented") -} - -func (t *testStateAPI) QueryBulkStateContent(ctx context.Context, req *currentstateAPI.QueryBulkStateContentRequest, res *currentstateAPI.QueryBulkStateContentResponse) error { - return fmt.Errorf("not implemented") -} - -func (t *testStateAPI) QuerySharedUsers(ctx context.Context, req *currentstateAPI.QuerySharedUsersRequest, res *currentstateAPI.QuerySharedUsersResponse) error { - return fmt.Errorf("not implemented") -} - -func (t *testStateAPI) QueryKnownUsers(ctx context.Context, req *currentstateAPI.QueryKnownUsersRequest, res *currentstateAPI.QueryKnownUsersResponse) error { - return fmt.Errorf("not implemented") -} - -func (t *testStateAPI) QueryServerBannedFromRoom(ctx context.Context, req *currentstateAPI.QueryServerBannedFromRoomRequest, res *currentstateAPI.QueryServerBannedFromRoomResponse) error { - return nil -} - type txnFedClient struct { state map[string]gomatrixserverlib.RespState // event_id to response stateIDs map[string]gomatrixserverlib.RespStateIDs // event_id to response @@ -391,12 +363,11 @@ func (c *txnFedClient) LookupMissingEvents(ctx context.Context, s gomatrixserver return c.getMissingEvents(missing) } -func mustCreateTransaction(rsAPI api.RoomserverInternalAPI, stateAPI currentstateAPI.CurrentStateInternalAPI, fedClient txnFederationClient, pdus []json.RawMessage) *txnReq { +func mustCreateTransaction(rsAPI api.RoomserverInternalAPI, fedClient txnFederationClient, pdus []json.RawMessage) *txnReq { t := &txnReq{ context: context.Background(), rsAPI: rsAPI, eduAPI: &testEDUProducer{}, - stateAPI: stateAPI, keys: &test.NopJSONVerifier{}, federation: fedClient, haveEvents: make(map[string]*gomatrixserverlib.HeaderedEvent), @@ -476,11 +447,10 @@ func TestBasicTransaction(t *testing.T) { } }, } - stateAPI := &testStateAPI{} pdus := []json.RawMessage{ testData[len(testData)-1], // a message event } - txn := mustCreateTransaction(rsAPI, stateAPI, &txnFedClient{}, pdus) + txn := mustCreateTransaction(rsAPI, &txnFedClient{}, pdus) mustProcessTransaction(t, txn, nil) assertInputRoomEvents(t, rsAPI.inputRoomEvents, []gomatrixserverlib.HeaderedEvent{testEvents[len(testEvents)-1]}) } @@ -499,11 +469,10 @@ func TestTransactionFailAuthChecks(t *testing.T) { } }, } - stateAPI := &testStateAPI{} pdus := []json.RawMessage{ testData[len(testData)-1], // a message event } - txn := mustCreateTransaction(rsAPI, stateAPI, &txnFedClient{}, pdus) + txn := mustCreateTransaction(rsAPI, &txnFedClient{}, pdus) mustProcessTransaction(t, txn, []string{ // expect the event to have an error testEvents[len(testEvents)-1].EventID(), @@ -558,8 +527,6 @@ func TestTransactionFetchMissingPrevEvents(t *testing.T) { }, } - stateAPI := &testStateAPI{} - cli := &txnFedClient{ getMissingEvents: func(missing gomatrixserverlib.MissingEvents) (res gomatrixserverlib.RespMissingEvents, err error) { if !reflect.DeepEqual(missing.EarliestEvents, []string{haveEvent.EventID()}) { @@ -579,7 +546,7 @@ func TestTransactionFetchMissingPrevEvents(t *testing.T) { pdus := []json.RawMessage{ inputEvent.JSON(), } - txn := mustCreateTransaction(rsAPI, stateAPI, cli, pdus) + txn := mustCreateTransaction(rsAPI, cli, pdus) mustProcessTransaction(t, txn, nil) assertInputRoomEvents(t, rsAPI.inputRoomEvents, []gomatrixserverlib.HeaderedEvent{prevEvent, inputEvent}) } @@ -729,12 +696,10 @@ func TestTransactionFetchMissingStateByStateIDs(t *testing.T) { }, } - stateAPI := &testStateAPI{} - pdus := []json.RawMessage{ eventD.JSON(), } - txn := mustCreateTransaction(rsAPI, stateAPI, cli, pdus) + txn := mustCreateTransaction(rsAPI, cli, pdus) mustProcessTransaction(t, txn, nil) assertInputRoomEvents(t, rsAPI.inputRoomEvents, []gomatrixserverlib.HeaderedEvent{eventB, eventC, eventD}) } diff --git a/federationsender/federationsender.go b/federationsender/federationsender.go index 5794d40a..0e2213da 100644 --- a/federationsender/federationsender.go +++ b/federationsender/federationsender.go @@ -59,7 +59,7 @@ func NewInternalAPI( queues := queue.NewOutgoingQueues( federationSenderDB, cfg.Matrix.ServerName, federation, - rsAPI, stateAPI, stats, + rsAPI, stats, &queue.SigningInfo{ KeyID: cfg.Matrix.KeyID, PrivateKey: cfg.Matrix.PrivateKey, diff --git a/federationsender/queue/queue.go b/federationsender/queue/queue.go index b13df612..04cb57e7 100644 --- a/federationsender/queue/queue.go +++ b/federationsender/queue/queue.go @@ -22,7 +22,6 @@ import ( "sync" "time" - stateapi "github.com/matrix-org/dendrite/currentstateserver/api" "github.com/matrix-org/dendrite/federationsender/statistics" "github.com/matrix-org/dendrite/federationsender/storage" "github.com/matrix-org/dendrite/roomserver/api" @@ -36,7 +35,6 @@ import ( type OutgoingQueues struct { db storage.Database rsAPI api.RoomserverInternalAPI - stateAPI stateapi.CurrentStateInternalAPI origin gomatrixserverlib.ServerName client *gomatrixserverlib.FederationClient statistics *statistics.Statistics @@ -51,14 +49,12 @@ func NewOutgoingQueues( origin gomatrixserverlib.ServerName, client *gomatrixserverlib.FederationClient, rsAPI api.RoomserverInternalAPI, - stateAPI stateapi.CurrentStateInternalAPI, statistics *statistics.Statistics, signing *SigningInfo, ) *OutgoingQueues { queues := &OutgoingQueues{ db: db, rsAPI: rsAPI, - stateAPI: stateAPI, origin: origin, client: client, statistics: statistics, @@ -144,9 +140,9 @@ func (oqs *OutgoingQueues) SendEvent( // Check if any of the destinations are prohibited by server ACLs. for destination := range destmap { - if stateapi.IsServerBannedFromRoom( + if api.IsServerBannedFromRoom( context.TODO(), - oqs.stateAPI, + oqs.rsAPI, ev.RoomID(), destination, ) { @@ -208,9 +204,9 @@ func (oqs *OutgoingQueues) SendEDU( // ACLs. if result := gjson.GetBytes(e.Content, "room_id"); result.Exists() { for destination := range destmap { - if stateapi.IsServerBannedFromRoom( + if api.IsServerBannedFromRoom( context.TODO(), - oqs.stateAPI, + oqs.rsAPI, result.Str, destination, ) { diff --git a/roomserver/internal/api.go b/roomserver/internal/api.go index bdea650e..4299dd47 100644 --- a/roomserver/internal/api.go +++ b/roomserver/internal/api.go @@ -40,6 +40,7 @@ func NewRoomserverAPI( outputRoomEventTopic string, caches caching.RoomServerCaches, keyRing gomatrixserverlib.JSONVerifier, ) *RoomserverInternalAPI { + serverACLs := acls.NewServerACLs(roomserverDB) a := &RoomserverInternalAPI{ DB: roomserverDB, Cfg: cfg, @@ -49,13 +50,14 @@ func NewRoomserverAPI( Queryer: &query.Queryer{ DB: roomserverDB, Cache: caches, - ServerACLs: acls.NewServerACLs(roomserverDB), + ServerACLs: serverACLs, }, Inputer: &input.Inputer{ DB: roomserverDB, OutputRoomEventTopic: outputRoomEventTopic, Producer: producer, ServerName: cfg.Matrix.ServerName, + ACLs: serverACLs, }, // perform-er structs get initialised when we have a federation sender to use } diff --git a/roomserver/internal/input/input.go b/roomserver/internal/input/input.go index 7a44ff42..51d20ad3 100644 --- a/roomserver/internal/input/input.go +++ b/roomserver/internal/input/input.go @@ -22,6 +22,7 @@ import ( "time" "github.com/Shopify/sarama" + "github.com/matrix-org/dendrite/roomserver/acls" "github.com/matrix-org/dendrite/roomserver/api" "github.com/matrix-org/dendrite/roomserver/storage" "github.com/matrix-org/gomatrixserverlib" @@ -33,6 +34,7 @@ type Inputer struct { DB storage.Database Producer sarama.SyncProducer ServerName gomatrixserverlib.ServerName + ACLs *acls.ServerACLs OutputRoomEventTopic string workers sync.Map // room ID -> *inputWorker @@ -88,6 +90,10 @@ func (r *Inputer) WriteOutputEvents(roomID string, updates []api.OutputEvent) er "send_as_server": updates[i].NewRoomEvent.SendAsServer, "sender": updates[i].NewRoomEvent.Event.Sender(), }) + if updates[i].NewRoomEvent.Event.Type() == "m.room.server_acl" && updates[i].NewRoomEvent.Event.StateKeyEquals("") { + ev := updates[i].NewRoomEvent.Event.Unwrap() + defer r.ACLs.OnServerACLUpdate(&ev) + } } logger.Infof("Producing to topic '%s'", r.OutputRoomEventTopic) messages[i] = &sarama.ProducerMessage{ diff --git a/syncapi/internal/keychange_test.go b/syncapi/internal/keychange_test.go index baf60ef0..6765fa65 100644 --- a/syncapi/internal/keychange_test.go +++ b/syncapi/internal/keychange_test.go @@ -114,10 +114,6 @@ func (s *mockCurrentStateAPI) QuerySharedUsers(ctx context.Context, req *api.Que return nil } -func (t *mockCurrentStateAPI) QueryServerBannedFromRoom(ctx context.Context, req *api.QueryServerBannedFromRoomRequest, res *api.QueryServerBannedFromRoomResponse) error { - return nil -} - type wantCatchup struct { hasNew bool changed []string