From 88c381e0fc1d67fd8f5ea4b0bc873a017152a809 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Wed, 3 Mar 2021 16:50:05 +0000 Subject: [PATCH 01/10] Tweak AS registration check --- clientapi/routing/register.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/clientapi/routing/register.go b/clientapi/routing/register.go index 614e19d50d..9e09d74d46 100644 --- a/clientapi/routing/register.go +++ b/clientapi/routing/register.go @@ -591,9 +591,10 @@ func handleRegistrationFlow( accessToken, accessTokenErr := auth.ExtractAccessToken(req) // Appservices are special and are not affected by disabled - // registration or user exclusivity. - if r.Auth.Type == authtypes.LoginTypeApplicationService || - (r.Auth.Type == "" && accessTokenErr == nil) { + // registration or user exclusivity. We'll go onto the appservice + // registration flow if a valid access token was provided or if + // the login type specifically requests it. + if r.Auth.Type == authtypes.LoginTypeApplicationService || accessTokenErr == nil { return handleApplicationServiceRegistration( accessToken, accessTokenErr, req, r, cfg, userAPI, ) From 2e70ef44036d13770576f0991704792a8987742e Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 4 Mar 2021 13:14:16 +0000 Subject: [PATCH 02/10] Check appservice usernames using correct function --- clientapi/routing/register.go | 23 ++++++++++++++++++----- sytest-whitelist | 3 +++ 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/clientapi/routing/register.go b/clientapi/routing/register.go index 9e09d74d46..41e3777338 100644 --- a/clientapi/routing/register.go +++ b/clientapi/routing/register.go @@ -46,6 +46,7 @@ import ( "github.com/matrix-org/gomatrixserverlib/tokens" "github.com/matrix-org/util" "github.com/prometheus/client_golang/prometheus" + "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" ) @@ -496,11 +497,20 @@ func Register( r.Username = strconv.FormatInt(id, 10) } + // Is this an appservice registration? It will be if the access + // token is supplied + accessToken, accessTokenErr := auth.ExtractAccessToken(req) + // Squash username to all lowercase letters r.Username = strings.ToLower(r.Username) - - if resErr = validateUsername(r.Username); resErr != nil { - return *resErr + if r.Auth.Type == authtypes.LoginTypeApplicationService || accessTokenErr == nil { + if resErr = validateApplicationServiceUsername(r.Username); resErr != nil { + return *resErr + } + } else { + if resErr = validateUsername(r.Username); resErr != nil { + return *resErr + } } if resErr = validatePassword(r.Password); resErr != nil { return *resErr @@ -513,7 +523,7 @@ func Register( "session_id": r.Auth.Session, }).Info("Processing registration request") - return handleRegistrationFlow(req, r, sessionID, cfg, userAPI) + return handleRegistrationFlow(req, r, sessionID, cfg, userAPI, accessToken, accessTokenErr) } func handleGuestRegistration( @@ -579,6 +589,8 @@ func handleRegistrationFlow( sessionID string, cfg *config.ClientAPI, userAPI userapi.UserInternalAPI, + accessToken string, + accessTokenErr error, ) util.JSONResponse { // TODO: Shared secret registration (create new user scripts) // TODO: Enable registration config flag @@ -588,7 +600,6 @@ func handleRegistrationFlow( // TODO: Handle mapping registrationRequest parameters into session parameters // TODO: email / msisdn auth types. - accessToken, accessTokenErr := auth.ExtractAccessToken(req) // Appservices are special and are not affected by disabled // registration or user exclusivity. We'll go onto the appservice @@ -680,6 +691,8 @@ func handleApplicationServiceRegistration( cfg *config.ClientAPI, userAPI userapi.UserInternalAPI, ) util.JSONResponse { + logrus.Warnf("APPSERVICE Is appservice registration %q", r.Username) + // Check if we previously had issues extracting the access token from the // request. if tokenErr != nil { diff --git a/sytest-whitelist b/sytest-whitelist index 1e4442a09f..3ad0ef99d7 100644 --- a/sytest-whitelist +++ b/sytest-whitelist @@ -510,3 +510,6 @@ Can pass a JSON filter as a query parameter Local room members can get room messages Remote room members can get room messages Guest users can send messages to guest_access rooms if joined +AS can create a user +AS can create a user with an underscore +AS can create a user with inhibit_login From d606eec69f48675a533b04d44e51353019f82034 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 4 Mar 2021 13:36:09 +0000 Subject: [PATCH 03/10] Update sytest-whitelist --- sytest-whitelist | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sytest-whitelist b/sytest-whitelist index 3ad0ef99d7..7ccbaad141 100644 --- a/sytest-whitelist +++ b/sytest-whitelist @@ -513,3 +513,6 @@ Guest users can send messages to guest_access rooms if joined AS can create a user AS can create a user with an underscore AS can create a user with inhibit_login +AS can set avatar for ghosted users +AS can set displayname for ghosted users +Ghost user must register before joining room From 9cf65c51f062a91aec2c516dca878ddbe1737f13 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 4 Mar 2021 14:30:49 +0000 Subject: [PATCH 04/10] Use gomatrixserverlib.Client since that allows us to disable TLS validation using the config --- appservice/appservice.go | 12 +++++------- appservice/query/query.go | 17 ++++------------- appservice/workers/transaction_scheduler.go | 16 +++++----------- build/gobind/monolith.go | 2 +- cmd/dendrite-demo-libp2p/main.go | 2 +- cmd/dendrite-demo-yggdrasil/main.go | 2 +- cmd/dendrite-monolith-server/main.go | 6 ++++-- .../personalities/appservice.go | 3 ++- 8 files changed, 23 insertions(+), 37 deletions(-) diff --git a/appservice/appservice.go b/appservice/appservice.go index d783c7eb7f..95b8d95c22 100644 --- a/appservice/appservice.go +++ b/appservice/appservice.go @@ -16,9 +16,7 @@ package appservice import ( "context" - "net/http" "sync" - "time" "github.com/gorilla/mux" appserviceAPI "github.com/matrix-org/dendrite/appservice/api" @@ -33,6 +31,7 @@ import ( "github.com/matrix-org/dendrite/setup/config" "github.com/matrix-org/dendrite/setup/kafka" userapi "github.com/matrix-org/dendrite/userapi/api" + "github.com/matrix-org/gomatrixserverlib" "github.com/sirupsen/logrus" ) @@ -45,6 +44,7 @@ func AddInternalRoutes(router *mux.Router, queryAPI appserviceAPI.AppServiceQuer // can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes. func NewInternalAPI( base *setup.BaseDendrite, + client *gomatrixserverlib.Client, userAPI userapi.UserInternalAPI, rsAPI roomserverAPI.RoomserverInternalAPI, ) appserviceAPI.AppServiceQueryAPI { @@ -79,10 +79,8 @@ func NewInternalAPI( // Create appserivce query API with an HTTP client that will be used for all // outbound and inbound requests (inbound only for the internal API) appserviceQueryAPI := &query.AppServiceQueryAPI{ - HTTPClient: &http.Client{ - Timeout: time.Second * 30, - }, - Cfg: base.Cfg, + HTTPClient: client, + Cfg: base.Cfg, } // Only consume if we actually have ASes to track, else we'll just chew cycles needlessly. @@ -98,7 +96,7 @@ func NewInternalAPI( } // Create application service transaction workers - if err := workers.SetupTransactionWorkers(appserviceDB, workerStates); err != nil { + if err := workers.SetupTransactionWorkers(client, appserviceDB, workerStates); err != nil { logrus.WithError(err).Panicf("failed to start app service transaction workers") } return appserviceQueryAPI diff --git a/appservice/query/query.go b/appservice/query/query.go index 7e5ac47531..35339539dc 100644 --- a/appservice/query/query.go +++ b/appservice/query/query.go @@ -24,6 +24,7 @@ import ( "github.com/matrix-org/dendrite/appservice/api" "github.com/matrix-org/dendrite/setup/config" + "github.com/matrix-org/gomatrixserverlib" opentracing "github.com/opentracing/opentracing-go" log "github.com/sirupsen/logrus" ) @@ -33,7 +34,7 @@ const userIDExistsPath = "/users/" // AppServiceQueryAPI is an implementation of api.AppServiceQueryAPI type AppServiceQueryAPI struct { - HTTPClient *http.Client + HTTPClient *gomatrixserverlib.Client Cfg *config.Dendrite } @@ -47,11 +48,6 @@ func (a *AppServiceQueryAPI) RoomAliasExists( span, ctx := opentracing.StartSpanFromContext(ctx, "ApplicationServiceRoomAlias") defer span.Finish() - // Create an HTTP client if one does not already exist - if a.HTTPClient == nil { - a.HTTPClient = makeHTTPClient() - } - // Determine which application service should handle this request for _, appservice := range a.Cfg.Derived.ApplicationServices { if appservice.URL != "" && appservice.IsInterestedInRoomAlias(request.Alias) { @@ -68,7 +64,7 @@ func (a *AppServiceQueryAPI) RoomAliasExists( } req = req.WithContext(ctx) - resp, err := a.HTTPClient.Do(req) + resp, err := a.HTTPClient.DoHTTPRequest(ctx, req) if resp != nil { defer func() { err = resp.Body.Close() @@ -115,11 +111,6 @@ func (a *AppServiceQueryAPI) UserIDExists( span, ctx := opentracing.StartSpanFromContext(ctx, "ApplicationServiceUserID") defer span.Finish() - // Create an HTTP client if one does not already exist - if a.HTTPClient == nil { - a.HTTPClient = makeHTTPClient() - } - // Determine which application service should handle this request for _, appservice := range a.Cfg.Derived.ApplicationServices { if appservice.URL != "" && appservice.IsInterestedInUserID(request.UserID) { @@ -134,7 +125,7 @@ func (a *AppServiceQueryAPI) UserIDExists( if err != nil { return err } - resp, err := a.HTTPClient.Do(req.WithContext(ctx)) + resp, err := a.HTTPClient.DoHTTPRequest(ctx, req) if resp != nil { defer func() { err = resp.Body.Close() diff --git a/appservice/workers/transaction_scheduler.go b/appservice/workers/transaction_scheduler.go index 45748c2145..47d447c2cf 100644 --- a/appservice/workers/transaction_scheduler.go +++ b/appservice/workers/transaction_scheduler.go @@ -34,8 +34,6 @@ import ( var ( // Maximum size of events sent in each transaction. transactionBatchSize = 50 - // Timeout for sending a single transaction to an application service. - transactionTimeout = time.Second * 60 ) // SetupTransactionWorkers spawns a separate goroutine for each application @@ -44,6 +42,7 @@ var ( // size), then send that off to the AS's /transactions/{txnID} endpoint. It also // handles exponentially backing off in case the AS isn't currently available. func SetupTransactionWorkers( + client *gomatrixserverlib.Client, appserviceDB storage.Database, workerStates []types.ApplicationServiceWorkerState, ) error { @@ -51,7 +50,7 @@ func SetupTransactionWorkers( for _, workerState := range workerStates { // Don't create a worker if this AS doesn't want to receive events if workerState.AppService.URL != "" { - go worker(appserviceDB, workerState) + go worker(client, appserviceDB, workerState) } } return nil @@ -59,17 +58,12 @@ func SetupTransactionWorkers( // worker is a goroutine that sends any queued events to the application service // it is given. -func worker(db storage.Database, ws types.ApplicationServiceWorkerState) { +func worker(client *gomatrixserverlib.Client, db storage.Database, ws types.ApplicationServiceWorkerState) { log.WithFields(log.Fields{ "appservice": ws.AppService.ID, }).Info("Starting application service") ctx := context.Background() - // Create a HTTP client for sending requests to app services - client := &http.Client{ - Timeout: transactionTimeout, - } - // Initial check for any leftover events to send from last time eventCount, err := db.CountEventsWithAppServiceID(ctx, ws.AppService.ID) if err != nil { @@ -206,7 +200,7 @@ func createTransaction( // send sends events to an application service. Returns an error if an OK was not // received back from the application service or the request timed out. func send( - client *http.Client, + client *gomatrixserverlib.Client, appservice config.ApplicationService, txnID int, transaction []byte, @@ -219,7 +213,7 @@ func send( return err } req.Header.Set("Content-Type", "application/json") - resp, err := client.Do(req) + resp, err := client.DoHTTPRequest(context.TODO(), req) if err != nil { return err } diff --git a/build/gobind/monolith.go b/build/gobind/monolith.go index 332d156bde..58fe0d1556 100644 --- a/build/gobind/monolith.go +++ b/build/gobind/monolith.go @@ -129,7 +129,7 @@ func (m *DendriteMonolith) Start() { base, cache.New(), userAPI, ) - asAPI := appservice.NewInternalAPI(base, userAPI, rsAPI) + asAPI := appservice.NewInternalAPI(base, base.CreateClient(), userAPI, rsAPI) rsAPI.SetAppserviceAPI(asAPI) ygg.SetSessionFunc(func(address string) { diff --git a/cmd/dendrite-demo-libp2p/main.go b/cmd/dendrite-demo-libp2p/main.go index 0610ec777f..2e8792b2d9 100644 --- a/cmd/dendrite-demo-libp2p/main.go +++ b/cmd/dendrite-demo-libp2p/main.go @@ -163,7 +163,7 @@ func main() { eduInputAPI := eduserver.NewInternalAPI( &base.Base, cache.New(), userAPI, ) - asAPI := appservice.NewInternalAPI(&base.Base, userAPI, rsAPI) + asAPI := appservice.NewInternalAPI(&base.Base, base.Base.CreateClient(), userAPI, rsAPI) rsAPI.SetAppserviceAPI(asAPI) fsAPI := federationsender.NewInternalAPI( &base.Base, federation, rsAPI, keyRing, diff --git a/cmd/dendrite-demo-yggdrasil/main.go b/cmd/dendrite-demo-yggdrasil/main.go index 2a4a335abc..b74a74a65d 100644 --- a/cmd/dendrite-demo-yggdrasil/main.go +++ b/cmd/dendrite-demo-yggdrasil/main.go @@ -111,7 +111,7 @@ func main() { base, cache.New(), userAPI, ) - asAPI := appservice.NewInternalAPI(base, userAPI, rsAPI) + asAPI := appservice.NewInternalAPI(base, base.CreateClient(), userAPI, rsAPI) rsAPI.SetAppserviceAPI(asAPI) fsAPI := federationsender.NewInternalAPI( base, federation, rsAPI, keyRing, diff --git a/cmd/dendrite-monolith-server/main.go b/cmd/dendrite-monolith-server/main.go index b82f73211b..b8a3e231f4 100644 --- a/cmd/dendrite-monolith-server/main.go +++ b/cmd/dendrite-monolith-server/main.go @@ -121,7 +121,9 @@ func main() { eduInputAPI = base.EDUServerClient() } - asAPI := appservice.NewInternalAPI(base, userAPI, rsAPI) + client := base.CreateClient() + + asAPI := appservice.NewInternalAPI(base, client, userAPI, rsAPI) if base.UseHTTPAPIs { appservice.AddInternalRoutes(base.InternalAPIMux, asAPI) asAPI = base.AppserviceHTTPClient() @@ -131,7 +133,7 @@ func main() { monolith := setup.Monolith{ Config: base.Cfg, AccountDB: accountDB, - Client: base.CreateClient(), + Client: client, FedClient: federation, KeyRing: keyRing, diff --git a/cmd/dendrite-polylith-multi/personalities/appservice.go b/cmd/dendrite-polylith-multi/personalities/appservice.go index d269b15d41..5be3e594e0 100644 --- a/cmd/dendrite-polylith-multi/personalities/appservice.go +++ b/cmd/dendrite-polylith-multi/personalities/appservice.go @@ -23,8 +23,9 @@ import ( func Appservice(base *setup.BaseDendrite, cfg *config.Dendrite) { userAPI := base.UserAPIClient() rsAPI := base.RoomserverHTTPClient() + client := base.CreateClient() - intAPI := appservice.NewInternalAPI(base, userAPI, rsAPI) + intAPI := appservice.NewInternalAPI(base, client, userAPI, rsAPI) appservice.AddInternalRoutes(base.InternalAPIMux, intAPI) base.SetupAndServeHTTP( From d327bacf2878ea492cdbc900806da6f220329ffd Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 4 Mar 2021 14:38:26 +0000 Subject: [PATCH 05/10] Add appservice-specific client and ability to control TLS validation for appservices only --- appservice/appservice.go | 3 +-- build/gobind/monolith.go | 2 +- cmd/dendrite-demo-libp2p/main.go | 2 +- cmd/dendrite-demo-yggdrasil/main.go | 2 +- cmd/dendrite-monolith-server/main.go | 6 ++---- .../personalities/appservice.go | 3 +-- cmd/generate-config/main.go | 1 + dendrite-config.yaml | 5 +++++ setup/base.go | 14 ++++++++++++++ setup/config/config_appservice.go | 4 ++++ 10 files changed, 31 insertions(+), 11 deletions(-) diff --git a/appservice/appservice.go b/appservice/appservice.go index 95b8d95c22..f608e8e761 100644 --- a/appservice/appservice.go +++ b/appservice/appservice.go @@ -31,7 +31,6 @@ import ( "github.com/matrix-org/dendrite/setup/config" "github.com/matrix-org/dendrite/setup/kafka" userapi "github.com/matrix-org/dendrite/userapi/api" - "github.com/matrix-org/gomatrixserverlib" "github.com/sirupsen/logrus" ) @@ -44,10 +43,10 @@ func AddInternalRoutes(router *mux.Router, queryAPI appserviceAPI.AppServiceQuer // can call functions directly on the returned API or via an HTTP interface using AddInternalRoutes. func NewInternalAPI( base *setup.BaseDendrite, - client *gomatrixserverlib.Client, userAPI userapi.UserInternalAPI, rsAPI roomserverAPI.RoomserverInternalAPI, ) appserviceAPI.AppServiceQueryAPI { + client := base.CreateAppserviceClient() consumer, _ := kafka.SetupConsumerProducer(&base.Cfg.Global.Kafka) // Create a connection to the appservice postgres DB diff --git a/build/gobind/monolith.go b/build/gobind/monolith.go index 58fe0d1556..332d156bde 100644 --- a/build/gobind/monolith.go +++ b/build/gobind/monolith.go @@ -129,7 +129,7 @@ func (m *DendriteMonolith) Start() { base, cache.New(), userAPI, ) - asAPI := appservice.NewInternalAPI(base, base.CreateClient(), userAPI, rsAPI) + asAPI := appservice.NewInternalAPI(base, userAPI, rsAPI) rsAPI.SetAppserviceAPI(asAPI) ygg.SetSessionFunc(func(address string) { diff --git a/cmd/dendrite-demo-libp2p/main.go b/cmd/dendrite-demo-libp2p/main.go index 2e8792b2d9..0610ec777f 100644 --- a/cmd/dendrite-demo-libp2p/main.go +++ b/cmd/dendrite-demo-libp2p/main.go @@ -163,7 +163,7 @@ func main() { eduInputAPI := eduserver.NewInternalAPI( &base.Base, cache.New(), userAPI, ) - asAPI := appservice.NewInternalAPI(&base.Base, base.Base.CreateClient(), userAPI, rsAPI) + asAPI := appservice.NewInternalAPI(&base.Base, userAPI, rsAPI) rsAPI.SetAppserviceAPI(asAPI) fsAPI := federationsender.NewInternalAPI( &base.Base, federation, rsAPI, keyRing, diff --git a/cmd/dendrite-demo-yggdrasil/main.go b/cmd/dendrite-demo-yggdrasil/main.go index b74a74a65d..2a4a335abc 100644 --- a/cmd/dendrite-demo-yggdrasil/main.go +++ b/cmd/dendrite-demo-yggdrasil/main.go @@ -111,7 +111,7 @@ func main() { base, cache.New(), userAPI, ) - asAPI := appservice.NewInternalAPI(base, base.CreateClient(), userAPI, rsAPI) + asAPI := appservice.NewInternalAPI(base, userAPI, rsAPI) rsAPI.SetAppserviceAPI(asAPI) fsAPI := federationsender.NewInternalAPI( base, federation, rsAPI, keyRing, diff --git a/cmd/dendrite-monolith-server/main.go b/cmd/dendrite-monolith-server/main.go index b8a3e231f4..b82f73211b 100644 --- a/cmd/dendrite-monolith-server/main.go +++ b/cmd/dendrite-monolith-server/main.go @@ -121,9 +121,7 @@ func main() { eduInputAPI = base.EDUServerClient() } - client := base.CreateClient() - - asAPI := appservice.NewInternalAPI(base, client, userAPI, rsAPI) + asAPI := appservice.NewInternalAPI(base, userAPI, rsAPI) if base.UseHTTPAPIs { appservice.AddInternalRoutes(base.InternalAPIMux, asAPI) asAPI = base.AppserviceHTTPClient() @@ -133,7 +131,7 @@ func main() { monolith := setup.Monolith{ Config: base.Cfg, AccountDB: accountDB, - Client: client, + Client: base.CreateClient(), FedClient: federation, KeyRing: keyRing, diff --git a/cmd/dendrite-polylith-multi/personalities/appservice.go b/cmd/dendrite-polylith-multi/personalities/appservice.go index 5be3e594e0..d269b15d41 100644 --- a/cmd/dendrite-polylith-multi/personalities/appservice.go +++ b/cmd/dendrite-polylith-multi/personalities/appservice.go @@ -23,9 +23,8 @@ import ( func Appservice(base *setup.BaseDendrite, cfg *config.Dendrite) { userAPI := base.UserAPIClient() rsAPI := base.RoomserverHTTPClient() - client := base.CreateClient() - intAPI := appservice.NewInternalAPI(base, client, userAPI, rsAPI) + intAPI := appservice.NewInternalAPI(base, userAPI, rsAPI) appservice.AddInternalRoutes(base.InternalAPIMux, intAPI) base.SetupAndServeHTTP( diff --git a/cmd/generate-config/main.go b/cmd/generate-config/main.go index fa0da10c52..9ef0f0b416 100644 --- a/cmd/generate-config/main.go +++ b/cmd/generate-config/main.go @@ -61,6 +61,7 @@ func main() { } if *defaultsForCI { + cfg.AppServiceAPI.DisableTLSValidation = true cfg.ClientAPI.RateLimiting.Enabled = false cfg.FederationSender.DisableTLSValidation = true cfg.MSCs.MSCs = []string{"msc2836", "msc2946", "msc2444", "msc2753"} diff --git a/dendrite-config.yaml b/dendrite-config.yaml index a3d1065d42..bf604c9d6c 100644 --- a/dendrite-config.yaml +++ b/dendrite-config.yaml @@ -125,6 +125,11 @@ app_service_api: max_idle_conns: 2 conn_max_lifetime: -1 + # Disable the validation of TLS certificates of appservices. This is + # not recommended in production since it may allow appservice traffic + # to be sent to an unverified endpoint. + disable_tls_validation: false + # Appservice configuration files to load into this homeserver. config_files: [] diff --git a/setup/base.go b/setup/base.go index e9aa2a45e1..9919bd42c5 100644 --- a/setup/base.go +++ b/setup/base.go @@ -290,6 +290,20 @@ func (b *BaseDendrite) CreateClient() *gomatrixserverlib.Client { return client } +// CreateClient creates a new client (normally used for media fetch requests). +// Should only be called once per component. +func (b *BaseDendrite) CreateAppserviceClient() *gomatrixserverlib.Client { + opts := []gomatrixserverlib.ClientOption{ + gomatrixserverlib.WithSkipVerify(b.Cfg.AppServiceAPI.DisableTLSValidation), + } + if b.Cfg.Global.DNSCache.Enabled { + opts = append(opts, gomatrixserverlib.WithDNSCache(b.DNSCache)) + } + client := gomatrixserverlib.NewClient(opts...) + client.SetUserAgent(fmt.Sprintf("Dendrite/%s", internal.VersionString())) + return client +} + // CreateFederationClient creates a new federation client. Should only be called // once per component. func (b *BaseDendrite) CreateFederationClient() *gomatrixserverlib.FederationClient { diff --git a/setup/config/config_appservice.go b/setup/config/config_appservice.go index a042691dbb..a6f77abfe6 100644 --- a/setup/config/config_appservice.go +++ b/setup/config/config_appservice.go @@ -33,6 +33,10 @@ type AppServiceAPI struct { Database DatabaseOptions `yaml:"database"` + // DisableTLSValidation disables the validation of X.509 TLS certs + // on appservice endpoints. This is not recommended in production! + DisableTLSValidation bool `yaml:"disable_tls_validation"` + ConfigFiles []string `yaml:"config_files"` } From 0d95e06045de7fc8820d27a8cd1291f29709b01d Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 4 Mar 2021 14:40:20 +0000 Subject: [PATCH 06/10] Set timeout on appservice client --- setup/base.go | 1 + 1 file changed, 1 insertion(+) diff --git a/setup/base.go b/setup/base.go index 9919bd42c5..b22c41e7e1 100644 --- a/setup/base.go +++ b/setup/base.go @@ -295,6 +295,7 @@ func (b *BaseDendrite) CreateClient() *gomatrixserverlib.Client { func (b *BaseDendrite) CreateAppserviceClient() *gomatrixserverlib.Client { opts := []gomatrixserverlib.ClientOption{ gomatrixserverlib.WithSkipVerify(b.Cfg.AppServiceAPI.DisableTLSValidation), + gomatrixserverlib.WithTimeout(time.Second * 60), } if b.Cfg.Global.DNSCache.Enabled { opts = append(opts, gomatrixserverlib.WithDNSCache(b.DNSCache)) From e7bdd06e930e06d87e4fdc43ece7e9e217c6da17 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 4 Mar 2021 14:58:19 +0000 Subject: [PATCH 07/10] Review comments --- clientapi/routing/register.go | 3 --- setup/base.go | 5 +++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/clientapi/routing/register.go b/clientapi/routing/register.go index 41e3777338..9e0ca51fa8 100644 --- a/clientapi/routing/register.go +++ b/clientapi/routing/register.go @@ -46,7 +46,6 @@ import ( "github.com/matrix-org/gomatrixserverlib/tokens" "github.com/matrix-org/util" "github.com/prometheus/client_golang/prometheus" - "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus" ) @@ -691,8 +690,6 @@ func handleApplicationServiceRegistration( cfg *config.ClientAPI, userAPI userapi.UserInternalAPI, ) util.JSONResponse { - logrus.Warnf("APPSERVICE Is appservice registration %q", r.Username) - // Check if we previously had issues extracting the access token from the // request. if tokenErr != nil { diff --git a/setup/base.go b/setup/base.go index b22c41e7e1..f8a45409f2 100644 --- a/setup/base.go +++ b/setup/base.go @@ -290,8 +290,9 @@ func (b *BaseDendrite) CreateClient() *gomatrixserverlib.Client { return client } -// CreateClient creates a new client (normally used for media fetch requests). -// Should only be called once per component. +// CreateAppserviceClient creates a new client for application services. +// It has a specific timeout and obeys TLS validation from the appservice +// config rather than the federation config. func (b *BaseDendrite) CreateAppserviceClient() *gomatrixserverlib.Client { opts := []gomatrixserverlib.ClientOption{ gomatrixserverlib.WithSkipVerify(b.Cfg.AppServiceAPI.DisableTLSValidation), From ff04a962f11dfa5e3f487323ab89e5964e74cf00 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 4 Mar 2021 15:08:56 +0000 Subject: [PATCH 08/10] Remove dead code --- appservice/query/query.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/appservice/query/query.go b/appservice/query/query.go index 35339539dc..b4c3352871 100644 --- a/appservice/query/query.go +++ b/appservice/query/query.go @@ -20,7 +20,6 @@ import ( "context" "net/http" "net/url" - "time" "github.com/matrix-org/dendrite/appservice/api" "github.com/matrix-org/dendrite/setup/config" @@ -160,10 +159,3 @@ func (a *AppServiceQueryAPI) UserIDExists( response.UserIDExists = false return nil } - -// makeHTTPClient creates an HTTP client with certain options that will be used for all query requests to application services -func makeHTTPClient() *http.Client { - return &http.Client{ - Timeout: time.Second * 30, - } -} From 2db487cdd38e44b202574c917549bcf1546eb288 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Thu, 4 Mar 2021 15:58:47 +0000 Subject: [PATCH 09/10] Enforce LoginTypeApplicationService after all --- clientapi/routing/register.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clientapi/routing/register.go b/clientapi/routing/register.go index 9e0ca51fa8..cd19dec97f 100644 --- a/clientapi/routing/register.go +++ b/clientapi/routing/register.go @@ -502,7 +502,7 @@ func Register( // Squash username to all lowercase letters r.Username = strings.ToLower(r.Username) - if r.Auth.Type == authtypes.LoginTypeApplicationService || accessTokenErr == nil { + if r.Auth.Type == authtypes.LoginTypeApplicationService { if resErr = validateApplicationServiceUsername(r.Username); resErr != nil { return *resErr } @@ -604,7 +604,7 @@ func handleRegistrationFlow( // registration or user exclusivity. We'll go onto the appservice // registration flow if a valid access token was provided or if // the login type specifically requests it. - if r.Auth.Type == authtypes.LoginTypeApplicationService || accessTokenErr == nil { + if r.Auth.Type == authtypes.LoginTypeApplicationService { return handleApplicationServiceRegistration( accessToken, accessTokenErr, req, r, cfg, userAPI, ) From f7ab99a77f2996389c0b7de28d763ce454689791 Mon Sep 17 00:00:00 2001 From: Neil Alexander Date: Fri, 5 Mar 2021 10:17:32 +0000 Subject: [PATCH 10/10] Check correct auth type field --- clientapi/routing/register.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clientapi/routing/register.go b/clientapi/routing/register.go index cd19dec97f..7d5ddbea94 100644 --- a/clientapi/routing/register.go +++ b/clientapi/routing/register.go @@ -502,7 +502,7 @@ func Register( // Squash username to all lowercase letters r.Username = strings.ToLower(r.Username) - if r.Auth.Type == authtypes.LoginTypeApplicationService { + if r.Type == authtypes.LoginTypeApplicationService && accessTokenErr == nil { if resErr = validateApplicationServiceUsername(r.Username); resErr != nil { return *resErr } @@ -604,7 +604,7 @@ func handleRegistrationFlow( // registration or user exclusivity. We'll go onto the appservice // registration flow if a valid access token was provided or if // the login type specifically requests it. - if r.Auth.Type == authtypes.LoginTypeApplicationService { + if r.Type == authtypes.LoginTypeApplicationService && accessTokenErr == nil { return handleApplicationServiceRegistration( accessToken, accessTokenErr, req, r, cfg, userAPI, )