From 93942f8ab62ffdb55888d5d35adef6fe73e3ea59 Mon Sep 17 00:00:00 2001 From: Kegsay Date: Fri, 22 Jan 2021 16:08:47 +0000 Subject: [PATCH] Gate peeking behind msc flags (#1731) --- clientapi/clientapi.go | 3 +- clientapi/routing/routing.go | 32 ++++++----- .../personalities/clientapi.go | 1 + .../personalities/federationapi.go | 1 + cmd/generate-config/main.go | 2 +- federationapi/federationapi.go | 3 +- federationapi/federationapi_test.go | 2 +- federationapi/routing/routing.go | 57 ++++++++++--------- setup/config/config_mscs.go | 16 +++++- setup/monolith.go | 3 +- setup/mscs/mscs.go | 3 + 11 files changed, 76 insertions(+), 47 deletions(-) diff --git a/clientapi/clientapi.go b/clientapi/clientapi.go index 8a2ea8fc..2c4fa5d6 100644 --- a/clientapi/clientapi.go +++ b/clientapi/clientapi.go @@ -46,6 +46,7 @@ func AddPublicRoutes( userAPI userapi.UserInternalAPI, keyAPI keyserverAPI.KeyInternalAPI, extRoomsProvider api.ExtraPublicRoomsProvider, + mscCfg *config.MSCs, ) { _, producer := kafka.SetupConsumerProducer(&cfg.Matrix.Kafka) @@ -57,6 +58,6 @@ func AddPublicRoutes( routing.Setup( router, cfg, eduInputAPI, rsAPI, asAPI, accountsDB, userAPI, federation, - syncProducer, transactionsCache, fsAPI, keyAPI, extRoomsProvider, + syncProducer, transactionsCache, fsAPI, keyAPI, extRoomsProvider, mscCfg, ) } diff --git a/clientapi/routing/routing.go b/clientapi/routing/routing.go index 7c320253..a56359b4 100644 --- a/clientapi/routing/routing.go +++ b/clientapi/routing/routing.go @@ -58,6 +58,7 @@ func Setup( federationSender federationSenderAPI.FederationSenderInternalAPI, keyAPI keyserverAPI.KeyInternalAPI, extRoomsProvider api.ExtraPublicRoomsProvider, + mscCfg *config.MSCs, ) { rateLimits := newRateLimits(&cfg.RateLimiting) userInteractiveAuth := auth.NewUserInteractive(accountDB.GetAccountByPassword, cfg) @@ -110,20 +111,23 @@ func Setup( ) }), ).Methods(http.MethodPost, http.MethodOptions) - r0mux.Handle("/peek/{roomIDOrAlias}", - httputil.MakeAuthAPI(gomatrixserverlib.Peek, userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse { - if r := rateLimits.rateLimit(req); r != nil { - return *r - } - vars, err := httputil.URLDecodeMapValues(mux.Vars(req)) - if err != nil { - return util.ErrorResponse(err) - } - return PeekRoomByIDOrAlias( - req, device, rsAPI, accountDB, vars["roomIDOrAlias"], - ) - }), - ).Methods(http.MethodPost, http.MethodOptions) + + if mscCfg.Enabled("msc2753") { + r0mux.Handle("/peek/{roomIDOrAlias}", + httputil.MakeAuthAPI(gomatrixserverlib.Peek, userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse { + if r := rateLimits.rateLimit(req); r != nil { + return *r + } + vars, err := httputil.URLDecodeMapValues(mux.Vars(req)) + if err != nil { + return util.ErrorResponse(err) + } + return PeekRoomByIDOrAlias( + req, device, rsAPI, accountDB, vars["roomIDOrAlias"], + ) + }), + ).Methods(http.MethodPost, http.MethodOptions) + } r0mux.Handle("/joined_rooms", httputil.MakeAuthAPI("joined_rooms", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse { return GetJoinedRooms(req, device, rsAPI) diff --git a/cmd/dendrite-polylith-multi/personalities/clientapi.go b/cmd/dendrite-polylith-multi/personalities/clientapi.go index b3cc411b..ec445ceb 100644 --- a/cmd/dendrite-polylith-multi/personalities/clientapi.go +++ b/cmd/dendrite-polylith-multi/personalities/clientapi.go @@ -35,6 +35,7 @@ func ClientAPI(base *setup.BaseDendrite, cfg *config.Dendrite) { clientapi.AddPublicRoutes( base.PublicClientAPIMux, &base.Cfg.ClientAPI, accountDB, federation, rsAPI, eduInputAPI, asQuery, transactions.New(), fsAPI, userAPI, keyAPI, nil, + &cfg.MSCs, ) base.SetupAndServeHTTP( diff --git a/cmd/dendrite-polylith-multi/personalities/federationapi.go b/cmd/dendrite-polylith-multi/personalities/federationapi.go index 7957b211..498be3c4 100644 --- a/cmd/dendrite-polylith-multi/personalities/federationapi.go +++ b/cmd/dendrite-polylith-multi/personalities/federationapi.go @@ -33,6 +33,7 @@ func FederationAPI(base *setup.BaseDendrite, cfg *config.Dendrite) { base.PublicFederationAPIMux, base.PublicKeyAPIMux, &base.Cfg.FederationAPI, userAPI, federation, keyRing, rsAPI, fsAPI, base.EDUServerClient(), keyAPI, + &base.Cfg.MSCs, ) base.SetupAndServeHTTP( diff --git a/cmd/generate-config/main.go b/cmd/generate-config/main.go index ff0b311a..fa0da10c 100644 --- a/cmd/generate-config/main.go +++ b/cmd/generate-config/main.go @@ -63,7 +63,7 @@ func main() { if *defaultsForCI { cfg.ClientAPI.RateLimiting.Enabled = false cfg.FederationSender.DisableTLSValidation = true - cfg.MSCs.MSCs = []string{"msc2836", "msc2946"} + cfg.MSCs.MSCs = []string{"msc2836", "msc2946", "msc2444", "msc2753"} cfg.Logging[0].Level = "trace" // don't hit matrix.org when running tests!!! cfg.SigningKeyServer.KeyPerspectives = config.KeyPerspectives{} diff --git a/federationapi/federationapi.go b/federationapi/federationapi.go index 350d5853..6188b283 100644 --- a/federationapi/federationapi.go +++ b/federationapi/federationapi.go @@ -38,10 +38,11 @@ func AddPublicRoutes( federationSenderAPI federationSenderAPI.FederationSenderInternalAPI, eduAPI eduserverAPI.EDUServerInputAPI, keyAPI keyserverAPI.KeyInternalAPI, + mscCfg *config.MSCs, ) { routing.Setup( fedRouter, keyRouter, cfg, rsAPI, eduAPI, federationSenderAPI, keyRing, - federation, userAPI, keyAPI, + federation, userAPI, keyAPI, mscCfg, ) } diff --git a/federationapi/federationapi_test.go b/federationapi/federationapi_test.go index aed47a36..923cd0ec 100644 --- a/federationapi/federationapi_test.go +++ b/federationapi/federationapi_test.go @@ -31,7 +31,7 @@ func TestRoomsV3URLEscapeDoNot404(t *testing.T) { fsAPI := base.FederationSenderHTTPClient() // TODO: This is pretty fragile, as if anything calls anything on these nils this test will break. // Unfortunately, it makes little sense to instantiate these dependencies when we just want to test routing. - federationapi.AddPublicRoutes(base.PublicFederationAPIMux, base.PublicKeyAPIMux, &cfg.FederationAPI, nil, nil, keyRing, nil, fsAPI, nil, nil) + federationapi.AddPublicRoutes(base.PublicFederationAPIMux, base.PublicKeyAPIMux, &cfg.FederationAPI, nil, nil, keyRing, nil, fsAPI, nil, nil, &cfg.MSCs) baseURL, cancel := test.ListenAndServe(t, base.PublicFederationAPIMux, true) defer cancel() serverName := gomatrixserverlib.ServerName(strings.TrimPrefix(baseURL, "https://")) diff --git a/federationapi/routing/routing.go b/federationapi/routing/routing.go index 7e76a143..b579ae1f 100644 --- a/federationapi/routing/routing.go +++ b/federationapi/routing/routing.go @@ -48,6 +48,7 @@ func Setup( federation *gomatrixserverlib.FederationClient, userAPI userapi.UserInternalAPI, keyAPI keyserverAPI.KeyInternalAPI, + mscCfg *config.MSCs, ) { v2keysmux := keyMux.PathPrefix("/v2").Subrouter() v1fedmux := fedMux.PathPrefix("/v1").Subrouter() @@ -229,35 +230,37 @@ func Setup( }, )).Methods(http.MethodGet) - v1fedmux.Handle("/peek/{roomID}/{peekID}", httputil.MakeFedAPI( - "federation_peek", cfg.Matrix.ServerName, keys, wakeup, - func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { - if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { - return util.JSONResponse{ - Code: http.StatusForbidden, - JSON: jsonerror.Forbidden("Forbidden by server ACLs"), + if mscCfg.Enabled("msc2444") { + v1fedmux.Handle("/peek/{roomID}/{peekID}", httputil.MakeFedAPI( + "federation_peek", cfg.Matrix.ServerName, keys, wakeup, + func(httpReq *http.Request, request *gomatrixserverlib.FederationRequest, vars map[string]string) util.JSONResponse { + if roomserverAPI.IsServerBannedFromRoom(httpReq.Context(), rsAPI, vars["roomID"], request.Origin()) { + return util.JSONResponse{ + Code: http.StatusForbidden, + JSON: jsonerror.Forbidden("Forbidden by server ACLs"), + } } - } - roomID := vars["roomID"] - peekID := vars["peekID"] - queryVars := httpReq.URL.Query() - remoteVersions := []gomatrixserverlib.RoomVersion{} - if vers, ok := queryVars["ver"]; ok { - // The remote side supplied a ?ver= so use that to build up the list - // of supported room versions - for _, v := range vers { - remoteVersions = append(remoteVersions, gomatrixserverlib.RoomVersion(v)) + roomID := vars["roomID"] + peekID := vars["peekID"] + queryVars := httpReq.URL.Query() + remoteVersions := []gomatrixserverlib.RoomVersion{} + if vers, ok := queryVars["ver"]; ok { + // The remote side supplied a ?ver= so use that to build up the list + // of supported room versions + for _, v := range vers { + remoteVersions = append(remoteVersions, gomatrixserverlib.RoomVersion(v)) + } + } else { + // The remote side didn't supply a ?ver= so just assume that they only + // support room version 1 + remoteVersions = append(remoteVersions, gomatrixserverlib.RoomVersionV1) } - } else { - // The remote side didn't supply a ?ver= so just assume that they only - // support room version 1 - remoteVersions = append(remoteVersions, gomatrixserverlib.RoomVersionV1) - } - return Peek( - httpReq, request, cfg, rsAPI, roomID, peekID, remoteVersions, - ) - }, - )).Methods(http.MethodPut, http.MethodDelete) + return Peek( + httpReq, request, cfg, rsAPI, roomID, peekID, remoteVersions, + ) + }, + )).Methods(http.MethodPut, http.MethodDelete) + } v1fedmux.Handle("/make_join/{roomID}/{userID}", httputil.MakeFedAPI( "federation_make_join", cfg.Matrix.ServerName, keys, wakeup, diff --git a/setup/config/config_mscs.go b/setup/config/config_mscs.go index 4b53495f..764273ec 100644 --- a/setup/config/config_mscs.go +++ b/setup/config/config_mscs.go @@ -3,7 +3,11 @@ package config type MSCs struct { Matrix *Global `yaml:"-"` - // The MSCs to enable + // The MSCs to enable. Supported MSCs include: + // 'msc2444': Peeking over federation - https://github.com/matrix-org/matrix-doc/pull/2444 + // 'msc2753': Peeking via /sync - https://github.com/matrix-org/matrix-doc/pull/2753 + // 'msc2836': Threading - https://github.com/matrix-org/matrix-doc/pull/2836 + // 'msc2946': Spaces Summary - https://github.com/matrix-org/matrix-doc/pull/2946 MSCs []string `yaml:"mscs"` Database DatabaseOptions `yaml:"database"` @@ -14,6 +18,16 @@ func (c *MSCs) Defaults() { c.Database.ConnectionString = "file:mscs.db" } +// Enabled returns true if the given msc is enabled. Should in the form 'msc12345'. +func (c *MSCs) Enabled(msc string) bool { + for _, m := range c.MSCs { + if m == msc { + return true + } + } + return false +} + func (c *MSCs) Verify(configErrs *ConfigErrors, isMonolith bool) { checkNotEmpty(configErrs, "mscs.database.connection_string", string(c.Database.ConnectionString)) } diff --git a/setup/monolith.go b/setup/monolith.go index 2403f57f..fd84ef53 100644 --- a/setup/monolith.go +++ b/setup/monolith.go @@ -62,11 +62,12 @@ func (m *Monolith) AddAllPublicRoutes(csMux, ssMux, keyMux, mediaMux *mux.Router m.FedClient, m.RoomserverAPI, m.EDUInternalAPI, m.AppserviceAPI, transactions.New(), m.FederationSenderAPI, m.UserAPI, m.KeyAPI, m.ExtPublicRoomsProvider, + &m.Config.MSCs, ) federationapi.AddPublicRoutes( ssMux, keyMux, &m.Config.FederationAPI, m.UserAPI, m.FedClient, m.KeyRing, m.RoomserverAPI, m.FederationSenderAPI, - m.EDUInternalAPI, m.KeyAPI, + m.EDUInternalAPI, m.KeyAPI, &m.Config.MSCs, ) mediaapi.AddPublicRoutes(mediaMux, &m.Config.MediaAPI, m.UserAPI, m.Client) syncapi.AddPublicRoutes( diff --git a/setup/mscs/mscs.go b/setup/mscs/mscs.go index 027885c8..da02956b 100644 --- a/setup/mscs/mscs.go +++ b/setup/mscs/mscs.go @@ -42,7 +42,10 @@ func EnableMSC(base *setup.BaseDendrite, monolith *setup.Monolith, msc string) e return msc2836.Enable(base, monolith.RoomserverAPI, monolith.FederationSenderAPI, monolith.UserAPI, monolith.KeyRing) case "msc2946": return msc2946.Enable(base, monolith.RoomserverAPI, monolith.UserAPI, monolith.FederationSenderAPI, monolith.KeyRing) + case "msc2444": // enabled inside federationapi + case "msc2753": // enabled inside clientapi default: return fmt.Errorf("EnableMSC: unknown msc '%s'", msc) } + return nil }